| src/api/procurementManagement/procurementLedger.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/api/salesManagement/salesLedger.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/collaborativeApproval/approvalProcess/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/collaborativeApproval/approvalProcess/index6.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/procurementManagement/invoiceEntry/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/procurementManagement/procurementLedger/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/salesManagement/invoiceRegistration/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/salesManagement/salesLedger/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/api/procurementManagement/procurementLedger.js
@@ -72,3 +72,12 @@ method: "get", }); } // æ ¹æ®éè´ååå·æ¥è¯¢è¯¦æ export function getPurchaseByCode(query) { return request({ url: "/purchase/ledger/getPurchaseByCode", method: "get", params: query, }); } src/api/salesManagement/salesLedger.js
@@ -116,4 +116,13 @@ method: "get", params: query, }); } // æ ¹æ®éå®ååå·æ¥è¯¢éå®è¯¦æ export function getSalesByCode(query) { return request({ url: "/sales/ledger/getSalesByCode", method: "get", params: query, }); } src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue
@@ -49,7 +49,7 @@ </el-form-item> </el-col> </el-row> <el-row> <el-row v-if="!isPurchaseApproval && !isSalesApproval"> <el-col :span="24"> <el-form-item label="审æ¹äºç±ï¼" prop="approveReason"> <el-input v-model="form.approveReason" placeholder="请è¾å ¥" clearable type="textarea" disabled/> @@ -90,6 +90,98 @@ </el-col> </el-row> </el-form> <div v-if="isPurchaseApproval" style="margin: 10px 0 18px;"> <el-divider content-position="left">éè´è¯¦æ </el-divider> <el-skeleton :loading="purchaseLoading" animated> <template #template> <el-skeleton-item variant="h3" style="width: 30%" /> <el-skeleton-item variant="text" style="width: 100%" /> <el-skeleton-item variant="text" style="width: 100%" /> </template> <template #default> <el-empty v-if="!purchaseDetail || !purchaseDetail.purchaseContractNumber" description="æªæ¥è¯¢å°å¯¹åºéè´è¯¦æ " /> <template v-else> <el-descriptions :column="2" border> <el-descriptions-item label="éè´ååå·">{{ purchaseDetail.purchaseContractNumber }}</el-descriptions-item> <el-descriptions-item label="ä¾åºååç§°">{{ purchaseDetail.supplierName }}</el-descriptions-item> <el-descriptions-item label="项ç®åç§°">{{ purchaseDetail.projectName }}</el-descriptions-item> <el-descriptions-item label="éå®ååå·">{{ purchaseDetail.salesContractNo }}</el-descriptions-item> <el-descriptions-item label="ç¾è®¢æ¥æ">{{ purchaseDetail.executionDate }}</el-descriptions-item> <el-descriptions-item label="å½å ¥æ¥æ">{{ purchaseDetail.entryDate }}</el-descriptions-item> <el-descriptions-item label="仿¬¾æ¹å¼">{{ purchaseDetail.paymentMethod }}</el-descriptions-item> <el-descriptions-item label="ååéé¢" :span="2"> <span style="font-size: 18px; color: #e6a23c; font-weight: bold;"> Â¥{{ Number(purchaseDetail.contractAmount ?? 0).toFixed(2) }} </span> </el-descriptions-item> </el-descriptions> <div style="margin-top: 20px;"> <h4>产åæç»</h4> <el-table :data="purchaseProducts" border style="width: 100%"> <el-table-column prop="productCategory" label="产ååç§°" /> <el-table-column prop="specificationModel" label="è§æ ¼åå·" /> <el-table-column prop="unit" label="åä½" /> <el-table-column prop="quantity" label="æ°é" /> <el-table-column prop="taxInclusiveUnitPrice" label="å«ç¨åä»·"> <template #default="scope">Â¥{{ Number(scope.row.taxInclusiveUnitPrice ?? 0).toFixed(2) }}</template> </el-table-column> <el-table-column prop="taxInclusiveTotalPrice" label="å«ç¨æ»ä»·"> <template #default="scope">Â¥{{ Number(scope.row.taxInclusiveTotalPrice ?? 0).toFixed(2) }}</template> </el-table-column> </el-table> </div> </template> </template> </el-skeleton> </div> <div v-if="isSalesApproval" style="margin: 10px 0 18px;"> <el-divider content-position="left">éå®è¯¦æ </el-divider> <el-skeleton :loading="salesLoading" animated> <template #template> <el-skeleton-item variant="h3" style="width: 30%" /> <el-skeleton-item variant="text" style="width: 100%" /> <el-skeleton-item variant="text" style="width: 100%" /> </template> <template #default> <el-empty v-if="!salesDetail || !salesDetail.salesContractNo" description="æªæ¥è¯¢å°å¯¹åºéå®è¯¦æ " /> <template v-else> <el-descriptions :column="2" border> <el-descriptions-item label="éå®ååå·">{{ salesDetail.salesContractNo }}</el-descriptions-item> <el-descriptions-item label="客æ·ååå·">{{ salesDetail.customerContractNo }}</el-descriptions-item> <el-descriptions-item label="客æ·åç§°">{{ salesDetail.customerName }}</el-descriptions-item> <el-descriptions-item label="ä¸å¡å">{{ salesDetail.salesman }}</el-descriptions-item> <el-descriptions-item label="项ç®åç§°">{{ salesDetail.projectName }}</el-descriptions-item> <el-descriptions-item label="仿¬¾æ¹å¼">{{ salesDetail.paymentMethod }}</el-descriptions-item> <el-descriptions-item label="å½å ¥äºº">{{ salesEntryPersonDisplay }}</el-descriptions-item> <el-descriptions-item label="å½å ¥æ¥æ">{{ salesDetail.entryDate }}</el-descriptions-item> <el-descriptions-item label="ç¾è®¢æ¥æ">{{ salesDetail.executionDate }}</el-descriptions-item> <el-descriptions-item label="ååéé¢" :span="2"> <span style="font-size: 18px; color: #e6a23c; font-weight: bold;"> Â¥{{ Number(salesDetail.contractAmount ?? 0).toFixed(2) }} </span> </el-descriptions-item> </el-descriptions> <div style="margin-top: 20px;"> <h4>产åæç»</h4> <el-table :data="salesProducts" border style="width: 100%"> <el-table-column prop="productCategory" label="产ååç§°" /> <el-table-column prop="specificationModel" label="è§æ ¼åå·" /> <el-table-column prop="unit" label="åä½" /> <el-table-column prop="quantity" label="æ°é" /> <el-table-column prop="taxInclusiveUnitPrice" label="å«ç¨åä»·"> <template #default="scope">Â¥{{ Number(scope.row.taxInclusiveUnitPrice ?? 0).toFixed(2) }}</template> </el-table-column> <el-table-column prop="taxInclusiveTotalPrice" label="å«ç¨æ»ä»·"> <template #default="scope">Â¥{{ Number(scope.row.taxInclusiveTotalPrice ?? 0).toFixed(2) }}</template> </el-table-column> </el-table> </div> </template> </template> </el-skeleton> </div> <el-form :model="{ activities }" ref="formRef" label-position="top"> <el-steps :active="getActiveStep()" finish-status="success" process-status="process" align-center direction="vertical"> <el-step @@ -163,13 +255,15 @@ </template> <script setup> import { getCurrentInstance, reactive, ref, toRefs } from "vue"; import { computed, getCurrentInstance, reactive, ref, toRefs } from "vue"; import vueEsign from "vue-esign"; import { approveProcessDetails, getDept, updateApproveNode } from "@/api/collaborativeApproval/approvalProcess.js"; import { getPurchaseByCode } from "@/api/procurementManagement/procurementLedger.js"; import { getSalesByCode } from "@/api/salesManagement/salesLedger.js"; import useUserStore from "@/store/modules/user.js"; import {userListNoPageByTenantId} from "@/api/system/user.js"; import { WarningFilled, Edit, Check, MoreFilled } from '@element-plus/icons-vue' @@ -184,6 +278,38 @@ const userStore = useUserStore() const productOptions = ref([]); const userList = ref([]) const purchaseLoading = ref(false) const currentPurchase = ref({}) const isPurchaseApproval = computed(() => Number(props.approveType) === 5) const salesLoading = ref(false) const currentSales = ref({}) const isSalesApproval = computed(() => Number(props.approveType) === 6) const purchaseDetail = computed(() => currentPurchase.value?.data || currentPurchase.value || {}) const purchaseProducts = computed(() => { const detail = purchaseDetail.value || {} return detail.productData || detail.products || detail.children || [] }) const salesDetail = computed(() => currentSales.value?.data || currentSales.value || {}) const salesProducts = computed(() => { const detail = salesDetail.value || {} return detail.productData || detail.products || detail.children || [] }) /** éå®è¯¦æ ï¼å½å ¥äººï¼æ¥å£å¯è½åªè¿ entryPerson ç¨æ·IDï¼éç¨ userList 忥æµç§°ï¼ */ const salesEntryPersonDisplay = computed(() => { const d = salesDetail.value || {} if (d.entryPersonName) return d.entryPersonName if (d.recorderName) return d.recorderName if (d.createByName) return d.createByName if (d.createUserName) return d.createUserName const id = d.entryPerson if (id != null && id !== "" && userList.value?.length) { const u = userList.value.find( (x) => x.userId == id || String(x.userId) === String(id) ) if (u) return u.nickName } return id != null && id !== "" ? String(id) : "-" }) const data = reactive({ form: { approveTime: "", @@ -242,11 +368,40 @@ const openDialog = (type, row) => { operationType.value = type; dialogFormVisible.value = true; currentPurchase.value = {} currentSales.value = {} userListNoPageByTenantId().then((res) => { userList.value = res.data; }); form.value = {...row} getProductOptions() if (isPurchaseApproval.value) { const purchaseContractNumber = row?.approveReason if (purchaseContractNumber) { purchaseLoading.value = true getPurchaseByCode({ purchaseContractNumber }).then((res) => { // å ¼å®¹å端è¿å {code,data} æç´æ¥è¿å详æ 对象两ç§ç»æ currentPurchase.value = res || {} }).catch(() => { proxy.$modal.msgError("æ¥è¯¢éè´è¯¦æ 失败") }).finally(() => { purchaseLoading.value = false }) } } if (isSalesApproval.value) { const salesContractNo = row?.approveReason if (salesContractNo) { salesLoading.value = true getSalesByCode({ salesContractNo }).then((res) => { currentSales.value = res || {} }).catch(() => { proxy.$modal.msgError("æ¥è¯¢éå®è¯¦æ 失败") }).finally(() => { salesLoading.value = false }) } } approveProcessDetails(row.approveId).then((res) => { activities.value = res.data // å¢å isApprovalåæ®µ @@ -353,6 +508,10 @@ const closeDia = () => { proxy.resetForm("formRef"); dialogFormVisible.value = false; purchaseLoading.value = false currentPurchase.value = {} salesLoading.value = false currentSales.value = {} emit('close') }; defineExpose({ src/views/collaborativeApproval/approvalProcess/index.vue
@@ -263,6 +263,7 @@ 3: "åºå·®ç®¡ç审æ¹è¡¨", 4: "æ¥é管ç审æ¹è¡¨", 5: "éè´ç³è¯·å®¡æ¹è¡¨", 6: "éå®è®¢å审æ¹è¡¨", } const fileName = nameMap[type] || nameMap[0] proxy.download(url, {}, `${fileName}.xlsx`) src/views/collaborativeApproval/approvalProcess/index6.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,22 @@ <template> <div class="container"> <!-- å¼å ¥index.vueç»ä»¶å¹¶ä¼ éåæ° --> <ApprovalProcessIndex :approveType="6" /> </div> </template> <script setup> import ApprovalProcessIndex from "./index.vue"; // å®ä¹ç»ä»¶åç§° defineOptions({ name: "ApprovalProcessIndex1", }); </script> <style scoped> .container { width: 100%; height: 100%; } </style> src/views/procurementManagement/invoiceEntry/index.vue
@@ -120,6 +120,7 @@ gePurchaseListPage, { purchaseContractNumber: undefined, approvalStatus: 2 }, [ { src/views/procurementManagement/procurementLedger/index.vue
@@ -118,6 +118,31 @@ width="420" show-overflow-tooltip /> <el-table-column label="审æ¹ç¶æ" width="140"> <template #default="scope"> <el-tag v-if="(scope.row.approveStatus ?? scope.row.approvalStatus ?? scope.row.auditStatus) == 0" type="warning" >å¾ å®¡æ ¸</el-tag> <el-tag v-else-if="(scope.row.approveStatus ?? scope.row.approvalStatus ?? scope.row.auditStatus) == 1" type="primary" >å®¡æ ¸ä¸</el-tag> <el-tag v-else-if="(scope.row.approveStatus ?? scope.row.approvalStatus ?? scope.row.auditStatus) == 2" type="success" >å®¡æ ¸å®æ</el-tag> <el-tag v-else-if="(scope.row.approveStatus ?? scope.row.approvalStatus ?? scope.row.auditStatus) == 3" type="danger" >å®¡æ ¸æªéè¿</el-tag> <el-tag v-else-if="(scope.row.approveStatus ?? scope.row.approvalStatus ?? scope.row.auditStatus) == 4" type="info" >已鿰æäº¤</el-tag> <el-tag v-else type="info">-</el-tag> </template> </el-table-column> <el-table-column label="仿¬¾æ¹å¼" width="100" @@ -298,6 +323,48 @@ placeholder="è¯·éæ©" clearable /> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="24"> <el-form-item> <template #label> <span>审æ¹äººéæ©ï¼</span> <el-button type="primary" @click="addApproverNode" style="margin-left: 8px;">æ°å¢èç¹</el-button> </template> <div style="display: flex; align-items: flex-end; flex-wrap: wrap;"> <div v-for="(node, index) in approverNodes" :key="node.id" style="margin-right: 30px; text-align: center; margin-bottom: 10px;" > <div> <span>审æ¹äºº</span> â </div> <el-select v-model="node.userId" placeholder="éæ©äººå" style="width: 140px; margin-bottom: 8px;" > <el-option v-for="user in userList" :key="user.userId" :label="user.nickName" :value="user.userId" /> </el-select> <div> <el-button type="danger" size="small" @click="removeApproverNode(index)" v-if="approverNodes.length > 1" >å é¤</el-button> </div> </div> </div> </el-form-item> </el-col> </el-row> @@ -832,6 +899,8 @@ }); const total = ref(0); const fileList = ref([]); const approverNodes = ref([{ id: 1, userId: null }]); let nextApproverId = 2; import useUserStore from "@/store/modules/user"; import { modelList, productTreeList } from "@/api/basicData/product.js"; import dayjs from "dayjs"; @@ -879,6 +948,13 @@ }); const { form, rules } = toRefs(data); const { form: searchForm } = useFormData(data.searchForm); const addApproverNode = () => { approverNodes.value.push({ id: nextApproverId++, userId: null }); }; const removeApproverNode = (index) => { approverNodes.value.splice(index, 1); }; // 产å表åå¼¹æ¡æ°æ® const productFormVisible = ref(false); @@ -1033,6 +1109,8 @@ form.value = {}; productData.value = []; fileList.value = []; approverNodes.value = [{ id: 1, userId: null }]; nextApproverId = 2; if (operationType.value == "add") { createPurchaseNo().then((res) => { form.value.purchaseContractNumber = res.data; @@ -1054,6 +1132,17 @@ getPurchaseById({ id: row.id, type: 2 }).then((res) => { form.value = { ...res }; productData.value = form.value.productData; const approveUserIds = form.value.approveUserIds || form.value.approverIds; if (approveUserIds) { const ids = String(approveUserIds) .split(",") .map((id) => Number(id.trim())) .filter((id) => !Number.isNaN(id)); if (ids.length > 0) { approverNodes.value = ids.map((id, idx) => ({ id: idx + 1, userId: id })); nextApproverId = ids.length + 1; } } if (form.value.salesLedgerFiles) { fileList.value = form.value.salesLedgerFiles; } else { @@ -1108,6 +1197,12 @@ const submitForm = () => { proxy.$refs["formRef"].validate((valid) => { if (valid) { const hasEmptyApprover = approverNodes.value.some((node) => !node.userId); if (hasEmptyApprover) { proxy.$modal.msgWarning("请为ææå®¡æ¹èç¹éæ©å®¡æ¹äºº"); return; } form.value.approveUserIds = approverNodes.value.map((node) => node.userId).join(","); if (productData.value.length > 0) { form.value.productData = proxy.HaveJson(productData.value); } else { src/views/salesManagement/invoiceRegistration/index.vue
@@ -437,6 +437,7 @@ searchForm: { customerName: "", status: false, approvalStatus: 2, customerContractNo: undefined, // 客æ·ååå· projectName: undefined, // 项ç®åç§° createUer: undefined, // ç»è®°äºº src/views/salesManagement/salesLedger/index.vue
@@ -70,6 +70,40 @@ <el-table-column label="客æ·åç§°" prop="customerName" width="300" show-overflow-tooltip /> <el-table-column label="ä¸å¡å" prop="salesman" width="100" show-overflow-tooltip /> <el-table-column label="项ç®åç§°" prop="projectName" width="180" show-overflow-tooltip /> <el-table-column label="å®¡æ ¸ç¶æ" width="140"> <template #default="scope"> <el-tag v-if="(scope.row.approveStatus ?? scope.row.approvalStatus) == 0" type="warning" >å¾ å®¡æ ¸</el-tag> <el-tag v-else-if="(scope.row.approveStatus ?? scope.row.approvalStatus) == 1" type="primary" >å®¡æ ¸ä¸</el-tag> <el-tag v-else-if="(scope.row.approveStatus ?? scope.row.approvalStatus) == 2" type="success" >å®¡æ ¸å®æ</el-tag> <el-tag v-else-if="(scope.row.approveStatus ?? scope.row.approvalStatus) == 3" type="danger" >å®¡æ ¸æªéè¿</el-tag> <el-tag v-else-if="(scope.row.approveStatus ?? scope.row.approvalStatus) == 4" type="info" >已鿰æäº¤</el-tag> <el-tag v-else type="info">-</el-tag> </template> </el-table-column> <el-table-column label="éå®ç±»å" width="120"> <template #default="scope"> <el-tag :type="scope.row.salesType === 'ç´§æ¥' ? 'danger' : 'info'" >{{ scope.row.salesType || '-' }}</el-tag> </template> </el-table-column> <el-table-column label="仿¬¾æ¹å¼" prop="paymentMethod" show-overflow-tooltip /> <el-table-column label="ååéé¢(å )" prop="contractAmount" width="220" show-overflow-tooltip :formatter="formattedNumber" /> @@ -156,6 +190,62 @@ <el-col :span="12"> <el-form-item label="仿¬¾æ¹å¼"> <el-input v-model="form.paymentMethod" placeholder="请è¾å ¥" clearable :disabled="operationType === 'view'" /> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="éå®ç±»åï¼" prop="salesType"> <el-select v-model="form.salesType" placeholder="è¯·éæ©" clearable :disabled="operationType === 'view'" style="width: 100%" > <el-option label="æ®é" value="æ®é" /> <el-option label="ç´§æ¥" value="ç´§æ¥" /> </el-select> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="24"> <el-form-item v-if="operationType !== 'view'"> <template #label> <span>审æ¹äººéæ©ï¼</span> <el-button type="primary" @click="addApproverNode" style="margin-left: 8px;">æ°å¢èç¹</el-button> </template> <div style="display: flex; align-items: flex-end; flex-wrap: wrap;"> <div v-for="(node, index) in approverNodes" :key="node.id" style="margin-right: 30px; text-align: center; margin-bottom: 10px;" > <div> <span>审æ¹äºº</span> â </div> <el-select v-model="node.userId" placeholder="éæ©äººå" style="width: 140px; margin-bottom: 8px;" > <el-option v-for="user in userList" :key="user.userId" :label="user.nickName" :value="user.userId" /> </el-select> <div> <el-button type="danger" size="small" @click="removeApproverNode(index)" v-if="approverNodes.length > 1" >å é¤</el-button> </div> </div> </div> </el-form-item> </el-col> </el-row> @@ -505,6 +595,8 @@ }); const total = ref(0); const fileList = ref([]); const approverNodes = ref([{ id: 1, userId: null }]); let nextApproverId = 2; // ç¨æ·ä¿¡æ¯è¡¨åå¼¹æ¡æ°æ® const operationType = ref(""); @@ -531,8 +623,10 @@ productData: [], executionDate: "", paymentMethod: "", salesType: "æ®é", }, rules: { salesType: [{ required: true, message: "è¯·éæ©éå®ç±»å", trigger: "change" }], salesman: [{ required: true, message: "è¯·éæ©", trigger: "change" }], customerContractNo: [ { required: true, message: "请è¾å ¥", trigger: "blur" }, @@ -546,6 +640,12 @@ }); const { form, rules } = toRefs(data); const { form: searchForm } = useFormData(data.searchForm); const addApproverNode = () => { approverNodes.value.push({ id: nextApproverId++, userId: null }); }; const removeApproverNode = (index) => { approverNodes.value.splice(index, 1); }; // 产å表åå¼¹æ¡æ°æ® const productFormVisible = ref(false); const productOperationType = ref(""); @@ -759,6 +859,8 @@ operationType.value = type; form.value = {}; productData.value = []; approverNodes.value = [{ id: 1, userId: null }]; nextApproverId = 2; let userLists = await userListNoPage(); userList.value = userLists.data; customerList().then((res) => { @@ -770,8 +872,22 @@ getSalesLedgerWithProducts({ id: row.id, type: 1 }).then((res) => { form.value = { ...res }; form.value.entryPerson = Number(res.entryPerson); if (!form.value.salesType) { form.value.salesType = "æ®é"; } productData.value = form.value.productData; fileList.value = form.value.salesLedgerFiles; const approveUserIds = form.value.approveUserIds || form.value.approverIds; if (approveUserIds) { const ids = String(approveUserIds) .split(",") .map((id) => Number(id.trim())) .filter((id) => !Number.isNaN(id)); if (ids.length > 0) { approverNodes.value = ids.map((id, idx) => ({ id: idx + 1, userId: id })); nextApproverId = ids.length + 1; } } }); } // let userAll = await userStore.getInfo() @@ -781,6 +897,9 @@ // } // }); form.value.entryDate = getCurrentDate(); // 设置é»è®¤å½å ¥æ¥æä¸ºå½åæ¥æ if (type === "add") { form.value.salesType = "æ®é"; } dialogFormVisible.value = true; }; function changs(val) { @@ -826,6 +945,14 @@ const submitForm = () => { proxy.$refs["formRef"].validate((valid) => { if (valid) { if (operationType.value !== "view") { const hasEmptyApprover = approverNodes.value.some((node) => !node.userId); if (hasEmptyApprover) { proxy.$modal.msgWarning("请为ææå®¡æ¹èç¹éæ©å®¡æ¹äºº"); return; } form.value.approveUserIds = approverNodes.value.map((node) => node.userId).join(","); } console.log('productData.value--', productData.value) if (productData.value !== null && productData.value.length > 0) { form.value.productData = proxy.HaveJson(productData.value);