修改vue写的前端页面到底有多方便?如果熟练的话,出乎你想象的快。
原来的页面:/admin/stock
原来的文件地址:src\views\admin\stock\Stock.vue
另一个页面有个入库功能,需要转移到上面的页面中:
路径:/purchase/request
地址:src\views\purchase\request\Request.vue
入库功能包括一个开启按键(1)和一个弹出表单(2):
开启按键代码:
<a-button type="primary" ghost @click="warehouse">入库</a-button>
warehouse () {
this.stockAdd.visiable = true
},
弹出表单窗口是一个独立存在的vue文件:
路径:src\views\purchase\request\RequestAdd.vue
RequestAdd.vue代码:
<template>
<a-drawer
title="物品入库"
:maskClosable="false"
placement="right"
:closable="false"
:visible="show"
:width="1200"
@close="onClose"
style="height: calc(100% - 55px);overflow: auto;padding-bottom: 53px;"
>
<a-form :form="form" layout="horizontal">
<a-row :gutter="50">
<a-col :span="12">
<a-form-item label='保管人' v-bind="formItemLayout">
<a-input v-decorator="[
'custodian',
{ rules: [{ required: true, message: '请输入保管人!' }] }
]"/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label='入库人' v-bind="formItemLayout">
<a-input v-decorator="[
'putUser',
{ rules: [{ required: true, message: '请输入入库人!' }] }
]"/>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label='备注消息' v-bind="formItemLayout">
<a-textarea :rows="4" v-decorator="[
'content',
{ rules: [{ required: true, message: '请输入名称!' }] }
]"/>
</a-form-item>
</a-col>
<a-col :span="24">
<a-table :columns="columns" :data-source="dataList">
<template slot="nameShow" slot-scope="text, record">
<a-input v-model="record.name"></a-input>
</template>
<template slot="typeShow" slot-scope="text, record">
<a-input v-model="record.type"></a-input>
</template>
<template slot="typeIdShow" slot-scope="text, record">
<a-select v-model="record.typeId" style="width: 100%">
<a-select-option v-for="(item, index) in consumableType" :value="item.id" :key="index">{{ item.name }}</a-select-option>
</a-select>
</template>
<template slot="unitShow" slot-scope="text, record">
<a-input v-model="record.unit"></a-input>
</template>
<template slot="amountShow" slot-scope="text, record">
<a-input-number v-model="record.amount" :min="1" :step="1"/>
</template>
<template slot="priceShow" slot-scope="text, record">
<a-input-number v-model="record.price" :min="1"/>
</template>
</a-table>
<a-button @click="dataAdd" type="primary" ghost size="large" style="margin-top: 10px;width: 100%">
新增物品
</a-button>
</a-col>
</a-row>
</a-form>
<div class="drawer-bootom-button">
<a-popconfirm title="确定放弃编辑?" @confirm="onClose" okText="确定" cancelText="取消">
<a-button style="margin-right: .8rem">取消</a-button>
</a-popconfirm>
<a-button @click="handleSubmit" type="primary" :loading="loading">提交</a-button>
</div>
</a-drawer>
</template>
<script>
import {mapState} from 'vuex'
const formItemLayout = {
labelCol: { span: 24 },
wrapperCol: { span: 24 }
}
export default {
name: 'requestAdd',
props: {
requestAddVisiable: {
default: false
}
},
computed: {
...mapState({
currentUser: state => state.account.user
}),
show: {
get: function () {
return this.requestAddVisiable
},
set: function () {
}
},
columns () {
return [{
title: '物品名称',
dataIndex: 'name',
scopedSlots: {customRender: 'nameShow'}
}, {
title: '型号',
dataIndex: 'type',
scopedSlots: {customRender: 'typeShow'}
}, {
title: '数量',
dataIndex: 'amount',
scopedSlots: {customRender: 'amountShow'}
}, {
title: '所属类型',
dataIndex: 'typeId',
width: 200,
scopedSlots: {customRender: 'typeIdShow'}
}, {
title: '单位',
dataIndex: 'unit',
scopedSlots: {customRender: 'unitShow'}
}, {
title: '单价',
dataIndex: 'price',
scopedSlots: {customRender: 'priceShow'}
}]
}
},
mounted () {
this.getConsumableType()
},
data () {
return {
dataList: [],
formItemLayout,
form: this.$form.createForm(this),
loading: false,
consumableType: []
}
},
methods: {
getConsumableType () {
this.$get('/cos/consumable-type/list').then((r) => {
this.consumableType = r.data.data
})
},
dataAdd () {
this.dataList.push({name: '', type: '', typeId: '', unit: '', amount: '', price: ''})
},
reset () {
this.loading = false
this.form.resetFields()
},
onClose () {
this.reset()
this.$emit('close')
},
handleSubmit () {
let price = 0
this.dataList.forEach(item => {
price += item.price * item.amount
})
this.form.validateFields((err, values) => {
values.price = price
values.goods = JSON.stringify(this.dataList)
if (!err) {
this.loading = true
this.$post('/cos/stock-info/put', {
...values
}).then((r) => {
this.reset()
this.$emit('success')
}).catch(() => {
this.loading = false
})
}
})
}
}
}
</script>
<style scoped>
</style>
在Request.vue中引用RequestAdd.vue的方法:
<request-add
v-if="requestAdd.visiable"
@close="handleRequestAddClose"
@success="handleRequestAddSuccess"
:requestAddVisiable="requestAdd.visiable">
</request-add>
<script>
...
import RequestAdd from './RequestAdd'
...
export default {
...
data () {
return {
...
requestAdd: {
visiable: false
},
...
}
},
...
methods: {
...
handleRequestAddClose () {
this.requestAdd.visiable = false
},
handleRequestAddSuccess () {
this.requestAdd.visiable = false
this.$message.success('入库成功')
this.search()
},
...
search () {
let {sortedInfo, filteredInfo} = this
let sortField, sortOrder
// 获取当前列的排序和列的过滤规则
if (sortedInfo) {
sortField = sortedInfo.field
sortOrder = sortedInfo.order
}
this.fetch({
sortField: sortField,
sortOrder: sortOrder,
...this.queryParams,
...filteredInfo
})
},
...
fetch (params = {}) {
// 显示loading
this.loading = true
if (this.paginationInfo) {
// 如果分页信息不为空,则设置表格当前第几页,每页条数,并设置查询分页参数
this.$refs.TableInfo.pagination.current = this.paginationInfo.current
this.$refs.TableInfo.pagination.pageSize = this.paginationInfo.pageSize
params.size = this.paginationInfo.pageSize
params.current = this.paginationInfo.current
} else {
// 如果分页信息为空,则设置为默认值
params.size = this.pagination.defaultPageSize
params.current = this.pagination.defaultCurrent
}
if (params.typeId === undefined) {
delete params.typeId
}
this.$get('/cos/stock-info/page', {
...params
}).then((r) => {
let data = r.data.data
const pagination = {...this.pagination}
pagination.total = data.total
this.dataSource = data.records
this.pagination = pagination
// 数据加载完毕,关闭loading
this.loading = false
})
}
},
watch: {}
}
</script>
实际上就是在Request.vue中添加一个数据对象(requestAdd.visiable)和两个方法(handleRequestAddClose、handleRequestAddSuccess)
开始改造
将RequestAdd.vue文件加入Stock.vue所在路径,修改合适的文件名称为StockAdd.vue,同时修改StockAdd.vue对外暴露的name和props的名称。
在Stock.vue的<template>代码适当位置添加按键和表单(7行代码):
在Stock.vue的<script>代码中添加相关的引用(2行代码)、数据(3行代码)、函数(8行代码):
总结
改造过程,共复制vue文件1个,修改代码23行。熟悉代码的情况下,修改用时很短。
说明vue组件化特性为代码复用带来极大便利。
源码
src\views\purchase\request\Request.vue
<template>
<a-card :bordered="false" class="card-area">
<div :class="advanced ? 'search' : null">
<!-- 搜索区域 -->
<a-form layout="horizontal">
<a-row :gutter="15">
<div :class="advanced ? null: 'fold'">
<a-col :md="6" :sm="24">
<a-form-item
label="物品名称"
:labelCol="{span: 4}"
:wrapperCol="{span: 18, offset: 2}">
<a-input v-model="queryParams.name"/>
</a-form-item>
</a-col>
<a-col :md="6" :sm="24">
<a-form-item
label="物品型号"
:labelCol="{span: 4}"
:wrapperCol="{span: 18, offset: 2}">
<a-input v-model="queryParams.type"/>
</a-form-item>
</a-col>
<a-col :md="6" :sm="24">
<a-form-item
label="物品类型"
:labelCol="{span: 4}"
:wrapperCol="{span: 18, offset: 2}">
<a-select v-model="queryParams.typeId" style="width: 100%" allowClear>
<a-select-option v-for="(item, index) in consumableType" :value="item.id" :key="index">{{ item.name }}</a-select-option>
</a-select>
</a-form-item>
</a-col>
</div>
<span style="float: right; margin-top: 3px;">
<a-button type="primary" @click="search">查询</a-button>
<a-button style="margin-left: 8px" @click="reset">重置</a-button>
</span>
</a-row>
</a-form>
</div>
<div>
<div class="operator">
<a-button type="primary" ghost @click="add">入库</a-button>
<!-- <a-button @click="batchDelete">删除</a-button> 后台API不存在/cos/request-type/{id}删除接口 这个按键是多余的 -->
</div>
<!-- 表格区域 -->
<a-table ref="TableInfo"
:columns="columns"
:rowKey="record => record.id"
:dataSource="dataSource"
:pagination="pagination"
:loading="loading"
:rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
:scroll="{ x: 900 }"
@change="handleTableChange">
<template slot="titleShow" slot-scope="text, record">
<template>
<a-badge status="processing"/>
<a-tooltip>
<template slot="title">
{{ record.title }}
</template>
{{ record.title.slice(0, 8) }} ...
</a-tooltip>
</template>
</template>
<template slot="contentShow" slot-scope="text, record">
<template>
<a-tooltip>
<template slot="title">
{{ record.content }}
</template>
{{ record.content.slice(0, 30) }} ...
</a-tooltip>
</template>
</template>
<template slot="operation" slot-scope="text, record">
<a-icon type="setting" theme="twoTone" twoToneColor="#4a9ff5" @click="edit(record)" title="修 改"></a-icon>
</template>
</a-table>
</div>
<request-add
v-if="requestAdd.visiable"
@close="handleRequestAddClose"
@success="handleRequestAddSuccess"
:requestAddVisiable="requestAdd.visiable">
</request-add>
</a-card>
</template>
<script>
import RangeDate from '@/components/datetime/RangeDate'
import RequestAdd from './RequestAdd'
import {mapState} from 'vuex'
import moment from 'moment'
moment.locale('zh-cn')
export default {
name: 'request',
components: {RequestAdd, RangeDate},
data () {
return {
advanced: false,
requestAdd: {
visiable: false
},
requestEdit: {
visiable: false
},
queryParams: {},
filteredInfo: null,
sortedInfo: null,
paginationInfo: null,
dataSource: [],
selectedRowKeys: [],
loading: false,
pagination: {
pageSizeOptions: ['10', '20', '30', '40', '100'],
defaultCurrent: 1,
defaultPageSize: 10,
showQuickJumper: true,
showSizeChanger: true,
showTotal: (total, range) => `显示 ${range[0]} ~ ${range[1]} 条记录,共 ${total} 条记录`
},
consumableType: []
}
},
computed: {
...mapState({
currentUser: state => state.account.user
}),
columns () {
return [{
title: '物品名称',
dataIndex: 'name'
}, {
title: '型号',
dataIndex: 'type',
customRender: (text, row, index) => {
if (text !== null) {
return text
} else {
return '- -'
}
}
}, {
title: '物品数量',
dataIndex: 'amount',
customRender: (text, row, index) => {
if (text !== null) {
return text
} else {
return '- -'
}
}
}, {
title: '单位',
dataIndex: 'unit',
customRender: (text, row, index) => {
if (text !== null) {
return text
} else {
return '- -'
}
}
}, {
title: '单价',
dataIndex: 'price',
customRender: (text, row, index) => {
if (text !== null) {
return '¥' + text.toFixed(2)
} else {
return '- -'
}
}
}, {
title: '总价',
dataIndex: 'allPrice',
customRender: (text, row, index) => {
return '¥' + (row.price * row.amount).toFixed(2)
}
}, {
title: '物品类型',
dataIndex: 'consumableType',
customRender: (text, row, index) => {
if (text !== null) {
return <a-tag>{text}</a-tag>
} else {
return '- -'
}
}
}, {
title: '备注',
dataIndex: 'content',
customRender: (text, row, index) => {
if (text !== null) {
return text
} else {
return '- -'
}
}
}, {
title: '入库时间',
dataIndex: 'createDate',
customRender: (text, row, index) => {
if (text !== null) {
return text
} else {
return '- -'
}
}
}]
}
},
mounted () {
this.fetch()
this.getConsumableType()
},
methods: {
getConsumableType () {
this.$get('/cos/consumable-type/list').then((r) => {
this.consumableType = r.data.data
})
},
onSelectChange (selectedRowKeys) {
this.selectedRowKeys = selectedRowKeys
},
toggleAdvanced () {
this.advanced = !this.advanced
},
add () {
this.requestAdd.visiable = true
},
handleRequestAddClose () {
this.requestAdd.visiable = false
},
handleRequestAddSuccess () {
this.requestAdd.visiable = false
this.$message.success('入库成功')
this.search()
},
handleDeptChange (value) {
this.queryParams.deptId = value || ''
},
batchDelete () {
if (!this.selectedRowKeys.length) {
this.$message.warning('请选择需要删除的记录')
return
}
let that = this
this.$confirm({
title: '确定删除所选中的记录?',
content: '当您点击确定按钮后,这些记录将会被彻底删除',
centered: true,
onOk () {
let ids = that.selectedRowKeys.join(',')
that.$delete('/cos/request-type/' + ids).then(() => {
that.$message.success('删除成功')
that.selectedRowKeys = []
that.search()
})
},
onCancel () {
that.selectedRowKeys = []
}
})
},
search () {
let {sortedInfo, filteredInfo} = this
let sortField, sortOrder
// 获取当前列的排序和列的过滤规则
if (sortedInfo) {
sortField = sortedInfo.field
sortOrder = sortedInfo.order
}
this.fetch({
sortField: sortField,
sortOrder: sortOrder,
...this.queryParams,
...filteredInfo
})
},
reset () {
// 取消选中
this.selectedRowKeys = []
// 重置分页
this.$refs.TableInfo.pagination.current = this.pagination.defaultCurrent
if (this.paginationInfo) {
this.paginationInfo.current = this.pagination.defaultCurrent
this.paginationInfo.pageSize = this.pagination.defaultPageSize
}
// 重置列过滤器规则
this.filteredInfo = null
// 重置列排序规则
this.sortedInfo = null
// 重置查询参数
this.queryParams = {}
this.fetch()
},
handleTableChange (pagination, filters, sorter) {
// 将这三个参数赋值给Vue data,用于后续使用
this.paginationInfo = pagination
this.filteredInfo = filters
this.sortedInfo = sorter
this.fetch({
sortField: sorter.field,
sortOrder: sorter.order,
...this.queryParams,
...filters
})
},
fetch (params = {}) {
// 显示loading
this.loading = true
if (this.paginationInfo) {
// 如果分页信息不为空,则设置表格当前第几页,每页条数,并设置查询分页参数
this.$refs.TableInfo.pagination.current = this.paginationInfo.current
this.$refs.TableInfo.pagination.pageSize = this.paginationInfo.pageSize
params.size = this.paginationInfo.pageSize
params.current = this.paginationInfo.current
} else {
// 如果分页信息为空,则设置为默认值
params.size = this.pagination.defaultPageSize
params.current = this.pagination.defaultCurrent
}
if (params.typeId === undefined) {
delete params.typeId
}
this.$get('/cos/stock-info/page', {
...params
}).then((r) => {
let data = r.data.data
const pagination = {...this.pagination}
pagination.total = data.total
this.dataSource = data.records
this.pagination = pagination
// 数据加载完毕,关闭loading
this.loading = false
})
}
},
watch: {}
}
</script>
<style lang="less" scoped>
@import "../../../../static/less/Common";
</style>
src\views\purchase\request\RequestAdd.vue:
<template>
<a-drawer
title="物品入库"
:maskClosable="false"
placement="right"
:closable="false"
:visible="show"
:width="1200"
@close="onClose"
style="height: calc(100% - 55px);overflow: auto;padding-bottom: 53px;"
>
<a-form :form="form" layout="horizontal">
<a-row :gutter="50">
<a-col :span="12">
<a-form-item label='保管人' v-bind="formItemLayout">
<a-input v-decorator="[
'custodian',
{ rules: [{ required: true, message: '请输入保管人!' }] }
]"/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label='入库人' v-bind="formItemLayout">
<a-input v-decorator="[
'putUser',
{ rules: [{ required: true, message: '请输入入库人!' }] }
]"/>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label='备注消息' v-bind="formItemLayout">
<a-textarea :rows="4" v-decorator="[
'content',
{ rules: [{ required: true, message: '请输入名称!' }] }
]"/>
</a-form-item>
</a-col>
<a-col :span="24">
<a-table :columns="columns" :data-source="dataList">
<template slot="nameShow" slot-scope="text, record">
<a-input v-model="record.name"></a-input>
</template>
<template slot="typeShow" slot-scope="text, record">
<a-input v-model="record.type"></a-input>
</template>
<template slot="typeIdShow" slot-scope="text, record">
<a-select v-model="record.typeId" style="width: 100%">
<a-select-option v-for="(item, index) in consumableType" :value="item.id" :key="index">{{ item.name }}</a-select-option>
</a-select>
</template>
<template slot="unitShow" slot-scope="text, record">
<a-input v-model="record.unit"></a-input>
</template>
<template slot="amountShow" slot-scope="text, record">
<a-input-number v-model="record.amount" :min="1" :step="1"/>
</template>
<template slot="priceShow" slot-scope="text, record">
<a-input-number v-model="record.price" :min="1"/>
</template>
</a-table>
<a-button @click="dataAdd" type="primary" ghost size="large" style="margin-top: 10px;width: 100%">
新增物品
</a-button>
</a-col>
</a-row>
</a-form>
<div class="drawer-bootom-button">
<a-popconfirm title="确定放弃编辑?" @confirm="onClose" okText="确定" cancelText="取消">
<a-button style="margin-right: .8rem">取消</a-button>
</a-popconfirm>
<a-button @click="handleSubmit" type="primary" :loading="loading">提交</a-button>
</div>
</a-drawer>
</template>
<script>
import {mapState} from 'vuex'
const formItemLayout = {
labelCol: { span: 24 },
wrapperCol: { span: 24 }
}
export default {
name: 'requestAdd',
props: {
requestAddVisiable: {
default: false
}
},
computed: {
...mapState({
currentUser: state => state.account.user
}),
show: {
get: function () {
return this.requestAddVisiable
},
set: function () {
}
},
columns () {
return [{
title: '物品名称',
dataIndex: 'name',
scopedSlots: {customRender: 'nameShow'}
}, {
title: '型号',
dataIndex: 'type',
scopedSlots: {customRender: 'typeShow'}
}, {
title: '数量',
dataIndex: 'amount',
scopedSlots: {customRender: 'amountShow'}
}, {
title: '所属类型',
dataIndex: 'typeId',
width: 200,
scopedSlots: {customRender: 'typeIdShow'}
}, {
title: '单位',
dataIndex: 'unit',
scopedSlots: {customRender: 'unitShow'}
}, {
title: '单价',
dataIndex: 'price',
scopedSlots: {customRender: 'priceShow'}
}]
}
},
mounted () {
this.getConsumableType()
},
data () {
return {
dataList: [],
formItemLayout,
form: this.$form.createForm(this),
loading: false,
consumableType: []
}
},
methods: {
getConsumableType () {
this.$get('/cos/consumable-type/list').then((r) => {
this.consumableType = r.data.data
})
},
dataAdd () {
this.dataList.push({name: '', type: '', typeId: '', unit: '', amount: '', price: ''})
},
reset () {
this.loading = false
this.form.resetFields()
},
onClose () {
this.reset()
this.$emit('close')
},
handleSubmit () {
let price = 0
this.dataList.forEach(item => {
price += item.price * item.amount
})
this.form.validateFields((err, values) => {
values.price = price
values.goods = JSON.stringify(this.dataList)
if (!err) {
this.loading = true
this.$post('/cos/stock-info/put', {
...values
}).then((r) => {
this.reset()
this.$emit('success')
}).catch(() => {
this.loading = false
})
}
})
}
}
}
</script>
<style scoped>
</style>
src\views\admin\stock\Stock.vue(修改后):
<template>
<a-card :bordered="false" class="card-area">
<div :class="advanced ? 'search' : null">
<!-- 搜索区域 -->
<a-form layout="horizontal">
<a-row :gutter="15">
<div :class="advanced ? null: 'fold'">
<a-col :md="6" :sm="24">
<a-form-item
label="物品名称"
:labelCol="{span: 4}"
:wrapperCol="{span: 18, offset: 2}">
<a-input v-model="queryParams.name"/>
</a-form-item>
</a-col>
<a-col :md="6" :sm="24">
<a-form-item
label="物品型号"
:labelCol="{span: 4}"
:wrapperCol="{span: 18, offset: 2}">
<a-input v-model="queryParams.type"/>
</a-form-item>
</a-col>
<a-col :md="6" :sm="24">
<a-form-item
label="物品类型"
:labelCol="{span: 4}"
:wrapperCol="{span: 18, offset: 2}">
<a-select v-model="queryParams.typeId" style="width: 100%" allowClear>
<a-select-option v-for="(item, index) in consumableType" :value="item.id" :key="index">{{ item.name }}</a-select-option>
</a-select>
</a-form-item>
</a-col>
</div>
<span style="float: right; margin-top: 3px;">
<a-button type="primary" @click="search">查询</a-button>
<a-button style="margin-left: 8px" @click="reset">重置</a-button>
</span>
</a-row>
</a-form>
</div>
<div>
<div class="operator">
<a-button type="primary" ghost @click="warehouse">入库</a-button>
<a-button type="primary" ghost @click="outOfWarehouse">出库</a-button>
<!--<a-button @click="batchDelete">删除</a-button>-->
</div>
<!-- 表格区域 -->
<a-table ref="TableInfo"
:columns="columns"
:rowKey="record => record.id"
:dataSource="dataSource"
:pagination="pagination"
:loading="loading"
:rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
:scroll="{ x: 900 }"
@change="handleTableChange">
<template slot="titleShow" slot-scope="text, record">
<template>
<a-badge status="processing"/>
<a-tooltip>
<template slot="title">
{{ record.title }}
</template>
{{ record.title.slice(0, 8) }} ...
</a-tooltip>
</template>
</template>
<template slot="contentShow" slot-scope="text, record">
<template>
<a-tooltip>
<template slot="title">
{{ record.content }}
</template>
{{ record.content.slice(0, 30) }} ...
</a-tooltip>
</template>
</template>
<template slot="operation" slot-scope="text, record">
<a-icon type="setting" theme="twoTone" twoToneColor="#4a9ff5" @click="edit(record)" title="修 改"></a-icon>
</template>
</a-table>
</div>
<stock-add
v-if="stockAdd.visiable"
@close="handleStockAddClose"
@success="handleStockAddSuccess"
:stockAddVisiable="stockAdd.visiable">
</stock-add>
<stock-out
@close="handleStockoutClose"
@success="handleStockoutSuccess"
:stockoutData="stockout.data"
:stockoutVisiable="stockout.visiable">
</stock-out>
</a-card>
</template>
<script>
import RangeDate from '@/components/datetime/RangeDate'
import {mapState} from 'vuex'
import StockOut from './StockOut'
import StockAdd from './StockAdd'
import moment from 'moment'
moment.locale('zh-cn')
export default {
name: 'Stock',
components: {StockOut, StockAdd, RangeDate},
data () {
return {
advanced: false,
stockAdd: {
visiable: false
},
stockout: {
visiable: false,
data: null
},
requestEdit: {
visiable: false
},
queryParams: {},
filteredInfo: null,
sortedInfo: null,
paginationInfo: null,
dataSource: [],
selectedRowKeys: [],
selectedRows: [],
loading: false,
pagination: {
pageSizeOptions: ['10', '20', '30', '40', '100'],
defaultCurrent: 1,
defaultPageSize: 10,
showQuickJumper: true,
showSizeChanger: true,
showTotal: (total, range) => `显示 ${range[0]} ~ ${range[1]} 条记录,共 ${total} 条记录`
},
consumableType: []
}
},
computed: {
...mapState({
currentUser: state => state.account.user
}),
columns () {
return [{
title: '物品名称',
dataIndex: 'name'
}, {
title: '型号',
dataIndex: 'type',
customRender: (text, row, index) => {
if (text !== null) {
return text
} else {
return '- -'
}
}
}, {
title: '物品数量',
dataIndex: 'amount',
customRender: (text, row, index) => {
if (text !== null) {
return text
} else {
return '- -'
}
}
}, {
title: '单位',
dataIndex: 'unit',
customRender: (text, row, index) => {
if (text !== null) {
return text
} else {
return '- -'
}
}
}, {
title: '单价',
dataIndex: 'price',
customRender: (text, row, index) => {
if (text !== null) {
return '¥' + text.toFixed(2)
} else {
return '- -'
}
}
}, {
title: '总价',
dataIndex: 'allPrice',
customRender: (text, row, index) => {
return '¥' + (row.price * row.amount).toFixed(2)
}
}, {
title: '物品类型',
dataIndex: 'consumableType',
customRender: (text, row, index) => {
if (text !== null) {
return <a-tag>{text}</a-tag>
} else {
return '- -'
}
}
}, {
title: '备注',
dataIndex: 'content',
customRender: (text, row, index) => {
if (text !== null) {
return text
} else {
return '- -'
}
}
}, {
title: '入库时间',
dataIndex: 'createDate',
customRender: (text, row, index) => {
if (text !== null) {
return text
} else {
return '- -'
}
}
}]
}
},
mounted () {
this.fetch()
this.getConsumableType()
},
methods: {
getConsumableType () {
this.$get('/cos/consumable-type/list').then((r) => {
this.consumableType = r.data.data
})
},
onSelectChange (selectedRowKeys, selectedRows) {
selectedRows.forEach(item => {
if (item.amount === 0) {
this.$message.warning(`${item.name}没有库存!`)
return false
}
})
this.selectedRowKeys = selectedRowKeys
this.selectedRows = selectedRows
},
toggleAdvanced () {
this.advanced = !this.advanced
},
// “入库”按键响应
warehouse () {
this.stockAdd.visiable = true
},
// “出库”按键的响应方法
outOfWarehouse () {
if (!this.selectedRowKeys.length) {
this.$message.warning('请选择需要出库的物品')
return
}
let goods = this.selectedRows
let amt = false
let warningwords = '某个物品'
goods.forEach(item => {
item.max = item.amount
if (item.amount === 0) {
amt = true
warningwords = item.name
}
})
if (amt) {
this.$message.warning(`${warningwords}没有库存!`)
return
}
this.stockout.data = JSON.parse(JSON.stringify(goods))
this.stockout.visiable = true
},
handleStockAddClose () {
this.stockAdd.visiable = false
},
handleStockAddSuccess () {
this.stockAdd.visiable = false
this.$message.success('入库成功')
this.search()
},
handleStockoutClose () {
this.stockout.visiable = false
},
handleStockoutSuccess () {
this.stockout.visiable = false
this.selectedRows = []
this.selectedRowKeys = []
this.$message.success('出库成功')
this.search()
},
handleDeptChange (value) {
this.queryParams.deptId = value || ''
},
batchDelete () {
if (!this.selectedRowKeys.length) {
this.$message.warning('请选择需要删除的记录')
return
}
let that = this
this.$confirm({
title: '确定删除所选中的记录?',
content: '当您点击确定按钮后,这些记录将会被彻底删除',
centered: true,
onOk () {
let ids = that.selectedRowKeys.join(',')
that.$delete('/cos/request-type/' + ids).then(() => {
that.$message.success('删除成功')
that.selectedRowKeys = []
that.selectedRows = []
that.search()
})
},
onCancel () {
that.selectedRowKeys = []
that.selectedRows = []
}
})
},
search () {
let {sortedInfo, filteredInfo} = this
let sortField, sortOrder
// 获取当前列的排序和列的过滤规则
if (sortedInfo) {
sortField = sortedInfo.field
sortOrder = sortedInfo.order
}
this.fetch({
sortField: sortField,
sortOrder: sortOrder,
...this.queryParams,
...filteredInfo
})
},
reset () {
// 取消选中
this.selectedRowKeys = []
// 重置分页
this.$refs.TableInfo.pagination.current = this.pagination.defaultCurrent
if (this.paginationInfo) {
this.paginationInfo.current = this.pagination.defaultCurrent
this.paginationInfo.pageSize = this.pagination.defaultPageSize
}
// 重置列过滤器规则
this.filteredInfo = null
// 重置列排序规则
this.sortedInfo = null
// 重置查询参数
this.queryParams = {}
this.fetch()
},
handleTableChange (pagination, filters, sorter) {
// 将这三个参数赋值给Vue data,用于后续使用
this.paginationInfo = pagination
this.filteredInfo = filters
this.sortedInfo = sorter
this.fetch({
sortField: sorter.field,
sortOrder: sorter.order,
...this.queryParams,
...filters
})
},
fetch (params = {}) {
// 显示loading
this.loading = true
if (this.paginationInfo) {
// 如果分页信息不为空,则设置表格当前第几页,每页条数,并设置查询分页参数
this.$refs.TableInfo.pagination.current = this.paginationInfo.current
this.$refs.TableInfo.pagination.pageSize = this.paginationInfo.pageSize
params.size = this.paginationInfo.pageSize
params.current = this.paginationInfo.current
} else {
// 如果分页信息为空,则设置为默认值
params.size = this.pagination.defaultPageSize
params.current = this.pagination.defaultCurrent
}
if (params.typeId === undefined) {
delete params.typeId
}
this.$get('/cos/stock-info/page', {
...params
}).then((r) => {
let data = r.data.data
const pagination = {...this.pagination}
pagination.total = data.total
this.dataSource = data.records
this.pagination = pagination
// 数据加载完毕,关闭loading
this.loading = false
})
}
},
watch: {}
}
</script>
<style lang="less" scoped>
@import "../../../../static/less/Common";
</style>
src\views\admin\stock\StockAdd.vue(修改后):
<template>
<a-drawer
title="物品入库"
:maskClosable="false"
placement="right"
:closable="false"
:visible="show"
:width="1200"
@close="onClose"
style="height: calc(100% - 55px);overflow: auto;padding-bottom: 53px;"
>
<a-form :form="form" layout="horizontal">
<a-row :gutter="50">
<a-col :span="12">
<a-form-item label='保管人' v-bind="formItemLayout">
<a-input v-decorator="[
'custodian',
{ rules: [{ required: true, message: '请输入保管人!' }] }
]"/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label='入库人' v-bind="formItemLayout">
<a-input v-decorator="[
'putUser',
{ rules: [{ required: true, message: '请输入入库人!' }] }
]"/>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label='备注消息' v-bind="formItemLayout">
<a-textarea :rows="4" v-decorator="[
'content',
{ rules: [{ required: true, message: '请输入名称!' }] }
]"/>
</a-form-item>
</a-col>
<a-col :span="24">
<a-table :columns="columns" :data-source="dataList">
<template slot="nameShow" slot-scope="text, record">
<a-input v-model="record.name"></a-input>
</template>
<template slot="typeShow" slot-scope="text, record">
<a-input v-model="record.type"></a-input>
</template>
<template slot="typeIdShow" slot-scope="text, record">
<a-select v-model="record.typeId" style="width: 100%">
<a-select-option v-for="(item, index) in consumableType" :value="item.id" :key="index">{{ item.name }}</a-select-option>
</a-select>
</template>
<template slot="unitShow" slot-scope="text, record">
<a-input v-model="record.unit"></a-input>
</template>
<template slot="amountShow" slot-scope="text, record">
<a-input-number v-model="record.amount" :min="1" :step="1"/>
</template>
<template slot="priceShow" slot-scope="text, record">
<a-input-number v-model="record.price" :min="1"/>
</template>
</a-table>
<a-button @click="dataAdd" type="primary" ghost size="large" style="margin-top: 10px;width: 100%">
新增物品
</a-button>
</a-col>
</a-row>
</a-form>
<div class="drawer-bootom-button">
<a-popconfirm title="确定放弃编辑?" @confirm="onClose" okText="确定" cancelText="取消">
<a-button style="margin-right: .8rem">取消</a-button>
</a-popconfirm>
<a-button @click="handleSubmit" type="primary" :loading="loading">提交</a-button>
</div>
</a-drawer>
</template>
<script>
import {mapState} from 'vuex'
const formItemLayout = {
labelCol: { span: 24 },
wrapperCol: { span: 24 }
}
export default {
name: 'stockAdd',
props: {
stockAddVisiable: {
default: false
}
},
computed: {
...mapState({
currentUser: state => state.account.user
}),
show: {
get: function () {
return this.stockAddVisiable
},
set: function () {
}
},
columns () {
return [{
title: '物品名称',
dataIndex: 'name',
scopedSlots: {customRender: 'nameShow'}
}, {
title: '型号',
dataIndex: 'type',
scopedSlots: {customRender: 'typeShow'}
}, {
title: '数量',
dataIndex: 'amount',
scopedSlots: {customRender: 'amountShow'}
}, {
title: '所属类型',
dataIndex: 'typeId',
width: 200,
scopedSlots: {customRender: 'typeIdShow'}
}, {
title: '单位',
dataIndex: 'unit',
scopedSlots: {customRender: 'unitShow'}
}, {
title: '单价',
dataIndex: 'price',
scopedSlots: {customRender: 'priceShow'}
}]
}
},
mounted () {
this.getConsumableType()
},
data () {
return {
dataList: [],
formItemLayout,
form: this.$form.createForm(this),
loading: false,
consumableType: []
}
},
methods: {
getConsumableType () {
this.$get('/cos/consumable-type/list').then((r) => {
this.consumableType = r.data.data
})
},
dataAdd () {
this.dataList.push({name: '', type: '', typeId: '', unit: '', amount: '', price: ''})
},
reset () {
this.loading = false
this.form.resetFields()
},
onClose () {
this.reset()
this.$emit('close')
},
handleSubmit () {
let price = 0
this.dataList.forEach(item => {
price += item.price * item.amount
})
this.form.validateFields((err, values) => {
values.price = price
values.goods = JSON.stringify(this.dataList)
if (!err) {
this.loading = true
this.$post('/cos/stock-info/put', {
...values
}).then((r) => {
this.reset()
this.$emit('success')
}).catch(() => {
this.loading = false
})
}
})
}
}
}
</script>
<style scoped>
</style>