refactor(刀具管理): 重构刀具管理相关组件结构
重构刀具管理模块,将刀具信息、刀具库存和刀具额定寿命整合到刀具列表页签中,移除独立的刀具台账页面
优化子组件数据加载逻辑,确保切换页签和选择刀具时正确加载对应数据
为扩展属性列表和额定寿命列表添加行内编辑功能
| | |
| | | <template > |
| | | <a-card :bordered="false" :body-style="{ padding: '0 24px 24px 24px' }"> |
| | | <a-tabs default-active-key="1"> |
| | | <a-tab-pane key="1" tab="刀具信息"> |
| | | <cutting-tool-list ref="cuttingToolList"></cutting-tool-list> |
| | | </a-tab-pane> |
| | | <a-tab-pane key="2" tab="刀具库存"> |
| | | <cutting-inventory-list ref="cuttingInventoryList"></cutting-inventory-list> |
| | | </a-tab-pane> |
| | | <a-tab-pane key="3" tab="刀具额定寿命"> |
| | | <rated-life-list ref="RatedLifeList"></rated-life-list> |
| | | </a-tab-pane> |
| | | </a-tabs> |
| | | </a-card> |
| | | </template> |
| | | <!--<template >--> |
| | | <!-- <a-card :bordered="false" :body-style="{ padding: '0 24px 24px 24px' }">--> |
| | | <!-- <a-tabs default-active-key="1">--> |
| | | <!-- <a-tab-pane key="1" tab="刀具信息">--> |
| | | <!-- <cutting-tool-list ref="cuttingToolList"></cutting-tool-list>--> |
| | | <!-- </a-tab-pane>--> |
| | | <!-- <a-tab-pane key="2" tab="刀具库存">--> |
| | | <!-- <cutting-inventory-list ref="cuttingInventoryList"></cutting-inventory-list>--> |
| | | <!-- </a-tab-pane>--> |
| | | <!-- <a-tab-pane key="3" tab="刀具额定寿命">--> |
| | | <!-- <rated-life-list ref="RatedLifeList"></rated-life-list>--> |
| | | <!-- </a-tab-pane>--> |
| | | <!-- </a-tabs>--> |
| | | <!-- </a-card>--> |
| | | <!--</template>--> |
| | | |
| | | <script> |
| | | import CuttingToolList from './CuttingToolList' |
| | | import CuttingInventoryList from './CuttingInventoryList' |
| | | import RatedLifeList from './RatedLifeList.vue' |
| | | <!--<script>--> |
| | | <!--import CuttingToolList from './CuttingToolList'--> |
| | | <!--import CuttingInventoryList from './CuttingInventoryList'--> |
| | | <!--import RatedLifeList from './RatedLifeList.vue'--> |
| | | |
| | | export default { |
| | | name: '刀具台账', |
| | | components: { |
| | | CuttingToolList, |
| | | CuttingInventoryList, |
| | | RatedLifeList, |
| | | }, |
| | | data() { |
| | | return {} |
| | | }, |
| | | methods: { |
| | | callback(key) { |
| | | console.log('切换到页签:', key) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | <!--export default {--> |
| | | <!-- name: '刀具台账',--> |
| | | <!-- components: {--> |
| | | <!-- CuttingToolList,--> |
| | | <!-- CuttingInventoryList,--> |
| | | <!-- RatedLifeList,--> |
| | | <!-- },--> |
| | | <!-- data() {--> |
| | | <!-- return {}--> |
| | | <!-- },--> |
| | | <!-- methods: {--> |
| | | <!-- callback(key) {--> |
| | | <!-- console.log('切换到页签:', key)--> |
| | | <!-- }--> |
| | | <!-- }--> |
| | | <!--}--> |
| | | <!--</script>--> |
| | | |
| | | <style scoped> |
| | | @import '~@assets/less/common.less'; |
| | | <!--<style scoped>--> |
| | | <!--@import '~@assets/less/common.less';--> |
| | | |
| | | </style> |
| | | <!--</style>--> |
| | |
| | | <template> |
| | | <a-card :bordered="false"> |
| | | <!-- 新增按钮 --> |
| | | <div class="table-operator" style="margin-bottom: 10px;"> |
| | | <a-button |
| | | @click="handleAdd" |
| | | type="primary" |
| | | icon="plus" |
| | | :disabled="queryParam.cuttingId === '-1' || !queryParam.cuttingId" |
| | | > |
| | | 新增 |
| | | </a-button> |
| | | </div> |
| | | |
| | | <!-- table区域-begin --> |
| | | <div> |
| | | <a-table |
| | |
| | | </a-button> |
| | | </template> |
| | | |
| | | <span slot="action" slot-scope="text, record"> |
| | | <a @click="handleEdit(record)">编辑</a> |
| | | <!-- 可编辑单元格 --> |
| | | <template |
| | | v-for="col in ['propertyCode', 'propertyName', 'propertyUnit', 'propertyValue']" |
| | | :slot="col" |
| | | slot-scope="text, record" |
| | | > |
| | | <div :key="col"> |
| | | <a-input |
| | | v-if="record.editable" |
| | | style="margin: -5px 0" |
| | | :value="text" |
| | | @change="e => handleChange(e.target.value, record.id, col)" |
| | | /> |
| | | <template v-else> |
| | | {{ text }} |
| | | </template> |
| | | </div> |
| | | </template> |
| | | |
| | | <!-- 操作列 --> |
| | | <span slot="action" slot-scope="text, record"> |
| | | <div class="editable-row-operations"> |
| | | <span v-if="record.editable"> |
| | | <a-popconfirm title="确定保存?" @confirm="() => save(record.id)"> |
| | | <a>保存</a> |
| | | </a-popconfirm> |
| | | <a style="margin-left: 8px" @click="() => cancel(record.id)">取消</a> |
| | | </span> |
| | | <span v-else> |
| | | <a :disabled="editingKey !== ''" @click="() => edit(record.id)">编辑</a> |
| | | <a-divider type="vertical" /> |
| | | <a-dropdown> |
| | | <a class="ant-dropdown-link">更多 <a-icon type="down" /></a> |
| | | <a-menu slot="overlay"> |
| | | <a-menu-item> |
| | | <a @click="handleDetail(record)">详情</a> |
| | | </a-menu-item> |
| | | <a-menu-item> |
| | | <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)"> |
| | | <a>删除</a> |
| | |
| | | </a-menu> |
| | | </a-dropdown> |
| | | </span> |
| | | </div> |
| | | </span> |
| | | |
| | | </a-table> |
| | | </div> |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | |
| | | import '@/assets/less/TableExpand.less' |
| | | import { mixinDevice } from '@/utils/mixin' |
| | | import { JeecgListMixin } from '@/mixins/JeecgListMixin' |
| | | import { putAction, getAction, postAction } from '@/api/manage' |
| | | |
| | | export default { |
| | | name: 'CuttingPropertiesList', |
| | |
| | | data () { |
| | | return { |
| | | description: '刀具扩展属性管理页面', |
| | | editingKey: '', |
| | | // 表头 |
| | | columns: [ |
| | | { |
| | |
| | | { |
| | | title:'属性编码', |
| | | align:"center", |
| | | dataIndex: 'propertyCode' |
| | | dataIndex: 'propertyCode', |
| | | scopedSlots: { customRender: 'propertyCode' } |
| | | }, |
| | | { |
| | | title:'属性名称', |
| | | align:"center", |
| | | dataIndex: 'propertyName' |
| | | dataIndex: 'propertyName', |
| | | scopedSlots: { customRender: 'propertyName' } |
| | | }, |
| | | { |
| | | title:'计量单位', |
| | | align:"center", |
| | | dataIndex: 'propertyUnit' |
| | | dataIndex: 'propertyUnit', |
| | | scopedSlots: { customRender: 'propertyUnit' } |
| | | }, |
| | | { |
| | | title:'属性值', |
| | | align:"center", |
| | | dataIndex: 'propertyValue' |
| | | dataIndex: 'propertyValue', |
| | | scopedSlots: { customRender: 'propertyValue' } |
| | | }, |
| | | { |
| | | title: '操作', |
| | | dataIndex: 'action', |
| | | align:"center", |
| | | scopedSlots: { customRender: 'action' }, |
| | | width: 200, |
| | | } |
| | | ], |
| | | url: { |
| | |
| | | deleteBatch: "/cms/cuttingProperties/deleteBatch", |
| | | exportXlsUrl: "/cms/cuttingProperties/exportXls", |
| | | importExcelUrl: "cms/cuttingProperties/importExcel", |
| | | |
| | | edit: "/cms/cuttingProperties/edit", |
| | | add: "/cms/cuttingProperties/add" // 添加新增接口 |
| | | }, |
| | | dictOptions:{}, |
| | | superFieldList:[], |
| | |
| | | this.queryParam.cuttingId = cuttingId; |
| | | this.loadData(1); |
| | | }, |
| | | |
| | | // 新增行 |
| | | handleAdd() { |
| | | // 如果已经在编辑状态,不允许新增 |
| | | if (this.editingKey !== '') { |
| | | // 查找正在编辑的记录并取消编辑 |
| | | const editingRecord = this.dataSource.find(item => item.id === this.editingKey); |
| | | if (editingRecord) { |
| | | this.cancel(this.editingKey); |
| | | } |
| | | } |
| | | |
| | | // 创建新的空数据项 |
| | | const newRow = { |
| | | id: 'new_' + new Date().getTime(), // 临时ID |
| | | cuttingId: this.queryParam.cuttingId, |
| | | propertyCode: '', |
| | | propertyName: '', |
| | | propertyUnit: '', |
| | | propertyValue: '', |
| | | editable: true, |
| | | isNew: true // 标记为新添加的行 |
| | | }; |
| | | |
| | | // 将新行插入到数据源开头 |
| | | this.dataSource = [newRow, ...this.dataSource]; |
| | | this.editingKey = newRow.id; |
| | | }, |
| | | |
| | | // 编辑行数据 |
| | | edit(key) { |
| | | // 先保存当前数据的副本 |
| | | const newData = [...this.dataSource]; |
| | | const target = newData.find(item => key === item.id); |
| | | this.editingKey = key; |
| | | |
| | | if (target) { |
| | | target.editable = true; |
| | | this.dataSource = newData; |
| | | } |
| | | }, |
| | | |
| | | // 保存编辑的数据 |
| | | save(key) { |
| | | const newData = [...this.dataSource]; |
| | | const target = newData.find(item => key === item.id); |
| | | |
| | | if (target) { |
| | | delete target.editable; |
| | | this.dataSource = newData; |
| | | |
| | | // 判断是新增还是编辑 |
| | | if (target.isNew) { |
| | | // 新增操作 |
| | | const params = { ...target }; |
| | | delete params.id; |
| | | delete params.isNew; |
| | | // 删除创建时间字段,让后端自动生成 |
| | | delete params.createTime; |
| | | delete params.updateTime; |
| | | |
| | | postAction(this.url.add, params).then(res => { |
| | | if (res.success) { |
| | | this.$message.success('新增成功'); |
| | | this.editingKey = ''; |
| | | this.loadData(); // 重新加载数据 |
| | | } else { |
| | | this.$message.error(res.message); |
| | | } |
| | | }).catch(err => { |
| | | this.$message.error('新增失败'); |
| | | console.log(err); |
| | | }); |
| | | } else { |
| | | // 编辑操作 - 只发送需要更新的字段 |
| | | const params = { |
| | | id: target.id, |
| | | propertyCode: target.propertyCode, |
| | | propertyName: target.propertyName, |
| | | propertyUnit: target.propertyUnit, |
| | | propertyValue: target.propertyValue, |
| | | // 不包含 createTime 字段 |
| | | }; |
| | | |
| | | putAction(this.url.edit, params).then(res => { |
| | | if (res.success) { |
| | | this.$message.success('保存成功'); |
| | | this.editingKey = ''; |
| | | this.loadData(); // 重新加载数据 |
| | | } else { |
| | | this.$message.error(res.message); |
| | | } |
| | | }).catch(err => { |
| | | this.$message.error('保存失败'); |
| | | console.log(err); |
| | | }); |
| | | } |
| | | } |
| | | }, |
| | | |
| | | // 取消编辑 |
| | | cancel(key) { |
| | | const newData = [...this.dataSource]; |
| | | const targetIndex = newData.findIndex(item => key === item.id); |
| | | this.editingKey = ''; |
| | | |
| | | if (targetIndex >= 0) { |
| | | // 如果是新增的行,直接删除 |
| | | if (newData[targetIndex].isNew) { |
| | | newData.splice(targetIndex, 1); |
| | | this.dataSource = newData; |
| | | } else { |
| | | // 如果是编辑的行,从后端重新获取数据以恢复原始值 |
| | | const target = newData[targetIndex]; |
| | | getAction(this.url.list, { id: key }).then(res => { |
| | | if(res.success && res.result.records.length > 0) { |
| | | const originalData = res.result.records[0]; |
| | | Object.keys(target).forEach(key => { |
| | | if(key !== 'editable') { |
| | | target[key] = originalData[key]; |
| | | } |
| | | }); |
| | | delete target.editable; |
| | | this.dataSource = newData; |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | }, |
| | | |
| | | // 处理单元格值变化 |
| | | handleChange(value, key, column) { |
| | | const newData = [...this.dataSource]; |
| | | const target = newData.find(item => key === item.id); |
| | | |
| | | if (target) { |
| | | target[column] = value; |
| | | this.dataSource = newData; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | @import '~@assets/less/common.less'; |
| | | |
| | | .editable-row-operations a { |
| | | margin-right: 8px; |
| | | } |
| | | </style> |
| | |
| | | </a-table> |
| | | </div> |
| | | |
| | | <a-tabs defaultActiveKey="1"> |
| | | <a-tabs defaultActiveKey="1" @change="onTabChange"> |
| | | <a-tab-pane tab="扩展属性" key="1"> |
| | | <cutting-properties-list ref="cuttingPropertiesList"></cutting-properties-list> |
| | | </a-tab-pane> |
| | | <a-tab-pane key="2" tab="刀具库存"> |
| | | <cutting-inventory-list ref="cuttingInventoryList"></cutting-inventory-list> |
| | | </a-tab-pane> |
| | | <a-tab-pane key="3" tab="刀具额定寿命"> |
| | | <rated-life-list |
| | | ref="RatedLifeList" |
| | | :selected-cutting-id="selectedRowKeys.length > 0 ? selectedRowKeys[0] : ''"> |
| | | </rated-life-list> |
| | | </a-tab-pane> |
| | | </a-tabs> |
| | | <!-- table区域-end --> |
| | |
| | | import CuttingPropertiesList from './CuttingPropertiesList' |
| | | import JDictSelectTag from '@/components/dict/JDictSelectTag' |
| | | import JSearchSelectTag from '@/components/dict/JSearchSelectTag' |
| | | import CuttingInventoryList from '@views/cms/CuttingInventoryList.vue' |
| | | import RatedLifeList from '@views/cms/RatedLifeList.vue' |
| | | import { getAction } from '@api/manage' |
| | | |
| | | export default { |
| | | name: 'CuttingToolList', |
| | | mixins: [JeecgListMixin, mixinDevice], |
| | | components: { |
| | | RatedLifeList, |
| | | CuttingInventoryList, |
| | | CuttingToolModal, |
| | | CuttingPropertiesList, |
| | | JDictSelectTag, |
| | | JSearchSelectTag |
| | | JSearchSelectTag, |
| | | }, |
| | | data() { |
| | | return { |
| | |
| | | } |
| | | }; |
| | | }, |
| | | |
| | | onSelectChange(selectedRowKeys) { |
| | | console.log('Selected row keys:', selectedRowKeys); |
| | | this.selectedRowKeys = selectedRowKeys; |
| | | if (selectedRowKeys.length > 0) { |
| | | this.$refs.cuttingPropertiesList.getCuttingProperties(selectedRowKeys[0]); |
| | | console.log('Loading details for:', selectedRowKeys[0]); |
| | | const selectedId = selectedRowKeys[0]; |
| | | |
| | | // 使用 $nextTick 确保 DOM 更新完成 |
| | | this.$nextTick(() => { |
| | | // 检查并调用各个子组件的方法,无论当前在哪个页签 |
| | | if (this.$refs.cuttingPropertiesList) { |
| | | this.$refs.cuttingPropertiesList.getCuttingProperties(selectedId); |
| | | } |
| | | |
| | | if (this.$refs.RatedLifeList) { |
| | | this.$refs.RatedLifeList.getRatedLife(selectedId); |
| | | } |
| | | |
| | | if (this.$refs.cuttingInventoryList) { |
| | | this.$refs.cuttingInventoryList.getCuttingInventory(selectedId); |
| | | } |
| | | }); |
| | | } |
| | | }, |
| | | |
| | | handleEdit(record) { |
| | | this.$refs.modalForm.edit(record); |
| | | this.$refs.modalForm.title = '编辑'; |
| | |
| | | }, |
| | | searchQuery() { |
| | | this.selectedRowKeys = []; |
| | | this.loadData(); |
| | | |
| | | // 清理所有子组件的数据 |
| | | this.$nextTick(() => { |
| | | if (this.$refs.cuttingPropertiesList) { |
| | | this.$refs.cuttingPropertiesList.getCuttingProperties("-1"); |
| | | this.$refs.cuttingPropertiesList.loadData(); |
| | | this.$refs.cuttingPropertiesList.selectedRowKeys = []; |
| | | this.loadData(); |
| | | } |
| | | |
| | | if (this.$refs.cuttingInventoryList) { |
| | | this.$refs.cuttingInventoryList.getCuttingInventory("-1"); |
| | | this.$refs.cuttingInventoryList.selectedRowKeys = []; |
| | | } |
| | | |
| | | if (this.$refs.RatedLifeList) { |
| | | this.$refs.RatedLifeList.getRatedLife("-1"); |
| | | this.$refs.RatedLifeList.selectedRowKeys = []; |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | searchReset() { |
| | | this.queryParam = { |
| | | cuttingCode: '', |
| | | cuttingName: '', |
| | | cuttingCategory: '' |
| | | }; |
| | | this.$refs.cuttingPropertiesList.getCuttingProperties("-1"); |
| | | this.selectedRowKeys = []; |
| | | this.loadData(); |
| | | |
| | | // 清理所有子组件的数据 |
| | | this.$nextTick(() => { |
| | | if (this.$refs.cuttingPropertiesList) { |
| | | this.$refs.cuttingPropertiesList.getCuttingProperties("-1"); |
| | | this.$refs.cuttingPropertiesList.selectedRowKeys = []; |
| | | } |
| | | |
| | | if (this.$refs.cuttingInventoryList) { |
| | | this.$refs.cuttingInventoryList.getCuttingInventory("-1"); |
| | | this.$refs.cuttingInventoryList.selectedRowKeys = []; |
| | | } |
| | | |
| | | if (this.$refs.RatedLifeList) { |
| | | this.$refs.RatedLifeList.getRatedLife("-1"); |
| | | this.$refs.RatedLifeList.selectedRowKeys = []; |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | onClearSelected() { |
| | | this.selectedRowKeys = []; |
| | | this.selectionRows = []; |
| | | // 清空 CuttingPropertiesList 列表数据 |
| | | this.$refs.cuttingPropertiesList.dataSource = []; |
| | | this.$refs.cuttingPropertiesList.selectedRowKeys = []; |
| | | this.$refs.cuttingPropertiesList.selectionRows = []; |
| | | this.$refs.cuttingPropertiesList.queryParam.cuttingId = "-1"; |
| | | }, |
| | | |
| | | loadData(arg) { |
| | | if(!this.url.list){ |
| | | this.$message.error("请设置url.list属性!") |
| | | return |
| | | } |
| | | //加载数据 若传入参数1则加载第一页的内容 |
| | | if (arg === 1) { |
| | | this.ipagination.current = 1; |
| | | } |
| | | var params = this.getQueryParams();//查询条件 |
| | | console.log('params',params) |
| | | if(!params){ |
| | | return false; |
| | | } |
| | | this.loading = true; |
| | | getAction(this.url.list, params).then((res) => { |
| | | if (res.success) { |
| | | // console.log(res) |
| | | //update-begin---author:zhangyafei Date:20201118 for:适配不分页的数据列表------------ |
| | | this.dataSource = res.result.records||res.result; |
| | | if(res.result.total) |
| | | { |
| | | this.ipagination.total = res.result.total; |
| | | }else{ |
| | | this.ipagination.total = 0; |
| | | } |
| | | //update-end---author:zhangyafei Date:20201118 for:适配不分页的数据列表------------ |
| | | }else{ |
| | | this.$message.warning(res.message) |
| | | } |
| | | }).finally(() => { |
| | | this.loading = false |
| | | }) |
| | | }, |
| | | |
| | | onTabChange(activeKey) { |
| | | // 当页签切换时,如果已有选中的刀具,立即加载对应的数据 |
| | | if (this.selectedRowKeys.length > 0) { |
| | | const selectedId = this.selectedRowKeys[0]; |
| | | this.$nextTick(() => { |
| | | switch(activeKey) { |
| | | case '1': |
| | | if (this.$refs.cuttingPropertiesList) { |
| | | this.$refs.cuttingPropertiesList.getCuttingProperties(selectedId); |
| | | } |
| | | break; |
| | | case '2': |
| | | if (this.$refs.cuttingInventoryList) { |
| | | this.$refs.cuttingInventoryList.getCuttingInventory(selectedId); |
| | | } |
| | | break; |
| | | case '3': |
| | | if (this.$refs.RatedLifeList) { |
| | | this.$refs.RatedLifeList.getRatedLife(selectedId); |
| | | } |
| | | break; |
| | | } |
| | | }); |
| | | } |
| | | }, |
| | | |
| | | handleOk() { |
| | | // 新增/修改 成功时,重载列表 |
| | | this.loadData(); |
| | |
| | | <template> |
| | | <a-card :bordered="false"> |
| | | <!-- 查询区域 --> |
| | | <div class="table-page-search-wrapper"> |
| | | <a-form layout="inline" @keyup.enter.native="searchQuery"> |
| | | <a-row :gutter="24"> |
| | | <a-col :md="6" :sm="8"> |
| | | <a-form-item label="刀具编码"> |
| | | <a-input placeholder="请输入刀具编码" v-model="queryParam.cuttingId" /> |
| | | </a-form-item> |
| | | </a-col> |
| | | <a-col :md="6" :sm="8"> |
| | | <a-form-item label="工件材质"> |
| | | <a-input placeholder="请输入工件材质" v-model="queryParam.workpieceMaterial" /> |
| | | </a-form-item> |
| | | </a-col> |
| | | <a-col |
| | | :md="6" |
| | | :sm="8" |
| | | > |
| | | <span |
| | | style="float: left;overflow: hidden;" |
| | | class="table-page-search-submitButtons" |
| | | > |
| | | <!-- 新增按钮 --> |
| | | <div class="table-operator" style="margin-bottom: 10px;"> |
| | | <a-button |
| | | @click="handleAdd" |
| | | type="primary" |
| | | @click="searchQuery" |
| | | icon="search" |
| | | >查询</a-button> |
| | | <a-button |
| | | type="primary" |
| | | @click="searchReset" |
| | | icon="reload" |
| | | style="margin-left: 8px" |
| | | >重置</a-button> |
| | | </span> |
| | | </a-col> |
| | | </a-row> |
| | | </a-form> |
| | | </div> |
| | | <!-- 查询区域-END --> |
| | | |
| | | <!-- 操作按钮区域 --> |
| | | <div class="table-operator"> |
| | | <a-button @click="handleAdd" type="primary" icon="plus">新增</a-button> |
| | | <a-button type="primary" icon="download" @click="handleExportXls('额定寿命')">导出</a-button> |
| | | <a-upload name="file" :showUploadList="false" :multiple="false" :headers="tokenHeader" :action="importExcelUrl" @change="handleImportExcel"> |
| | | <a-button type="primary" icon="import">导入</a-button> |
| | | </a-upload> |
| | | icon="plus" |
| | | :disabled="!selectedCuttingId || selectedCuttingId === '' || selectedCuttingId === '-1'" |
| | | > |
| | | 新增 |
| | | </a-button> |
| | | </div> |
| | | |
| | | <!-- table区域-begin --> |
| | | <div> |
| | | <div class="ant-alert ant-alert-info" style="margin-bottom: 16px;"> |
| | | <i class="anticon anticon-info-circle ant-alert-icon"></i> 已选择 <a style="font-weight: 600">{{ selectedRowKeys.length }}</a>项 |
| | | <a style="margin-left: 24px" @click="onClearSelected">清空</a> |
| | | </div> |
| | | |
| | | <a-table |
| | | ref="table" |
| | | size="middle" |
| | |
| | | :dataSource="dataSource" |
| | | :pagination="ipagination" |
| | | :loading="loading" |
| | | :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}" |
| | | class="j-table-force-nowrap" |
| | | @change="handleTableChange"> |
| | | |
| | |
| | | </a-button> |
| | | </template> |
| | | |
| | | <span slot="action" slot-scope="text, record"> |
| | | <a @click="handleEdit(record)">编辑</a> |
| | | <!-- 可编辑单元格 --> |
| | | <template |
| | | v-for="col in ['workpieceMaterial', 'ratedLife']" |
| | | :slot="col" |
| | | slot-scope="text, record" |
| | | > |
| | | <div :key="col"> |
| | | <a-input |
| | | v-if="record.editable" |
| | | style="margin: -5px 0" |
| | | :value="text" |
| | | @change="e => handleChange(e.target.value, record.id, col)" |
| | | /> |
| | | <template v-else> |
| | | {{ text }} |
| | | </template> |
| | | </div> |
| | | </template> |
| | | |
| | | <!-- 操作列 --> |
| | | <span slot="action" slot-scope="text, record"> |
| | | <div class="editable-row-operations"> |
| | | <span v-if="record.editable"> |
| | | <a-popconfirm title="确定保存?" @confirm="() => save(record.id)"> |
| | | <a>保存</a> |
| | | </a-popconfirm> |
| | | <a style="margin-left: 8px" @click="() => cancel(record.id)">取消</a> |
| | | </span> |
| | | <span v-else> |
| | | <a :disabled="editingKey !== ''" @click="() => edit(record.id)">编辑</a> |
| | | <a-divider type="vertical" /> |
| | | <a-dropdown> |
| | | <a class="ant-dropdown-link">更多 <a-icon type="down" /></a> |
| | | <a-menu slot="overlay"> |
| | | <a-menu-item> |
| | | <a @click="handleDetail(record)">详情</a> |
| | | </a-menu-item> |
| | | <a-menu-item> |
| | | <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)"> |
| | | <a>删除</a> |
| | |
| | | </a-menu-item> |
| | | </a-menu> |
| | | </a-dropdown> |
| | | </span> |
| | | </div> |
| | | </span> |
| | | |
| | | </a-table> |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | |
| | | import '@/assets/less/TableExpand.less' |
| | | import { mixinDevice } from '@/utils/mixin' |
| | | import { JeecgListMixin } from '@/mixins/JeecgListMixin' |
| | | import { putAction, getAction, postAction } from '@/api/manage' |
| | | import RatedLifeModal from './modules/RatedLifeModal' |
| | | |
| | | export default { |
| | |
| | | components: { |
| | | RatedLifeModal |
| | | }, |
| | | props: { |
| | | selectedCuttingId: { |
| | | type: String, |
| | | default: '' |
| | | } |
| | | }, |
| | | data () { |
| | | return { |
| | | description: '额定寿命管理页面', |
| | | editingKey: '', |
| | | // 表头 |
| | | columns: [ |
| | | { |
| | |
| | | { |
| | | title:'刀具编码', |
| | | align:"center", |
| | | dataIndex: 'cuttingId', |
| | | dataIndex: 'cuttingId_dictText', |
| | | sorter: true |
| | | }, |
| | | { |
| | | title:'工件材质', |
| | | align:"center", |
| | | dataIndex: 'workpieceMaterial' |
| | | dataIndex: 'workpieceMaterial', |
| | | scopedSlots: { customRender: 'workpieceMaterial' } |
| | | }, |
| | | { |
| | | title:'额定寿命', |
| | | align:"center", |
| | | dataIndex: 'ratedLife' |
| | | dataIndex: 'ratedLife', |
| | | scopedSlots: { customRender: 'ratedLife' } |
| | | }, |
| | | { |
| | | title: '操作', |
| | | dataIndex: 'action', |
| | | align:"center", |
| | | fixed:"right", |
| | | width:147, |
| | | scopedSlots: { customRender: 'action' } |
| | | scopedSlots: { customRender: 'action' }, |
| | | width: 200, |
| | | } |
| | | ], |
| | | url: { |
| | |
| | | deleteBatch: "/cms/ratedLife/deleteBatch", |
| | | exportXlsUrl: "/cms/ratedLife/exportXls", |
| | | importExcelUrl: "cms/ratedLife/importExcel", |
| | | |
| | | edit: "/cms/ratedLife/edit", |
| | | add: "/cms/ratedLife/add" |
| | | }, |
| | | dictOptions:{}, |
| | | superFieldList:[], |
| | |
| | | methods: { |
| | | initDictConfig(){ |
| | | }, |
| | | getRatedLife(cuttingId) { |
| | | this.queryParam.cuttingId = cuttingId; |
| | | // this.ipagination.current = 1; |
| | | this.loadData(1); |
| | | }, |
| | | getSuperFieldList(){ |
| | | let fieldList=[]; |
| | | fieldList.push({type:'string',value:'cuttingId',text:'刀具ID'}) |
| | | fieldList.push({type:'string',value:'workpieceMaterial',text:'工件材质'}) |
| | | fieldList.push({type:'number',value:'ratedLife',text:'额定寿命'}) |
| | | this.superFieldList = fieldList |
| | | }, |
| | | |
| | | // 新增行 |
| | | handleAdd() { |
| | | // 如果已经在编辑状态,自动取消当前编辑项 |
| | | if (this.editingKey !== '') { |
| | | // 查找正在编辑的记录并取消编辑 |
| | | const editingRecord = this.dataSource.find(item => item.id === this.editingKey); |
| | | if (editingRecord) { |
| | | this.cancel(this.editingKey); |
| | | } |
| | | } |
| | | |
| | | // 创建新的空数据项 |
| | | const newRow = { |
| | | id: 'new_' + new Date().getTime(), // 临时ID |
| | | cuttingId: this.queryParam.cuttingId, |
| | | workpieceMaterial: '', |
| | | ratedLife: '', |
| | | editable: true, |
| | | isNew: true // 标记为新添加的行 |
| | | }; |
| | | |
| | | // 将新行插入到数据源开头 |
| | | this.dataSource = [newRow, ...this.dataSource]; |
| | | this.editingKey = newRow.id; |
| | | }, |
| | | |
| | | // 编辑行数据 |
| | | edit(key) { |
| | | // 先保存当前数据的副本 |
| | | const newData = [...this.dataSource]; |
| | | const target = newData.find(item => key === item.id); |
| | | this.editingKey = key; |
| | | |
| | | if (target) { |
| | | target.editable = true; |
| | | this.dataSource = newData; |
| | | } |
| | | }, |
| | | |
| | | // 保存编辑的数据 |
| | | save(key) { |
| | | const newData = [...this.dataSource]; |
| | | const target = newData.find(item => key === item.id); |
| | | |
| | | if (target) { |
| | | delete target.editable; |
| | | this.dataSource = newData; |
| | | |
| | | // 判断是新增还是编辑 |
| | | if (target.isNew) { |
| | | // 新增操作 |
| | | const params = { ...target }; |
| | | delete params.id; |
| | | delete params.isNew; |
| | | // 删除创建时间字段,让后端自动生成 |
| | | delete params.createTime; |
| | | delete params.updateTime; |
| | | |
| | | postAction(this.url.add, params).then(res => { |
| | | if (res.success) { |
| | | this.$message.success('新增成功'); |
| | | this.editingKey = ''; |
| | | this.loadData(); // 重新加载数据 |
| | | } else { |
| | | this.$message.error(res.message); |
| | | } |
| | | }).catch(err => { |
| | | this.$message.error('新增失败'); |
| | | console.log(err); |
| | | }); |
| | | } else { |
| | | // 编辑操作 - 只发送需要更新的字段 |
| | | const params = { |
| | | id: target.id, |
| | | cuttingId: target.cuttingId, |
| | | workpieceMaterial: target.workpieceMaterial, |
| | | ratedLife: target.ratedLife, |
| | | }; |
| | | |
| | | putAction(this.url.edit, params).then(res => { |
| | | if (res.success) { |
| | | this.$message.success('保存成功'); |
| | | this.editingKey = ''; |
| | | this.loadData(); // 重新加载数据 |
| | | } else { |
| | | this.$message.error(res.message); |
| | | } |
| | | }).catch(err => { |
| | | this.$message.error('保存失败'); |
| | | console.log(err); |
| | | }); |
| | | } |
| | | } |
| | | }, |
| | | |
| | | // 取消编辑 |
| | | cancel(key) { |
| | | const newData = [...this.dataSource]; |
| | | const targetIndex = newData.findIndex(item => key === item.id); |
| | | this.editingKey = ''; |
| | | |
| | | if (targetIndex >= 0) { |
| | | // 如果是新增的行,直接删除 |
| | | if (newData[targetIndex].isNew) { |
| | | newData.splice(targetIndex, 1); |
| | | this.dataSource = newData; |
| | | } else { |
| | | // 如果是编辑的行,从后端重新获取数据以恢复原始值 |
| | | const target = newData[targetIndex]; |
| | | getAction(this.url.list, { id: key }).then(res => { |
| | | if(res.success && res.result.records.length > 0) { |
| | | const originalData = res.result.records[0]; |
| | | Object.keys(target).forEach(key => { |
| | | if(key !== 'editable') { |
| | | target[key] = originalData[key]; |
| | | } |
| | | }); |
| | | delete target.editable; |
| | | this.dataSource = newData; |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | }, |
| | | |
| | | // 处理单元格值变化 |
| | | handleChange(value, key, column) { |
| | | const newData = [...this.dataSource]; |
| | | const target = newData.find(item => key === item.id); |
| | | |
| | | if (target) { |
| | | target[column] = value; |
| | | this.dataSource = newData; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | @import '~@assets/less/common.less'; |
| | | |
| | | .editable-row-operations a { |
| | | margin-right: 8px; |
| | | } |
| | | </style> |
| | |
| | | </a-col> |
| | | </a-row> |
| | | <!-- 子表格信息--> |
| | | <a-tabs defaultActiveKey="1"> |
| | | <a-tab-pane |
| | | tab="刀具明细" |
| | | key="1" |
| | | > |
| | | <!-- <a-tabs defaultActiveKey="1">--> |
| | | <!-- <a-tab-pane--> |
| | | <!-- tab="刀具明细"--> |
| | | <!-- key="1"--> |
| | | <!-- >--> |
| | | |
| | | <a-table |
| | | ref="table" |
| | | bordered |
| | | size="middle" |
| | | rowKey="id" |
| | | :columns="columns" |
| | | :dataSource="dataSource" |
| | | :pagination=false |
| | | > |
| | | <!-- <a-table--> |
| | | <!-- ref="table"--> |
| | | <!-- bordered--> |
| | | <!-- size="middle"--> |
| | | <!-- rowKey="id"--> |
| | | <!-- :columns="columns"--> |
| | | <!-- :dataSource="dataSource"--> |
| | | <!-- :pagination=false--> |
| | | <!-- >--> |
| | | |
| | | <template |
| | | v-for="col in columns" |
| | | :slot="col.dataIndex" |
| | | slot-scope='text, record, index' |
| | | > |
| | | <div :key="col.dataIndex"> |
| | | <!-- <template--> |
| | | <!-- v-for="col in columns"--> |
| | | <!-- :slot="col.dataIndex"--> |
| | | <!-- slot-scope='text, record, index'--> |
| | | <!-- >--> |
| | | <!-- <div :key="col.dataIndex">--> |
| | | |
| | | |
| | | |
| | | <a-input |
| | | :value="text" |
| | | :disabled="disableSubmit" |
| | | v-if="col.dataIndex == 'propertyCode'" |
| | | @change="(e)=>handleChange(e.target.value, record.key, col, index)" |
| | | /> |
| | | <!-- <a-input--> |
| | | <!-- :value="text"--> |
| | | <!-- :disabled="disableSubmit"--> |
| | | <!-- v-if="col.dataIndex == 'propertyCode'"--> |
| | | <!-- @change="(e)=>handleChange(e.target.value, record.key, col, index)"--> |
| | | <!-- />--> |
| | | |
| | | <a-input |
| | | :value="text" |
| | | :disabled="disableSubmit" |
| | | v-else-if="col.dataIndex == 'propertyName'" |
| | | @change="(e)=>handleChange(e.target.value, record.key, col, index)" |
| | | /> |
| | | <!-- <a-input--> |
| | | <!-- :value="text"--> |
| | | <!-- :disabled="disableSubmit"--> |
| | | <!-- v-else-if="col.dataIndex == 'propertyName'"--> |
| | | <!-- @change="(e)=>handleChange(e.target.value, record.key, col, index)"--> |
| | | <!-- />--> |
| | | |
| | | <a-input |
| | | :value="text" |
| | | :disabled="disableSubmit" |
| | | v-else-if="col.dataIndex == 'propertyUnit'" |
| | | @change="(e)=>handleChange(e.target.value, record.key, col, index)" |
| | | /> |
| | | <!-- <a-input--> |
| | | <!-- :value="text"--> |
| | | <!-- :disabled="disableSubmit"--> |
| | | <!-- v-else-if="col.dataIndex == 'propertyUnit'"--> |
| | | <!-- @change="(e)=>handleChange(e.target.value, record.key, col, index)"--> |
| | | <!-- />--> |
| | | |
| | | <a-input |
| | | :value="text" |
| | | :disabled="disableSubmit" |
| | | v-else-if="col.dataIndex == 'propertyValue'" |
| | | @change="(e)=>handleChange(e.target.value, record.key, col, index)" |
| | | /> |
| | | <!-- <a-input--> |
| | | <!-- :value="text"--> |
| | | <!-- :disabled="disableSubmit"--> |
| | | <!-- v-else-if="col.dataIndex == 'propertyValue'"--> |
| | | <!-- @change="(e)=>handleChange(e.target.value, record.key, col, index)"--> |
| | | <!-- />--> |
| | | |
| | | </div> |
| | | </template> |
| | | <!-- </div>--> |
| | | <!-- </template>--> |
| | | |
| | | <template |
| | | slot="action" |
| | | slot-scope="text,record,index" |
| | | > |
| | | <a-popconfirm |
| | | title="是否要删除此行?" |
| | | @confirm="handleDelete(text,record,index)" |
| | | > |
| | | <Tooltip |
| | | placement="top" |
| | | title="删除" |
| | | > |
| | | <!-- shape="circle" --> |
| | | <a-button |
| | | :disabled="disableSubmit" |
| | | icon="delete" |
| | | /> |
| | | </Tooltip> |
| | | </a-popconfirm> |
| | | </template> |
| | | <!-- <template--> |
| | | <!-- slot="action"--> |
| | | <!-- slot-scope="text,record,index"--> |
| | | <!-- >--> |
| | | <!-- <a-popconfirm--> |
| | | <!-- title="是否要删除此行?"--> |
| | | <!-- @confirm="handleDelete(text,record,index)"--> |
| | | <!-- >--> |
| | | <!-- <Tooltip--> |
| | | <!-- placement="top"--> |
| | | <!-- title="删除"--> |
| | | <!-- >--> |
| | | <!-- <!– shape="circle" –>--> |
| | | <!-- <a-button--> |
| | | <!-- :disabled="disableSubmit"--> |
| | | <!-- icon="delete"--> |
| | | <!-- />--> |
| | | <!-- </Tooltip>--> |
| | | <!-- </a-popconfirm>--> |
| | | <!-- </template>--> |
| | | |
| | | </a-table> |
| | | <!-- </a-table>--> |
| | | |
| | | <a-button |
| | | :disabled="disableSubmit" |
| | | style="width: 100%; margin-top: 16px; margin-bottom: 8px" |
| | | type="dashed" |
| | | icon="plus" |
| | | @click="addPropertiesList" |
| | | >添加扩展属性</a-button> |
| | | </a-tab-pane> |
| | | </a-tabs> |
| | | <!-- <a-button--> |
| | | <!-- :disabled="disableSubmit"--> |
| | | <!-- style="width: 100%; margin-top: 16px; margin-bottom: 8px"--> |
| | | <!-- type="dashed"--> |
| | | <!-- icon="plus"--> |
| | | <!-- @click="addPropertiesList"--> |
| | | <!-- >添加扩展属性</a-button>--> |
| | | <!-- </a-tab-pane>--> |
| | | <!-- </a-tabs>--> |
| | | <!-- 子表格信息结束--> |
| | | </a-form> |
| | | </a-spin> |