src/api/basicData/enum.js
@@ -7,17 +7,35 @@ }) } export function findAllQualifiedStockRecordTypeOptions() { // åæ ¼å ¥åºæ¥æºç±»å export function findAllQualifiedStockInRecordTypeOptions() { return request({ url: '/basic/enum/StockQualifiedRecordTypeEnum', url: '/basic/enum/StockInQualifiedRecordTypeEnum', method: 'get' }) } export function findAllUnqualifiedStockRecordTypeOptions() { // ä¸åæ ¼å ¥åºæ¥æºç±»å export function findAllUnQualifiedStockInRecordTypeOptions() { return request({ url: '/basic/enum/StockUnQualifiedRecordTypeEnum', url: '/basic/enum/StockInUnQualifiedRecordTypeEnum', method: 'get' }) } // åæ ¼åºåºæ¥æºç±»å export function findAllQualifiedStockOutRecordTypeOptions() { return request({ url: '/basic/enum/StockOutQualifiedRecordTypeEnum', method: 'get' }) } // ä¸åæ ¼åºåºæ¥æºç±»å export function findAllUnQualifiedStockOutRecordTypeOptions() { return request({ url: '/basic/enum/StockOutUnQualifiedRecordTypeEnum', method: 'get' }) } src/api/productionManagement/productionOrder.js
@@ -36,6 +36,22 @@ }); } // ç产订å-æ°å¢ export function addProductOrder(data) { return request({ url: "/productOrder/addProductOrder", method: "post", data: data, }); } export function delProductOrder(ids) { return request({ url: `/productOrder/${ids}`, method: "delete", }); } // ç产订å-æ¥è¯¢äº§åç»æå表 export function listProcessBom(query) { return request({ src/api/viewIndex.js
@@ -1,6 +1,15 @@ // é¦é¡µæ¥å£ import request from "@/utils/request"; // å·¥åæ§è¡æçåæ export const workOrderEfficiencyAnalysis = (query) => { return request({ url: "/home/workOrderEfficiencyAnalysis", method: "get", params: query, }); }; // åæææ£æµ export const rawMaterialDetection = (query) => { return request({ src/views/basicData/product/index.vue
@@ -30,11 +30,8 @@ :props="{ children: 'children', label: 'label' }" highlight-current node-key="id" style=" height: calc(100vh - 190px); overflow-y: scroll; scrollbar-width: none; " class="product-tree-scroll" style="height: calc(100vh - 190px); overflow-y: auto" > <template #default="{ node, data }"> <div class="custom-tree-node"> @@ -43,7 +40,7 @@ <component :is="data.children && data.children.length > 0 ? node.expanded ? 'FolderOpened' : 'Folder' : 'Tickets'" /> </el-icon> {{ data.label }} <span class="tree-node-label">{{ data.label }}</span> </span> <div> <el-button @@ -111,6 +108,8 @@ <el-input v-model="form.productName" placeholder="请è¾å ¥äº§ååç§°" maxlength="20" show-word-limit clearable @keydown.enter.prevent /> @@ -239,7 +238,10 @@ productName: "", }, rules: { productName: [{ required: true, message: "请è¾å ¥", trigger: "blur" }], productName: [ { required: true, message: "请è¾å ¥", trigger: "blur" }, { max: 20, message: "产ååç§°ä¸è½è¶ è¿20个å符", trigger: "blur" }, ], }, modelForm: { model: "", @@ -467,18 +469,21 @@ display: flex; } .left { width: 380px; width: 450px; min-width: 450px; padding: 16px; background: #ffffff; } .right { width: calc(100% - 380px); flex: 1; min-width: 0; padding: 16px; margin-left: 20px; background: #ffffff; } .custom-tree-node { flex: 1; min-width: 0; display: flex; align-items: center; justify-content: space-between; @@ -486,13 +491,42 @@ padding-right: 8px; } .tree-node-content { flex: 1; min-width: 0; display: flex; align-items: center; /* åç´å± ä¸ */ align-items: center; height: 100%; overflow: hidden; } .tree-node-content .orange-icon { flex-shrink: 0; } .tree-node-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .orange-icon { color: orange; font-size: 18px; margin-right: 8px; /* 徿 䏿åä¹é´å ç¹é´è· */ } .product-tree-scroll { scrollbar-width: thin; scrollbar-color: #c0c4cc #f5f7fa; } .product-tree-scroll::-webkit-scrollbar { width: 8px; } .product-tree-scroll::-webkit-scrollbar-track { background: #f5f7fa; border-radius: 4px; } .product-tree-scroll::-webkit-scrollbar-thumb { background: #c0c4cc; border-radius: 4px; } .product-tree-scroll::-webkit-scrollbar-thumb:hover { background: #909399; } </style> src/views/collaborativeApproval/sealManagement/index.vue
@@ -95,55 +95,6 @@ </el-form> </FormDialog> <!-- è§ç« å¶åº¦åå¸å¯¹è¯æ¡ --> <!-- <el-dialog v-model="showRegulationDialog" :title="operationType === 'add' ? 'åå¸å¶åº¦' : 'ç¼è¾å¶åº¦'" width="800px"> <el-form :model="regulationForm" :rules="regulationRules" ref="regulationFormRef" label-width="100px"> <el-form-item label="å¶åº¦ç¼å·" prop="regulationNum"> <el-input v-model="regulationForm.regulationNum" placeholder="请è¾å ¥å¶åº¦ç¼å·" /> </el-form-item> <el-form-item label="å¶åº¦æ é¢" prop="title"> <el-input v-model="regulationForm.title" placeholder="请è¾å ¥å¶åº¦æ é¢" /> </el-form-item> <el-form-item label="å¶åº¦åç±»" prop="category"> <el-select v-model="regulationForm.category" placeholder="è¯·éæ©å¶åº¦åç±»" style="width: 100%"> <el-option label="人äºå¶åº¦" value="hr" /> <el-option label="è´¢å¡å¶åº¦" value="finance" /> <el-option label="å®å ¨å¶åº¦" value="safety" /> <el-option label="ææ¯å¶åº¦" value="tech" /> </el-select> </el-form-item> <el-form-item label="å¶åº¦å 容" prop="content"> <el-input v-model="regulationForm.content" type="textarea" :rows="10" placeholder="请è¾å ¥å¶åº¦è¯¦ç»å 容" /> </el-form-item> <el-form-item label="å¶åº¦çæ¬" prop="version"> <el-input v-model="regulationForm.version" placeholder="请è¾å ¥å¶åº¦çæ¬" /> </el-form-item> <el-form-item label="çææ¶é´" prop="effectiveTime"> <el-date-picker v-model="regulationForm.effectiveTime" type="datetime" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" placeholder="éæ©çææ¶é´" style="width: 100%" /> </el-form-item> <el-form-item label="éç¨èå´" prop="scope"> <el-checkbox-group v-model="regulationForm.scope"> <el-checkbox label="all">å ¨ä½åå·¥</el-checkbox> <el-checkbox label="manager">管çå±</el-checkbox> <el-checkbox label="hr">人äºé¨é¨</el-checkbox> <el-checkbox label="finance">è´¢å¡é¨é¨</el-checkbox> <el-checkbox label="tech">ææ¯é¨é¨</el-checkbox> </el-checkbox-group> </el-form-item> <el-form-item label="æ¯å¦éè¦ç¡®è®¤" prop="requireConfirm"> <el-switch v-model="regulationForm.requireConfirm" /> <span class="ml-10">å¼å¯ååå·¥éè¦é 读确认</span> </el-form-item> </el-form> <template #footer> <span class="dialog-footer"> <el-button @click="showRegulationDialog = false">åæ¶</el-button> <el-button type="primary" @click="submitRegulation">åå¸å¶åº¦</el-button> </span> </template> </el-dialog> --> <!-- ç¨å°è¯¦æ å¯¹è¯æ¡ --> <FormDialog v-model="showSealDetailDialog" @@ -171,81 +122,6 @@ </div> </FormDialog> <!-- è§ç« å¶åº¦è¯¦æ å¯¹è¯æ¡ --> <FormDialog v-model="showRegulationDetailDialog" title="è§ç« å¶åº¦è¯¦æ " :width="'800px'" @close="closeRegulationDetailDialog" @confirm="handleRegulationDetailConfirm" @cancel="closeRegulationDetailDialog" > <div v-if="currentRegulationDetail"> <el-descriptions :column="2" border> <el-descriptions-item label="å¶åº¦ç¼å·">{{ currentRegulationDetail.id }}</el-descriptions-item> <el-descriptions-item label="å¶åº¦æ é¢">{{ currentRegulationDetail.title }}</el-descriptions-item> <el-descriptions-item label="åç±»">{{ getCategoryText(currentRegulationDetail.category) }}</el-descriptions-item> <el-descriptions-item label="çæ¬">{{ currentRegulationDetail.version }}</el-descriptions-item> <el-descriptions-item label="åå¸äºº">{{ currentRegulationDetail.createUserName }}</el-descriptions-item> <el-descriptions-item label="å叿¶é´">{{ currentRegulationDetail.createTime }}</el-descriptions-item> </el-descriptions> <div class="mt-20"> <h4>å¶åº¦å 容</h4> <div class="regulation-content">{{ currentRegulationDetail.content }}</div> </div> <!-- 妿tableData>0 æ¾ç¤º --> <div style="margin: 10px 0;" v-if="tableData && tableData.length > 0" > <el-button type="success" @click="resetForm(currentRegulationDetail)">确认æ¥ç</el-button> </div> </div> </FormDialog> <!-- çæ¬åå²å¯¹è¯æ¡ --> <FormDialog v-model="showVersionHistoryDialog" title="çæ¬åå²" :width="'800px'" @close="closeVersionHistoryDialog" @confirm="closeVersionHistoryDialog" @cancel="closeVersionHistoryDialog" > <el-table :data="versionHistory" style="width: 100%;margin-bottom: 10px"> <el-table-column prop="version" label="çæ¬å·" width="100" /> <el-table-column prop="updateTime" label="æ´æ°æ¶é´" width="180" /> <el-table-column prop="createUserName" label="æ´æ°äºº" width="120" /> <el-table-column prop="changeLog" label="åæ´è¯´æ"> <template #default="scope"> <el-tag :type="scope.row.status === 'active' ? 'success' : 'info'"> {{ scope.row.status === 'active' ? 'çæä¸' : 'å·²åºæ¢' }} </el-tag> </template> </el-table-column> </el-table> </FormDialog> <!-- é è¯»ç¶æå¯¹è¯æ¡ --> <FormDialog v-model="showReadStatusDialog" title="é è¯»ç¶æ" :width="'800px'" @close="closeReadStatusDialog" @confirm="closeReadStatusDialog" @cancel="closeReadStatusDialog" > <el-table :data="readStatusList" style="width: 100%;margin-bottom: 10px"> <el-table-column prop="employee" label="åå·¥å§å" width="120" /> <el-table-column prop="department" label="æå±é¨é¨" width="150" /> <el-table-column prop="createTime" label="é 读æ¶é´" width="180" /> <el-table-column prop="confirmTime" label="确认æ¶é´" width="180" /> <el-table-column prop="status" label="ç¶æ" width="100"> <template #default="scope"> <el-tag :type="scope.row.status === 'confirmed' ? 'success' : 'warning'"> {{ scope.row.status === 'confirmed' ? '已确认' : 'æªç¡®è®¤' }} </el-tag> </template> </el-table-column> </el-table> </FormDialog> </div> </template> @@ -253,21 +129,13 @@ import { ref, reactive, onMounted, getCurrentInstance, watch } from 'vue' import { useRoute } from 'vue-router' import { ElMessage, ElMessageBox } from 'element-plus' import { Plus } from '@element-plus/icons-vue' import { listSealApplication, addSealApplication, updateSealApplication,listRuleManagement,addRuleManagement,updateRuleManagement,delRuleManagement,getReadingStatusByRuleId,getReadingStatusList,addReadingStatus,updateReadingStatus } from '@/api/collaborativeApproval/sealManagement.js' import { el } from 'element-plus/es/locales.mjs' import { getUserProfile, userListNoPageByTenantId } from '@/api/system/user.js' import { listSealApplication, addSealApplication, updateSealApplication } from '@/api/collaborativeApproval/sealManagement.js' import { userListNoPageByTenantId } from '@/api/system/user.js' import useUserStore from '@/store/modules/user' import { userLoginFacotryList } from "@/api/system/user.js" import {staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js" import FormDialog from '@/components/Dialog/FormDialog.vue' import PIMTable from '@/components/PIMTable/PIMTable.vue' // ååºå¼æ°æ® const currentUser = ref(null) const activeTab = ref('seal') const operationType = ref('add') const tableData = ref([]) // ç¨å°ç³è¯·ç¸å ³ const userStore = useUserStore() const route = useRoute() @@ -306,61 +174,8 @@ size: 10, total: 0 }) // è§ç« å¶åº¦ç¸å ³ const showRegulationDialog = ref(false) const showRegulationDetailDialog = ref(false) const showVersionHistoryDialog = ref(false) const showReadStatusDialog = ref(false) const currentRegulationDetail = ref(null) const regulationFormRef = ref() const regulationForm = reactive({ id: '', regulationNum: '', title: '', category: '', content: '', version: '', status: 'active', readCount: 0, effectiveTime: '', scope: [], requireConfirm: false }) const readStatus = ref({ id: '', ruleId: '', employee: '', department: '', createTime: '', confirmTime: '', status: 'unconfirmed' }) const regulationRules = { title: [{ required: true, message: '请è¾å ¥å¶åº¦æ é¢', trigger: 'blur' }], category: [{ required: true, message: 'è¯·éæ©å¶åº¦åç±»', trigger: 'change' }], content: [{ required: true, message: '请è¾å ¥å¶åº¦å 容', trigger: 'blur' }], effectiveTime: [{ required: true, message: 'è¯·éæ©çææ¶é´', trigger: 'change' }], scope: [{ required: true, message: 'è¯·éæ©éç¨èå´', trigger: 'change' }] } const regulationSearchForm = reactive({ title: '', category: '' }) // åæ°æ® const sealApplications = ref([]) const regulations = ref([]) const versionHistory = ref([]) const readStatusList = ref([]) // { employee: 'éå¿å¼º', department: 'éå®é¨', readTime: '2025-01-11 10:30:00', confirmTime: '2025-01-11 10:35:00', status: 'confirmed' }, // { employee: 'åé å©·', department: 'ææ¯é¨', readTime: '2025-01-11 14:20:00', confirmTime: '', status: 'unconfirmed' }, // { employee: 'ç建å½', department: 'è´¢å¡é¨', readTime: '2025-01-12 09:15:00', confirmTime: '2025-01-12 09:20:00', status: 'confirmed' } // ç¨å°ç³è¯·ç¶æ const getStatusType = (status) => { @@ -371,7 +186,7 @@ } return statusMap[status] || 'info' } // å¶åº¦ç¶æ // ç¨å°ç³è¯·ç¶æææ¬ const getStatusText = (status) => { const statusMap = { pending: 'å¾ å®¡æ¹', @@ -436,16 +251,6 @@ } ]) // å¶åº¦åç±» const getCategoryText = (category) => { const categoryMap = { hr: '人äºå¶åº¦', finance: 'è´¢å¡å¶åº¦', safety: 'å®å ¨å¶åº¦', tech: 'ææ¯å¶åº¦' } return categoryMap[category] || 'æªç¥' } // æç´¢å°ç« ç³è¯· const searchSealApplications = () => { page.current=1 @@ -459,17 +264,6 @@ sealSearchForm.status = '' sealSearchForm.applicationNum = '' searchSealApplications() } // æç´¢å¶åº¦ const searchRegulations = () => { page.current=1 getRegulationList() } // éç½®å¶åº¦æç´¢ const resetRegulationSearch = () => { regulationSearchForm.title = '' regulationSearchForm.category = '' searchRegulations() } // æäº¤ç¨å°ç³è¯· const submitSealApplication = async () => { @@ -519,106 +313,6 @@ const closeSealDetailDialog = () => { showSealDetailDialog.value = false } // å ³éè§ç« å¶åº¦è¯¦æ å¯¹è¯æ¡ const closeRegulationDetailDialog = () => { showRegulationDetailDialog.value = false } // å¤çè§ç« å¶åº¦è¯¦æ 确认 const handleRegulationDetailConfirm = () => { // 妿tableData>0ï¼æ§è¡ç¡®è®¤æ¥çæä½ if (currentRegulationDetail.value && tableData.value && tableData.value.length > 0) { resetForm(currentRegulationDetail.value) } closeRegulationDetailDialog() } // å ³éçæ¬åå²å¯¹è¯æ¡ const closeVersionHistoryDialog = () => { showVersionHistoryDialog.value = false } // å ³éé è¯»ç¶æå¯¹è¯æ¡ const closeReadStatusDialog = () => { showReadStatusDialog.value = false } // æ°å¢ const handleAdd = () => { operationType.value = 'add' resetRegulationForm() showRegulationDialog.value = true } // ç¼è¾ const handleEdit = (row) => { operationType.value = 'edit' Object.assign(regulationForm, row) showRegulationDialog.value = true } // åºå¼ const repealEdit = (row) => { operationType.value = 'edit' Object.assign(regulationForm, row) regulationForm.status = 'repealed' ElMessageBox.confirm('确认åºå¼è¯¥å¶åº¦ï¼', 'æç¤º', { confirmButtonText: 'ç¡®å®', cancelButtonText: 'åæ¶', type: 'warning' }).then(() => { updateRuleManagement(regulationForm).then(res => { if(res.code == 200){ ElMessage.success('å¶åº¦åºå¼æå') // showRegulationDialog.value = false getRegulationList() resetRegulationForm() } }) }).catch(() => { ElMessage({ type: 'info', message: '已忶åºå¼' }) }) } // åå¸å¶åº¦ const submitRegulation = async () => { try { await regulationFormRef.value.validate() if(operationType.value == 'add'){ addRuleManagement(regulationForm).then(res => { if(res.code == 200){ ElMessage.success('å¶åº¦å叿å') showRegulationDialog.value = false getRegulationList() resetRegulationForm() } }) }else{ updateRuleManagement(regulationForm).then(res => { if(res.code == 200){ ElMessage.success('å¶åº¦ç¼è¾æå') showRegulationDialog.value = false resetRegulationForm() getRegulationList() }})} }catch(err){ ElMessage.error(err.msg) } } //éç½®å¶åº¦è¡¨å const resetRegulationForm = () => { Object.assign(regulationForm, { id: '', regulationNum: '', title: '', category: '', content: '', version: '', status: 'active', readCount: 0, effectiveTime: '', scope: [], requireConfirm: false }) } // æ¥çç¨å°ç³è¯·è¯¦æ const viewSealDetail = (row) => { @@ -627,7 +321,6 @@ } // 审æ¹ç¨å°ç³è¯· const approveSeal = (row) => { console.log(row) ElMessageBox.confirm('确认éè¿è¯¥ç¨å°ç³è¯·ï¼', 'æç¤º', { confirmButtonText: 'ç¡®å®', cancelButtonText: 'åæ¶', @@ -637,6 +330,7 @@ updateSealApplication(row).then(res => { if(res.code == 200){ ElMessage.success('审æ¹éè¿') getSealApplicationList() } }) }) @@ -652,122 +346,10 @@ row.status = 'rejected' updateSealApplication(row).then(res => { if(res.code == 200){ ElMessage.success('å®¡æ¹æç»') } }) ElMessage.success('å·²æç»ç³è¯·') }) } // è·åå¨èåå·¥å表 const getList = () => { tableLoading.value = true; //è·åå½åç»å½ç¨æ·ä¿¡æ¯ getUserProfile().then(res => { if(res.code == 200){ console.log(res.data.userName) currentUser.value = res.data.userName getSealApplicationList() } }) staffOnJobListPage({staffState: 1, ...page}).then(res => { tableLoading.value = false; // tableData.value = res.data.records // //çéåºåcurrentUserååç人å tableData.value = res.data.records.filter(item => item.staffName === currentUser.value) page.total = res.data.total; if(tableData.value.length == 0){ ElMessage.error('å½åç¨æ·æªå å ¥ä»»ä½é¨é¨') } }).catch(err => { tableLoading.value = false; }) }; // æ¥çå¶åº¦çæ¬åå² const viewVersionHistory = (row) => { showVersionHistoryDialog.value = true const params = { category: row.category } listRuleManagement(page,params).then(res => { if(res.code == 200){ versionHistory.value = res.data.records } }) } // æ¥çå¶åº¦è¯¦æ const viewRegulation = (row) => { getList() currentRegulationDetail.value = row showRegulationDetailDialog.value = true getReadingStatusByRuleId(row.id).then(res => { if(res.code == 200){ readStatusList.value = res.data if(readStatusList.value.length==0 && tableData.value.length>0){ const params = { ruleId: row.id, employee: tableData.value[0].staffName, department: tableData.value[0].postJob, status: 'unconfirmed' } addReadingStatus(params).then(res => { if(res.code == 200){ ElMessage.success('å¶åº¦é 读æå') } }) } } }) } // æ¥çå¶åº¦é è¯»ç¶æ const viewReadStatus = (row) => { showReadStatusDialog.value = true //æ¥çé è¯»ç¶æå表 getReadingStatusByRuleId(row.id).then(res => { if(res.code == 200){ readStatusList.value = res.data } }) } //确认æ¥ç const resetForm = (row) => { console.log("row",row) row.readCount = row.readCount + 1 updateRuleManagement(row).then(res => { if(res.code == 200){ ElMessage.success('æ¥çæ°éä¿®æ¹æå') //ä¿®æ¹é è¯»ç¶æ //æ ¹æ®å¶åº¦idåå½åç»å½çåå·¥å¾å°é è¯»ç¶æ // let item = readStatusList.value.filter(item => item.employee == tableData.value[0].staffName ) // if(item.length>0){ // item[0].status = 'confirmed', // item[0].confirmTime = new Date().toISOString().replace('T', ' ').split('.')[0]; // } // çéå½åå工对åºè¯¥å¶åº¦çé è¯»ç¶æè®°å½ let statusItem = readStatusList.value.find(item => item.employee === tableData.value[0].staffName && item.ruleId === row.id); if (statusItem) { // 妿æ¾å°è®°å½ï¼æ´æ°ç¶æå确认æ¶é´ statusItem.status = 'confirmed'; // æ ¼å¼åæ¶é´ä¸º"YYYY-MM-DD HH:mm:ss"æ ¼å¼ const now = new Date(); statusItem.confirmTime = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}:${String(now.getSeconds()).padStart(2, '0')}`; // statusItem.confirmTime = new Date().toISOString().replace('T', ' ').split('.')[0]; updateReadingStatus(statusItem).then(res => { if(res.code == 200){ ElMessage.success('å¶åº¦é è¯»ç¶æä¿®æ¹æå') } }) } } }) } @@ -782,44 +364,13 @@ tableLoading.value = true listSealApplication(page,sealSearchForm) .then(res => { //è·åå½åç»å½çé¨é¨ä¿¡æ¯ // è·åå½åç»å½çé¨é¨ä¿¡æ¯å¹¶è¿æ»¤æ°æ® const currentFactoryName = userStore.currentFactoryName if (currentFactoryName) { // æ ¹æ®currentFactoryNameè¿æ»¤åºdepartmentç¸åçæ°æ® sealApplications.value = res.data.records.filter(item => item.department === currentFactoryName) // æ´æ°è¿æ»¤åçæ»æ° page.total = sealApplications.value.length } else { // å¦ææ²¡æcurrentFactoryNameï¼åæ¾ç¤ºæææ°æ® sealApplications.value = res.data.records page.total = res.data.total } // sealApplications.value = res.data.records // page.value.total = res.data.total; tableLoading.value = false; tableLoading.value = false }).catch(err => { tableLoading.value = false; tableLoading.value = false }) } // è·åè§ç« å¶åº¦åè¡¨æ°æ® const getRegulationList = async () => { tableLoading.value = true listRuleManagement(page,regulationSearchForm) .then(res => { regulations.value = res.data.records // è¿æ»¤æå·²åºå¼çå¶åº¦ // regulations.value = res.data.records.filter(item => item.status !== 'repealed') page.total = res.data.total; tableLoading.value = false; }).catch(err => { tableLoading.value = false; }) } // å页ååå¤ç const paginationChange = (obj) => { page.current = obj.page; @@ -845,7 +396,6 @@ } else { getSealApplicationList() } getRegulationList() }) </script> @@ -868,26 +418,7 @@ margin-bottom: 20px; } .mt-20 { margin-top: 20px; } .ml-10 { margin-left: 10px; } .regulation-content { background-color: #f5f5f5; padding: 15px; border-radius: 4px; line-height: 1.6; white-space: pre-wrap; height: 200px; } .dialog-footer { display: flex; justify-content: flex-end; gap: 10px; } </style> src/views/inventoryManagement/dispatchLog/Record.vue
@@ -112,9 +112,7 @@ delStockOut, } from "@/api/inventoryManagement/stockOut.js"; import { findAllQualifiedStockRecordTypeOptions, findAllStockRecordTypeOptions, findAllUnqualifiedStockRecordTypeOptions findAllQualifiedStockOutRecordTypeOptions, findAllUnQualifiedStockOutRecordTypeOptions, } from "@/api/basicData/enum.js"; const userStore = useUserStore(); @@ -186,13 +184,13 @@ // è·åæ¥æºç±»åé项 const fetchStockRecordTypeOptions = () => { if (props.type === '0') { findAllQualifiedStockRecordTypeOptions() findAllQualifiedStockOutRecordTypeOptions() .then(res => { stockRecordTypeOptions.value = res.data; }) return } findAllUnqualifiedStockRecordTypeOptions() findAllUnQualifiedStockOutRecordTypeOptions() .then(res => { stockRecordTypeOptions.value = res.data; }) src/views/inventoryManagement/receiptManagement/Record.vue
@@ -109,8 +109,7 @@ batchDeleteStockInRecords, } from "@/api/inventoryManagement/stockInRecord.js"; import { findAllQualifiedStockRecordTypeOptions, findAllUnqualifiedStockRecordTypeOptions findAllQualifiedStockInRecordTypeOptions, findAllUnQualifiedStockInRecordTypeOptions, } from "@/api/basicData/enum.js"; const {proxy} = getCurrentInstance(); @@ -176,13 +175,13 @@ // è·åæ¥æºç±»åé项 const fetchStockRecordTypeOptions = () => { if (props.type === '0') { findAllQualifiedStockRecordTypeOptions() findAllQualifiedStockInRecordTypeOptions() .then(res => { stockRecordTypeOptions.value = res.data; }) return } findAllUnqualifiedStockRecordTypeOptions() findAllUnQualifiedStockInRecordTypeOptions() .then(res => { stockRecordTypeOptions.value = res.data; }) src/views/inventoryManagement/stockReport/index.vue
@@ -240,14 +240,12 @@ import { ElMessage } from 'element-plus' import * as echarts from 'echarts' import { getStockMonthlyReport, getStockInOutReport, } from '@/api/inventoryManagement/stockReport' import { getStockInventoryInAndOutReportList, getStockInventoryReportList } from "@/api/inventoryManagement/stockInventory.js"; import {findAllQualifiedStockRecordTypeOptions} from "@/api/basicData/enum.js"; import { findAllQualifiedStockInRecordTypeOptions, } from "@/api/basicData/enum.js"; const { proxy } = getCurrentInstance() @@ -277,7 +275,7 @@ // è·åæ¥æºç±»åé项 const fetchStockRecordTypeOptions = () => { findAllQualifiedStockRecordTypeOptions() findAllQualifiedStockInRecordTypeOptions() .then(res => { stockRecordTypeOptions.value = res.data; }) src/views/procurementManagement/procurementLedger/index.vue
@@ -157,6 +157,10 @@ prop="entryDate" width="100" show-overflow-tooltip /> <el-table-column label="夿³¨" prop="remarks" width="200" show-overflow-tooltip /> <el-table-column fixed="right" label="æä½" width="120" @@ -450,8 +454,8 @@ <el-row :gutter="30"> <el-col :span="24"> <el-form-item label="夿³¨Â·ï¼" prop="remark"> <el-input v-model="form.remark" prop="remarks"> <el-input v-model="form.remarks" placeholder="请è¾å ¥" clearable type="textarea" @@ -462,7 +466,7 @@ <el-row :gutter="30"> <el-col :span="24"> <el-form-item label="éä»¶ææï¼" prop="remark"> prop="purchaseLedgerFiles"> <el-upload v-model:file-list="fileList" :action="upload.url" multiple src/views/productionManagement/productionOrder/New.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,192 @@ <template> <div> <el-dialog v-model="isShow" title="æ°å¢ç产订å" width="800" @close="closeModal" > <el-form label-width="140px" :model="formState" label-position="top" ref="formRef"> <el-form-item label="产ååç§°" prop="productModelId" :rules="[ { required: true, message: 'è¯·éæ©äº§å', trigger: 'change', } ]" > <el-button type="primary" @click="showProductSelectDialog = true"> {{ formState.productName ? formState.productName : 'éæ©äº§å' }} </el-button> </el-form-item> <el-form-item label="è§æ ¼" prop="productModelName" > <el-input v-model="formState.productModelName" disabled /> </el-form-item> <el-form-item label="åä½" prop="unit" > <el-input v-model="formState.unit" disabled /> </el-form-item> <el-form-item label="å·¥èºè·¯çº¿"> <el-select v-model="formState.routeId" placeholder="è¯·éæ©å·¥èºè·¯çº¿" style="width: 100%;" :loading="bindRouteLoading"> <el-option v-for="item in routeOptions" :key="item.id" :label="`${item.processRouteCode || ''}`" :value="item.id" /> </el-select> </el-form-item> <el-form-item label="éæ±æ°é" prop="quantity" > <el-input-number v-model="formState.quantity" :step="1" :min="1" style="width: 100%" /> </el-form-item> </el-form> <!-- 产åéæ©å¼¹çª --> <ProductSelectDialog v-model="showProductSelectDialog" @confirm="handleProductSelect" single /> <template #footer> <div class="dialog-footer"> <el-button type="primary" @click="handleSubmit">确认</el-button> <el-button @click="closeModal">åæ¶</el-button> </div> </template> </el-dialog> </div> </template> <script setup> import {ref, computed, getCurrentInstance} from "vue"; import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue"; import {addProductOrder, listProcessRoute} from "@/api/productionManagement/productionOrder.js"; const props = defineProps({ visible: { type: Boolean, required: true, }, type: { type: String, required: true, default: 'qualified', }, }); const emit = defineEmits(['update:visible', 'completed']); // ååºå¼æ°æ®ï¼æ¿ä»£é项å¼ç dataï¼ const formState = ref({ productId: undefined, productModelId: undefined, routeId: undefined, productName: "", productModelName: "", unit: "", quantity: 0, }); const isShow = computed({ get() { return props.visible; }, set(val) { emit('update:visible', val); }, }); const showProductSelectDialog = ref(false); let { proxy } = getCurrentInstance() const closeModal = () => { // éç½®è¡¨åæ°æ® formState.value = { productId: undefined, productModelId: undefined, routeId: undefined, productName: "", productModelName: "", quantity: '', }; isShow.value = false; }; // 产åéæ©å¤ç const handleProductSelect = async (products) => { if (products && products.length > 0) { const product = products[0]; formState.value.productId = product.productId; formState.value.productName = product.productName; formState.value.productModelName = product.model; formState.value.productModelId = product.id; formState.value.unit = product.unit; showProductSelectDialog.value = false; fetchRouteOptions( product.id); // 触å表åéªè¯æ´æ° proxy.$refs["formRef"]?.validateField('productModelId'); } }; const routeOptions = ref([]); const bindRouteLoading = ref(false); const fetchRouteOptions = (productModelId) => { formState.value.routeId = undefined; routeOptions.value = [] bindRouteLoading.value = true; listProcessRoute({ productModelId: productModelId }).then(res => { routeOptions.value = res.data || []; }).finally(() => { bindRouteLoading.value = false; }) } const handleSubmit = () => { proxy.$refs["formRef"].validate(valid => { if (valid) { // éªè¯æ¯å¦éæ©äºäº§ååè§æ ¼ if (!formState.value.productModelId) { proxy.$modal.msgError("è¯·éæ©äº§å"); return; } if (!formState.value.productModelId) { proxy.$modal.msgError("è¯·éæ©è§æ ¼"); return; } addProductOrder(formState.value).then(res => { // å ³éæ¨¡ææ¡ isShow.value = false; // åç¥ç¶ç»ä»¶å·²å®æ emit('completed'); proxy.$modal.msgSuccess("æäº¤æå"); }) } }) }; defineExpose({ closeModal, handleSubmit, isShow, }); </script> src/views/productionManagement/productionOrder/index.vue
@@ -41,6 +41,8 @@ </el-form-item> </el-form> <div> <el-button type="primary" @click="isShowNewModal = true">æ°å¢</el-button> <el-button type="danger" @click="handleDelete">å é¤</el-button> <el-button @click="handleOut">导åº</el-button> </div> </div> @@ -51,6 +53,8 @@ :page="page" :tableLoading="tableLoading" :row-class-name="tableRowClassName" :isSelection="true" @selection-change="handleSelectionChange" @pagination="pagination"> <template #completionStatus="{ row }"> <el-progress @@ -86,6 +90,10 @@ </span> </template> </el-dialog> <new-product-order v-if="isShowNewModal" v-model:visible="isShowNewModal" @completed="handleQuery" /> </div> </template> @@ -98,12 +106,17 @@ productOrderListPage, listProcessRoute, bindingRoute, listProcessBom, listProcessBom, delProductOrder, } from "@/api/productionManagement/productionOrder.js"; import { listMain as getOrderProcessRouteMain } from "@/api/productionManagement/productProcessRoute.js"; import {fileDel} from "@/api/financialManagement/revenueManagement.js"; import PIMTable from "@/components/PIMTable/PIMTable.vue"; const NewProductOrder = defineAsyncComponent(() => import("@/views/productionManagement/productionOrder/New.vue")); const { proxy } = getCurrentInstance(); const router = useRouter(); const isShowNewModal = ref(false); const tableColumn = ref([ { @@ -208,6 +221,7 @@ size: 100, total: 0, }); const selectedRows = ref([]); const data = reactive({ searchForm: { @@ -239,6 +253,7 @@ // æ·»å 表è¡ç±»åæ¹æ³ const tableRowClassName = ({ row }) => { if (!row.deliveryDate) return ''; if (row.isFh) return ''; const diff = row.deliveryDaysDiff; @@ -386,6 +401,33 @@ }); }; // è¡¨æ ¼éæ©æ°æ® const handleSelectionChange = (selection) => { selectedRows.value = selection; }; const handleDelete = () => { let ids = []; if (selectedRows.value.length > 0) { ids = selectedRows.value.map((item) => item.id); } else { proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); return; } ElMessageBox.confirm("éä¸çå 容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "导åº", { confirmButtonText: "确认", cancelButtonText: "åæ¶", type: "warning", }).then(() => { delProductOrder(ids).then((res) => { proxy.$modal.msgSuccess("å 餿å"); getList(); }); }).catch(() => { proxy.$modal.msg("已忶"); }); }; // å¯¼åº const handleOut = () => { ElMessageBox.confirm("éä¸çå 容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { src/views/qualityManagement/finalInspection/index.vue
@@ -96,6 +96,11 @@ width: 120 }, { label: "ç产工åå·", prop: "workOrderNo", width: 120 }, { label: "æ£éªå", prop: "checkName", }, src/views/qualityManagement/processInspection/index.vue
@@ -96,6 +96,11 @@ width: 120 }, { label: "ç产工åå·", prop: "workOrderNo", width: 120 }, { label: "å·¥åº", prop: "process", width: 230 src/views/qualityManagement/rawMaterialInspection/index.vue
@@ -98,6 +98,11 @@ width: 120 }, { label: "éè´è®¢åå·", prop: "purchaseContractNo", width: 120 }, { label: "ä¾åºå", prop: "supplier", width: 230 src/views/reportAnalysis/productionAnalysis/components/right-top.vue
@@ -2,25 +2,16 @@ <div> <PanelHeader title="å·¥åæ§è¡æçåæ" /> <div class="main-panel panel-item-customers"> <Echarts ref="chart" :chartStyle="chartStyle" :grid="grid" :legend="barLegend" :series="chartSeries" :tooltip="tooltip" :xAxis="xAxis1" :yAxis="yAxis1" :options="{ backgroundColor: 'transparent', textStyle: { color: '#B8C8E0' } }" style="height: 260px" /> <Echarts ref="chart" :chartStyle="chartStyle" :grid="grid" :legend="barLegend" :series="chartSeries" :tooltip="tooltip" :xAxis="xAxis1" :yAxis="yAxis1" :options="{ backgroundColor: 'transparent', textStyle: { color: '#B8C8E0' } }" style="height: 260px" /> </div> </div> </template> <script setup> import { ref, onMounted } from 'vue' import { qualityStatistics } from '@/api/viewIndex.js' import { workOrderEfficiencyAnalysis } from '@/api/viewIndex.js' import PanelHeader from './PanelHeader.vue' import Echarts from '@/components/Echarts/echarts.vue' @@ -37,7 +28,6 @@ data: ['å¼å·¥', '宿', 'è¯åç'], } // æ±ç¶å¾ï¼å¼å·¥ãå®æï¼æçº¿å¾ï¼è¯åçï¼é¢è² rgba(90, 216, 166, 1)ï¼ const chartSeries = ref([ { name: 'å¼å·¥', @@ -111,6 +101,7 @@ const xAxis1 = ref([ { type: 'category', axisTick: { show: false }, axisLabel: { color: '#B8C8E0' }, data: [] }, ]) const yAxis1 = [ { type: 'value', name: 'ä»¶', axisLabel: { color: '#B8C8E0' }, nameTextStyle: { color: '#B8C8E0' } }, { @@ -125,25 +116,23 @@ ] const fetchData = () => { qualityStatistics() workOrderEfficiencyAnalysis() .then((res) => { if (!res?.data?.item || !Array.isArray(res.data.item)) return const items = res.data.item xAxis1.value[0].data = items.map((d) => d.date) // å¼å·¥ï¼è¿ç¨æ£éªæ° chartSeries.value[0].data = items.map((d) => Number(d.processNum) || 0) // 宿ï¼åºåæ° chartSeries.value[1].data = items.map((d) => Number(d.factoryNum) || 0) // è¯åçï¼åºåæ°/è¿ç¨æ°*100ï¼æ åç¬æ¥å£æ¶ç¨æ¤å ä½ï¼ chartSeries.value[2].data = items.map((d) => { const processNum = Number(d.processNum) || 0 const factoryNum = Number(d.factoryNum) || 0 if (processNum <= 0) return 0 return Math.min(100, Math.round((factoryNum / processNum) * 100)) }) // æ ¹æ®ä½ çç»æï¼æ°æ®ç´æ¥å¨ res.data ä¸ if (!res?.data || !Array.isArray(res.data)) return const list = res.data xAxis1.value[0].data = list.map((item) => item.date) chartSeries.value[0].data = list.map((item) => Number(item.startQuantity) || 0) chartSeries.value[1].data = list.map((item) => Number(item.finishQuantity) || 0) chartSeries.value[2].data = list.map((item) => Number(item.yieldRate) || 0) }) .catch((err) => { console.error('è·åå¼å·¥ä¸è¯åçæ°æ®å¤±è´¥:', err) console.error('è·åå·¥åæçæ°æ®å¤±è´¥:', err) }) } src/views/safeProduction/dangerInvestigation/index.vue
@@ -111,13 +111,13 @@ </el-table-column> <el-table-column fixed="right" label="æä½" min-width="250" min-width="150" align="center"> <template #default="scope"> <el-button link <!-- <el-button link type="primary" size="small" @click="openForm('edit', scope.row)">ç¼è¾</el-button> @click="openForm('edit', scope.row)">ç¼è¾</el-button> --> <el-button link type="primary" size="small" @@ -125,12 +125,12 @@ <el-button link type="primary" size="small" :disabled="scope.row.isRectify" :disabled="scope.row.isRectify || scope.row.rectifyActualTime" @click="openForm('edit2', scope.row)">æ´æ¹</el-button> <el-button link type="primary" size="small" :disabled="!scope.row.rectifyActualTime" :disabled="!scope.row.rectifyActualTime || scope.row.verifyTime" @click="openForm('edit3', scope.row)">éªæ¶</el-button> </template> </el-table-column> src/views/salesManagement/receiptPayment/index.vue
@@ -335,7 +335,7 @@ const getStatusTagType = (statusName = '') => { const normalized = statusName.trim(); if (!normalized) return 'info'; return normalized === 'æªå®æå款' ? 'danger' : 'success'; return normalized === 'æªå®æä»æ¬¾' ? 'danger' : 'success'; }; // æ¥è¯¢å表 /** æç´¢æé®æä½ */ src/views/salesManagement/salesLedger/index.vue
@@ -118,6 +118,7 @@ <el-table-column label="å½å ¥æ¥æ" prop="entryDate" width="120" show-overflow-tooltip /> <el-table-column label="ç¾è®¢æ¥æ" prop="executionDate" width="120" show-overflow-tooltip /> <el-table-column label="äº¤ä»æ¥æ" prop="deliveryDate" width="120" show-overflow-tooltip /> <el-table-column label="夿³¨" prop="remarks" width="200" show-overflow-tooltip /> <el-table-column fixed="right" label="æä½" min-width="100" align="center"> <template #default="scope"> <el-button link type="primary" size="small" @click="openForm('edit', scope.row)">ç¼è¾</el-button> @@ -242,14 +243,14 @@ </el-table> <el-row :gutter="30"> <el-col :span="24"> <el-form-item label="夿³¨Â·ï¼" prop="remark"> <el-input v-model="form.remark" placeholder="请è¾å ¥" clearable type="textarea" :rows="2" :disabled="operationType === 'view'" /> <el-form-item label="夿³¨ï¼" prop="remarks"> <el-input v-model="form.remarks" placeholder="请è¾å ¥" clearable type="textarea" :rows="2" :disabled="operationType === 'view'" /> </el-form-item> </el-col> </el-row> <el-row :gutter="30"> <el-col :span="24"> <el-form-item label="éä»¶ææï¼" prop="remark"> <el-form-item label="éä»¶ææï¼" prop="salesLedgerFiles"> <el-upload v-model:file-list="fileList" :action="upload.url" multiple ref="fileUpload" auto-upload :headers="upload.headers" :before-upload="handleBeforeUpload" :on-error="handleUploadError" :on-success="handleUploadSuccess" :on-remove="handleRemove"> @@ -1004,6 +1005,7 @@ // æ·»å 表è¡ç±»åæ¹æ³ const tableRowClassName = ({ row }) => { if (!row.deliveryDate) return ''; if (row.isFh) return ''; const diff = row.deliveryDaysDiff; src/views/salesManagement/salesQuotation/index.vue
@@ -231,6 +231,7 @@ <el-table :data="form.products" border style="width: 100%" class="product-table" v-if="form.products.length > 0"> <el-table-column prop="product" label="产ååç§°" width="200"> <template #default="scope"> <el-form-item :prop="`products.${scope.$index}.productId`" class="product-table-form-item"> <el-tree-select v-model="scope.row.productId" placeholder="è¯·éæ©" @@ -241,15 +242,18 @@ :render-after-expand="false" style="width: 100%" /> </el-form-item> </template> </el-table-column> <el-table-column prop="specification" label="è§æ ¼åå·" width="150"> <el-table-column prop="specification" label="è§æ ¼åå·" width="200"> <template #default="scope"> <el-form-item :prop="`products.${scope.$index}.specificationId`" class="product-table-form-item"> <el-select v-model="scope.row.specificationId" placeholder="è¯·éæ©" clearable @change="getProductModel($event, scope.row)" style="width: 100%" > <el-option v-for="item in scope.row.modelOptions || []" @@ -258,16 +262,21 @@ :value="item.id" /> </el-select> </el-form-item> </template> </el-table-column> <el-table-column prop="unit" label="åä½"> <template #default="scope"> <el-input v-model="scope.row.unit" placeholder="åä½" /> <el-form-item :prop="`products.${scope.$index}.unit`" class="product-table-form-item"> <el-input v-model="scope.row.unit" placeholder="åä½" clearable/> </el-form-item> </template> </el-table-column> <el-table-column prop="unitPrice" label="åä»·"> <template #default="scope"> <el-form-item :prop="`products.${scope.$index}.unitPrice`" class="product-table-form-item"> <el-input-number v-model="scope.row.unitPrice" :min="0" :precision="2" style="width: 100%" /> </el-form-item> </template> </el-table-column> <el-table-column label="æä½" width="80" align="center"> @@ -393,13 +402,30 @@ totalAmount: 0 }) const rules = { const baseRules = { customer: [{ required: true, message: 'è¯·éæ©å®¢æ·', trigger: 'change' }], salesperson: [{ required: true, message: 'è¯·éæ©ä¸å¡å', trigger: 'change' }], quotationDate: [{ required: true, message: 'è¯·éæ©æ¥ä»·æ¥æ', trigger: 'change' }], validDate: [{ required: true, message: 'è¯·éæ©æææ', trigger: 'change' }], paymentMethod: [{ required: true, message: '请è¾å ¥ä»æ¬¾æ¹å¼', trigger: 'blur' }] } const productRowRules = { productId: [{ required: true, message: 'è¯·éæ©äº§ååç§°', trigger: 'change' }], specificationId: [{ required: true, message: 'è¯·éæ©è§æ ¼åå·', trigger: 'change' }], unit: [{ required: true, message: '请填ååä½', trigger: 'blur' }], unitPrice: [{ required: true, message: '请填ååä»·', trigger: 'change' }] } const rules = computed(() => { const r = { ...baseRules } ;(form.products || []).forEach((_, i) => { r[`products.${i}.productId`] = productRowRules.productId r[`products.${i}.specificationId`] = productRowRules.specificationId r[`products.${i}.unit`] = productRowRules.unit r[`products.${i}.unitPrice`] = productRowRules.unitPrice }) return r }) const userList = ref([]); const customerOption = ref([]); @@ -956,6 +982,17 @@ padding: 8px 0; } .product-table-form-item { margin-bottom: 0; :deep(.el-form-item__content) { margin-left: 0 !important; } :deep(.el-form-item__label) { width: auto; min-width: auto; } } .approver-nodes-container { display: flex; flex-wrap: wrap;