Merge branch 'dev_NEW_pro' of http://114.132.189.42:9002/r/product-inventory-management into dev_NEW_pro
已复制1个文件
已添加9个文件
已重命名1个文件
已修改48个文件
| | |
| | | "VITE_BASE_API": "http://1.15.17.182:9048", |
| | | "VITE_JAVA_API": "http://1.15.17.182:9049" |
| | | }, |
| | | "logo": "logo/Logo.png", |
| | | "logo": "logo/XDRJ.png", |
| | | "favicon": "favicon/favicon.ico" |
| | | }, |
| | | "BTYX": { |
| | |
| | | "logo": "logo/QXYLogo.png", |
| | | "favicon": "favicon/QXYfavicon.ico" |
| | | }, |
| | | "HQJC": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "å强建æç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://36.134.77.64:9001", |
| | | "VITE_JAVA_API": "http://36.134.77.64:9000" |
| | | }, |
| | | "logo": "logo/HQJCLogo.png", |
| | | "favicon": "favicon/HQJCfavicon.ico" |
| | | }, |
| | | "XCDQ": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "ææ¨çµå¨ç®¡çç³»ç»", |
| | |
| | | }, |
| | | "logo": "logo/XCDQLogo.png", |
| | | "favicon": "favicon/XCDQfavicon.ico" |
| | | }, |
| | | "BWSM": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "å
«ç»´å贸管çç³»ç»", |
| | | "VITE_BASE_API": "http://1.15.17.182:9070", |
| | | "VITE_JAVA_API": "http://1.15.17.182:9069" |
| | | }, |
| | | "logo": "logo/BWSMLogo.png", |
| | | "favicon": "favicon/BWSMfavicon.ico" |
| | | }, |
| | | "CKGM": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "宸康工贸管çç³»ç»", |
| | | "VITE_BASE_API": "http://1.15.17.182:9072", |
| | | "VITE_JAVA_API": "http://1.15.17.182:9071" |
| | | }, |
| | | "logo": "logo/CKGMLogo.png", |
| | | "favicon": "favicon/CKGMfavicon.ico" |
| | | }, |
| | | "RFSY": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "ç丰çä¸ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://1.15.17.182:9076", |
| | | "VITE_JAVA_API": "http://1.15.17.182:9075" |
| | | }, |
| | | "logo": "logo/RFSYLogo.png", |
| | | "favicon": "favicon/RFSYfavicon.ico" |
| | | }, |
| | | "ZQSY": { |
| | | "env": { |
| | |
| | | "logo": "logo/KYHGLogo.png", |
| | | "favicon": "favicon/KYHGfavicon.ico" |
| | | }, |
| | | "JXSM": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "è¥å£å¿æ´é«åè´¸æéå
¬å¸", |
| | | "VITE_BASE_API": "http://36.134.76.148:9001", |
| | | "VITE_JAVA_API": "http://36.134.76.148:9002" |
| | | }, |
| | | "logo": "logo/JXSMLogo.png", |
| | | "favicon": "favicon/JXSMico.ico" |
| | | }, |
| | | "logo": "/src/assets/logo/logo.png", |
| | | "favicon": "/public/favicon.ico" |
| | | } |
| | |
| | | }); |
| | | } |
| | | |
| | | export function createPurchaseNo() { |
| | | export function createPurchaseNo(entryDate) { |
| | | return request({ |
| | | url: "/purchase/ledger/createPurchaseNo", |
| | | method: "get", |
| | | params: { entryDate }, |
| | | }); |
| | | } |
| | | export function updateApprovalStatus(query) { |
| | | return request({ |
| | | url: "/purchase/ledger/updateApprovalStatus", |
| | | method: "post", |
| | | data: query, |
| | | }); |
| | | return request({ |
| | | url: "/purchase/ledger/updateApprovalStatus", |
| | | method: "post", |
| | | data: query, |
| | | }); |
| | | } |
| | | |
| | | // ä¿åéè´æ¨¡æ¿ |
| | | export function addPurchaseTemplate(data) { |
| | | return request({ |
| | | url: "/purchaseLedgerTemplate/add", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | return request({ |
| | | url: "/purchaseLedgerTemplate/add", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | // ä¿®æ¹éè´æ¨¡æ¿ |
| | | export function updatePurchaseTemplate(data) { |
| | | return request({ |
| | | url: "/purchaseLedgerTemplate/update", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | return request({ |
| | | url: "/purchaseLedgerTemplate/update", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | // æ¥è¯¢éè´æ¨¡æ¿ |
| | | export function getPurchaseTemplateList(query) { |
| | | return request({ |
| | | url: "/purchase/ledger/getPurchaseTemplateList", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | return request({ |
| | | url: "/purchase/ledger/getPurchaseTemplateList", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | // å é¤éè´æ¨¡æ¿ |
| | | export function delPurchaseTemplate(id) { |
| | | return request({ |
| | | url: "/purchaseLedgerTemplate/delete", |
| | | method: "delete", |
| | | data: id, |
| | | }); |
| | | return request({ |
| | | url: "/purchaseLedgerTemplate/delete", |
| | | method: "delete", |
| | | data: id, |
| | | }); |
| | | } |
| | | // æ¥è¯¢éè´è¯¦æ
|
| | | export function getPurchaseByCode(id) { |
| | | return request({ |
| | | url: "/purchase/ledger/getPurchaseByCode", |
| | | method: "get", |
| | | params: id, |
| | | }); |
| | | } |
| | | return request({ |
| | | url: "/purchase/ledger/getPurchaseByCode", |
| | | method: "get", |
| | | params: id, |
| | | }); |
| | | } |
| | | |
| | | export function batchGeneratePurchaseInboundSteps(query) { |
| | | return request({ |
| | | url: "/purchase/ledger/batchInsertPurchaseSteps", |
| | | method: "post", |
| | | data: query, |
| | | }); |
| | | } |
| | |
| | | & .nest-menu .el-sub-menu > .el-sub-menu__title, |
| | | & .el-sub-menu .el-menu-item { |
| | | min-width: 0 !important; |
| | | width: calc(100% - 24px) !important; |
| | | margin: 0 12px 8px !important; |
| | | height: 46px; |
| | | line-height: 46px; |
| | | padding-left: 14px !important; |
| | | padding-right: 14px !important; |
| | | border-radius: 12px; |
| | | width: calc(100% - 32px) !important; |
| | | margin: 0 16px 6px !important; |
| | | height: 40px; |
| | | line-height: 40px; |
| | | padding-left: 12px !important; |
| | | padding-right: 12px !important; |
| | | border-radius: 8px; |
| | | transition: all 0.24s ease; |
| | | color: var(--sidebar-text); |
| | | border: 1px solid rgba(255, 255, 255, 0.06) !important; |
| | | background: linear-gradient(128deg, rgba(255, 255, 255, 0.04), rgba(255, 255, 255, 0.01)); |
| | | border: none !important; |
| | | background: transparent; |
| | | font-size: 13px; |
| | | |
| | | &:hover { |
| | | background: linear-gradient(128deg, rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.24), rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.07)) !important; |
| | | border-color: rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.3) !important; |
| | | transform: translateX(2px); |
| | | background: rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.12) !important; |
| | | transform: translateX(4px); |
| | | } |
| | | |
| | | &.is-active { |
| | | background: var(--menu-active-bg, linear-gradient(135deg, var(--el-color-primary), var(--el-color-primary-light-3))) !important; |
| | | background-size: 180% 180%; |
| | | background: rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.85) !important; |
| | | color: #fff !important; |
| | | font-weight: 500; |
| | | box-shadow: var(--menu-active-glow, 0 10px 24px rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.34)); |
| | | animation: sidebarActiveFlow 4.6s ease infinite; |
| | | box-shadow: 0 4px 12px rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.25); |
| | | } |
| | | } |
| | | |
| | | // åèå容卿 ·å¼ - å¢å 缩è¿åè§è§å±æ¬¡ |
| | | & .el-sub-menu .el-menu { |
| | | padding: 4px 0 8px; |
| | | margin-left: 8px; |
| | | border-left: 2px solid rgba(255, 255, 255, 0.08); |
| | | } |
| | | } |
| | | |
| | | .hideSidebar { |
| | |
| | | allowFileUpload: false, |
| | | emptySessionText: 'ææ è´¢å¡ä¼è¯', |
| | | quickPrompts: [ |
| | | 'æ¥çç»è¥é©¾é©¶è±', |
| | | 'æ¥çæ¬æç»è¥é©¾é©¶è±', |
| | | 'çææ¬å¨ç»è¥å¨æ¥ï¼å©æ¶¦ä¸ç°éæµï¼', |
| | | 'åææ¬æå©æ¶¦ä¸éåå ', |
| | | 'è¿30天åªä¸ªå®¢æ·å©æ¶¦è´¡ç®æé«', |
| | | 'æ¥çæ¬æç»è¥é©¾é©¶è±', |
| | | 'æ¥è¯¢è¿30å¤©äºæè®¢å', |
| | | 'è¿30天åªä¸ªå®¢æ·å©æ¶¦è´¡ç®æé«', |
| | | 'åæè¿30天åºåèµéå ç¨', |
| | | '颿µæªæ¥3个æç°éæµ', |
| | | 'æ¥è¯¢åºæ¶å款é£é©', |
| | | 'åªä¸ªå·¥åºææ¬æé«' |
| | | ] |
| | | } |
| | |
| | | allowFileUpload: false, |
| | | emptySessionText: 'ææ ç产ä¼è¯', |
| | | quickPrompts: [ |
| | | 'æ¥è¯¢æ¬æç产计å', |
| | | 'æ¥çæè¿10æ¡å·¥å', |
| | | 'æ¥è®¾å¤A-01çç»´ä¿®æ
åµ', |
| | | 'æ¥è´¨éä¸åæ ¼è®°å½', |
| | | 'æ¥ä½åºåç©æ', |
| | | 'æ¥è¿7天å¼å¸¸å¤ç', |
| | | 'çæå¶é é¢è¦çæ¿', |
| | | 'åææ¬æçäº§å®æçåå¼å¸¸ç', |
| | | 'ç»åºå·¥å龿å设å¤å¾
ä¿®çåç建议' |
| | | 'æ¥è¯¢ç产ç°åºæ°æ®', |
| | | 'æ¥è¯¢çäº§è®¡åæ§è¡æ
åµ', |
| | | 'æ¥è¯¢å·¥åæ§è¡æ
åµ', |
| | | 'æ¥è¯¢è®¾å¤è¿è¡æ
åµ', |
| | | 'æ¥è¯¢è´¨éå¼å¸¸æ°æ®', |
| | | 'æ¥è¯¢ç©æç¸å
³æ°æ®', |
| | | 'æ¥çå¶é é¢è¦çæ¿', |
| | | 'åææ¬æå¶é ç»è¥æ
åµ', |
| | | 'åæè¿7天ç产å¼å¸¸', |
| | | 'çæå¶é åç建议' |
| | | ] |
| | | } |
| | |
| | | fileAnalyzeUrl: '/purchase-ai/analyze-files', |
| | | emptySessionText: 'ææ éè´ä¼è¯', |
| | | quickPrompts: [ |
| | | 'æ¬æéè´é颿åååçç©ææåªäºï¼', |
| | | 'åªäºéè´è®¢åè¿æªå
¥åºï¼', |
| | | 'æè¿7天ä¾åºåå°è´§å¼å¸¸æåªäºï¼', |
| | | '帮æç»è®¡å¾
仿¬¾éè´åï¼', |
| | | 'ååºæ¬æéè´éè´§æ
åµ' |
| | | 'æ¥è¯¢éè´å°è´¦å表', |
| | | 'æ¥è¯¢æè¿10æ¡éè´å°è´¦', |
| | | 'ç»è®¡æ¬æéè´æ°æ®', |
| | | 'æ¥è¯¢æ¬æéè´ç©æé颿è¡', |
| | | 'æ¥è¯¢æªå
¥åºéè´è®¢å', |
| | | 'æ¥è¯¢éè´å°è´§å¼å¸¸', |
| | | 'æ¥è¯¢å¾
仿¬¾éè´å', |
| | | 'æ¥è¯¢æ¬æéè´éè´§æ
åµ', |
| | | 'æ¥è¯¢æä¸ªéè´å°è´¦è¯¦æ
', |
| | | 'åæä¾åºåéè´é颿å' |
| | | ] |
| | | } |
| | |
| | | </script>
|
| | |
|
| | | <style lang="scss" scoped>
|
| | | .sidebar-item-wrapper { |
| | | :deep(.menu-icon) { |
| | | width: 26px; |
| | | height: 26px; |
| | | margin-right: 12px; |
| | | display: inline-flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | flex-shrink: 0; |
| | | transition: color 0.2s ease; |
| | | color: var(--sidebar-text); |
| | | opacity: 0.88; |
| | | } |
| | | |
| | | :deep(.el-menu-item:hover .menu-icon), |
| | | :deep(.el-sub-menu__title:hover .menu-icon) { |
| | | color: #ffffff; |
| | | opacity: 1; |
| | | } |
| | | .sidebar-item-wrapper {
|
| | | :deep(.menu-icon) {
|
| | | width: 26px;
|
| | | height: 26px;
|
| | | margin-right: 12px;
|
| | | display: inline-flex;
|
| | | align-items: center;
|
| | | justify-content: center;
|
| | | flex-shrink: 0;
|
| | | transition: color 0.2s ease;
|
| | | color: var(--sidebar-text);
|
| | | opacity: 0.88;
|
| | | }
|
| | | |
| | | :deep(.el-menu-item:hover .menu-icon),
|
| | | :deep(.el-sub-menu__title:hover .menu-icon) {
|
| | | color: #ffffff;
|
| | | opacity: 1;
|
| | | }
|
| | |
|
| | | :deep(.el-menu-item.is-active .menu-icon) {
|
| | | color: var(--menu-active-text) !important;
|
| | | opacity: 1;
|
| | | }
|
| | |
|
| | | :deep(.menu-title) { |
| | | font-weight: 500; |
| | | transition: color 0.2s ease; |
| | | color: var(--sidebar-text); |
| | | opacity: 0.82; |
| | | } |
| | | |
| | | :deep(.el-menu-item:hover .menu-title), |
| | | :deep(.el-sub-menu__title:hover .menu-title) { |
| | | color: #ffffff; |
| | | opacity: 1; |
| | | } |
| | | |
| | | :deep(.el-menu-item.is-active .menu-title) { |
| | | color: var(--menu-active-text) !important; |
| | | opacity: 1; |
| | | } |
| | | |
| | | :deep(.nest-menu) { |
| | | .menu-icon { |
| | | width: 22px; |
| | | height: 22px; |
| | | margin-right: 10px; |
| | | } |
| | | |
| | | .menu-title { font-size: 13px; } |
| | | } |
| | | } |
| | | :deep(.menu-title) {
|
| | | font-weight: 500;
|
| | | transition: color 0.2s ease;
|
| | | color: var(--sidebar-text);
|
| | | opacity: 0.82;
|
| | | }
|
| | | |
| | | :deep(.el-menu-item:hover .menu-title),
|
| | | :deep(.el-sub-menu__title:hover .menu-title) {
|
| | | color: #ffffff;
|
| | | opacity: 1;
|
| | | }
|
| | | |
| | | :deep(.el-menu-item.is-active .menu-title) {
|
| | | color: var(--menu-active-text) !important;
|
| | | opacity: 1;
|
| | | }
|
| | | |
| | | :deep(.nest-menu) {
|
| | | .menu-icon {
|
| | | width: 18px;
|
| | | height: 18px;
|
| | | margin-right: 8px;
|
| | | opacity: 0.7;
|
| | | }
|
| | | |
| | | .menu-title { |
| | | font-size: 13px;
|
| | | opacity: 0.85;
|
| | | }
|
| | | |
| | | .el-menu-item.is-active {
|
| | | .menu-icon {
|
| | | opacity: 1;
|
| | | }
|
| | | .menu-title {
|
| | | opacity: 1;
|
| | | }
|
| | | }
|
| | | }
|
| | | }
|
| | | </style>
|
| | |
| | | class="main-container main-layout"> |
| | | <div :class="{ 'fixed-header': fixedHeader, 'with-tags': showTagsView }"> |
| | | <navbar @setLayout="setLayout" /> |
| | | <tags-view v-if="showTagsView" /> |
| | | <tags-view /> |
| | | </div> |
| | | <app-main /> |
| | | <settings ref="settingRef" /> |
| | |
| | | const sidebar = computed(() => useAppStore().sidebar); |
| | | const device = computed(() => useAppStore().device); |
| | | const needTagsView = computed(() => settingsStore.tagsView); |
| | | const showTagsView = computed(() => needTagsView.value && tagsViewStore.visitedViews.length > 1); |
| | | const showTagsView = computed( |
| | | () => needTagsView.value && tagsViewStore.visitedViews.length > 1 |
| | | ); |
| | | const fixedHeader = computed(() => settingsStore.fixedHeader); |
| | | const aiEnabled = computed(() => Number(userStore.aiEnabled) === 1); |
| | | const showGlobalAiChat = computed(() => { |
| | | const isIndustrialBrainRoute = String(route.path || "").startsWith("/ai-industrial-brain"); |
| | | const isIndustrialBrainRoute = String(route.path || "").startsWith( |
| | | "/ai-industrial-brain" |
| | | ); |
| | | return !isIndustrialBrainRoute && aiEnabled.value; |
| | | }); |
| | | |
| | |
| | | position: relative; |
| | | min-height: 100%; |
| | | width: 100%; |
| | | background: |
| | | radial-gradient(circle at 14% -8%, rgba(59, 130, 246, 0.14), transparent 36%), |
| | | radial-gradient(circle at 88% -12%, rgba(56, 189, 248, 0.1), transparent 30%), |
| | | background: radial-gradient( |
| | | circle at 14% -8%, |
| | | rgba(59, 130, 246, 0.14), |
| | | transparent 36% |
| | | ), |
| | | radial-gradient( |
| | | circle at 88% -12%, |
| | | rgba(56, 189, 248, 0.1), |
| | | transparent 30% |
| | | ), |
| | | linear-gradient(165deg, #f3f7fc 0%, #eef5ff 56%, #f8fbff 100%); |
| | | |
| | | &.mobile.openSidebar { |
| | |
| | | prop="paramCode"> |
| | | <el-input v-model="formData.paramCode" |
| | | disabled |
| | | placeholder="èªå¨çæ" /> |
| | | placeholder="ä¿ååèªå¨çæ" /> |
| | | </el-form-item> |
| | | <el-form-item label="åæ°åç§°" |
| | | prop="paramName"> |
| | |
| | | value="2" /> |
| | | </el-select> |
| | | </el-form-item> --> |
| | | <el-form-item label="å建æ¶é´" |
| | | prop="createTime"> |
| | | <el-date-picker v-model="formCreateTimeDate" |
| | | type="date" |
| | | placeholder="éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | <el-form-item label="åä½" |
| | | prop="unit"> |
| | | <el-input v-model="formData.unit" |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { onMounted, ref, reactive } from "vue"; |
| | | import { onMounted, ref, reactive, computed } from "vue"; |
| | | import dayjs from "dayjs"; |
| | | import { |
| | | parameterListPage, |
| | | addParameter, |
| | |
| | | remark: "", |
| | | isRequired: 0, |
| | | paramFormat: "", |
| | | createTime: "", |
| | | }); |
| | | const rules = reactive({ |
| | | paramName: [{ required: true, message: "请è¾å
¥åæ°åç§°", trigger: "blur" }], |
| | |
| | | }, |
| | | }, |
| | | ], |
| | | }); |
| | | const formCreateTimeDate = computed({ |
| | | get: () => (formData.createTime ? String(formData.createTime).split(" ")[0] : ""), |
| | | set: (value) => { |
| | | formData.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : ""; |
| | | }, |
| | | }); |
| | | // const productTypes = ref([]); |
| | | const isEdit = ref(false); |
| | |
| | | formData.unit = ""; |
| | | formData.remark = ""; |
| | | formData.isRequired = 0; |
| | | formData.createTime = dayjs().format("YYYY-MM-DD HH:mm:ss"); |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | |
| | | formData.remark = row.remark || ""; |
| | | formData.paramFormat = row.paramFormat || ""; |
| | | formData.isRequired = row.isRequired || 0; |
| | | formData.createTime = row.createTime || ""; |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | |
| | | }, |
| | | rules: { |
| | | purchaseContractNumber: [ |
| | | { required: true, message: "请è¾å
¥", trigger: "blur" }, |
| | | { required: false, message: "请è¾å
¥", trigger: "blur" }, |
| | | ], |
| | | projectName: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | supplierId: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | |
| | | productData.value = []; |
| | | fileList.value = []; |
| | | if (operationType.value == "add") { |
| | | createPurchaseNo().then(res => { |
| | | form.value.purchaseContractNumber = res.data; |
| | | }); |
| | | form.value.purchaseContractNumber = ""; |
| | | } |
| | | userListNoPage().then(res => { |
| | | userList.value = res.data; |
| | |
| | | } |
| | | // æäº¤è¡¨å |
| | | const submitForm = n => { |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | proxy.$refs["formRef"].validate(async valid => { |
| | | if (valid) { |
| | | if (productData.value.length > 0) { |
| | | form.value.productData = proxy.HaveJson(productData.value); |
| | |
| | | form.value.tempFileIds = tempFileIds; |
| | | form.value.type = 2; |
| | | form.value.approvalStatus = n; |
| | | |
| | | // 妿éè´ååå·ä¸ºç©ºï¼åæ ¹æ®å½å
¥æ¥æèªå¨çæ |
| | | if (!form.value.purchaseContractNumber) { |
| | | try { |
| | | const purchaseNoRes = await createPurchaseNo(form.value.entryDate); |
| | | if (purchaseNoRes?.data) { |
| | | form.value.purchaseContractNumber = purchaseNoRes.data; |
| | | } |
| | | } catch (error) { |
| | | console.error("çæéè´ååå·å¤±è´¥:", error); |
| | | proxy.$modal.msgWarning("çæéè´ååå·å¤±è´¥"); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | addOrEditPurchase(form.value).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | |
| | | </div> |
| | | </template> |
| | | |
| | | |
| | | <!-- ç¨å°ç³è¯·ç®¡ç --> |
| | | <div class="tab-content"> |
| | | <el-row :gutter="20" class="mb-20 "> |
| | |
| | | :isShowPagination="true" |
| | | @pagination="paginationChange" |
| | | /> |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | |
| | | <!-- ç¨å°ç³è¯·å¯¹è¯æ¡ --> |
| | |
| | | const sealFormRef = ref() |
| | | const userList = ref([]) |
| | | const sealForm = reactive({ |
| | | id: null, |
| | | applicationNum: '', |
| | | title: '', |
| | | sealType: '', |
| | |
| | | |
| | | // ç¨å°ç³è¯·è¡¨æ ¼åé
ç½®ï¼éå¨ getStatusText/getSealTypeText çä¹åå®ä¹ï¼ |
| | | const sealTableColumn = ref([ |
| | | { label: 'ç³è¯·ç¼å·', prop: 'applicationNum',}, |
| | | { label: 'ç³è¯·ç¼å·', prop: 'applicationNum' }, |
| | | { label: 'ç³è¯·æ é¢', prop: 'title', showOverflowTooltip: true }, |
| | | { label: 'ç³è¯·äºº', prop: 'createUserName', }, |
| | | { label: 'ç³è¯·äºº', prop: 'createUserName' }, |
| | | { label: 'æå±é¨é¨', prop: 'department', width: 150 }, |
| | | { |
| | | label: 'ç¨å°ç±»å', |
| | |
| | | formatData: (v) => getStatusText(v), |
| | | formatType: (v) => getStatusType(v) |
| | | }, |
| | | { label: '审æ¹äºº', prop: 'approveUserName', width: 100 }, |
| | | { |
| | | dataType: 'action', |
| | | label: 'æä½', |
| | | width: 200, |
| | | width: 250, |
| | | fixed: 'right', |
| | | align: 'center', |
| | | operation: [ |
| | | { |
| | | name: '审æ¹', |
| | | clickFun: (row) => approveSeal(row), |
| | | showHide: (row) => row.status === 'pending' |
| | | showHide: (row) => row.status === 'pending' && Number(userStore.id) === row.approveUserId |
| | | }, |
| | | { |
| | | name: 'æç»', |
| | | clickFun: (row) => rejectSeal(row), |
| | | showHide: (row) => row.status === 'pending' |
| | | showHide: (row) => row.status === 'pending' && Number(userStore.id) === row.approveUserId |
| | | }, |
| | | { name: '详æ
', clickFun: (row) => viewSealDetail(row) } |
| | | { |
| | | name: 'éæ°ç³è¯·', |
| | | clickFun: (row) => reapplySeal(row), |
| | | showHide: (row) => row.status === 'rejected' && Number(userStore.id) === row.createUser |
| | | }, |
| | | { name: '详æ
', clickFun: (row) => viewSealDetail(row) } |
| | | ] |
| | | } |
| | | ]) |
| | | |
| | | // æç´¢å°ç« ç³è¯· |
| | | const searchSealApplications = () => { |
| | | page.current=1 |
| | | page.current = 1 |
| | | getSealApplicationList() |
| | | |
| | | // ElMessage.success('æç´¢å®æ') |
| | | } |
| | | // éç½®å°ç« ç³è¯·æç´¢ |
| | | const resetSealSearch = () => { |
| | |
| | | sealSearchForm.applicationNum = '' |
| | | searchSealApplications() |
| | | } |
| | | |
| | | // éæ°ç³è¯·ç¨å° |
| | | const reapplySeal = (row) => { |
| | | // é¢å¡«è¡¨åæ°æ® |
| | | Object.assign(sealForm, { |
| | | id: row.id, |
| | | applicationNum: row.applicationNum, |
| | | title: row.title, |
| | | sealType: row.sealType, |
| | | reason: row.reason, |
| | | approveUserId: row.approveUserId, |
| | | urgency: row.urgency || 'normal', |
| | | status: 'pending', |
| | | storageBlobDTOs: row.storageBlobVOList || [] |
| | | }) |
| | | showSealApplyDialog.value = true |
| | | } |
| | | |
| | | // æäº¤ç¨å°ç³è¯· |
| | | const submitSealApplication = async () => { |
| | | try { |
| | | await sealFormRef.value.validate() |
| | | addSealApplication(sealForm).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('ç³è¯·æäº¤æå') |
| | | const request = sealForm.id ? updateSealApplication : addSealApplication |
| | | request(sealForm).then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success(sealForm.id ? 'éæ°ç³è¯·æå' : 'ç³è¯·æäº¤æå') |
| | | closeSealApplyDialog() |
| | | getSealApplicationList() |
| | | Object.assign(sealForm, { |
| | | applicationNum: '', |
| | | title: '', |
| | | sealType: '', |
| | | reason: '', |
| | | approveUserId: '', |
| | | urgency: 'normal', |
| | | status: 'pending', |
| | | storageBlobDTOs: [] |
| | | }) |
| | | id: null, |
| | | applicationNum: '', |
| | | title: '', |
| | | sealType: '', |
| | | reason: '', |
| | | approveUserId: '', |
| | | urgency: 'normal', |
| | | status: 'pending', |
| | | storageBlobDTOs: [] |
| | | }) |
| | | } |
| | | }).catch(err => { |
| | | console.log(err.msg) |
| | | }) |
| | | |
| | | } catch (error) { |
| | | } |
| | | } |
| | | |
| | | // å
³éç¨å°ç³è¯·å¯¹è¯æ¡ |
| | | const closeSealApplyDialog = () => { |
| | | // æ¸
ç©ºè¡¨åæ°æ® |
| | | Object.assign(sealForm, { |
| | | id: null, |
| | | applicationNum: '', |
| | | title: '', |
| | | sealType: '', |
| | |
| | | }).then(() => { |
| | | row.status = 'approved' |
| | | updateSealApplication(row).then(res => { |
| | | if(res.code == 200){ |
| | | if (res.code == 200) { |
| | | ElMessage.success('审æ¹éè¿') |
| | | getSealApplicationList() |
| | | } |
| | |
| | | inputErrorMessage: 'æç»åå ä¸è½ä¸ºç©º' |
| | | }).then(({ value }) => { |
| | | row.status = 'rejected' |
| | | row.reason = value |
| | | updateSealApplication(row).then(res => { |
| | | if(res.code == 200){ |
| | | if (res.code == 200) { |
| | | ElMessage.success('å·²æç»ç³è¯·') |
| | | getSealApplicationList() |
| | | } |
| | |
| | | const getSealApplicationList = async () => { |
| | | tableLoading.value = true |
| | | listSealApplication(page, sealSearchForm) |
| | | .then(res => { |
| | | sealApplications.value = res.data.records |
| | | page.total = res.data.total |
| | | tableLoading.value = false |
| | | }).catch(err => { |
| | | tableLoading.value = false |
| | | }) |
| | | .then(res => { |
| | | sealApplications.value = res.data.records |
| | | page.total = res.data.total |
| | | tableLoading.value = false |
| | | }).catch(err => { |
| | | tableLoading.value = false |
| | | }) |
| | | } |
| | | // å页ååå¤ç |
| | | const paginationChange = (obj) => { |
| | |
| | | .attachment-table { |
| | | border-radius: 4px; |
| | | } |
| | | </style> |
| | | </style> |
| | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="èµäº§ç¼å·" prop="assetCode"> |
| | | <el-input v-model="form.assetCode" placeholder="ç³»ç»èªå¨çæ" disabled /> |
| | | <el-input v-model="form.assetCode" placeholder="ä¿ååèªå¨çæ" disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å建æ¶é´" prop="createTime"> |
| | | <el-date-picker v-model="createTimeDate" type="date" placeholder="éæ©æ¥æ" value-format="YYYY-MM-DD" style="width: 100%;" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-form-item label="夿³¨" prop="remark"> |
| | | <el-input v-model="form.remark" type="textarea" :rows="3" placeholder="请è¾å
¥å¤æ³¨" /> |
| | | </el-form-item> |
| | |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted, computed } from "vue"; |
| | | import dayjs from "dayjs"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | import { |
| | |
| | | keeper: "", |
| | | status: "in_use", |
| | | remark: "", |
| | | createTime: "", |
| | | }); |
| | | |
| | | const form = reactive({ |
| | | ...createDefaultForm(), |
| | | }); |
| | | const createTimeDate = computed({ |
| | | get: () => (form.createTime ? String(form.createTime).split(" ")[0] : ""), |
| | | set: (value) => { |
| | | form.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : ""; |
| | | }, |
| | | }); |
| | | |
| | | const rules = { |
| | |
| | | getTableData(); |
| | | }; |
| | | |
| | | const buildAssetCode = () => `GD${Date.now().toString().slice(-10)}`; |
| | | |
| | | const add = () => { |
| | | isEdit.value = false; |
| | | isView.value = false; |
| | | currentId.value = null; |
| | | dialogTitle.value = "æ°å¢åºå®èµäº§"; |
| | | Object.assign(form, createDefaultForm(), { |
| | | assetCode: buildAssetCode(), |
| | | purchaseDate: new Date().toISOString().split('T')[0], |
| | | createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), |
| | | }); |
| | | dialogVisible.value = true; |
| | | }; |
| | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="èµäº§ç¼å·" prop="assetCode"> |
| | | <el-input v-model="form.assetCode" placeholder="ç³»ç»èªå¨çæ" disabled /> |
| | | <el-input v-model="form.assetCode" placeholder="ä¿ååèªå¨çæ" disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å建æ¶é´" prop="createTime"> |
| | | <el-date-picker v-model="createTimeDate" type="date" placeholder="éæ©æ¥æ" value-format="YYYY-MM-DD" style="width: 100%;" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-form-item label="èµäº§æè¿°" prop="description"> |
| | | <el-input v-model="form.description" type="textarea" :rows="3" placeholder="请è¾å
¥èµäº§æè¿°" /> |
| | | </el-form-item> |
| | |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted, computed } from "vue"; |
| | | import dayjs from "dayjs"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | import { |
| | |
| | | status: "in_use", |
| | | description: "", |
| | | remark: "", |
| | | createTime: "", |
| | | }); |
| | | |
| | | const form = reactive({ |
| | | ...createDefaultForm(), |
| | | }); |
| | | const createTimeDate = computed({ |
| | | get: () => (form.createTime ? String(form.createTime).split(" ")[0] : ""), |
| | | set: (value) => { |
| | | form.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : ""; |
| | | }, |
| | | }); |
| | | |
| | | const rules = { |
| | |
| | | getTableData(); |
| | | }; |
| | | |
| | | const buildAssetCode = () => `WX${Date.now().toString().slice(-10)}`; |
| | | |
| | | const add = () => { |
| | | isEdit.value = false; |
| | | isView.value = false; |
| | | currentId.value = null; |
| | | dialogTitle.value = "æ°å¢æ å½¢èµäº§"; |
| | | Object.assign(form, createDefaultForm(), { |
| | | assetCode: buildAssetCode(), |
| | | acquisitionDate: new Date().toISOString().split('T')[0], |
| | | createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), |
| | | }); |
| | | dialogVisible.value = true; |
| | | }; |
| | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç³è¯·åå·" prop="invoiceApplicationNo"> |
| | | <el-input v-model="form.invoiceApplicationNo" placeholder="ç³»ç»èªå¨çæ" disabled /> |
| | | <el-input v-model="form.invoiceApplicationNo" placeholder="ä¿ååèªå¨çæ" disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å建æ¶é´" prop="createTime"> |
| | | <el-date-picker |
| | | v-model="formCreateTimeDate" |
| | | type="date" |
| | | placeholder="éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 100%;" |
| | | :disabled="isView" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="仿¬¾éé¢" prop="paymentAmount"> |
| | | <el-input-number |
| | | v-model="form.paymentAmount" |
| | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="仿¬¾åå·" prop="paymentNumber"> |
| | | <el-input v-model="paymentForm.paymentNumber" placeholder="ç³»ç»èªå¨çæ" disabled /> |
| | | <el-input v-model="paymentForm.paymentNumber" placeholder="ä¿ååèªå¨çæ" disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å建æ¶é´" prop="createTime"> |
| | | <el-date-picker |
| | | v-model="paymentFormCreateTimeDate" |
| | | type="date" |
| | | placeholder="éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 100%;" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="仿¬¾éé¢" prop="paymentAmount"> |
| | | <el-input-number |
| | |
| | | |
| | | <script setup> |
| | | import { ref, reactive, computed, onMounted, nextTick, getCurrentInstance } from "vue"; |
| | | import dayjs from "dayjs"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | import { getOptions } from "@/api/procurementManagement/procurementLedger.js"; |
| | |
| | | bankAccount: "", |
| | | bankName: "", |
| | | remark: "", |
| | | createTime: "", |
| | | }); |
| | | |
| | | const paymentRules = { |
| | |
| | | stockInRecordIds: [], |
| | | inboundBatches: "", |
| | | status: 0, |
| | | createTime: "", |
| | | }); |
| | | const formCreateTimeDate = computed({ |
| | | get: () => (form.createTime ? String(form.createTime).split(" ")[0] : ""), |
| | | set: (value) => { |
| | | form.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : ""; |
| | | }, |
| | | }); |
| | | const paymentFormCreateTimeDate = computed({ |
| | | get: () => (paymentForm.createTime ? String(paymentForm.createTime).split(" ")[0] : ""), |
| | | set: (value) => { |
| | | paymentForm.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : ""; |
| | | }, |
| | | }); |
| | | |
| | | const rules = { |
| | |
| | | stockInRecordIds, |
| | | inboundBatches: formatInboundBatches(row.inboundBatches), |
| | | status: normalizeStatus(row.status), |
| | | createTime: row.createTime ?? "", |
| | | }); |
| | | }; |
| | | |
| | |
| | | remark: row.remark ?? "", |
| | | status: statusOverride !== undefined ? statusOverride : normalizeStatus(row.status), |
| | | paymentAmount: Number(row.paymentAmount ?? row.amount ?? 0), |
| | | createTime: row.createTime, |
| | | }); |
| | | |
| | | const buildSubmitPayload = (forUpdate = false) => { |
| | |
| | | remark: form.remark || "", |
| | | status: 0, |
| | | paymentAmount: form.paymentAmount, |
| | | createTime: form.createTime, |
| | | }; |
| | | if (forUpdate) { |
| | | payload.id = currentId.value; |
| | |
| | | stockInRecordIds: [], |
| | | inboundBatches: "", |
| | | status: 0, |
| | | createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), |
| | | }); |
| | | inboundBatchList.value = []; |
| | | inboundBatchOptions.value = []; |
| | |
| | | bankAccount: row.bankAccountNum ?? row.bankAccount ?? "", |
| | | bankName: row.bankAccountName ?? row.bankName ?? "", |
| | | remark: "", |
| | | createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), |
| | | }); |
| | | paymentDialogVisible.value = true; |
| | | nextTick(() => { |
| | |
| | | paymentAmount: paymentForm.paymentAmount, |
| | | paymentNumber: paymentForm.paymentNumber || "", |
| | | remark: paymentForm.remark || "", |
| | | createTime: paymentForm.createTime, |
| | | }) |
| | | .then((res) => { |
| | | if (res.code === 200) { |
| | |
| | | slot: "inboundDate", |
| | | }, |
| | | { label: "产ååç§°", prop: "productName", minWidth: "140" }, |
| | | { label: "产åè§æ ¼", prop: "specificationModel", minWidth: "140" }, |
| | | { label: "è§æ ¼åå·", prop: "specificationModel", minWidth: "140" }, |
| | | { |
| | | label: "éé¢", |
| | | prop: "inboundAmount", |
| | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="ç³è¯·åå·" prop="applyCode"> |
| | | <el-input v-model="form.applyCode" placeholder="ç³»ç»èªå¨çæ" disabled /> |
| | | <el-input v-model="form.applyCode" placeholder="ä¿ååèªå¨çæ" disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å建æ¶é´" prop="createTime"> |
| | | <el-date-picker |
| | | v-model="formCreateTimeDate" |
| | | type="date" |
| | | placeholder="éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 100%;" |
| | | :disabled="isView" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-form-item label="å票å
容" prop="content"> |
| | | <el-input v-model="form.content" type="textarea" :rows="3" placeholder="请è¾å
¥å票å
容" :disabled="isView" /> |
| | | </el-form-item> |
| | |
| | | |
| | | <script setup> |
| | | import { ref, reactive, computed, onMounted, nextTick, getCurrentInstance, defineAsyncComponent } from "vue"; |
| | | import dayjs from "dayjs"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | import { listCustomer } from "@/api/basicData/customer.js"; |
| | |
| | | applyDate: "", |
| | | content: "", |
| | | remark: "", |
| | | createTime: "", |
| | | }); |
| | | const formCreateTimeDate = computed({ |
| | | get: () => (form.createTime ? String(form.createTime).split(" ")[0] : ""), |
| | | set: (value) => { |
| | | form.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : ""; |
| | | }, |
| | | }); |
| | | |
| | | const rules = { |
| | |
| | | status: normalizeStatus(row.status ?? row.auditStatus), |
| | | outboundBatchNos, |
| | | outboundBatches: formatOutboundBatches(row.outboundBatches), |
| | | createTime: row.createTime ?? "", |
| | | }); |
| | | }; |
| | | |
| | |
| | | isView.value = false; |
| | | dialogTitle.value = "æ°å¢å¼ç¥¨ç³è¯·"; |
| | | Object.assign(form, { |
| | | applyCode: "KP" + Date.now().toString().slice(-8), |
| | | applyCode: "", |
| | | customerId: "", |
| | | outboundBatchNos: [], |
| | | outboundBatches: "", |
| | |
| | | applyDate: new Date().toISOString().split("T")[0], |
| | | content: "", |
| | | remark: "", |
| | | createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), |
| | | }); |
| | | outboundBatchList.value = []; |
| | | outboundBatchOptions.value = []; |
| | |
| | | invoiceAmount: form.amount, |
| | | taxRate: form.taxRate, |
| | | status: 0, |
| | | createTime: form.createTime, |
| | | }; |
| | | if (forUpdate) { |
| | | payload.id = currentId.value; |
| | |
| | | <el-form-item label="æ¶æ¬¾åå·" |
| | | prop="receiptCode"> |
| | | <el-input v-model="form.receiptCode" |
| | | placeholder="ç³»ç»èªå¨çæ" |
| | | placeholder="ä¿ååèªå¨çæ" |
| | | disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | :label="item.label" |
| | | :value="item.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å建æ¶é´" |
| | | prop="createTime"> |
| | | <el-date-picker v-model="formCreateTimeDate" |
| | | type="date" |
| | | placeholder="éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 100%;" |
| | | :disabled="isView" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | nextTick, |
| | | getCurrentInstance, |
| | | } from "vue"; |
| | | import dayjs from "dayjs"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | import { listCustomer } from "@/api/basicData/customer.js"; |
| | |
| | | stockOutRecordIds: [], |
| | | outboundBatches: "", |
| | | remark: "", |
| | | createTime: "", |
| | | }); |
| | | const formCreateTimeDate = computed({ |
| | | get: () => (form.createTime ? String(form.createTime).split(" ")[0] : ""), |
| | | set: (value) => { |
| | | form.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : ""; |
| | | }, |
| | | }); |
| | | |
| | | const rules = { |
| | |
| | | collectionNumber: form.receiptCode || "", |
| | | remark: form.remark || "", |
| | | stockOutRecordIds: (form.stockOutRecordIds || []).join(","), |
| | | createTime: form.createTime, |
| | | }; |
| | | if (forUpdate) { |
| | | payload.id = currentId.value; |
| | |
| | | stockOutRecordIds, |
| | | outboundBatches: formatOutboundBatches(row.outboundBatches), |
| | | remark: row.remark ?? "", |
| | | createTime: row.createTime ?? "", |
| | | }); |
| | | }; |
| | | |
| | |
| | | isView.value = false; |
| | | dialogTitle.value = "æ°å¢æ¶æ¬¾"; |
| | | Object.assign(form, { |
| | | receiptCode: "SK" + Date.now().toString().slice(-8), |
| | | receiptCode: "", |
| | | customerId: "", |
| | | receiptDate: new Date().toISOString().split("T")[0], |
| | | amount: 0, |
| | |
| | | stockOutRecordIds: [], |
| | | outboundBatches: "", |
| | | remark: "", |
| | | createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), |
| | | }); |
| | | outboundBatchList.value = []; |
| | | outboundBatchOptions.value = []; |
| | |
| | | <template> |
| | | <!-- éå®åºåº --> |
| | | <!-- éå®åºåº --> |
| | | <div class="app-container"> |
| | | <el-form :model="filters" :inline="true"> |
| | | <el-form :model="filters" |
| | | :inline="true"> |
| | | <el-form-item label="åºåºåå·:"> |
| | | <el-input v-model="filters.outboundBatches" placeholder="请è¾å
¥åºåºåå·" clearable style="width: 200px;" /> |
| | | <el-input v-model="filters.outboundBatches" |
| | | placeholder="请è¾å
¥åºåºåå·" |
| | | clearable |
| | | style="width: 200px;" /> |
| | | </el-form-item> |
| | | <el-form-item label="客æ·åç§°:"> |
| | | <el-input v-model="filters.customerName" placeholder="请è¾å
¥å®¢æ·åç§°" clearable style="width: 200px;" /> |
| | | <el-input v-model="filters.customerName" |
| | | placeholder="请è¾å
¥å®¢æ·åç§°" |
| | | clearable |
| | | style="width: 200px;" /> |
| | | </el-form-item> |
| | | <el-form-item label="åºåºæ¥æ:"> |
| | | <el-date-picker |
| | | v-model="filters.dateRange" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="daterange" |
| | | range-separator="è³" |
| | | start-placeholder="å¼å§æ¥æ" |
| | | end-placeholder="ç»ææ¥æ" |
| | | clearable |
| | | /> |
| | | <el-date-picker v-model="filters.dateRange" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="daterange" |
| | | range-separator="è³" |
| | | start-placeholder="å¼å§æ¥æ" |
| | | end-placeholder="ç»ææ¥æ" |
| | | clearable /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="onSearch">æç´¢</el-button> |
| | | <el-button type="primary" |
| | | @click="onSearch">æç´¢</el-button> |
| | | <el-button @click="resetFilters">éç½®</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | |
| | | <div class="actions"> |
| | | <div></div> |
| | | <div> |
| | | <el-button @click="handleOut" icon="Download">导åº</el-button> |
| | | <el-button @click="handleOut" |
| | | icon="Download">导åº</el-button> |
| | | </div> |
| | | </div> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="columns" |
| | | :tableData="dataList" |
| | | :tableLoading="tableLoading" |
| | | :page="{ |
| | | <PIMTable rowKey="id" |
| | | :column="columns" |
| | | :tableData="dataList" |
| | | :tableLoading="tableLoading" |
| | | :page="{ |
| | | current: pagination.currentPage, |
| | | size: pagination.pageSize, |
| | | total: pagination.total, |
| | | }" |
| | | @pagination="changePage" |
| | | /> |
| | | @pagination="changePage" /> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted, getCurrentInstance } from "vue"; |
| | | import { ElMessage } from "element-plus"; |
| | | import { listPageAccountSales } from "@/api/financialManagement/accountSales"; |
| | | import { ref, reactive, onMounted, getCurrentInstance } from "vue"; |
| | | import { ElMessage } from "element-plus"; |
| | | import { listPageAccountSales } from "@/api/financialManagement/accountSales"; |
| | | |
| | | defineOptions({ |
| | | name: "éå®åºåº", |
| | | }); |
| | | defineOptions({ |
| | | name: "éå®åºåº", |
| | | }); |
| | | |
| | | const { proxy } = getCurrentInstance(); |
| | | const { proxy } = getCurrentInstance(); |
| | | |
| | | const filters = reactive({ |
| | | outboundBatches: "", |
| | | customerName: "", |
| | | dateRange: [], |
| | | }); |
| | | const filters = reactive({ |
| | | outboundBatches: "", |
| | | customerName: "", |
| | | dateRange: [], |
| | | }); |
| | | |
| | | const pagination = reactive({ |
| | | currentPage: 1, |
| | | pageSize: 10, |
| | | total: 0, |
| | | }); |
| | | const pagination = reactive({ |
| | | currentPage: 1, |
| | | pageSize: 10, |
| | | total: 0, |
| | | }); |
| | | |
| | | const columns = [ |
| | | { label: "åºåºåå·", prop: "outboundBatches", minWidth: "150" }, |
| | | { label: "客æ·åç§°", prop: "customerName", minWidth: "180" }, |
| | | { label: "åºåºæ¥æ", prop: "shippingDate", width: "170" }, |
| | | { label: "产ååç§°", prop: "productName", minWidth: "140" }, |
| | | { label: "产åè§æ ¼", prop: "specificationModel", minWidth: "140" }, |
| | | { |
| | | label: "éé¢", |
| | | prop: "outboundAmount", |
| | | minWidth: "120", |
| | | align: "right", |
| | | formatData: (val) => (val === null || val === undefined || val === "" ? "" : Number(val).toLocaleString("zh-CN", { minimumFractionDigits: 2, maximumFractionDigits: 2 })), |
| | | }, |
| | | { label: "åè´§ç¼å·", prop: "shippingNo", minWidth: "140" }, |
| | | { label: "éå®è®¢åå·", prop: "salesContractNo", minWidth: "150" }, |
| | | ]; |
| | | const columns = [ |
| | | { label: "åºåºåå·", prop: "outboundBatches", minWidth: "150" }, |
| | | { label: "客æ·åç§°", prop: "customerName", minWidth: "180" }, |
| | | { label: "åºåºæ¥æ", prop: "shippingDate", width: "170" }, |
| | | { label: "产ååç§°", prop: "productName", minWidth: "140" }, |
| | | { label: "è§æ ¼åå·", prop: "specificationModel", minWidth: "140" }, |
| | | { |
| | | label: "éé¢", |
| | | prop: "outboundAmount", |
| | | minWidth: "120", |
| | | align: "right", |
| | | formatData: val => |
| | | val === null || val === undefined || val === "" |
| | | ? "" |
| | | : Number(val).toLocaleString("zh-CN", { |
| | | minimumFractionDigits: 2, |
| | | maximumFractionDigits: 2, |
| | | }), |
| | | }, |
| | | { label: "åè´§ç¼å·", prop: "shippingNo", minWidth: "140" }, |
| | | { label: "éå®è®¢åå·", prop: "salesContractNo", minWidth: "150" }, |
| | | ]; |
| | | |
| | | const dataList = ref([]); |
| | | const tableLoading = ref(false); |
| | | const dataList = ref([]); |
| | | const tableLoading = ref(false); |
| | | |
| | | function buildFilterParams() { |
| | | const params = { |
| | | outboundBatches: filters.outboundBatches || undefined, |
| | | customerName: filters.customerName || undefined, |
| | | }; |
| | | if (filters.dateRange && filters.dateRange.length === 2) { |
| | | params.startDate = filters.dateRange[0]; |
| | | params.endDate = filters.dateRange[1]; |
| | | function buildFilterParams() { |
| | | const params = { |
| | | outboundBatches: filters.outboundBatches || undefined, |
| | | customerName: filters.customerName || undefined, |
| | | }; |
| | | if (filters.dateRange && filters.dateRange.length === 2) { |
| | | params.startDate = filters.dateRange[0]; |
| | | params.endDate = filters.dateRange[1]; |
| | | } |
| | | return params; |
| | | } |
| | | return params; |
| | | } |
| | | |
| | | const onSearch = () => { |
| | | pagination.currentPage = 1; |
| | | getTableData(); |
| | | }; |
| | | const onSearch = () => { |
| | | pagination.currentPage = 1; |
| | | getTableData(); |
| | | }; |
| | | |
| | | const getTableData = () => { |
| | | tableLoading.value = true; |
| | | listPageAccountSales({ |
| | | ...buildFilterParams(), |
| | | current: pagination.currentPage, |
| | | size: pagination.pageSize, |
| | | }) |
| | | .then((res) => { |
| | | const ok = res.code === 200 || res.code === 0; |
| | | if (ok && res.data) { |
| | | pagination.total = res.data.total ?? 0; |
| | | dataList.value = res.data.records ?? []; |
| | | } else { |
| | | ElMessage.error(res.msg || "æ¥è¯¢å¤±è´¥"); |
| | | const getTableData = () => { |
| | | tableLoading.value = true; |
| | | listPageAccountSales({ |
| | | ...buildFilterParams(), |
| | | current: pagination.currentPage, |
| | | size: pagination.pageSize, |
| | | }) |
| | | .then(res => { |
| | | const ok = res.code === 200 || res.code === 0; |
| | | if (ok && res.data) { |
| | | pagination.total = res.data.total ?? 0; |
| | | dataList.value = res.data.records ?? []; |
| | | } else { |
| | | ElMessage.error(res.msg || "æ¥è¯¢å¤±è´¥"); |
| | | dataList.value = []; |
| | | } |
| | | }) |
| | | .catch(() => { |
| | | dataList.value = []; |
| | | } |
| | | }) |
| | | .catch(() => { |
| | | dataList.value = []; |
| | | }) |
| | | .finally(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | }) |
| | | .finally(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | const resetFilters = () => { |
| | | filters.outboundBatches = ""; |
| | | filters.customerName = ""; |
| | | filters.dateRange = []; |
| | | pagination.currentPage = 1; |
| | | getTableData(); |
| | | }; |
| | | const resetFilters = () => { |
| | | filters.outboundBatches = ""; |
| | | filters.customerName = ""; |
| | | filters.dateRange = []; |
| | | pagination.currentPage = 1; |
| | | getTableData(); |
| | | }; |
| | | |
| | | const changePage = ({ page, limit }) => { |
| | | pagination.currentPage = page; |
| | | pagination.pageSize = limit; |
| | | getTableData(); |
| | | }; |
| | | const changePage = ({ page, limit }) => { |
| | | pagination.currentPage = page; |
| | | pagination.pageSize = limit; |
| | | getTableData(); |
| | | }; |
| | | |
| | | const handleOut = () => { |
| | | proxy.download( |
| | | "/accountSales/exportAccountSalesOutbound", |
| | | buildFilterParams(), |
| | | `éå®åºåº_${new Date().getTime()}.xlsx` |
| | | ); |
| | | }; |
| | | const handleOut = () => { |
| | | proxy.download( |
| | | "/accountSales/exportAccountSalesOutbound", |
| | | buildFilterParams(), |
| | | `éå®åºåº_${new Date().getTime()}.xlsx` |
| | | ); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getTableData(); |
| | | }); |
| | | onMounted(() => { |
| | | getTableData(); |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .actions { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | margin-bottom: 15px; |
| | | } |
| | | .actions { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | margin-bottom: 15px; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <div> |
| | | <div class="search_form" style="margin-bottom: 10px"> |
| | | <el-form |
| | | ref="searchFormRef" |
| | | :model="searchForm" |
| | | class="demo-form-inline" |
| | | > |
| | | <div class="search_form" |
| | | style="margin-bottom: 10px"> |
| | | <el-form ref="searchFormRef" |
| | | :model="searchForm" |
| | | class="demo-form-inline"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="4"> |
| | | <el-form-item label="åºåºæ¥æ" prop="timeStr"> |
| | | <el-form-item label="åºåºæ¥æ" |
| | | prop="timeStr"> |
| | | <el-date-picker v-model="searchForm.timeStr" |
| | | type="date" |
| | | placeholder="è¯·éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable/> |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="4"> |
| | | <el-form-item label="产å大类" prop="productName"> |
| | | <el-form-item label="产å大类" |
| | | prop="productName"> |
| | | <el-input v-model="searchForm.productName" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | clearable/> |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | |
| | | <el-col :span="4"> |
| | | <el-form-item label="产åè§æ ¼" prop="model"> |
| | | <el-form-item label="è§æ ¼åå·" |
| | | prop="model"> |
| | | <el-input v-model="searchForm.model" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | clearable/> |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="4"> |
| | | <el-form-item label="æ¹å·" prop="batchNo"> |
| | | <el-form-item label="æ¹å·" |
| | | prop="batchNo"> |
| | | <el-input v-model="searchForm.batchNo" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | clearable/> |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="4"> |
| | | <el-form-item label="æ¥æº" prop="recordType"> |
| | | <el-select |
| | | v-model="searchForm.recordType" |
| | | style="width: 240px" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | > |
| | | <el-option |
| | | v-for="item in stockRecordTypeOptions" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | /> |
| | | <el-form-item label="æ¥æº" |
| | | prop="recordType"> |
| | | <el-select v-model="searchForm.recordType" |
| | | style="width: 240px" |
| | | placeholder="è¯·éæ©" |
| | | clearable> |
| | | <el-option v-for="item in stockRecordTypeOptions" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <!-- æé® --> |
| | | <el-col :span="4"> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="getList"> |
| | | <el-button type="primary" |
| | | @click="getList"> |
| | | æç´¢ |
| | | </el-button> |
| | | |
| | | <el-button @click="resetSearch"> |
| | | éç½® |
| | | </el-button> |
| | |
| | | </el-form> |
| | | </div> |
| | | <div class="actions"> |
| | | <el-button type="primary" @click="handleBatchApprove">审æ¹</el-button> |
| | | <el-button type="primary" |
| | | @click="handleBatchApprove">审æ¹</el-button> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | <el-button type="danger" plain @click="handleDelete">å é¤</el-button> |
| | | <el-button type="primary" plain @click="handlePrint">æå°</el-button> |
| | | <el-button type="danger" |
| | | plain |
| | | @click="handleDelete">å é¤</el-button> |
| | | <el-button type="primary" |
| | | plain |
| | | @click="handlePrint">æå°</el-button> |
| | | </div> |
| | | <div class="table_list"> |
| | | <el-table |
| | | :data="tableData" |
| | | border |
| | | v-loading="tableLoading" |
| | | @selection-change="handleSelectionChange" |
| | | :expand-row-keys="expandedRowKeys" |
| | | :row-key="(row) => row.id" |
| | | style="width: 100%" |
| | | height="calc(100vh - 18.5em)" |
| | | > |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table-column align="center" label="åºå·" type="index" width="60" /> |
| | | <el-table-column |
| | | label="åºåºæ¹æ¬¡" |
| | | prop="outboundBatches" |
| | | min-width="100" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="åºåºæ¥æ" |
| | | prop="createTime" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="产å大类" |
| | | prop="productName" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column label="è§æ ¼åå·" prop="model" show-overflow-tooltip /> |
| | | <el-table-column label="æ¹å·" prop="batchNo" show-overflow-tooltip /> |
| | | <el-table-column label="åä½" prop="unit" show-overflow-tooltip /> |
| | | <el-table-column |
| | | label="åºåºæ°é" |
| | | prop="stockOutNum" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column label="åºåºäºº" prop="createBy" show-overflow-tooltip /> |
| | | <el-table-column label="æ¥æº" prop="recordType" show-overflow-tooltip> |
| | | <el-table :data="tableData" |
| | | border |
| | | v-loading="tableLoading" |
| | | @selection-change="handleSelectionChange" |
| | | :expand-row-keys="expandedRowKeys" |
| | | :row-key="(row) => row.id" |
| | | style="width: 100%" |
| | | height="calc(100vh - 18.5em)"> |
| | | <el-table-column align="center" |
| | | type="selection" |
| | | width="55" /> |
| | | <el-table-column align="center" |
| | | label="åºå·" |
| | | type="index" |
| | | width="60" /> |
| | | <el-table-column label="åºåºæ¹æ¬¡" |
| | | prop="outboundBatches" |
| | | min-width="100" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="åºåºæ¥æ" |
| | | prop="createTime" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="产å大类" |
| | | prop="productName" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="è§æ ¼åå·" |
| | | prop="model" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="æ¹å·" |
| | | prop="batchNo" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="åä½" |
| | | prop="unit" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="åºåºæ°é" |
| | | prop="stockOutNum" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="åºåºäºº" |
| | | prop="createBy" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="æ¥æº" |
| | | prop="recordType" |
| | | show-overflow-tooltip> |
| | | <template #default="scope"> |
| | | {{ getRecordType(scope.row.recordType) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="审æ¹ç¶æ" |
| | | prop="approvalStatus" |
| | | show-overflow-tooltip |
| | | > |
| | | <el-table-column label="审æ¹ç¶æ" |
| | | prop="approvalStatus" |
| | | show-overflow-tooltip> |
| | | <template #default="scope"> |
| | | <el-tag |
| | | :type="getApprovalStatusTagType(scope.row.approvalStatus)" |
| | | size="small" |
| | | > |
| | | <el-tag :type="getApprovalStatusTagType(scope.row.approvalStatus)" |
| | | size="small"> |
| | | {{ getApprovalStatusLabel(scope.row.approvalStatus) }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <pagination |
| | | v-show="total > 0" |
| | | :total="total" |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | :page="page.current" |
| | | :limit="page.size" |
| | | @pagination="paginationChange" |
| | | /> |
| | | <pagination v-show="total > 0" |
| | | :total="total" |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | :page="page.current" |
| | | :limit="page.size" |
| | | @pagination="paginationChange" /> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import pagination from "@/components/PIMTable/Pagination.vue"; |
| | | import { ref } from "vue"; |
| | | import { ElMessageBox } from "element-plus"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { getCurrentDate } from "@/utils/index.js"; |
| | | import { |
| | | getStockOutPage, |
| | | delPendingStockOut, |
| | | batchApproveStockOutRecords, |
| | | } from "@/api/inventoryManagement/stockOut.js"; |
| | | import { |
| | | findAllQualifiedStockOutRecordTypeOptions, |
| | | findAllUnQualifiedStockOutRecordTypeOptions, |
| | | } from "@/api/basicData/enum.js"; |
| | | import pagination from "@/components/PIMTable/Pagination.vue"; |
| | | import { ref } from "vue"; |
| | | import { ElMessageBox } from "element-plus"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { getCurrentDate } from "@/utils/index.js"; |
| | | import { |
| | | getStockOutPage, |
| | | delPendingStockOut, |
| | | batchApproveStockOutRecords, |
| | | } from "@/api/inventoryManagement/stockOut.js"; |
| | | import { |
| | | findAllQualifiedStockOutRecordTypeOptions, |
| | | findAllUnQualifiedStockOutRecordTypeOptions, |
| | | } from "@/api/basicData/enum.js"; |
| | | |
| | | const userStore = useUserStore(); |
| | | const { proxy } = getCurrentInstance(); |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const tableLoading = ref(false); |
| | | // æ¥æºç±»åé项 |
| | | const stockRecordTypeOptions = ref([]); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | }); |
| | | const total = ref(0); |
| | | const userStore = useUserStore(); |
| | | const { proxy } = getCurrentInstance(); |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const tableLoading = ref(false); |
| | | // æ¥æºç±»åé项 |
| | | const stockRecordTypeOptions = ref([]); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | }); |
| | | const total = ref(0); |
| | | |
| | | const props = defineProps({ |
| | | type: { |
| | | type: String, |
| | | required: true, |
| | | default: "0", |
| | | }, |
| | | topParentProductId: { |
| | | type: [String, Number], |
| | | default: undefined, |
| | | }, |
| | | }); |
| | | const props = defineProps({ |
| | | type: { |
| | | type: String, |
| | | required: true, |
| | | default: "0", |
| | | }, |
| | | topParentProductId: { |
| | | type: [String, Number], |
| | | default: undefined, |
| | | }, |
| | | }); |
| | | |
| | | // æå°ç¸å
³ |
| | | const printPreviewVisible = ref(false); |
| | | const printData = ref([]); |
| | | // æå°ç¸å
³ |
| | | const printPreviewVisible = ref(false); |
| | | const printData = ref([]); |
| | | |
| | | // ç¨æ·ä¿¡æ¯è¡¨åå¼¹æ¡æ°æ® |
| | | const data = reactive({ |
| | | searchForm: { |
| | | supplierName: "", |
| | | timeStr: "", |
| | | recordType: "", |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | // ç¨æ·ä¿¡æ¯è¡¨åå¼¹æ¡æ°æ® |
| | | const data = reactive({ |
| | | searchForm: { |
| | | supplierName: "", |
| | | timeStr: "", |
| | | recordType: "", |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | |
| | | const searchFormRef = ref(null); |
| | | const searchFormRef = ref(null); |
| | | |
| | | const resetSearch = () => { |
| | | searchFormRef.value?.resetFields(); |
| | | page.current = 1; |
| | | getList(); |
| | | } |
| | | const resetSearch = () => { |
| | | searchFormRef.value?.resetFields(); |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | const paginationChange = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | getStockOutPage({ |
| | | ...searchForm.value, |
| | | ...page, |
| | | topParentProductId: props.topParentProductId, |
| | | }) |
| | | .then((res) => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | tableData.value.map((item) => { |
| | | item.children = []; |
| | | }); |
| | | total.value = res.data.total; |
| | | const paginationChange = obj => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | getStockOutPage({ |
| | | ...searchForm.value, |
| | | ...page, |
| | | topParentProductId: props.topParentProductId, |
| | | }) |
| | | .catch(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | tableData.value.map(item => { |
| | | item.children = []; |
| | | }); |
| | | total.value = res.data.total; |
| | | }) |
| | | .catch(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | const getRecordType = (recordType) => { |
| | | return ( |
| | | stockRecordTypeOptions.value.find((item) => item.value === recordType) |
| | | ?.label || "" |
| | | ); |
| | | }; |
| | | const getRecordType = recordType => { |
| | | return ( |
| | | stockRecordTypeOptions.value.find(item => item.value === recordType) |
| | | ?.label || "" |
| | | ); |
| | | }; |
| | | |
| | | const approvalStatusLabelMap = { |
| | | 0: "å¾
审æ¹", |
| | | 1: "éè¿", |
| | | 2: "驳å", |
| | | 3: "å¾
确认", |
| | | pending: "å¾
审æ¹", |
| | | approved: "éè¿", |
| | | rejected: "驳å", |
| | | PENDING: "å¾
审æ¹", |
| | | APPROVED: "éè¿", |
| | | REJECTED: "驳å", |
| | | }; |
| | | const approvalStatusLabelMap = { |
| | | 0: "å¾
审æ¹", |
| | | 1: "éè¿", |
| | | 2: "驳å", |
| | | 3: "å¾
确认", |
| | | pending: "å¾
审æ¹", |
| | | approved: "éè¿", |
| | | rejected: "驳å", |
| | | PENDING: "å¾
审æ¹", |
| | | APPROVED: "éè¿", |
| | | REJECTED: "驳å", |
| | | }; |
| | | |
| | | const getApprovalStatusLabel = (status) => { |
| | | if (status === null || status === undefined || status === "") { |
| | | return "å¾
审æ¹"; |
| | | } |
| | | return approvalStatusLabelMap[status] || "å¾
审æ¹"; |
| | | }; |
| | | const getApprovalStatusLabel = status => { |
| | | if (status === null || status === undefined || status === "") { |
| | | return "å¾
审æ¹"; |
| | | } |
| | | return approvalStatusLabelMap[status] || "å¾
审æ¹"; |
| | | }; |
| | | |
| | | // éè¿/驳ååºå®è²ï¼å
¶ä½ï¼å«å¾
审æ¹ã空å¼ãæªæ å°ä½ææ¡ä¸ºå¾
审æ¹ï¼ç»ä¸ç¨ warning é¢è¦è² |
| | | const getApprovalStatusTagType = (status) => { |
| | | if ( |
| | | status === 1 || |
| | | status === "1" || |
| | | status === "approved" || |
| | | status === "APPROVED" |
| | | ) |
| | | return "success"; |
| | | if ( |
| | | status === 2 || |
| | | status === "2" || |
| | | status === "rejected" || |
| | | status === "REJECTED" |
| | | ) |
| | | return "danger"; |
| | | return "warning"; |
| | | }; |
| | | // éè¿/驳ååºå®è²ï¼å
¶ä½ï¼å«å¾
审æ¹ã空å¼ãæªæ å°ä½ææ¡ä¸ºå¾
审æ¹ï¼ç»ä¸ç¨ warning é¢è¦è² |
| | | const getApprovalStatusTagType = status => { |
| | | if ( |
| | | status === 1 || |
| | | status === "1" || |
| | | status === "approved" || |
| | | status === "APPROVED" |
| | | ) |
| | | return "success"; |
| | | if ( |
| | | status === 2 || |
| | | status === "2" || |
| | | status === "rejected" || |
| | | status === "REJECTED" |
| | | ) |
| | | return "danger"; |
| | | return "warning"; |
| | | }; |
| | | |
| | | // è·åæ¥æºç±»åé项 |
| | | const fetchStockRecordTypeOptions = () => { |
| | | if (props.type === "0") { |
| | | findAllQualifiedStockOutRecordTypeOptions().then((res) => { |
| | | // è·åæ¥æºç±»åé项 |
| | | const fetchStockRecordTypeOptions = () => { |
| | | if (props.type === "0") { |
| | | findAllQualifiedStockOutRecordTypeOptions().then(res => { |
| | | stockRecordTypeOptions.value = res.data; |
| | | }); |
| | | return; |
| | | } |
| | | findAllUnQualifiedStockOutRecordTypeOptions().then(res => { |
| | | stockRecordTypeOptions.value = res.data; |
| | | }); |
| | | return; |
| | | } |
| | | findAllUnQualifiedStockOutRecordTypeOptions().then((res) => { |
| | | stockRecordTypeOptions.value = res.data; |
| | | }); |
| | | }; |
| | | }; |
| | | |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | | // è¿æ»¤æåæ°æ® |
| | | selectedRows.value = selection.filter((item) => item.id); |
| | | console.log("selection", selectedRows.value); |
| | | }; |
| | | const expandedRowKeys = ref([]); |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = selection => { |
| | | // è¿æ»¤æåæ°æ® |
| | | selectedRows.value = selection.filter(item => item.id); |
| | | console.log("selection", selectedRows.value); |
| | | }; |
| | | const expandedRowKeys = ref([]); |
| | | |
| | | const handleBatchApprove = () => { |
| | | if (selectedRows.value.length === 0) { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | | } |
| | | const ids = selectedRows.value.map((item) => item.id); |
| | | ElMessageBox.confirm("è¯·éæ©å®¡æ¹ç»æ", "审æ¹", { |
| | | confirmButtonText: "éè¿", |
| | | cancelButtonText: "驳å", |
| | | type: "warning", |
| | | distinguishCancelAndClose: true, |
| | | }) |
| | | .then(() => { |
| | | batchApproveStockOutRecords({ ids, approvalStatus: 1 }) |
| | | .then(() => { |
| | | proxy.$modal.msgSuccess("审æ¹éè¿æå"); |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msgError("审æ¹éè¿å¤±è´¥"); |
| | | }); |
| | | const handleBatchApprove = () => { |
| | | if (selectedRows.value.length === 0) { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | | } |
| | | const ids = selectedRows.value.map(item => item.id); |
| | | ElMessageBox.confirm("è¯·éæ©å®¡æ¹ç»æ", "审æ¹", { |
| | | confirmButtonText: "éè¿", |
| | | cancelButtonText: "驳å", |
| | | type: "warning", |
| | | distinguishCancelAndClose: true, |
| | | }) |
| | | .catch((action) => { |
| | | if (action === "cancel") { |
| | | batchApproveStockOutRecords({ ids, approvalStatus: 2 }) |
| | | .then(() => { |
| | | batchApproveStockOutRecords({ ids, approvalStatus: 1 }) |
| | | .then(() => { |
| | | proxy.$modal.msgSuccess("审æ¹é©³åæå"); |
| | | proxy.$modal.msgSuccess("审æ¹éè¿æå"); |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msgError("审æ¹é©³å失败"); |
| | | proxy.$modal.msgError("审æ¹éè¿å¤±è´¥"); |
| | | }); |
| | | return; |
| | | } |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download( |
| | | "/stockOutRecord/exportStockOutRecord", |
| | | { type: props.type }, |
| | | props.type === "0" ? "åæ ¼åºåºå°è´¦.xlsx" : "ä¸åæ ¼åºåºå°è´¦.xlsx" |
| | | ); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | |
| | | // å é¤ |
| | | 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(() => { |
| | | delPendingStockOut(ids).then((res) => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }) |
| | | .catch(action => { |
| | | if (action === "cancel") { |
| | | batchApproveStockOutRecords({ ids, approvalStatus: 2 }) |
| | | .then(() => { |
| | | proxy.$modal.msgSuccess("审æ¹é©³åæå"); |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msgError("审æ¹é©³å失败"); |
| | | }); |
| | | return; |
| | | } |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | .then(() => { |
| | | proxy.download( |
| | | "/stockOutRecord/exportStockOutRecord", |
| | | { type: props.type }, |
| | | props.type === "0" ? "åæ ¼åºåºå°è´¦.xlsx" : "ä¸åæ ¼åºåºå°è´¦.xlsx" |
| | | ); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | |
| | | // æå°åè½ |
| | | const handlePrint = () => { |
| | | if (selectedRows.value.length === 0) { |
| | | proxy.$modal.msgWarning("è¯·éæ©è¦æå°çæ°æ®"); |
| | | return; |
| | | } |
| | | printData.value = [...selectedRows.value]; |
| | | console.log("æå°æ°æ®:", printData.value); |
| | | printPreviewVisible.value = true; |
| | | }; |
| | | // å é¤ |
| | | 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(() => { |
| | | delPendingStockOut(ids).then(res => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | |
| | | // æ§è¡æå° |
| | | const executePrint = () => { |
| | | console.log("å¼å§æ§è¡æå°ï¼æ°æ®æ¡æ°:", printData.value.length); |
| | | console.log("æå°æ°æ®:", printData.value); |
| | | // æå°åè½ |
| | | const handlePrint = () => { |
| | | if (selectedRows.value.length === 0) { |
| | | proxy.$modal.msgWarning("è¯·éæ©è¦æå°çæ°æ®"); |
| | | return; |
| | | } |
| | | printData.value = [...selectedRows.value]; |
| | | console.log("æå°æ°æ®:", printData.value); |
| | | printPreviewVisible.value = true; |
| | | }; |
| | | |
| | | // å建ä¸ä¸ªæ°çæå°çªå£ |
| | | const printWindow = window.open("", "_blank", "width=800,height=600"); |
| | | // æ§è¡æå° |
| | | const executePrint = () => { |
| | | console.log("å¼å§æ§è¡æå°ï¼æ°æ®æ¡æ°:", printData.value.length); |
| | | console.log("æå°æ°æ®:", printData.value); |
| | | |
| | | // æå»ºæå°å
容 |
| | | let printContent = ` |
| | | <!DOCTYPE html> |
| | | <html> |
| | | <head> |
| | | <meta charset="UTF-8"> |
| | | <title>æå°é¢è§</title> |
| | | <style> |
| | | body { |
| | | margin: 0; |
| | | padding: 0; |
| | | font-family: "SimSun", serif; |
| | | background: white; |
| | | } |
| | | .print-page { |
| | | width: 200mm; |
| | | height: 75mm; |
| | | padding: 10mm; |
| | | padding-left: 20mm; |
| | | background: white; |
| | | box-sizing: border-box; |
| | | page-break-after: always; |
| | | page-break-inside: avoid; |
| | | } |
| | | .print-page:last-child { |
| | | page-break-after: avoid; |
| | | } |
| | | .delivery-note { |
| | | width: 100%; |
| | | height: 100%; |
| | | font-size: 12px; |
| | | line-height: 1.2; |
| | | display: flex; |
| | | flex-direction: column; |
| | | color: #000; |
| | | } |
| | | .header { |
| | | text-align: center; |
| | | margin-bottom: 8px; |
| | | } |
| | | .company-name { |
| | | font-size: 18px; |
| | | font-weight: bold; |
| | | margin-bottom: 4px; |
| | | } |
| | | .document-title { |
| | | font-size: 16px; |
| | | font-weight: bold; |
| | | } |
| | | .info-section { |
| | | margin-bottom: 8px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | .info-row { |
| | | line-height: 20px; |
| | | } |
| | | .label { |
| | | font-weight: bold; |
| | | width: 60px; |
| | | font-size: 12px; |
| | | } |
| | | .value { |
| | | margin-right: 20px; |
| | | min-width: 80px; |
| | | font-size: 12px; |
| | | } |
| | | .table-section { |
| | | margin-bottom: 40px; |
| | | // flex: 0.6; |
| | | } |
| | | .product-table { |
| | | width: 100%; |
| | | border-collapse: collapse; |
| | | border: 1px solid #000; |
| | | } |
| | | .product-table th, .product-table td { |
| | | border: 1px solid #000; |
| | | padding: 6px; |
| | | text-align: center; |
| | | font-size: 12px; |
| | | line-height: 1.4; |
| | | } |
| | | .product-table th { |
| | | font-weight: bold; |
| | | } |
| | | .total-value { |
| | | font-weight: bold; |
| | | } |
| | | .footer-section { |
| | | margin-top: auto; |
| | | } |
| | | .footer-row { |
| | | display: flex; |
| | | margin-bottom: 3px; |
| | | line-height: 22px; |
| | | justify-content: space-between; |
| | | } |
| | | .footer-item { |
| | | display: flex; |
| | | margin-right: 20px; |
| | | } |
| | | .footer-item .label { |
| | | font-weight: bold; |
| | | width: 80px; |
| | | font-size: 12px; |
| | | } |
| | | .footer-item .value { |
| | | min-width: 80px; |
| | | font-size: 12px; |
| | | } |
| | | .address-item .address-value { |
| | | min-width: 200px; |
| | | } |
| | | @media print { |
| | | // å建ä¸ä¸ªæ°çæå°çªå£ |
| | | const printWindow = window.open("", "_blank", "width=800,height=600"); |
| | | |
| | | // æå»ºæå°å
容 |
| | | let printContent = ` |
| | | <!DOCTYPE html> |
| | | <html> |
| | | <head> |
| | | <meta charset="UTF-8"> |
| | | <title>æå°é¢è§</title> |
| | | <style> |
| | | body { |
| | | margin: 0; |
| | | padding: 0; |
| | | font-family: "SimSun", serif; |
| | | background: white; |
| | | } |
| | | .print-page { |
| | | margin: 0; |
| | | padding: 10mm; |
| | | /* padding-left: 20mm; */ |
| | | page-break-inside: avoid; |
| | | page-break-after: always; |
| | | } |
| | | .print-page { |
| | | width: 200mm; |
| | | height: 75mm; |
| | | padding: 10mm; |
| | | padding-left: 20mm; |
| | | background: white; |
| | | box-sizing: border-box; |
| | | page-break-after: always; |
| | | page-break-inside: avoid; |
| | | } |
| | | .print-page:last-child { |
| | | page-break-after: avoid; |
| | | } |
| | | } |
| | | </style> |
| | | </head> |
| | | <body> |
| | | `; |
| | | .delivery-note { |
| | | width: 100%; |
| | | height: 100%; |
| | | font-size: 12px; |
| | | line-height: 1.2; |
| | | display: flex; |
| | | flex-direction: column; |
| | | color: #000; |
| | | } |
| | | .header { |
| | | text-align: center; |
| | | margin-bottom: 8px; |
| | | } |
| | | .company-name { |
| | | font-size: 18px; |
| | | font-weight: bold; |
| | | margin-bottom: 4px; |
| | | } |
| | | .document-title { |
| | | font-size: 16px; |
| | | font-weight: bold; |
| | | } |
| | | .info-section { |
| | | margin-bottom: 8px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | .info-row { |
| | | line-height: 20px; |
| | | } |
| | | .label { |
| | | font-weight: bold; |
| | | width: 60px; |
| | | font-size: 12px; |
| | | } |
| | | .value { |
| | | margin-right: 20px; |
| | | min-width: 80px; |
| | | font-size: 12px; |
| | | } |
| | | .table-section { |
| | | margin-bottom: 40px; |
| | | // flex: 0.6; |
| | | } |
| | | .product-table { |
| | | width: 100%; |
| | | border-collapse: collapse; |
| | | border: 1px solid #000; |
| | | } |
| | | .product-table th, .product-table td { |
| | | border: 1px solid #000; |
| | | padding: 6px; |
| | | text-align: center; |
| | | font-size: 12px; |
| | | line-height: 1.4; |
| | | } |
| | | .product-table th { |
| | | font-weight: bold; |
| | | } |
| | | .total-value { |
| | | font-weight: bold; |
| | | } |
| | | .footer-section { |
| | | margin-top: auto; |
| | | } |
| | | .footer-row { |
| | | display: flex; |
| | | margin-bottom: 3px; |
| | | line-height: 22px; |
| | | justify-content: space-between; |
| | | } |
| | | .footer-item { |
| | | display: flex; |
| | | margin-right: 20px; |
| | | } |
| | | .footer-item .label { |
| | | font-weight: bold; |
| | | width: 80px; |
| | | font-size: 12px; |
| | | } |
| | | .footer-item .value { |
| | | min-width: 80px; |
| | | font-size: 12px; |
| | | } |
| | | .address-item .address-value { |
| | | min-width: 200px; |
| | | } |
| | | @media print { |
| | | body { |
| | | margin: 0; |
| | | padding: 0; |
| | | } |
| | | .print-page { |
| | | margin: 0; |
| | | padding: 10mm; |
| | | /* padding-left: 20mm; */ |
| | | page-break-inside: avoid; |
| | | page-break-after: always; |
| | | } |
| | | .print-page:last-child { |
| | | page-break-after: avoid; |
| | | } |
| | | } |
| | | </style> |
| | | </head> |
| | | <body> |
| | | `; |
| | | |
| | | // ä¸ºæ¯æ¡æ°æ®çææå°é¡µé¢ |
| | | printData.value.forEach((item, index) => { |
| | | printContent += ` |
| | | <div class="print-page"> |
| | | <div class="delivery-note"> |
| | | <div class="header"> |
| | | <div class="document-title">é¶å®åè´§å</div> |
| | | </div> |
| | | |
| | | <div class="info-section"> |
| | | <div class="info-row"> |
| | | <div> |
| | | <span class="label">åè´§æ¥æï¼</span> |
| | | <span class="value">${formatDate(item.createTime)}</span> |
| | | // ä¸ºæ¯æ¡æ°æ®çææå°é¡µé¢ |
| | | printData.value.forEach((item, index) => { |
| | | printContent += ` |
| | | <div class="print-page"> |
| | | <div class="delivery-note"> |
| | | <div class="header"> |
| | | <div class="document-title">é¶å®åè´§å</div> |
| | | </div> |
| | | |
| | | <div class="info-section"> |
| | | <div class="info-row"> |
| | | <div> |
| | | <span class="label">åè´§æ¥æï¼</span> |
| | | <span class="value">${formatDate(item.createTime)}</span> |
| | | </div> |
| | | <div> |
| | | <span class="label">客æ·åç§°ï¼</span> |
| | | <span class="value">${item.supplierName}</span> |
| | | </div> |
| | | </div> |
| | | <div> |
| | | <span class="label">客æ·åç§°ï¼</span> |
| | | <span class="value">${item.supplierName}</span> |
| | | <div class="info-row"> |
| | | <span class="label">åå·ï¼</span> |
| | | <span class="value">${item.code || ""}</span> |
| | | </div> |
| | | </div> |
| | | <div class="info-row"> |
| | | <span class="label">åå·ï¼</span> |
| | | <span class="value">${item.code || ""}</span> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="table-section"> |
| | | <table class="product-table"> |
| | | <thead> |
| | | <tr> |
| | | <th>产ååç§°</th> |
| | | <th>è§æ ¼åå·</th> |
| | | <th>åä½</th> |
| | | <th>åä»·</th> |
| | | <th>é¶å®æ°é</th> |
| | | <th>é¶å®éé¢</th> |
| | | </tr> |
| | | </thead> |
| | | <tbody> |
| | | <tr> |
| | | <td>${item.productName || "ç ç°ç "}</td> |
| | | <td>${item.model || "æ å"}</td> |
| | | <td>${item.unit || "å"}</td> |
| | | <td>${item.taxInclusiveUnitPrice || "0"}</td> |
| | | <td>${item.inboundNum || "2000"}</td> |
| | | <td>${item.taxInclusiveTotalPrice || "0"}</td> |
| | | </tr> |
| | | </tbody> |
| | | <tfoot> |
| | | <tr> |
| | | <td class="label">å计</td> |
| | | <td class="total-value"></td> |
| | | <td class="total-value"></td> |
| | | <td class="total-value"></td> |
| | | <td class="total-value">${item.inboundNum || "2000"}</td> |
| | | <td class="total-value">${ |
| | | item.taxInclusiveTotalPrice || "0" |
| | | }</td> |
| | | </tr> |
| | | </tfoot> |
| | | </table> |
| | | </div> |
| | | |
| | | <div class="footer-section"> |
| | | <div class="footer-row"> |
| | | <div class="footer-item"> |
| | | <span class="label">æ¶è´§çµè¯ï¼</span> |
| | | <span class="value"></span> |
| | | </div> |
| | | <div class="footer-item"> |
| | | <span class="label">æ¶è´§äººï¼</span> |
| | | <span class="value"></span> |
| | | </div> |
| | | <div class="footer-item address-item"> |
| | | <span class="label">æ¶è´§å°åï¼</span> |
| | | <span class="value address-value"></span> |
| | | </div> |
| | | <div class="table-section"> |
| | | <table class="product-table"> |
| | | <thead> |
| | | <tr> |
| | | <th>产ååç§°</th> |
| | | <th>è§æ ¼åå·</th> |
| | | <th>åä½</th> |
| | | <th>åä»·</th> |
| | | <th>é¶å®æ°é</th> |
| | | <th>é¶å®éé¢</th> |
| | | </tr> |
| | | </thead> |
| | | <tbody> |
| | | <tr> |
| | | <td>${item.productName || "ç ç°ç "}</td> |
| | | <td>${item.model || "æ å"}</td> |
| | | <td>${item.unit || "å"}</td> |
| | | <td>${item.taxInclusiveUnitPrice || "0"}</td> |
| | | <td>${item.inboundNum || "2000"}</td> |
| | | <td>${item.taxInclusiveTotalPrice || "0"}</td> |
| | | </tr> |
| | | </tbody> |
| | | <tfoot> |
| | | <tr> |
| | | <td class="label">å计</td> |
| | | <td class="total-value"></td> |
| | | <td class="total-value"></td> |
| | | <td class="total-value"></td> |
| | | <td class="total-value">${item.inboundNum || "2000"}</td> |
| | | <td class="total-value">${ |
| | | item.taxInclusiveTotalPrice || "0" |
| | | }</td> |
| | | </tr> |
| | | </tfoot> |
| | | </table> |
| | | </div> |
| | | <div class="footer-row"> |
| | | <div class="footer-item"> |
| | | <span class="label">æä½åï¼</span> |
| | | <span class="value">${userStore.nickName || "æå¼å"}</span> |
| | | |
| | | <div class="footer-section"> |
| | | <div class="footer-row"> |
| | | <div class="footer-item"> |
| | | <span class="label">æ¶è´§çµè¯ï¼</span> |
| | | <span class="value"></span> |
| | | </div> |
| | | <div class="footer-item"> |
| | | <span class="label">æ¶è´§äººï¼</span> |
| | | <span class="value"></span> |
| | | </div> |
| | | <div class="footer-item address-item"> |
| | | <span class="label">æ¶è´§å°åï¼</span> |
| | | <span class="value address-value"></span> |
| | | </div> |
| | | </div> |
| | | <div class="footer-item"> |
| | | <span class="label">æå°æ¥æï¼</span> |
| | | <span class="value">${formatDateTime(new Date())}</span> |
| | | <div class="footer-row"> |
| | | <div class="footer-item"> |
| | | <span class="label">æä½åï¼</span> |
| | | <span class="value">${userStore.nickName || "æå¼å"}</span> |
| | | </div> |
| | | <div class="footer-item"> |
| | | <span class="label">æå°æ¥æï¼</span> |
| | | <span class="value">${formatDateTime(new Date())}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | `; |
| | | }); |
| | | |
| | | printContent += ` |
| | | </body> |
| | | </html> |
| | | `; |
| | | |
| | | // åå
¥å
容尿°çªå£ |
| | | printWindow.document.write(printContent); |
| | | printWindow.document.close(); |
| | | |
| | | // çå¾
å
容å è½½å®æåæå° |
| | | printWindow.onload = () => { |
| | | setTimeout(() => { |
| | | printWindow.print(); |
| | | printWindow.close(); |
| | | printPreviewVisible.value = false; |
| | | }, 500); |
| | | }; |
| | | }; |
| | | |
| | | // æ ¼å¼åæ¥æ |
| | | const formatDate = dateString => { |
| | | if (!dateString) return getCurrentDate(); |
| | | const date = new Date(dateString); |
| | | const year = date.getFullYear(); |
| | | const month = String(date.getMonth() + 1).padStart(2, "0"); |
| | | const day = String(date.getDate()).padStart(2, "0"); |
| | | return `${year}/${month}/${day}`; |
| | | }; |
| | | |
| | | // æ ¼å¼åæ¥ææ¶é´ |
| | | const formatDateTime = date => { |
| | | const year = date.getFullYear(); |
| | | const month = String(date.getMonth() + 1).padStart(2, "0"); |
| | | const day = String(date.getDate()).padStart(2, "0"); |
| | | const hours = String(date.getHours()).padStart(2, "0"); |
| | | const minutes = String(date.getMinutes()).padStart(2, "0"); |
| | | const seconds = String(date.getSeconds()).padStart(2, "0"); |
| | | return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`; |
| | | }; |
| | | onMounted(() => { |
| | | getList(); |
| | | fetchStockRecordTypeOptions(); |
| | | }); |
| | | |
| | | printContent += ` |
| | | </body> |
| | | </html> |
| | | `; |
| | | |
| | | // åå
¥å
容尿°çªå£ |
| | | printWindow.document.write(printContent); |
| | | printWindow.document.close(); |
| | | |
| | | // çå¾
å
容å è½½å®æåæå° |
| | | printWindow.onload = () => { |
| | | setTimeout(() => { |
| | | printWindow.print(); |
| | | printWindow.close(); |
| | | printPreviewVisible.value = false; |
| | | }, 500); |
| | | }; |
| | | }; |
| | | |
| | | // æ ¼å¼åæ¥æ |
| | | const formatDate = (dateString) => { |
| | | if (!dateString) return getCurrentDate(); |
| | | const date = new Date(dateString); |
| | | const year = date.getFullYear(); |
| | | const month = String(date.getMonth() + 1).padStart(2, "0"); |
| | | const day = String(date.getDate()).padStart(2, "0"); |
| | | return `${year}/${month}/${day}`; |
| | | }; |
| | | |
| | | // æ ¼å¼åæ¥ææ¶é´ |
| | | const formatDateTime = (date) => { |
| | | const year = date.getFullYear(); |
| | | const month = String(date.getMonth() + 1).padStart(2, "0"); |
| | | const day = String(date.getDate()).padStart(2, "0"); |
| | | const hours = String(date.getHours()).padStart(2, "0"); |
| | | const minutes = String(date.getMinutes()).padStart(2, "0"); |
| | | const seconds = String(date.getSeconds()).padStart(2, "0"); |
| | | return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`; |
| | | }; |
| | | onMounted(() => { |
| | | getList(); |
| | | fetchStockRecordTypeOptions(); |
| | | }); |
| | | |
| | | watch( |
| | | () => props.topParentProductId, |
| | | () => { |
| | | page.current = 1; |
| | | getList(); |
| | | } |
| | | ); |
| | | watch( |
| | | () => props.topParentProductId, |
| | | () => { |
| | | page.current = 1; |
| | | getList(); |
| | | } |
| | | ); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .print-preview-dialog { |
| | | .el-dialog__body { |
| | | padding: 0; |
| | | max-height: 80vh; |
| | | overflow-y: auto; |
| | | } |
| | | } |
| | | |
| | | .print-preview-container { |
| | | .print-preview-header { |
| | | padding: 15px; |
| | | border-bottom: 1px solid #e4e7ed; |
| | | text-align: center; |
| | | |
| | | .el-button { |
| | | margin: 0 10px; |
| | | .print-preview-dialog { |
| | | .el-dialog__body { |
| | | padding: 0; |
| | | max-height: 80vh; |
| | | overflow-y: auto; |
| | | } |
| | | } |
| | | |
| | | .print-preview-content { |
| | | padding: 20px; |
| | | background-color: #f5f5f5; |
| | | min-height: 400px; |
| | | } |
| | | } |
| | | |
| | | .print-page { |
| | | width: 220mm; |
| | | height: 90mm; |
| | | padding: 10mm; |
| | | margin: 0 auto; |
| | | background: white; |
| | | box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); |
| | | margin-bottom: 10px; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | .delivery-note { |
| | | width: 100%; |
| | | height: 100%; |
| | | font-family: "SimSun", serif; |
| | | font-size: 10px; |
| | | line-height: 1.2; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .header { |
| | | text-align: center; |
| | | margin-bottom: 8px; |
| | | |
| | | .company-name { |
| | | font-size: 18px; |
| | | font-weight: bold; |
| | | margin-bottom: 4px; |
| | | } |
| | | |
| | | .document-title { |
| | | font-size: 16px; |
| | | font-weight: bold; |
| | | } |
| | | } |
| | | |
| | | .info-section { |
| | | margin-bottom: 8px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | |
| | | .info-row { |
| | | line-height: 20px; |
| | | |
| | | .label { |
| | | font-weight: bold; |
| | | width: 60px; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .value { |
| | | margin-right: 20px; |
| | | min-width: 80px; |
| | | font-size: 14px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .table-section { |
| | | margin-bottom: 4px; |
| | | flex: 1; |
| | | |
| | | .product-table { |
| | | width: 100%; |
| | | border-collapse: collapse; |
| | | border: 1px solid #000; |
| | | |
| | | th, |
| | | td { |
| | | border: 1px solid #000; |
| | | padding: 6px; |
| | | .print-preview-container { |
| | | .print-preview-header { |
| | | padding: 15px; |
| | | border-bottom: 1px solid #e4e7ed; |
| | | text-align: center; |
| | | font-size: 14px; |
| | | line-height: 1.4; |
| | | |
| | | .el-button { |
| | | margin: 0 10px; |
| | | } |
| | | } |
| | | |
| | | th { |
| | | .print-preview-content { |
| | | padding: 20px; |
| | | background-color: #f5f5f5; |
| | | min-height: 400px; |
| | | } |
| | | } |
| | | |
| | | .print-page { |
| | | width: 220mm; |
| | | height: 90mm; |
| | | padding: 10mm; |
| | | margin: 0 auto; |
| | | background: white; |
| | | box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); |
| | | margin-bottom: 10px; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | .delivery-note { |
| | | width: 100%; |
| | | height: 100%; |
| | | font-family: "SimSun", serif; |
| | | font-size: 10px; |
| | | line-height: 1.2; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .header { |
| | | text-align: center; |
| | | margin-bottom: 8px; |
| | | |
| | | .company-name { |
| | | font-size: 18px; |
| | | font-weight: bold; |
| | | margin-bottom: 4px; |
| | | } |
| | | |
| | | .total-label { |
| | | text-align: right; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .total-value { |
| | | .document-title { |
| | | font-size: 16px; |
| | | font-weight: bold; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .footer-section { |
| | | .footer-row { |
| | | .info-section { |
| | | margin-bottom: 8px; |
| | | display: flex; |
| | | margin-bottom: 3px; |
| | | line-height: 20px; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | |
| | | .footer-item { |
| | | display: flex; |
| | | margin-right: 20px; |
| | | .info-row { |
| | | line-height: 20px; |
| | | |
| | | .label { |
| | | font-weight: bold; |
| | | width: 80px; |
| | | width: 60px; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .value { |
| | | margin-right: 20px; |
| | | min-width: 80px; |
| | | font-size: 14px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | &.address-item { |
| | | .address-value { |
| | | min-width: 200px; |
| | | .table-section { |
| | | margin-bottom: 4px; |
| | | flex: 1; |
| | | |
| | | .product-table { |
| | | width: 100%; |
| | | border-collapse: collapse; |
| | | border: 1px solid #000; |
| | | |
| | | th, |
| | | td { |
| | | border: 1px solid #000; |
| | | padding: 6px; |
| | | text-align: center; |
| | | font-size: 14px; |
| | | line-height: 1.4; |
| | | } |
| | | |
| | | th { |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .total-label { |
| | | text-align: right; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .total-value { |
| | | font-weight: bold; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .footer-section { |
| | | .footer-row { |
| | | display: flex; |
| | | margin-bottom: 3px; |
| | | line-height: 20px; |
| | | justify-content: space-between; |
| | | |
| | | .footer-item { |
| | | display: flex; |
| | | margin-right: 20px; |
| | | |
| | | .label { |
| | | font-weight: bold; |
| | | width: 80px; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .value { |
| | | min-width: 80px; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | &.address-item { |
| | | .address-value { |
| | | min-width: 200px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | @media print { |
| | | .app-container { |
| | | display: none; |
| | | @media print { |
| | | .app-container { |
| | | display: none; |
| | | } |
| | | |
| | | .print-page { |
| | | box-shadow: none; |
| | | margin: 0; |
| | | padding: 10mm; |
| | | padding-left: 20mm; |
| | | page-break-inside: avoid; |
| | | page-break-after: always; |
| | | } |
| | | .print-page:last-child { |
| | | page-break-after: avoid; |
| | | } |
| | | } |
| | | |
| | | .print-page { |
| | | box-shadow: none; |
| | | margin: 0; |
| | | padding: 10mm; |
| | | padding-left: 20mm; |
| | | page-break-inside: avoid; |
| | | page-break-after: always; |
| | | .actions { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | margin-bottom: 10px; |
| | | } |
| | | .print-page:last-child { |
| | | page-break-after: avoid; |
| | | } |
| | | } |
| | | |
| | | .actions { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | margin-bottom: 10px; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <div> |
| | | <div class="search_form" style="margin-bottom: 10px;"> |
| | | <el-form |
| | | ref="searchFormRef" |
| | | :model="searchForm" |
| | | class="demo-form-inline" |
| | | > |
| | | <div class="search_form" |
| | | style="margin-bottom: 10px;"> |
| | | <el-form ref="searchFormRef" |
| | | :model="searchForm" |
| | | class="demo-form-inline"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="4"> |
| | | <el-form-item label="å
¥åºæ¥æ" prop="timeStr"> |
| | | <el-form-item label="å
¥åºæ¥æ" |
| | | prop="timeStr"> |
| | | <el-date-picker v-model="searchForm.timeStr" |
| | | type="date" |
| | | placeholder="è¯·éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable/> |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="4"> |
| | | <el-form-item label="产å大类" prop="productName"> |
| | | <el-form-item label="产å大类" |
| | | prop="productName"> |
| | | <el-input v-model="searchForm.productName" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | clearable/> |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | |
| | | <el-col :span="4"> |
| | | <el-form-item label="产åè§æ ¼" prop="model"> |
| | | <el-form-item label="è§æ ¼åå·" |
| | | prop="model"> |
| | | <el-input v-model="searchForm.model" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | clearable/> |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="4"> |
| | | <el-form-item label="æ¹å·" prop="batchNo"> |
| | | <el-form-item label="æ¹å·" |
| | | prop="batchNo"> |
| | | <el-input v-model="searchForm.batchNo" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | clearable/> |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="4"> |
| | | <el-form-item label="æ¥æº" prop="recordType"> |
| | | <el-form-item label="æ¥æº" |
| | | prop="recordType"> |
| | | <el-select v-model="searchForm.recordType" |
| | | style="width: 240px" |
| | | placeholder="è¯·éæ©" |
| | |
| | | <el-option v-for="item in stockRecordTypeOptions" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value"/> |
| | | :value="item.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <!-- æé® --> |
| | | <el-col :span="4"> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="getList"> |
| | | <el-button type="primary" |
| | | @click="getList"> |
| | | æç´¢ |
| | | </el-button> |
| | | |
| | | <el-button @click="resetSearch"> |
| | | éç½® |
| | | </el-button> |
| | |
| | | <el-table-column align="center" |
| | | type="selection" |
| | | :selectable="isRowSelectable" |
| | | width="55"/> |
| | | width="55" /> |
| | | <el-table-column align="center" |
| | | label="åºå·" |
| | | type="index" |
| | | width="60"/> |
| | | width="60" /> |
| | | <el-table-column label="å
¥åºæ¹æ¬¡" |
| | | prop="inboundBatches" |
| | | width="200" |
| | | show-overflow-tooltip/> |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="å
¥åºæ¶é´" |
| | | prop="createTime" |
| | | show-overflow-tooltip/> |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="产å大类" |
| | | prop="productName" |
| | | show-overflow-tooltip/> |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="è§æ ¼åå·" |
| | | prop="model" |
| | | show-overflow-tooltip/> |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="æ¹å·" |
| | | prop="batchNo" |
| | | show-overflow-tooltip/> |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="åä½" |
| | | prop="unit" |
| | | show-overflow-tooltip/> |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="å
¥åºæ°é" |
| | | prop="stockInNum" |
| | | show-overflow-tooltip/> |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="å
¥åºäºº" |
| | | prop="createBy" |
| | | show-overflow-tooltip/> |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="æ¥æº" |
| | | prop="recordType" |
| | | show-overflow-tooltip> |
| | |
| | | {{ getRecordType(scope.row.recordType) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | v-if="showSourceOrderNoColumn" |
| | | label="æºåå·" |
| | | width="150" |
| | | prop="sourceOrderNo" |
| | | show-overflow-tooltip> |
| | | <el-table-column v-if="showSourceOrderNoColumn" |
| | | label="æºåå·" |
| | | width="150" |
| | | prop="sourceOrderNo" |
| | | show-overflow-tooltip> |
| | | <template #default="scope"> |
| | | {{ formatSourceOrderNo(scope.row?.sourceOrderNo) }} |
| | | </template> |
| | |
| | | prop="approvalStatus" |
| | | show-overflow-tooltip> |
| | | <template #default="scope"> |
| | | <el-tag :type="getApprovalStatusTagType(scope.row.approvalStatus)" size="small"> |
| | | <el-tag :type="getApprovalStatusTagType(scope.row.approvalStatus)" |
| | | size="small"> |
| | | {{ getApprovalStatusLabel(scope.row.approvalStatus) }} |
| | | </el-tag> |
| | | </template> |
| | |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | :page="page.current" |
| | | :limit="page.size" |
| | | @pagination="pageProductChange"/> |
| | | @pagination="pageProductChange" /> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import pagination from "@/components/PIMTable/Pagination.vue"; |
| | | import { |
| | | ref, |
| | | reactive, |
| | | toRefs, |
| | | computed, |
| | | onMounted, |
| | | getCurrentInstance, |
| | | } from "vue"; |
| | | import {ElMessageBox} from "element-plus"; |
| | | import { |
| | | getStockInRecordListPage, |
| | | batchDeletePendingStockInRecords, |
| | | batchApproveStockInRecords, |
| | | batchUnapproveStockInRecords, |
| | | } from "@/api/inventoryManagement/stockInRecord.js"; |
| | | import { |
| | | findAllQualifiedStockInRecordTypeOptions, |
| | | // findAllUnQualifiedStockInRecordTypeOptions, |
| | | } from "@/api/basicData/enum.js"; |
| | | import pagination from "@/components/PIMTable/Pagination.vue"; |
| | | import { |
| | | ref, |
| | | reactive, |
| | | toRefs, |
| | | computed, |
| | | onMounted, |
| | | getCurrentInstance, |
| | | } from "vue"; |
| | | import { ElMessageBox } from "element-plus"; |
| | | import { |
| | | getStockInRecordListPage, |
| | | batchDeletePendingStockInRecords, |
| | | batchApproveStockInRecords, |
| | | batchUnapproveStockInRecords, |
| | | } from "@/api/inventoryManagement/stockInRecord.js"; |
| | | import { |
| | | findAllQualifiedStockInRecordTypeOptions, |
| | | // findAllUnQualifiedStockInRecordTypeOptions, |
| | | } from "@/api/basicData/enum.js"; |
| | | |
| | | const {proxy} = getCurrentInstance(); |
| | | const { proxy } = getCurrentInstance(); |
| | | |
| | | const props = defineProps({ |
| | | type: { |
| | | type: String, |
| | | required: true, |
| | | default: '0' |
| | | }, |
| | | topParentProductId: { |
| | | type: [String, Number], |
| | | default: undefined |
| | | } |
| | | }) |
| | | const props = defineProps({ |
| | | type: { |
| | | type: String, |
| | | required: true, |
| | | default: "0", |
| | | }, |
| | | topParentProductId: { |
| | | type: [String, Number], |
| | | default: undefined, |
| | | }, |
| | | }); |
| | | |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const tableLoading = ref(false); |
| | | // æ¥æºç±»åé项 |
| | | const stockRecordTypeOptions = ref([]); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 10, |
| | | }); |
| | | const total = ref(0); |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const tableLoading = ref(false); |
| | | // æ¥æºç±»åé项 |
| | | const stockRecordTypeOptions = ref([]); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 10, |
| | | }); |
| | | const total = ref(0); |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | productName: "", |
| | | batchNo: "", |
| | | model: "", |
| | | timeStr: "", |
| | | recordType: "", |
| | | }, |
| | | }); |
| | | const {searchForm} = toRefs(data); |
| | | const searchFormRef = ref(null); |
| | | const data = reactive({ |
| | | searchForm: { |
| | | productName: "", |
| | | batchNo: "", |
| | | model: "", |
| | | timeStr: "", |
| | | recordType: "", |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | const searchFormRef = ref(null); |
| | | |
| | | const resetSearch = () => { |
| | | searchFormRef.value?.resetFields(); |
| | | page.current = 1; |
| | | getList(); |
| | | } |
| | | const resetSearch = () => { |
| | | searchFormRef.value?.resetFields(); |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | const getRecordType = (recordType) => { |
| | | return stockRecordTypeOptions.value.find(item => item.value === recordType)?.label || '' |
| | | } |
| | | const getRecordType = recordType => { |
| | | return ( |
| | | stockRecordTypeOptions.value.find(item => item.value === recordType) |
| | | ?.label || "" |
| | | ); |
| | | }; |
| | | |
| | | const approvalStatusLabelMap = { |
| | | 0: "å¾
审æ¹", |
| | | 1: "éè¿", |
| | | 2: "驳å", |
| | | pending: "å¾
审æ¹", |
| | | approved: "éè¿", |
| | | rejected: "驳å", |
| | | PENDING: "å¾
审æ¹", |
| | | APPROVED: "éè¿", |
| | | REJECTED: "驳å", |
| | | }; |
| | | approvalStatusLabelMap[3] = "å¾
确认"; |
| | | const approvalStatusLabelMap = { |
| | | 0: "å¾
审æ¹", |
| | | 1: "éè¿", |
| | | 2: "驳å", |
| | | pending: "å¾
审æ¹", |
| | | approved: "éè¿", |
| | | rejected: "驳å", |
| | | PENDING: "å¾
审æ¹", |
| | | APPROVED: "éè¿", |
| | | REJECTED: "驳å", |
| | | }; |
| | | approvalStatusLabelMap[3] = "å¾
确认"; |
| | | |
| | | const getApprovalStatusLabel = (status) => { |
| | | if (status === null || status === undefined || status === "") { |
| | | return "å¾
审æ¹"; |
| | | } |
| | | return approvalStatusLabelMap[status] || "å¾
审æ¹"; |
| | | }; |
| | | const getApprovalStatusLabel = status => { |
| | | if (status === null || status === undefined || status === "") { |
| | | return "å¾
审æ¹"; |
| | | } |
| | | return approvalStatusLabelMap[status] || "å¾
审æ¹"; |
| | | }; |
| | | |
| | | // éè¿/驳ååºå®è²ï¼å
¶ä½ï¼å«å¾
审æ¹ã空å¼ãæªæ å°ä½ææ¡ä¸ºå¾
审æ¹ï¼ç»ä¸ç¨ warning é¢è¦è² |
| | | const getApprovalStatusTagType = (status) => { |
| | | if (status === 1 || status === "1" || status === "approved" || status === "APPROVED") return "success"; |
| | | if (status === 2 || status === "2" || status === "rejected" || status === "REJECTED") return "danger"; |
| | | return "warning"; |
| | | }; |
| | | // éè¿/驳ååºå®è²ï¼å
¶ä½ï¼å«å¾
审æ¹ã空å¼ãæªæ å°ä½ææ¡ä¸ºå¾
审æ¹ï¼ç»ä¸ç¨ warning é¢è¦è² |
| | | const getApprovalStatusTagType = status => { |
| | | if ( |
| | | status === 1 || |
| | | status === "1" || |
| | | status === "approved" || |
| | | status === "APPROVED" |
| | | ) |
| | | return "success"; |
| | | if ( |
| | | status === 2 || |
| | | status === "2" || |
| | | status === "rejected" || |
| | | status === "REJECTED" |
| | | ) |
| | | return "danger"; |
| | | return "warning"; |
| | | }; |
| | | |
| | | const isPendingApproval = status => { |
| | | return status === 0 || status === "0" || status === "pending" || status === "PENDING" || status === null || status === undefined || status === ""; |
| | | }; |
| | | const isPendingApproval = status => { |
| | | return ( |
| | | status === 0 || |
| | | status === "0" || |
| | | status === "pending" || |
| | | status === "PENDING" || |
| | | status === null || |
| | | status === undefined || |
| | | status === "" |
| | | ); |
| | | }; |
| | | |
| | | const isRejectedApproval = status => { |
| | | return status === 2 || status === "2" || status === "rejected" || status === "REJECTED"; |
| | | }; |
| | | const isRejectedApproval = status => { |
| | | return ( |
| | | status === 2 || |
| | | status === "2" || |
| | | status === "rejected" || |
| | | status === "REJECTED" |
| | | ); |
| | | }; |
| | | |
| | | const isRowSelectable = row => { |
| | | return isPendingApproval(row?.approvalStatus) || isRejectedApproval(row?.approvalStatus); |
| | | }; |
| | | const isRowSelectable = row => { |
| | | return ( |
| | | isPendingApproval(row?.approvalStatus) || |
| | | isRejectedApproval(row?.approvalStatus) |
| | | ); |
| | | }; |
| | | |
| | | const canBatchApprove = computed(() => { |
| | | return selectedRows.value.length > 0 |
| | | && selectedRows.value.every(row => isPendingApproval(row.approvalStatus)); |
| | | }); |
| | | const canBatchApprove = computed(() => { |
| | | return ( |
| | | selectedRows.value.length > 0 && |
| | | selectedRows.value.every(row => isPendingApproval(row.approvalStatus)) |
| | | ); |
| | | }); |
| | | |
| | | const canReverseApprove = computed(() => { |
| | | return selectedRows.value.length > 0 |
| | | && selectedRows.value.every(row => isRejectedApproval(row.approvalStatus)); |
| | | }); |
| | | const canReverseApprove = computed(() => { |
| | | return ( |
| | | selectedRows.value.length > 0 && |
| | | selectedRows.value.every(row => isRejectedApproval(row.approvalStatus)) |
| | | ); |
| | | }); |
| | | |
| | | const canDelete = computed(() => canBatchApprove.value); |
| | | const showSourceOrderNoColumn = computed(() => { |
| | | const topParentProductId = Number(props.topParentProductId); |
| | | return topParentProductId === 276 || topParentProductId === 278; |
| | | }); |
| | | const canDelete = computed(() => canBatchApprove.value); |
| | | const showSourceOrderNoColumn = computed(() => { |
| | | const topParentProductId = Number(props.topParentProductId); |
| | | return topParentProductId === 276 || topParentProductId === 278; |
| | | }); |
| | | |
| | | const formatSourceOrderNo = (value) => { |
| | | const text = String(value ?? "").trim(); |
| | | return text || "--"; |
| | | }; |
| | | const formatSourceOrderNo = value => { |
| | | const text = String(value ?? "").trim(); |
| | | return text || "--"; |
| | | }; |
| | | |
| | | const pageProductChange = obj => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const pageProductChange = obj => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | getStockInRecordListPage(Object.assign({}, {...searchForm.value, ...page, topParentProductId: props.topParentProductId})) |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | getStockInRecordListPage( |
| | | Object.assign( |
| | | {}, |
| | | { |
| | | ...searchForm.value, |
| | | ...page, |
| | | topParentProductId: props.topParentProductId, |
| | | } |
| | | ) |
| | | ) |
| | | .then(res => { |
| | | tableData.value = res.data.records; |
| | | total.value = res.data.total || 0; |
| | | }).finally(() => { |
| | | tableLoading.value = false; |
| | | }) |
| | | }; |
| | | }) |
| | | .finally(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | // è·åæ¥æºç±»åé项 |
| | | const fetchStockRecordTypeOptions = () => { |
| | | if (props.type === '0') { |
| | | findAllQualifiedStockInRecordTypeOptions() |
| | | .then(res => { |
| | | stockRecordTypeOptions.value = res.data; |
| | | }) |
| | | return |
| | | } |
| | | // findAllUnQualifiedStockInRecordTypeOptions() |
| | | // .then(res => { |
| | | // stockRecordTypeOptions.value = res.data; |
| | | // }) |
| | | } |
| | | // è·åæ¥æºç±»åé项 |
| | | const fetchStockRecordTypeOptions = () => { |
| | | if (props.type === "0") { |
| | | findAllQualifiedStockInRecordTypeOptions().then(res => { |
| | | stockRecordTypeOptions.value = res.data; |
| | | }); |
| | | return; |
| | | } |
| | | // findAllUnQualifiedStockInRecordTypeOptions() |
| | | // .then(res => { |
| | | // stockRecordTypeOptions.value = res.data; |
| | | // }) |
| | | }; |
| | | |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = selection => { |
| | | selectedRows.value = selection.filter(item => item.id && isRowSelectable(item)); |
| | | }; |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = selection => { |
| | | selectedRows.value = selection.filter( |
| | | item => item.id && isRowSelectable(item) |
| | | ); |
| | | }; |
| | | |
| | | const expandedRowKeys = ref([]); |
| | | const expandedRowKeys = ref([]); |
| | | |
| | | const handleReverseApprove = () => { |
| | | if (!canReverseApprove.value) { |
| | | proxy.$modal.msgWarning("è¯·éæ©å·²é©³åçæ°æ®"); |
| | | return; |
| | | } |
| | | const ids = selectedRows.value.map(item => item.id); |
| | | ElMessageBox.confirm("å审åè®°å½å°æ¢å¤ä¸ºå¾
审æ¹ç¶æï¼æ¯å¦ç¡®è®¤å审ï¼", "å审", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | const handleReverseApprove = () => { |
| | | if (!canReverseApprove.value) { |
| | | proxy.$modal.msgWarning("è¯·éæ©å·²é©³åçæ°æ®"); |
| | | return; |
| | | } |
| | | const ids = selectedRows.value.map(item => item.id); |
| | | ElMessageBox.confirm("å审åè®°å½å°æ¢å¤ä¸ºå¾
审æ¹ç¶æï¼æ¯å¦ç¡®è®¤å审ï¼", "å审", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | batchUnapproveStockInRecords({ids}) |
| | | .then(() => { |
| | | proxy.$modal.msgSuccess("å审æå"); |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msgError("å审失败"); |
| | | }); |
| | | batchUnapproveStockInRecords({ ids }) |
| | | .then(() => { |
| | | proxy.$modal.msgSuccess("å审æå"); |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msgError("å审失败"); |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | }; |
| | | |
| | | const handleBatchApprove = () => { |
| | | if (!canBatchApprove.value) { |
| | | proxy.$modal.msgWarning("è¯·éæ©å¾
审æ¹çæ°æ®"); |
| | | return; |
| | | } |
| | | const ids = selectedRows.value.map(item => item.id); |
| | | ElMessageBox.confirm("è¯·éæ©å®¡æ¹ç»æ", "审æ¹", { |
| | | confirmButtonText: "éè¿", |
| | | cancelButtonText: "驳å", |
| | | type: "warning", |
| | | distinguishCancelAndClose: true, |
| | | }) |
| | | const handleBatchApprove = () => { |
| | | if (!canBatchApprove.value) { |
| | | proxy.$modal.msgWarning("è¯·éæ©å¾
审æ¹çæ°æ®"); |
| | | return; |
| | | } |
| | | const ids = selectedRows.value.map(item => item.id); |
| | | ElMessageBox.confirm("è¯·éæ©å®¡æ¹ç»æ", "审æ¹", { |
| | | confirmButtonText: "éè¿", |
| | | cancelButtonText: "驳å", |
| | | type: "warning", |
| | | distinguishCancelAndClose: true, |
| | | }) |
| | | .then(() => { |
| | | batchApproveStockInRecords({ids, approvalStatus: 1}) |
| | | batchApproveStockInRecords({ ids, approvalStatus: 1 }) |
| | | .then(() => { |
| | | proxy.$modal.msgSuccess("审æ¹éè¿æå"); |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msgError("审æ¹éè¿å¤±è´¥"); |
| | | }); |
| | | }) |
| | | .catch(action => { |
| | | if (action === "cancel") { |
| | | batchApproveStockInRecords({ ids, approvalStatus: 2 }) |
| | | .then(() => { |
| | | proxy.$modal.msgSuccess("审æ¹éè¿æå"); |
| | | proxy.$modal.msgSuccess("审æ¹é©³åæå"); |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msgError("审æ¹éè¿å¤±è´¥"); |
| | | proxy.$modal.msgError("审æ¹é©³å失败"); |
| | | }); |
| | | }) |
| | | .catch((action) => { |
| | | if (action === "cancel") { |
| | | batchApproveStockInRecords({ids, approvalStatus: 2}) |
| | | .then(() => { |
| | | proxy.$modal.msgSuccess("审æ¹é©³åæå"); |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msgError("审æ¹é©³å失败"); |
| | | }); |
| | | return; |
| | | } |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | }; |
| | | |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | // æ ¹æ®ä¸åç tab ç±»åè°ç¨ä¸åçå¯¼åºæ¥å£ |
| | | proxy.download("/stockInRecord/exportStockInRecord", {type: props.type}, props.type === '0' ? "åæ ¼å
¥åº.xlsx" : "ä¸åæ ¼å
¥åº.xlsx"); |
| | | proxy.download( |
| | | "/stockInRecord/exportStockInRecord", |
| | | { type: props.type }, |
| | | props.type === "0" ? "åæ ¼å
¥åº.xlsx" : "ä¸åæ ¼å
¥åº.xlsx" |
| | | ); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | }; |
| | | |
| | | // å é¤ |
| | | const handleDelete = () => { |
| | | if (!canDelete.value) { |
| | | proxy.$modal.msgWarning("è¯·éæ©å¾
审æ¹çæ°æ®"); |
| | | return; |
| | | } |
| | | const ids = selectedRows.value.map(item => item.id); |
| | | // å é¤ |
| | | const handleDelete = () => { |
| | | if (!canDelete.value) { |
| | | proxy.$modal.msgWarning("è¯·éæ©å¾
审æ¹çæ°æ®"); |
| | | return; |
| | | } |
| | | const ids = selectedRows.value.map(item => item.id); |
| | | |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "å é¤", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "å é¤", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | batchDeletePendingStockInRecords(ids) |
| | | .then(() => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msgError("å é¤å¤±è´¥"); |
| | | }); |
| | | .then(() => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msgError("å é¤å¤±è´¥"); |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | fetchStockRecordTypeOptions(); |
| | | }); |
| | | |
| | | watch( |
| | | () => props.topParentProductId, |
| | | () => { |
| | | page.current = 1; |
| | | onMounted(() => { |
| | | getList(); |
| | | } |
| | | ); |
| | | fetchStockRecordTypeOptions(); |
| | | }); |
| | | |
| | | watch( |
| | | () => props.topParentProductId, |
| | | () => { |
| | | page.current = 1; |
| | | getList(); |
| | | } |
| | | ); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .actions { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | margin-bottom: 10px; |
| | | } |
| | | .actions { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | margin-bottom: 10px; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <div> |
| | | <div class="search_form mb10"> |
| | | <el-form |
| | | ref="searchFormRef" |
| | | :model="searchForm" |
| | | class="demo-form-inline" |
| | | > |
| | | <el-form ref="searchFormRef" |
| | | :model="searchForm" |
| | | class="demo-form-inline"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="4"> |
| | | <el-form-item label="产å大类" prop="productName"> |
| | | <el-form-item label="产å大类" |
| | | prop="productName"> |
| | | <el-input v-model="searchForm.productName" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | clearable/> |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | |
| | | <el-col :span="4"> |
| | | <el-form-item label="产åè§æ ¼" prop="model"> |
| | | <el-form-item label="è§æ ¼åå·" |
| | | prop="model"> |
| | | <el-input v-model="searchForm.model" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | clearable/> |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="4"> |
| | | <el-form-item label="æ¹å·" prop="batchNo"> |
| | | <el-form-item label="æ¹å·" |
| | | prop="batchNo"> |
| | | <el-input v-model="searchForm.batchNo" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | clearable/> |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <!-- æé® --> |
| | | <el-col :span="4"> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="getList"> |
| | | <el-button type="primary" |
| | | @click="getList"> |
| | | æç´¢ |
| | | </el-button> |
| | | |
| | | <el-button @click="resetSearch"> |
| | | éç½® |
| | | </el-button> |
| | |
| | | </el-row> |
| | | </el-form> |
| | | <div> |
| | | <el-button type="primary" @click="isShowNewModal = true" |
| | | >æ°å¢åºå</el-button |
| | | > |
| | | <el-button |
| | | type="info" |
| | | plain |
| | | icon="Upload" |
| | | @click="isShowImportModal = true" |
| | | > |
| | | <el-button type="primary" |
| | | @click="isShowNewModal = true">æ°å¢åºå</el-button> |
| | | <el-button type="info" |
| | | plain |
| | | icon="Upload" |
| | | @click="isShowImportModal = true"> |
| | | 导å
¥åºå |
| | | </el-button> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | | <el-table |
| | | :data="tableData" |
| | | border |
| | | v-loading="tableLoading" |
| | | @selection-change="handleSelectionChange" |
| | | :expand-row-keys="expandedRowKeys" |
| | | :row-key="(row, index) => index" |
| | | style="width: 100%" |
| | | :row-class-name="tableRowClassName" |
| | | height="calc(100vh - 18.5em)" |
| | | > |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table-column align="center" label="åºå·" type="index" width="60" /> |
| | | <el-table-column |
| | | label="产ååç§°" |
| | | prop="productName" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column label="è§æ ¼åå·" prop="model" show-overflow-tooltip /> |
| | | <el-table-column label="åä½" prop="unit" show-overflow-tooltip /> |
| | | <el-table-column label="æ¹å·" prop="batchNo" show-overflow-tooltip /> |
| | | <el-table-column |
| | | label="åæ ¼åºåæ°é" |
| | | prop="qualifiedQuantity" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="ä¸åæ ¼åºåæ°é" |
| | | prop="unQualifiedQuantity" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="åæ ¼å»ç»æ°é" |
| | | prop="qualifiedLockedQuantity" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="ä¸åæ ¼å»ç»æ°é" |
| | | prop="unQualifiedLockedQuantity" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="åºåé¢è¦æ°é" |
| | | prop="warnNum" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column label="夿³¨" prop="remark" show-overflow-tooltip /> |
| | | <el-table-column |
| | | label="æè¿æ´æ°æ¶é´" |
| | | prop="updateTime" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | fixed="right" |
| | | label="æä½" |
| | | min-width="80" |
| | | align="center" |
| | | > |
| | | <el-table :data="tableData" |
| | | border |
| | | v-loading="tableLoading" |
| | | @selection-change="handleSelectionChange" |
| | | :expand-row-keys="expandedRowKeys" |
| | | :row-key="(row, index) => index" |
| | | style="width: 100%" |
| | | :row-class-name="tableRowClassName" |
| | | height="calc(100vh - 18.5em)"> |
| | | <el-table-column align="center" |
| | | type="selection" |
| | | width="55" /> |
| | | <el-table-column align="center" |
| | | label="åºå·" |
| | | type="index" |
| | | width="60" /> |
| | | <el-table-column label="产ååç§°" |
| | | prop="productName" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="è§æ ¼åå·" |
| | | prop="model" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="åä½" |
| | | prop="unit" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="æ¹å·" |
| | | prop="batchNo" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="åæ ¼åºåæ°é" |
| | | prop="qualifiedQuantity" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="ä¸åæ ¼åºåæ°é" |
| | | prop="unQualifiedQuantity" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="åæ ¼å»ç»æ°é" |
| | | prop="qualifiedLockedQuantity" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="ä¸åæ ¼å»ç»æ°é" |
| | | prop="unQualifiedLockedQuantity" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="åºåé¢è¦æ°é" |
| | | prop="warnNum" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="夿³¨" |
| | | prop="remark" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="æè¿æ´æ°æ¶é´" |
| | | prop="updateTime" |
| | | show-overflow-tooltip /> |
| | | <el-table-column fixed="right" |
| | | label="æä½" |
| | | min-width="80" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | link |
| | | type="primary" |
| | | @click="showDetailModal(scope.row)" |
| | | >详æ
</el-button |
| | | > |
| | | <el-button link |
| | | type="primary" |
| | | @click="showDetailModal(scope.row)">详æ
</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <pagination |
| | | v-show="total > 0" |
| | | :total="total" |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | :page="page.current" |
| | | :limit="page.size" |
| | | @pagination="paginationChange" |
| | | /> |
| | | <pagination v-show="total > 0" |
| | | :total="total" |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | :page="page.current" |
| | | :limit="page.size" |
| | | @pagination="paginationChange" /> |
| | | </div> |
| | | <batch-no-qty-detail |
| | | v-if="isShowDetailModal" |
| | | v-model:visible="isShowDetailModal" |
| | | :record="record" |
| | | @subtract="handleDetailSubtract" |
| | | @frozen="handleDetailFrozen" |
| | | @thaw="handleDetailThaw" |
| | | /> |
| | | <new-stock-inventory |
| | | v-if="isShowNewModal" |
| | | v-model:visible="isShowNewModal" |
| | | :top-product-parent-id="props.productId" |
| | | @completed="handleQuery" |
| | | /> |
| | | |
| | | <subtract-stock-inventory |
| | | v-if="isShowSubtractModal" |
| | | v-model:visible="isShowSubtractModal" |
| | | :record="record" |
| | | :type="record.stockType" |
| | | @completed="handleQuery" |
| | | /> |
| | | <batch-no-qty-detail v-if="isShowDetailModal" |
| | | v-model:visible="isShowDetailModal" |
| | | :record="record" |
| | | @subtract="handleDetailSubtract" |
| | | @frozen="handleDetailFrozen" |
| | | @thaw="handleDetailThaw" /> |
| | | <new-stock-inventory v-if="isShowNewModal" |
| | | v-model:visible="isShowNewModal" |
| | | :top-product-parent-id="props.productId" |
| | | @completed="handleQuery" /> |
| | | <subtract-stock-inventory v-if="isShowSubtractModal" |
| | | v-model:visible="isShowSubtractModal" |
| | | :record="record" |
| | | :type="record.stockType" |
| | | @completed="handleQuery" /> |
| | | <!-- 导å
¥åºå--> |
| | | <import-stock-inventory |
| | | v-if="isShowImportModal" |
| | | v-model:visible="isShowImportModal" |
| | | type="qualified" |
| | | @uploadSuccess="handleQuery" |
| | | /> |
| | | <import-stock-inventory v-if="isShowImportModal" |
| | | v-model:visible="isShowImportModal" |
| | | type="qualified" |
| | | @uploadSuccess="handleQuery" /> |
| | | <!-- å»ç»/è§£å»åºå--> |
| | | <frozen-and-thaw-stock-inventory |
| | | v-if="isShowFrozenAndThawModal" |
| | | v-model:visible="isShowFrozenAndThawModal" |
| | | :record="record" |
| | | :operation-type="operationType" |
| | | :type="record.stockType" |
| | | @completed="handleQuery" |
| | | /> |
| | | <frozen-and-thaw-stock-inventory v-if="isShowFrozenAndThawModal" |
| | | v-model:visible="isShowFrozenAndThawModal" |
| | | :record="record" |
| | | :operation-type="operationType" |
| | | :type="record.stockType" |
| | | @completed="handleQuery" /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import pagination from "@/components/PIMTable/Pagination.vue"; |
| | | import { ref, reactive, toRefs, onMounted, getCurrentInstance } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import { getStockInventoryListPageCombined } from "@/api/inventoryManagement/stockInventory.js"; |
| | | const props = defineProps({ |
| | | productId: { |
| | | type: Number, |
| | | required: true, |
| | | default: 0, |
| | | }, |
| | | }); |
| | | import pagination from "@/components/PIMTable/Pagination.vue"; |
| | | import { ref, reactive, toRefs, onMounted, getCurrentInstance } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import { getStockInventoryListPageCombined } from "@/api/inventoryManagement/stockInventory.js"; |
| | | const props = defineProps({ |
| | | productId: { |
| | | type: Number, |
| | | required: true, |
| | | default: 0, |
| | | }, |
| | | }); |
| | | |
| | | const NewStockInventory = defineAsyncComponent(() => |
| | | import("@/views/inventoryManagement/stockManagement/New.vue") |
| | | ); |
| | | const SubtractStockInventory = defineAsyncComponent(() => |
| | | import("@/views/inventoryManagement/stockManagement/Subtract.vue") |
| | | ); |
| | | const ImportStockInventory = defineAsyncComponent(() => |
| | | import("@/views/inventoryManagement/stockManagement/Import.vue") |
| | | ); |
| | | const FrozenAndThawStockInventory = defineAsyncComponent(() => |
| | | import("@/views/inventoryManagement/stockManagement/FrozenAndThaw.vue") |
| | | ); |
| | | const BatchNoQtyDetail = defineAsyncComponent(() => |
| | | import("@/views/inventoryManagement/stockManagement/BatchNoQtyDetail.vue") |
| | | ); |
| | | const { proxy } = getCurrentInstance(); |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const record = ref({}); |
| | | const tableLoading = ref(false); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | }); |
| | | const total = ref(0); |
| | | // æ¯å¦æ¾ç¤ºæ°å¢å¼¹æ¡ |
| | | const isShowNewModal = ref(false); |
| | | // æ¯å¦æ¾ç¤ºé¢ç¨å¼¹æ¡ |
| | | const isShowSubtractModal = ref(false); |
| | | // æ¯å¦æ¾ç¤ºå»ç»/è§£å»å¼¹æ¡ |
| | | const isShowFrozenAndThawModal = ref(false); |
| | | // æ¯å¦æ¾ç¤ºè¯¦æ
å¼¹æ¡ |
| | | const isShowDetailModal = ref(false); |
| | | // æä½ç±»å |
| | | const operationType = ref("frozen"); |
| | | // æ¯å¦æ¾ç¤ºå¯¼å
¥å¼¹æ¡ |
| | | const isShowImportModal = ref(false); |
| | | const data = reactive({ |
| | | searchForm: { |
| | | productName: "", |
| | | model: "", |
| | | batchNo: "", |
| | | topParentProductId: props.productId, |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | const searchFormRef = ref(null); |
| | | const NewStockInventory = defineAsyncComponent(() => |
| | | import("@/views/inventoryManagement/stockManagement/New.vue") |
| | | ); |
| | | const SubtractStockInventory = defineAsyncComponent(() => |
| | | import("@/views/inventoryManagement/stockManagement/Subtract.vue") |
| | | ); |
| | | const ImportStockInventory = defineAsyncComponent(() => |
| | | import("@/views/inventoryManagement/stockManagement/Import.vue") |
| | | ); |
| | | const FrozenAndThawStockInventory = defineAsyncComponent(() => |
| | | import("@/views/inventoryManagement/stockManagement/FrozenAndThaw.vue") |
| | | ); |
| | | const BatchNoQtyDetail = defineAsyncComponent(() => |
| | | import("@/views/inventoryManagement/stockManagement/BatchNoQtyDetail.vue") |
| | | ); |
| | | const { proxy } = getCurrentInstance(); |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const record = ref({}); |
| | | const tableLoading = ref(false); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | }); |
| | | const total = ref(0); |
| | | // æ¯å¦æ¾ç¤ºæ°å¢å¼¹æ¡ |
| | | const isShowNewModal = ref(false); |
| | | // æ¯å¦æ¾ç¤ºé¢ç¨å¼¹æ¡ |
| | | const isShowSubtractModal = ref(false); |
| | | // æ¯å¦æ¾ç¤ºå»ç»/è§£å»å¼¹æ¡ |
| | | const isShowFrozenAndThawModal = ref(false); |
| | | // æ¯å¦æ¾ç¤ºè¯¦æ
å¼¹æ¡ |
| | | const isShowDetailModal = ref(false); |
| | | // æä½ç±»å |
| | | const operationType = ref("frozen"); |
| | | // æ¯å¦æ¾ç¤ºå¯¼å
¥å¼¹æ¡ |
| | | const isShowImportModal = ref(false); |
| | | const data = reactive({ |
| | | searchForm: { |
| | | productName: "", |
| | | model: "", |
| | | batchNo: "", |
| | | topParentProductId: props.productId, |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | const searchFormRef = ref(null); |
| | | |
| | | const resetSearch = () => { |
| | | searchFormRef.value?.resetFields(); |
| | | page.current = 1; |
| | | getList(); |
| | | } |
| | | const resetSearch = () => { |
| | | searchFormRef.value?.resetFields(); |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const paginationChange = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | getStockInventoryListPageCombined({ ...searchForm.value, ...page }) |
| | | .then((res) => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | total.value = res.data.total; |
| | | // æ°æ®å è½½å®æåæ£æ¥åºå |
| | | // checkStockAndCreatePurchase(); |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const paginationChange = obj => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | getStockInventoryListPageCombined({ ...searchForm.value, ...page }) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | total.value = res.data.total; |
| | | // æ°æ®å è½½å®æåæ£æ¥åºå |
| | | // checkStockAndCreatePurchase(); |
| | | }) |
| | | .catch(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | const handleFileSuccess = response => { |
| | | const { code, msg } = response; |
| | | if (code == 200) { |
| | | ElMessage({ message: "导å
¥æå", type: "success" }); |
| | | upload.open = false; |
| | | emits("uploadSuccess"); |
| | | } else { |
| | | ElMessage({ message: msg, type: "error" }); |
| | | } |
| | | }; |
| | | |
| | | // ç¹å»é¢ç¨ |
| | | const showSubtractModal = row => { |
| | | record.value = row; |
| | | isShowSubtractModal.value = true; |
| | | }; |
| | | |
| | | // ç¹å»è¯¦æ
|
| | | const showDetailModal = row => { |
| | | if (!row?.productId || !row?.productModelId) { |
| | | proxy.$modal.msgError("å½åæ°æ®ç¼ºå°äº§åIDæè§æ ¼åå·ID"); |
| | | return; |
| | | } |
| | | record.value = row; |
| | | isShowDetailModal.value = true; |
| | | }; |
| | | |
| | | const handleDetailSubtract = row => { |
| | | isShowDetailModal.value = false; |
| | | showSubtractModal(row); |
| | | }; |
| | | |
| | | const handleDetailFrozen = row => { |
| | | isShowDetailModal.value = false; |
| | | showFrozenModal(row); |
| | | }; |
| | | |
| | | const handleDetailThaw = row => { |
| | | isShowDetailModal.value = false; |
| | | showThawModal(row); |
| | | }; |
| | | |
| | | // ç¹å»å»ç» |
| | | const showFrozenModal = row => { |
| | | record.value = row; |
| | | isShowFrozenAndThawModal.value = true; |
| | | operationType.value = "frozen"; |
| | | }; |
| | | |
| | | // ç¹å»è§£å» |
| | | const showThawModal = row => { |
| | | record.value = row; |
| | | isShowFrozenAndThawModal.value = true; |
| | | operationType.value = "thaw"; |
| | | }; |
| | | |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = selection => { |
| | | // è¿æ»¤æåæ°æ® |
| | | selectedRows.value = selection.filter(item => item.id); |
| | | console.log("selection", selectedRows.value); |
| | | }; |
| | | const expandedRowKeys = ref([]); |
| | | |
| | | // è¡¨æ ¼è¡ç±»å |
| | | const tableRowClassName = ({ row }) => { |
| | | const stock = Number(row?.qualifiedUnLockedQuantity ?? 0); |
| | | const warn = Number(row?.warnNum ?? 0); |
| | | if (!Number.isFinite(stock) || !Number.isFinite(warn)) { |
| | | return ""; |
| | | } |
| | | return stock < warn ? "row-low-stock" : ""; |
| | | }; |
| | | |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .catch(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | .then(() => { |
| | | proxy.download( |
| | | "/stockInventory/exportStockInventory", |
| | | { topParentProductId: props.productId }, |
| | | "åºåä¿¡æ¯.xlsx" |
| | | ); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | |
| | | const handleFileSuccess = (response) => { |
| | | const { code, msg } = response; |
| | | if (code == 200) { |
| | | ElMessage({ message: "导å
¥æå", type: "success" }); |
| | | upload.open = false; |
| | | emits("uploadSuccess"); |
| | | } else { |
| | | ElMessage({ message: msg, type: "error" }); |
| | | } |
| | | }; |
| | | |
| | | // ç¹å»é¢ç¨ |
| | | const showSubtractModal = (row) => { |
| | | record.value = row; |
| | | isShowSubtractModal.value = true; |
| | | }; |
| | | |
| | | // ç¹å»è¯¦æ
|
| | | const showDetailModal = (row) => { |
| | | if (!row?.productId || !row?.productModelId) { |
| | | proxy.$modal.msgError("å½åæ°æ®ç¼ºå°äº§åIDæè§æ ¼åå·ID"); |
| | | return; |
| | | } |
| | | record.value = row; |
| | | isShowDetailModal.value = true; |
| | | }; |
| | | |
| | | const handleDetailSubtract = (row) => { |
| | | isShowDetailModal.value = false; |
| | | showSubtractModal(row); |
| | | }; |
| | | |
| | | const handleDetailFrozen = (row) => { |
| | | isShowDetailModal.value = false; |
| | | showFrozenModal(row); |
| | | }; |
| | | |
| | | const handleDetailThaw = (row) => { |
| | | isShowDetailModal.value = false; |
| | | showThawModal(row); |
| | | }; |
| | | |
| | | // ç¹å»å»ç» |
| | | const showFrozenModal = (row) => { |
| | | record.value = row; |
| | | isShowFrozenAndThawModal.value = true; |
| | | operationType.value = "frozen"; |
| | | }; |
| | | |
| | | // ç¹å»è§£å» |
| | | const showThawModal = (row) => { |
| | | record.value = row; |
| | | isShowFrozenAndThawModal.value = true; |
| | | operationType.value = "thaw"; |
| | | }; |
| | | |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | | // è¿æ»¤æåæ°æ® |
| | | selectedRows.value = selection.filter((item) => item.id); |
| | | console.log("selection", selectedRows.value); |
| | | }; |
| | | const expandedRowKeys = ref([]); |
| | | |
| | | // è¡¨æ ¼è¡ç±»å |
| | | const tableRowClassName = ({ row }) => { |
| | | const stock = Number(row?.qualifiedUnLockedQuantity ?? 0); |
| | | const warn = Number(row?.warnNum ?? 0); |
| | | if (!Number.isFinite(stock) || !Number.isFinite(warn)) { |
| | | return ""; |
| | | } |
| | | return stock < warn ? "row-low-stock" : ""; |
| | | }; |
| | | |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download( |
| | | "/stockInventory/exportStockInventory", |
| | | { topParentProductId: props.productId }, |
| | | "åºåä¿¡æ¯.xlsx" |
| | | ); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | :deep(.row-low-stock td) { |
| | | background-color: #fde2e2; |
| | | color: #c45656; |
| | | } |
| | | :deep(.row-low-stock td) { |
| | | background-color: #fde2e2; |
| | | color: #c45656; |
| | | } |
| | | |
| | | :deep(.row-low-stock:hover > td) { |
| | | background-color: #fcd4d4; |
| | | } |
| | | :deep(.row-low-stock:hover > td) { |
| | | background-color: #fcd4d4; |
| | | } |
| | | </style> |
| | |
| | | import { |
| | | createEmptyNode, |
| | | formatDisplayTime, |
| | | mapNodesFromApi, |
| | | mapSignModeFromApi, |
| | | mapSignModeToApi, |
| | | normalizeFlowNodes, |
| | | nodeSignModeLabel, |
| | | } from "../approve-template/approveTemplateConstants.js"; |
| | | import { createEmptyNode, formatDisplayTime, mapNodesFromApi, mapSignModeFromApi, mapSignModeToApi, normalizeFlowNodes, nodeSignModeLabel } from "../approve-template/approveTemplateConstants.js"; |
| | | import { buildFormPayloadFromFields, parseFormConfigToData } from "../approve-template/formConfigUtils.js"; |
| | | import { |
| | | isDynamicOptionSource, |
| | | resolveSelectDisplayLabel, |
| | | } from "../approve-template/selectOptionSource.js"; |
| | | import { |
| | | appendDotNotationQuery, |
| | | buildApprovalInstanceSearchDto, |
| | | } from "../approve-shared/approvalInstanceListSearch.js"; |
| | | import { isDynamicOptionSource, resolveSelectDisplayLabel } from "../approve-template/selectOptionSource.js"; |
| | | import { appendDotNotationQuery, buildApprovalInstanceSearchDto } from "../approve-shared/approvalInstanceListSearch.js"; |
| | | |
| | | /** 审æ¹ç±»åï¼ä¸åç«¯åæ®µ approvalType 对é½ï¼åæå¯åæ¥ï¼ */ |
| | | export const APPROVAL_TYPE_OPTIONS = [ |
| | |
| | | if (upper === "APPROVED" || upper === "APPROVE" || upper === "PASS" || upper === "AGREE") { |
| | | return "approved"; |
| | | } |
| | | if ( |
| | | upper === "REJECTED" || |
| | | upper === "REJECT" || |
| | | upper === "REFUSE" || |
| | | upper === "REFUSED" || |
| | | upper === "DENIED" |
| | | ) { |
| | | if (upper === "REJECTED" || upper === "REJECT" || upper === "REFUSE" || upper === "REFUSED" || upper === "DENIED") { |
| | | return "rejected"; |
| | | } |
| | | if (upper === "CANCELLED" || upper === "CANCEL" || upper === "REVOKED") return "cancelled"; |
| | | if ( |
| | | upper === "PENDING" || |
| | | upper === "IN_PROGRESS" || |
| | | upper === "PROCESSING" || |
| | | upper === "RUNNING" || |
| | | upper === "WAIT" || |
| | | upper === "WAITING" |
| | | ) { |
| | | if (upper === "PENDING" || upper === "IN_PROGRESS" || upper === "PROCESSING" || upper === "RUNNING" || upper === "WAIT" || upper === "WAITING") { |
| | | return "pending"; |
| | | } |
| | | if (s.includes("è稿")) return "draft"; |
| | |
| | | } |
| | | const tasks = row.tasks; |
| | | if (Array.isArray(tasks) && tasks.length) { |
| | | const rejected = tasks.some((t) => |
| | | normalizeApprovalStatusKey(t?.status ?? t?.taskStatus) === "rejected" |
| | | ); |
| | | const rejected = tasks.some(t => normalizeApprovalStatusKey(t?.status ?? t?.taskStatus) === "rejected"); |
| | | if (rejected) return "REJECTED"; |
| | | const allApproved = tasks.every((t) => |
| | | normalizeApprovalStatusKey(t?.status ?? t?.taskStatus) === "approved" |
| | | ); |
| | | const allApproved = tasks.every(t => normalizeApprovalStatusKey(t?.status ?? t?.taskStatus) === "approved"); |
| | | if (allApproved) return "APPROVED"; |
| | | } |
| | | return ""; |
| | |
| | | /** å端 records â æ¶é´çº¿å±ç¤ºç»æ */ |
| | | export function mapRecordsFromApi(records) { |
| | | const list = Array.isArray(records) ? records : []; |
| | | return list.map((r) => ({ |
| | | return list.map(r => ({ |
| | | id: r.id, |
| | | operatorName: r.approverName || r.operatorName || r.createUserName || "", |
| | | result: mapRecordResultFromApi(r.approveAction ?? r.action ?? r.status), |
| | |
| | | const list = Array.isArray(tasks) ? tasks : []; |
| | | if (!list.length) return []; |
| | | const byLevel = new Map(); |
| | | list.forEach((t) => { |
| | | list.forEach(t => { |
| | | const level = Number(t.levelNo ?? t.taskLevel ?? t.nodeOrder ?? 1); |
| | | if (!byLevel.has(level)) { |
| | | byLevel.set(level, { |
| | |
| | | node.signMode = mapSignModeFromApi(t.approveType); |
| | | } |
| | | }); |
| | | return [...byLevel.entries()] |
| | | .sort(([a], [b]) => a - b) |
| | | .map(([, node]) => node); |
| | | return [...byLevel.entries()].sort(([a], [b]) => a - b).map(([, node]) => node); |
| | | } |
| | | |
| | | /** é¡µé¢ flowNodes â å端 tasks */ |
| | | export function mapFlowNodesToTasks(flowNodes, { instanceId, templateId } = {}) { |
| | | const nodes = normalizeFlowNodes(flowNodes); |
| | | const tasks = []; |
| | | nodes.forEach((n) => { |
| | | nodes.forEach(n => { |
| | | const levelNo = n.nodeOrder ?? 1; |
| | | const approveType = mapSignModeToApi(n.signMode); |
| | | n.approvers.forEach((a, idx) => { |
| | |
| | | return String(val); |
| | | } |
| | | if (field?.type === "select" && field.options?.length) { |
| | | const hit = field.options.find((o) => String(o.value) === String(val)); |
| | | const hit = field.options.find(o => String(o.value) === String(val)); |
| | | return hit?.label || String(val); |
| | | } |
| | | if (Array.isArray(val)) return val.join(" è³ "); |
| | |
| | | }; |
| | | if (!fields.length && Object.keys(formPayload).length) { |
| | | fields = Object.keys(formPayload) |
| | | .filter((k) => k && k !== "summary") |
| | | .map((k) => ({ |
| | | .filter(k => k && k !== "summary") |
| | | .map(k => ({ |
| | | key: k, |
| | | label: k, |
| | | type: guessFieldTypeFromValue(formPayload[k]), |
| | |
| | | export function buildInstanceDto({ submitForm, activeTemplate, userStore, flowNodes, existingRow }) { |
| | | const payload = submitForm?.formPayload || {}; |
| | | const tpl = activeTemplate || {}; |
| | | const title = |
| | | String(payload.summary || payload.title || "").trim() || |
| | | tpl.label || |
| | | submitForm?.templateName || |
| | | "审æ¹ç³è¯·"; |
| | | const title = String(payload.summary || payload.title || "").trim() || tpl.label || submitForm?.templateName || "审æ¹ç³è¯·"; |
| | | const templateId = submitForm?.templateId || tpl.templateId; |
| | | const instanceId = existingRow?.id ?? submitForm?.instanceId; |
| | | const taskList = mapFlowNodesToTasks(flowNodes || submitForm?.flowNodes, { |
| | |
| | | tasks: taskList, |
| | | }; |
| | | |
| | | const attachments = |
| | | (Array.isArray(submitForm?.storageBlobDTOs) && submitForm.storageBlobDTOs.length |
| | | ? submitForm.storageBlobDTOs |
| | | : null) || tpl.storageBlobDTOs; |
| | | const attachments = (Array.isArray(submitForm?.storageBlobDTOs) && submitForm.storageBlobDTOs.length ? submitForm.storageBlobDTOs : null) || tpl.storageBlobDTOs; |
| | | if (attachments?.length) dto.storageBlobDTOs = attachments; |
| | | |
| | | if (isUpdate) { |
| | | dto.id = existingRow?.id ?? submitForm?.instanceId; |
| | | dto.instanceNo = existingRow?.instanceNo ?? submitForm?.instanceNo ?? ""; |
| | | dto.status = |
| | | submitForm?.saveStatusApi || |
| | | existingRow?.statusRaw || |
| | | mapInstanceStatusToApi(existingRow?.approvalStatus) || |
| | | "PENDING"; |
| | | dto.status = submitForm?.saveStatusApi || existingRow?.statusRaw || mapInstanceStatusToApi(existingRow?.approvalStatus) || "PENDING"; |
| | | dto.currentLevel = existingRow?.currentLevel ?? submitForm?.currentLevel ?? 1; |
| | | dto.applicantId = existingRow?.applicantId ?? existingRow?.applicantNo; |
| | | dto.applicantName = existingRow?.applicantName || ""; |
| | |
| | | /** é¡µé¢ approvalStatus â å端 status */ |
| | | export function mapInstanceStatusToApi(approvalStatus) { |
| | | const key = normalizeApprovalStatusKey(approvalStatus); |
| | | const hit = APPROVAL_STATUS_OPTIONS.find((x) => x.value === key); |
| | | const hit = APPROVAL_STATUS_OPTIONS.find(x => x.value === key); |
| | | return hit?.api || "PENDING"; |
| | | } |
| | | |
| | |
| | | const resolved = resolveInstanceFormFields(row); |
| | | const { fields, formPayload, templateSnapshot } = resolved; |
| | | const tasks = Array.isArray(row.tasks) ? row.tasks : []; |
| | | const flowNodes = tasks.length |
| | | ? mapTasksToFlowNodes(tasks) |
| | | : mapNodesFromApi(row.nodes || row.flowNodes); |
| | | const flowNodes = tasks.length ? mapTasksToFlowNodes(tasks) : mapNodesFromApi(row.nodes || row.flowNodes); |
| | | const approvalRecords = mapRecordsFromApi(row.records); |
| | | return { |
| | | id: row.id, |
| | |
| | | templateSnapshot, |
| | | tasks, |
| | | records: Array.isArray(row.records) ? row.records : [], |
| | | storageBlobVOList: row.storageBlobVOList || [], |
| | | storageBlobDTOs: row.storageBlobVOList || row.storageBlobDTOs || [], |
| | | flowNodes, |
| | | approvalFlowNodes: [], |
| | | currentNodeIndex: 0, |
| | | approvalRecords, |
| | | rejectReason: |
| | | approvalRecords.find((r) => r.result === "rejected")?.opinion || "", |
| | | rejectReason: approvalRecords.find(r => r.result === "rejected")?.opinion || "", |
| | | purchaseContractNumber: row.purchaseContractNumber || "", |
| | | quotationNo: row.quotationNo || "", |
| | | shippingNo: row.shippingNo || "", |
| | | }; |
| | | } |
| | | |
| | |
| | | }; |
| | | } |
| | | |
| | | export function buildApprovalInstanceListParams({ |
| | | page, |
| | | searchForm, |
| | | businessType, |
| | | extraParams, |
| | | }) { |
| | | export function buildApprovalInstanceListParams({ page, searchForm, businessType, extraParams }) { |
| | | const dto = buildApprovalInstanceSearchDto(searchForm, extraParams); |
| | | const bizType = businessType ?? searchForm?.businessType; |
| | | if (bizType != null && bizType !== "") { |
| | |
| | | } |
| | | |
| | | export function approvalTypeLabel(v) { |
| | | return APPROVAL_TYPE_OPTIONS.find((x) => x.value === v)?.label || v || "â"; |
| | | return APPROVAL_TYPE_OPTIONS.find(x => x.value === v)?.label || v || "â"; |
| | | } |
| | | |
| | | export function approvalTypeStyle(v) { |
| | | const hit = APPROVAL_TYPE_OPTIONS.find((x) => x.value === v); |
| | | const hit = APPROVAL_TYPE_OPTIONS.find(x => x.value === v); |
| | | if (!hit) return {}; |
| | | return { |
| | | backgroundColor: hit.cellBg, |
| | |
| | | |
| | | export function approvalStatusLabel(v) { |
| | | const key = normalizeApprovalStatusKey(v); |
| | | return APPROVAL_STATUS_OPTIONS.find((x) => x.value === key)?.label || "â"; |
| | | return APPROVAL_STATUS_OPTIONS.find(x => x.value === key)?.label || "â"; |
| | | } |
| | | |
| | | /** ä¸å¡ç³è¯·é¡µç¶æææ¡ï¼PENDINGâè¿è¡ä¸ APPROVEDâ已宿 REJECTEDâ已驳å */ |
| | |
| | | * è¿è¡ä¸(PENDING)ã已宿(APPROVED) ä¸å¯ä¿®æ¹ï¼å·²é©³åãå·²æ¤éçå¯ä¿®æ¹ |
| | | */ |
| | | export function canEditBusinessInstanceRow(row) { |
| | | const key = normalizeApprovalStatusKey( |
| | | row?.approvalStatus ?? row?.statusRaw ?? row?.status |
| | | ); |
| | | const key = normalizeApprovalStatusKey(row?.approvalStatus ?? row?.statusRaw ?? row?.status); |
| | | return key !== "pending" && key !== "approved"; |
| | | } |
| | | |
| | |
| | | /** åè¡¨è¡ â ç¼è¾è¡¨åï¼ä»
ç¨è¡æ°æ®åæ¾ï¼ */ |
| | | export function buildEditFormFromInstanceRow(row) { |
| | | const { fields, formPayload, templateSnapshot } = resolveInstanceFormFields(row); |
| | | const normalized = normalizeFlowNodes( |
| | | row?.flowNodes?.length ? row.flowNodes : mapTasksToFlowNodes(row?.tasks) |
| | | ); |
| | | const flowNodes = normalized.length |
| | | ? JSON.parse(JSON.stringify(normalized)) |
| | | : [createEmptyNode(1)]; |
| | | const normalized = normalizeFlowNodes(row?.flowNodes?.length ? row.flowNodes : mapTasksToFlowNodes(row?.tasks)); |
| | | const flowNodes = normalized.length ? JSON.parse(JSON.stringify(normalized)) : [createEmptyNode(1)]; |
| | | |
| | | return { |
| | | templateKey: String(row?.templateId || ""), |
| | |
| | | formPayload, |
| | | flowNodes, |
| | | templateAttachments: initTemplateAttachmentsFromSnapshot(templateSnapshot), |
| | | storageBlobDTOs: row?.storageBlobDTOs?.length |
| | | ? JSON.parse(JSON.stringify(row.storageBlobDTOs)) |
| | | : [], |
| | | storageBlobDTOs: (row?.storageBlobDTOs?.length ? row.storageBlobDTOs : row?.storageBlobVOList || []).map(f => JSON.parse(JSON.stringify(f))), |
| | | }; |
| | | } |
| | | |
| | |
| | | const tpl = templateOverride || null; |
| | | const payload = tpl?.fields?.length ? buildFormPayloadFromFields(tpl.fields) : { summary: "" }; |
| | | const normalized = normalizeFlowNodes(flowNodesOverride); |
| | | const flowNodes = normalized.length |
| | | ? JSON.parse(JSON.stringify(normalized)) |
| | | : [createEmptyNode(1)]; |
| | | const flowNodes = normalized.length ? JSON.parse(JSON.stringify(normalized)) : [createEmptyNode(1)]; |
| | | return { |
| | | templateKey: templateKey || "", |
| | | templateId: tpl?.templateId || "", |
| | |
| | | formFieldDefs: tpl?.fields || [], |
| | | formPayload: payload, |
| | | flowNodes, |
| | | templateAttachments: tpl?.storageBlobDTOs |
| | | ? JSON.parse(JSON.stringify(tpl.storageBlobDTOs)) |
| | | : [], |
| | | templateAttachments: tpl?.storageBlobDTOs ? JSON.parse(JSON.stringify(tpl.storageBlobDTOs)) : [], |
| | | storageBlobDTOs: [], |
| | | }; |
| | | } |
| | |
| | | <div class="approve-detail-panel"> |
| | | <div class="detail-block"> |
| | | <div class="detail-block-title">åºæ¬ä¿¡æ¯</div> |
| | | <el-descriptions :column="2" border> |
| | | <el-descriptions :column="2" |
| | | border> |
| | | <el-descriptions-item label="ä¸å¡åå·">{{ row.bizId || row.id || "â" }}</el-descriptions-item> |
| | | <el-descriptions-item label="审æ¹ç¶æ"> |
| | | <el-tag :type="approvalStatusTagType(row.approvalStatus)" size="small" effect="plain"> |
| | | <el-tag :type="approvalStatusTagType(row.approvalStatus)" |
| | | size="small" |
| | | effect="plain"> |
| | | {{ approvalStatusLabel(row.approvalStatus) }} |
| | | </el-tag> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="审æ¹ç±»å"> |
| | | <span class="approve-type-cell" :style="approvalTypeStyle(row.approvalType)"> |
| | | <span class="approve-type-cell" |
| | | :style="approvalTypeStyle(row.approvalType)"> |
| | | {{ approvalTypeLabel(row.approvalType) }} |
| | | </span> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="ç³è¯·äººç¼å·">{{ row.applicantNo || "â" }}</el-descriptions-item> |
| | | <el-descriptions-item label="ç³è¯·äººåç§°">{{ row.applicantName || "â" }}</el-descriptions-item> |
| | | <el-descriptions-item label="ç³è¯·æè¦">{{ row.summary || "â" }}</el-descriptions-item> |
| | | <el-descriptions-item v-if="row.rejectReason" label="驳ååå " :span="2"> |
| | | <el-descriptions-item v-if="row.rejectReason" |
| | | label="驳ååå " |
| | | :span="2"> |
| | | <span class="reject-text">{{ row.rejectReason }}</span> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="å建æ¶é´" :span="2"> |
| | | <el-descriptions-item label="å建æ¶é´" |
| | | :span="2"> |
| | | {{ formatDisplayTime(row.createTime) }} |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | </div> |
| | | |
| | | <div class="detail-block"> |
| | | <div class="detail-block-title">å¡«æ¥å
容</div> |
| | | <FormPayloadFields |
| | | :fields="formResolved.fields" |
| | | :form-payload="formResolved.formPayload" |
| | | readonly |
| | | /> |
| | | <!-- é»è®¤è¡¨åå±ç¤º --> |
| | | <FormPayloadFields v-if="!isSpecialApprovalType" |
| | | :fields="formResolved.fields" |
| | | :form-payload="formResolved.formPayload" |
| | | readonly /> |
| | | |
| | | <!-- å货审æ¹è¯¦æ
--> |
| | | <template v-else-if="row.businessType === 7"> |
| | | <div v-if="detailData.shippingInfo" class="shipment-detail"> |
| | | <el-divider content-position="left">å货详æ
</el-divider> |
| | | <el-descriptions :column="2" border> |
| | | <el-descriptions-item label="éå®è®¢å">{{ detailData.shippingInfo.salesContractNo || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="å货订åå·">{{ detailData.shippingInfo.shippingNo || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="客æ·åç§°">{{ detailData.shippingInfo.customerName || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="åè´§ç±»å">{{ detailData.shippingInfo.type || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="åè´§æ¥æ">{{ detailData.shippingInfo.shippingDateDate || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="å®¡æ ¸ç¶æ">{{ detailData.shippingInfo.status || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="å货车çå·">{{ detailData.shippingInfo.shippingCarNumber || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="å¿«éå
¬å¸">{{ detailData.shippingInfo.expressCompany || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="å¿«éåå·" :span="2">{{ detailData.shippingInfo.expressNumber || "--" }}</el-descriptions-item> |
| | | </el-descriptions> |
| | | <div v-if="detailData.shippingProductDetailDtoList.length" style="margin-top: 20px;"> |
| | | <h4>产åæç»</h4> |
| | | <el-table :data="detailData.shippingProductDetailDtoList" |
| | | border |
| | | size="small" |
| | | style="width: 100%"> |
| | | <el-table-column label="æ¹å·" prop="batchNo" min-width="160" show-overflow-tooltip /> |
| | | <el-table-column label="产ååç§°" prop="productName" min-width="160" show-overflow-tooltip /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" min-width="160" show-overflow-tooltip /> |
| | | <el-table-column label="åè´§æ°é" prop="deliveryQuantity" min-width="120" align="center" /> |
| | | </el-table> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <!-- éè´å®¡æ¹è¯¦æ
--> |
| | | <template v-else-if="row.businessType === 5"> |
| | | <div v-if="detailData" class="procurement-detail"> |
| | | <el-divider content-position="left">éè´è¯¦æ
</el-divider> |
| | | <el-descriptions :column="2" border> |
| | | <el-descriptions-item label="éè´ååå·">{{ detailData.purchaseContractNumber || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="ä¾åºååç§°">{{ detailData.supplierName || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="项ç®åç§°">{{ detailData.projectName || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="éå®ååå·">{{ detailData.salesContractNo || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="ç¾è®¢æ¥æ">{{ detailData.executionDate || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="å½å
¥æ¥æ">{{ detailData.entryDate || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="仿¬¾æ¹å¼">{{ detailData.paymentMethod || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="ååéé¢" :span="2"> |
| | | <span style="font-size: 18px; color: #e6a23c; font-weight: bold;"> |
| | | ¥{{ Number(detailData.contractAmount ?? 0).toFixed(2) }} |
| | | </span> |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | <div v-if="detailData.productData.length" style="margin-top: 20px;"> |
| | | <h4>产åæç»</h4> |
| | | <el-table :data="detailData.productData" |
| | | 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> |
| | | </div> |
| | | </template> |
| | | |
| | | <!-- æ¥ä»·å®¡æ¹è¯¦æ
--> |
| | | <template v-else-if="row.businessType === 6"> |
| | | <div v-if="detailData" class="quotation-detail"> |
| | | <el-divider content-position="left">æ¥ä»·è¯¦æ
</el-divider> |
| | | <el-descriptions :column="2" border> |
| | | <el-descriptions-item label="æ¥ä»·åå·">{{ detailData.quotationNo || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="客æ·åç§°">{{ detailData.customer || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="ä¸å¡å">{{ detailData.salesperson || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="æ¥ä»·æ¥æ">{{ detailData.quotationDate || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="æææè³">{{ detailData.validDate || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="仿¬¾æ¹å¼">{{ detailData.paymentMethod || "--" }}</el-descriptions-item> |
| | | <el-descriptions-item label="æ¥ä»·æ»é¢" :span="2"> |
| | | <span style="font-size: 18px; color: #e6a23c; font-weight: bold;"> |
| | | ¥{{ Number(detailData.totalAmount ?? 0).toFixed(2) }} |
| | | </span> |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | <div v-if="detailData.products.length" style="margin-top: 20px;"> |
| | | <h4>产åæç»</h4> |
| | | <el-table :data="detailData.products" |
| | | border |
| | | style="width: 100%"> |
| | | <el-table-column prop="product" label="产ååç§°" /> |
| | | <el-table-column prop="specification" label="è§æ ¼åå·" /> |
| | | <el-table-column prop="unit" label="åä½" /> |
| | | <el-table-column prop="unitPrice" label="åä»·"> |
| | | <template #default="scope">Â¥{{ Number(scope.row.unitPrice ?? 0).toFixed(2) }}</template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | <div v-if="detailData.remark" style="margin-top: 20px;"> |
| | | <h4>夿³¨</h4> |
| | | <p>{{ detailData.remark }}</p> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | </div> |
| | | <div v-if="attachmentList.length" |
| | | class="detail-block"> |
| | | <div class="detail-block-title">éä»¶å表</div> |
| | | <div class="attachment-list"> |
| | | <div v-for="file in attachmentList" |
| | | :key="file.id" |
| | | class="attachment-item"> |
| | | <el-icon class="file-icon"> |
| | | <Paperclip /> |
| | | </el-icon> |
| | | <span class="file-name" |
| | | :title="file.name || file.originalFilename"> |
| | | {{ file.name || file.originalFilename }} |
| | | </span> |
| | | <div class="file-actions"> |
| | | <el-link v-if="file.previewURL || file.url" |
| | | type="primary" |
| | | :underline="false" |
| | | @click="openFile(file.previewURL || file.url)">é¢è§</el-link> |
| | | <el-divider v-if="(file.previewURL || file.url) && file.downloadURL" |
| | | direction="vertical" /> |
| | | <el-link v-if="file.downloadURL" |
| | | type="primary" |
| | | :underline="false" |
| | | @click="openFile(file.downloadURL)">ä¸è½½</el-link> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { computed } from "vue"; |
| | | import { formatDisplayTime } from "../../approve-template/approveTemplateConstants.js"; |
| | | import { |
| | | approvalTypeLabel, |
| | | approvalTypeStyle, |
| | | approvalStatusLabel, |
| | | approvalStatusTagType, |
| | | resolveInstanceFormFields, |
| | | } from "../approveListConstants.js"; |
| | | import FormPayloadFields from "./FormPayloadFields.vue"; |
| | | import { computed } from "vue"; |
| | | import { Paperclip } from "@element-plus/icons-vue"; |
| | | import { formatDisplayTime } from "../../approve-template/approveTemplateConstants.js"; |
| | | import { |
| | | approvalTypeLabel, |
| | | approvalTypeStyle, |
| | | approvalStatusLabel, |
| | | approvalStatusTagType, |
| | | resolveInstanceFormFields, |
| | | } from "../approveListConstants.js"; |
| | | import FormPayloadFields from "./FormPayloadFields.vue"; |
| | | |
| | | const props = defineProps({ |
| | | row: { type: Object, default: () => ({}) }, |
| | | }); |
| | | const props = defineProps({ |
| | | row: { type: Object, default: () => ({}) }, |
| | | detailData: { type: Object, default: () => ({}) }, |
| | | }); |
| | | |
| | | const formResolved = computed(() => resolveInstanceFormFields(props.row)); |
| | | const formResolved = computed(() => resolveInstanceFormFields(props.row)); |
| | | |
| | | |
| | | // æ¯å¦ä¸ºç¹æ®å®¡æ¹ç±»åï¼éè´ãåè´§ãæ¥ä»·ï¼ |
| | | const isSpecialApprovalType = computed(() => { |
| | | return [5, 7, 6].includes(props.row.businessType); |
| | | }); |
| | | |
| | | // 详æ
æ°æ®ï¼ç´æ¥ä½¿ç¨ä¼ å
¥ç detail-data åæ°ï¼ |
| | | const detailData = computed(() => { |
| | | return props.detailData || {}; |
| | | }); |
| | | |
| | | const attachmentList = computed(() => { |
| | | const list = props.row.storageBlobVOList || props.row.storageBlobDTOs || []; |
| | | return Array.isArray(list) ? list : []; |
| | | }); |
| | | |
| | | function openFile(url) { |
| | | if (!url) return; |
| | | window.open(url, "_blank"); |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .approve-detail-panel { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 20px; |
| | | } |
| | | .detail-block-title { |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | color: var(--el-text-color-primary); |
| | | margin: 0 0 12px; |
| | | padding-left: 10px; |
| | | border-left: 3px solid var(--el-color-primary); |
| | | line-height: 1.4; |
| | | } |
| | | .approve-type-cell { |
| | | display: inline-block; |
| | | padding: 2px 10px; |
| | | border-radius: 4px; |
| | | font-size: 13px; |
| | | line-height: 1.5; |
| | | } |
| | | .reject-text { |
| | | color: var(--el-color-danger); |
| | | } |
| | | </style> |
| | | .approve-detail-panel { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 20px; |
| | | } |
| | | .detail-block-title { |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | color: var(--el-text-color-primary); |
| | | margin: 0 0 12px; |
| | | padding-left: 10px; |
| | | border-left: 3px solid var(--el-color-primary); |
| | | line-height: 1.4; |
| | | } |
| | | .approve-type-cell { |
| | | display: inline-block; |
| | | padding: 2px 10px; |
| | | border-radius: 4px; |
| | | font-size: 13px; |
| | | line-height: 1.5; |
| | | } |
| | | .reject-text { |
| | | color: var(--el-color-danger); |
| | | } |
| | | |
| | | .attachment-list { |
| | | display: grid; |
| | | grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); |
| | | gap: 12px; |
| | | } |
| | | .attachment-item { |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 10px 12px; |
| | | background-color: var(--el-fill-color-light); |
| | | border-radius: 6px; |
| | | border: 1px solid var(--el-border-color-lighter); |
| | | transition: all 0.3s; |
| | | } |
| | | .attachment-item:hover { |
| | | border-color: var(--el-color-primary-light-5); |
| | | background-color: var(--el-color-primary-light-9); |
| | | } |
| | | .file-icon { |
| | | font-size: 18px; |
| | | color: var(--el-text-color-secondary); |
| | | margin-right: 10px; |
| | | } |
| | | .file-name { |
| | | flex: 1; |
| | | font-size: 13px; |
| | | color: var(--el-text-color-primary); |
| | | white-space: nowrap; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | margin-right: 12px; |
| | | } |
| | | .file-actions { |
| | | display: flex; |
| | | align-items: center; |
| | | flex-shrink: 0; |
| | | } |
| | | </style> |
| | |
| | | class="approve-detail-dialog" |
| | | > |
| | | <div class="approve-detail-body"> |
| | | <ApproveDetailPanel :row="detailRow" /> |
| | | <ApproveDetailPanel :row="detailRow" :detail-data="detailData" /> |
| | | <div class="detail-block"> |
| | | <div class="detail-block-title"> |
| | | å®¡æ¹æµç¨ï¼{{ detailRow.tasks?.length || detailRow.flowNodes?.length || 0 }} é¡¹ï¼ |
| | |
| | | destroy-on-close |
| | | @closed="approveOpinion = ''" |
| | | > |
| | | <ApproveDetailPanel :row="approveDialog.row" /> |
| | | <ApproveDetailPanel :row="approveDialog.row" :detail-data="detailData" /> |
| | | <div class="detail-block mt16"> |
| | | <div class="detail-block-title"> |
| | | å®¡æ¹æµç¨ï¼{{ approveDialog.row?.tasks?.length || approveDialog.row?.flowNodes?.length || 0 }} é¡¹ï¼ |
| | |
| | | tableColumn, |
| | | detailDialog, |
| | | detailRow, |
| | | detailData, |
| | | reimburseDialog, |
| | | approveDialog, |
| | | approveOpinion, |
| | |
| | | border-left: 3px solid var(--el-color-primary); |
| | | line-height: 1.4; |
| | | } |
| | | </style> |
| | | </style> |
| | |
| | | saveApprovalInstance, |
| | | updateApprovalInstance, |
| | | } from "@/api/officeProcessAutomation/approvalInstance.js"; |
| | | import { getQuotationList } from "@/api/salesManagement/salesQuotation.js"; |
| | | import { getPurchaseByCode } from "@/api/procurementManagement/procurementLedger.js"; |
| | | import { getDeliveryDetailByShippingNo } from "@/api/salesManagement/deliveryLedger.js"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | |
| | | |
| | | const detailDialog = reactive({ visible: false }); |
| | | const detailRow = ref({}); |
| | | const detailData = ref({}); |
| | | |
| | | const approveDialog = reactive({ visible: false, row: null }); |
| | | const approveOpinion = ref(""); |
| | |
| | | })); |
| | | |
| | | const tableColumn = ref([ |
| | | { label: "ç³è¯·äººç¼å·", prop: "applicantNo", width: 110 }, |
| | | // { label: "ç³è¯·äººç¼å·", prop: "applicantNo", width: 110 }, |
| | | { label: "ç³è¯·äººåç§°", prop: "applicantName", minWidth: 100 }, |
| | | { label: "模æ¿ç±»å", prop: "businessName", minWidth: 120 }, |
| | | { |
| | |
| | | fetchBusinessTypeOptions(), |
| | | listApprovalTemplate(TEMPLATE_TYPE_CUSTOM), |
| | | ]); |
| | | submitBusinessTypeOptions.value = typeOptions; |
| | | submitBusinessTypeOptions.value = typeOptions.filter((x) => ![5, 6, 7].includes(x.value)); |
| | | allSubmitTemplates.value = unwrapTemplateList(customRes) |
| | | .filter((row) => mapEnabledFromApi(row.enabled)) |
| | | .map(mapSubmitTemplateCard); |
| | |
| | | await openReimburseDetail(row, "detail"); |
| | | return; |
| | | } |
| | | |
| | | detailRow.value = { ...row }; |
| | | // æ¥ä»·å®¡æ¹ï¼ç¨å®¡æ¹äºç±å段æ¿è½½ç"æ¥ä»·åå·"廿¥æ¥ä»·å表 |
| | | if (row.businessType === 6) { |
| | | const quotationNo = row?.quotationNo; |
| | | if (quotationNo) { |
| | | const res = await getQuotationList({ quotationNo }); |
| | | const records = res?.data?.records || []; |
| | | detailData.value = records[0] || {}; |
| | | } |
| | | } |
| | | |
| | | // éè´å®¡æ¹ï¼ç¨å®¡æ¹äºç±å段æ¿è½½ç"éè´ååå·"廿¥éè´è¯¦æ
|
| | | else if (row.businessType === 5) { |
| | | const purchaseContractNumber = row?.purchaseContractNumber; |
| | | if (purchaseContractNumber) { |
| | | const res = await getPurchaseByCode({ purchaseContractNumber }); |
| | | detailData.value = res || {}; |
| | | } |
| | | } |
| | | |
| | | // å货审æ¹ï¼ç¨å®¡æ¹äºç±å段æ¿è½½ç"åè´§åå·"廿¥å货详æ
|
| | | else if (row.businessType === 7) { |
| | | const shippingNo = row?.shippingNo; |
| | | if (shippingNo) { |
| | | const res = await getDeliveryDetailByShippingNo({ shippingNo }); |
| | | detailData.value = res?.data || res || {}; |
| | | } |
| | | } |
| | | |
| | | // å
¶ä»å®¡æ¹ç±»å |
| | | else { |
| | | detailData.value = {}; |
| | | } |
| | | |
| | | detailDialog.visible = true; |
| | | } |
| | | |
| | | async function openApprove(row) { |
| | | |
| | | if (inferReimburseModuleKeyFromInstance(row)) { |
| | | approveOpinion.value = ""; |
| | | await openReimburseDetail(row, "approve"); |
| | |
| | | } |
| | | approveDialog.row = { ...row }; |
| | | approveOpinion.value = ""; |
| | | // æ¥ä»·å®¡æ¹ï¼ç¨å®¡æ¹äºç±å段æ¿è½½ç"æ¥ä»·åå·"廿¥æ¥ä»·å表 |
| | | if (row.businessType === 6) { |
| | | const quotationNo = row?.quotationNo; |
| | | if (quotationNo) { |
| | | const res = await getQuotationList({ quotationNo }); |
| | | const records = res?.data?.records || []; |
| | | detailData.value = records[0] || {}; |
| | | } |
| | | } |
| | | |
| | | // éè´å®¡æ¹ï¼ç¨å®¡æ¹äºç±å段æ¿è½½ç"éè´ååå·"廿¥éè´è¯¦æ
|
| | | else if (row.businessType === 5) { |
| | | const purchaseContractNumber = row?.purchaseContractNumber; |
| | | if (purchaseContractNumber) { |
| | | const res = await getPurchaseByCode({ purchaseContractNumber }); |
| | | detailData.value = res || {}; |
| | | } |
| | | } |
| | | |
| | | // å货审æ¹ï¼ç¨å®¡æ¹äºç±å段æ¿è½½ç"åè´§åå·"廿¥å货详æ
|
| | | else if (row.businessType === 7) { |
| | | const shippingNo = row?.shippingNo; |
| | | if (shippingNo) { |
| | | const res = await getDeliveryDetailByShippingNo({ shippingNo }); |
| | | detailData.value = res?.data || res || {}; |
| | | } |
| | | } |
| | | |
| | | // å
¶ä»å®¡æ¹ç±»å |
| | | else { |
| | | detailData.value = {}; |
| | | } |
| | | approveDialog.visible = true; |
| | | } |
| | | |
| | |
| | | tableColumn, |
| | | detailDialog, |
| | | detailRow, |
| | | detailData, |
| | | reimburseDialog, |
| | | approveDialog, |
| | | approveOpinion, |
| | |
| | | openApprove, |
| | | fetchApprovalList, |
| | | }; |
| | | } |
| | | } |
| | |
| | | import { computed } from "vue"; |
| | | import { |
| | | businessApprovalStatusLabel, |
| | | businessApprovalStatusTagType, |
| | | formatFieldDisplayValue, |
| | | resolveInstanceFormFields, |
| | | } from "../approve-list/approveListConstants.js"; |
| | | import { |
| | | INSTANCE_NO_SEARCH_MODULE_KEYS, |
| | | INSTANCE_NO_TABLE_COLUMN, |
| | | } from "./approvalInstanceListSearch.js"; |
| | | import { businessApprovalStatusLabel, businessApprovalStatusTagType, formatFieldDisplayValue, resolveInstanceFormFields } from "../approve-list/approveListConstants.js"; |
| | | import { INSTANCE_NO_SEARCH_MODULE_KEYS, INSTANCE_NO_TABLE_COLUMN } from "./approvalInstanceListSearch.js"; |
| | | |
| | | /** å表/详æ
ä¸åæ¾ä¸ºç¬ç«åçå¡«æ¥é¡¹ keyï¼é¿å
è¦çå®ä¾ç³»ç»åæ®µï¼ */ |
| | | const DEFAULT_EXCLUDE_KEYS = new Set([ |
| | | "summary", |
| | | "status", |
| | | "approvalStatus", |
| | | "approvalstatus", |
| | | "instanceStatus", |
| | | "publishStatus", |
| | | "newsStatus", |
| | | ]); |
| | | const DEFAULT_EXCLUDE_KEYS = new Set(["summary", "status", "approvalStatus", "approvalstatus", "instanceStatus", "publishStatus", "newsStatus"]); |
| | | |
| | | /** enrich åå¿
é¡»ä¿ççå®ä¾å段ï¼ä¸è¢« formConfig éºå¹³è¦çï¼ */ |
| | | const PRESERVE_INSTANCE_FIELDS = [ |
| | |
| | | "unread", |
| | | "currentLevel", |
| | | "newsStatus", |
| | | "storageBlobVOList", |
| | | "storageBlobDTOs", |
| | | ]; |
| | | |
| | | /** |
| | |
| | | if (!f?.key || DEFAULT_EXCLUDE_KEYS.has(f.key)) continue; |
| | | const val = formPayload[f.key]; |
| | | let text = formatFieldDisplayValue(f, val, caches); |
| | | if ( |
| | | text === String(val) && |
| | | row?.applicantName && |
| | | (f.label === "ç³è¯·äºº" || f.key === "applicant" || f.key === "applicantName") |
| | | ) { |
| | | const idMatch = |
| | | String(val) === String(row.applicantId) || |
| | | String(val) === String(row.applicantNo); |
| | | if (text === String(val) && row?.applicantName && (f.label === "ç³è¯·äºº" || f.key === "applicant" || f.key === "applicantName")) { |
| | | const idMatch = String(val) === String(row.applicantId) || String(val) === String(row.applicantNo); |
| | | if (idMatch) text = row.applicantName; |
| | | } |
| | | formDisplay[f.key] = text; |
| | |
| | | * ä»å表é¦è¡ formConfig çæä¸»è¡¨å¨æåï¼label åèªæ¨¡æ¿å段 labelï¼ |
| | | */ |
| | | export function getFormConfigFieldColumns(firstRow, { excludeKeys = DEFAULT_EXCLUDE_KEYS } = {}) { |
| | | const fields = (firstRow?.formFieldDefs || []).filter( |
| | | (f) => f?.key && !excludeKeys.has(f.key) |
| | | ); |
| | | return fields.map((f) => ({ |
| | | const fields = (firstRow?.formFieldDefs || []).filter(f => f?.key && !excludeKeys.has(f.key)); |
| | | return fields.map(f => ({ |
| | | label: f.label || f.key, |
| | | prop: f.key, |
| | | minWidth: f.type === "textarea" ? 200 : f.type === "datetimerange" ? 160 : 120, |
| | |
| | | * ä¸å¡ç³è¯·ä¸»è¡¨åï¼åºå®å + formConfig 卿å + 审æ¹ç¶æ + æä½ |
| | | */ |
| | | export function buildInstanceTableColumns(tableDataRef, buildTableActions, options = {}) { |
| | | const { |
| | | moduleKey, |
| | | excludeKeys = DEFAULT_EXCLUDE_KEYS, |
| | | beforeFormColumns = [], |
| | | extraColumns = [], |
| | | afterFormColumns = [], |
| | | actionWidth = 260, |
| | | } = options; |
| | | const { moduleKey, excludeKeys = DEFAULT_EXCLUDE_KEYS, beforeFormColumns = [], extraColumns = [], afterFormColumns = [], actionWidth = 260 } = options; |
| | | |
| | | const leadingCols = |
| | | moduleKey && INSTANCE_NO_SEARCH_MODULE_KEYS.has(moduleKey) |
| | | ? [INSTANCE_NO_TABLE_COLUMN] |
| | | : []; |
| | | const leadingCols = moduleKey && INSTANCE_NO_SEARCH_MODULE_KEYS.has(moduleKey) ? [INSTANCE_NO_TABLE_COLUMN] : []; |
| | | |
| | | return computed(() => { |
| | | const formCols = getFormConfigFieldColumns(tableDataRef.value?.[0], { excludeKeys }); |
| | |
| | | prop: "approvalStatus", |
| | | width: 110, |
| | | dataType: "tag", |
| | | formatData: (v) => businessApprovalStatusLabel(v), |
| | | formatType: (v) => businessApprovalStatusTagType(v), |
| | | formatData: v => businessApprovalStatusLabel(v), |
| | | formatType: v => businessApprovalStatusTagType(v), |
| | | }, |
| | | { |
| | | dataType: "action", |
| | |
| | | import dayjs from "dayjs"; |
| | | import { APPROVAL_MODULE_KEYS } from "./approvalModuleRegistry.js"; |
| | | |
| | | /** æ¯æå®¡æ¹åå·æ¥è¯¢/主表å±ç¤ºç审æ¹ç³è¯·æ¨¡å */ |
| | |
| | | return no ? { instanceNo: no } : {}; |
| | | } |
| | | |
| | | /** ç»è£
approvalInstanceDto æ¥è¯¢ç段ï¼ç³è¯·äºº + 审æ¹åå·ï¼ */ |
| | | /** ç»è£
approvalInstanceDto æ¥è¯¢ç段ï¼ç³è¯·äºº + 审æ¹åå· + ç¶æ + æ¶é´èå´ï¼ */ |
| | | export function buildApprovalInstanceSearchDto(searchForm = {}, extraParams = {}) { |
| | | const dto = { |
| | | ...(extraParams && typeof extraParams === "object" ? extraParams : {}), |
| | | }; |
| | | Object.assign(dto, pickApplicantFromSearchForm(searchForm)); |
| | | Object.assign(dto, pickInstanceNoFromSearchForm(searchForm)); |
| | | |
| | | // 审æ¹ç¶æ |
| | | if (searchForm?.status) { |
| | | dto.status = searchForm.status; |
| | | } |
| | | |
| | | // å建æ¶é´èå´ |
| | | const range = searchForm?.createTimeRange; |
| | | if (Array.isArray(range) && range[0]) { |
| | | dto.createTimeStart = range[0] + (range[0].includes(":") ? "" : " 00:00:00"); |
| | | } |
| | | if (Array.isArray(range) && range[1]) { |
| | | dto.createTimeEnd = range[1] + (range[1].includes(":") ? "" : " 23:59:59"); |
| | | } |
| | | |
| | | delete dto.createTime; |
| | | delete dto.createTimeStart; |
| | | delete dto.createTimeEnd; |
| | | return dto; |
| | | } |
| | | |
| | |
| | | function matchApplicantKeyword(row, keyword) { |
| | | const kw = (keyword || "").trim().toLowerCase(); |
| | | if (!kw) return true; |
| | | const parts = [ |
| | | row?.applicantName, |
| | | row?.applicantNo, |
| | | row?.applicantId, |
| | | getRowPayloadValue(row, ["applicant", "applicantName", "applicantId"]), |
| | | ] |
| | | .filter((v) => v != null && v !== "") |
| | | .map((v) => String(v).toLowerCase()); |
| | | return parts.some((p) => p.includes(kw)); |
| | | const parts = [row?.applicantName, row?.applicantNo, row?.applicantId, getRowPayloadValue(row, ["applicant", "applicantName", "applicantId"])] |
| | | .filter(v => v != null && v !== "") |
| | | .map(v => String(v).toLowerCase()); |
| | | return parts.some(p => p.includes(kw)); |
| | | } |
| | | |
| | | function matchApplicantId(row, applicantId) { |
| | | if (applicantId == null || applicantId === "") return true; |
| | | const id = String(applicantId); |
| | | if (row?.applicantId != null && String(row.applicantId) === id) return true; |
| | | const payloadApplicant = getRowPayloadValue(row, [ |
| | | "applicant", |
| | | "applicantId", |
| | | "applicantUserId", |
| | | ]); |
| | | const payloadApplicant = getRowPayloadValue(row, ["applicant", "applicantId", "applicantUserId"]); |
| | | return String(payloadApplicant) === id; |
| | | } |
| | | |
| | |
| | | function matchInstanceNo(row, instanceNo) { |
| | | const kw = (instanceNo || "").trim().toLowerCase(); |
| | | if (!kw) return true; |
| | | const parts = [row?.instanceNo, row?.bizId] |
| | | .filter((v) => v != null && v !== "") |
| | | .map((v) => String(v).toLowerCase()); |
| | | return parts.some((p) => p.includes(kw)); |
| | | const parts = [row?.instanceNo, row?.bizId].filter(v => v != null && v !== "").map(v => String(v).toLowerCase()); |
| | | return parts.some(p => p.includes(kw)); |
| | | } |
| | | |
| | | /** æ¯å¦åå¨å表ç鿡件ï¼ç³è¯·äºº / 审æ¹åå·ï¼ */ |
| | | /** æ¯å¦åå¨å表ç鿡件ï¼ç³è¯·äºº / 审æ¹åå· / ç¶æ / æ¶é´èå´ï¼ */ |
| | | export function hasActiveModuleSearch(moduleKey, searchForm = {}) { |
| | | const sf = searchForm || {}; |
| | | if ((sf.instanceNo || "").trim()) return true; |
| | | if ((sf.applicantKeyword || "").trim()) return true; |
| | | if ((sf.applicantName || "").trim()) return true; |
| | | return sf.applicantId != null && sf.applicantId !== ""; |
| | | if (sf.applicantId != null && sf.applicantId !== "") return true; |
| | | if (sf.status) return true; |
| | | if (Array.isArray(sf.createTimeRange) && sf.createTimeRange.length === 2) return true; |
| | | return false; |
| | | } |
| | | |
| | | /** æç³è¯·äººã审æ¹åå·åå端å
åºçé */ |
| | | /** æç³è¯·äººã审æ¹åå·ãç¶æãæ¶é´èå´åå端å
åºçé */ |
| | | export function filterInstanceRowsByModuleSearch(moduleKey, rows, searchForm = {}) { |
| | | const sf = searchForm || {}; |
| | | const list = Array.isArray(rows) ? rows : []; |
| | | if (!hasActiveModuleSearch(moduleKey, sf)) return list; |
| | | |
| | | return list.filter( |
| | | (row) => |
| | | matchInstanceNo(row, sf.instanceNo) && |
| | | matchApplicantId(row, sf.applicantId) && |
| | | matchApplicantKeyword(row, sf.applicantKeyword || sf.applicantName) |
| | | ); |
| | | return list.filter(row => { |
| | | // 审æ¹åå· |
| | | if (!matchInstanceNo(row, sf.instanceNo)) return false; |
| | | // ç³è¯·äºº |
| | | if (!matchApplicantId(row, sf.applicantId)) return false; |
| | | if (!matchApplicantKeyword(row, sf.applicantKeyword || sf.applicantName)) return false; |
| | | // ç¶æ |
| | | if (sf.status && String(row.statusRaw || row.status).toUpperCase() !== String(sf.status).toUpperCase()) { |
| | | return false; |
| | | } |
| | | // æ¶é´èå´ |
| | | if (Array.isArray(sf.createTimeRange) && sf.createTimeRange.length === 2) { |
| | | const rowTime = row.createTime || row.applyTime; |
| | | if (rowTime) { |
| | | const t = dayjs(rowTime); |
| | | const start = dayjs(sf.createTimeRange[0] + " 00:00:00"); |
| | | const end = dayjs(sf.createTimeRange[1] + " 23:59:59"); |
| | | if (t.isBefore(start) || t.isAfter(end)) return false; |
| | | } |
| | | } |
| | | return true; |
| | | }); |
| | | } |
| | |
| | | import { matchBusinessTypeValue } from "../approve-list/approveListConstants.js"; |
| | | |
| | | /** |
| | | * åä¸å¡æ¨¡åä¸å®¡æ¹æ¨¡æ¿ç±»åçæ å°ï¼é
ç½®åå
¥å£ï¼ |
| | | * businessType ä¸å端 TypeEnums / listPage 约å®ä¸è´ï¼åæ»æä¸¾å¼ï¼ |
| | |
| | | |
| | | <template v-if="detailAttachments.length"> |
| | | |
| | | <el-tag |
| | | |
| | | v-for="(f, i) in detailAttachments" |
| | | |
| | | :key="i" |
| | | |
| | | class="detail-attachment-tag" |
| | | |
| | | type="info" |
| | | |
| | | effect="plain" |
| | | |
| | | > |
| | | |
| | | {{ attachmentDisplayName(f) }} |
| | | |
| | | </el-tag> |
| | | <div class="detail-attachment-list"> |
| | | <div |
| | | v-for="(f, i) in detailAttachments" |
| | | :key="i" |
| | | class="detail-attachment-item" |
| | | @click="openAttachmentFile(f)" |
| | | > |
| | | <el-icon class="attachment-icon"><Document /></el-icon> |
| | | <span class="attachment-name">{{ attachmentDisplayName(f) }}</span> |
| | | <el-icon class="attachment-download"><Download /></el-icon> |
| | | </div> |
| | | </div> |
| | | |
| | | </template> |
| | | |
| | |
| | | |
| | | <script setup> |
| | | |
| | | import { ArrowRight, Plus, RefreshRight } from "@element-plus/icons-vue"; |
| | | import { ArrowRight, Document, Download, Plus, RefreshRight } from "@element-plus/icons-vue"; |
| | | |
| | | import { ElMessage } from "element-plus"; |
| | | |
| | |
| | | |
| | | } |
| | | |
| | | function openAttachmentFile(file) { |
| | | const url = file?.url || file?.previewURL || file?.downloadURL || file?.previewUrl || ""; |
| | | if (url) { |
| | | window.open(url, "_blank"); |
| | | } else { |
| | | ElMessage.warning("æ æ³æå¼è¯¥éä»¶"); |
| | | } |
| | | } |
| | | |
| | | |
| | | function unwrapArray(payload) { |
| | |
| | | |
| | | } |
| | | |
| | | .detail-attachment-tag { |
| | | .detail-attachment-list { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 8px; |
| | | } |
| | | |
| | | margin: 0 8px 8px 0; |
| | | .detail-attachment-item { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 6px; |
| | | padding: 8px 12px; |
| | | background: var(--el-fill-color-light); |
| | | border-radius: 6px; |
| | | cursor: pointer; |
| | | transition: background 0.2s; |
| | | } |
| | | |
| | | .detail-attachment-item:hover { |
| | | background: var(--el-fill-color); |
| | | } |
| | | |
| | | .attachment-icon { |
| | | font-size: 16px; |
| | | color: var(--el-text-color-regular); |
| | | } |
| | | |
| | | .attachment-name { |
| | | font-size: 14px; |
| | | color: var(--el-text-color-primary); |
| | | } |
| | | |
| | | .attachment-download { |
| | | font-size: 14px; |
| | | color: var(--el-text-color-secondary); |
| | | } |
| | | |
| | | .text-muted { |
| | |
| | | }); |
| | | } |
| | | |
| | | function openFormDialog(mode, row) { |
| | | async function openFormDialog(mode, row) { |
| | | formDialog.mode = mode; |
| | | formDialog.title = mode === "add" ? "æ°å»ºå®¡æ¹æ¨¡æ¿" : "ç¼è¾å®¡æ¹æ¨¡æ¿"; |
| | | resetForm(mode === "edit" ? row : null); |
| | | if (mode === "edit" && row?.id) { |
| | | // ç¼è¾æ¶å
æ¥è¯¢è¯¦æ
è·å宿´æ°æ®ï¼å
å«éä»¶ï¼ |
| | | try { |
| | | const res = await getApprovalTemplateDetail(row.id); |
| | | const detailData = mapTemplateFromApi(unwrapTemplateDetail(res)); |
| | | resetForm(detailData); |
| | | } catch { |
| | | resetForm(row); |
| | | } |
| | | } else { |
| | | resetForm(mode === "edit" ? row : null); |
| | | } |
| | | formDialog.visible = true; |
| | | } |
| | | |
| | |
| | | <template> |
| | | <div> |
| | | <el-dialog |
| | | v-model="dialogFormVisible" |
| | | title="详æ
" |
| | | width="70%" |
| | | @close="closeDia" |
| | | > |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :tableLoading="tableLoading" |
| | | height="600" |
| | | ></PIMTable> |
| | | <el-dialog v-model="dialogFormVisible" |
| | | title="详æ
" |
| | | width="70%" |
| | | @close="closeDia"> |
| | | <PIMTable rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :tableLoading="tableLoading" |
| | | height="600"></PIMTable> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | <Files ref="filesDia"></Files> |
| | | <FileList v-if="fileDialogVisible" |
| | | v-model:visible="fileDialogVisible" |
| | | :record-type="'staff_contract'" |
| | | :record-id="recordId" /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref} from "vue"; |
| | | import {findStaffContractListPage} from "@/api/personnelManagement/staffContract.js"; |
| | | const Files = defineAsyncComponent(() => import( "@/views/personnelManagement/contractManagement/filesDia.vue")); |
| | | const { proxy } = getCurrentInstance() |
| | | const emit = defineEmits(['close']) |
| | | const filesDia = ref() |
| | | const dialogFormVisible = ref(false); |
| | | const operationType = ref('') |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "ååå¹´é", |
| | | prop: "contractTerm", |
| | | }, |
| | | { |
| | | label: "ååå¼å§æ¥æ", |
| | | prop: "contractStartTime", |
| | | }, |
| | | { |
| | | label: "ååç»ææ¥æ", |
| | | prop: "contractEndTime", |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: 'right', |
| | | width: 120, |
| | | operation: [ |
| | | { |
| | | name: "ä¸ä¼ éä»¶", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | filesDia.value.openDialog( row,'åå') |
| | | import { ref, defineAsyncComponent, getCurrentInstance } from "vue"; |
| | | import { findStaffContractListPage } from "@/api/personnelManagement/staffContract.js"; |
| | | const FileList = defineAsyncComponent(() => |
| | | import("@/components/Dialog/FileList.vue") |
| | | ); |
| | | const { proxy } = getCurrentInstance(); |
| | | const emit = defineEmits(["close"]); |
| | | const fileDialogVisible = ref(false); |
| | | const recordId = ref(0); |
| | | const dialogFormVisible = ref(false); |
| | | const operationType = ref(""); |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "ååå¹´é", |
| | | prop: "contractTerm", |
| | | }, |
| | | { |
| | | label: "ååå¼å§æ¥æ", |
| | | prop: "contractStartTime", |
| | | }, |
| | | { |
| | | label: "ååç»ææ¥æ", |
| | | prop: "contractEndTime", |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 120, |
| | | operation: [ |
| | | { |
| | | name: "éä»¶", |
| | | type: "text", |
| | | clickFun: row => { |
| | | recordId.value = row.id; |
| | | fileDialogVisible.value = true; |
| | | }, |
| | | }, |
| | | } |
| | | ], |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | ], |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openDialog = (type, row) => { |
| | | operationType.value = type; |
| | | dialogFormVisible.value = true; |
| | | if (operationType.value === 'edit') { |
| | | findStaffContractListPage({staffOnJobId: row.id}).then(res => { |
| | | tableData.value = res.data.records |
| | | }) |
| | | } |
| | | } |
| | | // æå¼å¼¹æ¡ |
| | | const openDialog = (type, row) => { |
| | | operationType.value = type; |
| | | dialogFormVisible.value = true; |
| | | if (operationType.value === "edit") { |
| | | findStaffContractListPage({ staffOnJobId: row.id }).then(res => { |
| | | tableData.value = res.data.records; |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | const openUploadFile = (row) => { |
| | | filesDia.value.open = true |
| | | filesDia.value.row = row |
| | | } |
| | | |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | dialogFormVisible.value = false; |
| | | emit('close') |
| | | }; |
| | | defineExpose({ |
| | | openDialog, |
| | | }); |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | dialogFormVisible.value = false; |
| | | emit("close"); |
| | | }; |
| | | defineExpose({ |
| | | openDialog, |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | |
| | | </style> |
| | |
| | | <template> |
| | | <div> |
| | | <el-dialog |
| | | v-model="dialogFormVisible" |
| | | title="详æ
" |
| | | width="70%" |
| | | @close="closeDia" |
| | | > |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :tableLoading="tableLoading" |
| | | height="600" |
| | | ></PIMTable> |
| | | <el-dialog v-model="dialogFormVisible" |
| | | title="详æ
" |
| | | width="70%" |
| | | @close="closeDia"> |
| | | <PIMTable rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :tableLoading="tableLoading" |
| | | height="600"></PIMTable> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | <Files ref="filesDia"></Files> |
| | | <FileList v-if="fileDialogVisible" |
| | | v-model:visible="fileDialogVisible" |
| | | :record-type="'staff_contract'" |
| | | :record-id="recordId" /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref} from "vue"; |
| | | import {findStaffContractListPage} from "@/api/personnelManagement/staffContract.js"; |
| | | const Files = defineAsyncComponent(() => import( "@/views/personnelManagement/contractManagement/filesDia.vue")); |
| | | const { proxy } = getCurrentInstance() |
| | | const emit = defineEmits(['close']) |
| | | const filesDia = ref() |
| | | const dialogFormVisible = ref(false); |
| | | const operationType = ref('') |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "ååå¹´é", |
| | | prop: "contractTerm", |
| | | }, |
| | | { |
| | | label: "ååå¼å§æ¥æ", |
| | | prop: "contractStartTime", |
| | | }, |
| | | { |
| | | label: "ååç»ææ¥æ", |
| | | prop: "contractEndTime", |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: 'right', |
| | | width: 120, |
| | | operation: [ |
| | | { |
| | | name: "ä¸ä¼ éä»¶", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | filesDia.value.openDialog( row,'åå') |
| | | import { ref, defineAsyncComponent, getCurrentInstance } from "vue"; |
| | | import { findStaffContractListPage } from "@/api/personnelManagement/staffContract.js"; |
| | | const FileList = defineAsyncComponent(() => |
| | | import("@/components/Dialog/FileList.vue") |
| | | ); |
| | | const { proxy } = getCurrentInstance(); |
| | | const emit = defineEmits(["close"]); |
| | | const fileDialogVisible = ref(false); |
| | | const recordId = ref(0); |
| | | const dialogFormVisible = ref(false); |
| | | const operationType = ref(""); |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "ååå¹´é", |
| | | prop: "contractTerm", |
| | | }, |
| | | { |
| | | label: "ååå¼å§æ¥æ", |
| | | prop: "contractStartTime", |
| | | }, |
| | | { |
| | | label: "ååç»ææ¥æ", |
| | | prop: "contractEndTime", |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 120, |
| | | operation: [ |
| | | { |
| | | name: "éä»¶", |
| | | type: "text", |
| | | clickFun: row => { |
| | | recordId.value = row.id; |
| | | fileDialogVisible.value = true; |
| | | }, |
| | | }, |
| | | } |
| | | ], |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | ], |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openDialog = (type, row) => { |
| | | operationType.value = type; |
| | | dialogFormVisible.value = true; |
| | | if (operationType.value === 'edit') { |
| | | findStaffContractListPage({staffOnJobId: row.id}).then(res => { |
| | | tableData.value = res.data.records |
| | | }) |
| | | } |
| | | } |
| | | // æå¼å¼¹æ¡ |
| | | const openDialog = (type, row) => { |
| | | operationType.value = type; |
| | | dialogFormVisible.value = true; |
| | | if (operationType.value === "edit") { |
| | | findStaffContractListPage({ staffOnJobId: row.id }).then(res => { |
| | | tableData.value = res.data.records; |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | const openUploadFile = (row) => { |
| | | filesDia.value.open = true |
| | | filesDia.value.row = row |
| | | } |
| | | |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | dialogFormVisible.value = false; |
| | | emit('close') |
| | | }; |
| | | defineExpose({ |
| | | openDialog, |
| | | }); |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | dialogFormVisible.value = false; |
| | | emit("close"); |
| | | }; |
| | | defineExpose({ |
| | | openDialog, |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | |
| | | </style> |
| | |
| | | </div> |
| | | <div class="table_list"> |
| | | <div style="display: flex;justify-content: flex-end;margin-bottom: 20px;"> |
| | | <el-button type="success" |
| | | plain |
| | | @click="handleBatchGenerate">æ¹éçææ°æ®</el-button> |
| | | <el-button type="primary" |
| | | @click="openForm('add')">æ°å¢å°è´¦</el-button> |
| | | <el-button type="primary" |
| | |
| | | prop="specificationModel" /> |
| | | <el-table-column label="åä½" |
| | | prop="unit" /> |
| | | <el-table-column label="å
¥åºå®¡æ ¸ç¶æ" |
| | | <el-table-column label="å
¥åºå®¡æ ¸ç¶æ" |
| | | prop="stockInApprovalStatus" |
| | | width="120"> |
| | | <template #default="scope"> |
| | |
| | | getOptions, |
| | | getPurchaseTemplateList, |
| | | delPurchaseTemplate, |
| | | batchGeneratePurchaseInboundSteps, |
| | | } from "@/api/procurementManagement/procurementLedger.js"; |
| | | import useFormData from "@/hooks/useFormData.js"; |
| | | const FileList = defineAsyncComponent(() => |
| | |
| | | // è·åå
¥åºç¶ææ ç¾ç±»å |
| | | const getStockInStatusType = status => { |
| | | const typeMap = { |
| | | "å¾
å
¥åº": "info", // å¾
å
¥åº - ç°è² |
| | | "å
¥åºä¸": "warning", // å
¥åºä¸ - æ©è² |
| | | "å®å
¨å
¥åº": "success", // å®å
¨å
¥åº - ç»¿è² |
| | | å¾
å
¥åº: "info", // å¾
å
¥åº - ç°è² |
| | | å
¥åºä¸: "warning", // å
¥åºä¸ - æ©è² |
| | | å®å
¨å
¥åº: "success", // å®å
¨å
¥åº - ç»¿è² |
| | | }; |
| | | return typeMap[status] || ""; |
| | | }; |
| | |
| | | // è·åå
¥åºå®¡æ ¸ç¶ææ ç¾ç±»å |
| | | const getStockInApprovalStatusType = status => { |
| | | const typeMap = { |
| | | "å¾
å
¥åº": "info", // å¾
å
¥åº - ç°è² |
| | | "å
¥åºä¸": "warning", // å
¥åºä¸ - æ©è² |
| | | "å®å
¨å
¥åº": "success", // å®å
¨å
¥åº - ç»¿è² |
| | | å¾
å
¥åº: "info", // å¾
å
¥åº - ç°è² |
| | | å
¥åºä¸: "warning", // å
¥åºä¸ - æ©è² |
| | | å®å
¨å
¥åº: "success", // å®å
¨å
¥åº - ç»¿è² |
| | | }; |
| | | return typeMap[status] || ""; |
| | | }; |
| | |
| | | }, |
| | | rules: { |
| | | purchaseContractNumber: [ |
| | | { required: true, message: "请è¾å
¥", trigger: "blur" }, |
| | | { required: false, message: "请è¾å
¥", trigger: "blur" }, |
| | | ], |
| | | projectName: [ |
| | | { required: true, message: "请è¾å
¥é¡¹ç®åç§°", trigger: "blur" }, |
| | |
| | | const openForm = async (type, row) => { |
| | | // ç¼è¾æ¶æ£æ¥å
¥åºç¶æï¼å®å
¨å
¥åºæ¶ä¸è½ç¼è¾ |
| | | if (type === "edit" && row) { |
| | | if (row.stockInStatus === 'å®å
¨å
¥åº') { |
| | | if (row.stockInStatus === "å®å
¨å
¥åº") { |
| | | proxy.$modal.msgWarning("å®å
¨å
¥åºç¶æçè®°å½ä¸è½ç¼è¾"); |
| | | return; |
| | | } |
| | |
| | | |
| | | form.value.entryDate = getCurrentDate(); |
| | | |
| | | if (type === "add") { |
| | | // æ°å¢æ¶çæéè´ååå· |
| | | try { |
| | | const purchaseNoRes = await createPurchaseNo(); |
| | | if (purchaseNoRes?.data) { |
| | | form.value.purchaseContractNumber = purchaseNoRes.data; |
| | | } |
| | | } catch (error) { |
| | | console.error("çæéè´ååå·å¤±è´¥:", error); |
| | | proxy.$modal.msgWarning("çæéè´ååå·å¤±è´¥"); |
| | | } |
| | | } else if (type === "edit" && row?.id) { |
| | | if (type === "edit" && row?.id) { |
| | | // ç¼è¾æ¶å è½½æ°æ® |
| | | currentId.value = row.id; |
| | | try { |
| | |
| | | form.value = { ...purchaseRes, stockInStatus: row.stockInStatus }; |
| | | fileList.value = purchaseRes.storageBlobVOS || []; |
| | | // ä½¿ç¨ productList æ¥å£è·å产åå表ï¼ä»¥è·åå
¥åºå®¡æ ¸ç¶æ |
| | | const productRes = await productList({ salesLedgerId: row.id, type: 2 }); |
| | | const productRes = await productList({ |
| | | salesLedgerId: row.id, |
| | | type: 2, |
| | | }); |
| | | productData.value = productRes.data || []; |
| | | } catch (error) { |
| | | console.error("å è½½éè´å°è´¦æ°æ®å¤±è´¥:", error); |
| | |
| | | |
| | | // æäº¤è¡¨å |
| | | const submitForm = () => { |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | proxy.$refs["formRef"].validate(async valid => { |
| | | if (valid) { |
| | | if (productData.value.length > 0) { |
| | | // æ°å¢æ¶ï¼éè¦ä»æ¯ä¸ªäº§å对象ä¸å é¤ id åæ®µ |
| | |
| | | delete submitData.id; |
| | | } |
| | | |
| | | // 妿éè´ååå·ä¸ºç©ºï¼åæ ¹æ®å½å
¥æ¥æèªå¨çæ |
| | | if (!submitData.purchaseContractNumber) { |
| | | try { |
| | | const purchaseNoRes = await createPurchaseNo(submitData.entryDate); |
| | | if (purchaseNoRes?.data) { |
| | | submitData.purchaseContractNumber = purchaseNoRes.data; |
| | | } |
| | | } catch (error) { |
| | | console.error("çæéè´ååå·å¤±è´¥:", error); |
| | | proxy.$modal.msgWarning("çæéè´ååå·å¤±è´¥"); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | addOrEditPurchase(submitData).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | |
| | | // æå¼äº§åå¼¹æ¡ |
| | | const openProductForm = async (type, row, index) => { |
| | | // ç¼è¾æ¶æ£æ¥äº§åå
¥åºå®¡æ ¸ç¶æï¼å®å
¨å
¥åºæ¶ä¸è½ç¼è¾ |
| | | if (type === "edit" && row && row.stockInApprovalStatus === 'å®å
¨å
¥åº') { |
| | | if (type === "edit" && row && row.stockInApprovalStatus === "å®å
¨å
¥åº") { |
| | | proxy.$modal.msgWarning("å®å
¨å
¥åºç¶æç产åä¸è½ç¼è¾"); |
| | | return; |
| | | } |
| | |
| | | } |
| | | // æ£æ¥éä¸ç产å䏿¯å¦æå®å
¨å
¥åºç |
| | | const hasFullyStocked = productSelectedRows.value.some( |
| | | row => row.stockInApprovalStatus === 'å®å
¨å
¥åº' |
| | | row => row.stockInApprovalStatus === "å®å
¨å
¥åº" |
| | | ); |
| | | if (hasFullyStocked) { |
| | | proxy.$modal.msgWarning("éä¸ç产åä¸å
å«å®å
¨å
¥åºç产åï¼æ æ³å é¤"); |
| | |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | |
| | | const handleBatchGenerate = async () => { |
| | | if (selectedRows.value.length === 0) { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | | } |
| | | const ids = selectedRows.value.map((item) => item.id); |
| | | |
| | | ElMessageBox.confirm("确认æ¹éçææ°æ®ï¼", "æ¹éçæ", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "info", |
| | | }) |
| | | .then(() => { |
| | | proxy.$modal.loading("æ£å¨æ¹éçææ°æ®ï¼è¯·ç¨å..."); |
| | | batchGeneratePurchaseInboundSteps({ ids }) |
| | | .then((res) => { |
| | | proxy.$modal.msgSuccess("æ¹éçææå"); |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msgError("æ¹éçæå¤±è´¥"); |
| | | }) |
| | | .finally(() => { |
| | | proxy.$modal.closeLoading(); |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | |
| | | contractNo: form.value.salesLedgerId, |
| | | }); |
| | | if (code == 200) { |
| | | productData.value = data; |
| | | productData.value = data || []; |
| | | } |
| | | }; |
| | | |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <!-- æç´¢åºå --> |
| | | <el-card class="search-card" shadow="never"> |
| | | <el-form :model="searchForm" :inline="true" class="search-form"> |
| | | <el-card class="search-card" |
| | | shadow="never"> |
| | | <el-form :model="searchForm" |
| | | :inline="true" |
| | | class="search-form"> |
| | | <el-form-item label="计ååç§°"> |
| | | <el-input v-model="searchForm.planName" placeholder="请è¾å
¥è®¡ååç§°" clearable /> |
| | | <el-input v-model="searchForm.planName" |
| | | placeholder="请è¾å
¥è®¡ååç§°" |
| | | clearable /> |
| | | </el-form-item> |
| | | <el-form-item label="ç¶æ"> |
| | | <el-select v-model="searchForm.status" placeholder="è¯·éæ©ç¶æ" clearable style="width: 150px"> |
| | | <el-option label="å¯ç¨" value="active" /> |
| | | <el-option label="ç¦ç¨" value="disabled" /> |
| | | <el-select v-model="searchForm.status" |
| | | placeholder="è¯·éæ©ç¶æ" |
| | | clearable |
| | | style="width: 150px"> |
| | | <el-option label="å¯ç¨" |
| | | value="active" /> |
| | | <el-option label="ç¦ç¨" |
| | | value="disabled" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleSearch"> |
| | | <el-icon><Search /></el-icon> |
| | | <el-button type="primary" |
| | | @click="handleSearch"> |
| | | <el-icon> |
| | | <Search /> |
| | | </el-icon> |
| | | æç´¢ |
| | | </el-button> |
| | | <el-button @click="handleReset"> |
| | | <el-icon><Refresh /></el-icon> |
| | | <el-icon> |
| | | <Refresh /> |
| | | </el-icon> |
| | | éç½® |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </el-card> |
| | | |
| | | <!-- æä½æé® --> |
| | | <el-card class="table-card" shadow="never"> |
| | | <el-card class="table-card" |
| | | shadow="never"> |
| | | <div class="table-header"> |
| | | <div class="table-title">éè´è®¡åå表</div> |
| | | <div class="table-actions"> |
| | | <el-button type="primary" @click="handleAdd"> |
| | | <el-icon><Plus /></el-icon> |
| | | <el-button type="primary" |
| | | @click="handleAdd"> |
| | | <el-icon> |
| | | <Plus /> |
| | | </el-icon> |
| | | æ°å¢è®¡å |
| | | </el-button> |
| | | <el-button type="info" @click="handleExport"> |
| | | <el-icon><Download /></el-icon> |
| | | <el-button type="info" |
| | | @click="handleExport"> |
| | | <el-icon> |
| | | <Download /> |
| | | </el-icon> |
| | | å¯¼åº |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- æ°æ®è¡¨æ ¼ --> |
| | | <el-table |
| | | v-loading="loading" |
| | | :data="tableData" |
| | | stripe |
| | | border |
| | | style="width: 100%" |
| | | > |
| | | <el-table-column prop="planName" label="计ååç§°" min-width="150" /> |
| | | <el-table-column prop="description" label="æè¿°" min-width="200" show-overflow-tooltip /> |
| | | <el-table-column prop="formula" label="计ç®å
¬å¼" min-width="200" show-overflow-tooltip> |
| | | <el-table v-loading="loading" |
| | | :data="tableData" |
| | | stripe |
| | | border |
| | | style="width: 100%"> |
| | | <el-table-column prop="planName" |
| | | label="计ååç§°" |
| | | min-width="150" /> |
| | | <el-table-column prop="description" |
| | | label="æè¿°" |
| | | min-width="200" |
| | | show-overflow-tooltip /> |
| | | <el-table-column prop="formula" |
| | | label="计ç®å
¬å¼" |
| | | min-width="200" |
| | | show-overflow-tooltip> |
| | | <template #default="{ row }"> |
| | | <el-tag type="info" size="small">{{ row.formula }}</el-tag> |
| | | <el-tag type="info" |
| | | size="small">{{ row.formula }}</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="status" label="ç¶æ" width="80" align="center"> |
| | | <el-table-column prop="status" |
| | | label="ç¶æ" |
| | | width="80" |
| | | align="center"> |
| | | <template #default="{ row }"> |
| | | <el-tag :type="row.status === 'active' ? 'success' : 'info'" size="small"> |
| | | <el-tag :type="row.status === 'active' ? 'success' : 'info'" |
| | | size="small"> |
| | | {{ row.status === 'active' ? 'å¯ç¨' : 'ç¦ç¨' }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="updateTime" label="æåè®¡ç®æ¶é´" width="160" /> |
| | | <el-table-column label="æä½" width="200" fixed="right" align="center"> |
| | | <el-table-column prop="updateTime" |
| | | label="æåè®¡ç®æ¶é´" |
| | | width="160" /> |
| | | <el-table-column label="æä½" |
| | | width="200" |
| | | fixed="right" |
| | | align="center"> |
| | | <template #default="{ row }"> |
| | | <el-button type="primary" link @click="handleEdit(row)">ç¼è¾</el-button> |
| | | <el-button type="success" link @click="handleCalculate(row)">计ç®</el-button> |
| | | <el-button type="danger" link @click="handleDelete(row)">å é¤</el-button> |
| | | <el-button type="primary" |
| | | link |
| | | @click="handleEdit(row)">ç¼è¾</el-button> |
| | | <el-button type="success" |
| | | link |
| | | @click="handleCalculate(row)">计ç®</el-button> |
| | | <el-button type="danger" |
| | | link |
| | | @click="handleDelete(row)">å é¤</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <!-- å页 --> |
| | | <div class="pagination-container"> |
| | | <el-pagination |
| | | v-model:current-page="pagination.current" |
| | | v-model:page-size="pagination.size" |
| | | :page-sizes="[10, 20, 50, 100]" |
| | | :total="total" |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | @size-change="handleSizeChange" |
| | | @current-change="handleCurrentChange" |
| | | /> |
| | | <el-pagination v-model:current-page="pagination.current" |
| | | v-model:page-size="pagination.size" |
| | | :page-sizes="[10, 20, 50, 100]" |
| | | :total="total" |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | @size-change="handleSizeChange" |
| | | @current-change="handleCurrentChange" /> |
| | | </div> |
| | | </el-card> |
| | | |
| | | <!-- æ°å¢/ç¼è¾å¯¹è¯æ¡ --> |
| | | <FormDialog |
| | | v-model="dialogVisible" |
| | | :title="dialogType === 'add' ? 'æ°å¢éè´è®¡å' : 'ç¼è¾éè´è®¡å'" |
| | | :width="'1000px'" |
| | | :operation-type="dialogType" |
| | | :close-on-click-modal="false" |
| | | @close="dialogVisible = false" |
| | | @confirm="handleSubmit" |
| | | @cancel="dialogVisible = false" |
| | | > |
| | | <FormDialog v-model="dialogVisible" |
| | | :title="dialogType === 'add' ? 'æ°å¢éè´è®¡å' : 'ç¼è¾éè´è®¡å'" |
| | | :width="'1000px'" |
| | | :operation-type="dialogType" |
| | | :close-on-click-modal="false" |
| | | @close="dialogVisible = false" |
| | | @confirm="handleSubmit" |
| | | @cancel="dialogVisible = false"> |
| | | <div class="form-container"> |
| | | <!-- åºæ¬ä¿¡æ¯ --> |
| | | <div class="form-section"> |
| | | <div class="section-title">åºæ¬ä¿¡æ¯</div> |
| | | <el-form |
| | | ref="formRef" |
| | | :model="formData" |
| | | :rules="formRules" |
| | | label-width="120px" |
| | | > |
| | | <el-form ref="formRef" |
| | | :model="formData" |
| | | :rules="formRules" |
| | | label-width="120px"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç¼ç " prop="code"> |
| | | <el-input v-model="formData.code" placeholder="ç³»ç»èªå¨çæ" disabled /> |
| | | <el-form-item label="ç¼ç " |
| | | prop="code"> |
| | | <el-input v-model="formData.code" |
| | | placeholder="ä¿ååèªå¨çæ" |
| | | disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="åç§°" prop="planName" required> |
| | | <el-input v-model="formData.planName" placeholder="请è¾å
¥è®¡ååç§°" /> |
| | | <el-form-item label="åç§°" |
| | | prop="planName" |
| | | required> |
| | | <el-input v-model="formData.planName" |
| | | placeholder="请è¾å
¥è®¡ååç§°" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-form-item label="æè¿°" prop="description"> |
| | | <el-input |
| | | v-model="formData.description" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥è®¡åæè¿°" |
| | | /> |
| | | <el-form-item label="æè¿°" |
| | | prop="description"> |
| | | <el-input v-model="formData.description" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥è®¡åæè¿°" /> |
| | | </el-form-item> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç¶æ" prop="status"> |
| | | <el-select v-model="formData.status" placeholder="è¯·éæ©ç¶æ" style="width: 100%"> |
| | | <el-option label="å¯ç¨" value="active" /> |
| | | <el-option label="ç¦ç¨" value="disabled" /> |
| | | <el-form-item label="ç¶æ" |
| | | prop="status"> |
| | | <el-select v-model="formData.status" |
| | | placeholder="è¯·éæ©ç¶æ" |
| | | style="width: 100%"> |
| | | <el-option label="å¯ç¨" |
| | | value="active" /> |
| | | <el-option label="ç¦ç¨" |
| | | value="disabled" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ¯å¦ç³»ç»é¢ç½®"> |
| | | <el-checkbox v-model="formData.isSystemPreset">æ¯</el-checkbox> |
| | | <el-form-item label="å建æ¶é´" prop="createTime"> |
| | | <el-date-picker v-model="formCreateTimeDate" |
| | | type="date" |
| | | placeholder="éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | </div> |
| | | |
| | | <!-- 计ç®åæ° --> |
| | | <div class="form-section"> |
| | | <div class="section-title">计ç®åæ°</div> |
| | | <el-tabs v-model="activeTab" class="param-tabs"> |
| | | <el-tab-pane label="鿱忰" name="demand"> |
| | | <el-tabs v-model="activeTab" |
| | | class="param-tabs"> |
| | | <el-tab-pane label="鿱忰" |
| | | name="demand"> |
| | | <div class="checkbox-group"> |
| | | <el-checkbox v-model="formData.considerExistingStock">èèç°æåºå</el-checkbox> |
| | | <el-checkbox v-model="formData.warehouseControl">ä»åºè¿è¡MRPçæ§å¶</el-checkbox> |
| | |
| | | <el-checkbox v-model="formData.negativeStockAsDemand">è´åºåä½ä¸ºéæ±</el-checkbox> |
| | | </div> |
| | | </el-tab-pane> |
| | | <el-tab-pane label="计ç®åæ°" name="calculation"> |
| | | <el-tab-pane label="计ç®åæ°" |
| | | name="calculation"> |
| | | <div class="checkbox-group"> |
| | | <el-checkbox v-model="formData.considerExistingStock">èèç°æåºå</el-checkbox> |
| | | <el-checkbox v-model="formData.warehouseControl">ä»åºè¿è¡MRPçæ§å¶</el-checkbox> |
| | |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | | </div> |
| | | |
| | | <!-- æ±æ»åå¹¶é项 --> |
| | | <div class="form-section"> |
| | | <div class="section-title">æ±æ»åå¹¶é项</div> |
| | |
| | | <el-checkbox v-model="formData.summaryDemandDate">éæ±æ¥æ</el-checkbox> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 计ç®å
¬å¼ --> |
| | | <div class="form-section"> |
| | | <div class="section-title">计ç®å
¬å¼</div> |
| | | <div class="formula-input-section"> |
| | | <el-form-item label="计ç®å
¬å¼" prop="formula" required> |
| | | <el-input |
| | | v-model="formData.formula" |
| | | placeholder="ä¾å¦: é¢è®¡åºåºæ°é - ç°æåºå + å®å
¨åºå - é¢è®¡å
¥åºæ°é" |
| | | @input="validateFormula" |
| | | /> |
| | | <el-form-item label="计ç®å
¬å¼" |
| | | prop="formula" |
| | | required> |
| | | <el-input v-model="formData.formula" |
| | | placeholder="ä¾å¦: é¢è®¡åºåºæ°é - ç°æåºå + å®å
¨åºå - é¢è®¡å
¥åºæ°é" |
| | | @input="validateFormula" /> |
| | | </el-form-item> |
| | | <div class="formula-help"> |
| | | <el-text type="info" size="small"> |
| | | <el-text type="info" |
| | | size="small"> |
| | | æ¯æåéï¼é¢è®¡åºåºæ°éãç°æåºåãå®å
¨åºåãé¢è®¡å
¥åºæ°é |
| | | </el-text> |
| | | </div> |
| | |
| | | </div> |
| | | </div> |
| | | </FormDialog> |
| | | |
| | | <!-- 产åéæ©å¯¹è¯æ¡ --> |
| | | <FormDialog |
| | | v-model="productSelectDialogVisible" |
| | | title="éæ©äº§å" |
| | | :width="'800px'" |
| | | :close-on-click-modal="false" |
| | | @close="productSelectDialogVisible = false" |
| | | @confirm="handleConfirmProductSelection" |
| | | @cancel="productSelectDialogVisible = false" |
| | | > |
| | | <FormDialog v-model="productSelectDialogVisible" |
| | | title="éæ©äº§å" |
| | | :width="'800px'" |
| | | :close-on-click-modal="false" |
| | | @close="productSelectDialogVisible = false" |
| | | @confirm="handleConfirmProductSelection" |
| | | @cancel="productSelectDialogVisible = false"> |
| | | <div class="product-select"> |
| | | <el-alert |
| | | title="è¯·éæ©è¦è®¡ç®ç产å" |
| | | type="info" |
| | | :closable="false" |
| | | show-icon |
| | | > |
| | | <el-alert title="è¯·éæ©è¦è®¡ç®ç产å" |
| | | type="info" |
| | | :closable="false" |
| | | show-icon> |
| | | <template #default> |
| | | <p>éæ©äº§ååï¼ç³»ç»å°æ ¹æ®å½å计ç®å
¬å¼å产ååºåæ
åµè¿è¡è®¡ç®ã</p> |
| | | </template> |
| | | </el-alert> |
| | | |
| | | <el-table |
| | | v-loading="productLoading" |
| | | :data="productList" |
| | | @selection-change="handleProductSelectionChange" |
| | | stripe |
| | | border |
| | | style="width: 100%; margin-top: 20px;" |
| | | > |
| | | <el-table-column type="selection" width="55" /> |
| | | <el-table-column prop="productCategory" label="产å大类" min-width="150" /> |
| | | <el-table-column prop="specificationModel" label="产åè§æ ¼" width="120" /> |
| | | <el-table-column prop="inboundNum0" label="ç°æåºå" width="100" align="right" /> |
| | | <el-table-column prop="inboundNum" label="å®å
¨åºå" width="100" align="right" /> |
| | | <el-table-column prop="inboundNum" label="é¢è®¡åºåº" width="100" align="right" /> |
| | | <el-table-column prop="inboundNum0" label="é¢è®¡å
¥åº" width="100" align="right" /> |
| | | <el-table v-loading="productLoading" |
| | | :data="productList" |
| | | @selection-change="handleProductSelectionChange" |
| | | stripe |
| | | border |
| | | style="width: 100%; margin-top: 20px;"> |
| | | <el-table-column type="selection" |
| | | width="55" /> |
| | | <el-table-column prop="productCategory" |
| | | label="产å大类" |
| | | min-width="150" /> |
| | | <el-table-column prop="specificationModel" |
| | | label="è§æ ¼åå·" |
| | | width="120" /> |
| | | <el-table-column prop="inboundNum0" |
| | | label="ç°æåºå" |
| | | width="100" |
| | | align="right" /> |
| | | <el-table-column prop="inboundNum" |
| | | label="å®å
¨åºå" |
| | | width="100" |
| | | align="right" /> |
| | | <el-table-column prop="inboundNum" |
| | | label="é¢è®¡åºåº" |
| | | width="100" |
| | | align="right" /> |
| | | <el-table-column prop="inboundNum0" |
| | | label="é¢è®¡å
¥åº" |
| | | width="100" |
| | | align="right" /> |
| | | </el-table> |
| | | </div> |
| | | </FormDialog> |
| | | |
| | | <!-- 计ç®ç»æå¯¹è¯æ¡ --> |
| | | <FormDialog |
| | | v-model="calculateDialogVisible" |
| | | title="éè´è®¡ç®ç»æ" |
| | | :width="'1000px'" |
| | | :close-on-click-modal="false" |
| | | @close="calculateDialogVisible = false" |
| | | @confirm="handleCreatePurchaseOrder" |
| | | @cancel="calculateDialogVisible = false" |
| | | > |
| | | <FormDialog v-model="calculateDialogVisible" |
| | | title="éè´è®¡ç®ç»æ" |
| | | :width="'1000px'" |
| | | :close-on-click-modal="false" |
| | | @close="calculateDialogVisible = false" |
| | | @confirm="handleCreatePurchaseOrder" |
| | | @cancel="calculateDialogVisible = false"> |
| | | <div class="calculate-result"> |
| | | <el-alert |
| | | title="计ç®ç»æ" |
| | | type="success" |
| | | :closable="false" |
| | | show-icon |
| | | > |
| | | <el-alert title="计ç®ç»æ" |
| | | type="success" |
| | | :closable="false" |
| | | show-icon> |
| | | <template #default> |
| | | <p>åºäºå½åé
ç½®ç计ç®å
¬å¼ååºåæ
åµï¼ç³»ç»å·²è®¡ç®åºå产åçéè´éæ±ã</p> |
| | | </template> |
| | | </el-alert> |
| | | |
| | | <el-table :data="calculateResult" stripe border style="width: 100%; margin-top: 20px;"> |
| | | <el-table-column prop="productCategory" label="产å大类" min-width="150" /> |
| | | <el-table-column prop="specificationModel" label="产åè§æ ¼" width="120" /> |
| | | <el-table-column prop="inboundNum0" label="ç°æåºå" width="100" align="right" /> |
| | | <el-table-column prop="inboundNum" label="å®å
¨åºå" width="100" align="right" /> |
| | | <el-table-column prop="inboundNum" label="é¢è®¡åºåºæ°é" width="120" align="right" /> |
| | | <el-table-column prop="inboundNum0" label="é¢è®¡å
¥åºæ°é" width="120" align="right" /> |
| | | <el-table-column prop="weeklyNetDemand" label="æå¨åéæ±" width="120" align="right"> |
| | | <el-table :data="calculateResult" |
| | | stripe |
| | | border |
| | | style="width: 100%; margin-top: 20px;"> |
| | | <el-table-column prop="productCategory" |
| | | label="产å大类" |
| | | min-width="150" /> |
| | | <el-table-column prop="specificationModel" |
| | | label="è§æ ¼åå·" |
| | | width="120" /> |
| | | <el-table-column prop="inboundNum0" |
| | | label="ç°æåºå" |
| | | width="100" |
| | | align="right" /> |
| | | <el-table-column prop="inboundNum" |
| | | label="å®å
¨åºå" |
| | | width="100" |
| | | align="right" /> |
| | | <el-table-column prop="inboundNum" |
| | | label="é¢è®¡åºåºæ°é" |
| | | width="120" |
| | | align="right" /> |
| | | <el-table-column prop="inboundNum0" |
| | | label="é¢è®¡å
¥åºæ°é" |
| | | width="120" |
| | | align="right" /> |
| | | <el-table-column prop="weeklyNetDemand" |
| | | label="æå¨åéæ±" |
| | | width="120" |
| | | align="right"> |
| | | <template #default="{ row }"> |
| | | <el-tag :type="row.weeklyNetDemand > 0 ? 'warning' : 'success'" size="small"> |
| | | <el-tag :type="row.weeklyNetDemand > 0 ? 'warning' : 'success'" |
| | | size="small"> |
| | | {{ row.weeklyNetDemand }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="suggestedPurchase" label="建议éè´" width="100" align="right"> |
| | | <el-table-column prop="suggestedPurchase" |
| | | label="建议éè´" |
| | | width="100" |
| | | align="right"> |
| | | <template #default="{ row }"> |
| | | <el-tag :type="row.suggestedPurchase > 0 ? 'danger' : 'success'" size="small"> |
| | | <el-tag :type="row.suggestedPurchase > 0 ? 'danger' : 'success'" |
| | | size="small"> |
| | | {{ row.suggestedPurchase }} |
| | | </el-tag> |
| | | </template> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import FormDialog from '@/components/Dialog/FormDialog.vue'; |
| | | import {ref, reactive, onMounted, getCurrentInstance} from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { Search, Refresh, Plus, Download } from '@element-plus/icons-vue' |
| | | import {listPage,add,update,del,listPageCopy} from "@/api/procurementManagement/procurementPlan.js" |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | import { ref, reactive, onMounted, getCurrentInstance, computed } from "vue"; |
| | | import dayjs from "dayjs"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import { Search, Refresh, Plus, Download } from "@element-plus/icons-vue"; |
| | | import { |
| | | listPage, |
| | | add, |
| | | update, |
| | | del, |
| | | listPageCopy, |
| | | } from "@/api/procurementManagement/procurementPlan.js"; |
| | | |
| | | // ååºå¼æ°æ® |
| | | const loading = ref(false) |
| | | const submitLoading = ref(false) |
| | | const dialogVisible = ref(false) |
| | | const productSelectDialogVisible = ref(false) |
| | | const calculateDialogVisible = ref(false) |
| | | const dialogType = ref('add') |
| | | const productLoading = ref(false) |
| | | const selectedProducts = ref([]) |
| | | const currentPlan = ref(null) |
| | | // ååºå¼æ°æ® |
| | | const loading = ref(false); |
| | | const submitLoading = ref(false); |
| | | const dialogVisible = ref(false); |
| | | const productSelectDialogVisible = ref(false); |
| | | const calculateDialogVisible = ref(false); |
| | | const dialogType = ref("add"); |
| | | const productLoading = ref(false); |
| | | const selectedProducts = ref([]); |
| | | const currentPlan = ref(null); |
| | | |
| | | // æç´¢è¡¨å |
| | | const searchForm = reactive({ |
| | | planName: '', |
| | | status: '' |
| | | }) |
| | | // æç´¢è¡¨å |
| | | const searchForm = reactive({ |
| | | planName: "", |
| | | status: "", |
| | | }); |
| | | |
| | | // åé¡µæ°æ® |
| | | const pagination = reactive({ |
| | | current: 1, |
| | | size: 20 |
| | | }) |
| | | // åé¡µæ°æ® |
| | | const pagination = reactive({ |
| | | current: 1, |
| | | size: 20, |
| | | }); |
| | | |
| | | // è¡¨åæ°æ® |
| | | const formData = reactive({ |
| | | code: '', |
| | | planName: '', |
| | | description: '', |
| | | status: '', |
| | | isSystemPreset: false, |
| | | formula: '', |
| | | // 计ç®åæ° |
| | | considerExistingStock: false, |
| | | warehouseControl: false, |
| | | calculateTotalDemand: false, |
| | | considerSafetyStock: false, |
| | | considerLockedStock: false, |
| | | notConsiderMaterialAux: false, |
| | | negativeStockAsDemand: false, |
| | | // æ±æ»åå¹¶é项 |
| | | summaryMaterial: false, |
| | | summaryAuxAttributes: false, |
| | | summaryDemandDate: false |
| | | }) |
| | | |
| | | // å½åæ¿æ´»çæ ç¾é¡µ |
| | | const activeTab = ref('demand') |
| | | |
| | | // 表åéªè¯è§å |
| | | const formRules = { |
| | | planName: [ |
| | | { required: true, message: '请è¾å
¥è®¡ååç§°', trigger: 'blur' } |
| | | ], |
| | | status: [ |
| | | { required: true, message: 'è¯·éæ©ç¶æ', trigger: 'change' } |
| | | ], |
| | | formula: [ |
| | | { required: true, message: '请è¾å
¥è®¡ç®å
¬å¼', trigger: 'blur' } |
| | | ] |
| | | } |
| | | |
| | | // è¡¨æ ¼æ°æ® |
| | | const tableData = ref([]) |
| | | |
| | | // 产ååè¡¨æ°æ® |
| | | const productList = ref([ |
| | | { |
| | | id: 4, |
| | | productName: '产åD', |
| | | productCode: 'PD004', |
| | | existingStock: 90, |
| | | safetyStock: 40, |
| | | expectedOutbound: 160, |
| | | expectedInbound: 35 |
| | | } |
| | | ]) |
| | | |
| | | // 计ç®ç»ææ°æ® |
| | | const calculateResult = ref([ |
| | | { |
| | | productName: '产åA', |
| | | existingStock: 100, |
| | | safetyStock: 50, |
| | | expectedOutbound: 200, |
| | | expectedInbound: 30, |
| | | weeklyNetDemand: 120, |
| | | suggestedPurchase: 150 |
| | | }, |
| | | { |
| | | productName: '产åB', |
| | | existingStock: 80, |
| | | safetyStock: 30, |
| | | expectedOutbound: 150, |
| | | expectedInbound: 20, |
| | | weeklyNetDemand: 100, |
| | | suggestedPurchase: 120 |
| | | } |
| | | ]) |
| | | const total = ref(0) |
| | | // æ¹æ³ |
| | | const handleSearch = () => { |
| | | pagination.current = 1 |
| | | loadData() |
| | | } |
| | | |
| | | const handleReset = () => { |
| | | Object.assign(searchForm, { |
| | | planName: '', |
| | | status: '' |
| | | }) |
| | | handleSearch() |
| | | } |
| | | |
| | | const loadData = () => { |
| | | loading.value = true |
| | | listPage({...searchForm,...pagination}).then(res => { |
| | | if(res.code === 200){ |
| | | tableData.value = res.data.records |
| | | total.value = res.data.total |
| | | loading.value = false |
| | | } |
| | | }) |
| | | } |
| | | |
| | | const handleAdd = () => { |
| | | dialogType.value = 'add' |
| | | resetForm() |
| | | // èªå¨çæç¼ç |
| | | formData.code = 'CGJH' + String(Date.now()).slice(-4) |
| | | dialogVisible.value = true |
| | | } |
| | | |
| | | const handleEdit = (row) => { |
| | | dialogType.value = 'edit' |
| | | Object.assign(formData, row) |
| | | dialogVisible.value = true |
| | | } |
| | | |
| | | const handleDelete = async (row) => { |
| | | try { |
| | | await ElMessageBox.confirm('ç¡®å®è¦å é¤è¿ä¸ªéè´è®¡ååï¼', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | }) |
| | | let ids = [row.id] |
| | | del(ids).then(res =>{ |
| | | if(res.code === 200){ |
| | | ElMessage.success('å 餿å') |
| | | loadData() |
| | | } |
| | | }) |
| | | } catch { |
| | | // ç¨æ·åæ¶å é¤ |
| | | } |
| | | } |
| | | |
| | | const handleSubmit = async () => { |
| | | try { |
| | | // 表åéªè¯ |
| | | if (!formData.planName || !formData.formula) { |
| | | ElMessage.error('请填åå¿
填项') |
| | | return |
| | | } |
| | | |
| | | submitLoading.value = true |
| | | |
| | | if (dialogType.value === 'add') { |
| | | add(formData).then(res => { |
| | | if(res.code === 200){ |
| | | ElMessage.success('æ°å¢æå') |
| | | dialogVisible.value = false |
| | | loadData() |
| | | } |
| | | }) |
| | | } else { |
| | | // ç¼è¾ |
| | | update(formData).then(res => { |
| | | if(res.code === 200){ |
| | | ElMessage.success('ç¼è¾æå') |
| | | dialogVisible.value = false |
| | | loadData() |
| | | } |
| | | }) |
| | | } |
| | | |
| | | |
| | | } catch (error) { |
| | | ElMessage.error('æä½å¤±è´¥') |
| | | } finally { |
| | | submitLoading.value = false |
| | | } |
| | | } |
| | | |
| | | const resetForm = () => { |
| | | Object.assign(formData, { |
| | | code: '', |
| | | planName: '', |
| | | description: '', |
| | | status: '', |
| | | // è¡¨åæ°æ® |
| | | const formData = reactive({ |
| | | code: "", |
| | | planName: "", |
| | | description: "", |
| | | status: "", |
| | | isSystemPreset: false, |
| | | formula: 'é¢è®¡åºåºæ°é - ç°æåºå + å®å
¨åºå - é¢è®¡å
¥åºæ°é', |
| | | formula: "", |
| | | createTime: "", |
| | | // 计ç®åæ° |
| | | considerExistingStock: false, |
| | | warehouseControl: false, |
| | |
| | | // æ±æ»åå¹¶é项 |
| | | summaryMaterial: false, |
| | | summaryAuxAttributes: false, |
| | | summaryDemandDate: false |
| | | }) |
| | | activeTab.value = 'demand' |
| | | } |
| | | summaryDemandDate: false, |
| | | }); |
| | | const formCreateTimeDate = computed({ |
| | | get: () => (formData.createTime ? String(formData.createTime).split(" ")[0] : ""), |
| | | set: (value) => { |
| | | formData.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : ""; |
| | | }, |
| | | }); |
| | | |
| | | const validateFormula = () => { |
| | | // ç®åçå
¬å¼éªè¯ |
| | | const formula = formData.formula |
| | | if (formula && !/^[a-zA-Z\u4e00-\u9fa5\s\*\+\-\/\(\)\d\.]+$/.test(formula)) { |
| | | ElMessage.warning('å
¬å¼æ ¼å¼å¯è½ä¸æ£ç¡®ï¼è¯·æ£æ¥') |
| | | } |
| | | } |
| | | // å½åæ¿æ´»çæ ç¾é¡µ |
| | | const activeTab = ref("demand"); |
| | | |
| | | const handleCalculate = (row) => { |
| | | currentPlan.value = row |
| | | productSelectDialogVisible.value = true |
| | | loadProductList() |
| | | } |
| | | // 表åéªè¯è§å |
| | | const formRules = { |
| | | planName: [{ required: true, message: "请è¾å
¥è®¡ååç§°", trigger: "blur" }], |
| | | status: [{ required: true, message: "è¯·éæ©ç¶æ", trigger: "change" }], |
| | | formula: [{ required: true, message: "请è¾å
¥è®¡ç®å
¬å¼", trigger: "blur" }], |
| | | }; |
| | | |
| | | const loadProductList = () => { |
| | | productLoading.value = true |
| | | // 模æå è½½äº§åæ°æ® |
| | | listPageCopy({size:-1}).then(res => { |
| | | if(res.code === 200){ |
| | | productList.value = res.data.records |
| | | productLoading.value = false |
| | | // è¡¨æ ¼æ°æ® |
| | | const tableData = ref([]); |
| | | |
| | | // 产ååè¡¨æ°æ® |
| | | const productList = ref([ |
| | | { |
| | | id: 4, |
| | | productName: "产åD", |
| | | productCode: "PD004", |
| | | existingStock: 90, |
| | | safetyStock: 40, |
| | | expectedOutbound: 160, |
| | | expectedInbound: 35, |
| | | }, |
| | | ]); |
| | | |
| | | // 计ç®ç»ææ°æ® |
| | | const calculateResult = ref([ |
| | | { |
| | | productName: "产åA", |
| | | existingStock: 100, |
| | | safetyStock: 50, |
| | | expectedOutbound: 200, |
| | | expectedInbound: 30, |
| | | weeklyNetDemand: 120, |
| | | suggestedPurchase: 150, |
| | | }, |
| | | { |
| | | productName: "产åB", |
| | | existingStock: 80, |
| | | safetyStock: 30, |
| | | expectedOutbound: 150, |
| | | expectedInbound: 20, |
| | | weeklyNetDemand: 100, |
| | | suggestedPurchase: 120, |
| | | }, |
| | | ]); |
| | | const total = ref(0); |
| | | // æ¹æ³ |
| | | const handleSearch = () => { |
| | | pagination.current = 1; |
| | | loadData(); |
| | | }; |
| | | |
| | | const handleReset = () => { |
| | | Object.assign(searchForm, { |
| | | planName: "", |
| | | status: "", |
| | | }); |
| | | handleSearch(); |
| | | }; |
| | | |
| | | const loadData = () => { |
| | | loading.value = true; |
| | | listPage({ ...searchForm, ...pagination }).then(res => { |
| | | if (res.code === 200) { |
| | | tableData.value = res.data.records; |
| | | total.value = res.data.total; |
| | | loading.value = false; |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | const handleAdd = () => { |
| | | dialogType.value = "add"; |
| | | resetForm(); |
| | | formData.createTime = dayjs().format("YYYY-MM-DD HH:mm:ss"); |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | const handleEdit = row => { |
| | | dialogType.value = "edit"; |
| | | Object.assign(formData, row); |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | const handleDelete = async row => { |
| | | try { |
| | | await ElMessageBox.confirm("ç¡®å®è¦å é¤è¿ä¸ªéè´è®¡ååï¼", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }); |
| | | let ids = [row.id]; |
| | | del(ids).then(res => { |
| | | if (res.code === 200) { |
| | | ElMessage.success("å 餿å"); |
| | | loadData(); |
| | | } |
| | | }); |
| | | } catch { |
| | | // ç¨æ·åæ¶å é¤ |
| | | } |
| | | }) |
| | | } |
| | | }; |
| | | |
| | | const handleProductSelectionChange = (selection) => { |
| | | selectedProducts.value = selection |
| | | } |
| | | const handleSubmit = async () => { |
| | | try { |
| | | // 表åéªè¯ |
| | | if (!formData.planName || !formData.formula) { |
| | | ElMessage.error("请填åå¿
填项"); |
| | | return; |
| | | } |
| | | |
| | | const handleConfirmProductSelection = () => { |
| | | if (selectedProducts.value.length === 0) { |
| | | ElMessage.warning('è¯·éæ©è¦è®¡ç®ç产å') |
| | | return |
| | | } |
| | | |
| | | ElMessage.success(`æ£å¨è®¡ç® ${currentPlan.value.planName} çéè´éæ±...`) |
| | | productSelectDialogVisible.value = false |
| | | |
| | | // æ ¹æ®éæ©ç产åå计ç®å
¬å¼è¿è¡è®¡ç® |
| | | calculateWithSelectedProducts() |
| | | } |
| | | submitLoading.value = true; |
| | | |
| | | const calculateWithSelectedProducts = () => { |
| | | // 模æè®¡ç®è¿ç¨ |
| | | // æ ¹æ®éæ©çäº§åæ´æ°è®¡ç®ç»æ |
| | | const result = selectedProducts.value.map(product => { |
| | | // è¿éåºè¯¥æ ¹æ®å®é
ç计ç®å
¬å¼è¿è¡è®¡ç® |
| | | // 示ä¾ï¼é¢è®¡åºåºæ°é - ç°æåºå + å®å
¨åºå - é¢è®¡å
¥åºæ°é |
| | | const weeklyNetDemand = product.inboundNum - product.inboundNum0 + product.inboundNum - product.inboundNum0 |
| | | const suggestedPurchase = Math.max(0, weeklyNetDemand) |
| | | |
| | | return { |
| | | productCategory: product.productCategory, |
| | | specificationModel: product.specificationModel, |
| | | inboundNum0: product.inboundNum0, |
| | | inboundNum: product.inboundNum, |
| | | weeklyNetDemand: weeklyNetDemand, |
| | | suggestedPurchase: suggestedPurchase |
| | | if (dialogType.value === "add") { |
| | | add(formData).then(res => { |
| | | if (res.code === 200) { |
| | | ElMessage.success("æ°å¢æå"); |
| | | dialogVisible.value = false; |
| | | loadData(); |
| | | } |
| | | }); |
| | | } else { |
| | | // ç¼è¾ |
| | | update(formData).then(res => { |
| | | if (res.code === 200) { |
| | | ElMessage.success("ç¼è¾æå"); |
| | | dialogVisible.value = false; |
| | | loadData(); |
| | | } |
| | | }); |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error("æä½å¤±è´¥"); |
| | | } finally { |
| | | submitLoading.value = false; |
| | | } |
| | | }) |
| | | }; |
| | | |
| | | calculateResult.value = result |
| | | calculateDialogVisible.value = true |
| | | } |
| | | const resetForm = () => { |
| | | Object.assign(formData, { |
| | | code: "", |
| | | planName: "", |
| | | description: "", |
| | | status: "", |
| | | isSystemPreset: false, |
| | | formula: "é¢è®¡åºåºæ°é - ç°æåºå + å®å
¨åºå - é¢è®¡å
¥åºæ°é", |
| | | // 计ç®åæ° |
| | | considerExistingStock: false, |
| | | warehouseControl: false, |
| | | calculateTotalDemand: false, |
| | | considerSafetyStock: false, |
| | | considerLockedStock: false, |
| | | notConsiderMaterialAux: false, |
| | | negativeStockAsDemand: false, |
| | | // æ±æ»åå¹¶é项 |
| | | summaryMaterial: false, |
| | | summaryAuxAttributes: false, |
| | | summaryDemandDate: false, |
| | | }); |
| | | activeTab.value = "demand"; |
| | | }; |
| | | |
| | | const validateFormula = () => { |
| | | // ç®åçå
¬å¼éªè¯ |
| | | const formula = formData.formula; |
| | | if (formula && !/^[a-zA-Z\u4e00-\u9fa5\s\*\+\-\/\(\)\d\.]+$/.test(formula)) { |
| | | ElMessage.warning("å
¬å¼æ ¼å¼å¯è½ä¸æ£ç¡®ï¼è¯·æ£æ¥"); |
| | | } |
| | | }; |
| | | |
| | | const handleCreatePurchaseOrder = () => { |
| | | calculateDialogVisible.value = false |
| | | } |
| | | const { proxy } = getCurrentInstance(); |
| | | const handleExport = () => { |
| | | ElMessageBox.confirm("å
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | const handleCalculate = row => { |
| | | currentPlan.value = row; |
| | | productSelectDialogVisible.value = true; |
| | | loadProductList(); |
| | | }; |
| | | |
| | | const loadProductList = () => { |
| | | productLoading.value = true; |
| | | // 模æå è½½äº§åæ°æ® |
| | | listPageCopy({ size: -1 }).then(res => { |
| | | if (res.code === 200) { |
| | | productList.value = res.data.records; |
| | | productLoading.value = false; |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | const handleProductSelectionChange = selection => { |
| | | selectedProducts.value = selection; |
| | | }; |
| | | |
| | | const handleConfirmProductSelection = () => { |
| | | if (selectedProducts.value.length === 0) { |
| | | ElMessage.warning("è¯·éæ©è¦è®¡ç®ç产å"); |
| | | return; |
| | | } |
| | | |
| | | ElMessage.success(`æ£å¨è®¡ç® ${currentPlan.value.planName} çéè´éæ±...`); |
| | | productSelectDialogVisible.value = false; |
| | | |
| | | // æ ¹æ®éæ©ç产åå计ç®å
¬å¼è¿è¡è®¡ç® |
| | | calculateWithSelectedProducts(); |
| | | }; |
| | | |
| | | const calculateWithSelectedProducts = () => { |
| | | // 模æè®¡ç®è¿ç¨ |
| | | // æ ¹æ®éæ©çäº§åæ´æ°è®¡ç®ç»æ |
| | | const result = selectedProducts.value.map(product => { |
| | | // è¿éåºè¯¥æ ¹æ®å®é
ç计ç®å
¬å¼è¿è¡è®¡ç® |
| | | // 示ä¾ï¼é¢è®¡åºåºæ°é - ç°æåºå + å®å
¨åºå - é¢è®¡å
¥åºæ°é |
| | | const weeklyNetDemand = |
| | | product.inboundNum - |
| | | product.inboundNum0 + |
| | | product.inboundNum - |
| | | product.inboundNum0; |
| | | const suggestedPurchase = Math.max(0, weeklyNetDemand); |
| | | |
| | | return { |
| | | productCategory: product.productCategory, |
| | | specificationModel: product.specificationModel, |
| | | inboundNum0: product.inboundNum0, |
| | | inboundNum: product.inboundNum, |
| | | weeklyNetDemand: weeklyNetDemand, |
| | | suggestedPurchase: suggestedPurchase, |
| | | }; |
| | | }); |
| | | |
| | | calculateResult.value = result; |
| | | calculateDialogVisible.value = true; |
| | | }; |
| | | |
| | | const handleCreatePurchaseOrder = () => { |
| | | calculateDialogVisible.value = false; |
| | | }; |
| | | const { proxy } = getCurrentInstance(); |
| | | const handleExport = () => { |
| | | ElMessageBox.confirm("å
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/procurementPlan/export", {}, "éè´è®¡å.xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | const handleSizeChange = size => { |
| | | pagination.size = size; |
| | | loadData(); |
| | | }; |
| | | |
| | | const handleSizeChange = (size) => { |
| | | pagination.size = size |
| | | loadData() |
| | | } |
| | | const handleCurrentChange = current => { |
| | | pagination.current = current; |
| | | loadData(); |
| | | }; |
| | | |
| | | const handleCurrentChange = (current) => { |
| | | pagination.current = current |
| | | loadData() |
| | | } |
| | | |
| | | // çå½å¨æ |
| | | onMounted(() => { |
| | | loadData() |
| | | }) |
| | | // çå½å¨æ |
| | | onMounted(() => { |
| | | loadData(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .app-container { |
| | | padding: 20px; |
| | | } |
| | | .app-container { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .page-header { |
| | | margin-bottom: 20px; |
| | | } |
| | | .page-header { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .page-header h2 { |
| | | margin: 0 0 8px 0; |
| | | color: #303133; |
| | | font-size: 24px; |
| | | font-weight: 600; |
| | | } |
| | | .page-header h2 { |
| | | margin: 0 0 8px 0; |
| | | color: #303133; |
| | | font-size: 24px; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | .page-header p { |
| | | margin: 0; |
| | | color: #909399; |
| | | font-size: 14px; |
| | | } |
| | | .page-header p { |
| | | margin: 0; |
| | | color: #909399; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .search-card { |
| | | margin-bottom: 20px; |
| | | } |
| | | .search-card { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .search-form { |
| | | margin-bottom: 0; |
| | | } |
| | | .search-form { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .table-card { |
| | | margin-bottom: 20px; |
| | | } |
| | | .table-card { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .table-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 20px; |
| | | } |
| | | .table-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .table-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | } |
| | | .table-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | } |
| | | |
| | | .table-actions { |
| | | display: flex; |
| | | gap: 10px; |
| | | } |
| | | .table-actions { |
| | | display: flex; |
| | | gap: 10px; |
| | | } |
| | | |
| | | .pagination-container { |
| | | margin-top: 20px; |
| | | display: flex; |
| | | justify-content: end; |
| | | } |
| | | .pagination-container { |
| | | margin-top: 20px; |
| | | display: flex; |
| | | justify-content: end; |
| | | } |
| | | |
| | | .form-container { |
| | | padding: 0 20px; |
| | | } |
| | | .form-container { |
| | | padding: 0 20px; |
| | | } |
| | | |
| | | .formula-help { |
| | | margin-top: 5px; |
| | | } |
| | | .formula-help { |
| | | margin-top: 5px; |
| | | } |
| | | |
| | | .calculate-result { |
| | | padding: 20px 0; |
| | | } |
| | | .calculate-result { |
| | | padding: 20px 0; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | text-align: right; |
| | | } |
| | | .dialog-footer { |
| | | text-align: right; |
| | | } |
| | | |
| | | :deep(.el-card__body) { |
| | | padding: 20px; |
| | | } |
| | | :deep(.el-card__body) { |
| | | padding: 20px; |
| | | } |
| | | |
| | | :deep(.el-table) { |
| | | font-size: 14px; |
| | | } |
| | | :deep(.el-table) { |
| | | font-size: 14px; |
| | | } |
| | | |
| | | :deep(.el-form-item__label) { |
| | | font-weight: 500; |
| | | } |
| | | :deep(.el-form-item__label) { |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .form-container { |
| | | padding: 0; |
| | | } |
| | | .form-container { |
| | | padding: 0; |
| | | } |
| | | |
| | | .form-section { |
| | | margin-bottom: 24px; |
| | | border: 1px solid #e4e7ed; |
| | | border-radius: 6px; |
| | | overflow: hidden; |
| | | } |
| | | .form-section { |
| | | margin-bottom: 24px; |
| | | border: 1px solid #e4e7ed; |
| | | border-radius: 6px; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .section-title { |
| | | background-color: #f5f7fa; |
| | | padding: 12px 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | border-bottom: 1px solid #e4e7ed; |
| | | } |
| | | .section-title { |
| | | background-color: #f5f7fa; |
| | | padding: 12px 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | border-bottom: 1px solid #e4e7ed; |
| | | } |
| | | |
| | | .form-section .el-form { |
| | | padding: 20px; |
| | | } |
| | | .form-section .el-form { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .param-tabs { |
| | | padding: 20px; |
| | | } |
| | | .param-tabs { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .param-tabs :deep(.el-tabs__header) { |
| | | margin-bottom: 20px; |
| | | } |
| | | .param-tabs :deep(.el-tabs__header) { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .param-tabs :deep(.el-tabs__item.is-active) { |
| | | color: #f56c6c; |
| | | border-bottom-color: #f56c6c; |
| | | } |
| | | .param-tabs :deep(.el-tabs__item.is-active) { |
| | | color: #f56c6c; |
| | | border-bottom-color: #f56c6c; |
| | | } |
| | | |
| | | .checkbox-group { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 16px; |
| | | } |
| | | .checkbox-group { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 16px; |
| | | } |
| | | |
| | | .checkbox-group .el-checkbox { |
| | | margin-right: 0; |
| | | margin-bottom: 8px; |
| | | } |
| | | .checkbox-group .el-checkbox { |
| | | margin-right: 0; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .formula-input-section { |
| | | padding: 20px; |
| | | } |
| | | .formula-input-section { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .formula-input-section .el-form-item { |
| | | margin-bottom: 12px; |
| | | } |
| | | .formula-input-section .el-form-item { |
| | | margin-bottom: 12px; |
| | | } |
| | | |
| | | .formula-help { |
| | | text-align: center; |
| | | margin-top: 8px; |
| | | } |
| | | .formula-help { |
| | | text-align: center; |
| | | margin-top: 8px; |
| | | } |
| | | </style> |
| | |
| | | <el-option label="ä¾åºåB" value="ä¾åºåB" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="å建æ¶é´"> |
| | | <el-date-picker v-model="formCreateTimeDate" |
| | | type="date" |
| | | placeholder="éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | <el-form-item label="夿³¨"> |
| | | <el-input v-model="formData.remark" type="textarea" :rows="3" placeholder="请è¾å
¥å¤æ³¨ä¿¡æ¯" /> |
| | | </el-form-item> |
| | |
| | | |
| | | <script setup> |
| | | import FormDialog from '@/components/Dialog/FormDialog.vue'; |
| | | import { ref, reactive } from 'vue' |
| | | import { ref, reactive, computed } from 'vue' |
| | | import dayjs from 'dayjs' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | |
| | | const loading = ref(false) |
| | |
| | | |
| | | const formData = reactive({ |
| | | supplierName: '', |
| | | remark: '' |
| | | remark: '', |
| | | createTime: '' |
| | | }) |
| | | const formCreateTimeDate = computed({ |
| | | get: () => (formData.createTime ? String(formData.createTime).split(' ')[0] : ''), |
| | | set: (value) => { |
| | | formData.createTime = value ? `${value} ${dayjs().format('HH:mm:ss')}` : '' |
| | | } |
| | | }) |
| | | |
| | | const mockData = [ |
| | |
| | | const openDialog = (type, row = {}) => { |
| | | dialogType.value = type |
| | | if (type === 'edit' && row.id) { |
| | | Object.assign(formData, { supplierName: row.supplierName, remark: row.remark }) |
| | | Object.assign(formData, { supplierName: row.supplierName, remark: row.remark, createTime: row.createTime || '' }) |
| | | } else { |
| | | Object.assign(formData, { supplierName: '', remark: '' }) |
| | | Object.assign(formData, { supplierName: '', remark: '', createTime: dayjs().format('YYYY-MM-DD HH:mm:ss') }) |
| | | } |
| | | dialogVisible.value = true |
| | | } |
| | |
| | | if (dialogType.value === 'add') { |
| | | const newOrder = { |
| | | id: Date.now(), |
| | | orderNo: `PO${Date.now()}`, |
| | | orderNo: '', |
| | | supplierName: formData.supplierName, |
| | | status: 'draft', |
| | | totalAmount: 0, |
| | | createTime: new Date().toLocaleString(), |
| | | createTime: formData.createTime, |
| | | remark: formData.remark |
| | | } |
| | | tableData.value.unshift(newOrder) |
| | |
| | | <el-input v-model="formData.inspector" placeholder="请è¾å
¥è´¨æ£åå§å" /> |
| | | </el-form-item> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å建æ¶é´"> |
| | | <el-date-picker v-model="formCreateTimeDate" |
| | | type="date" |
| | | placeholder="éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-form-item label="夿³¨"> |
| | | <el-input v-model="formData.remark" type="textarea" :rows="3" placeholder="请è¾å
¥å¤æ³¨ä¿¡æ¯" /> |
| | | </el-form-item> |
| | |
| | | |
| | | <script setup> |
| | | import FormDialog from '@/components/Dialog/FormDialog.vue'; |
| | | import { ref, reactive } from 'vue' |
| | | import { ref, reactive, computed } from 'vue' |
| | | import dayjs from 'dayjs' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | |
| | | const loading = ref(false) |
| | |
| | | supplierName: '', |
| | | products: [], |
| | | inspector: '', |
| | | remark: '' |
| | | remark: '', |
| | | createTime: '' |
| | | }) |
| | | const formCreateTimeDate = computed({ |
| | | get: () => (formData.createTime ? String(formData.createTime).split(' ')[0] : ''), |
| | | set: (value) => { |
| | | formData.createTime = value ? `${value} ${dayjs().format('HH:mm:ss')}` : '' |
| | | } |
| | | }) |
| | | |
| | | const mockData = [ |
| | |
| | | arrivalNo: row.arrivalNo, |
| | | supplierName: row.supplierName, |
| | | inspector: row.inspector, |
| | | remark: row.remark |
| | | remark: row.remark, |
| | | createTime: row.createTime || '' |
| | | }) |
| | | } else { |
| | | Object.assign(formData, { |
| | | arrivalNo: '', |
| | | supplierName: '', |
| | | Object.assign(formData, { |
| | | arrivalNo: '', |
| | | supplierName: '', |
| | | products: [], |
| | | inspector: '', |
| | | remark: '' |
| | | inspector: '', |
| | | remark: '', |
| | | createTime: dayjs().format('YYYY-MM-DD HH:mm:ss') |
| | | }) |
| | | } |
| | | dialogVisible.value = true |
| | |
| | | if (dialogType.value === 'add') { |
| | | const newInspection = { |
| | | id: Date.now(), |
| | | inspectionNo: `QI${Date.now()}`, |
| | | inspectionNo: '', |
| | | arrivalNo: formData.arrivalNo, |
| | | supplierName: formData.supplierName, |
| | | status: 'pending', |
| | | qualifiedQuantity: totalQualified, |
| | | unqualifiedQuantity: totalUnqualified, |
| | | inspectionTime: new Date().toLocaleString(), |
| | | inspectionTime: formData.createTime, |
| | | inspector: formData.inspector, |
| | | remark: formData.remark |
| | | } |
| | |
| | | <el-form-item label="æ è¯ç±»å"> |
| | | <span>{{ currentProduct.identifierType }}</span> |
| | | </el-form-item> |
| | | <el-form-item label="å建æ¶é´"> |
| | | <el-date-picker v-model="createTimeDate" |
| | | type="date" |
| | | placeholder="éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 100%"></el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item label="çææ°é" |
| | | prop="generateQuantity"> |
| | | <el-input-number v-model="generateQuantity" |
| | |
| | | |
| | | <script setup> |
| | | import { ref, reactive, computed } from "vue"; |
| | | import dayjs from "dayjs"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import { Plus, Search, Loading, Download } from "@element-plus/icons-vue"; |
| | | import Pagination from "@/components/PIMTable/Pagination.vue"; |
| | |
| | | const generateQuantity = ref(1); |
| | | const codeRule = ref(""); |
| | | const customPrefix = ref(""); |
| | | const createTime = ref(dayjs().format("YYYY-MM-DD HH:mm:ss")); |
| | | const createTimeDate = computed({ |
| | | get: () => (createTime.value ? String(createTime.value).split(" ")[0] : ""), |
| | | set: (value) => { |
| | | createTime.value = value ? `${value} ${dayjs().format("HH:mm:ss")}` : ""; |
| | | }, |
| | | }); |
| | | const newBatchNo = ref(""); |
| | | const reassignReason = ref(""); |
| | | const formRef = ref(); |
| | |
| | | currentProduct.value.batchNo |
| | | }_${String(i).padStart(3, "0")}`; |
| | | } else if (codeRule.value === "æ¶é´æ³+éæºæ°") { |
| | | identifierCode = `TS_${Date.now()}_${Math.floor(Math.random() * 1000)}`; |
| | | identifierCode = ""; |
| | | } else if (codeRule.value === "èªå®ä¹è§å") { |
| | | identifierCode = `${customPrefix.value || "CUSTOM"}_${Date.now()}_${i}`; |
| | | identifierCode = ""; |
| | | } |
| | | |
| | | newIdentifiers.push({ |
| | |
| | | identifierType: currentProduct.value.identifierType, |
| | | identifierCode: identifierCode, |
| | | status: "å·²çæ", |
| | | generateTime: new Date().toLocaleString(), |
| | | generateTime: createTime.value, |
| | | remark: "æ¹éçæ", |
| | | }); |
| | | } |
| | |
| | | border> |
| | | <el-descriptions-item label="ç产订åå·">{{ rowData.productionOrderDto?.npsNo || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="产ååç§°">{{ rowData.productionOrderDto?.productName || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="产åè§æ ¼">{{ rowData.productionOrderDto?.model || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="è§æ ¼åå·">{{ rowData.productionOrderDto?.model || '-' }}</el-descriptions-item> |
| | | <!-- <el-descriptions-item label="ç©æç¼ç ">{{ rowData.productionOrderDto?.materialCode || '-' }}</el-descriptions-item> --> |
| | | <el-descriptions-item label="è®¡åæ°é">{{ rowData.productionOrderDto?.quantity || 0 }} <span class="unit">{{ rowData.productionOrderDto?.unit || '-' }}</span></el-descriptions-item> |
| | | <el-descriptions-item label="å½åç¶æ"> |
| | |
| | | <span class="info-value">{{ transferCardRowData.productName }}</span> |
| | | </div> |
| | | <div class="info-item"> |
| | | <span class="info-label">产åè§æ ¼</span> |
| | | <span class="info-label">è§æ ¼åå·</span> |
| | | <span class="info-value">{{ transferCardRowData.model }}</span> |
| | | </div> |
| | | <!-- <div class="info-item"> |
| | |
| | | <span class="info-value">{{ transferCardRowData.productName }}</span> |
| | | </div> |
| | | <div class="info-item"> |
| | | <span class="info-label">产åè§æ ¼</span> |
| | | <span class="info-label">è§æ ¼åå·</span> |
| | | <span class="info-value">{{ transferCardRowData.model }}</span> |
| | | </div> |
| | | <div class="info-item"> |
| | |
| | | style="width: 160px;" |
| | | @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="产åè§æ ¼:" |
| | | <el-form-item label="è§æ ¼åå·:" |
| | | prop="model"> |
| | | <el-input v-model="searchForm.model" |
| | | placeholder="请è¾å
¥" |
| | |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col> |
| | | <el-form-item label="产åè§æ ¼"> |
| | | <el-form-item label="è§æ ¼åå·"> |
| | | <div class="info-display">{{ mergeForm.model || '-' }}</div> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | :max="sumAssignedQuantity" |
| | | @change="onBlur" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | <el-form-item label="å建æ¶é´"> |
| | | <el-date-picker v-model="mergeCreateTimeDate" |
| | | type="date" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | |
| | | prop="mpsNo"> |
| | | <el-input v-model="form.mpsNo" |
| | | disabled |
| | | placeholder="æ°å¢åèªå¨çæ" /> |
| | | placeholder="ä¿ååèªå¨çæ" /> |
| | | </el-form-item> |
| | | <el-form-item label="产ååç§°" |
| | | prop="productId"> |
| | |
| | | @change="handleProductChange" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | <el-form-item label="产åè§æ ¼" |
| | | <el-form-item label="è§æ ¼åå·" |
| | | prop="productModelId"> |
| | | <el-select v-model="form.productModelId" |
| | | @change="handleChangeSpecification" |
| | |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 100%" |
| | | placeholder="è¯·éæ©æ¿è¯ºæ¥æ" /> |
| | | </el-form-item> |
| | | <el-form-item label="å建æ¶é´" |
| | | prop="createTime"> |
| | | <el-date-picker v-model="formCreateTimeDate" |
| | | type="date" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 100%" |
| | | placeholder="è¯·éæ©å建æ¶é´" /> |
| | | </el-form-item> |
| | | <el-form-item label="夿³¨" |
| | | prop="remark"> |
| | |
| | | }, |
| | | }, |
| | | { |
| | | label: "产åè§æ ¼", |
| | | label: "è§æ ¼åå·", |
| | | prop: "model", |
| | | width: "150px", |
| | | className: "spec-cell", |
| | |
| | | Number(row.qtyRequired || 0) - Number(row.quantityIssued || 0); |
| | | mergeForm.planCompleteTime = row.requiredDate || ""; |
| | | mergeForm.productId = row.productId || ""; |
| | | mergeForm.createTime = dayjs().format("YYYY-MM-DD HH:mm:ss"); |
| | | mergeForm.ids = [row.id]; |
| | | sumAssignedQuantity.value = |
| | | Number(row.qtyRequired || 0) - Number(row.quantityIssued || 0); |
| | |
| | | totalAssignedQuantity: 0, |
| | | planCompleteTime: "", |
| | | productId: "", |
| | | createTime: "", |
| | | }); |
| | | const mergeCreateTimeDate = computed({ |
| | | get: () => (mergeForm.createTime ? String(mergeForm.createTime).split(" ")[0] : ""), |
| | | set: (value) => { |
| | | mergeForm.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : ""; |
| | | }, |
| | | }); |
| | | |
| | | // 导å
¥ç¸å
³ |
| | |
| | | requiredDate: "", |
| | | promisedDeliveryDate: "", |
| | | remark: "", |
| | | createTime: "", |
| | | }); |
| | | const formCreateTimeDate = computed({ |
| | | get: () => (form.createTime ? String(form.createTime).split(" ")[0] : ""), |
| | | set: (value) => { |
| | | form.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : ""; |
| | | }, |
| | | }); |
| | | const rules = reactive({ |
| | | productId: [{ required: true, message: "è¯·éæ©äº§å", trigger: "change" }], |
| | | productModelId: [ |
| | | { required: true, message: "è¯·éæ©äº§åè§æ ¼", trigger: "change" }, |
| | | { required: true, message: "è¯·éæ©è§æ ¼åå·", trigger: "change" }, |
| | | ], |
| | | qtyRequired: [{ required: true, message: "请è¾å
¥æ°é", trigger: "blur" }], |
| | | requiredDate: [ |
| | |
| | | }); |
| | | }; |
| | | |
| | | // éä¸ç产åè§æ ¼ID |
| | | // éä¸çè§æ ¼åå·ID |
| | | const selectedProductModelId = ref(""); |
| | | |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = selection => { |
| | | selectedRows.value = selection; |
| | | // 妿æéä¸çè¡ï¼è®°å½ç¬¬ä¸ä¸ªéä¸è¡ç产åè§æ ¼ID |
| | | // 妿æéä¸çè¡ï¼è®°å½ç¬¬ä¸ä¸ªéä¸è¡çè§æ ¼åå·ID |
| | | if (selection.length > 0) { |
| | | selectedProductModelId.value = selection[0].productModelId; |
| | | } else { |
| | | // å¦ææ²¡æéä¸çè¡ï¼æ¸
空产åè§æ ¼ID |
| | | // å¦ææ²¡æéä¸çè¡ï¼æ¸
ç©ºè§æ ¼åå·ID |
| | | selectedProductModelId.value = ""; |
| | | } |
| | | }; |
| | |
| | | if (!selectedProductModelId.value) { |
| | | return true; |
| | | } |
| | | // 妿æéä¸çè¡ï¼åªæäº§åè§æ ¼IDç¸åçè¡æå¯éæ© |
| | | // 妿æéä¸çè¡ï¼åªæè§æ ¼åå·IDç¸åçè¡æå¯éæ© |
| | | return row.productModelId === selectedProductModelId.value; |
| | | }; |
| | | // æåæ°æ®æé®æä½ |
| | |
| | | mergeForm.totalAssignedQuantity = totalAssignedQuantity; |
| | | mergeForm.planCompleteTime = firstRow.requiredDate || ""; |
| | | mergeForm.productId = firstRow.productId || ""; |
| | | mergeForm.createTime = dayjs().format("YYYY-MM-DD HH:mm:ss"); |
| | | mergeForm.ids = selectedRows.value.map(row => row.id); |
| | | |
| | | // æå¼å¼¹çª |
| | |
| | | requiredDate: "", |
| | | promisedDeliveryDate: "", |
| | | remark: "", |
| | | createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), |
| | | }); |
| | | dialogVisible.value = true; |
| | | fetchProductOptions(); |
| | |
| | | requiredDate: row.requiredDate || "", |
| | | promisedDeliveryDate: row.promisedDeliveryDate || "", |
| | | remark: row.remark || "", |
| | | createTime: row.createTime || "", |
| | | }); |
| | | dialogVisible.value = true; |
| | | fetchProductOptions(); |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <div class="search_form mb20"> |
| | | <div> |
| | | <span class="search_title">产ååç§°ï¼</span> |
| | | <el-input |
| | | v-model="searchForm.productName" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥äº§ååç§°æç´¢" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | /> |
| | | <span style="margin-left: 10px" class="search_title">æ£æµæ¥æï¼</span> |
| | | <el-date-picker v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange" |
| | | placeholder="è¯·éæ©" clearable @change="changeDaterange"/> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px" |
| | | >æç´¢ |
| | | </el-button |
| | | > |
| | | </div> |
| | | <div> |
| | | <el-button type="primary" @click="openForm('add')">æ°å¢</el-button> |
| | | <el-form ref="searchFormRef" |
| | | :model="searchForm" |
| | | class="demo-form-inline"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="4"> |
| | | <el-form-item label="产ååç§°" |
| | | prop="productName"> |
| | | <el-input v-model="searchForm.productName" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥äº§ååç§°æç´¢" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="6"> |
| | | <el-form-item label="æ£æµæ¥æ" |
| | | prop="entryDate"> |
| | | <el-date-picker v-model="searchForm.entryDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="daterange" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | @change="changeDaterange" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="4"> |
| | | <el-form-item label="éå®åå·" |
| | | prop="salesContractNo"> |
| | | <el-input v-model="searchForm.salesContractNo" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥éå®åå·æç´¢" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="4"> |
| | | <el-form-item label="ç产工åå·" |
| | | prop="workOrderNo"> |
| | | <el-input v-model="searchForm.workOrderNo" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥ç产工åå·æç´¢" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <!-- æé® --> |
| | | <el-col :span="4"> |
| | | <el-form-item> |
| | | <el-button type="primary" |
| | | @click="getList"> |
| | | æç´¢ |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <div class="actions"> |
| | | <el-button type="primary" |
| | | @click="openForm('add')">æ°å¢</el-button> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | <el-button type="danger" plain @click="handleDelete">å é¤</el-button> |
| | | <el-button type="danger" |
| | | plain |
| | | @click="handleDelete">å é¤</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | :total="page.total" |
| | | ></PIMTable> |
| | | <PIMTable rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | :total="page.total"></PIMTable> |
| | | </div> |
| | | <InspectionFormDia ref="inspectionFormDia" @close="handleQuery"></InspectionFormDia> |
| | | <FormDia ref="formDia" @close="handleQuery"></FormDia> |
| | | <files-dia ref="filesDia" @close="handleQuery"></files-dia> |
| | | <el-dialog v-model="dialogFormVisible" title="ç¼è¾æ£éªå" width="30%" |
| | | <InspectionFormDia ref="inspectionFormDia" |
| | | @close="handleQuery"></InspectionFormDia> |
| | | <FormDia ref="formDia" |
| | | @close="handleQuery"></FormDia> |
| | | <files-dia ref="filesDia" |
| | | @close="handleQuery"></files-dia> |
| | | <el-dialog v-model="dialogFormVisible" |
| | | title="ç¼è¾æ£éªå" |
| | | width="30%" |
| | | @close="closeDia"> |
| | | <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef"> |
| | | <el-form-item label="æ£éªåï¼" prop="checkName"> |
| | | <el-select v-model="form.checkName" placeholder="è¯·éæ©" clearable> |
| | | <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName" |
| | | :value="item.nickName"/> |
| | | <el-form :model="form" |
| | | label-width="140px" |
| | | label-position="top" |
| | | :rules="rules" |
| | | ref="formRef"> |
| | | <el-form-item label="æ£éªåï¼" |
| | | prop="checkName"> |
| | | <el-select v-model="form.checkName" |
| | | placeholder="è¯·éæ©" |
| | | clearable> |
| | | <el-option v-for="item in userList" |
| | | :key="item.nickName" |
| | | :label="item.nickName" |
| | | :value="item.nickName" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm">确认</el-button> |
| | | <el-button type="primary" |
| | | @click="submitForm">确认</el-button> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {Search} from "@element-plus/icons-vue"; |
| | | import {onMounted, ref, reactive, toRefs, getCurrentInstance, nextTick} from "vue"; |
| | | import InspectionFormDia from "@/views/qualityManagement/finalInspection/components/inspectionFormDia.vue"; |
| | | import FormDia from "@/views/qualityManagement/finalInspection/components/formDia.vue"; |
| | | import {ElMessageBox} from "element-plus"; |
| | | import { |
| | | downloadQualityInspect, |
| | | qualityInspectDel, |
| | | qualityInspectListPage, qualityInspectUpdate, |
| | | submitQualityInspect |
| | | } from "@/api/qualityManagement/rawMaterialInspection.js"; |
| | | import FilesDia from "@/views/qualityManagement/finalInspection/components/filesDia.vue"; |
| | | import dayjs from "dayjs"; |
| | | import {userListNoPage} from "@/api/system/user.js"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import { |
| | | onMounted, |
| | | ref, |
| | | reactive, |
| | | toRefs, |
| | | getCurrentInstance, |
| | | nextTick, |
| | | } from "vue"; |
| | | import InspectionFormDia from "@/views/qualityManagement/finalInspection/components/inspectionFormDia.vue"; |
| | | import FormDia from "@/views/qualityManagement/finalInspection/components/formDia.vue"; |
| | | import { ElMessageBox } from "element-plus"; |
| | | import { |
| | | downloadQualityInspect, |
| | | qualityInspectDel, |
| | | qualityInspectListPage, |
| | | qualityInspectUpdate, |
| | | submitQualityInspect, |
| | | } from "@/api/qualityManagement/rawMaterialInspection.js"; |
| | | import FilesDia from "@/views/qualityManagement/finalInspection/components/filesDia.vue"; |
| | | import dayjs from "dayjs"; |
| | | import { userListNoPage } from "@/api/system/user.js"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | productName: "", |
| | | entryDate: undefined, // å½å
¥æ¥æ |
| | | entryDateStart: undefined, |
| | | entryDateEnd: undefined, |
| | | }, |
| | | rules: { |
| | | checkName: [{required: true, message: "è¯·éæ©", trigger: "change"}], |
| | | }, |
| | | }); |
| | | const {searchForm} = toRefs(data); |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "æ£æµæ¥æ", |
| | | prop: "checkTime", |
| | | width: 120 |
| | | }, |
| | | { |
| | | label: "éå®åå·", |
| | | prop: "salesContractNo", |
| | | width: 120 |
| | | }, |
| | | { |
| | | label: "ç产工åå·", |
| | | prop: "workOrderNo", |
| | | width: 120 |
| | | }, |
| | | { |
| | | label: "æ£éªå", |
| | | prop: "checkName", |
| | | }, |
| | | { |
| | | label: "产ååç§°", |
| | | prop: "productName", |
| | | }, |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | prop: "model", |
| | | }, |
| | | { |
| | | label: "åä½", |
| | | prop: "unit", |
| | | }, |
| | | { |
| | | label: "æ»æ°é", |
| | | prop: "quantity", |
| | | width: 100 |
| | | }, |
| | | { |
| | | label: "åæ ¼æ°é", |
| | | prop: "qualifiedQuantity", |
| | | width: 100 |
| | | }, |
| | | { |
| | | label: "ä¸åæ ¼æ°é", |
| | | prop: "unqualifiedQuantity", |
| | | width: 100 |
| | | }, |
| | | { |
| | | label: "æ£æµåä½", |
| | | prop: "checkCompany", |
| | | width: 120 |
| | | }, |
| | | { |
| | | label: "æ£æµç»æ", |
| | | prop: "checkResult", |
| | | dataType: "tag", |
| | | formatType: (params) => { |
| | | if (params == 'ä¸åæ ¼') { |
| | | return "danger"; |
| | | } else if (params == 'åæ ¼') { |
| | | return "success"; |
| | | } else { |
| | | return 'danger'; |
| | | } |
| | | const data = reactive({ |
| | | searchForm: { |
| | | productName: "", |
| | | salesContractNo: "", |
| | | workOrderNo: "", |
| | | entryDate: undefined, // å½å
¥æ¥æ |
| | | entryDateStart: undefined, |
| | | entryDateEnd: undefined, |
| | | }, |
| | | }, |
| | | { |
| | | label: "æäº¤ç¶æ", |
| | | prop: "inspectState", |
| | | formatData: (params) => { |
| | | if (params) { |
| | | return "å·²æäº¤"; |
| | | } else { |
| | | return "æªæäº¤"; |
| | | } |
| | | rules: { |
| | | checkName: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | }, |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 280, |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openForm("edit", row); |
| | | }, |
| | | disabled: (row) => { |
| | | // å·²æäº¤åç¦ç¨ |
| | | if (row.inspectState == 1) return true; |
| | | // 妿æ£éªåæå¼ï¼åªæå½åç»å½ç¨æ·è½ç¼è¾ |
| | | if (row.checkName) { |
| | | return row.checkName !== userStore.nickName; |
| | | } |
| | | return false; |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "æ£æµæ¥æ", |
| | | prop: "checkTime", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "éå®åå·", |
| | | prop: "salesContractNo", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "ç产工åå·", |
| | | prop: "workOrderNo", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "æ£éªå", |
| | | prop: "checkName", |
| | | }, |
| | | { |
| | | label: "产ååç§°", |
| | | prop: "productName", |
| | | }, |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | prop: "model", |
| | | }, |
| | | { |
| | | label: "åä½", |
| | | prop: "unit", |
| | | }, |
| | | { |
| | | label: "æ»æ°é", |
| | | prop: "quantity", |
| | | width: 100, |
| | | }, |
| | | { |
| | | label: "åæ ¼æ°é", |
| | | prop: "qualifiedQuantity", |
| | | width: 100, |
| | | }, |
| | | { |
| | | label: "ä¸åæ ¼æ°é", |
| | | prop: "unqualifiedQuantity", |
| | | width: 100, |
| | | }, |
| | | { |
| | | label: "åæ ¼ç", |
| | | prop: "passRate", |
| | | width: 100, |
| | | dataType: "tag", |
| | | formatType: params => { |
| | | if (!params) return ""; |
| | | const rate = parseFloat(params); |
| | | if (rate < 90) { |
| | | return "danger"; |
| | | } else if (rate === 100) { |
| | | return "success"; |
| | | } else { |
| | | return "warning"; |
| | | } |
| | | }, |
| | | { |
| | | name: "æ¥ç", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openForm("view", row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "éä»¶", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openFilesFormDia(row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "æäº¤", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | submit(row.id); |
| | | }, |
| | | disabled: (row) => { |
| | | // å·²æäº¤åç¦ç¨ |
| | | if (row.inspectState == 1) return true; |
| | | // 妿æ£éªåæå¼ï¼åªæå½åç»å½ç¨æ·è½æäº¤ |
| | | if (row.checkName) { |
| | | return row.checkName !== userStore.nickName; |
| | | } |
| | | return false; |
| | | }, |
| | | { |
| | | label: "æ£æµåä½", |
| | | prop: "checkCompany", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "æ£æµç»æ", |
| | | prop: "checkResult", |
| | | dataType: "tag", |
| | | formatType: params => { |
| | | if (params == "ä¸åæ ¼") { |
| | | return "danger"; |
| | | } else if (params == "åæ ¼") { |
| | | return "success"; |
| | | } else { |
| | | return "danger"; |
| | | } |
| | | }, |
| | | { |
| | | name: "åé
æ£éªå", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | if (!row.checkName) { |
| | | open(row) |
| | | } else { |
| | | proxy.$modal.msgError("æ£éªåå·²åå¨"); |
| | | } |
| | | }, |
| | | disabled: (row) => { |
| | | return row.inspectState == 1 || row.checkName; |
| | | }, |
| | | { |
| | | label: "æäº¤ç¶æ", |
| | | prop: "inspectState", |
| | | formatData: params => { |
| | | if (params) { |
| | | return "å·²æäº¤"; |
| | | } else { |
| | | return "æªæäº¤"; |
| | | } |
| | | }, |
| | | { |
| | | name: "ä¸è½½", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | downLoadFile(row); |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 280, |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: row => { |
| | | openForm("edit", row); |
| | | }, |
| | | disabled: row => { |
| | | // å·²æäº¤åç¦ç¨ |
| | | if (row.inspectState == 1) return true; |
| | | // 妿æ£éªåæå¼ï¼åªæå½åç»å½ç¨æ·è½ç¼è¾ |
| | | if (row.checkName) { |
| | | return row.checkName !== userStore.nickName; |
| | | } |
| | | return false; |
| | | }, |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const tableLoading = ref(false); |
| | | const currentRow = ref(null) |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0 |
| | | }); |
| | | const formDia = ref() |
| | | const filesDia = ref() |
| | | const inspectionFormDia = ref() |
| | | const {proxy} = getCurrentInstance() |
| | | const userStore = useUserStore() |
| | | const userList = ref([]); |
| | | const form = ref({ |
| | | checkName: "" |
| | | }); |
| | | const dialogFormVisible = ref(false); |
| | | { |
| | | name: "æ¥ç", |
| | | type: "text", |
| | | clickFun: row => { |
| | | openForm("view", row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "éä»¶", |
| | | type: "text", |
| | | clickFun: row => { |
| | | openFilesFormDia(row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "æäº¤", |
| | | type: "text", |
| | | clickFun: row => { |
| | | submit(row.id); |
| | | }, |
| | | disabled: row => { |
| | | // å·²æäº¤åç¦ç¨ |
| | | if (row.inspectState == 1) return true; |
| | | // 妿æ£éªåæå¼ï¼åªæå½åç»å½ç¨æ·è½æäº¤ |
| | | if (row.checkName) { |
| | | return row.checkName !== userStore.nickName; |
| | | } |
| | | return false; |
| | | }, |
| | | }, |
| | | { |
| | | name: "åé
æ£éªå", |
| | | type: "text", |
| | | clickFun: row => { |
| | | if (!row.checkName) { |
| | | open(row); |
| | | } else { |
| | | proxy.$modal.msgError("æ£éªåå·²åå¨"); |
| | | } |
| | | }, |
| | | disabled: row => { |
| | | return row.inspectState == 1 || row.checkName; |
| | | }, |
| | | }, |
| | | { |
| | | name: "ä¸è½½", |
| | | type: "text", |
| | | clickFun: row => { |
| | | downLoadFile(row); |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const tableLoading = ref(false); |
| | | const currentRow = ref(null); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | const formDia = ref(); |
| | | const filesDia = ref(); |
| | | const inspectionFormDia = ref(); |
| | | const { proxy } = getCurrentInstance(); |
| | | const userStore = useUserStore(); |
| | | const userList = ref([]); |
| | | const form = ref({ |
| | | checkName: "", |
| | | }); |
| | | const dialogFormVisible = ref(false); |
| | | |
| | | const changeDaterange = (value) => { |
| | | searchForm.value.entryDateStart = undefined; |
| | | searchForm.value.entryDateEnd = undefined; |
| | | if (value) { |
| | | searchForm.value.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD"); |
| | | searchForm.value.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD"); |
| | | } |
| | | getList(); |
| | | }; |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const pagination = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | const params = {...searchForm.value, ...page}; |
| | | params.entryDate = undefined |
| | | qualityInspectListPage({...params, inspectType: 2}).then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records |
| | | page.total = res.data.total; |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | | }) |
| | | }; |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | const changeDaterange = value => { |
| | | searchForm.value.entryDateStart = undefined; |
| | | searchForm.value.entryDateEnd = undefined; |
| | | if (value) { |
| | | searchForm.value.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD"); |
| | | searchForm.value.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD"); |
| | | } |
| | | getList(); |
| | | }; |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const pagination = obj => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | const params = { ...searchForm.value, ...page }; |
| | | params.entryDate = undefined; |
| | | qualityInspectListPage({ ...params, inspectType: 2 }) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records.map(item => { |
| | | const quantity = parseFloat(item.quantity); |
| | | const qualifiedQuantity = parseFloat(item.qualifiedQuantity); |
| | | let passRate = null; |
| | | if (!isNaN(quantity) && !isNaN(qualifiedQuantity) && quantity > 0) { |
| | | passRate = ((qualifiedQuantity / quantity) * 100).toFixed(2) + "%"; |
| | | } |
| | | return { |
| | | ...item, |
| | | passRate: passRate, |
| | | }; |
| | | }); |
| | | page.total = res.data.total; |
| | | }) |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = selection => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openForm = (type, row) => { |
| | | nextTick(() => { |
| | | formDia.value?.openDialog(type, row) |
| | | }) |
| | | }; |
| | | // æå¼æ°å¢æ£éªå¼¹æ¡ |
| | | const openInspectionForm = (type, row) => { |
| | | nextTick(() => { |
| | | inspectionFormDia.value?.openDialog(type, row) |
| | | }) |
| | | }; |
| | | // æå¼éä»¶å¼¹æ¡ |
| | | const openFilesFormDia = (type, row) => { |
| | | nextTick(() => { |
| | | filesDia.value?.openDialog(type, row) |
| | | }) |
| | | }; |
| | | // æå¼å¼¹æ¡ |
| | | const openForm = (type, row) => { |
| | | nextTick(() => { |
| | | formDia.value?.openDialog(type, row); |
| | | }); |
| | | }; |
| | | // æå¼æ°å¢æ£éªå¼¹æ¡ |
| | | const openInspectionForm = (type, row) => { |
| | | nextTick(() => { |
| | | inspectionFormDia.value?.openDialog(type, row); |
| | | }); |
| | | }; |
| | | // æå¼éä»¶å¼¹æ¡ |
| | | const openFilesFormDia = (type, row) => { |
| | | nextTick(() => { |
| | | filesDia.value?.openDialog(type, row); |
| | | }); |
| | | }; |
| | | |
| | | // å é¤ |
| | | 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", |
| | | }) |
| | | // å é¤ |
| | | 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(() => { |
| | | qualityInspectDel(ids).then((res) => { |
| | | qualityInspectDel(ids).then(res => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }); |
| | |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | }; |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/quality/qualityInspect/export", {inspectType: 2}, "åºåæ£éª.xlsx"); |
| | | proxy.download( |
| | | "/quality/qualityInspect/export", |
| | | { inspectType: 2 }, |
| | | "åºåæ£éª.xlsx" |
| | | ); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | }; |
| | | |
| | | // æä»· |
| | | const submit = async (id) => { |
| | | const res = await submitQualityInspect({id: id}) |
| | | if (res.code === 200) { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | getList(); |
| | | } |
| | | } |
| | | |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | dialogFormVisible.value = false; |
| | | }; |
| | | |
| | | const submitForm = () => { |
| | | if (currentRow.value) { |
| | | const data = { |
| | | ...form.value, |
| | | id: currentRow.value.id |
| | | } |
| | | qualityInspectUpdate(data).then(res => { |
| | | // æä»· |
| | | const submit = async id => { |
| | | const res = await submitQualityInspect({ id: id }); |
| | | if (res.code === 200) { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | getList(); |
| | | }) |
| | | } |
| | | }; |
| | | } |
| | | }; |
| | | |
| | | const open = async (row) => { |
| | | let userLists = await userListNoPage(); |
| | | userList.value = userLists.data; |
| | | currentRow.value = row |
| | | dialogFormVisible.value = true |
| | | } |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | dialogFormVisible.value = false; |
| | | }; |
| | | |
| | | const downLoadFile = (row) => { |
| | | downloadQualityInspect({id: row.id}).then((blobData) => { |
| | | const blob = new Blob([blobData], { |
| | | type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', |
| | | }) |
| | | const downloadUrl = window.URL.createObjectURL(blob) |
| | | const submitForm = () => { |
| | | if (currentRow.value) { |
| | | const data = { |
| | | ...form.value, |
| | | id: currentRow.value.id, |
| | | }; |
| | | qualityInspectUpdate(data).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | getList(); |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | const link = document.createElement('a') |
| | | link.href = downloadUrl |
| | | link.download = 'åæææ£éªæ¥å.docx' |
| | | document.body.appendChild(link) |
| | | link.click() |
| | | const open = async row => { |
| | | let userLists = await userListNoPage(); |
| | | userList.value = userLists.data; |
| | | currentRow.value = row; |
| | | dialogFormVisible.value = true; |
| | | }; |
| | | |
| | | document.body.removeChild(link) |
| | | window.URL.revokeObjectURL(downloadUrl) |
| | | }) |
| | | }; |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | const downLoadFile = row => { |
| | | downloadQualityInspect({ id: row.id }).then(blobData => { |
| | | const blob = new Blob([blobData], { |
| | | type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", |
| | | }); |
| | | const downloadUrl = window.URL.createObjectURL(blob); |
| | | |
| | | const link = document.createElement("a"); |
| | | link.href = downloadUrl; |
| | | link.download = "åæææ£éªæ¥å.docx"; |
| | | document.body.appendChild(link); |
| | | link.click(); |
| | | |
| | | document.body.removeChild(link); |
| | | window.URL.revokeObjectURL(downloadUrl); |
| | | }); |
| | | }; |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped></style> |
| | | <style scoped lang="scss"> |
| | | .actions { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | margin-bottom: 10px; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px"> |
| | | <el-form-item label="产ååç§°" prop="productName"> |
| | | <el-input |
| | | v-model="queryParams.productName" |
| | | placeholder="请è¾å
¥äº§ååç§°" |
| | | clearable |
| | | @keyup.enter.native="handleQuery" |
| | | /> |
| | | <el-form :model="queryParams" |
| | | ref="queryForm" |
| | | :inline="true" |
| | | v-show="showSearch" |
| | | label-width="68px"> |
| | | <el-form-item label="产ååç§°" |
| | | prop="productName"> |
| | | <el-input v-model="queryParams.productName" |
| | | placeholder="请è¾å
¥äº§ååç§°" |
| | | clearable |
| | | @keyup.enter.native="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="æ¹æ¬¡å·" prop="batchNumber"> |
| | | <el-input |
| | | v-model="queryParams.batchNumber" |
| | | placeholder="请è¾å
¥æ¹æ¬¡å·" |
| | | clearable |
| | | @keyup.enter.native="handleQuery" |
| | | /> |
| | | <el-form-item label="æ¹æ¬¡å·" |
| | | prop="batchNumber"> |
| | | <el-input v-model="queryParams.batchNumber" |
| | | placeholder="请è¾å
¥æ¹æ¬¡å·" |
| | | clearable |
| | | @keyup.enter.native="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="é忥æ" prop="returnDate"> |
| | | <el-date-picker |
| | | clearable |
| | | v-model="queryParams.returnDate" |
| | | type="date" |
| | | value-format="YYYY-MM-DD" |
| | | placeholder="è¯·éæ©é忥æ"> |
| | | <el-form-item label="é忥æ" |
| | | prop="returnDate"> |
| | | <el-date-picker clearable |
| | | v-model="queryParams.returnDate" |
| | | type="date" |
| | | value-format="YYYY-MM-DD" |
| | | placeholder="è¯·éæ©é忥æ"> |
| | | </el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" icon="Search" @click="handleQuery">æç´¢</el-button> |
| | | <el-button icon="Refresh" @click="resetQuery">éç½®</el-button> |
| | | <el-button type="primary" |
| | | icon="Search" |
| | | @click="handleQuery">æç´¢</el-button> |
| | | <el-button icon="Refresh" |
| | | @click="resetQuery">éç½®</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <el-row :gutter="10" class="mb8"> |
| | | <el-row :gutter="10" |
| | | class="mb8"> |
| | | <el-col :span="1.5"> |
| | | <el-button |
| | | type="primary" |
| | | plain |
| | | icon="Plus" |
| | | @click="handleAdd" |
| | | >æ°å¢</el-button> |
| | | <el-button type="primary" |
| | | plain |
| | | icon="Plus" |
| | | @click="handleAdd">æ°å¢</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button |
| | | type="success" |
| | | plain |
| | | icon="Edit" |
| | | :disabled="single" |
| | | @click="handleUpdate" |
| | | >ä¿®æ¹</el-button> |
| | | <el-button type="success" |
| | | plain |
| | | icon="Edit" |
| | | :disabled="single" |
| | | @click="handleUpdate">ä¿®æ¹</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button |
| | | type="danger" |
| | | plain |
| | | icon="Delete" |
| | | :disabled="multiple" |
| | | @click="handleDelete" |
| | | >å é¤</el-button> |
| | | <el-button type="danger" |
| | | plain |
| | | icon="Delete" |
| | | :disabled="multiple" |
| | | @click="handleDelete">å é¤</el-button> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button |
| | | type="warning" |
| | | plain |
| | | icon="Download" |
| | | @click="handleExport" |
| | | >导åº</el-button> |
| | | <el-button type="warning" |
| | | plain |
| | | icon="Download" |
| | | @click="handleExport">导åº</el-button> |
| | | </el-col> |
| | | <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> |
| | | <right-toolbar v-model:showSearch="showSearch" |
| | | @queryTable="getList"></right-toolbar> |
| | | </el-row> |
| | | |
| | | <el-table v-loading="loading" :data="nearExpiryReturnList" @selection-change="handleSelectionChange"> |
| | | <el-table-column type="selection" width="55" align="center" /> |
| | | <el-table-column label="åºå·" type="index" width="50" align="center" /> |
| | | <el-table-column label="产ååç§°" prop="productName" /> |
| | | <el-table-column label="产åè§æ ¼" prop="productSpec" /> |
| | | <el-table-column label="æ¹æ¬¡å·" prop="batchNumber" /> |
| | | <el-table-column label="çäº§æ¥æ" prop="productionDate" align="center"> |
| | | <el-table v-loading="loading" |
| | | :data="nearExpiryReturnList" |
| | | @selection-change="handleSelectionChange"> |
| | | <el-table-column type="selection" |
| | | width="55" |
| | | align="center" /> |
| | | <el-table-column label="åºå·" |
| | | type="index" |
| | | width="50" |
| | | align="center" /> |
| | | <el-table-column label="产ååç§°" |
| | | prop="productName" /> |
| | | <el-table-column label="è§æ ¼åå·" |
| | | prop="productSpec" /> |
| | | <el-table-column label="æ¹æ¬¡å·" |
| | | prop="batchNumber" /> |
| | | <el-table-column label="çäº§æ¥æ" |
| | | prop="productionDate" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | <span>{{ parseTime(scope.row.productionDate, '{y}-{m}-{d}') }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="å°ææ¥æ" prop="expiryDate" align="center"> |
| | | <el-table-column label="å°ææ¥æ" |
| | | prop="expiryDate" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | <span>{{ parseTime(scope.row.expiryDate, '{y}-{m}-{d}') }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="éåæ°é" prop="returnQuantity" /> |
| | | <el-table-column label="éååå " prop="returnReason" /> |
| | | <el-table-column label="é忥æ" prop="returnDate" align="center"> |
| | | <el-table-column label="éåæ°é" |
| | | prop="returnQuantity" /> |
| | | <el-table-column label="éååå " |
| | | prop="returnReason" /> |
| | | <el-table-column label="é忥æ" |
| | | prop="returnDate" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | <span>{{ parseTime(scope.row.returnDate, '{y}-{m}-{d}') }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="å¤çç¶æ" prop="status" align="center"> |
| | | <el-table-column label="å¤çç¶æ" |
| | | prop="status" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | <dict-tag :options="statusOptions" :value="scope.row.status"/> |
| | | <dict-tag :options="statusOptions" |
| | | :value="scope.row.status" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æä½" align="center" class-name="small-padding fixed-width"> |
| | | <el-table-column label="æä½" |
| | | align="center" |
| | | class-name="small-padding fixed-width"> |
| | | <template #default="scope"> |
| | | <el-button size="mini" type="text" icon="Edit" @click="handleUpdate(scope.row)">ä¿®æ¹</el-button> |
| | | <el-button size="mini" type="text" icon="Delete" @click="handleDelete(scope.row)">å é¤</el-button> |
| | | <el-button size="mini" |
| | | type="text" |
| | | icon="Edit" |
| | | @click="handleUpdate(scope.row)">ä¿®æ¹</el-button> |
| | | <el-button size="mini" |
| | | type="text" |
| | | icon="Delete" |
| | | @click="handleDelete(scope.row)">å é¤</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <pagination |
| | | v-show="total>0" |
| | | :total="total" |
| | | v-model:page="queryParams.pageNum" |
| | | v-model:limit="queryParams.pageSize" |
| | | @pagination="getList" |
| | | /> |
| | | |
| | | <pagination v-show="total>0" |
| | | :total="total" |
| | | v-model:page="queryParams.pageNum" |
| | | v-model:limit="queryParams.pageSize" |
| | | @pagination="getList" /> |
| | | <!-- æ·»å æä¿®æ¹ä¸´æéåå°è´¦å¯¹è¯æ¡ --> |
| | | <el-dialog :title="title" v-model="open" width="800px" append-to-body> |
| | | <el-form ref="formRef" :model="form" :rules="rules" label-width="100px"> |
| | | <el-dialog :title="title" |
| | | v-model="open" |
| | | width="800px" |
| | | append-to-body> |
| | | <el-form ref="formRef" |
| | | :model="form" |
| | | :rules="rules" |
| | | label-width="100px"> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="产ååç§°" prop="productName"> |
| | | <el-input v-model="form.productName" placeholder="请è¾å
¥äº§ååç§°" /> |
| | | <el-form-item label="产ååç§°" |
| | | prop="productName"> |
| | | <el-input v-model="form.productName" |
| | | placeholder="请è¾å
¥äº§ååç§°" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="产åè§æ ¼" prop="productSpec"> |
| | | <el-input v-model="form.productSpec" placeholder="请è¾å
¥äº§åè§æ ¼" /> |
| | | <el-form-item label="è§æ ¼åå·" |
| | | prop="productSpec"> |
| | | <el-input v-model="form.productSpec" |
| | | placeholder="请è¾å
¥è§æ ¼åå·" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ¹æ¬¡å·" prop="batchNumber"> |
| | | <el-input v-model="form.batchNumber" placeholder="请è¾å
¥æ¹æ¬¡å·" /> |
| | | <el-form-item label="æ¹æ¬¡å·" |
| | | prop="batchNumber"> |
| | | <el-input v-model="form.batchNumber" |
| | | placeholder="请è¾å
¥æ¹æ¬¡å·" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éåæ°é" prop="returnQuantity"> |
| | | <el-input-number v-model="form.returnQuantity" controls-position="right" :min="1" /> |
| | | <el-form-item label="éåæ°é" |
| | | prop="returnQuantity"> |
| | | <el-input-number v-model="form.returnQuantity" |
| | | controls-position="right" |
| | | :min="1" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="çäº§æ¥æ" prop="productionDate"> |
| | | <el-date-picker |
| | | clearable |
| | | v-model="form.productionDate" |
| | | type="date" |
| | | value-format="YYYY-MM-DD" |
| | | placeholder="è¯·éæ©çäº§æ¥æ"> |
| | | <el-form-item label="çäº§æ¥æ" |
| | | prop="productionDate"> |
| | | <el-date-picker clearable |
| | | v-model="form.productionDate" |
| | | type="date" |
| | | value-format="YYYY-MM-DD" |
| | | placeholder="è¯·éæ©çäº§æ¥æ"> |
| | | </el-date-picker> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å°ææ¥æ" prop="expiryDate"> |
| | | <el-date-picker |
| | | clearable |
| | | v-model="form.expiryDate" |
| | | type="date" |
| | | value-format="YYYY-MM-DD" |
| | | placeholder="è¯·éæ©å°ææ¥æ"> |
| | | <el-form-item label="å°ææ¥æ" |
| | | prop="expiryDate"> |
| | | <el-date-picker clearable |
| | | v-model="form.expiryDate" |
| | | type="date" |
| | | value-format="YYYY-MM-DD" |
| | | placeholder="è¯·éæ©å°ææ¥æ"> |
| | | </el-date-picker> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="é忥æ" prop="returnDate"> |
| | | <el-date-picker |
| | | clearable |
| | | v-model="form.returnDate" |
| | | type="date" |
| | | value-format="YYYY-MM-DD" |
| | | placeholder="è¯·éæ©é忥æ"> |
| | | <el-form-item label="é忥æ" |
| | | prop="returnDate"> |
| | | <el-date-picker clearable |
| | | v-model="form.returnDate" |
| | | type="date" |
| | | value-format="YYYY-MM-DD" |
| | | placeholder="è¯·éæ©é忥æ"> |
| | | </el-date-picker> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å¤çç¶æ" prop="status"> |
| | | <el-select v-model="form.status" placeholder="è¯·éæ©å¤çç¶æ"> |
| | | <el-option |
| | | v-for="dict in statusOptions" |
| | | :key="dict.value" |
| | | :label="dict.label" |
| | | :value="dict.value" |
| | | ></el-option> |
| | | <el-form-item label="å¤çç¶æ" |
| | | prop="status"> |
| | | <el-select v-model="form.status" |
| | | placeholder="è¯·éæ©å¤çç¶æ"> |
| | | <el-option v-for="dict in statusOptions" |
| | | :key="dict.value" |
| | | :label="dict.label" |
| | | :value="dict.value"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="éååå " prop="returnReason"> |
| | | <el-input v-model="form.returnReason" type="textarea" placeholder="请è¾å
¥éååå " /> |
| | | <el-form-item label="éååå " |
| | | prop="returnReason"> |
| | | <el-input v-model="form.returnReason" |
| | | type="textarea" |
| | | placeholder="请è¾å
¥éååå " /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="夿³¨" prop="remark"> |
| | | <el-input v-model="form.remark" type="textarea" placeholder="请è¾å
¥å¤æ³¨" /> |
| | | <el-form-item label="夿³¨" |
| | | prop="remark"> |
| | | <el-input v-model="form.remark" |
| | | type="textarea" |
| | | placeholder="请è¾å
¥å¤æ³¨" /> |
| | | </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 type="primary" |
| | | @click="submitForm">ç¡® å®</el-button> |
| | | <el-button @click="cancel">å æ¶</el-button> |
| | | </div> |
| | | </template> |
| | |
| | | </template> |
| | | |
| | | <script setup name="NearExpiryReturn"> |
| | | import { ref, reactive, onMounted } from "vue"; |
| | | import { ElMessageBox } from "element-plus"; |
| | | // APIæ¥å£å·²ç§»é¤ï¼ä¸åè°ç¨å端æ¥å£ |
| | | import { ref, reactive, onMounted } from "vue"; |
| | | import { ElMessageBox } from "element-plus"; |
| | | // APIæ¥å£å·²ç§»é¤ï¼ä¸åè°ç¨å端æ¥å£ |
| | | |
| | | const { proxy } = getCurrentInstance(); |
| | | const { parseTime } = proxy; |
| | | const { proxy } = getCurrentInstance(); |
| | | const { parseTime } = proxy; |
| | | |
| | | const nearExpiryReturnList = ref([]); |
| | | const open = ref(false); |
| | | const loading = ref(true); |
| | | const showSearch = ref(true); |
| | | const ids = ref([]); |
| | | const single = ref(true); |
| | | const multiple = ref(true); |
| | | const total = ref(0); |
| | | const title = ref(""); |
| | | const nearExpiryReturnList = ref([]); |
| | | const open = ref(false); |
| | | const loading = ref(true); |
| | | const showSearch = ref(true); |
| | | const ids = ref([]); |
| | | const single = ref(true); |
| | | const multiple = ref(true); |
| | | const total = ref(0); |
| | | const title = ref(""); |
| | | |
| | | // ç¶æåå
¸ |
| | | const statusOptions = ref([ |
| | | { label: "å¾
å¤ç", value: "0" }, |
| | | { label: "å¤çä¸", value: "1" }, |
| | | { label: "已宿", value: "2" } |
| | | ]); |
| | | // ç¶æåå
¸ |
| | | const statusOptions = ref([ |
| | | { label: "å¾
å¤ç", value: "0" }, |
| | | { label: "å¤çä¸", value: "1" }, |
| | | { label: "已宿", value: "2" }, |
| | | ]); |
| | | |
| | | const data = reactive({ |
| | | form: {}, |
| | | queryParams: { |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | productName: null, |
| | | batchNumber: null, |
| | | returnDate: null |
| | | }, |
| | | rules: { |
| | | productName: [ |
| | | { required: true, message: "产ååç§°ä¸è½ä¸ºç©º", trigger: "blur" } |
| | | ], |
| | | productSpec: [ |
| | | { required: true, message: "产åè§æ ¼ä¸è½ä¸ºç©º", trigger: "blur" } |
| | | ], |
| | | batchNumber: [ |
| | | { required: true, message: "æ¹æ¬¡å·ä¸è½ä¸ºç©º", trigger: "blur" } |
| | | ], |
| | | returnQuantity: [ |
| | | { required: true, message: "éåæ°éä¸è½ä¸ºç©º", trigger: "blur" } |
| | | ], |
| | | productionDate: [ |
| | | { required: true, message: "çäº§æ¥æä¸è½ä¸ºç©º", trigger: "blur" } |
| | | ], |
| | | expiryDate: [ |
| | | { required: true, message: "å°ææ¥æä¸è½ä¸ºç©º", trigger: "blur" } |
| | | ], |
| | | returnDate: [ |
| | | { required: true, message: "é忥æä¸è½ä¸ºç©º", trigger: "blur" } |
| | | ], |
| | | returnReason: [ |
| | | { required: true, message: "éååå ä¸è½ä¸ºç©º", trigger: "blur" } |
| | | ], |
| | | status: [ |
| | | { required: true, message: "å¤çç¶æä¸è½ä¸ºç©º", trigger: "change" } |
| | | ] |
| | | } |
| | | }); |
| | | |
| | | const { queryParams, form, rules } = toRefs(data); |
| | | |
| | | /** æ¥è¯¢ä¸´æéåå°è´¦å表 */ |
| | | function getList() { |
| | | loading.value = true; |
| | | // ä¸è°ç¨æ¥å£ï¼è¿åç©ºæ°æ® |
| | | nearExpiryReturnList.value = []; |
| | | total.value = 0; |
| | | loading.value = false; |
| | | } |
| | | |
| | | // åæ¶æé® |
| | | function cancel() { |
| | | open.value = false; |
| | | reset(); |
| | | } |
| | | |
| | | // 表åéç½® |
| | | function reset() { |
| | | form.value = { |
| | | id: null, |
| | | productName: null, |
| | | productSpec: null, |
| | | batchNumber: null, |
| | | productionDate: null, |
| | | expiryDate: null, |
| | | returnQuantity: null, |
| | | returnReason: null, |
| | | returnDate: null, |
| | | status: null, |
| | | remark: null |
| | | }; |
| | | proxy.resetForm("formRef"); |
| | | } |
| | | |
| | | /** æç´¢æé®æä½ */ |
| | | function handleQuery() { |
| | | queryParams.value.pageNum = 1; |
| | | getList(); |
| | | } |
| | | |
| | | /** éç½®æé®æä½ */ |
| | | function resetQuery() { |
| | | proxy.resetForm("queryForm"); |
| | | handleQuery(); |
| | | } |
| | | |
| | | // å¤éæ¡é䏿°æ® |
| | | function handleSelectionChange(selection) { |
| | | ids.value = selection.map(item => item.id); |
| | | single.value = selection.length !== 1; |
| | | multiple.value = !selection.length; |
| | | } |
| | | |
| | | /** æ°å¢æé®æä½ */ |
| | | function handleAdd() { |
| | | reset(); |
| | | open.value = true; |
| | | title.value = "æ·»å 临æéåå°è´¦"; |
| | | } |
| | | |
| | | /** ä¿®æ¹æé®æä½ */ |
| | | function handleUpdate(row) { |
| | | reset(); |
| | | // ä¸è°ç¨æ¥å£ï¼ç´æ¥ä½¿ç¨ä¼ å
¥çæ°æ® |
| | | if (row) { |
| | | form.value = { ...row }; |
| | | open.value = true; |
| | | title.value = "ä¿®æ¹ä¸´æéåå°è´¦"; |
| | | } |
| | | } |
| | | |
| | | /** æäº¤æé® */ |
| | | function submitForm() { |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | if (valid) { |
| | | // ä¸è°ç¨æ¥å£ï¼åªæ¾ç¤ºæåæç¤º |
| | | if (form.value.id != null) { |
| | | proxy.$modal.msgSuccess("ä¿®æ¹æå"); |
| | | } else { |
| | | proxy.$modal.msgSuccess("æ°å¢æå"); |
| | | } |
| | | open.value = false; |
| | | getList(); |
| | | } |
| | | const data = reactive({ |
| | | form: {}, |
| | | queryParams: { |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | productName: null, |
| | | batchNumber: null, |
| | | returnDate: null, |
| | | }, |
| | | rules: { |
| | | productName: [ |
| | | { required: true, message: "产ååç§°ä¸è½ä¸ºç©º", trigger: "blur" }, |
| | | ], |
| | | productSpec: [ |
| | | { required: true, message: "è§æ ¼åå·ä¸è½ä¸ºç©º", trigger: "blur" }, |
| | | ], |
| | | batchNumber: [ |
| | | { required: true, message: "æ¹æ¬¡å·ä¸è½ä¸ºç©º", trigger: "blur" }, |
| | | ], |
| | | returnQuantity: [ |
| | | { required: true, message: "éåæ°éä¸è½ä¸ºç©º", trigger: "blur" }, |
| | | ], |
| | | productionDate: [ |
| | | { required: true, message: "çäº§æ¥æä¸è½ä¸ºç©º", trigger: "blur" }, |
| | | ], |
| | | expiryDate: [ |
| | | { required: true, message: "å°ææ¥æä¸è½ä¸ºç©º", trigger: "blur" }, |
| | | ], |
| | | returnDate: [ |
| | | { required: true, message: "é忥æä¸è½ä¸ºç©º", trigger: "blur" }, |
| | | ], |
| | | returnReason: [ |
| | | { required: true, message: "éååå ä¸è½ä¸ºç©º", trigger: "blur" }, |
| | | ], |
| | | status: [ |
| | | { required: true, message: "å¤çç¶æä¸è½ä¸ºç©º", trigger: "change" }, |
| | | ], |
| | | }, |
| | | }); |
| | | } |
| | | |
| | | /** å é¤æé®æä½ */ |
| | | function handleDelete(row) { |
| | | const deleteIds = row.id || ids.value; |
| | | ElMessageBox.confirm('æ¯å¦ç¡®è®¤å é¤ä¸´æéåå°è´¦ç¼å·ä¸º"' + deleteIds + '"çæ°æ®é¡¹ï¼', "è¦å", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning" |
| | | }).then(function() { |
| | | // ä¸è°ç¨æ¥å£ï¼åªæ¾ç¤ºæåæç¤º |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | const { queryParams, form, rules } = toRefs(data); |
| | | |
| | | /** æ¥è¯¢ä¸´æéåå°è´¦å表 */ |
| | | function getList() { |
| | | loading.value = true; |
| | | // ä¸è°ç¨æ¥å£ï¼è¿åç©ºæ°æ® |
| | | nearExpiryReturnList.value = []; |
| | | total.value = 0; |
| | | loading.value = false; |
| | | } |
| | | |
| | | // åæ¶æé® |
| | | function cancel() { |
| | | open.value = false; |
| | | reset(); |
| | | } |
| | | |
| | | // 表åéç½® |
| | | function reset() { |
| | | form.value = { |
| | | id: null, |
| | | productName: null, |
| | | productSpec: null, |
| | | batchNumber: null, |
| | | productionDate: null, |
| | | expiryDate: null, |
| | | returnQuantity: null, |
| | | returnReason: null, |
| | | returnDate: null, |
| | | status: null, |
| | | remark: null, |
| | | }; |
| | | proxy.resetForm("formRef"); |
| | | } |
| | | |
| | | /** æç´¢æé®æä½ */ |
| | | function handleQuery() { |
| | | queryParams.value.pageNum = 1; |
| | | getList(); |
| | | }).catch(() => {}); |
| | | } |
| | | } |
| | | |
| | | /** å¯¼åºæé®æä½ */ |
| | | function handleExport() { |
| | | // ä¸è°ç¨æ¥å£ï¼åªæ¾ç¤ºæç¤º |
| | | proxy.$modal.msgSuccess("导åºåè½ææªå®ç°"); |
| | | } |
| | | /** éç½®æé®æä½ */ |
| | | function resetQuery() { |
| | | proxy.resetForm("queryForm"); |
| | | handleQuery(); |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | // å¤éæ¡é䏿°æ® |
| | | function handleSelectionChange(selection) { |
| | | ids.value = selection.map(item => item.id); |
| | | single.value = selection.length !== 1; |
| | | multiple.value = !selection.length; |
| | | } |
| | | |
| | | /** æ°å¢æé®æä½ */ |
| | | function handleAdd() { |
| | | reset(); |
| | | open.value = true; |
| | | title.value = "æ·»å 临æéåå°è´¦"; |
| | | } |
| | | |
| | | /** ä¿®æ¹æé®æä½ */ |
| | | function handleUpdate(row) { |
| | | reset(); |
| | | // ä¸è°ç¨æ¥å£ï¼ç´æ¥ä½¿ç¨ä¼ å
¥çæ°æ® |
| | | if (row) { |
| | | form.value = { ...row }; |
| | | open.value = true; |
| | | title.value = "ä¿®æ¹ä¸´æéåå°è´¦"; |
| | | } |
| | | } |
| | | |
| | | /** æäº¤æé® */ |
| | | function submitForm() { |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | if (valid) { |
| | | // ä¸è°ç¨æ¥å£ï¼åªæ¾ç¤ºæåæç¤º |
| | | if (form.value.id != null) { |
| | | proxy.$modal.msgSuccess("ä¿®æ¹æå"); |
| | | } else { |
| | | proxy.$modal.msgSuccess("æ°å¢æå"); |
| | | } |
| | | open.value = false; |
| | | getList(); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | /** å é¤æé®æä½ */ |
| | | function handleDelete(row) { |
| | | const deleteIds = row.id || ids.value; |
| | | ElMessageBox.confirm( |
| | | 'æ¯å¦ç¡®è®¤å é¤ä¸´æéåå°è´¦ç¼å·ä¸º"' + deleteIds + '"çæ°æ®é¡¹ï¼', |
| | | "è¦å", |
| | | { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | } |
| | | ) |
| | | .then(function () { |
| | | // ä¸è°ç¨æ¥å£ï¼åªæ¾ç¤ºæåæç¤º |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }) |
| | | .catch(() => {}); |
| | | } |
| | | |
| | | /** å¯¼åºæé®æä½ */ |
| | | function handleExport() { |
| | | // ä¸è°ç¨æ¥å£ï¼åªæ¾ç¤ºæç¤º |
| | | proxy.$modal.msgSuccess("导åºåè½ææªå®ç°"); |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | |
| | | <div class="search_form mb20"> |
| | | <div> |
| | | <span class="search_title">å·¥åºï¼</span> |
| | | <el-input |
| | | v-model="searchForm.process" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥å·¥åºæç´¢" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | /> |
| | | <span style="margin-left: 10px" class="search_title">æ£æµæ¥æï¼</span> |
| | | <el-date-picker v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange" |
| | | placeholder="è¯·éæ©" clearable @change="changeDaterange" /> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px" |
| | | >æç´¢</el-button |
| | | > |
| | | <el-input v-model="searchForm.process" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥å·¥åºæç´¢" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" /> |
| | | <span style="margin-left: 10px" |
| | | class="search_title">æ£æµæ¥æï¼</span> |
| | | <el-date-picker v-model="searchForm.entryDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="daterange" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | @change="changeDaterange" /> |
| | | <span style="margin-left: 10px" |
| | | class="search_title">ç产工åå·ï¼</span> |
| | | <el-input v-model="searchForm.workOrderNo" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥ç产工åå·æç´¢" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" /> |
| | | <el-button type="primary" |
| | | @click="handleQuery" |
| | | style="margin-left: 10px">æç´¢</el-button> |
| | | </div> |
| | | <div> |
| | | <el-button type="primary" @click="openForm('add')">æ°å¢</el-button> |
| | | <el-button type="primary" |
| | | @click="openForm('add')">æ°å¢</el-button> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | <el-button type="danger" plain @click="handleDelete">å é¤</el-button> |
| | | <el-button type="danger" |
| | | plain |
| | | @click="handleDelete">å é¤</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | :total="page.total" |
| | | ></PIMTable> |
| | | <PIMTable rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | :total="page.total"></PIMTable> |
| | | </div> |
| | | <InspectionFormDia ref="inspectionFormDia" @close="handleQuery"></InspectionFormDia> |
| | | <FormDia ref="formDia" @close="handleQuery"></FormDia> |
| | | <files-dia ref="filesDia" @close="handleQuery"></files-dia> |
| | | <el-dialog v-model="dialogFormVisible" title="ç¼è¾æ£éªå" width="30%" |
| | | @close="closeDia"> |
| | | <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef"> |
| | | <el-form-item label="æ£éªåï¼" prop="checkName"> |
| | | <el-select v-model="form.checkName" placeholder="è¯·éæ©" clearable> |
| | | <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName" |
| | | :value="item.nickName"/> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm">确认</el-button> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | <InspectionFormDia ref="inspectionFormDia" |
| | | @close="handleQuery"></InspectionFormDia> |
| | | <FormDia ref="formDia" |
| | | @close="handleQuery"></FormDia> |
| | | <files-dia ref="filesDia" |
| | | @close="handleQuery"></files-dia> |
| | | <el-dialog v-model="dialogFormVisible" |
| | | title="ç¼è¾æ£éªå" |
| | | width="30%" |
| | | @close="closeDia"> |
| | | <el-form :model="form" |
| | | label-width="140px" |
| | | label-position="top" |
| | | :rules="rules" |
| | | ref="formRef"> |
| | | <el-form-item label="æ£éªåï¼" |
| | | prop="checkName"> |
| | | <el-select v-model="form.checkName" |
| | | placeholder="è¯·éæ©" |
| | | clearable> |
| | | <el-option v-for="item in userList" |
| | | :key="item.nickName" |
| | | :label="item.nickName" |
| | | :value="item.nickName" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="submitForm">确认</el-button> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import {onMounted, ref, reactive, toRefs, getCurrentInstance, nextTick} from "vue"; |
| | | import InspectionFormDia from "@/views/qualityManagement/processInspection/components/inspectionFormDia.vue"; |
| | | import FormDia from "@/views/qualityManagement/processInspection/components/formDia.vue"; |
| | | import {ElMessageBox} from "element-plus"; |
| | | import { |
| | | downloadQualityInspect, |
| | | qualityInspectDel, |
| | | qualityInspectListPage, qualityInspectUpdate, |
| | | submitQualityInspect |
| | | } from "@/api/qualityManagement/rawMaterialInspection.js"; |
| | | import FilesDia from "@/views/qualityManagement/processInspection/components/filesDia.vue"; |
| | | import dayjs from "dayjs"; |
| | | import {userListNoPage} from "@/api/system/user.js"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import { |
| | | onMounted, |
| | | ref, |
| | | reactive, |
| | | toRefs, |
| | | getCurrentInstance, |
| | | nextTick, |
| | | } from "vue"; |
| | | import InspectionFormDia from "@/views/qualityManagement/processInspection/components/inspectionFormDia.vue"; |
| | | import FormDia from "@/views/qualityManagement/processInspection/components/formDia.vue"; |
| | | import { ElMessageBox } from "element-plus"; |
| | | import { |
| | | downloadQualityInspect, |
| | | qualityInspectDel, |
| | | qualityInspectListPage, |
| | | qualityInspectUpdate, |
| | | submitQualityInspect, |
| | | } from "@/api/qualityManagement/rawMaterialInspection.js"; |
| | | import FilesDia from "@/views/qualityManagement/processInspection/components/filesDia.vue"; |
| | | import dayjs from "dayjs"; |
| | | import { userListNoPage } from "@/api/system/user.js"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | process: "", |
| | | entryDate: undefined, // å½å
¥æ¥æ |
| | | entryDateStart: undefined, |
| | | entryDateEnd: undefined, |
| | | }, |
| | | rules: { |
| | | checkName: [{required: true, message: "è¯·éæ©", trigger: "change"}], |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "æ£æµæ¥æ", |
| | | prop: "checkTime", |
| | | width: 120 |
| | | }, |
| | | { |
| | | label: "ç产工åå·", |
| | | prop: "workOrderNo", |
| | | width: 120 |
| | | }, |
| | | { |
| | | label: "å·¥åº", |
| | | prop: "process", |
| | | width: 230 |
| | | }, |
| | | { |
| | | label: "æ£éªå", |
| | | prop: "checkName", |
| | | }, |
| | | { |
| | | label: "产ååç§°", |
| | | prop: "productName", |
| | | }, |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | prop: "model", |
| | | }, |
| | | { |
| | | label: "åä½", |
| | | prop: "unit", |
| | | }, |
| | | { |
| | | label: "æ»æ°é", |
| | | prop: "quantity", |
| | | width: 100 |
| | | }, |
| | | { |
| | | label: "åæ ¼æ°é", |
| | | prop: "qualifiedQuantity", |
| | | width: 100 |
| | | }, |
| | | { |
| | | label: "ä¸åæ ¼æ°é", |
| | | prop: "unqualifiedQuantity", |
| | | width: 100 |
| | | }, |
| | | { |
| | | label: "æ£æµåä½", |
| | | prop: "checkCompany", |
| | | width: 120 |
| | | }, |
| | | { |
| | | label: "æ£æµç»æ", |
| | | prop: "checkResult", |
| | | dataType: "tag", |
| | | formatType: (params) => { |
| | | if (params == 'ä¸åæ ¼') { |
| | | return "danger"; |
| | | } else if (params == 'åæ ¼') { |
| | | return "success"; |
| | | } else { |
| | | return 'danger'; |
| | | } |
| | | const data = reactive({ |
| | | searchForm: { |
| | | process: "", |
| | | entryDate: undefined, // å½å
¥æ¥æ |
| | | workOrderNo: "", |
| | | entryDateStart: undefined, |
| | | entryDateEnd: undefined, |
| | | }, |
| | | }, |
| | | { |
| | | label: "æäº¤ç¶æ", |
| | | prop: "inspectState", |
| | | formatData: (params) => { |
| | | if (params) { |
| | | return "å·²æäº¤"; |
| | | } else { |
| | | return "æªæäº¤"; |
| | | } |
| | | }, |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 280, |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openForm("edit", row); |
| | | }, |
| | | disabled: (row) => { |
| | | // å·²æäº¤åç¦ç¨ |
| | | if (row.inspectState == 1) return true; |
| | | // 妿æ£éªåæå¼ï¼åªæå½åç»å½ç¨æ·è½ç¼è¾ |
| | | if (row.checkName) { |
| | | return row.checkName !== userStore.nickName; |
| | | } |
| | | return false; |
| | | } |
| | | rules: { |
| | | checkName: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "æ£æµæ¥æ", |
| | | prop: "checkTime", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "ç产工åå·", |
| | | prop: "workOrderNo", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "å·¥åº", |
| | | prop: "process", |
| | | width: 230, |
| | | }, |
| | | { |
| | | label: "æ£éªå", |
| | | prop: "checkName", |
| | | }, |
| | | { |
| | | label: "产ååç§°", |
| | | prop: "productName", |
| | | }, |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | prop: "model", |
| | | }, |
| | | { |
| | | label: "åä½", |
| | | prop: "unit", |
| | | }, |
| | | { |
| | | label: "æ»æ°é", |
| | | prop: "quantity", |
| | | width: 100, |
| | | }, |
| | | { |
| | | label: "åæ ¼æ°é", |
| | | prop: "qualifiedQuantity", |
| | | width: 100, |
| | | }, |
| | | { |
| | | label: "ä¸åæ ¼æ°é", |
| | | prop: "unqualifiedQuantity", |
| | | width: 100, |
| | | }, |
| | | { |
| | | label: "åæ ¼ç", |
| | | prop: "passRate", |
| | | width: 100, |
| | | dataType: "tag", |
| | | formatType: params => { |
| | | if (!params) return ""; |
| | | const rate = parseFloat(params); |
| | | if (rate < 90) { |
| | | return "danger"; |
| | | } else if (rate === 100) { |
| | | return "success"; |
| | | } else { |
| | | return "warning"; |
| | | } |
| | | }, |
| | | { |
| | | name: "æ¥ç", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openForm("view", row); |
| | | }, |
| | | }, |
| | | { |
| | | label: "æ£æµåä½", |
| | | prop: "checkCompany", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "æ£æµç»æ", |
| | | prop: "checkResult", |
| | | dataType: "tag", |
| | | formatType: params => { |
| | | if (params == "ä¸åæ ¼") { |
| | | return "danger"; |
| | | } else if (params == "åæ ¼") { |
| | | return "success"; |
| | | } else { |
| | | return "danger"; |
| | | } |
| | | }, |
| | | { |
| | | name: "éä»¶", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openFilesFormDia(row); |
| | | }, |
| | | }, |
| | | { |
| | | label: "æäº¤ç¶æ", |
| | | prop: "inspectState", |
| | | formatData: params => { |
| | | if (params) { |
| | | return "å·²æäº¤"; |
| | | } else { |
| | | return "æªæäº¤"; |
| | | } |
| | | }, |
| | | { |
| | | name: "æäº¤", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | submit(row.id); |
| | | }, |
| | | disabled: (row) => { |
| | | // å·²æäº¤åç¦ç¨ |
| | | if (row.inspectState == 1) return true; |
| | | // 妿æ£éªåæå¼ï¼åªæå½åç»å½ç¨æ·è½æäº¤ |
| | | if (row.checkName) { |
| | | return row.checkName !== userStore.nickName; |
| | | } |
| | | return false; |
| | | } |
| | | }, |
| | | { |
| | | name: "åé
æ£éªå", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | if (!row.checkName) { |
| | | open(row) |
| | | } else { |
| | | proxy.$modal.msgError("æ£éªåå·²åå¨"); |
| | | } |
| | | }, |
| | | disabled: (row) => { |
| | | return row.inspectState == 1 || row.checkName; |
| | | } |
| | | }, |
| | | { |
| | | name: "ä¸è½½", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | downLoadFile(row); |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | | const userList = ref([]); |
| | | const currentRow = ref(null) |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const tableLoading = ref(false); |
| | | const dialogFormVisible = ref(false); |
| | | const form = ref({ |
| | | checkName: "" |
| | | }); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0 |
| | | }); |
| | | const formDia = ref() |
| | | const filesDia = ref() |
| | | const inspectionFormDia = ref() |
| | | const { proxy } = getCurrentInstance() |
| | | const userStore = useUserStore() |
| | | const changeDaterange = (value) => { |
| | | searchForm.value.entryDateStart = undefined; |
| | | searchForm.value.entryDateEnd = undefined; |
| | | if (value) { |
| | | searchForm.value.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD"); |
| | | searchForm.value.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD"); |
| | | } |
| | | getList(); |
| | | }; |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const pagination = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | const params = { ...searchForm.value, ...page }; |
| | | params.entryDate = undefined |
| | | qualityInspectListPage({...params, inspectType: 1}).then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records |
| | | page.total = res.data.total; |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | | }) |
| | | }; |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 280, |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: row => { |
| | | openForm("edit", row); |
| | | }, |
| | | disabled: row => { |
| | | // å·²æäº¤åç¦ç¨ |
| | | if (row.inspectState == 1) return true; |
| | | // 妿æ£éªåæå¼ï¼åªæå½åç»å½ç¨æ·è½ç¼è¾ |
| | | if (row.checkName) { |
| | | return row.checkName !== userStore.nickName; |
| | | } |
| | | return false; |
| | | }, |
| | | }, |
| | | { |
| | | name: "æ¥ç", |
| | | type: "text", |
| | | clickFun: row => { |
| | | openForm("view", row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "éä»¶", |
| | | type: "text", |
| | | clickFun: row => { |
| | | openFilesFormDia(row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "æäº¤", |
| | | type: "text", |
| | | clickFun: row => { |
| | | submit(row.id); |
| | | }, |
| | | disabled: row => { |
| | | // å·²æäº¤åç¦ç¨ |
| | | if (row.inspectState == 1) return true; |
| | | // 妿æ£éªåæå¼ï¼åªæå½åç»å½ç¨æ·è½æäº¤ |
| | | if (row.checkName) { |
| | | return row.checkName !== userStore.nickName; |
| | | } |
| | | return false; |
| | | }, |
| | | }, |
| | | { |
| | | name: "åé
æ£éªå", |
| | | type: "text", |
| | | clickFun: row => { |
| | | if (!row.checkName) { |
| | | open(row); |
| | | } else { |
| | | proxy.$modal.msgError("æ£éªåå·²åå¨"); |
| | | } |
| | | }, |
| | | disabled: row => { |
| | | return row.inspectState == 1 || row.checkName; |
| | | }, |
| | | }, |
| | | { |
| | | name: "ä¸è½½", |
| | | type: "text", |
| | | clickFun: row => { |
| | | downLoadFile(row); |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | | const userList = ref([]); |
| | | const currentRow = ref(null); |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const tableLoading = ref(false); |
| | | const dialogFormVisible = ref(false); |
| | | const form = ref({ |
| | | checkName: "", |
| | | }); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | const formDia = ref(); |
| | | const filesDia = ref(); |
| | | const inspectionFormDia = ref(); |
| | | const { proxy } = getCurrentInstance(); |
| | | const userStore = useUserStore(); |
| | | const changeDaterange = value => { |
| | | searchForm.value.entryDateStart = undefined; |
| | | searchForm.value.entryDateEnd = undefined; |
| | | if (value) { |
| | | searchForm.value.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD"); |
| | | searchForm.value.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD"); |
| | | } |
| | | getList(); |
| | | }; |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const pagination = obj => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | const params = { ...searchForm.value, ...page }; |
| | | params.entryDate = undefined; |
| | | qualityInspectListPage({ ...params, inspectType: 1 }) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records.map(item => { |
| | | const quantity = parseFloat(item.quantity); |
| | | const qualifiedQuantity = parseFloat(item.qualifiedQuantity); |
| | | let passRate = null; |
| | | if (!isNaN(quantity) && !isNaN(qualifiedQuantity) && quantity > 0) { |
| | | passRate = ((qualifiedQuantity / quantity) * 100).toFixed(2) + "%"; |
| | | } |
| | | return { |
| | | ...item, |
| | | passRate: passRate, |
| | | }; |
| | | }); |
| | | page.total = res.data.total; |
| | | }) |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = selection => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openForm = (type, row) => { |
| | | nextTick(() => { |
| | | formDia.value?.openDialog(type, row) |
| | | }) |
| | | }; |
| | | // æå¼æ°å¢æ£éªå¼¹æ¡ |
| | | const openInspectionForm = (type, row) => { |
| | | nextTick(() => { |
| | | inspectionFormDia.value?.openDialog(type, row) |
| | | }) |
| | | }; |
| | | // æå¼éä»¶å¼¹æ¡ |
| | | const openFilesFormDia = (type, row) => { |
| | | nextTick(() => { |
| | | filesDia.value?.openDialog(type, row) |
| | | }) |
| | | }; |
| | | // æä»· |
| | | const submit = async (id) => { |
| | | const res = await submitQualityInspect({id: id}) |
| | | if (res.code === 200) { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | getList(); |
| | | } |
| | | } |
| | | const open = async (row) => { |
| | | let userLists = await userListNoPage(); |
| | | userList.value = userLists.data; |
| | | currentRow.value = row |
| | | dialogFormVisible.value = true |
| | | } |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | dialogFormVisible.value = false; |
| | | }; |
| | | const submitForm = () => { |
| | | if (currentRow.value) { |
| | | const data = { |
| | | ...form.value, |
| | | id: currentRow.value.id |
| | | } |
| | | qualityInspectUpdate(data).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | getList(); |
| | | }) |
| | | } |
| | | }; |
| | | // æå¼å¼¹æ¡ |
| | | const openForm = (type, row) => { |
| | | nextTick(() => { |
| | | formDia.value?.openDialog(type, row); |
| | | }); |
| | | }; |
| | | // æå¼æ°å¢æ£éªå¼¹æ¡ |
| | | const openInspectionForm = (type, row) => { |
| | | nextTick(() => { |
| | | inspectionFormDia.value?.openDialog(type, row); |
| | | }); |
| | | }; |
| | | // æå¼éä»¶å¼¹æ¡ |
| | | const openFilesFormDia = (type, row) => { |
| | | nextTick(() => { |
| | | filesDia.value?.openDialog(type, row); |
| | | }); |
| | | }; |
| | | // æä»· |
| | | const submit = async id => { |
| | | const res = await submitQualityInspect({ id: id }); |
| | | if (res.code === 200) { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | getList(); |
| | | } |
| | | }; |
| | | const open = async row => { |
| | | let userLists = await userListNoPage(); |
| | | userList.value = userLists.data; |
| | | currentRow.value = row; |
| | | dialogFormVisible.value = true; |
| | | }; |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | dialogFormVisible.value = false; |
| | | }; |
| | | const submitForm = () => { |
| | | if (currentRow.value) { |
| | | const data = { |
| | | ...form.value, |
| | | id: currentRow.value.id, |
| | | }; |
| | | qualityInspectUpdate(data).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | getList(); |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | // å é¤ |
| | | 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", |
| | | }) |
| | | // å é¤ |
| | | 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(() => { |
| | | qualityInspectDel(ids).then((res) => { |
| | | qualityInspectDel(ids).then(res => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }); |
| | |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | const downLoadFile = (row) => { |
| | | downloadQualityInspect({ id: row.id }).then((blobData) => { |
| | | const blob = new Blob([blobData], { |
| | | type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', |
| | | }) |
| | | const downloadUrl = window.URL.createObjectURL(blob) |
| | | }; |
| | | const downLoadFile = row => { |
| | | downloadQualityInspect({ id: row.id }).then(blobData => { |
| | | const blob = new Blob([blobData], { |
| | | type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", |
| | | }); |
| | | const downloadUrl = window.URL.createObjectURL(blob); |
| | | |
| | | const link = document.createElement('a') |
| | | link.href = downloadUrl |
| | | link.download = 'è¿ç¨æ£éªæ¥å.docx' |
| | | document.body.appendChild(link) |
| | | link.click() |
| | | const link = document.createElement("a"); |
| | | link.href = downloadUrl; |
| | | link.download = "è¿ç¨æ£éªæ¥å.docx"; |
| | | document.body.appendChild(link); |
| | | link.click(); |
| | | |
| | | document.body.removeChild(link) |
| | | window.URL.revokeObjectURL(downloadUrl) |
| | | }) |
| | | }; |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | document.body.removeChild(link); |
| | | window.URL.revokeObjectURL(downloadUrl); |
| | | }); |
| | | }; |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/quality/qualityInspect/export", {inspectType: 1}, "è¿ç¨æ£éª.xlsx"); |
| | | proxy.download( |
| | | "/quality/qualityInspect/export", |
| | | { inspectType: 1 }, |
| | | "è¿ç¨æ£éª.xlsx" |
| | | ); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | }; |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped></style> |
| | |
| | | <div class="search_form mb20"> |
| | | <div> |
| | | <span class="search_title">ä¾åºåï¼</span> |
| | | <el-input |
| | | v-model="searchForm.supplier" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥ä¾åºåæç´¢" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | /> |
| | | <span style="margin-left: 10px" class="search_title">æ£æµæ¥æï¼</span> |
| | | <el-date-picker v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange" |
| | | placeholder="è¯·éæ©" clearable @change="changeDaterange"/> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px" |
| | | >æç´¢ |
| | | </el-button |
| | | > |
| | | <el-input v-model="searchForm.supplier" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥ä¾åºåæç´¢" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" /> |
| | | <span style="margin-left: 10px" |
| | | class="search_title">æ£æµæ¥æï¼</span> |
| | | <el-date-picker v-model="searchForm.entryDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="daterange" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | @change="changeDaterange" /> |
| | | <span style="margin-left: 10px" |
| | | class="search_title">éè´è®¢åå·ï¼</span> |
| | | <el-input v-model="searchForm.purchaseContractNo" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥éè´è®¢åå·æç´¢" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" /> |
| | | <el-button type="primary" |
| | | @click="handleQuery" |
| | | style="margin-left: 10px">æç´¢ |
| | | </el-button> |
| | | </div> |
| | | <div> |
| | | <el-button type="primary" @click="openForm('add')">æ°å¢</el-button> |
| | | <el-button type="primary" |
| | | @click="openForm('add')">æ°å¢</el-button> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | <el-button type="danger" plain @click="handleDelete">å é¤</el-button> |
| | | <el-button type="danger" |
| | | plain |
| | | @click="handleDelete">å é¤</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | :total="page.total" |
| | | ></PIMTable> |
| | | <PIMTable rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | :total="page.total"></PIMTable> |
| | | </div> |
| | | <InspectionFormDia ref="inspectionFormDia" @close="handleQuery"></InspectionFormDia> |
| | | <FormDia ref="formDia" @close="handleQuery"></FormDia> |
| | | <files-dia ref="filesDia" @close="handleQuery"></files-dia> |
| | | <el-dialog v-model="dialogFormVisible" title="ç¼è¾æ£éªå" width="30%" |
| | | <InspectionFormDia ref="inspectionFormDia" |
| | | @close="handleQuery"></InspectionFormDia> |
| | | <FormDia ref="formDia" |
| | | @close="handleQuery"></FormDia> |
| | | <files-dia ref="filesDia" |
| | | @close="handleQuery"></files-dia> |
| | | <el-dialog v-model="dialogFormVisible" |
| | | title="ç¼è¾æ£éªå" |
| | | width="30%" |
| | | @close="closeDia"> |
| | | <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef"> |
| | | <el-form-item label="æ£éªåï¼" prop="checkName"> |
| | | <el-select v-model="form.checkName" placeholder="è¯·éæ©" clearable> |
| | | <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName" |
| | | :value="item.nickName"/> |
| | | <el-form :model="form" |
| | | label-width="140px" |
| | | label-position="top" |
| | | :rules="rules" |
| | | ref="formRef"> |
| | | <el-form-item label="æ£éªåï¼" |
| | | prop="checkName"> |
| | | <el-select v-model="form.checkName" |
| | | placeholder="è¯·éæ©" |
| | | clearable> |
| | | <el-option v-for="item in userList" |
| | | :key="item.nickName" |
| | | :label="item.nickName" |
| | | :value="item.nickName" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm">确认</el-button> |
| | | <el-button type="primary" |
| | | @click="submitForm">确认</el-button> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {Search} from "@element-plus/icons-vue"; |
| | | import {onMounted, ref, reactive, toRefs, getCurrentInstance, nextTick} from "vue"; |
| | | import InspectionFormDia from "@/views/qualityManagement/rawMaterialInspection/components/inspectionFormDia.vue"; |
| | | import FormDia from "@/views/qualityManagement/rawMaterialInspection/components/formDia.vue"; |
| | | import {ElMessageBox} from "element-plus"; |
| | | import { |
| | | downloadQualityInspect, |
| | | qualityInspectDel, |
| | | qualityInspectListPage, qualityInspectUpdate, |
| | | submitQualityInspect |
| | | } from "@/api/qualityManagement/rawMaterialInspection.js"; |
| | | import FilesDia from "@/views/qualityManagement/rawMaterialInspection/components/filesDia.vue"; |
| | | import dayjs from "dayjs"; |
| | | import {userListNoPage} from "@/api/system/user.js"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import { |
| | | onMounted, |
| | | ref, |
| | | reactive, |
| | | toRefs, |
| | | getCurrentInstance, |
| | | nextTick, |
| | | } from "vue"; |
| | | import InspectionFormDia from "@/views/qualityManagement/rawMaterialInspection/components/inspectionFormDia.vue"; |
| | | import FormDia from "@/views/qualityManagement/rawMaterialInspection/components/formDia.vue"; |
| | | import { ElMessageBox } from "element-plus"; |
| | | import { |
| | | downloadQualityInspect, |
| | | qualityInspectDel, |
| | | qualityInspectListPage, |
| | | qualityInspectUpdate, |
| | | submitQualityInspect, |
| | | } from "@/api/qualityManagement/rawMaterialInspection.js"; |
| | | import FilesDia from "@/views/qualityManagement/rawMaterialInspection/components/filesDia.vue"; |
| | | import dayjs from "dayjs"; |
| | | import { userListNoPage } from "@/api/system/user.js"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | supplier: "", |
| | | entryDate: undefined, // å½å
¥æ¥æ |
| | | entryDateStart: undefined, |
| | | entryDateEnd: undefined, |
| | | }, |
| | | rules: { |
| | | checkName: [{required: true, message: "è¯·éæ©", trigger: "change"}], |
| | | }, |
| | | }); |
| | | const {searchForm, rules} = toRefs(data); |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "æ£æµæ¥æ", |
| | | prop: "checkTime", |
| | | width: 120 |
| | | }, |
| | | { |
| | | label: "éè´è®¢åå·", |
| | | prop: "purchaseContractNo", |
| | | width: 120 |
| | | }, |
| | | { |
| | | label: "ä¾åºå", |
| | | prop: "supplier", |
| | | width: 230 |
| | | }, |
| | | { |
| | | label: "æ£éªå", |
| | | prop: "checkName", |
| | | }, |
| | | { |
| | | label: "产ååç§°", |
| | | prop: "productName", |
| | | }, |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | prop: "model", |
| | | }, |
| | | { |
| | | label: "åä½", |
| | | prop: "unit", |
| | | }, |
| | | { |
| | | label: "æ»æ°é", |
| | | prop: "quantity", |
| | | width: 100 |
| | | }, |
| | | { |
| | | label: "åæ ¼æ°é", |
| | | prop: "qualifiedQuantity", |
| | | width: 100 |
| | | }, |
| | | { |
| | | label: "ä¸åæ ¼æ°é", |
| | | prop: "unqualifiedQuantity", |
| | | width: 100 |
| | | }, |
| | | { |
| | | label: "æ£æµåä½", |
| | | prop: "checkCompany", |
| | | width: 120 |
| | | }, |
| | | { |
| | | label: "æ£æµåä½", |
| | | prop: "checkCompany", |
| | | width: 120 |
| | | }, |
| | | { |
| | | label: "æ£æµç»æ", |
| | | prop: "checkResult", |
| | | dataType: "tag", |
| | | formatType: (params) => { |
| | | if (params === 'ä¸åæ ¼') { |
| | | return "danger"; |
| | | } else if (params === 'åæ ¼') { |
| | | return "success"; |
| | | } else { |
| | | return 'danger'; |
| | | } |
| | | const data = reactive({ |
| | | searchForm: { |
| | | supplier: "", |
| | | entryDate: undefined, // å½å
¥æ¥æ |
| | | purchaseContractNo: "", |
| | | entryDateStart: undefined, |
| | | entryDateEnd: undefined, |
| | | }, |
| | | }, |
| | | { |
| | | label: "æäº¤ç¶æ", |
| | | prop: "inspectState", |
| | | formatData: (params) => { |
| | | if (params) { |
| | | return "å·²æäº¤"; |
| | | } else { |
| | | return "æªæäº¤"; |
| | | } |
| | | rules: { |
| | | checkName: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | }, |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 280, |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openForm("edit", row); |
| | | }, |
| | | disabled: (row) => { |
| | | // å·²æäº¤åç¦ç¨ |
| | | if (row.inspectState == 1) return true; |
| | | // 妿æ£éªåæå¼ï¼åªæå½åç»å½ç¨æ·è½ç¼è¾ |
| | | if (row.checkName) { |
| | | return row.checkName !== userStore.nickName; |
| | | } |
| | | return false; |
| | | } |
| | | }); |
| | | const { searchForm, rules } = toRefs(data); |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "æ£æµæ¥æ", |
| | | prop: "checkTime", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "éè´è®¢åå·", |
| | | prop: "purchaseContractNo", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "ä¾åºå", |
| | | prop: "supplier", |
| | | width: 230, |
| | | }, |
| | | { |
| | | label: "æ£éªå", |
| | | prop: "checkName", |
| | | }, |
| | | { |
| | | label: "产ååç§°", |
| | | prop: "productName", |
| | | }, |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | prop: "model", |
| | | }, |
| | | { |
| | | label: "åä½", |
| | | prop: "unit", |
| | | }, |
| | | { |
| | | label: "æ»æ°é", |
| | | prop: "quantity", |
| | | width: 100, |
| | | }, |
| | | { |
| | | label: "åæ ¼æ°é", |
| | | prop: "qualifiedQuantity", |
| | | width: 100, |
| | | }, |
| | | { |
| | | label: "ä¸åæ ¼æ°é", |
| | | prop: "unqualifiedQuantity", |
| | | width: 100, |
| | | }, |
| | | { |
| | | label: "åæ ¼ç", |
| | | prop: "passRate", |
| | | width: 100, |
| | | dataType: "tag", |
| | | formatType: params => { |
| | | if (!params) return ""; |
| | | const rate = parseFloat(params); |
| | | if (rate < 90) { |
| | | return "danger"; |
| | | } else if (rate === 100) { |
| | | return "success"; |
| | | } else { |
| | | return "warning"; |
| | | } |
| | | }, |
| | | { |
| | | name: "æ¥ç", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openForm("view", row); |
| | | }, |
| | | }, |
| | | { |
| | | label: "æ£æµåä½", |
| | | prop: "checkCompany", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "æ£æµåä½", |
| | | prop: "checkCompany", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "æ£æµç»æ", |
| | | prop: "checkResult", |
| | | dataType: "tag", |
| | | formatType: params => { |
| | | if (params === "ä¸åæ ¼") { |
| | | return "danger"; |
| | | } else if (params === "åæ ¼") { |
| | | return "success"; |
| | | } else { |
| | | return "danger"; |
| | | } |
| | | }, |
| | | { |
| | | name: "éä»¶", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openFilesFormDia(row); |
| | | }, |
| | | }, |
| | | { |
| | | label: "æäº¤ç¶æ", |
| | | prop: "inspectState", |
| | | formatData: params => { |
| | | if (params) { |
| | | return "å·²æäº¤"; |
| | | } else { |
| | | return "æªæäº¤"; |
| | | } |
| | | }, |
| | | { |
| | | name: "æäº¤", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | submit(row.id); |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 280, |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: row => { |
| | | openForm("edit", row); |
| | | }, |
| | | disabled: row => { |
| | | // å·²æäº¤åç¦ç¨ |
| | | if (row.inspectState == 1) return true; |
| | | // 妿æ£éªåæå¼ï¼åªæå½åç»å½ç¨æ·è½ç¼è¾ |
| | | if (row.checkName) { |
| | | return row.checkName !== userStore.nickName; |
| | | } |
| | | return false; |
| | | }, |
| | | }, |
| | | disabled: (row) => { |
| | | // å·²æäº¤åç¦ç¨ |
| | | if (row.inspectState == 1) return true; |
| | | // 妿æ£éªåæå¼ï¼åªæå½åç»å½ç¨æ·è½æäº¤ |
| | | if (row.checkName) { |
| | | return row.checkName !== userStore.nickName; |
| | | } |
| | | return false; |
| | | } |
| | | }, |
| | | { |
| | | name: "åé
æ£éªå", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | if (!row.checkName) { |
| | | open(row) |
| | | } else { |
| | | proxy.$modal.msgError("æ£éªåå·²åå¨"); |
| | | { |
| | | name: "æ¥ç", |
| | | type: "text", |
| | | clickFun: row => { |
| | | openForm("view", row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "éä»¶", |
| | | type: "text", |
| | | clickFun: row => { |
| | | openFilesFormDia(row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "æäº¤", |
| | | type: "text", |
| | | clickFun: row => { |
| | | submit(row.id); |
| | | }, |
| | | disabled: row => { |
| | | // å·²æäº¤åç¦ç¨ |
| | | if (row.inspectState == 1) return true; |
| | | // 妿æ£éªåæå¼ï¼åªæå½åç»å½ç¨æ·è½æäº¤ |
| | | if (row.checkName) { |
| | | return row.checkName !== userStore.nickName; |
| | | } |
| | | return false; |
| | | }, |
| | | }, |
| | | { |
| | | name: "åé
æ£éªå", |
| | | type: "text", |
| | | clickFun: row => { |
| | | if (!row.checkName) { |
| | | open(row); |
| | | } else { |
| | | proxy.$modal.msgError("æ£éªåå·²åå¨"); |
| | | } |
| | | }, |
| | | disabled: row => { |
| | | return row.inspectState == 1 || row.checkName; |
| | | }, |
| | | }, |
| | | { |
| | | name: "ä¸è½½", |
| | | type: "text", |
| | | clickFun: row => { |
| | | downLoadFile(row); |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const tableLoading = ref(false); |
| | | const userList = ref([]); |
| | | const dialogFormVisible = ref(false); |
| | | const form = ref({ |
| | | checkName: "", |
| | | }); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | const currentRow = ref(null); |
| | | const formDia = ref(); |
| | | const filesDia = ref(); |
| | | const inspectionFormDia = ref(); |
| | | const { proxy } = getCurrentInstance(); |
| | | const userStore = useUserStore(); |
| | | const changeDaterange = value => { |
| | | searchForm.value.entryDateStart = undefined; |
| | | searchForm.value.entryDateEnd = undefined; |
| | | if (value) { |
| | | searchForm.value.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD"); |
| | | searchForm.value.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD"); |
| | | } |
| | | getList(); |
| | | }; |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const pagination = obj => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | const params = { ...searchForm.value, ...page }; |
| | | params.entryDate = undefined; |
| | | qualityInspectListPage({ ...params, inspectType: 0 }) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records.map(item => { |
| | | const quantity = parseFloat(item.quantity); |
| | | const qualifiedQuantity = parseFloat(item.qualifiedQuantity); |
| | | let passRate = null; |
| | | if (!isNaN(quantity) && !isNaN(qualifiedQuantity) && quantity > 0) { |
| | | passRate = ((qualifiedQuantity / quantity) * 100).toFixed(2) + "%"; |
| | | } |
| | | }, |
| | | disabled: (row) => { |
| | | return row.inspectState == 1 || row.checkName; |
| | | } |
| | | }, |
| | | { |
| | | name: "ä¸è½½", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | downLoadFile(row); |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const tableLoading = ref(false); |
| | | const userList = ref([]); |
| | | const dialogFormVisible = ref(false); |
| | | const form = ref({ |
| | | checkName: "" |
| | | }); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0 |
| | | }); |
| | | const currentRow = ref(null) |
| | | const formDia = ref() |
| | | const filesDia = ref() |
| | | const inspectionFormDia = ref() |
| | | const {proxy} = getCurrentInstance() |
| | | const userStore = useUserStore() |
| | | const changeDaterange = (value) => { |
| | | searchForm.value.entryDateStart = undefined; |
| | | searchForm.value.entryDateEnd = undefined; |
| | | if (value) { |
| | | searchForm.value.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD"); |
| | | searchForm.value.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD"); |
| | | } |
| | | getList(); |
| | | }; |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const pagination = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | const params = {...searchForm.value, ...page}; |
| | | params.entryDate = undefined |
| | | qualityInspectListPage({...params, inspectType: 0}).then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records |
| | | page.total = res.data.total; |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | | }) |
| | | }; |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | return { |
| | | ...item, |
| | | passRate: passRate, |
| | | }; |
| | | }); |
| | | page.total = res.data.total; |
| | | }) |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = selection => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openForm = (type, row) => { |
| | | nextTick(() => { |
| | | formDia.value?.openDialog(type, row) |
| | | }) |
| | | }; |
| | | // æå¼éä»¶å¼¹æ¡ |
| | | const openFilesFormDia = (type, row) => { |
| | | nextTick(() => { |
| | | filesDia.value?.openDialog(type, row) |
| | | }) |
| | | }; |
| | | // æå¼å¼¹æ¡ |
| | | const openForm = (type, row) => { |
| | | nextTick(() => { |
| | | formDia.value?.openDialog(type, row); |
| | | }); |
| | | }; |
| | | // æå¼éä»¶å¼¹æ¡ |
| | | const openFilesFormDia = (type, row) => { |
| | | nextTick(() => { |
| | | filesDia.value?.openDialog(type, row); |
| | | }); |
| | | }; |
| | | |
| | | // å é¤ |
| | | 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", |
| | | }) |
| | | // å é¤ |
| | | 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(() => { |
| | | qualityInspectDel(ids).then((res) => { |
| | | qualityInspectDel(ids).then(res => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }); |
| | |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | }; |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/quality/qualityInspect/export", {inspectType: 0}, "åæææ£éª.xlsx"); |
| | | proxy.download( |
| | | "/quality/qualityInspect/export", |
| | | { inspectType: 0 }, |
| | | "åæææ£éª.xlsx" |
| | | ); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | }; |
| | | |
| | | // æä»· |
| | | const submit = async (id) => { |
| | | const res = await submitQualityInspect({id: id}) |
| | | if (res.code === 200) { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | getList(); |
| | | } |
| | | } |
| | | |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | dialogFormVisible.value = false; |
| | | }; |
| | | |
| | | const submitForm = () => { |
| | | if (currentRow.value) { |
| | | const data = { |
| | | ...form.value, |
| | | id: currentRow.value.id |
| | | } |
| | | qualityInspectUpdate(data).then(res => { |
| | | // æä»· |
| | | const submit = async id => { |
| | | const res = await submitQualityInspect({ id: id }); |
| | | if (res.code === 200) { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | getList(); |
| | | }) |
| | | } |
| | | }; |
| | | } |
| | | }; |
| | | |
| | | const open = async (row) => { |
| | | let userLists = await userListNoPage(); |
| | | userList.value = userLists.data; |
| | | currentRow.value = row |
| | | dialogFormVisible.value = true |
| | | } |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | dialogFormVisible.value = false; |
| | | }; |
| | | |
| | | const downLoadFile = (row) => { |
| | | downloadQualityInspect({ id: row.id }).then((blobData) => { |
| | | const blob = new Blob([blobData], { |
| | | type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', |
| | | }) |
| | | const downloadUrl = window.URL.createObjectURL(blob) |
| | | const submitForm = () => { |
| | | if (currentRow.value) { |
| | | const data = { |
| | | ...form.value, |
| | | id: currentRow.value.id, |
| | | }; |
| | | qualityInspectUpdate(data).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | getList(); |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | const link = document.createElement('a') |
| | | link.href = downloadUrl |
| | | link.download = 'åæææ£éªæ¥å.docx' |
| | | document.body.appendChild(link) |
| | | link.click() |
| | | const open = async row => { |
| | | let userLists = await userListNoPage(); |
| | | userList.value = userLists.data; |
| | | currentRow.value = row; |
| | | dialogFormVisible.value = true; |
| | | }; |
| | | |
| | | document.body.removeChild(link) |
| | | window.URL.revokeObjectURL(downloadUrl) |
| | | }) |
| | | }; |
| | | const downLoadFile = row => { |
| | | downloadQualityInspect({ id: row.id }).then(blobData => { |
| | | const blob = new Blob([blobData], { |
| | | type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", |
| | | }); |
| | | const downloadUrl = window.URL.createObjectURL(blob); |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | const link = document.createElement("a"); |
| | | link.href = downloadUrl; |
| | | link.download = "åæææ£éªæ¥å.docx"; |
| | | document.body.appendChild(link); |
| | | link.click(); |
| | | |
| | | document.body.removeChild(link); |
| | | window.URL.revokeObjectURL(downloadUrl); |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped></style> |
| | |
| | | <el-form-item label="鿣ç¼å·ï¼" |
| | | prop="hiddenCode"> |
| | | <el-input v-model="form.hiddenCode" |
| | | placeholder="èªå¨çæ" |
| | | placeholder="ä¿ååèªå¨çæ" |
| | | disabled |
| | | clearable /> |
| | | </el-form-item> |
| | |
| | | prop="courseCode"> |
| | | <el-input v-model="form.courseCode" |
| | | disabled |
| | | placeholder="èªå¨çæ" /> |
| | | placeholder="ä¿ååèªå¨çæ" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å建æ¶é´" |
| | | prop="createTime"> |
| | | <el-date-picker style="width: 100%" |
| | | v-model="formCreateTimeDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | trainingMode: "", // å¹è®æ¹å¼ |
| | | placeTraining: "", // å¹è®å°ç¹ |
| | | classHour: "", // è¯¾æ¶ |
| | | createTime: "", // å建æ¶é´ |
| | | }, |
| | | dialogVisible: false, |
| | | dialogTitle: "", |
| | | dialogType: "add", |
| | | viewDialogVisible: false, |
| | | currentKnowledge: {}, |
| | | }); |
| | | const formCreateTimeDate = computed({ |
| | | get: () => (form.value.createTime ? String(form.value.createTime).split(" ")[0] : ""), |
| | | set: (value) => { |
| | | form.value.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : ""; |
| | | }, |
| | | }); |
| | | |
| | | const { |
| | |
| | | trainingMode: "", // å¹è®æ¹å¼ |
| | | placeTraining: "", // å¹è®å°ç¹ |
| | | classHour: "", // è¯¾æ¶ |
| | | createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), // å建æ¶é´ |
| | | }); |
| | | } else if (type === "edit" && row) { |
| | | dialogTitle.value = "ç¼è¾å¹è®"; |
| | |
| | | trainingMode: row.trainingMode, // å¹è®æ¹å¼ |
| | | placeTraining: row.placeTraining, // å¹è®å°ç¹ |
| | | classHour: row.classHour, // è¯¾æ¶ |
| | | createTime: row.createTime || "", // å建æ¶é´ |
| | | }); |
| | | } |
| | | dialogVisible.value = true; |