src/api/basicData/product.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/main.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/utils/summarizeTable.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/basicData/product/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/procurementManagement/invoiceEntry/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/procurementManagement/procurementLedger/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/api/basicData/product.js
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,11 @@ // 产åç»´æ¤é¡µé¢æ¥å£ import request from '@/utils/request' // äº§åæ æ¥è¯¢ export function productTreeList(query) { return request({ url: '/basic/product/list', method: 'get', params: query }) } src/main.js
@@ -46,6 +46,7 @@ import PIMTable from "@/components/PIMTable/PIMTable.vue"; import { getToken } from "@/utils/auth"; import { summarizeTable } from "@/utils/summarizeTable.js"; const app = createApp(App) @@ -54,6 +55,7 @@ app.config.globalProperties.download = download app.config.globalProperties.parseTime = parseTime app.config.globalProperties.resetForm = resetForm app.config.globalProperties.summarizeTable = summarizeTable app.config.globalProperties.handleTree = handleTree app.config.globalProperties.addDateRange = addDateRange app.config.globalProperties.selectDictLabel = selectDictLabel src/utils/summarizeTable.js
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,35 @@ /** * éç¨çè¡¨æ ¼åè®¡æ¹æ³ * @param {Object} param * @param {Array} param.columns è¡¨æ ¼åé ç½® * @param {Array} param.data æ°æ®æº * @param {Array<string>} summaryProps éè¦æ±æ»çåæ®µåæ°ç» * @returns {Array} åè®¡è¡æ°æ® */ const summarizeTable = (param, summaryProps) => { const { columns, data } = param; const sums = []; columns.forEach((column, index) => { if (index === 0) { sums[index] = 'å计'; return; } const prop = column.property; if (summaryProps.includes(prop)) { const values = data.map(item => Number(item[prop])); // åªå¯¹æææ°åè¿è¡æ±å if (!values.every(isNaN)) { const sum = values.reduce((acc, val) => (!isNaN(val) ? acc + val : acc), 0); sums[index] = parseFloat(sum).toFixed(2); } else { sums[index] = ''; } } else { sums[index] = ''; } }); return sums; }; // 导åºå½æ°ä¾å ¶ä»æä»¶ä½¿ç¨ export { summarizeTable }; src/views/basicData/product/index.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,261 @@ <template> <div class="app-container product-view"> <div class="left"> <div> <el-input v-model="search" style="width: 240px" placeholder="è¾å ¥å ³é®åè¿è¡æç´¢" @change="searchFilter" @clear="searchFilter" clearable prefix-icon="Search" /> <el-button type="primary" @click="openProDia('add')" style="margin-left: 10px">æ°å¢äº§å</el-button> </div> <div> <el-tree ref="tree" v-loading="treeLoad" :data="list" :default-expanded-keys="expandedKeys" :draggable="true" :filter-node-method="filterNode" :props="{ children: 'children', label: 'label' }" highlight-current node-key="label" style="height: calc(100vh - 190px);overflow-y: scroll;scrollbar-width: none;"> <template #default="{ node, data }"> <div class="custom-tree-node"> <span>{{ node.label }}</span> <div> <el-button type="primary" link @click="openProDia('edit', data)"> ç¼è¾ </el-button> <!-- ä¿®æ¹æ¤å¤ --> <el-button v-if="!node.childNodes.length" style="margin-left: 4px" type="danger" link @click="remove(node, data)" > å é¤ </el-button> </div> </div> </template> </el-tree> </div> </div> <div class="right"> <div style="margin-bottom: 10px"> <el-button type="primary" @click="modelDia = true">æ°å¢è§æ ¼åå·</el-button> <el-button type="danger" @click="handleDelete" style="margin-left: 10px" plain>å é¤</el-button> </div> <PIMTable :column="tableColumn" :tableData="tableData" :page="page" :isSelection="true" :handleSelectionChange="handleSelectionChange" :tableLoading="tableLoading" @pagination="pagination" :total="total"></PIMTable> </div> <el-dialog :visible.sync="productDia" title="产å" width="400px"> <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef"> <el-row :gutter="30"> <el-col :span="24"> <el-form-item label="产ååç§°ï¼" prop="productName"> <el-input v-model="form.productName" placeholder="请è¾å ¥äº§ååç§°" clearable/> </el-form-item> </el-col> </el-row> </el-form> <template #footer> <div class="dialog-footer"> <el-button type="primary" @click="submitForm">确认</el-button> <el-button @click="closeProDia">åæ¶</el-button> </div> </template> </el-dialog> </div> </template> <script setup> import {ref} from "vue"; import {listCustomer} from "@/api/basicData/customerFile.js"; import {ElMessageBox} from "element-plus"; import {productTreeList} from "@/api/basicData/product.js"; const { proxy } = getCurrentInstance() const search = ref('') const treeLoad = ref(false) const list = ref([]) const expandedKeys = ref([]) const tableColumn = ref([ { label: 'è§æ ¼åå·', prop: 'model', }, { label: 'åä½', prop: 'model', }, { dataType: "action", label: "æä½", align: 'center', operation: [ { name: "ç¼è¾", type: "text", clickFun: (row) => { openForm('edit', row); }, }, ], }, ]) const tableData = ref([]) const tableLoading = ref(false) const total = ref(0) const selectedRows = ref([]) const page = reactive({ current: 1, size: 10, }) const productDia = ref(false) const modelDia = ref(false) const data = reactive({ form: { productName: '', }, rules: { productName: [{ required: true, message: "请è¾å ¥", trigger: "blur" }], } }) const { form, rules } = toRefs(data) const getProductTreeList = () => { treeLoad.value = true; productTreeList().then(res => { list.value = res list.value.forEach((a) => { expandedKeys.value.push(a.label); }); treeLoad.value = false; }).catch(err => { treeLoad.value = false; }) } const searchFilter = () => { proxy.$refs.tree.filter(search.value); } const openProDia = (type, data) => { productDia.value = true console.log('openEditDia', data) } const submitForm = () => { } const closeProDia = () => { proxy.$refs.formRef.resetFields(); productDia.value = false; } const remove = (value) => { } // è¡¨æ ¼éæ©æ°æ® const handleSelectionChange = (selection) => { selectedRows.value = selection } // å é¤ const handleDelete = () => { let ids = [] if (selectedRows.value.length > 0) { ids = selectedRows.value.map(item => item.id); } else { proxy.$modal.msgWarning('è¯·éæ©æ°æ®') return } ElMessageBox.confirm( 'éä¸çå 容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼', 'å é¤æç¤º', { confirmButtonText: '确认', cancelButtonText: 'åæ¶', type: 'warning', } ).then(() => { tableLoading.value = true delCustomer(ids).then(res => { proxy.$modal.msgSuccess("å 餿å") getList() }).finally(() => { tableLoading.value = false }) }).catch(() => { proxy.$modal.msg("已忶") }) } // æ¥è¯¢è§æ ¼åå· const pagination = ({ current, limit }) => { page.current = current; page.size = limit; getList() } const getList = () => { tableLoading.value = true listCustomer({...searchForm.value, ...page}).then(res => { tableLoading.value = false tableData.value = res.rows total.value = res.total }) } // è°ç¨treeè¿æ»¤æ¹æ³ 䏿è±è¿æ»¤ const filterNode = (value, data, node) => { if (!value) {ãããã//å¦ææ°æ®ä¸ºç©ºï¼åè¿åtrue,æ¾ç¤ºææçæ°æ®é¡¹ return true } // æ¥è¯¢å表æ¯å¦æå¹é æ°æ®ï¼å°å¼å°åï¼å¹é è±ææ°æ® let val = value.toLowerCase() return chooseNode(val, data, node) // è°ç¨è¿æ»¤äºå±æ¹æ³ } // è¿æ»¤ç¶èç¹ / åèç¹ (妿è¾å ¥çåæ°æ¯ç¶èç¹ä¸è½å¹é ï¼åè¿å该èç¹ä»¥åå ¶ä¸çææåèç¹ï¼å¦æåæ°æ¯åèç¹ï¼åè¿å该èç¹çç¶èç¹ãnameæ¯ä¸æå符ï¼enNameæ¯è±æå符. const chooseNode = (value, data, node) => { if (data.label.indexOf(value) !== -1) { return true } const level = node.level // å¦æä¼ å ¥çèç¹æ¬èº«å°±æ¯ä¸çº§èç¹å°±ä¸ç¨æ ¡éªäº if (level === 1) { return false } // å åå½åèç¹çç¶èç¹ let parentData = node.parent // éåå½åèç¹çç¶èç¹ let index = 0 while (index < level - 1) { // 妿å¹é å°ç´æ¥è¿åï¼æ¤å¤name弿¯ä¸æå符ï¼enNameæ¯è±æå符ã夿å¹é ä¸è±æè¿æ»¤ if (parentData.data.label.indexOf(value) !== -1) { return true } // å¦åçè¯åå¾ä¸ä¸å±åå¹é parentData = parentData.parent index++ } // 没å¹é å°è¿åfalse return false } getProductTreeList() </script> <style scoped> .product-view { display: flex; } .left { width: 380px; padding: 16px; background: #ffffff; } .right { width: calc(100% - 380px); padding: 16px; margin-left: 20px; background: #ffffff; } .custom-tree-node { flex: 1; display: flex; align-items: center; justify-content: space-between; font-size: 14px; padding-right: 8px; } </style> src/views/procurementManagement/invoiceEntry/index.vue
@@ -54,7 +54,6 @@ <el-table-column label="éè´ååå·" prop="purchaseContractNumber" show-overflow-tooltip/> <el-table-column label="éå®ååå·" prop="salesContractNo" show-overflow-tooltip/> <el-table-column label="ä¾åºååç§°" prop="supplierName" show-overflow-tooltip/> <el-table-column label="ä¸å¡å" prop="businessPerson" show-overflow-tooltip/> <el-table-column label="项ç®åç§°" prop="projectName" show-overflow-tooltip/> <el-table-column label="ååéé¢(å )" prop="contractAmount" show-overflow-tooltip/> <el-table-column fixed="right" label="æä½" min-width="60" align="center"> @@ -91,15 +90,6 @@ <el-col :span="12"> <el-form-item label="项ç®åç§°ï¼" prop="projectName"> <el-input v-model="form.projectName" placeholder="èªå¨å¡«å " clearable disabled/> </el-form-item> </el-col> </el-row> <el-row :gutter="30"> <el-col :span="12"> <el-form-item label="ä¸å¡åï¼" prop="businessPersonId"> <el-select v-model="form.businessPersonId" placeholder="èªå¨å¡«å " clearable disabled> <el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId"/> </el-select> </el-form-item> </el-col> </el-row> @@ -337,7 +327,6 @@ form.value.projectName = res.projectName productData.value = res.productData form.value.supplierName = res.supplierName form.value.businessPersonId = res.businessPersonId }) } // æäº¤è¡¨å src/views/procurementManagement/procurementLedger/index.vue
@@ -40,9 +40,9 @@ <el-table-column label="åä½" prop="unit" /> <el-table-column label="æ°é" prop="quantity" /> <el-table-column label="ç¨ç(%)" prop="taxRate" /> <el-table-column label="å«ç¨åä»·(å )" prop="taxInclusiveUnitPrice" /> <el-table-column label="å«ç¨æ»ä»·(å )" prop="taxInclusiveTotalPrice" /> <el-table-column label="ä¸å«ç¨æ»ä»·(å )" prop="taxExclusiveTotalPrice" /> <el-table-column label="å«ç¨åä»·(å )" prop="taxInclusiveUnitPrice" :formatter="formattedNumber" /> <el-table-column label="å«ç¨æ»ä»·(å )" prop="taxInclusiveTotalPrice" :formatter="formattedNumber" /> <el-table-column label="ä¸å«ç¨æ»ä»·(å )" prop="taxExclusiveTotalPrice" :formatter="formattedNumber" /> </el-table> </template> </el-table-column> @@ -50,9 +50,8 @@ <el-table-column label="éè´ååå·" prop="purchaseContractNumber" show-overflow-tooltip/> <el-table-column label="éå®ååå·" prop="salesContractNo" show-overflow-tooltip/> <el-table-column label="ä¾åºååç§°" prop="supplierName" show-overflow-tooltip/> <el-table-column label="ä¸å¡å" prop="businessPerson" show-overflow-tooltip/> <el-table-column label="项ç®åç§°" prop="projectName" show-overflow-tooltip/> <el-table-column label="ååéé¢(å )" prop="contractAmount" show-overflow-tooltip/> <el-table-column label="ååéé¢(å )" prop="contractAmount" show-overflow-tooltip :formatter="formattedNumber"/> <el-table-column label="å½å ¥äºº" prop="recorderName" show-overflow-tooltip/> <el-table-column label="å½å ¥æ¥æ" prop="entryDate" show-overflow-tooltip/> <el-table-column fixed="right" label="æä½" min-width="60" align="center"> @@ -96,20 +95,6 @@ </el-row> <el-row :gutter="30"> <el-col :span="12"> <el-form-item label="ä¸å¡åï¼" prop="businessPersonId"> <el-select v-model="form.businessPersonId" placeholder="è¯·éæ©" clearable @change="setPhone"> <el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId"/> </el-select> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="çµè¯ï¼" prop="phoneNumber"> <el-input v-model="form.phoneNumber" placeholder="请è¾å ¥" clearable/> </el-form-item> </el-col> </el-row> <el-row :gutter="30"> <el-col :span="12"> <el-form-item label="å½å ¥äººï¼" prop="recorderId"> <el-select v-model="form.recorderId" placeholder="è¯·éæ©" clearable disabled> <el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId"/> @@ -137,7 +122,7 @@ <el-button plain type="danger" @click="deleteProduct">å é¤</el-button> </el-form-item> </el-row> <el-table :data="productData" border @selection-change="productSelected"> <el-table :data="productData" border @selection-change="productSelected" show-summary :summary-method="summarizeProTable"> <el-table-column align="center" type="selection" width="55" /> <el-table-column align="center" label="åºå·" type="index" width="60" /> <el-table-column label="产å大类" prop="productCategory" /> @@ -145,12 +130,12 @@ <el-table-column label="åä½" prop="unit" /> <el-table-column label="æ°é" prop="quantity" /> <el-table-column label="ç¨ç(%)" prop="taxRate" /> <el-table-column label="å«ç¨åä»·(å )" prop="taxInclusiveUnitPrice" /> <el-table-column label="å«ç¨æ»ä»·(å )" prop="taxInclusiveTotalPrice" /> <el-table-column label="ä¸å«ç¨æ»ä»·(å )" prop="taxExclusiveTotalPrice" /> <el-table-column label="å«ç¨åä»·(å )" prop="taxInclusiveUnitPrice" :formatter="formattedNumber"/> <el-table-column label="å«ç¨æ»ä»·(å )" prop="taxInclusiveTotalPrice" :formatter="formattedNumber"/> <el-table-column label="ä¸å«ç¨æ»ä»·(å )" prop="taxExclusiveTotalPrice" :formatter="formattedNumber"/> <el-table-column fixed="right" label="æä½" min-width="60" align="center"> <template #default="scope"> <el-button link type="primary" size="small" @click="openProductForm('edit', scope.row);">ç¼è¾</el-button> <el-button link type="primary" size="small" @click="openProductForm('edit', scope.row, scope.$index);">ç¼è¾</el-button> </template> </el-table-column> </el-table> @@ -229,7 +214,7 @@ <el-row :gutter="30"> <el-col :span="12"> <el-form-item label="å«ç¨åä»·(å )ï¼" prop="taxInclusiveUnitPrice"> <el-input v-model="productForm.taxInclusiveUnitPrice" placeholder="请è¾å ¥" clearable/> <el-input-number v-model="productForm.taxInclusiveUnitPrice" :precision="2" :step="0.1" clearable style="width: 100%"/> </el-form-item> </el-col> <el-col :span="12"> @@ -245,12 +230,12 @@ <el-row :gutter="30"> <el-col :span="12"> <el-form-item label="å«ç¨æ»ä»·(å )ï¼" prop="taxInclusiveTotalPrice"> <el-input v-model="productForm.taxInclusiveTotalPrice" placeholder="请è¾å ¥" clearable/> <el-input-number v-model="productForm.taxInclusiveTotalPrice" :precision="2" :step="0.1" clearable style="width: 100%"/> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="ä¸å«ç¨æ»ä»·(å )ï¼" prop="taxExclusiveTotalPrice"> <el-input v-model="productForm.taxExclusiveTotalPrice" placeholder="请è¾å ¥" clearable/> <el-input-number v-model="productForm.taxExclusiveTotalPrice" :precision="2" :step="0.1" clearable style="width: 100%"/> </el-form-item> </el-col> </el-row> @@ -325,8 +310,6 @@ recorderId: '', entryDate: '', productData: [], businessPersonId: '', phoneNumber: '', supplierName: '', supplierId: '', }, @@ -334,8 +317,6 @@ purchaseContractNumber: [{ required: true, message: "请è¾å ¥", trigger: "blur" }], salesLedgerId: [{ required: true, message: "è¯·éæ©", trigger: "change" }], projectName: [{ required: true, message: "请è¾å ¥", trigger: "blur" }], businessPersonId: [{ required: true, message: "è¯·éæ©", trigger: "change" }], phoneNumber: [{ required: true, message: "请è¾å ¥", trigger: "blur" }], supplierId: [{ required: true, message: "请è¾å ¥", trigger: "blur" }], } }) @@ -343,6 +324,7 @@ // 产å表åå¼¹æ¡æ°æ® const productFormVisible = ref(false) const productOperationType = ref('') const productOperationIndex = ref('') const currentId = ref('') const productFormData = reactive({ productForm: { @@ -376,7 +358,9 @@ headers: { Authorization: "Bearer " + getToken() }, }) const formattedNumber = (row, column, cellValue) => { return parseFloat(cellValue).toFixed(2); }; // æ¥è¯¢å表 /** æç´¢æé®æä½ */ const handleQuery = () => { @@ -431,50 +415,12 @@ } // 主表åè®¡æ¹æ³ const summarizeMainTable = (param) => { const { columns, data } = param; const sums = []; columns.forEach((column, index) => { if (index === 0) { sums[index] = 'å计'; return; } const prop = column.property; if (['contractAmount'].includes(prop)) { const values = data.map(item => Number(item[prop])); if (!values.every(value => isNaN(value))) { sums[index] = values.reduce((acc, val) => (!isNaN(val) ? acc + val : acc), 0); } else { sums[index] = ''; } } else { sums[index] = ''; } }) return sums; return proxy.summarizeTable(param, ['contractAmount']); }; // å表åè®¡æ¹æ³ const summarizeChildrenTable = (param) => { const { columns, data } = param; const sums = []; columns.forEach((column, index) => { if (index === 0) { sums[index] = 'å计'; return; } const prop = column.property; if (['taxInclusiveUnitPrice', 'taxInclusiveTotalPrice', 'taxExclusiveTotalPrice'].includes(prop)) { const values = data.map(item => Number(item[prop])); if (!values.every(value => isNaN(value))) { sums[index] = values.reduce((acc, val) => (!isNaN(val) ? acc + val : acc), 0); } else { sums[index] = ''; } } else { sums[index] = ''; } }); return sums; } const summarizeProTable = (param) => { return proxy.summarizeTable(param, ['taxInclusiveUnitPrice', 'taxInclusiveTotalPrice', 'taxExclusiveTotalPrice']); }; // æå¼å¼¹æ¡ const openForm = (type, row) => { operationType.value = type @@ -505,10 +451,6 @@ }) } dialogFormVisible.value = true } // èµå¼çµè¯ const setPhone = (id) => { form.value.phoneNumber = userList.value.find(u => u.userId === id)?.phonenumber || ''; } // ä¸ä¼ åæ ¡æ£ function handleBeforeUpload(file) { @@ -577,8 +519,9 @@ dialogFormVisible.value = false } // æå¼äº§åå¼¹æ¡ const openProductForm = (type, row) => { const openProductForm = (type, row, index) => { productOperationType.value = type productOperationIndex.value = index productForm.value = {} proxy.resetForm("productFormRef") if (type === 'edit') { @@ -593,7 +536,11 @@ if (operationType.value === "edit") { submitProductEdit() } else { if (productOperationType.value === 'add') { productData.value.push({...productForm.value}) } else { productData.value[productOperationIndex.value] = {...productForm.value} } closeProductDia() } }