Merge remote-tracking branch 'origin/dev_天津军泰伟业' into dev_天津军泰伟业
# Conflicts:
# src/views/equipmentManagement/spareParts/index.vue
| | |
| | | :fixed="item.fixed" |
| | | :label="item.label" |
| | | :prop="item.prop" |
| | | show-overflow-tooltip |
| | | :show-overflow-tooltip="item.dataType !== 'action'" |
| | | :align="item.align" |
| | | :sortable="!!item.sortable" |
| | | :type="item.type" |
| | |
| | | <template> |
| | | <div class="qr-code-generator"> |
| | | <!-- äºç»´ç çæè¡¨å --> |
| | | <el-form :model="form" :rules="rules" ref="formRef" label-width="120px" class="qr-form"> |
| | | <el-form :model="form" |
| | | :rules="rules" |
| | | ref="formRef" |
| | | label-width="120px" |
| | | class="qr-form"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ è¯ç±»å" prop="type"> |
| | | <el-select v-model="form.type" placeholder="è¯·éæ©æ è¯ç±»å" style="width: 100%"> |
| | | <el-option label="äºç»´ç " value="qrcode"></el-option> |
| | | <el-option label="é²ä¼ªç " value="security"></el-option> |
| | | <el-form-item label="æ è¯ç±»å" |
| | | prop="type"> |
| | | <el-select v-model="form.type" |
| | | placeholder="è¯·éæ©æ è¯ç±»å" |
| | | style="width: 100%"> |
| | | <el-option label="äºç»´ç " |
| | | value="qrcode"></el-option> |
| | | <el-option label="é²ä¼ªç " |
| | | value="security"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å
容" prop="content"> |
| | | <el-input |
| | | v-model="form.content" |
| | | <el-form-item label="å
容" |
| | | prop="content"> |
| | | <el-input v-model="form.content" |
| | | placeholder="请è¾å
¥è¦ç¼ç çå
容" |
| | | :type="form.type === 'security' ? 'textarea' : 'text'" |
| | | :rows="form.type === 'security' ? 3 : 1" |
| | | ></el-input> |
| | | :rows="form.type === 'security' ? 3 : 1"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="尺寸" prop="size"> |
| | | <el-input-number |
| | | v-model="form.size" |
| | | <el-form-item label="尺寸" |
| | | prop="size"> |
| | | <el-input-number v-model="form.size" |
| | | :min="100" |
| | | :max="500" |
| | | :step="50" |
| | | style="width: 100%" |
| | | ></el-input-number> |
| | | style="width: 100%"></el-input-number> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="è¾¹è·" prop="margin"> |
| | | <el-input-number |
| | | v-model="form.margin" |
| | | <el-form-item label="è¾¹è·" |
| | | prop="margin"> |
| | | <el-input-number v-model="form.margin" |
| | | :min="0" |
| | | :max="10" |
| | | :step="1" |
| | | style="width: 100%" |
| | | ></el-input-number> |
| | | style="width: 100%"></el-input-number> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="忝è²" prop="foregroundColor"> |
| | | <el-color-picker v-model="form.foregroundColor" style="width: 100%"></el-color-picker> |
| | | <el-form-item label="忝è²" |
| | | prop="foregroundColor"> |
| | | <el-color-picker v-model="form.foregroundColor" |
| | | style="width: 100%"></el-color-picker> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="èæ¯è²" prop="backgroundColor"> |
| | | <el-color-picker v-model="form.backgroundColor" style="width: 100%"></el-color-picker> |
| | | <el-form-item label="èæ¯è²" |
| | | prop="backgroundColor"> |
| | | <el-color-picker v-model="form.backgroundColor" |
| | | style="width: 100%"></el-color-picker> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="24"> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="generateCode" :loading="generating"> |
| | | <el-button type="primary" |
| | | @click="generateCode" |
| | | :loading="generating"> |
| | | çæ{{ form.type === 'qrcode' ? 'äºç»´ç ' : 'é²ä¼ªç ' }} |
| | | </el-button> |
| | | <el-button @click="resetForm">éç½®</el-button> |
| | |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | |
| | | <!-- çæçç æ¾ç¤ºåºå --> |
| | | <div v-if="generatedCodeUrl" class="code-display"> |
| | | <div v-if="generatedCodeUrl" |
| | | class="code-display"> |
| | | <el-divider content-position="center"> |
| | | {{ form.type === 'qrcode' ? 'çæçäºç»´ç ' : 'çæçé²ä¼ªç ' }} |
| | | </el-divider> |
| | | |
| | | <div class="code-container"> |
| | | <div class="code-image"> |
| | | <img :src="generatedCodeUrl" :alt="form.type === 'qrcode' ? 'äºç»´ç ' : 'é²ä¼ªç '" /> |
| | | <img :src="generatedCodeUrl" |
| | | :alt="form.type === 'qrcode' ? 'äºç»´ç ' : 'é²ä¼ªç '" /> |
| | | </div> |
| | | |
| | | <div class="code-info"> |
| | | <p><strong>å
容ï¼</strong>{{ form.content }}</p> |
| | | <p><strong>ç±»åï¼</strong>{{ form.type === 'qrcode' ? 'äºç»´ç ' : 'é²ä¼ªç ' }}</p> |
| | |
| | | <p><strong>çææ¶é´ï¼</strong>{{ generateTime }}</p> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="code-actions"> |
| | | <el-button type="success" @click="downloadCode" icon="Download"> |
| | | <el-button type="success" |
| | | @click="downloadCode" |
| | | icon="Download"> |
| | | ä¸è½½å¾ç |
| | | </el-button> |
| | | <el-button type="primary" @click="copyToClipboard" icon="CopyDocument"> |
| | | <el-button type="primary" |
| | | @click="copyToClipboard" |
| | | icon="CopyDocument"> |
| | | å¤å¶å
容 |
| | | </el-button> |
| | | <el-button @click="printCode" icon="Printer"> |
| | | <el-button @click="printCode" |
| | | icon="Printer"> |
| | | æå° |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- æ¹éçæå¯¹è¯æ¡ --> |
| | | <el-dialog v-model="batchDialogVisible" title="æ¹éçæ" width="600px"> |
| | | <el-form :model="batchForm" label-width="120px"> |
| | | <el-dialog v-model="batchDialogVisible" |
| | | title="æ¹éçæ" |
| | | width="600px"> |
| | | <el-form :model="batchForm" |
| | | label-width="120px"> |
| | | <el-form-item label="çææ°é"> |
| | | <el-input-number v-model="batchForm.quantity" :min="1" :max="100" style="width: 100%"></el-input-number> |
| | | <el-input-number v-model="batchForm.quantity" |
| | | :min="1" |
| | | :max="100" |
| | | style="width: 100%"></el-input-number> |
| | | </el-form-item> |
| | | <el-form-item label="åç¼"> |
| | | <el-input v-model="batchForm.prefix" placeholder="请è¾å
¥åç¼ï¼å¦ï¼PROD_"></el-input> |
| | | <el-input v-model="batchForm.prefix" |
| | | placeholder="请è¾å
¥åç¼ï¼å¦ï¼PROD_"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="èµ·å§ç¼å·"> |
| | | <el-input-number v-model="batchForm.startNumber" :min="1" style="width: 100%"></el-input-number> |
| | | <el-input-number v-model="batchForm.startNumber" |
| | | :min="1" |
| | | style="width: 100%"></el-input-number> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="generateBatchCodes">å¼å§çæ</el-button> |
| | | <el-button @click="batchDialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="generateBatchCodes">å¼å§çæ</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- æ¹éçæç»æ --> |
| | | <div v-if="batchCodes.length > 0" class="batch-results"> |
| | | <div v-if="batchCodes.length > 0" |
| | | class="batch-results"> |
| | | <el-divider content-position="center">æ¹éçæç»æ</el-divider> |
| | | |
| | | <div class="batch-grid"> |
| | | <div |
| | | v-for="(code, index) in batchCodes" |
| | | <div v-for="(code, index) in batchCodes" |
| | | :key="index" |
| | | class="batch-item" |
| | | > |
| | | <img :src="code.url" :alt="code.content" /> |
| | | class="batch-item"> |
| | | <img :src="code.url" |
| | | :alt="code.content" /> |
| | | <p class="batch-content">{{ code.content }}</p> |
| | | <el-button size="small" @click="downloadSingleCode(code)">ä¸è½½</el-button> |
| | | <el-button size="small" |
| | | @click="downloadSingleCode(code)">ä¸è½½</el-button> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="batch-actions"> |
| | | <el-button type="success" @click="downloadAllCodes">ä¸è½½å
¨é¨</el-button> |
| | | <el-button type="success" |
| | | @click="downloadAllCodes">ä¸è½½å
¨é¨</el-button> |
| | | <el-button @click="clearBatchCodes">æ¸
ç©ºç»æ</el-button> |
| | | </div> |
| | | </div> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, computed, onMounted } from 'vue' |
| | | import QRCode from 'qrcode' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { Download, CopyDocument, Printer } from '@element-plus/icons-vue' |
| | | import { ref, reactive, computed, onMounted } from "vue"; |
| | | import QRCode from "qrcode"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import { Download, CopyDocument, Printer } from "@element-plus/icons-vue"; |
| | | |
| | | // å®ä¹ç»ä»¶åç§° |
| | | defineOptions({ |
| | | name: 'QRCodeGenerator' |
| | | }) |
| | | name: "QRCodeGenerator", |
| | | }); |
| | | |
| | | // è¡¨åæ°æ® |
| | | const form = reactive({ |
| | | type: 'qrcode', |
| | | content: '', |
| | | type: "qrcode", |
| | | content: "", |
| | | size: 200, |
| | | margin: 2, |
| | | foregroundColor: '#000000', |
| | | backgroundColor: '#FFFFFF' |
| | | }) |
| | | foregroundColor: "#000000", |
| | | backgroundColor: "#FFFFFF", |
| | | }); |
| | | |
| | | // 表åéªè¯è§å |
| | | const rules = { |
| | | type: [{ required: true, message: 'è¯·éæ©æ è¯ç±»å', trigger: 'change' }], |
| | | content: [{ required: true, message: '请è¾å
¥å
容', trigger: 'blur' }] |
| | | } |
| | | type: [{ required: true, message: "è¯·éæ©æ è¯ç±»å", trigger: "change" }], |
| | | content: [{ required: true, message: "请è¾å
¥å
容", trigger: "blur" }], |
| | | }; |
| | | |
| | | // ååºå¼æ°æ® |
| | | const formRef = ref() |
| | | const generating = ref(false) |
| | | const generatedCodeUrl = ref('') |
| | | const generateTime = ref('') |
| | | const batchDialogVisible = ref(false) |
| | | const formRef = ref(); |
| | | const generating = ref(false); |
| | | const generatedCodeUrl = ref(""); |
| | | const generateTime = ref(""); |
| | | const batchDialogVisible = ref(false); |
| | | const batchForm = reactive({ |
| | | quantity: 10, |
| | | prefix: '', |
| | | startNumber: 1 |
| | | }) |
| | | const batchCodes = ref([]) |
| | | prefix: "", |
| | | startNumber: 1, |
| | | }); |
| | | const batchCodes = ref([]); |
| | | |
| | | // çæäºç»´ç æé²ä¼ªç |
| | | const generateCode = async () => { |
| | | try { |
| | | await formRef.value.validate() |
| | | await formRef.value.validate(); |
| | | |
| | | if (!form.content.trim()) { |
| | | ElMessage.warning('请è¾å
¥è¦ç¼ç çå
容') |
| | | return |
| | | ElMessage.warning("请è¾å
¥è¦ç¼ç çå
容"); |
| | | return; |
| | | } |
| | | |
| | | generating.value = true |
| | | generating.value = true; |
| | | |
| | | if (form.type === 'qrcode') { |
| | | if (form.type === "qrcode") { |
| | | // çæäºç»´ç |
| | | generatedCodeUrl.value = await QRCode.toDataURL(form.content, { |
| | | width: form.size, |
| | | margin: form.margin, |
| | | color: { |
| | | dark: form.foregroundColor, |
| | | light: form.backgroundColor |
| | | light: form.backgroundColor, |
| | | }, |
| | | errorCorrectionLevel: 'M' |
| | | }) |
| | | errorCorrectionLevel: "M", |
| | | }); |
| | | } else { |
| | | // çæé²ä¼ªç ï¼ä½¿ç¨äºç»´ç ææ¯ï¼ä½å
å®¹æ ¼å¼ä¸åï¼ |
| | | const securityContent = generateSecurityCode(form.content) |
| | | const securityContent = generateSecurityCode(form.content); |
| | | generatedCodeUrl.value = await QRCode.toDataURL(securityContent, { |
| | | width: form.size, |
| | | margin: form.margin, |
| | | color: { |
| | | dark: form.foregroundColor, |
| | | light: form.backgroundColor |
| | | light: form.backgroundColor, |
| | | }, |
| | | errorCorrectionLevel: 'H' // é²ä¼ªç ä½¿ç¨æé«çº éçº§å« |
| | | }) |
| | | errorCorrectionLevel: "H", // é²ä¼ªç ä½¿ç¨æé«çº éçº§å« |
| | | }); |
| | | } |
| | | |
| | | generateTime.value = new Date().toLocaleString() |
| | | ElMessage.success('çææåï¼') |
| | | |
| | | generateTime.value = new Date().toLocaleString(); |
| | | ElMessage.success("çææåï¼"); |
| | | } catch (error) { |
| | | console.error('çæå¤±è´¥:', error) |
| | | ElMessage.error('çæå¤±è´¥ï¼' + error.message) |
| | | console.error("çæå¤±è´¥:", error); |
| | | ElMessage.error("çæå¤±è´¥ï¼" + error.message); |
| | | } finally { |
| | | generating.value = false |
| | | generating.value = false; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // çæé²ä¼ªç å
容 |
| | | const generateSecurityCode = (content) => { |
| | | const timestamp = Date.now() |
| | | const random = Math.random().toString(36).substr(2, 8) |
| | | return `SEC_${content}_${timestamp}_${random}` |
| | | } |
| | | const generateSecurityCode = content => { |
| | | const timestamp = Date.now(); |
| | | const random = Math.random().toString(36).substr(2, 8); |
| | | return `SEC_${content}_${timestamp}_${random}`; |
| | | }; |
| | | |
| | | // ä¸è½½çæçç |
| | | const downloadCode = () => { |
| | | if (!generatedCodeUrl.value) { |
| | | ElMessage.warning('请å
çæç ') |
| | | return |
| | | ElMessage.warning("请å
çæç "); |
| | | return; |
| | | } |
| | | |
| | | const a = document.createElement('a') |
| | | a.href = generatedCodeUrl.value |
| | | a.download = `${form.type === 'qrcode' ? 'äºç»´ç ' : 'é²ä¼ªç '}_${new Date().getTime()}.png` |
| | | document.body.appendChild(a) |
| | | a.click() |
| | | document.body.removeChild(a) |
| | | ElMessage.success('ä¸è½½æåï¼') |
| | | } |
| | | const a = document.createElement("a"); |
| | | a.href = generatedCodeUrl.value; |
| | | a.download = `${ |
| | | form.type === "qrcode" ? "äºç»´ç " : "é²ä¼ªç " |
| | | }_${new Date().getTime()}.png`; |
| | | document.body.appendChild(a); |
| | | a.click(); |
| | | document.body.removeChild(a); |
| | | ElMessage.success("ä¸è½½æåï¼"); |
| | | }; |
| | | |
| | | // å¤å¶å
容å°åªè´´æ¿ |
| | | const copyToClipboard = async () => { |
| | | try { |
| | | await navigator.clipboard.writeText(form.content) |
| | | ElMessage.success('å
容已å¤å¶å°åªè´´æ¿') |
| | | await navigator.clipboard.writeText(form.content); |
| | | ElMessage.success("å
容已å¤å¶å°åªè´´æ¿"); |
| | | } catch (error) { |
| | | // éçº§æ¹æ¡ |
| | | const textArea = document.createElement('textarea') |
| | | textArea.value = form.content |
| | | document.body.appendChild(textArea) |
| | | textArea.select() |
| | | document.execCommand('copy') |
| | | document.body.removeChild(textArea) |
| | | ElMessage.success('å
容已å¤å¶å°åªè´´æ¿') |
| | | const textArea = document.createElement("textarea"); |
| | | textArea.value = form.content; |
| | | document.body.appendChild(textArea); |
| | | textArea.select(); |
| | | document.execCommand("copy"); |
| | | document.body.removeChild(textArea); |
| | | ElMessage.success("å
容已å¤å¶å°åªè´´æ¿"); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // æå°ç |
| | | const printCode = () => { |
| | | if (!generatedCodeUrl.value) { |
| | | ElMessage.warning('请å
çæç ') |
| | | return |
| | | ElMessage.warning("请å
çæç "); |
| | | return; |
| | | } |
| | | |
| | | const printWindow = window.open('', '_blank') |
| | | const printWindow = window.open("", "_blank"); |
| | | printWindow.document.write(` |
| | | <html> |
| | | <head> |
| | | <title>æå°${form.type === 'qrcode' ? 'äºç»´ç ' : 'é²ä¼ªç '}</title> |
| | | <title>æå°${form.type === "qrcode" ? "äºç»´ç " : "é²ä¼ªç "}</title> |
| | | <style> |
| | | body { text-align: center; padding: 20px; } |
| | | img { max-width: 100%; height: auto; } |
| | |
| | | </style> |
| | | </head> |
| | | <body> |
| | | <h2>${form.type === 'qrcode' ? 'äºç»´ç ' : 'é²ä¼ªç '}</h2> |
| | | <img src="${generatedCodeUrl.value}" alt="${form.type === 'qrcode' ? 'äºç»´ç ' : 'é²ä¼ªç '}" /> |
| | | <h2>${form.type === "qrcode" ? "äºç»´ç " : "é²ä¼ªç "}</h2> |
| | | <img src="${generatedCodeUrl.value}" alt="${ |
| | | form.type === "qrcode" ? "äºç»´ç " : "é²ä¼ªç " |
| | | }" /> |
| | | <div class="info"> |
| | | <p><strong>å
容ï¼</strong>${form.content}</p> |
| | | <p><strong>çææ¶é´ï¼</strong>${generateTime.value}</p> |
| | | </div> |
| | | </body> |
| | | </html> |
| | | `) |
| | | printWindow.document.close() |
| | | printWindow.print() |
| | | } |
| | | `); |
| | | printWindow.document.close(); |
| | | printWindow.print(); |
| | | }; |
| | | |
| | | // é置表å |
| | | const resetForm = () => { |
| | | formRef.value.resetFields() |
| | | generatedCodeUrl.value = '' |
| | | generateTime.value = '' |
| | | batchCodes.value = [] |
| | | } |
| | | formRef.value.resetFields(); |
| | | generatedCodeUrl.value = ""; |
| | | generateTime.value = ""; |
| | | batchCodes.value = []; |
| | | }; |
| | | |
| | | // æ¹éçæ |
| | | const generateBatchCodes = async () => { |
| | | if (!batchForm.prefix.trim()) { |
| | | ElMessage.warning('请è¾å
¥åç¼') |
| | | return |
| | | ElMessage.warning("请è¾å
¥åç¼"); |
| | | return; |
| | | } |
| | | |
| | | batchCodes.value = [] |
| | | generating.value = true |
| | | batchCodes.value = []; |
| | | generating.value = true; |
| | | |
| | | try { |
| | | for (let i = 0; i < batchForm.quantity; i++) { |
| | | const number = batchForm.startNumber + i |
| | | const content = `${batchForm.prefix}${number.toString().padStart(6, '0')}` |
| | | const number = batchForm.startNumber + i; |
| | | const content = `${batchForm.prefix}${number |
| | | .toString() |
| | | .padStart(6, "0")}`; |
| | | |
| | | let codeUrl |
| | | if (form.type === 'qrcode') { |
| | | let codeUrl; |
| | | if (form.type === "qrcode") { |
| | | codeUrl = await QRCode.toDataURL(content, { |
| | | width: form.size, |
| | | margin: form.margin, |
| | | color: { |
| | | dark: form.foregroundColor, |
| | | light: form.backgroundColor |
| | | } |
| | | }) |
| | | light: form.backgroundColor, |
| | | }, |
| | | }); |
| | | } else { |
| | | const securityContent = generateSecurityCode(content) |
| | | const securityContent = generateSecurityCode(content); |
| | | codeUrl = await QRCode.toDataURL(securityContent, { |
| | | width: form.size, |
| | | margin: form.margin, |
| | | color: { |
| | | dark: form.foregroundColor, |
| | | light: form.backgroundColor |
| | | } |
| | | }) |
| | | light: form.backgroundColor, |
| | | }, |
| | | }); |
| | | } |
| | | |
| | | batchCodes.value.push({ |
| | | content, |
| | | url: codeUrl |
| | | }) |
| | | url: codeUrl, |
| | | }); |
| | | } |
| | | |
| | | ElMessage.success(`æ¹éçæå®æï¼å
±çæ ${batchForm.quantity} 个ç `) |
| | | batchDialogVisible.value = false |
| | | |
| | | ElMessage.success(`æ¹éçæå®æï¼å
±çæ ${batchForm.quantity} 个ç `); |
| | | batchDialogVisible.value = false; |
| | | } catch (error) { |
| | | console.error('æ¹éçæå¤±è´¥:', error) |
| | | ElMessage.error('æ¹éçæå¤±è´¥ï¼' + error.message) |
| | | console.error("æ¹éçæå¤±è´¥:", error); |
| | | ElMessage.error("æ¹éçæå¤±è´¥ï¼" + error.message); |
| | | } finally { |
| | | generating.value = false |
| | | generating.value = false; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // ä¸è½½å个æ¹éçæçç |
| | | const downloadSingleCode = (code) => { |
| | | const a = document.createElement('a') |
| | | a.href = code.url |
| | | a.download = `${code.content}.png` |
| | | document.body.appendChild(a) |
| | | a.click() |
| | | document.body.removeChild(a) |
| | | } |
| | | const downloadSingleCode = code => { |
| | | const a = document.createElement("a"); |
| | | a.href = code.url; |
| | | a.download = `${code.content}.png`; |
| | | document.body.appendChild(a); |
| | | a.click(); |
| | | document.body.removeChild(a); |
| | | }; |
| | | |
| | | // ä¸è½½æææ¹éçæçç |
| | | const downloadAllCodes = async () => { |
| | | if (batchCodes.value.length === 0) { |
| | | ElMessage.warning('没æå¯ä¸è½½çç ') |
| | | return |
| | | ElMessage.warning("没æå¯ä¸è½½çç "); |
| | | return; |
| | | } |
| | | |
| | | try { |
| | | // 使ç¨JSZipæå
ä¸è½½ |
| | | const JSZip = await import('jszip') |
| | | const zip = new JSZip.default() |
| | | const JSZip = await import("jszip"); |
| | | const zip = new JSZip.default(); |
| | | |
| | | batchCodes.value.forEach((code, index) => { |
| | | // å°base64转æ¢ä¸ºblob |
| | | const base64Data = code.url.split(',')[1] |
| | | const byteCharacters = atob(base64Data) |
| | | const byteNumbers = new Array(byteCharacters.length) |
| | | const base64Data = code.url.split(",")[1]; |
| | | const byteCharacters = atob(base64Data); |
| | | const byteNumbers = new Array(byteCharacters.length); |
| | | for (let i = 0; i < byteCharacters.length; i++) { |
| | | byteNumbers[i] = byteCharacters.charCodeAt(i) |
| | | byteNumbers[i] = byteCharacters.charCodeAt(i); |
| | | } |
| | | const byteArray = new Uint8Array(byteNumbers) |
| | | const byteArray = new Uint8Array(byteNumbers); |
| | | |
| | | zip.file(`${code.content}.png`, byteArray) |
| | | }) |
| | | zip.file(`${code.content}.png`, byteArray); |
| | | }); |
| | | |
| | | const content = await zip.generateAsync({ type: 'blob' }) |
| | | const a = document.createElement('a') |
| | | a.href = URL.createObjectURL(content) |
| | | a.download = `æ¹é${form.type === 'qrcode' ? 'äºç»´ç ' : 'é²ä¼ªç '}_${new Date().getTime()}.zip` |
| | | document.body.appendChild(a) |
| | | a.click() |
| | | document.body.removeChild(a) |
| | | URL.revokeObjectURL(a.href) |
| | | const content = await zip.generateAsync({ type: "blob" }); |
| | | const a = document.createElement("a"); |
| | | a.href = URL.createObjectURL(content); |
| | | a.download = `æ¹é${ |
| | | form.type === "qrcode" ? "äºç»´ç " : "é²ä¼ªç " |
| | | }_${new Date().getTime()}.zip`; |
| | | document.body.appendChild(a); |
| | | a.click(); |
| | | document.body.removeChild(a); |
| | | URL.revokeObjectURL(a.href); |
| | | |
| | | ElMessage.success('æ¹éä¸è½½å®æï¼') |
| | | ElMessage.success("æ¹éä¸è½½å®æï¼"); |
| | | } catch (error) { |
| | | console.error('æ¹éä¸è½½å¤±è´¥:', error) |
| | | ElMessage.error('æ¹éä¸è½½å¤±è´¥ï¼è¯·é个ä¸è½½') |
| | | console.error("æ¹éä¸è½½å¤±è´¥:", error); |
| | | ElMessage.error("æ¹éä¸è½½å¤±è´¥ï¼è¯·é个ä¸è½½"); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // æ¸
空æ¹éçæç»æ |
| | | const clearBatchCodes = () => { |
| | | batchCodes.value = [] |
| | | } |
| | | batchCodes.value = []; |
| | | }; |
| | | |
| | | // æ´é²æ¹æ³ç»ç¶ç»ä»¶ |
| | | defineExpose({ |
| | | generateCode, |
| | | downloadCode, |
| | | resetForm, |
| | | form |
| | | }) |
| | | form, |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | |
| | | _modelForm.model = _modelForm.otherModel; |
| | | } |
| | | delete _modelForm.otherModel; |
| | | // å°éä¸çæºå¨æ°ç»è½¬æ¢ä¸ºéå·åéçå符串 |
| | | // ç¡®ä¿ speculativeTradingName æ¯æ°ç»ç±»åï¼ç¶å转æ¢ä¸ºéå·åéçå符串 |
| | | let speculativeTradingNameValue = modelForm.value.speculativeTradingName; |
| | | if (!Array.isArray(speculativeTradingNameValue)) { |
| | | // 妿䏿¯æ°ç»ï¼è½¬æ¢ä¸ºæ°ç» |
| | | speculativeTradingNameValue = speculativeTradingNameValue.split(',').filter(item => item); |
| | | } |
| | | const submitData = { |
| | | ..._modelForm, |
| | | productId: currentId.value, |
| | | speculativeTradingName: modelForm.value.speculativeTradingName.join(',') |
| | | speculativeTradingName: speculativeTradingNameValue.join(',') |
| | | }; |
| | | addOrEditProductModel(submitData).then((res) => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | |
| | | <div class="table_list"> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="tableColumn" |
| | | :column="tableColumnCopy" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | |
| | | <script setup> |
| | | import FileList from "./fileList.vue"; |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import {onMounted, ref} from "vue"; |
| | | import {onMounted, ref, computed} from "vue"; |
| | | import {ElMessageBox} from "element-plus"; |
| | | import InfoFormDia from "@/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue"; |
| | | import ApprovalDia from "@/views/collaborativeApproval/approvalProcess/components/approvalDia.vue"; |
| | |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | const tableColumnCopy = computed(()=>{ |
| | | if(!tableColumn.value||!tableColumn.value.length){ |
| | | return [] |
| | | } |
| | | let tabIndex = -1; |
| | | tableColumn.value.map((item,_index) => { |
| | | if(props.approveType != 4&&item.prop == 'price'){ |
| | | tabIndex = _index |
| | | } |
| | | }) |
| | | if(tabIndex != -1){ |
| | | tableColumn.value.splice(tabIndex, 1) |
| | | return tableColumn.value |
| | | }else{ |
| | | return tableColumn.value |
| | | } |
| | | }) |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "审æ¹ç¶æ", |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <el-tabs v-model="activeTab" type="border-card"> |
| | | <el-tabs v-model="activeTab" |
| | | type="border-card"> |
| | | <!-- åæè®¾ç½® --> |
| | | <el-tab-pane label="åæè®¾ç½®" name="holiday"> |
| | | <el-tab-pane label="åæè®¾ç½®" |
| | | name="holiday"> |
| | | <div class="tab-content"> |
| | | <el-button type="primary" @click="openDialog('holiday', 'add')">æ°å¢åæ</el-button> |
| | | |
| | | <el-table :data="holidayData" border style="width: 100%; margin-top: 20px;"> |
| | | <el-table-column prop="name" label="åæåç§°" /> |
| | | <el-table-column prop="type" label="åæç±»å"> |
| | | <el-button type="primary" |
| | | @click="openDialog('holiday', 'add')">æ°å¢åæ</el-button> |
| | | <el-table :data="holidayData" |
| | | border |
| | | style="width: 100%; margin-top: 20px;"> |
| | | <el-table-column prop="name" |
| | | label="åæåç§°" /> |
| | | <el-table-column prop="type" |
| | | label="åæç±»å"> |
| | | <template #default="scope"> |
| | | <el-tag :type="getTagType(scope.row.type)">{{ getTypeLabel(scope.row.type) }}</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="startDate" label="å¼å§æ¥æ" /> |
| | | <el-table-column prop="endDate" label="ç»ææ¥æ" /> |
| | | <el-table-column prop="days" label="天æ°" align="center" /> |
| | | <el-table-column prop="status" label="ç¶æ" > |
| | | <el-table-column prop="startDate" |
| | | label="å¼å§æ¥æ" /> |
| | | <el-table-column prop="endDate" |
| | | label="ç»ææ¥æ" /> |
| | | <el-table-column prop="days" |
| | | label="天æ°" |
| | | align="center" /> |
| | | <el-table-column prop="status" |
| | | 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-column label="æä½" fixed="right"> |
| | | <el-table-column label="æä½" |
| | | fixed="right"> |
| | | <template #default="scope"> |
| | | <el-button type="primary" size="small" @click="openDialog('holiday', 'edit', scope.row)">ç¼è¾</el-button> |
| | | <el-button type="danger" size="small" @click="deleteItem('holiday', scope.row)">å é¤</el-button> |
| | | <el-button type="primary" |
| | | size="small" |
| | | @click="openDialog('holiday', 'edit', scope.row)">ç¼è¾</el-button> |
| | | <el-button type="danger" |
| | | size="small" |
| | | @click="deleteItem('holiday', scope.row)">å é¤</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </el-tab-pane> |
| | | |
| | | <!-- å¹´å设置 --> |
| | | <el-tab-pane label="å¹´å设置" name="annual"> |
| | | <el-tab-pane label="å¹´å设置" |
| | | name="annual"> |
| | | <div class="tab-content"> |
| | | <el-button type="primary" @click="openDialog('annual', 'add')">æ°å¢å¹´åè§å</el-button> |
| | | |
| | | <el-table :data="annualData" border style="width: 100%; margin-top: 20px;"> |
| | | <el-table-column prop="employeeType" label="å工类å"> |
| | | <el-button type="primary" |
| | | @click="openDialog('annual', 'add')">æ°å¢å¹´åè§å</el-button> |
| | | <el-table :data="annualData" |
| | | border |
| | | style="width: 100%; margin-top: 20px;"> |
| | | <el-table-column prop="employeeType" |
| | | label="å工类å"> |
| | | <template #default="scope"> |
| | | <el-tag :type="getTagType(scope.row.employeeType)">{{ getTypeLabel(scope.row.employeeType) }}</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="workYears" label="å·¥ä½å¹´é" /> |
| | | <el-table-column prop="annualDays" label="å¹´å天æ°" align="center" /> |
| | | <el-table-column prop="maxCarryOver" label="æå¤§ç»è½¬å¤©æ°" align="center" /> |
| | | <el-table-column prop="status" label="ç¶æ"> |
| | | <el-table-column prop="workYears" |
| | | label="å·¥ä½å¹´é" /> |
| | | <el-table-column prop="annualDays" |
| | | label="å¹´å天æ°" |
| | | align="center" /> |
| | | <el-table-column prop="maxCarryOver" |
| | | label="æå¤§ç»è½¬å¤©æ°" |
| | | align="center" /> |
| | | <el-table-column prop="status" |
| | | 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-column label="æä½" fixed="right"> |
| | | <el-table-column label="æä½" |
| | | fixed="right"> |
| | | <template #default="scope"> |
| | | <el-button type="primary" size="small" @click="openDialog('annual', 'edit', scope.row)">ç¼è¾</el-button> |
| | | <el-button type="danger" size="small" @click="deleteItem('annual', scope.row)">å é¤</el-button> |
| | | <el-button type="primary" |
| | | size="small" |
| | | @click="openDialog('annual', 'edit', scope.row)">ç¼è¾</el-button> |
| | | <el-button type="danger" |
| | | size="small" |
| | | @click="deleteItem('annual', scope.row)">å é¤</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </el-tab-pane> |
| | | |
| | | <!-- å ç设置 --> |
| | | <el-tab-pane label="å ç设置" name="overtime"> |
| | | <el-tab-pane label="å ç设置" |
| | | name="overtime"> |
| | | <div class="tab-content"> |
| | | <el-button type="primary" @click="openDialog('overtime', 'add')">æ°å¢å çè§å</el-button> |
| | | |
| | | <el-table :data="overtimeData" border style="width: 100%; margin-top: 20px;"> |
| | | <el-table-column prop="name" label="è§ååç§°" /> |
| | | <el-table-column prop="type" label="å çç±»å" > |
| | | <el-button type="primary" |
| | | @click="openDialog('overtime', 'add')">æ°å¢å çè§å</el-button> |
| | | <el-table :data="overtimeData" |
| | | border |
| | | style="width: 100%; margin-top: 20px;"> |
| | | <el-table-column prop="name" |
| | | label="è§ååç§°" /> |
| | | <el-table-column prop="type" |
| | | label="å çç±»å"> |
| | | <template #default="scope"> |
| | | <el-tag :type="getTagType(scope.row.type)">{{ getTypeLabel(scope.row.type) }}</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="startTime" label="å¼å§æ¶é´" /> |
| | | <el-table-column prop="endTime" label="ç»ææ¶é´" /> |
| | | <el-table-column prop="rate" label="åç" align="center" /> |
| | | <el-table-column prop="status" label="ç¶æ" > |
| | | <el-table-column prop="startTime" |
| | | label="å¼å§æ¶é´" /> |
| | | <el-table-column prop="endTime" |
| | | label="ç»ææ¶é´" /> |
| | | <el-table-column prop="rate" |
| | | label="åç" |
| | | align="center" /> |
| | | <el-table-column prop="status" |
| | | 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-column label="æä½" fixed="right"> |
| | | <el-table-column label="æä½" |
| | | fixed="right"> |
| | | <template #default="scope"> |
| | | <el-button type="primary" size="small" @click="openDialog('overtime', 'edit', scope.row)">ç¼è¾</el-button> |
| | | <el-button type="danger" size="small" @click="deleteItem('overtime', scope.row)">å é¤</el-button> |
| | | <el-button type="primary" |
| | | size="small" |
| | | @click="openDialog('overtime', 'edit', scope.row)">ç¼è¾</el-button> |
| | | <el-button type="danger" |
| | | size="small" |
| | | @click="deleteItem('overtime', scope.row)">å é¤</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </el-tab-pane> |
| | | |
| | | <!-- ä¸çæ¶é´è®¾ç½® --> |
| | | <el-tab-pane label="ä¸çæ¶é´è®¾ç½®" name="worktime"> |
| | | <el-tab-pane label="ä¸çæ¶é´è®¾ç½®" |
| | | name="worktime"> |
| | | <div class="tab-content"> |
| | | <el-button type="primary" @click="openDialog('worktime', 'add')">æ°å¢æ¶é´æ®µ</el-button> |
| | | |
| | | <el-table :data="worktimeData" border style="width: 100%; margin-top: 20px;"> |
| | | <el-table-column prop="name" label="æ¶é´æ®µåç§°" /> |
| | | <el-table-column prop="startTime" label="ä¸çæ¶é´"/> |
| | | <el-table-column prop="endTime" label="ä¸çæ¶é´" /> |
| | | <el-table-column prop="flexibleStart" label="å¼¹æ§ä¸ç"> |
| | | <el-button type="primary" |
| | | @click="openDialog('worktime', 'add')">æ°å¢æ¶é´æ®µ</el-button> |
| | | <el-table :data="worktimeData" |
| | | border |
| | | style="width: 100%; margin-top: 20px;"> |
| | | <el-table-column prop="name" |
| | | label="æ¶é´æ®µåç§°" /> |
| | | <el-table-column prop="startTime" |
| | | label="ä¸çæ¶é´" /> |
| | | <el-table-column prop="endTime" |
| | | label="ä¸çæ¶é´" /> |
| | | <el-table-column prop="flexibleStart" |
| | | label="å¼¹æ§ä¸ç"> |
| | | <template #default="scope"> |
| | | <el-tag :type="scope.row.flexibleStart === 'true' ? 'success' : 'info'"> |
| | | {{ scope.row.flexibleStart === 'true' ? 'æ¯' : 'å¦' }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="flexibleMinutes" label="å¼¹æ§æ¶é´(åé)" width="120" align="center" /> |
| | | <el-table-column prop="status" label="ç¶æ" > |
| | | <el-table-column prop="flexibleMinutes" |
| | | label="å¼¹æ§æ¶é´(åé)" |
| | | width="120" |
| | | align="center" /> |
| | | <el-table-column prop="status" |
| | | 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-column label="æä½" fixed="right"> |
| | | <el-table-column label="æä½" |
| | | fixed="right"> |
| | | <template #default="scope"> |
| | | <el-button type="primary" size="small" @click="openDialog('worktime', 'edit', scope.row)">ç¼è¾</el-button> |
| | | <el-button type="danger" size="small" @click="deleteItem('worktime', scope.row)">å é¤</el-button> |
| | | <el-button type="primary" |
| | | size="small" |
| | | @click="openDialog('worktime', 'edit', scope.row)">ç¼è¾</el-button> |
| | | <el-button type="danger" |
| | | size="small" |
| | | @click="deleteItem('worktime', scope.row)">å é¤</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </el-tab-pane> |
| | | |
| | | <!-- æå¡è®°å½ --> |
| | | <el-tab-pane label="æå¡è®°å½" name="attendance"> |
| | | <el-tab-pane label="æå¡è®°å½" |
| | | name="attendance"> |
| | | <div class="tab-content"> |
| | | <div style="margin-bottom: 20px;"> |
| | | <el-date-picker |
| | | v-model="attendanceDate" |
| | | <el-date-picker v-model="attendanceDate" |
| | | type="date" |
| | | placeholder="éæ©æ¥æ" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | style="margin-right: 10px;" |
| | | @change="filterAttendanceData" |
| | | /> |
| | | <el-select |
| | | v-model="attendanceStatus" |
| | | @change="filterAttendanceData" /> |
| | | <el-select v-model="attendanceStatus" |
| | | placeholder="éæ©ç¶æ" |
| | | style="width: 120px; margin-right: 10px;" |
| | | @change="filterAttendanceData" |
| | | > |
| | | <el-option label="å
¨é¨" value="" /> |
| | | <el-option label="æ£å¸¸" value="normal" /> |
| | | <el-option label="è¿å°" value="late" /> |
| | | <el-option label="æ©é" value="early" /> |
| | | <el-option label="缺å¤" value="absent" /> |
| | | @change="filterAttendanceData"> |
| | | <el-option label="å
¨é¨" |
| | | value="" /> |
| | | <el-option label="æ£å¸¸" |
| | | value="normal" /> |
| | | <el-option label="è¿å°" |
| | | value="late" /> |
| | | <el-option label="æ©é" |
| | | value="early" /> |
| | | <el-option label="缺å¤" |
| | | value="absent" /> |
| | | </el-select> |
| | | <el-button type="primary" @click="exportAttendance">导åºè®°å½</el-button> |
| | | <el-button type="primary" |
| | | @click="exportAttendance">导åºè®°å½</el-button> |
| | | </div> |
| | | |
| | | <el-table :data="filteredAttendanceData" border style="width: 100%;"> |
| | | <el-table-column prop="employeeName" label="åå·¥å§å" width="120" /> |
| | | <el-table-column prop="department" label="é¨é¨" width="120" /> |
| | | <el-table-column prop="date" label="æ¥æ" width="120" /> |
| | | <el-table-column prop="clockInTime" label="ä¸çæå¡" width="120" /> |
| | | <el-table-column prop="clockOutTime" label="ä¸çæå¡" width="120" /> |
| | | <el-table-column prop="workHours" label="工使¶é¿" width="100" align="center" /> |
| | | <el-table-column prop="status" label="ç¶æ" width="100" align="center"> |
| | | <el-table :data="filteredAttendanceData" |
| | | border |
| | | style="width: 100%;"> |
| | | <el-table-column prop="employeeName" |
| | | label="åå·¥å§å" |
| | | width="120" /> |
| | | <el-table-column prop="department" |
| | | label="é¨é¨" |
| | | width="120" /> |
| | | <el-table-column prop="date" |
| | | label="æ¥æ" |
| | | width="120" /> |
| | | <el-table-column prop="clockInTime" |
| | | label="ä¸çæå¡" |
| | | width="120" /> |
| | | <el-table-column prop="clockOutTime" |
| | | label="ä¸çæå¡" |
| | | width="120" /> |
| | | <el-table-column prop="workHours" |
| | | label="工使¶é¿" |
| | | width="100" |
| | | align="center" /> |
| | | <el-table-column prop="status" |
| | | label="ç¶æ" |
| | | width="100" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | <el-tag :type="getAttendanceTagType(scope.row.status)">{{ getAttendanceStatusLabel(scope.row.status) }}</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="location" label="æå¡å°ç¹" width="150" /> |
| | | <el-table-column prop="remark" label="夿³¨" min-width="150" /> |
| | | <el-table-column prop="location" |
| | | label="æå¡å°ç¹" |
| | | width="150" /> |
| | | <el-table-column prop="remark" |
| | | label="夿³¨" |
| | | min-width="150" /> |
| | | </el-table> |
| | | </div> |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | | |
| | | <!-- éç¨å¼¹çª --> |
| | | <el-dialog v-model="dialogVisible" :title="dialogTitle" width="600px"> |
| | | <el-form ref="formRef" :model="form" :rules="rules" label-width="100px"> |
| | | <el-form-item label="åç§°" prop="name" v-if="currentType !== 'annual'"> |
| | | <el-input v-model="form.name" placeholder="请è¾å
¥åç§°" /> |
| | | <el-dialog v-model="dialogVisible" |
| | | :title="dialogTitle" |
| | | width="600px"> |
| | | <el-form ref="formRef" |
| | | :model="form" |
| | | :rules="rules" |
| | | label-width="100px"> |
| | | <el-form-item label="åç§°" |
| | | prop="name" |
| | | v-if="currentType !== 'annual'"> |
| | | <el-input v-model="form.name" |
| | | placeholder="请è¾å
¥åç§°" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="ç±»å" prop="type" v-if="currentType === 'holiday' || currentType === 'overtime'"> |
| | | <el-select v-model="form.type" placeholder="è¯·éæ©ç±»å" style="width: 100%"> |
| | | <el-option |
| | | v-for="option in getTypeOptions()" |
| | | <el-form-item label="ç±»å" |
| | | prop="type" |
| | | v-if="currentType === 'holiday' || currentType === 'overtime'"> |
| | | <el-select v-model="form.type" |
| | | placeholder="è¯·éæ©ç±»å" |
| | | style="width: 100%"> |
| | | <el-option v-for="option in getTypeOptions()" |
| | | :key="option.value" |
| | | :label="option.label" |
| | | :value="option.value" |
| | | /> |
| | | :value="option.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="å工类å" prop="employeeType" v-if="currentType === 'annual'"> |
| | | <el-select v-model="form.employeeType" placeholder="è¯·éæ©å工类å" style="width: 100%"> |
| | | <el-form-item label="å工类å" |
| | | prop="employeeType" |
| | | v-if="currentType === 'annual'"> |
| | | <el-select v-model="form.employeeType" |
| | | placeholder="è¯·éæ©å工类å" |
| | | style="width: 100%"> |
| | | <!-- <el-option label="æ£å¼åå·¥" value="regular" /> |
| | | <el-option label="è¯ç¨æåå·¥" value="probation" /> |
| | | <el-option label="å®ä¹ ç" value="intern" /> --> |
| | | <el-option |
| | | v-for="option in getTypeOptions()" |
| | | <el-option v-for="option in getTypeOptions()" |
| | | :key="option.value" |
| | | :label="option.label" |
| | | :value="option.value" |
| | | /> |
| | | :value="option.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="å·¥ä½å¹´é" prop="workYears" v-if="currentType === 'annual'"> |
| | | <el-input v-model="form.workYears" placeholder="å¦ï¼1-3å¹´ã3-5å¹´ç" /> |
| | | <el-form-item label="å·¥ä½å¹´é" |
| | | prop="workYears" |
| | | v-if="currentType === 'annual'"> |
| | | <el-input v-model="form.workYears" |
| | | placeholder="å¦ï¼1-3å¹´ã3-5å¹´ç" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="å¹´å天æ°" prop="annualDays" v-if="currentType === 'annual'"> |
| | | <el-input-number v-model="form.annualDays" :min="0" :max="365" style="width: 100%" /> |
| | | <el-form-item label="å¹´å天æ°" |
| | | prop="annualDays" |
| | | v-if="currentType === 'annual'"> |
| | | <el-input-number v-model="form.annualDays" |
| | | :min="0" |
| | | :max="365" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="æå¤§ç»è½¬å¤©æ°" prop="maxCarryOver" v-if="currentType === 'annual'"> |
| | | <el-input-number v-model="form.maxCarryOver" :min="0" :max="30" style="width: 100%" /> |
| | | <el-form-item label="æå¤§ç»è½¬å¤©æ°" |
| | | prop="maxCarryOver" |
| | | v-if="currentType === 'annual'"> |
| | | <el-input-number v-model="form.maxCarryOver" |
| | | :min="0" |
| | | :max="30" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="æ¥æèå´" prop="dateRange" v-if="currentType === 'holiday'"> |
| | | <el-date-picker |
| | | v-model="form.dateRange" |
| | | <el-form-item label="æ¥æèå´" |
| | | prop="dateRange" |
| | | v-if="currentType === 'holiday'"> |
| | | <el-date-picker v-model="form.dateRange" |
| | | type="daterange" |
| | | range-separator="è³" |
| | | start-placeholder="å¼å§æ¥æ" |
| | | end-placeholder="ç»ææ¥æ" |
| | | style="width: 100%" |
| | | @change="calculateDays" |
| | | /> |
| | | @change="calculateDays" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="天æ°" prop="days" v-if="currentType === 'holiday'"> |
| | | <el-input-number v-model="form.days" :min="0" style="width: 100%" /> |
| | | <el-form-item label="天æ°" |
| | | prop="days" |
| | | v-if="currentType === 'holiday'"> |
| | | <el-input-number v-model="form.days" |
| | | :min="0" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="å¼å§æ¶é´" prop="startTime" v-if="currentType === 'overtime'"> |
| | | <el-time-picker |
| | | v-model="form.startTime" |
| | | <el-form-item label="å¼å§æ¶é´" |
| | | prop="startTime" |
| | | v-if="currentType === 'overtime'"> |
| | | <el-time-picker v-model="form.startTime" |
| | | placeholder="å¼å§æ¶é´" |
| | | format="HH:mm" |
| | | value-format="HH:mm" |
| | | style="width: 100%" |
| | | @change="validateTimeField('startTime')" |
| | | /> |
| | | @change="validateTimeField('startTime')" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="ç»ææ¶é´" prop="endTime" v-if="currentType === 'overtime'"> |
| | | <el-time-picker |
| | | v-model="form.endTime" |
| | | <el-form-item label="ç»ææ¶é´" |
| | | prop="endTime" |
| | | v-if="currentType === 'overtime'"> |
| | | <el-time-picker v-model="form.endTime" |
| | | placeholder="ç»ææ¶é´" |
| | | format="HH:mm" |
| | | value-format="HH:mm" |
| | | style="width: 100%" |
| | | @change="validateTimeField('endTime')" |
| | | /> |
| | | @change="validateTimeField('endTime')" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="åç" prop="rate" v-if="currentType === 'overtime'"> |
| | | <el-input-number v-model="form.rate" :min="1" :max="3" :step="0.5" style="width: 100%" /> |
| | | <el-form-item label="åç" |
| | | prop="rate" |
| | | v-if="currentType === 'overtime'"> |
| | | <el-input-number v-model="form.rate" |
| | | :min="1" |
| | | :max="3" |
| | | :step="0.5" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="ä¸çæ¶é´" prop="workStartTime" v-if="currentType === 'worktime'"> |
| | | <el-time-picker |
| | | v-model="form.workStartTime" |
| | | <el-form-item label="ä¸çæ¶é´" |
| | | prop="workStartTime" |
| | | v-if="currentType === 'worktime'"> |
| | | <el-time-picker v-model="form.workStartTime" |
| | | placeholder="ä¸çæ¶é´" |
| | | format="HH:mm" |
| | | value-format="HH:mm" |
| | | style="width: 100%" |
| | | @change="validateTimeField('workStartTime')" |
| | | /> |
| | | @change="validateTimeField('workStartTime')" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="ä¸çæ¶é´" prop="workEndTime" v-if="currentType === 'worktime'"> |
| | | <el-time-picker |
| | | v-model="form.workEndTime" |
| | | <el-form-item label="ä¸çæ¶é´" |
| | | prop="workEndTime" |
| | | v-if="currentType === 'worktime'"> |
| | | <el-time-picker v-model="form.workEndTime" |
| | | placeholder="ä¸çæ¶é´" |
| | | format="HH:mm" |
| | | value-format="HH:mm" |
| | | style="width: 100%" |
| | | @change="validateTimeField('workEndTime')" |
| | | /> |
| | | @change="validateTimeField('workEndTime')" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="å¼¹æ§ä¸ç" prop="flexibleStart" v-if="currentType === 'worktime'"> |
| | | <el-form-item label="å¼¹æ§ä¸ç" |
| | | prop="flexibleStart" |
| | | v-if="currentType === 'worktime'"> |
| | | <el-switch v-model="form.flexibleStart" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="å¼¹æ§æ¶é´(åé)" prop="flexibleMinutes" v-if="currentType === 'worktime' && form.flexibleStart"> |
| | | <el-input-number v-model="form.flexibleMinutes" :min="0" :max="120" style="width: 100%" /> |
| | | <el-form-item label="å¼¹æ§æ¶é´(åé)" |
| | | prop="flexibleMinutes" |
| | | v-if="currentType === 'worktime' && form.flexibleStart"> |
| | | <el-input-number v-model="form.flexibleMinutes" |
| | | :min="0" |
| | | :max="120" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="ç¶æ" prop="status"> |
| | | <el-form-item label="ç¶æ" |
| | | prop="status"> |
| | | <el-radio-group v-model="form.status"> |
| | | <el-radio value="active">å¯ç¨</el-radio> |
| | | <el-radio value="inactive">åç¨</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="submitForm">ç¡®å®</el-button> |
| | | <el-button @click="dialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="submitForm">ç¡®å®</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted, onUnmounted } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { listHolidaySettings, addHolidaySettings, updateHolidaySettings, delHolidaySettings, listAnnualLeaveSettingList, addAnnualLeaveSetting, updateAnnualLeaveSetting, delAnnualLeaveSetting, listOvertimeSettingList, addOvertimeSetting, updateOvertimeSetting, delOvertimeSetting, listWorkingHoursSettingList, addWorkingHoursSetting, updateWorkingHoursSetting, delWorkingHoursSetting } from '@/api/collaborativeApproval/attendanceManagement.js' |
| | | import { ref, reactive, onMounted, onUnmounted } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import { |
| | | listHolidaySettings, |
| | | addHolidaySettings, |
| | | updateHolidaySettings, |
| | | delHolidaySettings, |
| | | listAnnualLeaveSettingList, |
| | | addAnnualLeaveSetting, |
| | | updateAnnualLeaveSetting, |
| | | delAnnualLeaveSetting, |
| | | listOvertimeSettingList, |
| | | addOvertimeSetting, |
| | | updateOvertimeSetting, |
| | | delOvertimeSetting, |
| | | listWorkingHoursSettingList, |
| | | addWorkingHoursSetting, |
| | | updateWorkingHoursSetting, |
| | | delWorkingHoursSetting, |
| | | } from "@/api/collaborativeApproval/attendanceManagement.js"; |
| | | |
| | | // å½åæ¿æ´»çæ ç¾é¡µ |
| | | const activeTab = ref('holiday') |
| | | const activeTab = ref("holiday"); |
| | | |
| | | // å¼¹çªç¸å
³ |
| | | const dialogVisible = ref(false) |
| | | const dialogTitle = ref('') |
| | | const currentType = ref('') |
| | | const currentAction = ref('') |
| | | const currentEditId = ref('') |
| | | const formRef = ref() |
| | | const dialogVisible = ref(false); |
| | | const dialogTitle = ref(""); |
| | | const currentType = ref(""); |
| | | const currentAction = ref(""); |
| | | const currentEditId = ref(""); |
| | | const formRef = ref(); |
| | | const page = { |
| | | current: 1, |
| | | size: 20, |
| | | total: 0, |
| | | } |
| | | const holidayData = ref([]) |
| | | const annualData = ref([]) |
| | | const overtimeData = ref([]) |
| | | const worktimeData = ref([]) |
| | | }; |
| | | const holidayData = ref([]); |
| | | const annualData = ref([]); |
| | | const overtimeData = ref([]); |
| | | const worktimeData = ref([]); |
| | | |
| | | // æå¡è®°å½ç¸å
³æ°æ® |
| | | const attendanceData = ref([]) |
| | | const filteredAttendanceData = ref([]) |
| | | const attendanceDate = ref('') |
| | | const attendanceStatus = ref('') |
| | | const attendanceData = ref([]); |
| | | const filteredAttendanceData = ref([]); |
| | | const attendanceDate = ref(""); |
| | | const attendanceStatus = ref(""); |
| | | |
| | | // è¡¨åæ°æ® |
| | | const form = reactive({ |
| | | name: '', |
| | | type: '', |
| | | name: "", |
| | | type: "", |
| | | dateRange: [], |
| | | startDate: '', |
| | | endDate: '', |
| | | startDate: "", |
| | | endDate: "", |
| | | days: 0, |
| | | employeeType: '', |
| | | workYears: '', |
| | | employeeType: "", |
| | | workYears: "", |
| | | annualDays: 0, |
| | | maxCarryOver: 0, |
| | | startTime: '', // å çå¼å§æ¶é´ |
| | | endTime: '', // å çç»ææ¶é´ |
| | | workStartTime: '', // ä¸çæ¶é´ |
| | | workEndTime: '', // ä¸çæ¶é´ |
| | | startTime: "", // å çå¼å§æ¶é´ |
| | | endTime: "", // å çç»ææ¶é´ |
| | | workStartTime: "", // ä¸çæ¶é´ |
| | | workEndTime: "", // ä¸çæ¶é´ |
| | | rate: 1.5, |
| | | flexibleStart: false, |
| | | flexibleMinutes: 30, |
| | | status: 'active' |
| | | }) |
| | | status: "active", |
| | | }); |
| | | |
| | | // 表åéªè¯è§å |
| | | const rules = { |
| | | name: [{ required: true, message: '请è¾å
¥åç§°', trigger: 'blur' }], |
| | | type: [{ required: true, message: 'è¯·éæ©ç±»å', trigger: 'change' }], |
| | | dateRange: [{ required: true, message: 'è¯·éæ©æ¥æèå´', trigger: 'change' }], |
| | | days: [{ required: true, message: '请è¾å
¥å¤©æ°', trigger: 'blur' }], |
| | | employeeType: [{ required: true, message: 'è¯·éæ©å工类å', trigger: 'change' }], |
| | | workYears: [{ required: true, message: '请è¾å
¥å·¥ä½å¹´é', trigger: 'blur' }], |
| | | annualDays: [{ required: true, message: '请è¾å
¥å¹´å天æ°', trigger: 'blur' }], |
| | | maxCarryOver: [{ required: true, message: '请è¾å
¥æå¤§ç»è½¬å¤©æ°', trigger: 'blur' }], |
| | | startTime: [{ |
| | | name: [{ required: true, message: "请è¾å
¥åç§°", trigger: "blur" }], |
| | | type: [{ required: true, message: "è¯·éæ©ç±»å", trigger: "change" }], |
| | | dateRange: [{ required: true, message: "è¯·éæ©æ¥æèå´", trigger: "change" }], |
| | | days: [{ required: true, message: "请è¾å
¥å¤©æ°", trigger: "blur" }], |
| | | employeeType: [ |
| | | { required: true, message: "è¯·éæ©å工类å", trigger: "change" }, |
| | | ], |
| | | workYears: [{ required: true, message: "请è¾å
¥å·¥ä½å¹´é", trigger: "blur" }], |
| | | annualDays: [{ required: true, message: "请è¾å
¥å¹´å天æ°", trigger: "blur" }], |
| | | maxCarryOver: [ |
| | | { required: true, message: "请è¾å
¥æå¤§ç»è½¬å¤©æ°", trigger: "blur" }, |
| | | ], |
| | | startTime: [ |
| | | { |
| | | required: true, |
| | | message: 'è¯·éæ©å¼å§æ¶é´', |
| | | trigger: 'change', |
| | | message: "è¯·éæ©å¼å§æ¶é´", |
| | | trigger: "change", |
| | | validator: (rule, value, callback) => { |
| | | if (!value) { |
| | | callback(new Error('è¯·éæ©å¼å§æ¶é´')) |
| | | callback(new Error("è¯·éæ©å¼å§æ¶é´")); |
| | | } else { |
| | | callback() |
| | | callback(); |
| | | } |
| | | } |
| | | }], |
| | | endTime: [{ |
| | | }, |
| | | }, |
| | | ], |
| | | endTime: [ |
| | | { |
| | | required: true, |
| | | message: 'è¯·éæ©ç»ææ¶é´', |
| | | trigger: 'change', |
| | | message: "è¯·éæ©ç»ææ¶é´", |
| | | trigger: "change", |
| | | validator: (rule, value, callback) => { |
| | | if (!value) { |
| | | callback(new Error('è¯·éæ©ç»ææ¶é´')) |
| | | callback(new Error("è¯·éæ©ç»ææ¶é´")); |
| | | } else { |
| | | callback() |
| | | callback(); |
| | | } |
| | | } |
| | | }], |
| | | workStartTime: [{ |
| | | }, |
| | | }, |
| | | ], |
| | | workStartTime: [ |
| | | { |
| | | required: true, |
| | | message: 'è¯·éæ©ä¸çæ¶é´', |
| | | trigger: 'change', |
| | | message: "è¯·éæ©ä¸çæ¶é´", |
| | | trigger: "change", |
| | | validator: (rule, value, callback) => { |
| | | if (!value) { |
| | | callback(new Error('è¯·éæ©ä¸çæ¶é´')) |
| | | callback(new Error("è¯·éæ©ä¸çæ¶é´")); |
| | | } else { |
| | | callback() |
| | | callback(); |
| | | } |
| | | } |
| | | }], |
| | | workEndTime: [{ |
| | | }, |
| | | }, |
| | | ], |
| | | workEndTime: [ |
| | | { |
| | | required: true, |
| | | message: 'è¯·éæ©ä¸çæ¶é´', |
| | | trigger: 'change', |
| | | message: "è¯·éæ©ä¸çæ¶é´", |
| | | trigger: "change", |
| | | validator: (rule, value, callback) => { |
| | | if (!value) { |
| | | callback(new Error('è¯·éæ©ä¸çæ¶é´')) |
| | | callback(new Error("è¯·éæ©ä¸çæ¶é´")); |
| | | } else { |
| | | callback() |
| | | callback(); |
| | | } |
| | | } |
| | | }], |
| | | rate: [{ required: true, message: '请è¾å
¥åç', trigger: 'blur' }] |
| | | } |
| | | }, |
| | | }, |
| | | ], |
| | | rate: [{ required: true, message: "请è¾å
¥åç", trigger: "blur" }], |
| | | }; |
| | | // å·¥å
·å½æ° |
| | | const getTagType = (type) => { |
| | | const getTagType = type => { |
| | | const tagMap = { |
| | | legal: 'success', adjustment: 'warning', special: 'info', company: 'primary', |
| | | weekday: 'primary', weekend: 'warning', holiday: 'danger', night: 'info', |
| | | regular: 'success', probation: 'info', intern: 'danger' |
| | | } |
| | | return tagMap[type] || 'info' |
| | | } |
| | | legal: "success", |
| | | adjustment: "warning", |
| | | special: "info", |
| | | company: "primary", |
| | | weekday: "primary", |
| | | weekend: "warning", |
| | | holiday: "danger", |
| | | night: "info", |
| | | regular: "success", |
| | | probation: "info", |
| | | intern: "danger", |
| | | }; |
| | | return tagMap[type] || "info"; |
| | | }; |
| | | |
| | | const getTypeLabel = (type) => { |
| | | const getTypeLabel = type => { |
| | | const labelMap = { |
| | | legal: 'æ³å®è忥', adjustment: 'è°ä¼æ¥', special: 'ç¹æ®åæ', company: 'å
¬å¸åæ', |
| | | weekday: '工使¥å ç', weekend: '卿«å ç', holiday: 'è忥å ç', night: 'æ·±å¤å ç', |
| | | regular: 'æ£å¼åå·¥', probation: 'è¯ç¨æåå·¥', intern: 'å®ä¹ ç' |
| | | } |
| | | return labelMap[type] || type |
| | | } |
| | | legal: "æ³å®è忥", |
| | | adjustment: "è°ä¼æ¥", |
| | | special: "ç¹æ®åæ", |
| | | company: "å
¬å¸åæ", |
| | | weekday: "工使¥å ç", |
| | | weekend: "卿«å ç", |
| | | holiday: "è忥å ç", |
| | | night: "æ·±å¤å ç", |
| | | regular: "æ£å¼åå·¥", |
| | | probation: "è¯ç¨æåå·¥", |
| | | intern: "å®ä¹ ç", |
| | | }; |
| | | return labelMap[type] || type; |
| | | }; |
| | | |
| | | // æå¡è®°å½ç¸å
³å·¥å
·å½æ° |
| | | const getAttendanceTagType = (status) => { |
| | | const getAttendanceTagType = status => { |
| | | const tagMap = { |
| | | normal: 'success', |
| | | late: 'warning', |
| | | early: 'warning', |
| | | absent: 'danger' |
| | | } |
| | | return tagMap[status] || 'info' |
| | | } |
| | | normal: "success", |
| | | late: "warning", |
| | | early: "warning", |
| | | absent: "danger", |
| | | }; |
| | | return tagMap[status] || "info"; |
| | | }; |
| | | |
| | | const getAttendanceStatusLabel = (status) => { |
| | | const getAttendanceStatusLabel = status => { |
| | | const labelMap = { |
| | | normal: 'æ£å¸¸', |
| | | late: 'è¿å°', |
| | | early: 'æ©é', |
| | | absent: '缺å¤' |
| | | } |
| | | return labelMap[status] || status |
| | | } |
| | | normal: "æ£å¸¸", |
| | | late: "è¿å°", |
| | | early: "æ©é", |
| | | absent: "缺å¤", |
| | | }; |
| | | return labelMap[status] || status; |
| | | }; |
| | | |
| | | const getTypeOptions = () => { |
| | | if (currentType.value === 'holiday') { |
| | | if (currentType.value === "holiday") { |
| | | return [ |
| | | { label: 'æ³å®è忥', value: 'legal' }, |
| | | { label: 'è°ä¼æ¥', value: 'adjustment' }, |
| | | { label: 'ç¹æ®åæ', value: 'special' }, |
| | | { label: 'å
¬å¸åæ', value: 'company' } |
| | | ] |
| | | } else if (currentType.value === 'overtime') { |
| | | { label: "æ³å®è忥", value: "legal" }, |
| | | { label: "è°ä¼æ¥", value: "adjustment" }, |
| | | { label: "ç¹æ®åæ", value: "special" }, |
| | | { label: "å
¬å¸åæ", value: "company" }, |
| | | ]; |
| | | } else if (currentType.value === "overtime") { |
| | | return [ |
| | | { label: '工使¥å ç', value: 'weekday' }, |
| | | { label: '卿«å ç', value: 'weekend' }, |
| | | { label: 'è忥å ç', value: 'holiday' }, |
| | | { label: 'æ·±å¤å ç', value: 'night' } |
| | | ] |
| | | } else if (currentType.value === 'annual') { |
| | | { label: "工使¥å ç", value: "weekday" }, |
| | | { label: "卿«å ç", value: "weekend" }, |
| | | { label: "è忥å ç", value: "holiday" }, |
| | | { label: "æ·±å¤å ç", value: "night" }, |
| | | ]; |
| | | } else if (currentType.value === "annual") { |
| | | return [ |
| | | { label: 'æ£å¼åå·¥', value: 'regular' }, |
| | | { label: 'è¯ç¨æåå·¥', value: 'probation' }, |
| | | { label: 'å®ä¹ ç', value: 'intern' } |
| | | ] |
| | | { label: "æ£å¼åå·¥", value: "regular" }, |
| | | { label: "è¯ç¨æåå·¥", value: "probation" }, |
| | | { label: "å®ä¹ ç", value: "intern" }, |
| | | ]; |
| | | } |
| | | return [] |
| | | } |
| | | return []; |
| | | }; |
| | | |
| | | // 计ç®åæå¤©æ° |
| | | const calculateDays = () => { |
| | | try { |
| | | if (form.dateRange && form.dateRange.length === 2 && form.dateRange[0] && form.dateRange[1]) { |
| | | const start = new Date(form.dateRange[0]) |
| | | const end = new Date(form.dateRange[1]) |
| | | form.startDate = start.toISOString().split('T')[0] |
| | | form.endDate = end.toISOString().split('T')[0] |
| | | if ( |
| | | form.dateRange && |
| | | form.dateRange.length === 2 && |
| | | form.dateRange[0] && |
| | | form.dateRange[1] |
| | | ) { |
| | | const start = new Date(form.dateRange[0]); |
| | | const end = new Date(form.dateRange[1]); |
| | | form.startDate = start.toISOString().split("T")[0]; |
| | | form.endDate = end.toISOString().split("T")[0]; |
| | | |
| | | if (isNaN(start.getTime()) || isNaN(end.getTime())) { |
| | | console.warn('æ æçæ¥ææ ¼å¼') |
| | | return |
| | | console.warn("æ æçæ¥ææ ¼å¼"); |
| | | return; |
| | | } |
| | | |
| | | const diffTime = Math.abs(end - start) |
| | | const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)) + 1 |
| | | form.days = diffDays |
| | | const diffTime = Math.abs(end - start); |
| | | const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)) + 1; |
| | | form.days = diffDays; |
| | | } |
| | | } catch (error) { |
| | | console.error('计ç®å¤©æ°å¤±è´¥:', error) |
| | | console.error("计ç®å¤©æ°å¤±è´¥:", error); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // éªè¯æ¶é´æ ¼å¼ |
| | | // const validateTime = (time) => { |
| | |
| | | // } |
| | | |
| | | // éªè¯æ¶é´å段 |
| | | const validateTimeField = (fieldName) => { |
| | | const validateTimeField = fieldName => { |
| | | try { |
| | | const value = form[fieldName] |
| | | if (value && typeof value === 'object' && value.hour !== undefined) { |
| | | const value = form[fieldName]; |
| | | if (value && typeof value === "object" && value.hour !== undefined) { |
| | | // å¦ææ¯æ¶é´å¯¹è±¡ï¼è½¬æ¢ä¸ºåç¬¦ä¸²æ ¼å¼ |
| | | const hours = value.hour.toString().padStart(2, '0') |
| | | const minutes = value.minute.toString().padStart(2, '0') |
| | | form[fieldName] = `${hours}:${minutes}` |
| | | const hours = value.hour.toString().padStart(2, "0"); |
| | | const minutes = value.minute.toString().padStart(2, "0"); |
| | | form[fieldName] = `${hours}:${minutes}`; |
| | | } |
| | | } catch (error) { |
| | | console.error(`éªè¯æ¶é´å段 ${fieldName} 失败:`, error) |
| | | form[fieldName] = '' |
| | | console.error(`éªè¯æ¶é´å段 ${fieldName} 失败:`, error); |
| | | form[fieldName] = ""; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // æå¼å¼¹çª |
| | | const openDialog = (type, action, row = null) => { |
| | | try { |
| | | currentType.value = type |
| | | currentAction.value = action |
| | | currentType.value = type; |
| | | currentAction.value = action; |
| | | |
| | | if (action === 'add') { |
| | | dialogTitle.value = `æ°å¢${getTypeName(type)}` |
| | | currentEditId.value = '' |
| | | resetForm() |
| | | } else if (action === 'edit' && row) { |
| | | dialogTitle.value = `ç¼è¾${getTypeName(type)}` |
| | | currentEditId.value = row.id |
| | | fillForm(row) |
| | | if (action === "add") { |
| | | dialogTitle.value = `æ°å¢${getTypeName(type)}`; |
| | | currentEditId.value = ""; |
| | | resetForm(); |
| | | } else if (action === "edit" && row) { |
| | | dialogTitle.value = `ç¼è¾${getTypeName(type)}`; |
| | | currentEditId.value = row.id; |
| | | fillForm(row); |
| | | } |
| | | |
| | | dialogVisible.value = true |
| | | dialogVisible.value = true; |
| | | } catch (error) { |
| | | console.error('æå¼å¼¹çªå¤±è´¥:', error) |
| | | ElMessage.error('æå¼å¼¹çªå¤±è´¥ï¼è¯·éè¯') |
| | | console.error("æå¼å¼¹çªå¤±è´¥:", error); |
| | | ElMessage.error("æå¼å¼¹çªå¤±è´¥ï¼è¯·éè¯"); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | const getTypeName = (type) => { |
| | | const getTypeName = type => { |
| | | const nameMap = { |
| | | holiday: 'åæ', |
| | | annual: 'å¹´åè§å', |
| | | overtime: 'å çè§å', |
| | | worktime: 'æ¶é´æ®µ' |
| | | } |
| | | return nameMap[type] || '' |
| | | } |
| | | holiday: "åæ", |
| | | annual: "å¹´åè§å", |
| | | overtime: "å çè§å", |
| | | worktime: "æ¶é´æ®µ", |
| | | }; |
| | | return nameMap[type] || ""; |
| | | }; |
| | | |
| | | const resetForm = () => { |
| | | Object.assign(form, { |
| | | name: '', |
| | | type: '', |
| | | name: "", |
| | | type: "", |
| | | dateRange: [], |
| | | startDate: '', |
| | | endDate: '', |
| | | startDate: "", |
| | | endDate: "", |
| | | days: 0, |
| | | employeeType: '', |
| | | workYears: '', |
| | | employeeType: "", |
| | | workYears: "", |
| | | annualDays: 0, |
| | | maxCarryOver: 0, |
| | | startTime: '', |
| | | endTime: '', |
| | | workStartTime: '', |
| | | workEndTime: '', |
| | | startTime: "", |
| | | endTime: "", |
| | | workStartTime: "", |
| | | workEndTime: "", |
| | | rate: 1.5, |
| | | flexibleStart: false, |
| | | flexibleMinutes: 30, |
| | | status: 'active' |
| | | }) |
| | | } |
| | | status: "active", |
| | | }); |
| | | }; |
| | | |
| | | const fillForm = (row) => { |
| | | if (currentType.value === 'holiday') { |
| | | const fillForm = row => { |
| | | if (currentType.value === "holiday") { |
| | | Object.assign(form, { |
| | | name: row.name, |
| | | type: row.type, |
| | |
| | | startDate: row.startDate, |
| | | endDate: row.endDate, |
| | | days: row.days, |
| | | status: row.status |
| | | }) |
| | | } else if (currentType.value === 'annual') { |
| | | status: row.status, |
| | | }); |
| | | } else if (currentType.value === "annual") { |
| | | Object.assign(form, { |
| | | employeeType: row.employeeType, |
| | | workYears: row.workYears, |
| | | annualDays: row.annualDays, |
| | | maxCarryOver: row.maxCarryOver, |
| | | status: row.status |
| | | }) |
| | | } else if (currentType.value === 'overtime') { |
| | | status: row.status, |
| | | }); |
| | | } else if (currentType.value === "overtime") { |
| | | Object.assign(form, { |
| | | name: row.name, |
| | | type: row.type, |
| | | startTime: row.startTime || '', |
| | | endTime: row.endTime || '', |
| | | startTime: row.startTime || "", |
| | | endTime: row.endTime || "", |
| | | rate: row.rate, |
| | | status: row.status |
| | | }) |
| | | } else if (currentType.value === 'worktime') { |
| | | status: row.status, |
| | | }); |
| | | } else if (currentType.value === "worktime") { |
| | | Object.assign(form, { |
| | | name: row.name, |
| | | workStartTime: row.startTime || '', |
| | | workEndTime: row.endTime || '', |
| | | workStartTime: row.startTime || "", |
| | | workEndTime: row.endTime || "", |
| | | flexibleStart: row.flexibleStart, |
| | | flexibleMinutes: row.flexibleMinutes, |
| | | status: row.status |
| | | }) |
| | | status: row.status, |
| | | }); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // æäº¤è¡¨å |
| | | const submitForm = async () => { |
| | | try { |
| | | if (!formRef.value) { |
| | | ElMessage.error('表åå¼ç¨ä¸åå¨') |
| | | return |
| | | ElMessage.error("表åå¼ç¨ä¸åå¨"); |
| | | return; |
| | | } |
| | | |
| | | await formRef.value.validate() |
| | | await formRef.value.validate(); |
| | | |
| | | if (currentAction.value === 'add') { |
| | | addItem() |
| | | } else if (currentAction.value === 'edit') { |
| | | editItem() |
| | | if (currentAction.value === "add") { |
| | | addItem(); |
| | | } else if (currentAction.value === "edit") { |
| | | editItem(); |
| | | } |
| | | |
| | | dialogVisible.value = false |
| | | ElMessage.success('æä½æå') |
| | | dialogVisible.value = false; |
| | | ElMessage.success("æä½æå"); |
| | | } catch (error) { |
| | | console.error('表åéªè¯å¤±è´¥:', error) |
| | | ElMessage.error('表åéªè¯å¤±è´¥ï¼è¯·æ£æ¥è¾å
¥') |
| | | console.error("表åéªè¯å¤±è´¥:", error); |
| | | ElMessage.error("表åéªè¯å¤±è´¥ï¼è¯·æ£æ¥è¾å
¥"); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | const addItem = () => { |
| | | |
| | | if (currentType.value === 'holiday') { |
| | | if (currentType.value === "holiday") { |
| | | const params = { |
| | | name: form.name, |
| | | type: form.type, |
| | | startDate: form.startDate, |
| | | endDate: form.endDate, |
| | | days: form.days, |
| | | status: form.status |
| | | } |
| | | addHolidaySettings(params).then(res => { |
| | | status: form.status, |
| | | }; |
| | | addHolidaySettings(params) |
| | | .then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("æ·»å æå"); |
| | | // dialogVisible.value = false; |
| | | getHolidaySettingsList() |
| | | getHolidaySettingsList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | } else if (currentType.value === 'annual') { |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | } else if (currentType.value === "annual") { |
| | | // annualData.value.push(newItem) |
| | | const params = { |
| | | employeeType: form.employeeType, |
| | | workYears: form.workYears, |
| | | annualDays: form.annualDays, |
| | | maxCarryOver: form.maxCarryOver, |
| | | status: form.status |
| | | } |
| | | addAnnualLeaveSetting(params).then(res => { |
| | | status: form.status, |
| | | }; |
| | | addAnnualLeaveSetting(params) |
| | | .then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("æ·»å æå"); |
| | | // dialogVisible.value = false; |
| | | getAnnualLeaveSettingList() |
| | | getAnnualLeaveSettingList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | } else if (currentType.value === 'overtime') { |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | } else if (currentType.value === "overtime") { |
| | | const params = { |
| | | name: form.name, |
| | | type: form.type, |
| | | startTime: form.startTime || '', |
| | | endTime: form.endTime || '', |
| | | startTime: form.startTime || "", |
| | | endTime: form.endTime || "", |
| | | rate: form.rate, |
| | | status: form.status |
| | | } |
| | | addOvertimeSetting(params).then(res => { |
| | | status: form.status, |
| | | }; |
| | | addOvertimeSetting(params) |
| | | .then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("æ·»å æå"); |
| | | // dialogVisible.value = false; |
| | | getOvertimeSettingList() |
| | | getOvertimeSettingList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | // newItem.startTime = form.startTime || '' |
| | | // newItem.endTime = form.endTime || '' |
| | | // overtimeData.value.push(newItem) |
| | | } else if (currentType.value === 'worktime') { |
| | | } else if (currentType.value === "worktime") { |
| | | const params = { |
| | | name: form.name, |
| | | startTime: form.workStartTime || '', |
| | | endTime: form.workEndTime || '', |
| | | startTime: form.workStartTime || "", |
| | | endTime: form.workEndTime || "", |
| | | flexibleStart: form.flexibleStart, |
| | | flexibleMinutes: form.flexibleMinutes, |
| | | status: form.status |
| | | } |
| | | addWorkingHoursSetting(params).then(res => { |
| | | status: form.status, |
| | | }; |
| | | addWorkingHoursSetting(params) |
| | | .then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("æ·»å æå"); |
| | | getWorkingHoursSettingList() |
| | | getWorkingHoursSettingList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | // newItem.startTime = form.workStartTime || '' |
| | | // newItem.endTime = form.workEndTime || '' |
| | | // worktimeData.value.push(newItem) |
| | | } |
| | | } |
| | | }; |
| | | |
| | | const editItem = () => { |
| | | let dataArray |
| | | let index |
| | | let dataArray; |
| | | let index; |
| | | |
| | | if (currentType.value === 'holiday') { |
| | | if (currentType.value === "holiday") { |
| | | const params = { |
| | | id: currentEditId.value, |
| | | name: form.name, |
| | | type: form.type, |
| | | startDate: form.dateRange[0].toISOString().split('T')[0], |
| | | endDate: form.dateRange[1].toISOString().split('T')[0], |
| | | startDate: form.dateRange[0].toISOString().split("T")[0], |
| | | endDate: form.dateRange[1].toISOString().split("T")[0], |
| | | days: form.days, |
| | | status: form.status |
| | | } |
| | | updateHolidaySettings(params).then(res => { |
| | | status: form.status, |
| | | }; |
| | | updateHolidaySettings(params) |
| | | .then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("æ´æ°æå"); |
| | | // dialogVisible.value = false; |
| | | getHolidaySettingsList() |
| | | getHolidaySettingsList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | } else if (currentType.value === 'annual') { |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | } else if (currentType.value === "annual") { |
| | | const params = { |
| | | id: currentEditId.value, |
| | | employeeType: form.employeeType, |
| | | workYears: form.workYears, |
| | | annualDays: form.annualDays, |
| | | maxCarryOver: form.maxCarryOver, |
| | | status: form.status |
| | | } |
| | | updateAnnualLeaveSetting(params).then(res => { |
| | | status: form.status, |
| | | }; |
| | | updateAnnualLeaveSetting(params) |
| | | .then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("æ´æ°æå"); |
| | | getAnnualLeaveSettingList() |
| | | getAnnualLeaveSettingList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | } else if (currentType.value === 'overtime') { |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | } else if (currentType.value === "overtime") { |
| | | const params = { |
| | | id: currentEditId.value, |
| | | name: form.name, |
| | | type: form.type, |
| | | startTime: form.startTime || '', |
| | | endTime: form.endTime || '', |
| | | startTime: form.startTime || "", |
| | | endTime: form.endTime || "", |
| | | rate: form.rate, |
| | | status: form.status |
| | | } |
| | | updateOvertimeSetting(params).then(res => { |
| | | status: form.status, |
| | | }; |
| | | updateOvertimeSetting(params) |
| | | .then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("æ´æ°æå"); |
| | | getOvertimeSettingList() |
| | | getOvertimeSettingList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | |
| | | // dataArray = overtimeData.value |
| | | // index = dataArray.findIndex(item => item.id === currentEditId.value) |
| | |
| | | // status: form.status |
| | | // } |
| | | // } |
| | | } else if (currentType.value === 'worktime') { |
| | | } else if (currentType.value === "worktime") { |
| | | const params = { |
| | | id: currentEditId.value, |
| | | name: form.name, |
| | | startTime: form.workStartTime || '', |
| | | endTime: form.workEndTime || '', |
| | | startTime: form.workStartTime || "", |
| | | endTime: form.workEndTime || "", |
| | | flexibleStart: form.flexibleStart, |
| | | flexibleMinutes: form.flexibleMinutes, |
| | | status: form.status |
| | | } |
| | | updateWorkingHoursSetting(params).then(res => { |
| | | status: form.status, |
| | | }; |
| | | updateWorkingHoursSetting(params) |
| | | .then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("æ´æ°æå"); |
| | | getWorkingHoursSettingList() |
| | | getWorkingHoursSettingList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | // dataArray = worktimeData.value |
| | | // index = dataArray.findIndex(item => item.id === currentEditId.value) |
| | | // if (index > -1) { |
| | |
| | | // } |
| | | // } |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // æå¡è®°å½è¿æ»¤åè½ |
| | | const filterAttendanceData = () => { |
| | | let filtered = attendanceData.value |
| | | let filtered = attendanceData.value; |
| | | |
| | | // ææ¥æè¿æ»¤ |
| | | if (attendanceDate.value) { |
| | | filtered = filtered.filter(item => item.date === attendanceDate.value) |
| | | filtered = filtered.filter(item => item.date === attendanceDate.value); |
| | | } |
| | | |
| | | // æç¶æè¿æ»¤ |
| | | if (attendanceStatus.value) { |
| | | filtered = filtered.filter(item => item.status === attendanceStatus.value) |
| | | filtered = filtered.filter(item => item.status === attendanceStatus.value); |
| | | } |
| | | |
| | | filteredAttendanceData.value = filtered |
| | | } |
| | | filteredAttendanceData.value = filtered; |
| | | }; |
| | | |
| | | // å¯¼åºæå¡è®°å½ |
| | | const exportAttendance = () => { |
| | | ElMessage.success('导åºåè½å¼åä¸...') |
| | | } |
| | | ElMessage.success("导åºåè½å¼åä¸..."); |
| | | }; |
| | | |
| | | // åå§åæå¡è®°å½åæ°æ® |
| | | const initAttendanceData = () => { |
| | | const mockData = [ |
| | | { |
| | | id: 1, |
| | | employeeName: 'éå¿å¼º', |
| | | department: 'ææ¯é¨', |
| | | date: '2025-08-15', |
| | | clockInTime: '09:00:00', |
| | | clockOutTime: '18:00:00', |
| | | workHours: '8.0h', |
| | | status: 'normal', |
| | | location: 'å
¬å¸æ»é¨', |
| | | remark: '' |
| | | employeeName: "éå¿å¼º", |
| | | department: "ææ¯é¨", |
| | | date: "2025-08-15", |
| | | clockInTime: "09:00:00", |
| | | clockOutTime: "18:00:00", |
| | | workHours: "8.0h", |
| | | status: "normal", |
| | | location: "å
¬å¸æ»é¨", |
| | | remark: "", |
| | | }, |
| | | { |
| | | id: 2, |
| | | employeeName: 'æéªæ¢
', |
| | | department: 'å¸åºé¨', |
| | | date: '2025-08-16', |
| | | clockInTime: '08:58:00', |
| | | clockOutTime: '18:05:00', |
| | | workHours: '8.12h', |
| | | status: 'normal', |
| | | location: 'å
¬å¸æ»é¨', |
| | | remark: '' |
| | | employeeName: "æéªæ¢
", |
| | | department: "å¸åºé¨", |
| | | date: "2025-08-16", |
| | | clockInTime: "08:58:00", |
| | | clockOutTime: "18:05:00", |
| | | workHours: "8.12h", |
| | | status: "normal", |
| | | location: "å
¬å¸æ»é¨", |
| | | remark: "", |
| | | }, |
| | | { |
| | | id: 3, |
| | | employeeName: 'ç建å', |
| | | department: '人äºé¨', |
| | | date: '2025-08-16', |
| | | clockInTime: '09:02:00', |
| | | clockOutTime: '18:00:00', |
| | | workHours: '7.97h', |
| | | status: 'normal', |
| | | location: 'å
¬å¸æ»é¨', |
| | | remark: '' |
| | | employeeName: "ç建å", |
| | | department: "人äºé¨", |
| | | date: "2025-08-16", |
| | | clockInTime: "09:02:00", |
| | | clockOutTime: "18:00:00", |
| | | workHours: "7.97h", |
| | | status: "normal", |
| | | location: "å
¬å¸æ»é¨", |
| | | remark: "", |
| | | }, |
| | | { |
| | | id: 4, |
| | | employeeName: 'èµµæä¸½', |
| | | department: 'è´¢å¡é¨', |
| | | date: '2025-09-02', |
| | | clockInTime: '08:55:00', |
| | | clockOutTime: '18:10:00', |
| | | workHours: '8.25h', |
| | | status: 'normal', |
| | | location: 'å
¬å¸æ»é¨', |
| | | remark: '' |
| | | employeeName: "èµµæä¸½", |
| | | department: "è´¢å¡é¨", |
| | | date: "2025-09-02", |
| | | clockInTime: "08:55:00", |
| | | clockOutTime: "18:10:00", |
| | | workHours: "8.25h", |
| | | status: "normal", |
| | | location: "å
¬å¸æ»é¨", |
| | | remark: "", |
| | | }, |
| | | { |
| | | id: 5, |
| | | employeeName: 'å¼ å½åº', |
| | | department: 'ææ¯é¨', |
| | | date: '2025-09-02', |
| | | clockInTime: '09:00:00', |
| | | clockOutTime: '18:30:00', |
| | | workHours: '8.5h', |
| | | status: 'normal', |
| | | location: 'å
¬å¸æ»é¨', |
| | | remark: 'å ç' |
| | | employeeName: "å¼ å½åº", |
| | | department: "ææ¯é¨", |
| | | date: "2025-09-02", |
| | | clockInTime: "09:00:00", |
| | | clockOutTime: "18:30:00", |
| | | workHours: "8.5h", |
| | | status: "normal", |
| | | location: "å
¬å¸æ»é¨", |
| | | remark: "å ç", |
| | | }, |
| | | { |
| | | id: 6, |
| | | employeeName: 'åæè¾', |
| | | department: 'è¿è¥é¨', |
| | | date: '2025-09-03', |
| | | clockInTime: '09:05:00', |
| | | clockOutTime: '18:00:00', |
| | | workHours: '7.92h', |
| | | status: 'normal', |
| | | location: 'å
¬å¸æ»é¨', |
| | | remark: '' |
| | | employeeName: "åæè¾", |
| | | department: "è¿è¥é¨", |
| | | date: "2025-09-03", |
| | | clockInTime: "09:05:00", |
| | | clockOutTime: "18:00:00", |
| | | workHours: "7.92h", |
| | | status: "normal", |
| | | location: "å
¬å¸æ»é¨", |
| | | remark: "", |
| | | }, |
| | | { |
| | | id: 7, |
| | | employeeName: 'å丽å', |
| | | department: '设计é¨', |
| | | date: '2025-09-03', |
| | | clockInTime: '08:59:00', |
| | | clockOutTime: '18:02:00', |
| | | workHours: '8.05h', |
| | | status: 'normal', |
| | | location: 'å
¬å¸æ»é¨', |
| | | remark: '' |
| | | employeeName: "å丽å", |
| | | department: "设计é¨", |
| | | date: "2025-09-03", |
| | | clockInTime: "08:59:00", |
| | | clockOutTime: "18:02:00", |
| | | workHours: "8.05h", |
| | | status: "normal", |
| | | location: "å
¬å¸æ»é¨", |
| | | remark: "", |
| | | }, |
| | | { |
| | | id: 8, |
| | | employeeName: 'å¨å»ºå', |
| | | department: 'éå®é¨', |
| | | date: '2025-09-04', |
| | | clockInTime: '09:15:00', |
| | | clockOutTime: '18:00:00', |
| | | workHours: '7.75h', |
| | | status: 'late', |
| | | location: 'å
¬å¸æ»é¨', |
| | | remark: '交éå µå¡' |
| | | employeeName: "å¨å»ºå", |
| | | department: "éå®é¨", |
| | | date: "2025-09-04", |
| | | clockInTime: "09:15:00", |
| | | clockOutTime: "18:00:00", |
| | | workHours: "7.75h", |
| | | status: "late", |
| | | location: "å
¬å¸æ»é¨", |
| | | remark: "交éå µå¡", |
| | | }, |
| | | { |
| | | id: 9, |
| | | employeeName: 'å´å°è³', |
| | | department: '客æé¨', |
| | | date: '2025-09-04', |
| | | clockInTime: '09:01:00', |
| | | clockOutTime: '18:00:00', |
| | | workHours: '7.98h', |
| | | status: 'normal', |
| | | location: 'å
¬å¸æ»é¨', |
| | | remark: '' |
| | | employeeName: "å´å°è³", |
| | | department: "客æé¨", |
| | | date: "2025-09-04", |
| | | clockInTime: "09:01:00", |
| | | clockOutTime: "18:00:00", |
| | | workHours: "7.98h", |
| | | status: "normal", |
| | | location: "å
¬å¸æ»é¨", |
| | | remark: "", |
| | | }, |
| | | { |
| | | id: 10, |
| | | employeeName: 'é©¬ææ°', |
| | | department: 'ææ¯é¨', |
| | | date: '2025-09-05', |
| | | clockInTime: '08:57:00', |
| | | clockOutTime: '17:30:00', |
| | | workHours: '7.55h', |
| | | status: 'early', |
| | | location: 'å
¬å¸æ»é¨', |
| | | remark: 'ææ¥äºæå离å¼' |
| | | employeeName: "é©¬ææ°", |
| | | department: "ææ¯é¨", |
| | | date: "2025-09-05", |
| | | clockInTime: "08:57:00", |
| | | clockOutTime: "17:30:00", |
| | | workHours: "7.55h", |
| | | status: "early", |
| | | location: "å
¬å¸æ»é¨", |
| | | remark: "ææ¥äºæå离å¼", |
| | | }, |
| | | { |
| | | id: 11, |
| | | employeeName: 'ææä¸', |
| | | department: 'è¡æ¿é¨', |
| | | date: '2025-09-05', |
| | | clockInTime: '09:03:00', |
| | | clockOutTime: '18:08:00', |
| | | workHours: '8.08h', |
| | | status: 'normal', |
| | | location: 'å
¬å¸æ»é¨', |
| | | remark: '' |
| | | employeeName: "ææä¸", |
| | | department: "è¡æ¿é¨", |
| | | date: "2025-09-05", |
| | | clockInTime: "09:03:00", |
| | | clockOutTime: "18:08:00", |
| | | workHours: "8.08h", |
| | | status: "normal", |
| | | location: "å
¬å¸æ»é¨", |
| | | remark: "", |
| | | }, |
| | | { |
| | | id: 12, |
| | | employeeName: 'é»ç¾ç²', |
| | | department: 'è´¢å¡é¨', |
| | | date: '2025-09-06', |
| | | clockInTime: '', |
| | | clockOutTime: '', |
| | | workHours: '0h', |
| | | status: 'absent', |
| | | location: '', |
| | | remark: '请ç
å' |
| | | employeeName: "é»ç¾ç²", |
| | | department: "è´¢å¡é¨", |
| | | date: "2025-09-06", |
| | | clockInTime: "", |
| | | clockOutTime: "", |
| | | workHours: "0h", |
| | | status: "absent", |
| | | location: "", |
| | | remark: "请ç
å", |
| | | }, |
| | | { |
| | | id: 13, |
| | | employeeName: 'éæµ·æ¶', |
| | | department: 'å¸åºé¨', |
| | | date: '2025-08-14', |
| | | clockInTime: '09:00:00', |
| | | clockOutTime: '18:00:00', |
| | | workHours: '8.0h', |
| | | status: 'normal', |
| | | location: 'å
¬å¸æ»é¨', |
| | | remark: '' |
| | | employeeName: "éæµ·æ¶", |
| | | department: "å¸åºé¨", |
| | | date: "2025-08-14", |
| | | clockInTime: "09:00:00", |
| | | clockOutTime: "18:00:00", |
| | | workHours: "8.0h", |
| | | status: "normal", |
| | | location: "å
¬å¸æ»é¨", |
| | | remark: "", |
| | | }, |
| | | { |
| | | id: 14, |
| | | employeeName: '谢丽å¨', |
| | | department: '人äºé¨', |
| | | date: '2025-08-20', |
| | | clockInTime: '08:58:00', |
| | | clockOutTime: '18:03:00', |
| | | workHours: '8.08h', |
| | | status: 'normal', |
| | | location: 'å
¬å¸æ»é¨', |
| | | remark: '' |
| | | employeeName: "谢丽å¨", |
| | | department: "人äºé¨", |
| | | date: "2025-08-20", |
| | | clockInTime: "08:58:00", |
| | | clockOutTime: "18:03:00", |
| | | workHours: "8.08h", |
| | | status: "normal", |
| | | location: "å
¬å¸æ»é¨", |
| | | remark: "", |
| | | }, |
| | | { |
| | | id: 15, |
| | | employeeName: 'ä½å¿ä¼', |
| | | department: 'ææ¯é¨', |
| | | date: '2025-08-21', |
| | | clockInTime: '09:10:00', |
| | | clockOutTime: '18:00:00', |
| | | workHours: '7.83h', |
| | | status: 'late', |
| | | location: 'å
¬å¸æ»é¨', |
| | | remark: '' |
| | | employeeName: "ä½å¿ä¼", |
| | | department: "ææ¯é¨", |
| | | date: "2025-08-21", |
| | | clockInTime: "09:10:00", |
| | | clockOutTime: "18:00:00", |
| | | workHours: "7.83h", |
| | | status: "late", |
| | | location: "å
¬å¸æ»é¨", |
| | | remark: "", |
| | | }, |
| | | { |
| | | id: 16, |
| | | employeeName: '许é
è³', |
| | | department: '设计é¨', |
| | | date: '2025-08-22', |
| | | clockInTime: '09:01:00', |
| | | clockOutTime: '18:00:00', |
| | | workHours: '7.98h', |
| | | status: 'normal', |
| | | location: 'å
¬å¸æ»é¨', |
| | | remark: '' |
| | | employeeName: "许é
è³", |
| | | department: "设计é¨", |
| | | date: "2025-08-22", |
| | | clockInTime: "09:01:00", |
| | | clockOutTime: "18:00:00", |
| | | workHours: "7.98h", |
| | | status: "normal", |
| | | location: "å
¬å¸æ»é¨", |
| | | remark: "", |
| | | }, |
| | | { |
| | | id: 17, |
| | | employeeName: 'é建平', |
| | | department: 'è¿è¥é¨', |
| | | date: '2025-09-10', |
| | | clockInTime: '08:59:00', |
| | | clockOutTime: '18:05:00', |
| | | workHours: '8.1h', |
| | | status: 'normal', |
| | | location: 'å
¬å¸æ»é¨', |
| | | remark: '' |
| | | employeeName: "é建平", |
| | | department: "è¿è¥é¨", |
| | | date: "2025-09-10", |
| | | clockInTime: "08:59:00", |
| | | clockOutTime: "18:05:00", |
| | | workHours: "8.1h", |
| | | status: "normal", |
| | | location: "å
¬å¸æ»é¨", |
| | | remark: "", |
| | | }, |
| | | { |
| | | id: 18, |
| | | employeeName: 'æ¾å°çº¢', |
| | | department: '客æé¨', |
| | | date: '2025-09-11', |
| | | clockInTime: '09:02:00', |
| | | clockOutTime: '18:00:00', |
| | | workHours: '7.97h', |
| | | status: 'normal', |
| | | location: 'å
¬å¸æ»é¨', |
| | | remark: '' |
| | | } |
| | | ] |
| | | employeeName: "æ¾å°çº¢", |
| | | department: "客æé¨", |
| | | date: "2025-09-11", |
| | | clockInTime: "09:02:00", |
| | | clockOutTime: "18:00:00", |
| | | workHours: "7.97h", |
| | | status: "normal", |
| | | location: "å
¬å¸æ»é¨", |
| | | remark: "", |
| | | }, |
| | | ]; |
| | | |
| | | attendanceData.value = mockData |
| | | filteredAttendanceData.value = mockData |
| | | } |
| | | attendanceData.value = mockData; |
| | | filteredAttendanceData.value = mockData; |
| | | }; |
| | | |
| | | // å é¤é¡¹ç® |
| | | const deleteItem = (type, row) => { |
| | | ElMessageBox.confirm('ç¡®å®è¦å é¤è¿ä¸ªé¡¹ç®åï¼', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | ElMessageBox.confirm("ç¡®å®è¦å é¤è¿ä¸ªé¡¹ç®åï¼", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).then(() => { |
| | | let ids = []; |
| | | let dataArray |
| | | if (type === 'holiday') { |
| | | ids.push(row.id) |
| | | delHolidaySettings(ids).then(res => { |
| | | let dataArray; |
| | | if (type === "holiday") { |
| | | ids.push(row.id); |
| | | delHolidaySettings(ids) |
| | | .then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("å 餿å"); |
| | | ids = [] |
| | | getHolidaySettingsList() |
| | | ids = []; |
| | | getHolidaySettingsList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | } |
| | | else if (type === 'annual') { |
| | | ids.push(row.id) |
| | | delAnnualLeaveSetting(ids).then(res => { |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | } else if (type === "annual") { |
| | | ids.push(row.id); |
| | | delAnnualLeaveSetting(ids) |
| | | .then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("å 餿å"); |
| | | ids = [] |
| | | getAnnualLeaveSettingList() |
| | | ids = []; |
| | | getAnnualLeaveSettingList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | } |
| | | else if (type === 'overtime') { |
| | | ids.push(row.id) |
| | | delOvertimeSetting(ids).then(res => { |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | } else if (type === "overtime") { |
| | | ids.push(row.id); |
| | | delOvertimeSetting(ids) |
| | | .then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("å 餿å"); |
| | | ids = [] |
| | | getOvertimeSettingList() |
| | | ids = []; |
| | | getOvertimeSettingList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | } |
| | | else if (type === 'worktime') { |
| | | ids.push(row.id) |
| | | delWorkingHoursSetting(ids).then(res => { |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | } else if (type === "worktime") { |
| | | ids.push(row.id); |
| | | delWorkingHoursSetting(ids) |
| | | .then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("å 餿å"); |
| | | ids = [] |
| | | getWorkingHoursSettingList() |
| | | ids = []; |
| | | getWorkingHoursSettingList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | } |
| | | |
| | | // const index = dataArray.findIndex(item => item.id === row.id) |
| | |
| | | // dataArray.splice(index, 1) |
| | | // ElMessage.success('å 餿å') |
| | | // } |
| | | }) |
| | | } |
| | | }); |
| | | }; |
| | | // è·ååæè®¾ç½®å表 |
| | | const getHolidaySettingsList = () => { |
| | | // tableLoading.value = true; |
| | | listHolidaySettings({...page.value}) |
| | | .then(res => { |
| | | // tableLoading.value = false; |
| | | holidayData.value = res.data.records |
| | | holidayData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }).catch(err => { |
| | | // tableLoading.value = false; |
| | | }) |
| | | .catch(err => { |
| | | // tableLoading.value = false; |
| | | }); |
| | | }; |
| | | // è·åå¹´åè§åå表 |
| | | const getAnnualLeaveSettingList = () => { |
| | | |
| | | listAnnualLeaveSettingList({...page.value}) |
| | | .then(res => { |
| | | // console.log(res.data) |
| | | annualData.value = res.data.records |
| | | annualData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }).catch(err => { |
| | | }) |
| | | .catch(err => {}); |
| | | }; |
| | | // è·åå çè§åå表 |
| | | const getOvertimeSettingList = () => { |
| | | |
| | | listOvertimeSettingList({...page.value}) |
| | | .then(res => { |
| | | // console.log(res.data) |
| | | overtimeData.value = res.data.records |
| | | overtimeData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }).catch(err => { |
| | | }) |
| | | .catch(err => {}); |
| | | }; |
| | | // è·å工使¶é´è§åå表 |
| | | const getWorkingHoursSettingList = () => { |
| | | |
| | | listWorkingHoursSettingList({...page.value}) |
| | | .then(res => { |
| | | // console.log(res.data) |
| | | worktimeData.value = res.data.records |
| | | worktimeData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }).catch(err => { |
| | | }) |
| | | .catch(err => {}); |
| | | }; |
| | | onMounted(() => { |
| | | getHolidaySettingsList() |
| | | getAnnualLeaveSettingList() |
| | | getOvertimeSettingList() |
| | | getWorkingHoursSettingList() |
| | | initAttendanceData() |
| | | console.log('èå¤ç®¡ç页é¢å è½½å®æ') |
| | | }) |
| | | getHolidaySettingsList(); |
| | | getAnnualLeaveSettingList(); |
| | | getOvertimeSettingList(); |
| | | getWorkingHoursSettingList(); |
| | | initAttendanceData(); |
| | | console.log("èå¤ç®¡ç页é¢å è½½å®æ"); |
| | | }); |
| | | |
| | | onUnmounted(() => { |
| | | // æ¸
çå·¥ä½ |
| | | dialogVisible.value = false |
| | | currentType.value = '' |
| | | currentAction.value = '' |
| | | currentEditId.value = '' |
| | | }) |
| | | dialogVisible.value = false; |
| | | currentType.value = ""; |
| | | currentAction.value = ""; |
| | | currentEditId.value = ""; |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title">ç¥è¯æ é¢ï¼</span> |
| | | <el-input |
| | | v-model="searchForm.title" |
| | | <el-input v-model="searchForm.title" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥ç¥è¯æ é¢æç´¢" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | /> |
| | | :prefix-icon="Search" /> |
| | | <span class="search_title ml10">ç¥è¯ç±»åï¼</span> |
| | | <el-select v-model="searchForm.type" clearable @change="handleQuery" style="width: 240px"> |
| | | <el-option label="ååç¹æ¹" :value="'contract'" /> |
| | | <el-option label="å®¡æ¹æ¡ä¾" :value="'approval'" /> |
| | | <el-option label="è§£å³æ¹æ¡" :value="'solution'" /> |
| | | <el-option label="ç»éªæ»ç»" :value="'experience'" /> |
| | | <el-option label="æä½æå" :value="'guide'" /> |
| | | <el-select v-model="searchForm.type" |
| | | clearable |
| | | @change="handleQuery" |
| | | style="width: 240px"> |
| | | <el-option label="ååç¹æ¹" |
| | | :value="'contract'" /> |
| | | <el-option label="å®¡æ¹æ¡ä¾" |
| | | :value="'approval'" /> |
| | | <el-option label="è§£å³æ¹æ¡" |
| | | :value="'solution'" /> |
| | | <el-option label="ç»éªæ»ç»" |
| | | :value="'experience'" /> |
| | | <el-option label="æä½æå" |
| | | :value="'guide'" /> |
| | | </el-select> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px"> |
| | | <el-button type="primary" |
| | | @click="handleQuery" |
| | | style="margin-left: 10px"> |
| | | æç´¢ |
| | | </el-button> |
| | | </div> |
| | | <div> |
| | | <el-button @click="handleExport" style="margin-right: 10px">导åº</el-button> |
| | | <el-button type="primary" @click="openForm('add')">æ°å¢ç¥è¯</el-button> |
| | | <el-button type="danger" plain @click="handleDelete">å é¤</el-button> |
| | | <el-button @click="handleExport" |
| | | style="margin-right: 10px">导åº</el-button> |
| | | <el-button type="primary" |
| | | @click="openForm('add')">æ°å¢ç¥è¯</el-button> |
| | | <el-button type="danger" |
| | | plain |
| | | @click="handleDelete">å é¤</el-button> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="table_list"> |
| | | <PIMTable |
| | | rowKey="id" |
| | | <PIMTable rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | :total="page.total" |
| | | ></PIMTable> |
| | | :total="page.total"></PIMTable> |
| | | </div> |
| | | |
| | | <!-- æ°å¢/ç¼è¾ç¥è¯å¼¹çª --> |
| | | <el-dialog |
| | | v-model="dialogVisible" |
| | | <el-dialog v-model="dialogVisible" |
| | | :title="dialogTitle" |
| | | width="800px" |
| | | :close-on-click-modal="false" |
| | | > |
| | | <el-form ref="formRef" :model="form" :rules="rules" label-width="120px"> |
| | | :close-on-click-modal="false"> |
| | | <el-form ref="formRef" |
| | | :model="form" |
| | | :rules="rules" |
| | | label-width="120px"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç¥è¯æ é¢" prop="title"> |
| | | <el-input v-model="form.title" placeholder="请è¾å
¥ç¥è¯æ é¢" /> |
| | | <el-form-item label="ç¥è¯æ é¢" |
| | | prop="title"> |
| | | <el-input v-model="form.title" |
| | | placeholder="请è¾å
¥ç¥è¯æ é¢" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç¥è¯ç±»å" prop="type"> |
| | | <el-select v-model="form.type" placeholder="è¯·éæ©ç¥è¯ç±»å" style="width: 100%"> |
| | | <el-option label="ååç¹æ¹" value="contract" /> |
| | | <el-option label="å®¡æ¹æ¡ä¾" value="approval" /> |
| | | <el-option label="è§£å³æ¹æ¡" value="solution" /> |
| | | <el-option label="ç»éªæ»ç»" value="experience" /> |
| | | <el-option label="æä½æå" value="guide" /> |
| | | <el-form-item label="ç¥è¯ç±»å" |
| | | prop="type"> |
| | | <el-select v-model="form.type" |
| | | placeholder="è¯·éæ©ç¥è¯ç±»å" |
| | | style="width: 100%"> |
| | | <el-option label="ååç¹æ¹" |
| | | value="contract" /> |
| | | <el-option label="å®¡æ¹æ¡ä¾" |
| | | value="approval" /> |
| | | <el-option label="è§£å³æ¹æ¡" |
| | | value="solution" /> |
| | | <el-option label="ç»éªæ»ç»" |
| | | value="experience" /> |
| | | <el-option label="æä½æå" |
| | | value="guide" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éç¨åºæ¯" prop="scenario"> |
| | | <el-input v-model="form.scenario" placeholder="请è¾å
¥éç¨åºæ¯" /> |
| | | <el-form-item label="éç¨åºæ¯" |
| | | prop="scenario"> |
| | | <el-input v-model="form.scenario" |
| | | placeholder="请è¾å
¥éç¨åºæ¯" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="è§£å³æç" prop="efficiency"> |
| | | <el-select v-model="form.efficiency" placeholder="è¯·éæ©è§£å³æç" style="width: 100%"> |
| | | <el-option label="æ¾èæå" value="high" /> |
| | | <el-option label="ä¸è¬æå" value="medium" /> |
| | | <el-option label="轻微æå" value="low" /> |
| | | <el-form-item label="è§£å³æç" |
| | | prop="efficiency"> |
| | | <el-select v-model="form.efficiency" |
| | | placeholder="è¯·éæ©è§£å³æç" |
| | | style="width: 100%"> |
| | | <el-option label="æ¾èæå" |
| | | value="high" /> |
| | | <el-option label="ä¸è¬æå" |
| | | value="medium" /> |
| | | <el-option label="轻微æå" |
| | | value="low" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-form-item label="é®é¢æè¿°" prop="problem"> |
| | | <el-input |
| | | v-model="form.problem" |
| | | <el-form-item label="é®é¢æè¿°" |
| | | prop="problem"> |
| | | <el-input v-model="form.problem" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请æè¿°éå°çé®é¢" |
| | | /> |
| | | placeholder="请æè¿°éå°çé®é¢" /> |
| | | </el-form-item> |
| | | <el-form-item label="è§£å³æ¹æ¡" prop="solution"> |
| | | <el-input |
| | | v-model="form.solution" |
| | | <el-form-item label="è§£å³æ¹æ¡" |
| | | prop="solution"> |
| | | <el-input v-model="form.solution" |
| | | type="textarea" |
| | | :rows="4" |
| | | placeholder="è¯·è¯¦ç»æè¿°è§£å³æ¹æ¡" |
| | | /> |
| | | placeholder="è¯·è¯¦ç»æè¿°è§£å³æ¹æ¡" /> |
| | | </el-form-item> |
| | | <el-form-item label="å
³é®è¦ç¹" prop="keyPoints"> |
| | | <el-input |
| | | v-model="form.keyPoints" |
| | | <el-form-item label="å
³é®è¦ç¹" |
| | | prop="keyPoints"> |
| | | <el-input v-model="form.keyPoints" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥å
³é®è¦ç¹ï¼ç¨éå·åé" |
| | | /> |
| | | placeholder="请è¾å
¥å
³é®è¦ç¹ï¼ç¨éå·åé" /> |
| | | </el-form-item> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å建人" prop="creator"> |
| | | <el-input v-model="form.creator" placeholder="请è¾å
¥å建人" /> |
| | | <el-form-item label="å建人" |
| | | prop="creator"> |
| | | <el-input v-model="form.creator" |
| | | placeholder="请è¾å
¥å建人" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä½¿ç¨æ¬¡æ°" prop="usageCount"> |
| | | <el-input-number v-model="form.usageCount" :min="0" style="width: 100%" /> |
| | | <el-form-item label="ä½¿ç¨æ¬¡æ°" |
| | | prop="usageCount"> |
| | | <el-input-number v-model="form.usageCount" |
| | | :min="0" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="submitForm">ç¡®å®</el-button> |
| | | <el-button @click="dialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="submitForm">ç¡®å®</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- æ¥çç¥è¯è¯¦æ
å¼¹çª --> |
| | | <el-dialog |
| | | v-model="viewDialogVisible" |
| | | <el-dialog v-model="viewDialogVisible" |
| | | title="ç¥è¯è¯¦æ
" |
| | | width="900px" |
| | | :close-on-click-modal="false" |
| | | > |
| | | :close-on-click-modal="false"> |
| | | <div class="knowledge-detail"> |
| | | <el-descriptions :column="2" border> |
| | | <el-descriptions-item label="ç¥è¯æ é¢" :span="2"> |
| | | <el-descriptions :column="2" |
| | | border> |
| | | <el-descriptions-item label="ç¥è¯æ é¢" |
| | | :span="2"> |
| | | <span class="detail-title">{{ currentKnowledge.title }}</span> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="ç¥è¯ç±»å"> |
| | |
| | | {{ currentKnowledge.createTime }} |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | |
| | | <div class="detail-section"> |
| | | <h4>é®é¢æè¿°</h4> |
| | | <div class="detail-content">{{ currentKnowledge.problem }}</div> |
| | | </div> |
| | | |
| | | <div class="detail-section"> |
| | | <h4>è§£å³æ¹æ¡</h4> |
| | | <div class="detail-content">{{ currentKnowledge.solution }}</div> |
| | | </div> |
| | | |
| | | <div class="detail-section"> |
| | | <h4>å
³é®è¦ç¹</h4> |
| | | <div class="key-points"> |
| | | <el-tag |
| | | v-for="(point, index) in currentKnowledge.keyPoints.split(',')" |
| | | <el-tag v-for="(point, index) in currentKnowledge.keyPoints.split(',')" |
| | | :key="index" |
| | | type="success" |
| | | style="margin-right: 8px; margin-bottom: 8px;" |
| | | > |
| | | style="margin-right: 8px; margin-bottom: 8px;"> |
| | | {{ point.trim() }} |
| | | </el-tag> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="detail-section"> |
| | | <h4>使ç¨ç»è®¡</h4> |
| | | <div class="usage-stats"> |
| | |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="copyKnowledge">å¤å¶ç¥è¯</el-button> |
| | | <el-button @click="viewDialogVisible = false">å
³é</el-button> |
| | | <el-button type="primary" @click="copyKnowledge">å¤å¶ç¥è¯</el-button> |
| | | <!-- <el-button type="success" @click="markAsFavorite">æ¶è@</el-button> --> |
| | | </span> |
| | | </template> |
| | |
| | | import { onMounted, ref, reactive, toRefs, getCurrentInstance } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import PIMTable from "@/components/PIMTable/PIMTable.vue"; |
| | | import { listKnowledgeBase, delKnowledgeBase,addKnowledgeBase,updateKnowledgeBase } from "@/api/collaborativeApproval/knowledgeBase.js"; |
| | | import { |
| | | listKnowledgeBase, |
| | | delKnowledgeBase, |
| | | addKnowledgeBase, |
| | | updateKnowledgeBase, |
| | | } from "@/api/collaborativeApproval/knowledgeBase.js"; |
| | | |
| | | // 表åéªè¯è§å |
| | | const rules = { |
| | | title: [ |
| | | { required: true, message: "请è¾å
¥ç¥è¯æ é¢", trigger: "blur" } |
| | | ], |
| | | type: [ |
| | | { required: true, message: "è¯·éæ©ç¥è¯ç±»å", trigger: "change" } |
| | | ], |
| | | problem: [ |
| | | { required: true, message: "请æè¿°éå°çé®é¢", trigger: "blur" } |
| | | ], |
| | | title: [{ required: true, message: "请è¾å
¥ç¥è¯æ é¢", trigger: "blur" }], |
| | | type: [{ required: true, message: "è¯·éæ©ç¥è¯ç±»å", trigger: "change" }], |
| | | problem: [{ required: true, message: "请æè¿°éå°çé®é¢", trigger: "blur" }], |
| | | solution: [ |
| | | { required: true, message: "è¯·è¯¦ç»æè¿°è§£å³æ¹æ¡", trigger: "blur" } |
| | | ] |
| | | { required: true, message: "è¯·è¯¦ç»æè¿°è§£å³æ¹æ¡", trigger: "blur" }, |
| | | ], |
| | | }; |
| | | |
| | | // ååºå¼æ°æ® |
| | |
| | | solution: "", |
| | | keyPoints: "", |
| | | creator: "", |
| | | usageCount: 0 |
| | | usageCount: 0, |
| | | }, |
| | | dialogVisible: false, |
| | | dialogTitle: "", |
| | | dialogType: "add", |
| | | viewDialogVisible: false, |
| | | currentKnowledge: {} |
| | | currentKnowledge: {}, |
| | | }); |
| | | |
| | | const { |
| | |
| | | dialogTitle, |
| | | dialogType, |
| | | viewDialogVisible, |
| | | currentKnowledge |
| | | currentKnowledge, |
| | | } = toRefs(data); |
| | | |
| | | // 表åå¼ç¨ |
| | |
| | | label: "ç¥è¯ç±»å", |
| | | prop: "type", |
| | | dataType: "tag", |
| | | formatData: (params) => { |
| | | formatData: params => { |
| | | const typeMap = { |
| | | contract: "ååç¹æ¹", |
| | | approval: "å®¡æ¹æ¡ä¾", |
| | | solution: "è§£å³æ¹æ¡", |
| | | experience: "ç»éªæ»ç»", |
| | | guide: "æä½æå" |
| | | guide: "æä½æå", |
| | | }; |
| | | return typeMap[params] || params; |
| | | }, |
| | | formatType: (params) => { |
| | | formatType: params => { |
| | | const typeMap = { |
| | | contract: "success", |
| | | approval: "warning", |
| | | solution: "primary", |
| | | experience: "info", |
| | | guide: "danger" |
| | | guide: "danger", |
| | | }; |
| | | return typeMap[params] || "info"; |
| | | } |
| | | }, |
| | | }, |
| | | { |
| | | label: "éç¨åºæ¯", |
| | |
| | | label: "è§£å³æç", |
| | | prop: "efficiency", |
| | | dataType: "tag", |
| | | formatData: (params) => { |
| | | formatData: params => { |
| | | const efficiencyMap = { |
| | | high: "æ¾èæå", |
| | | medium: "ä¸è¬æå", |
| | | low: "轻微æå" |
| | | low: "轻微æå", |
| | | }; |
| | | return efficiencyMap[params] || params; |
| | | }, |
| | | formatType: (params) => { |
| | | formatType: params => { |
| | | const typeMap = { |
| | | high: "success", |
| | | medium: "warning", |
| | | low: "info" |
| | | low: "info", |
| | | }; |
| | | return typeMap[params] || "info"; |
| | | } |
| | | }, |
| | | }, |
| | | { |
| | | label: "ä½¿ç¨æ¬¡æ°", |
| | | prop: "usageCount", |
| | | width: 100, |
| | | align: "center" |
| | | align: "center", |
| | | }, |
| | | { |
| | | label: "å建人", |
| | |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | clickFun: row => { |
| | | openForm("edit", row); |
| | | } |
| | | }, |
| | | }, |
| | | { |
| | | name: "æ¥ç", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | clickFun: row => { |
| | | viewKnowledge(row); |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | | |
| | | // æ¨¡ææ°æ® |
| | |
| | | "{type}æ ååæä½æµç¨", |
| | | "{scenario}é®é¢è§£å³æ¹æ¡", |
| | | "{type}æä½³å®è·µæ»ç»", |
| | | "{scenario}æçæåæ¹æ¡" |
| | | "{scenario}æçæåæ¹æ¡", |
| | | ]; |
| | | |
| | | // ç¥è¯ç±»åé
ç½® |
| | |
| | | { type: "approval", label: "å®¡æ¹æ¡ä¾", efficiency: "medium" }, |
| | | { type: "solution", label: "è§£å³æ¹æ¡", efficiency: "high" }, |
| | | { type: "experience", label: "ç»éªæ»ç»", efficiency: "medium" }, |
| | | { type: "guide", label: "æä½æå", efficiency: "low" } |
| | | { type: "guide", label: "æä½æå", efficiency: "low" }, |
| | | ]; |
| | | |
| | | // åºæ¯å表 |
| | | const scenarios = ["大é¢åå审æ¹", "è·¨é¨é¨åä½", "ç´§æ¥éè´", "ç¹æ®ç³è¯·", "æµç¨ä¼å", "é®é¢å¤ç", "æ åå建设", "æçæå"]; |
| | | const scenarios = [ |
| | | "大é¢åå审æ¹", |
| | | "è·¨é¨é¨åä½", |
| | | "ç´§æ¥éè´", |
| | | "ç¹æ®ç³è¯·", |
| | | "æµç¨ä¼å", |
| | | "é®é¢å¤ç", |
| | | "æ åå建设", |
| | | "æçæå", |
| | | ]; |
| | | |
| | | // èªå¨çææ°æ°æ® |
| | | const generateNewData = () => { |
| | | const newId = (mockData.length + 1).toString(); |
| | | const now = new Date(); |
| | | const randomType = knowledgeTypes[Math.floor(Math.random() * knowledgeTypes.length)]; |
| | | const randomScenario = scenarios[Math.floor(Math.random() * scenarios.length)]; |
| | | const randomType = |
| | | knowledgeTypes[Math.floor(Math.random() * knowledgeTypes.length)]; |
| | | const randomScenario = |
| | | scenarios[Math.floor(Math.random() * scenarios.length)]; |
| | | |
| | | // çæéæºæ é¢ |
| | | let title = titleTemplates[Math.floor(Math.random() * titleTemplates.length)]; |
| | | title = title |
| | | .replace('{type}', randomType.label) |
| | | .replace('{scenario}', randomScenario); |
| | | .replace("{type}", randomType.label) |
| | | .replace("{scenario}", randomScenario); |
| | | |
| | | const newKnowledge = { |
| | | id: newId, |
| | |
| | | problem: `å¨${randomScenario}è¿ç¨ä¸éå°çé®é¢æè¿°...`, |
| | | solution: `é对${randomScenario}çè§£å³æ¹æ¡åæä½æ¥éª¤...`, |
| | | keyPoints: "å
³é®è¦ç¹1,å
³é®è¦ç¹2,å
³é®è¦ç¹3,å
³é®è¦ç¹4", |
| | | creator: ["å¼ ç»ç", "æä¸»ç®¡", "çä¸å", "åæ»ç"][Math.floor(Math.random() * 4)], |
| | | creator: ["å¼ ç»ç", "æä¸»ç®¡", "çä¸å", "åæ»ç"][ |
| | | Math.floor(Math.random() * 4) |
| | | ], |
| | | usageCount: Math.floor(Math.random() * 20) + 1, |
| | | createTime: now.toLocaleString() |
| | | createTime: now.toLocaleString(), |
| | | }; |
| | | |
| | | // æ·»å å°æ°æ®å¼å¤´ |
| | |
| | | listKnowledgeBase({...page.value, ...searchForm.value}) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records |
| | | tableData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | | }) |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | // å页å¤ç |
| | | const pagination = (obj) => { |
| | | const pagination = obj => { |
| | | page.value.current = obj.page; |
| | | page.value.size = obj.limit; |
| | | handleQuery(); |
| | | }; |
| | | |
| | | // éæ©ååå¤ç |
| | | const handleSelectionChange = (selection) => { |
| | | const handleSelectionChange = selection => { |
| | | selectedIds.value = selection.map(item => item.id); |
| | | }; |
| | | |
| | |
| | | solution: "", |
| | | keyPoints: "", |
| | | creator: "", |
| | | usageCount: 0 |
| | | usageCount: 0, |
| | | }); |
| | | } else if (type === "edit" && row) { |
| | | dialogTitle.value = "ç¼è¾ç¥è¯"; |
| | |
| | | solution: row.solution, |
| | | keyPoints: row.keyPoints, |
| | | creator: row.creator, |
| | | usageCount: row.usageCount |
| | | usageCount: row.usageCount, |
| | | }); |
| | | } |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | // æ¥çç¥è¯è¯¦æ
|
| | | const viewKnowledge = (row) => { |
| | | const viewKnowledge = row => { |
| | | currentKnowledge.value = { ...row }; |
| | | viewDialogVisible.value = true; |
| | | }; |
| | | |
| | | // è·åç±»åæ ç¾ç±»å |
| | | const getTypeTagType = (type) => { |
| | | const getTypeTagType = type => { |
| | | const typeMap = { |
| | | contract: "success", |
| | | approval: "warning", |
| | | solution: "primary", |
| | | experience: "info", |
| | | guide: "danger" |
| | | guide: "danger", |
| | | }; |
| | | return typeMap[type] || "info"; |
| | | }; |
| | | |
| | | // è·åç±»åæ ç¾ææ¬ |
| | | const getTypeLabel = (type) => { |
| | | const getTypeLabel = type => { |
| | | const typeMap = { |
| | | contract: "ååç¹æ¹", |
| | | approval: "å®¡æ¹æ¡ä¾", |
| | | solution: "è§£å³æ¹æ¡", |
| | | experience: "ç»éªæ»ç»", |
| | | guide: "æä½æå" |
| | | guide: "æä½æå", |
| | | }; |
| | | return typeMap[type] || type; |
| | | }; |
| | | |
| | | // è·åæçæ ç¾ç±»å |
| | | const getEfficiencyTagType = (efficiency) => { |
| | | const getEfficiencyTagType = efficiency => { |
| | | const typeMap = { |
| | | high: "success", |
| | | medium: "warning", |
| | | low: "info" |
| | | low: "info", |
| | | }; |
| | | return typeMap[efficiency] || "info"; |
| | | }; |
| | | |
| | | // è·åæçæ ç¾ææ¬ |
| | | const getEfficiencyLabel = (efficiency) => { |
| | | const getEfficiencyLabel = efficiency => { |
| | | const efficiencyMap = { |
| | | high: "æ¾èæå", |
| | | medium: "ä¸è¬æå", |
| | | low: "轻微æå" |
| | | low: "轻微æå", |
| | | }; |
| | | return efficiencyMap[efficiency] || efficiency; |
| | | }; |
| | | |
| | | // è·åæçæåç¾åæ¯ |
| | | const getEfficiencyScore = (efficiency) => { |
| | | const getEfficiencyScore = efficiency => { |
| | | const scoreMap = { |
| | | high: 40, |
| | | medium: 25, |
| | | low: 15 |
| | | low: 15, |
| | | }; |
| | | return scoreMap[efficiency] || 0; |
| | | }; |
| | | |
| | | // è·åå¹³åèçæ¶é´ |
| | | const getTimeSaved = (efficiency) => { |
| | | const getTimeSaved = efficiency => { |
| | | const timeMap = { |
| | | high: "2-3天", |
| | | medium: "1-2天", |
| | | low: "0.5-1天" |
| | | low: "0.5-1天", |
| | | }; |
| | | return timeMap[efficiency] || "æªç¥"; |
| | | }; |
| | |
| | | `.trim(); |
| | | |
| | | // å¤å¶å°åªè´´æ¿ |
| | | navigator.clipboard.writeText(knowledgeText).then(() => { |
| | | navigator.clipboard |
| | | .writeText(knowledgeText) |
| | | .then(() => { |
| | | ElMessage.success("ç¥è¯å
容已å¤å¶å°åªè´´æ¿"); |
| | | }).catch(() => { |
| | | }) |
| | | .catch(() => { |
| | | ElMessage.error("å¤å¶å¤±è´¥ï¼è¯·æå¨å¤å¶"); |
| | | }); |
| | | }; |
| | |
| | | // æ¶èç¥è¯ |
| | | const markAsFavorite = () => { |
| | | // å¢å ä½¿ç¨æ¬¡æ° |
| | | const index = mockData.findIndex(item => item.id === currentKnowledge.value.id); |
| | | const index = mockData.findIndex( |
| | | item => item.id === currentKnowledge.value.id |
| | | ); |
| | | if (index !== -1) { |
| | | mockData[index].usageCount += 1; |
| | | currentKnowledge.value.usageCount += 1; |
| | |
| | | await formRef.value.validate(); |
| | | if (dialogType.value === "add") { |
| | | // æ°å¢ç¥è¯ |
| | | addKnowledgeBase({...form.value}).then(res => { |
| | | addKnowledgeBase({ ...form.value }) |
| | | .then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("æ·»å æå"); |
| | | dialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | } else { |
| | | updateKnowledgeBase({...form.value}).then(res => { |
| | | updateKnowledgeBase({ ...form.value }) |
| | | .then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("æ´æ°æå"); |
| | | dialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | } |
| | | } catch (error) { |
| | | console.error("表åéªè¯å¤±è´¥:", error); |
| | |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).then(() => { |
| | | }) |
| | | .then(() => { |
| | | // console.log(selectedIds.value); |
| | | delKnowledgeBase(selectedIds.value).then(res => { |
| | | if(res.code == 200){ |
| | |
| | | selectedIds.value = []; |
| | | getList(); |
| | | } |
| | | }); |
| | | }) |
| | | }).catch(() => { |
| | | .catch(() => { |
| | | // ç¨æ·åæ¶ |
| | | }); |
| | | }; |
| | | |
| | | // å¯¼åº |
| | | const { proxy } = getCurrentInstance() |
| | | const { proxy } = getCurrentInstance(); |
| | | const handleExport = () => { |
| | | proxy.download('/knowledgeBase/export', { ...searchForm.value }, 'ç¥è¯åº.xlsx') |
| | | } |
| | | proxy.download( |
| | | "/knowledgeBase/export", |
| | | { ...searchForm.value }, |
| | | "ç¥è¯åº.xlsx" |
| | | ); |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped> |
| | |
| | | color: #606266; |
| | | line-height: 1.6; |
| | | font-size: 14px; |
| | | word-wrap: break-word; |
| | | } |
| | | |
| | | .card-footer { |
| | |
| | | border-left: 3px solid #409eff; |
| | | } |
| | | |
| | | .card-remark span { |
| | | flex: 1; |
| | | min-width: 0; |
| | | word-wrap: break-word; |
| | | word-break: break-all; |
| | | white-space: normal; |
| | | line-height: 1.5; |
| | | } |
| | | |
| | | .empty-state { |
| | | text-align: center; |
| | | padding: 60px 20px; |
| | |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title">éç¥æ é¢ï¼</span> |
| | | <el-input |
| | | v-model="searchForm.title" |
| | | <el-input v-model="searchForm.title" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥éç¥æ é¢æç´¢" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | /> |
| | | :prefix-icon="Search" /> |
| | | <span class="search_title ml10">éç¥ç±»åï¼</span> |
| | | <el-select v-model="searchForm.type" clearable @change="handleQuery" style="width: 240px"> |
| | | <el-option label="æ¾åéç¥" :value="'holiday'" /> |
| | | <el-option label="å¤ç½éç¥" :value="'penalty'" /> |
| | | <el-option label="å¼ä¼éç¥" :value="'meeting'" /> |
| | | <el-option label="临æ¶éç¥" :value="'temporary'" /> |
| | | <el-option label="æ£å¼éç¥" :value="'formal'" /> |
| | | <el-select v-model="searchForm.type" |
| | | clearable |
| | | @change="handleQuery" |
| | | style="width: 240px"> |
| | | <el-option label="æ¾åéç¥" |
| | | :value="'holiday'" /> |
| | | <el-option label="å¤ç½éç¥" |
| | | :value="'penalty'" /> |
| | | <el-option label="å¼ä¼éç¥" |
| | | :value="'meeting'" /> |
| | | <el-option label="临æ¶éç¥" |
| | | :value="'temporary'" /> |
| | | <el-option label="æ£å¼éç¥" |
| | | :value="'formal'" /> |
| | | </el-select> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px"> |
| | | <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="success" @click="openMeetingDialog">å¨çº¿ä¼è®®</el-button> |
| | | <el-button type="warning" @click="openFileShareDialog">æä»¶å
񄧮</el-button> |
| | | <el-button type="primary" |
| | | @click="openForm('add')">æ°å¢éç¥</el-button> |
| | | <el-button type="success" |
| | | @click="openMeetingDialog">å¨çº¿ä¼è®®</el-button> |
| | | <el-button type="warning" |
| | | @click="openFileShareDialog">æä»¶å
񄧮</el-button> |
| | | <!-- <el-button type="info" @click="refreshEmployees">å·æ°åå·¥</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" |
| | | <PIMTable rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | :total="page.total" |
| | | ></PIMTable> |
| | | :total="page.total"></PIMTable> |
| | | </div> |
| | | |
| | | <!-- æ°å¢/ç¼è¾éç¥å¼¹çª --> |
| | | <el-dialog |
| | | v-model="dialogVisible" |
| | | <el-dialog v-model="dialogVisible" |
| | | :title="dialogTitle" |
| | | width="800px" |
| | | :close-on-click-modal="false" |
| | | > |
| | | <el-form ref="formRef" :model="form" :rules="rules" label-width="120px"> |
| | | :close-on-click-modal="false"> |
| | | <el-form ref="formRef" |
| | | :model="form" |
| | | :rules="rules" |
| | | label-width="120px"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éç¥æ é¢" prop="title"> |
| | | <el-input v-model="form.title" placeholder="请è¾å
¥éç¥æ é¢" /> |
| | | <el-form-item label="éç¥æ é¢" |
| | | prop="title"> |
| | | <el-input v-model="form.title" |
| | | placeholder="请è¾å
¥éç¥æ é¢" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éç¥ç±»å" prop="type"> |
| | | <el-select v-model="form.type" placeholder="è¯·éæ©éç¥ç±»å" style="width: 100%"> |
| | | <el-option label="æ¾åéç¥" value="holiday" /> |
| | | <el-option label="å¤ç½éç¥" value="penalty" /> |
| | | <el-option label="å¼ä¼éç¥" value="meeting" /> |
| | | <el-option label="临æ¶éç¥" value="temporary" /> |
| | | <el-option label="æ£å¼éç¥" value="formal" /> |
| | | <el-form-item label="éç¥ç±»å" |
| | | prop="type"> |
| | | <el-select v-model="form.type" |
| | | placeholder="è¯·éæ©éç¥ç±»å" |
| | | style="width: 100%"> |
| | | <el-option label="æ¾åéç¥" |
| | | value="holiday" /> |
| | | <el-option label="å¤ç½éç¥" |
| | | value="penalty" /> |
| | | <el-option label="å¼ä¼éç¥" |
| | | value="meeting" /> |
| | | <el-option label="临æ¶éç¥" |
| | | value="temporary" /> |
| | | <el-option label="æ£å¼éç¥" |
| | | value="formal" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¼å
级" prop="priority"> |
| | | <el-select v-model="form.priority" placeholder="è¯·éæ©ä¼å
级" style="width: 100%"> |
| | | <el-option label="æ®é" value="low" /> |
| | | <el-option label="éè¦" value="medium" /> |
| | | <el-option label="ç´§æ¥" value="high" /> |
| | | <el-form-item label="ä¼å
级" |
| | | prop="priority"> |
| | | <el-select v-model="form.priority" |
| | | placeholder="è¯·éæ©ä¼å
级" |
| | | style="width: 100%"> |
| | | <el-option label="æ®é" |
| | | value="low" /> |
| | | <el-option label="éè¦" |
| | | value="medium" /> |
| | | <el-option label="ç´§æ¥" |
| | | value="high" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æææè³" prop="expireDate"> |
| | | <el-date-picker |
| | | v-model="form.expireDate" |
| | | <el-form-item label="æææè³" |
| | | prop="expireDate"> |
| | | <el-date-picker v-model="form.expireDate" |
| | | type="date" |
| | | placeholder="è¯·éæ©æææ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | style="width: 100%" |
| | | /> |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-form-item label="æ¥æ¶é¨é¨" prop="departments"> |
| | | <el-select |
| | | v-model="form.departments" |
| | | <el-form-item label="æ¥æ¶é¨é¨" |
| | | prop="departments"> |
| | | <el-select v-model="form.departments" |
| | | multiple |
| | | placeholder="è¯·éæ©æ¥æ¶é¨é¨" |
| | | style="width: 100%" |
| | | > |
| | | <el-option |
| | | v-for="dept in departments" |
| | | style="width: 100%"> |
| | | <el-option v-for="dept in departments" |
| | | :key="dept" |
| | | :label="dept" |
| | | :value="dept" |
| | | /> |
| | | :value="dept" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="忥æ¹å¼" prop="syncMethods"> |
| | | <el-form-item label="忥æ¹å¼" |
| | | prop="syncMethods"> |
| | | <el-checkbox-group v-model="form.syncMethods"> |
| | | <el-checkbox |
| | | v-for="method in syncMethods" |
| | | <el-checkbox v-for="method in syncMethods" |
| | | :key="method.value" |
| | | :label="method.value" |
| | | > |
| | | :label="method.value"> |
| | | {{ method.label }} |
| | | </el-checkbox> |
| | | </el-checkbox-group> |
| | | </el-form-item> |
| | | <el-form-item label="éç¥å
容" prop="content"> |
| | | <el-input |
| | | v-model="form.content" |
| | | <el-form-item label="éç¥å
容" |
| | | prop="content"> |
| | | <el-input v-model="form.content" |
| | | type="textarea" |
| | | :rows="4" |
| | | placeholder="请è¾å
¥éç¥å
容" |
| | | /> |
| | | placeholder="请è¾å
¥éç¥å
容" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="submitForm">ç¡®å®</el-button> |
| | | <el-button @click="dialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="submitForm">ç¡®å®</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- å¨çº¿ä¼è®®å¼¹çª --> |
| | | <el-dialog |
| | | v-model="meetingDialogVisible" |
| | | <el-dialog v-model="meetingDialogVisible" |
| | | title="å建å¨çº¿ä¼è®®" |
| | | width="700px" |
| | | :close-on-click-modal="false" |
| | | > |
| | | <el-form ref="meetingFormRef" :model="meetingForm" :rules="meetingRules" label-width="120px"> |
| | | <el-form-item label="ä¼è®®æ é¢" prop="title"> |
| | | <el-input v-model="meetingForm.title" placeholder="请è¾å
¥ä¼è®®æ é¢" /> |
| | | :close-on-click-modal="false"> |
| | | <el-form ref="meetingFormRef" |
| | | :model="meetingForm" |
| | | :rules="meetingRules" |
| | | label-width="120px"> |
| | | <el-form-item label="ä¼è®®æ é¢" |
| | | prop="title"> |
| | | <el-input v-model="meetingForm.title" |
| | | placeholder="请è¾å
¥ä¼è®®æ é¢" /> |
| | | </el-form-item> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å¼å§æ¶é´" prop="startTime"> |
| | | <el-date-picker |
| | | v-model="meetingForm.startTime" |
| | | <el-form-item label="å¼å§æ¶é´" |
| | | prop="startTime"> |
| | | <el-date-picker v-model="meetingForm.startTime" |
| | | type="datetime" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | format="YYYY-MM-DD HH:mm:ss" |
| | | placeholder="è¯·éæ©å¼å§æ¶é´" |
| | | style="width: 100%" |
| | | /> |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¼è®®æ¶é¿" prop="duration"> |
| | | <el-input-number |
| | | v-model="meetingForm.duration" |
| | | <el-form-item label="ä¼è®®æ¶é¿" |
| | | prop="duration"> |
| | | <el-input-number v-model="meetingForm.duration" |
| | | :min="15" |
| | | :max="480" |
| | | :step="15" |
| | | style="width: 100%" |
| | | /> |
| | | style="width: 100%" /> |
| | | <span style="margin-left: 10px">åé</span> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-form-item label="ä¼è®®å¹³å°" prop="platform"> |
| | | <el-select v-model="meetingForm.platform" placeholder="è¯·éæ©ä¼è®®å¹³å°" style="width: 100%"> |
| | | <el-option |
| | | v-for="platform in meetingPlatforms" |
| | | <el-form-item label="ä¼è®®å¹³å°" |
| | | prop="platform"> |
| | | <el-select v-model="meetingForm.platform" |
| | | placeholder="è¯·éæ©ä¼è®®å¹³å°" |
| | | style="width: 100%"> |
| | | <el-option v-for="platform in meetingPlatforms" |
| | | :key="platform.value" |
| | | :label="platform.label" |
| | | :value="platform.value" |
| | | /> |
| | | :value="platform.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="åä¼äººå" prop="participants"> |
| | | <el-select |
| | | v-model="meetingForm.participants" |
| | | <el-form-item label="åä¼äººå" |
| | | prop="participants"> |
| | | <el-select v-model="meetingForm.participants" |
| | | multiple |
| | | filterable |
| | | remote |
| | | :remote-method="filterEmployees" |
| | | :loading="employeesLoading" |
| | | placeholder="è¯·éæ©åä¼äººå" |
| | | style="width: 100%" |
| | | > |
| | | <el-option-group |
| | | v-for="group in employeeGroups" |
| | | style="width: 100%"> |
| | | <el-option-group v-for="group in employeeGroups" |
| | | :key="group.label" |
| | | :label="group.label" |
| | | > |
| | | <el-option |
| | | v-for="employee in group.options" |
| | | :label="group.label"> |
| | | <el-option v-for="employee in group.options" |
| | | :key="employee.value" |
| | | :label="`${employee.label} (${employee.dept})`" |
| | | :value="employee.value" |
| | | > |
| | | :value="employee.value"> |
| | | <div style="display: flex; justify-content: space-between; align-items: center;"> |
| | | <div> |
| | | <div style="font-weight: 500;">{{ employee.label }}</div> |
| | |
| | | 已鿩 {{ meetingForm.participants.length }} 人 |
| | | </div> |
| | | <!-- å·²éæ©äººå详æ
--> |
| | | <div v-if="meetingForm.participants.length > 0" style="margin-top: 10px;"> |
| | | <el-tag |
| | | v-for="participantId in meetingForm.participants" |
| | | <div v-if="meetingForm.participants.length > 0" |
| | | style="margin-top: 10px;"> |
| | | <el-tag v-for="participantId in meetingForm.participants" |
| | | :key="participantId" |
| | | closable |
| | | @close="removeParticipant(participantId)" |
| | | style="margin-right: 8px; margin-bottom: 8px;" |
| | | > |
| | | style="margin-right: 8px; margin-bottom: 8px;"> |
| | | {{ getEmployeeName(participantId) }} |
| | | </el-tag> |
| | | </div> |
| | | </el-form-item> |
| | | <el-form-item label="ä¼è®®æè¿°" prop="description"> |
| | | <el-input |
| | | v-model="meetingForm.description" |
| | | <el-form-item label="ä¼è®®æè¿°" |
| | | prop="description"> |
| | | <el-input v-model="meetingForm.description" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥ä¼è®®æè¿°" |
| | | /> |
| | | placeholder="请è¾å
¥ä¼è®®æè¿°" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="createMeeting">å建ä¼è®®</el-button> |
| | | <el-button @click="meetingDialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="createMeeting">å建ä¼è®®</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- æä»¶å
±äº«å¼¹çª --> |
| | | <el-dialog |
| | | v-model="fileShareDialogVisible" |
| | | <el-dialog v-model="fileShareDialogVisible" |
| | | title="æä»¶å
񄧮" |
| | | width="700px" |
| | | :close-on-click-modal="false" |
| | | > |
| | | <el-form ref="fileShareFormRef" :model="fileShareForm" :rules="fileShareRules" label-width="120px"> |
| | | <el-form-item label="å
±äº«æ é¢" prop="title"> |
| | | <el-input v-model="fileShareForm.title" placeholder="请è¾å
¥å
±äº«æ é¢" /> |
| | | :close-on-click-modal="false"> |
| | | <el-form ref="fileShareFormRef" |
| | | :model="fileShareForm" |
| | | :rules="fileShareRules" |
| | | label-width="120px"> |
| | | <el-form-item label="å
±äº«æ é¢" |
| | | prop="title"> |
| | | <el-input v-model="fileShareForm.title" |
| | | placeholder="请è¾å
¥å
±äº«æ é¢" /> |
| | | </el-form-item> |
| | | <el-form-item label="å
±äº«æè¿°" prop="description"> |
| | | <el-input |
| | | v-model="fileShareForm.description" |
| | | <el-form-item label="å
±äº«æè¿°" |
| | | prop="description"> |
| | | <el-input v-model="fileShareForm.description" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥å
±äº«æè¿°" |
| | | /> |
| | | placeholder="请è¾å
¥å
±äº«æè¿°" /> |
| | | </el-form-item> |
| | | <el-form-item label="æ¥æ¶é¨é¨" prop="departments"> |
| | | <el-select |
| | | v-model="fileShareForm.departments" |
| | | <el-form-item label="æ¥æ¶é¨é¨" |
| | | prop="departments"> |
| | | <el-select v-model="fileShareForm.departments" |
| | | multiple |
| | | placeholder="è¯·éæ©æ¥æ¶é¨é¨" |
| | | style="width: 100%" |
| | | > |
| | | <el-option |
| | | v-for="dept in departments" |
| | | style="width: 100%"> |
| | | <el-option v-for="dept in departments" |
| | | :key="dept" |
| | | :label="dept" |
| | | :value="dept" |
| | | /> |
| | | :value="dept" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="ä¸ä¼ æä»¶" prop="files"> |
| | | <el-upload |
| | | ref="uploadRef" |
| | | <el-form-item label="ä¸ä¼ æä»¶" |
| | | prop="files"> |
| | | <el-upload ref="uploadRef" |
| | | :auto-upload="false" |
| | | :on-change="handleFileChange" |
| | | :on-remove="removeFile" |
| | | :file-list="fileList" |
| | | multiple |
| | | :limit="10" |
| | | accept=".doc,.docx,.pdf,.xls,.xlsx,.ppt,.pptx,.txt,.jpg,.jpeg,.png,.gif" |
| | | > |
| | | accept=".doc,.docx,.pdf,.xls,.xlsx,.ppt,.pptx,.txt,.jpg,.jpeg,.png,.gif"> |
| | | <el-button type="primary">éæ©æä»¶</el-button> |
| | | <template #tip> |
| | | <div class="el-upload__tip"> |
| | |
| | | </el-form> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="shareFiles">å
±äº«æä»¶</el-button> |
| | | <el-button @click="fileShareDialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="shareFiles">å
±äº«æä»¶</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | |
| | | import PIMTable from "@/components/PIMTable/PIMTable.vue"; |
| | | import { userListNoPageByTenantId } from "@/api/system/user.js"; |
| | | import { staffOnJobListPage } from "@/api/personnelManagement/employeeRecord.js"; |
| | | import { listNotification, addNotification, updateNotification, delNotification,addOnlineMeeting,addFileSharing } from "@/api/collaborativeApproval/notificationManagement.js"; |
| | | import { |
| | | listNotification, |
| | | addNotification, |
| | | updateNotification, |
| | | delNotification, |
| | | addOnlineMeeting, |
| | | addFileSharing, |
| | | } from "@/api/collaborativeApproval/notificationManagement.js"; |
| | | import { id } from "element-plus/es/locales.mjs"; |
| | | |
| | | // 表åéªè¯è§å |
| | | const rules = { |
| | | title: [ |
| | | { required: true, message: "请è¾å
¥éç¥æ é¢", trigger: "blur" } |
| | | ], |
| | | type: [ |
| | | { required: true, message: "è¯·éæ©éç¥ç±»å", trigger: "change" } |
| | | ], |
| | | content: [ |
| | | { required: true, message: "请è¾å
¥éç¥å
容", trigger: "blur" } |
| | | ] |
| | | title: [{ required: true, message: "请è¾å
¥éç¥æ é¢", trigger: "blur" }], |
| | | type: [{ required: true, message: "è¯·éæ©éç¥ç±»å", trigger: "change" }], |
| | | content: [{ required: true, message: "请è¾å
¥éç¥å
容", trigger: "blur" }], |
| | | }; |
| | | |
| | | const meetingRules = { |
| | | title: [ |
| | | { required: true, message: "请è¾å
¥ä¼è®®æ é¢", trigger: "blur" } |
| | | ], |
| | | title: [{ required: true, message: "请è¾å
¥ä¼è®®æ é¢", trigger: "blur" }], |
| | | startTime: [ |
| | | { required: true, message: "è¯·éæ©ä¼è®®å¼å§æ¶é´", trigger: "change" } |
| | | { required: true, message: "è¯·éæ©ä¼è®®å¼å§æ¶é´", trigger: "change" }, |
| | | ], |
| | | participants: [ |
| | | { required: true, message: "è¯·éæ©åä¼äººå", trigger: "change" } |
| | | ] |
| | | { required: true, message: "è¯·éæ©åä¼äººå", trigger: "change" }, |
| | | ], |
| | | }; |
| | | |
| | | const fileShareRules = { |
| | | title: [ |
| | | { required: true, message: "请è¾å
¥å
±äº«æ é¢", trigger: "blur" } |
| | | ], |
| | | description: [ |
| | | { required: true, message: "请è¾å
¥å
±äº«æè¿°", trigger: "blur" } |
| | | ] |
| | | title: [{ required: true, message: "请è¾å
¥å
±äº«æ é¢", trigger: "blur" }], |
| | | description: [{ required: true, message: "请è¾å
¥å
±äº«æè¿°", trigger: "blur" }], |
| | | }; |
| | | |
| | | // ååºå¼æ°æ® |
| | |
| | | content: "", |
| | | departments: [], |
| | | expireDate: "", |
| | | syncMethods: [] |
| | | syncMethods: [], |
| | | }, |
| | | dialogVisible: false, |
| | | dialogTitle: "", |
| | |
| | | duration: 60, |
| | | participants: [], |
| | | description: "", |
| | | platform: "wechat" |
| | | platform: "wechat", |
| | | }, |
| | | // æä»¶å
±äº«ç¸å
³ |
| | | fileShareDialogVisible: false, |
| | |
| | | title: "", |
| | | description: "", |
| | | departments: [], |
| | | files: [] |
| | | files: [], |
| | | }, |
| | | fileList: [] |
| | | fileList: [], |
| | | }); |
| | | |
| | | const { |
| | |
| | | meetingForm, |
| | | fileShareDialogVisible, |
| | | fileShareForm, |
| | | fileList |
| | | fileList, |
| | | } = toRefs(data); |
| | | |
| | | // 表åå¼ç¨ |
| | |
| | | label: "éç¥ç±»å", |
| | | prop: "type", |
| | | dataType: "tag", |
| | | formatData: (params) => { |
| | | formatData: params => { |
| | | const typeMap = { |
| | | holiday: "æ¾åéç¥", |
| | | penalty: "å¤ç½éç¥", |
| | | meeting: "å¼ä¼éç¥", |
| | | temporary: "临æ¶éç¥", |
| | | formal: "æ£å¼éç¥" |
| | | formal: "æ£å¼éç¥", |
| | | }; |
| | | return typeMap[params] || params; |
| | | }, |
| | | formatType: (params) => { |
| | | formatType: params => { |
| | | const typeMap = { |
| | | holiday: "success", |
| | | penalty: "danger", |
| | | meeting: "warning", |
| | | temporary: "info", |
| | | formal: "primary" |
| | | formal: "primary", |
| | | }; |
| | | return typeMap[params] || "info"; |
| | | } |
| | | }, |
| | | }, |
| | | { |
| | | label: "ä¼å
级", |
| | | prop: "priority", |
| | | dataType: "tag", |
| | | formatData: (params) => { |
| | | formatData: params => { |
| | | const priorityMap = { |
| | | low: "æ®é", |
| | | medium: "éè¦", |
| | | high: "ç´§æ¥" |
| | | high: "ç´§æ¥", |
| | | }; |
| | | return priorityMap[params] || params; |
| | | }, |
| | | formatType: (params) => { |
| | | formatType: params => { |
| | | const typeMap = { |
| | | low: "info", |
| | | medium: "warning", |
| | | high: "danger" |
| | | high: "danger", |
| | | }; |
| | | return typeMap[params] || "info"; |
| | | } |
| | | }, |
| | | }, |
| | | { |
| | | label: "ç¶æ", |
| | | prop: "status", |
| | | dataType: "tag", |
| | | formatData: (params) => { |
| | | formatData: params => { |
| | | const statusMap = { |
| | | draft: "è稿", |
| | | published: "å·²åå¸", |
| | | expired: "å·²è¿æ" |
| | | expired: "å·²è¿æ", |
| | | }; |
| | | return statusMap[params] || params; |
| | | }, |
| | | formatType: (params) => { |
| | | formatType: params => { |
| | | const typeMap = { |
| | | draft: "info", |
| | | published: "success", |
| | | expired: "danger" |
| | | expired: "danger", |
| | | }; |
| | | return typeMap[params] || "info"; |
| | | } |
| | | }, |
| | | }, |
| | | { |
| | | label: "æ¥æ¶é¨é¨", |
| | | prop: "departments", |
| | | width: 150, |
| | | showOverflowTooltip: true, |
| | | formatData: (params) => { |
| | | formatData: params => { |
| | | if (!params || params.length === 0) return "å
¨é¨é¨é¨"; |
| | | return params.join(", "); |
| | | } |
| | | }, |
| | | }, |
| | | { |
| | | label: "æææè³", |
| | | prop: "expireDate", |
| | | width: 150, |
| | | formatData: (params) => { |
| | | formatData: params => { |
| | | if (!params) return "æ°¸ä¹
ææ"; |
| | | return params; |
| | | } |
| | | }, |
| | | }, |
| | | { |
| | | label: "å建æ¶é´", |
| | |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | clickFun: row => { |
| | | openForm("edit", row); |
| | | } |
| | | }, |
| | | }, |
| | | { |
| | | name: "åå¸", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | clickFun: row => { |
| | | publishNotification(row); |
| | | }, |
| | | // disabled: (row) => row.status === "published" |
| | |
| | | { |
| | | name: "æ¤å", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | clickFun: row => { |
| | | revokeNotification(row); |
| | | }, |
| | | // disabled: (row) => row.status !== "published" |
| | | } |
| | | ] |
| | | } |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | | // éç¥æ 颿¨¡æ¿ |
| | | const titleTemplates = [ |
| | |
| | | "{dept}é¨é¨å·¥ä½å®æéç¥", |
| | | "å
³äº{project}项ç®è¿åº¦çéç¥", |
| | | "{dept}é¨é¨äººåè°æ´éç¥", |
| | | "å
¬å¸{policy}æ¿çæ´æ°éç¥" |
| | | "å
¬å¸{policy}æ¿çæ´æ°éç¥", |
| | | ]; |
| | | |
| | | // éç¥ç±»åé
ç½® |
| | |
| | | { type: "meeting", label: "å¼ä¼éç¥", priority: "medium" }, |
| | | { type: "penalty", label: "å¤ç½éç¥", priority: "high" }, |
| | | { type: "temporary", label: "临æ¶éç¥", priority: "low" }, |
| | | { type: "formal", label: "æ£å¼éç¥", priority: "medium" } |
| | | { type: "formal", label: "æ£å¼éç¥", priority: "medium" }, |
| | | ]; |
| | | |
| | | // é¨é¨å表 |
| | | const departments = ["ææ¯é¨", "éå®é¨", "人äºé¨", "è´¢å¡é¨", "è¿è¥é¨", "å¸åºé¨", "客æé¨"]; |
| | | const departments = [ |
| | | "ææ¯é¨", |
| | | "éå®é¨", |
| | | "人äºé¨", |
| | | "è´¢å¡é¨", |
| | | "è¿è¥é¨", |
| | | "å¸åºé¨", |
| | | "客æé¨", |
| | | ]; |
| | | |
| | | // 人åå表 |
| | | const employees = ref([]); |
| | |
| | | const userResponse = await userListNoPageByTenantId(); |
| | | |
| | | if (userResponse.data) { |
| | | employees.value = userResponse.data.map(user => ({ |
| | | label: user.nickName || user.userName || 'æªç¥å§å', |
| | | employees.value = userResponse.data |
| | | .map(user => ({ |
| | | label: user.nickName || user.userName || "æªç¥å§å", |
| | | value: user.userId || user.id, |
| | | dept: user.dept?.deptName || 'æªç¥é¨é¨', |
| | | phone: user.phonenumber || '', |
| | | email: user.email || '', |
| | | status: user.status || '0' |
| | | })).filter(user => user.status === '0'); // åªæ¾ç¤ºæ£å¸¸ç¶æçç¨æ· |
| | | dept: user.dept?.deptName || "æªç¥é¨é¨", |
| | | phone: user.phonenumber || "", |
| | | email: user.email || "", |
| | | status: user.status || "0", |
| | | })) |
| | | .filter(user => user.status === "0"); // åªæ¾ç¤ºæ£å¸¸ç¶æçç¨æ· |
| | | } else { |
| | | // å¦æç³»ç»ç¨æ·æ¥å£å¤±è´¥ï¼ä½¿ç¨åå·¥å°è´¦æ¥å£ |
| | | const response = await staffOnJobListPage({ |
| | | pageNum: 1, |
| | | pageSize: 1000, |
| | | staffState: 1 // å¨èç¶æ |
| | | staffState: 1, // å¨èç¶æ |
| | | }); |
| | | |
| | | if (response.data && response.data.records) { |
| | | employees.value = response.data.records.map(employee => ({ |
| | | label: employee.staffName || employee.name || 'æªç¥å§å', |
| | | label: employee.staffName || employee.name || "æªç¥å§å", |
| | | value: employee.staffNo || employee.id || employee.staffId, |
| | | dept: employee.deptName || employee.department || 'æªç¥é¨é¨', |
| | | phone: employee.phone || employee.mobile || '', |
| | | email: employee.email || '', |
| | | status: '0' |
| | | dept: employee.deptName || employee.department || "æªç¥é¨é¨", |
| | | phone: employee.phone || employee.mobile || "", |
| | | email: employee.email || "", |
| | | status: "0", |
| | | })); |
| | | } |
| | | } |
| | | } catch (error) { |
| | | console.error('è·ååå·¥å表失败:', error); |
| | | console.error("è·ååå·¥å表失败:", error); |
| | | // 妿æ¥å£é½å¤±è´¥ï¼ä½¿ç¨é»è®¤æ°æ® |
| | | employees.value = [ |
| | | { label: "å¼ ä¸", value: "001", dept: "ææ¯é¨", phone: "13800138001", email: "zhangsan@company.com", status: "0" }, |
| | | { label: "æå", value: "002", dept: "éå®é¨", phone: "13800138002", email: "lisi@company.com", status: "0" }, |
| | | { label: "çäº", value: "003", dept: "人äºé¨", phone: "13800138003", email: "wangwu@company.com", status: "0" } |
| | | { |
| | | label: "å¼ ä¸", |
| | | value: "001", |
| | | dept: "ææ¯é¨", |
| | | phone: "13800138001", |
| | | email: "zhangsan@company.com", |
| | | status: "0", |
| | | }, |
| | | { |
| | | label: "æå", |
| | | value: "002", |
| | | dept: "éå®é¨", |
| | | phone: "13800138002", |
| | | email: "lisi@company.com", |
| | | status: "0", |
| | | }, |
| | | { |
| | | label: "çäº", |
| | | value: "003", |
| | | dept: "人äºé¨", |
| | | phone: "13800138003", |
| | | email: "wangwu@company.com", |
| | | status: "0", |
| | | }, |
| | | ]; |
| | | } finally { |
| | | employeesLoading.value = false; |
| | |
| | | const employeeGroups = computed(() => { |
| | | const groups = {}; |
| | | employees.value.forEach(employee => { |
| | | const dept = employee.dept || 'å
¶ä»é¨é¨'; |
| | | const dept = employee.dept || "å
¶ä»é¨é¨"; |
| | | if (!groups[dept]) { |
| | | groups[dept] = []; |
| | | } |
| | |
| | | .sort() |
| | | .map(dept => ({ |
| | | label: dept, |
| | | options: groups[dept].sort((a, b) => a.label.localeCompare(b.label, 'zh-CN')) |
| | | options: groups[dept].sort((a, b) => |
| | | a.label.localeCompare(b.label, "zh-CN") |
| | | ), |
| | | })); |
| | | }); |
| | | |
| | | // è¿æ»¤åå·¥ï¼è¿ç¨æç´¢ï¼ |
| | | const filterEmployees = (query) => { |
| | | if (query !== '') { |
| | | const filterEmployees = query => { |
| | | if (query !== "") { |
| | | const lowerQuery = query.toLowerCase(); |
| | | return employees.value.filter(employee => |
| | | return employees.value.filter( |
| | | employee => |
| | | employee.label.toLowerCase().includes(lowerQuery) || |
| | | employee.dept.toLowerCase().includes(lowerQuery) || |
| | | (employee.phone && employee.phone.includes(query)) || |
| | |
| | | // ç»è®¡åé¨é¨äººæ° |
| | | const deptStats = {}; |
| | | employees.value.forEach(emp => { |
| | | const dept = emp.dept || 'å
¶ä»é¨é¨'; |
| | | const dept = emp.dept || "å
¶ä»é¨é¨"; |
| | | deptStats[dept] = (deptStats[dept] || 0) + 1; |
| | | }); |
| | | |
| | | const deptInfo = Object.entries(deptStats) |
| | | .map(([dept, count]) => `${dept}: ${count}人`) |
| | | .join(', '); |
| | | .join(", "); |
| | | |
| | | ElMessage.success(`åå·¥åè¡¨å·æ°å®æï¼å
± ${employees.value.length} 人 (${deptInfo})`); |
| | | ElMessage.success( |
| | | `åå·¥åè¡¨å·æ°å®æï¼å
± ${employees.value.length} 人 (${deptInfo})` |
| | | ); |
| | | }; |
| | | |
| | | // è·ååå·¥å§å |
| | | const getEmployeeName = (employeeId) => { |
| | | const getEmployeeName = employeeId => { |
| | | const employee = employees.value.find(emp => emp.value === employeeId); |
| | | return employee ? employee.label : 'æªç¥äººå'; |
| | | return employee ? employee.label : "æªç¥äººå"; |
| | | }; |
| | | |
| | | // è·åå工详ç»ä¿¡æ¯ |
| | | const getEmployeeInfo = (employeeId) => { |
| | | const getEmployeeInfo = employeeId => { |
| | | const employee = employees.value.find(emp => emp.value === employeeId); |
| | | if (!employee) return null; |
| | | |
| | |
| | | name: employee.label, |
| | | dept: employee.dept, |
| | | phone: employee.phone, |
| | | email: employee.email |
| | | email: employee.email, |
| | | }; |
| | | }; |
| | | |
| | | // ç§»é¤åä¼äººå |
| | | const removeParticipant = (participantId) => { |
| | | const removeParticipant = participantId => { |
| | | const index = meetingForm.value.participants.indexOf(participantId); |
| | | if (index > -1) { |
| | | meetingForm.value.participants.splice(index, 1); |
| | |
| | | { label: "ä¼ä¸å¾®ä¿¡", value: "wechat" }, |
| | | { label: "éé", value: "dingtalk" }, |
| | | { label: "é®ä»¶", value: "email" }, |
| | | { label: "çä¿¡", value: "sms" } |
| | | { label: "çä¿¡", value: "sms" }, |
| | | ]; |
| | | |
| | | // ä¼è®®å¹³å°é项 |
| | |
| | | { label: "ä¼ä¸å¾®ä¿¡ä¼è®®", value: "wechat" }, |
| | | { label: "ééä¼è®®", value: "dingtalk" }, |
| | | { label: "è
¾è®¯ä¼è®®", value: "tencent" }, |
| | | { label: "Zoom", value: "zoom" } |
| | | { label: "Zoom", value: "zoom" }, |
| | | ]; |
| | | |
| | | // èªå¨çææ°æ°æ® |
| | | const generateNewData = () => { |
| | | const newId = (mockData.length + 1).toString(); |
| | | const now = new Date(); |
| | | const randomType = notificationTypes[Math.floor(Math.random() * notificationTypes.length)]; |
| | | const randomDept = departments[Math.floor(Math.random() * departments.length)]; |
| | | const randomType = |
| | | notificationTypes[Math.floor(Math.random() * notificationTypes.length)]; |
| | | const randomDept = |
| | | departments[Math.floor(Math.random() * departments.length)]; |
| | | |
| | | // çæéæºæ é¢ |
| | | let title = titleTemplates[Math.floor(Math.random() * titleTemplates.length)]; |
| | | title = title |
| | | .replace('{year}', now.getFullYear()) |
| | | .replace('{holiday}', ['æ¥è', 'å½åº', 'ä¸ç§', 'å
æ¦'][Math.floor(Math.random() * 4)]) |
| | | .replace('{dept}', randomDept) |
| | | .replace('{meeting}', ['å¨ä¾ä¼', 'æåº¦æ»ç»', '项ç®è¯å®¡', 'å¹è®ä¼è®®'][Math.floor(Math.random() * 4)]) |
| | | .replace('{behavior}', ['èå¤', 'çè£
', 'å·¥ä½æåº¦', 'å¢éåä½'][Math.floor(Math.random() * 4)]) |
| | | .replace('{company}', ['å
¬å¸', 'éå¢', 'æ»é¨'][Math.floor(Math.random() * 4)]) |
| | | .replace('{project}', ['æ°åå转å', '产åå级', 'å¸åºæå±', '人æå¹å
»'][Math.floor(Math.random() * 4)]) |
| | | .replace('{policy}', ['èå¤', 'èªé
¬', 'ç¦å©', 'æå'][Math.floor(Math.random() * 4)]); |
| | | .replace("{year}", now.getFullYear()) |
| | | .replace( |
| | | "{holiday}", |
| | | ["æ¥è", "å½åº", "ä¸ç§", "å
æ¦"][Math.floor(Math.random() * 4)] |
| | | ) |
| | | .replace("{dept}", randomDept) |
| | | .replace( |
| | | "{meeting}", |
| | | ["å¨ä¾ä¼", "æåº¦æ»ç»", "项ç®è¯å®¡", "å¹è®ä¼è®®"][ |
| | | Math.floor(Math.random() * 4) |
| | | ] |
| | | ) |
| | | .replace( |
| | | "{behavior}", |
| | | ["èå¤", "çè£
", "å·¥ä½æåº¦", "å¢éåä½"][Math.floor(Math.random() * 4)] |
| | | ) |
| | | .replace( |
| | | "{company}", |
| | | ["å
¬å¸", "éå¢", "æ»é¨"][Math.floor(Math.random() * 4)] |
| | | ) |
| | | .replace( |
| | | "{project}", |
| | | ["æ°åå转å", "产åå级", "å¸åºæå±", "人æå¹å
»"][ |
| | | Math.floor(Math.random() * 4) |
| | | ] |
| | | ) |
| | | .replace( |
| | | "{policy}", |
| | | ["èå¤", "èªé
¬", "ç¦å©", "æå"][Math.floor(Math.random() * 4)] |
| | | ); |
| | | |
| | | // éæºç¶æ |
| | | const statuses = ['draft', 'published']; |
| | | const statuses = ["draft", "published"]; |
| | | const randomStatus = statuses[Math.floor(Math.random() * statuses.length)]; |
| | | |
| | | // éæºä¼å
级 |
| | | const priorities = ['low', 'medium', 'high']; |
| | | const randomPriority = priorities[Math.floor(Math.random() * priorities.length)]; |
| | | const priorities = ["low", "medium", "high"]; |
| | | const randomPriority = |
| | | priorities[Math.floor(Math.random() * priorities.length)]; |
| | | |
| | | const newNotification = { |
| | | id: newId, |
| | |
| | | status: randomStatus, |
| | | content: `è¿æ¯${title}ç详ç»å
容ï¼è¯·ç¸å
³äººåæ³¨ææ¥ç...`, |
| | | departments: [randomDept], |
| | | expireDate: new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000).toISOString().split('T')[0], // 30天åè¿æ |
| | | expireDate: new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000) |
| | | .toISOString() |
| | | .split("T")[0], // 30天åè¿æ |
| | | syncMethods: ["wechat", "dingtalk"], |
| | | createTime: now.toLocaleString() |
| | | createTime: now.toLocaleString(), |
| | | }; |
| | | |
| | | // æ·»å å°æ°æ®å¼å¤´ |
| | |
| | | listNotification({...page.value, ...searchForm.value}) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records |
| | | tableData.value = res.data.records; |
| | | page.value.total = res.data.total; |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | | }) |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | // å页å¤ç |
| | | const pagination = (obj) => { |
| | | const pagination = obj => { |
| | | page.value.current = obj.page; |
| | | page.value.size = obj.limit; |
| | | handleQuery(); |
| | | }; |
| | | |
| | | // éæ©ååå¤ç |
| | | const handleSelectionChange = (selection) => { |
| | | const handleSelectionChange = selection => { |
| | | selectedIds.value = selection.map(item => item.id); |
| | | }; |
| | | |
| | |
| | | departments: [], |
| | | expireDate: "", |
| | | status: "draft", |
| | | syncMethods: [] |
| | | syncMethods: [], |
| | | }); |
| | | } else if (type === "edit" && row) { |
| | | dialogTitle.value = "ç¼è¾éç¥"; |
| | |
| | | departments: row.departments || [], |
| | | expireDate: row.expireDate || "", |
| | | status: row.status, |
| | | syncMethods: row.syncMethods || [] |
| | | syncMethods: row.syncMethods || [], |
| | | }); |
| | | } |
| | | dialogVisible.value = true; |
| | |
| | | duration: 60, |
| | | participants: [], |
| | | description: "", |
| | | platform: "wechat" |
| | | platform: "wechat", |
| | | }); |
| | | meetingDialogVisible.value = true; |
| | | }; |
| | |
| | | title: "", |
| | | description: "", |
| | | departments: [], |
| | | files: [] |
| | | files: [], |
| | | }); |
| | | fileList.value = []; |
| | | fileShareDialogVisible.value = true; |
| | |
| | | |
| | | if (dialogType.value === "add") { |
| | | // æ°å¢éç¥ |
| | | addNotification({...form.value}).then(res => { |
| | | addNotification({ ...form.value }) |
| | | .then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("æ·»å æå"); |
| | | dialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | } else { |
| | | // ç¼è¾éç¥ |
| | | updateNotification({...form.value}).then(res => { |
| | | updateNotification({ ...form.value }) |
| | | .then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("æ´æ°æå"); |
| | | dialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | } |
| | | } catch (error) { |
| | | console.error("表åéªè¯å¤±è´¥:", error); |
| | |
| | | duration: meetingForm.value.duration, |
| | | participants: meetingForm.value.participants, |
| | | description: meetingForm.value.description, |
| | | platform: meetingForm.value.platform |
| | | platform: meetingForm.value.platform, |
| | | }; |
| | | // æ°å¢ä¼è®® |
| | | addOnlineMeeting({...meetingInfo}).then(res => { |
| | | addOnlineMeeting({ ...meetingInfo }) |
| | | .then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("ä¼è®®æ·»å æå"); |
| | | meetingDialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | // 模æåéå°ä¼ä¸å¾®ä¿¡/éé |
| | | // const platformName = meetingPlatforms.find(p => p.value === meetingForm.value.platform)?.label || "æªç¥å¹³å°"; |
| | | // ElMessage.success(`ä¼è®®å建æåï¼ä¼è®®ID: ${meetingInfo.meetingId}ï¼å°éè¿${platformName}åééç¥`); |
| | | |
| | | // è·ååä¼äººåä¿¡æ¯ |
| | | const participantNames = meetingForm.value.participants.map(participantId => { |
| | | const employee = employees.value.find(emp => emp.value === participantId); |
| | | return employee ? employee.label : 'æªç¥äººå'; |
| | | }).join('ã'); |
| | | const participantNames = meetingForm.value.participants |
| | | .map(participantId => { |
| | | const employee = employees.value.find( |
| | | emp => emp.value === participantId |
| | | ); |
| | | return employee ? employee.label : "æªç¥äººå"; |
| | | }) |
| | | .join("ã"); |
| | | |
| | | // è·ååä¼äººå详ç»ä¿¡æ¯ |
| | | const participantDetails = meetingForm.value.participants.map(participantId => { |
| | | const employee = employees.value.find(emp => emp.value === participantId); |
| | | return employee ? { |
| | | const participantDetails = meetingForm.value.participants |
| | | .map(participantId => { |
| | | const employee = employees.value.find( |
| | | emp => emp.value === participantId |
| | | ); |
| | | return employee |
| | | ? { |
| | | name: employee.label, |
| | | dept: employee.dept, |
| | | phone: employee.phone, |
| | | email: employee.email |
| | | } : null; |
| | | }).filter(Boolean); |
| | | email: employee.email, |
| | | } |
| | | : null; |
| | | }) |
| | | .filter(Boolean); |
| | | |
| | | // å°ä¼è®®ä¿¡æ¯æ·»å å°éç¥å表 |
| | | const meetingNotification = { |
| | |
| | | type: "meeting", |
| | | priority: "high", |
| | | status: "published", |
| | | content: `ä¼è®®æ¶é´: ${meetingInfo.startTime}ï¼æ¶é¿: ${meetingInfo.duration}åéï¼å¹³å°: ${meetingPlatforms.find(p => p.value === meetingForm.value.platform)?.label || "æªç¥å¹³å°"}ï¼åä¼äººå: ${participantNames}ï¼å
±${participantDetails.length}人`, |
| | | content: `ä¼è®®æ¶é´: ${meetingInfo.startTime}ï¼æ¶é¿: ${ |
| | | meetingInfo.duration |
| | | }åéï¼å¹³å°: ${ |
| | | meetingPlatforms.find(p => p.value === meetingForm.value.platform) |
| | | ?.label || "æªç¥å¹³å°" |
| | | }ï¼åä¼äººå: ${participantNames}ï¼å
±${participantDetails.length}人`, |
| | | departments: [], |
| | | expireDate: "", |
| | | syncMethods: [meetingForm.value.platform] |
| | | syncMethods: [meetingForm.value.platform], |
| | | }; |
| | | addNotification({...meetingNotification}).then(res => { |
| | | addNotification({ ...meetingNotification }) |
| | | .then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("æ·»å æå"); |
| | | // dialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | // mockData.unshift(meetingNotification); |
| | | // getList(); |
| | | } catch (error) { |
| | |
| | | }; |
| | | |
| | | // æä»¶ä¸ä¼ å¤ç |
| | | const handleFileChange = (file) => { |
| | | const handleFileChange = file => { |
| | | const isLt10M = file.size / 1024 / 1024 < 10; |
| | | if (!isLt10M) { |
| | | ElMessage.error("ä¸ä¼ æä»¶å¤§å°ä¸è½è¶
è¿ 10MB!"); |
| | |
| | | name: file.name, |
| | | size: file.size, |
| | | type: file.type, |
| | | uid: file.uid |
| | | uid: file.uid, |
| | | }; |
| | | |
| | | fileList.value.push(fileInfo); |
| | |
| | | }; |
| | | |
| | | // ç§»é¤æä»¶ |
| | | const removeFile = (file) => { |
| | | const removeFile = file => { |
| | | const index = fileList.value.findIndex(item => item.uid === file.uid); |
| | | if (index !== -1) { |
| | | const index2 = fileShareForm.value.files.findIndex(item => item.uid === file.uid); |
| | | const index2 = fileShareForm.value.files.findIndex( |
| | | item => item.uid === file.uid |
| | | ); |
| | | if (index2 !== -1) { |
| | | fileShareForm.value.files.splice(index2, 1); |
| | | } |
| | |
| | | departments: fileShareForm.value.departments, |
| | | files: fileShareForm.value.files, |
| | | }; |
| | | addFileSharing({...shareInfo}).then(res => { |
| | | addFileSharing({ ...shareInfo }) |
| | | .then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("æä»¶å
±äº«æå"); |
| | | fileShareDialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | |
| | | // ElMessage.success(`æä»¶å
±äº«æåï¼å
±äº«ID: ${shareInfo.shareId}ï¼å·²éç¥ç¸å
³é¨é¨`); |
| | | |
| | | |
| | | // å°æä»¶å
±äº«ä¿¡æ¯æ·»å å°éç¥å表 |
| | | const fileShareNotification = { |
| | |
| | | expireDate: "", |
| | | syncMethods: ["wechat", "dingtalk"], |
| | | }; |
| | | addNotification({...fileShareNotification}).then(res => { |
| | | addNotification({ ...fileShareNotification }) |
| | | .then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("æ·»å æå"); |
| | | // dialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | |
| | | // mockData.unshift(fileShareNotification); |
| | | // getList(); |
| | |
| | | }; |
| | | |
| | | // åå¸éç¥ |
| | | const publishNotification = (row) => { |
| | | const publishNotification = row => { |
| | | Object.assign(form.value, { |
| | | id: row.id, |
| | | title: row.title, |
| | |
| | | departments: row.departments || [], |
| | | expireDate: row.expireDate || "", |
| | | status: row.status, |
| | | syncMethods: row.syncMethods || [] |
| | | syncMethods: row.syncMethods || [], |
| | | }); |
| | | form.value.status = "published"; |
| | | updateNotification({...form.value}).then(res => { |
| | | updateNotification({ ...form.value }) |
| | | .then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("éç¥å叿å"); |
| | | getList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | }; |
| | | |
| | | // æ¤åéç¥ |
| | | const revokeNotification = (row) => { |
| | | const revokeNotification = row => { |
| | | Object.assign(form.value, { |
| | | id: row.id, |
| | | title: row.title, |
| | |
| | | departments: row.departments || [], |
| | | expireDate: row.expireDate || "", |
| | | status: row.status, |
| | | syncMethods: row.syncMethods || [] |
| | | syncMethods: row.syncMethods || [], |
| | | }); |
| | | form.value.status = "draft"; |
| | | updateNotification({...form.value}).then(res => { |
| | | updateNotification({ ...form.value }) |
| | | .then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("éç¥å·²æ¤å"); |
| | | getList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | }; |
| | | |
| | | // å é¤éç¥ |
| | |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).then(() => { |
| | | delNotification(ids).then(res => { |
| | | }) |
| | | .then(() => { |
| | | delNotification(ids) |
| | | .then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("å 餿å"); |
| | | selectedIds.value = []; |
| | | getList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | }).catch(() => { |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | // ç¨æ·åæ¶ |
| | | }); |
| | | }; |
| | |
| | | <!-- 页颿 é¢ --> |
| | | <div class="page-header"> |
| | | <h2>ä¼è®®è稿</h2> |
| | | <el-button type="primary" @click="handleAdd"> |
| | | <el-icon><Plus /></el-icon> |
| | | <el-button type="primary" |
| | | @click="handleAdd"> |
| | | <el-icon> |
| | | <Plus /> |
| | | </el-icon> |
| | | æ°å»ºè稿 |
| | | </el-button> |
| | | </div> |
| | | |
| | | <!-- æç´¢åºå --> |
| | | <el-card class="search-card"> |
| | | <el-form :model="searchForm" label-width="100px" inline> |
| | | <el-form :model="searchForm" |
| | | label-width="100px" |
| | | inline> |
| | | <el-form-item label="ä¼è®®ä¸»é¢"> |
| | | <el-input v-model="searchForm.title" placeholder="请è¾å
¥ä¼è®®ä¸»é¢" clearable /> |
| | | <el-input v-model="searchForm.title" |
| | | placeholder="请è¾å
¥ä¼è®®ä¸»é¢" |
| | | clearable /> |
| | | </el-form-item> |
| | | <el-form-item label="ä¼è®®æ¥æ"> |
| | | <el-date-picker |
| | | v-model="searchForm.meetingDate" |
| | | <el-date-picker v-model="searchForm.meetingDate" |
| | | type="date" |
| | | placeholder="è¯·éæ©ä¼è®®æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | style="width: 100%" |
| | | /> |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleSearch">æç´¢</el-button> |
| | | <el-button type="primary" |
| | | @click="handleSearch">æç´¢</el-button> |
| | | <el-button @click="resetSearch">éç½®</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </el-card> |
| | | |
| | | <!-- è稿å表 --> |
| | | <el-card> |
| | | <el-table v-loading="loading" :data="draftList" border> |
| | | <el-table-column prop="title" label="ä¼è®®ä¸»é¢" align="center" min-width="200" show-overflow-tooltip /> |
| | | <el-table-column prop="room" label="ä¼è®®å®¤" align="center" width="120" /> |
| | | <el-table-column prop="host" label="主æäºº" align="center" width="120" /> |
| | | <el-table-column prop="meetingTime" label="ä¼è®®æ¶é´" align="center" width="180"> |
| | | <el-table v-loading="loading" |
| | | :data="draftList" |
| | | border> |
| | | <el-table-column prop="title" |
| | | label="ä¼è®®ä¸»é¢" |
| | | align="center" |
| | | min-width="200" |
| | | show-overflow-tooltip /> |
| | | <el-table-column prop="room" |
| | | label="ä¼è®®å®¤" |
| | | align="center" |
| | | width="120" /> |
| | | <el-table-column prop="host" |
| | | label="主æäºº" |
| | | align="center" |
| | | width="120" /> |
| | | <el-table-column prop="meetingTime" |
| | | label="ä¼è®®æ¶é´" |
| | | align="center" |
| | | width="180"> |
| | | <template #default="scope"> |
| | | {{ formatDateTime(scope.row.meetingTime) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="participants" label="åä¼äººæ°" align="center" width="100"> |
| | | <el-table-column prop="participants" |
| | | label="åä¼äººæ°" |
| | | align="center" |
| | | width="100"> |
| | | <template #default="scope"> |
| | | {{ scope.row.participants }}人 |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="createTime" label="å建æ¶é´" align="center" width="180" /> |
| | | <el-table-column label="æä½" align="center" width="200" fixed="right"> |
| | | <el-table-column prop="createTime" |
| | | label="å建æ¶é´" |
| | | align="center" |
| | | width="180" /> |
| | | <el-table-column label="æä½" |
| | | align="center" |
| | | width="200" |
| | | fixed="right"> |
| | | <template #default="scope"> |
| | | <el-button type="primary" link @click="viewDraft(scope.row)">æ¥ç</el-button> |
| | | <el-button type="primary" link @click="editDraft(scope.row)">ç¼è¾</el-button> |
| | | <el-button type="danger" link @click="deleteDraft(scope.row)">å é¤</el-button> |
| | | <el-button type="primary" |
| | | link |
| | | @click="viewDraft(scope.row)">æ¥ç</el-button> |
| | | <el-button type="primary" |
| | | link |
| | | @click="editDraft(scope.row)">ç¼è¾</el-button> |
| | | <el-button type="danger" |
| | | link |
| | | @click="deleteDraft(scope.row)">å é¤</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <!-- å页 --> |
| | | <pagination |
| | | v-show="total > 0" |
| | | <pagination v-show="total > 0" |
| | | :total="total" |
| | | v-model:page="queryParams.current" |
| | | v-model:limit="queryParams.size" |
| | | @pagination="getList" |
| | | /> |
| | | @pagination="getList" /> |
| | | </el-card> |
| | | |
| | | <!-- ä¼è®®è稿详æ
å¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | title="ä¼è®®è稿详æ
" |
| | | <el-dialog title="ä¼è®®è稿详æ
" |
| | | v-model="detailDialogVisible" |
| | | width="800px" |
| | | > |
| | | width="800px"> |
| | | <div v-if="currentDraft"> |
| | | <el-descriptions :column="2" border> |
| | | <el-descriptions :column="2" |
| | | border> |
| | | <el-descriptions-item label="ä¼è®®ä¸»é¢">{{ currentDraft.title }}</el-descriptions-item> |
| | | <el-descriptions-item label="ä¼è®®ç¼å·">{{ currentDraft.meetingId }}</el-descriptions-item> |
| | | <el-descriptions-item label="ä¼è®®å®¤">{{ currentDraft.room }}</el-descriptions-item> |
| | | <el-descriptions-item label="主æäºº">{{ currentDraft.host }}</el-descriptions-item> |
| | | <el-descriptions-item label="ä¼è®®æ¶é´" :span="2"> |
| | | <el-descriptions-item label="ä¼è®®æ¶é´" |
| | | :span="2"> |
| | | {{ formatDateTime(currentDraft.meetingTime) }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="å建æ¶é´">{{ currentDraft.createTime }}</el-descriptions-item> |
| | | </el-descriptions> |
| | | |
| | | <div class="content-section mt-20"> |
| | | <h4>åä¼äººå</h4> |
| | | <div class="participants-list"> |
| | | {{ currentDraft.participantList }} |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="content-section mt-20"> |
| | | <h4>ä¼è®®è¯´æ</h4> |
| | | <div class="meeting-description">{{ currentDraft.description }}</div> |
| | | </div> |
| | | </div> |
| | | |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button @click="detailDialogVisible = false">å
³ é</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- æ°å»º/ç¼è¾èç¨¿å¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | :title="dialogTitle" |
| | | <el-dialog :title="dialogTitle" |
| | | v-model="editDialogVisible" |
| | | width="700px" |
| | | > |
| | | <el-form :model="meetingForm" :rules="rules" ref="meetingFormRef" label-width="100px"> |
| | | <el-form-item label="ä¼è®®ä¸»é¢" prop="title"> |
| | | <el-input v-model="meetingForm.title" placeholder="请è¾å
¥ä¼è®®ä¸»é¢" /> |
| | | width="700px"> |
| | | <el-form :model="meetingForm" |
| | | :rules="rules" |
| | | ref="meetingFormRef" |
| | | label-width="100px"> |
| | | <el-form-item label="ä¼è®®ä¸»é¢" |
| | | prop="title"> |
| | | <el-input v-model="meetingForm.title" |
| | | placeholder="请è¾å
¥ä¼è®®ä¸»é¢" /> |
| | | </el-form-item> |
| | | <el-form-item label="ä¼è®®å®¤" prop="room"> |
| | | <el-select v-model="meetingForm.roomId" placeholder="è¯·éæ©ä¼è®®å®¤" style="width: 100%"> |
| | | <el-option v-for="(v,k) in roomList" :label="v.name" :value="v.id" /> |
| | | <el-form-item label="ä¼è®®å®¤" |
| | | prop="room"> |
| | | <el-select v-model="meetingForm.roomId" |
| | | placeholder="è¯·éæ©ä¼è®®å®¤" |
| | | style="width: 100%"> |
| | | <el-option v-for="(v,k) in roomList" |
| | | :label="v.name" |
| | | :value="v.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="主æäºº" prop="host"> |
| | | <el-input v-model="meetingForm.host" placeholder="请è¾å
¥ä¸»æäºº" /> |
| | | <el-form-item label="主æäºº" |
| | | prop="host"> |
| | | <el-input v-model="meetingForm.host" |
| | | placeholder="请è¾å
¥ä¸»æäºº" /> |
| | | </el-form-item> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¼è®®æ¥æ" prop="meetingDate"> |
| | | <el-date-picker |
| | | v-model="meetingForm.meetingDate" |
| | | <el-form-item label="ä¼è®®æ¥æ" |
| | | prop="meetingDate"> |
| | | <el-date-picker v-model="meetingForm.meetingDate" |
| | | type="date" |
| | | placeholder="è¯·éæ©ä¼è®®æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | :disabled-date="disabledDate" |
| | | style="width: 100%" |
| | | /> |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å¼å§æ¶é´" prop="startTime"> |
| | | <el-select |
| | | v-model="meetingForm.startTime" |
| | | <el-form-item label="å¼å§æ¶é´" |
| | | prop="startTime"> |
| | | <el-select v-model="meetingForm.startTime" |
| | | placeholder="è¯·éæ©å¼å§æ¶é´" |
| | | style="width: 100%" |
| | | > |
| | | <el-option |
| | | v-for="time in timeOptions" |
| | | style="width: 100%"> |
| | | <el-option v-for="time in timeOptions" |
| | | :key="time.value" |
| | | :label="time.label" |
| | | :value="time.value" |
| | | /> |
| | | :value="time.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç»ææ¶é´" prop="endTime"> |
| | | <el-select |
| | | v-model="meetingForm.endTime" |
| | | <el-form-item label="ç»ææ¶é´" |
| | | prop="endTime"> |
| | | <el-select v-model="meetingForm.endTime" |
| | | placeholder="è¯·éæ©ç»ææ¶é´" |
| | | style="width: 100%" |
| | | > |
| | | <el-option |
| | | v-for="time in timeOptions" |
| | | style="width: 100%"> |
| | | <el-option v-for="time in timeOptions" |
| | | :key="time.value" |
| | | :label="time.label" |
| | | :value="time.value" |
| | | /> |
| | | :value="time.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-form-item label="åä¼äººæ°" prop="participants"> |
| | | <el-input |
| | | v-model="meetingForm.participants" |
| | | <el-form-item label="åä¼äººæ°" |
| | | prop="participants"> |
| | | <el-input v-model="meetingForm.participants" |
| | | type="number" |
| | | placeholder="请è¾å
¥åä¼äººæ°" |
| | | /> |
| | | placeholder="请è¾å
¥åä¼äººæ°" /> |
| | | </el-form-item> |
| | | <el-form-item label="åä¼äººå" prop="participants"> |
| | | <el-input |
| | | v-model="meetingForm.participantList" |
| | | <el-form-item label="åä¼äººå" |
| | | prop="participants"> |
| | | <el-input v-model="meetingForm.participantList" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥åä¼äººåï¼ç¨éå·åé" |
| | | /> |
| | | placeholder="请è¾å
¥åä¼äººåï¼ç¨éå·åé" /> |
| | | </el-form-item> |
| | | <el-form-item label="ä¼è®®è¯´æ"> |
| | | <el-input |
| | | v-model="meetingForm.description" |
| | | <el-input v-model="meetingForm.description" |
| | | type="textarea" |
| | | :rows="4" |
| | | placeholder="请è¾å
¥ä¼è®®è¯´æ" |
| | | /> |
| | | placeholder="请è¾å
¥ä¼è®®è¯´æ" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="submitForm">ä¿ å</el-button> |
| | | <el-button @click="editDialogVisible = false">å æ¶</el-button> |
| | | <el-button type="primary" @click="submitForm">ä¿ å</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { Plus } from '@element-plus/icons-vue' |
| | | import Pagination from '@/components/Pagination/index.vue' |
| | | import {getRoomEnum,getDraftList,saveDraft,delDraft} from '@/api/collaborativeApproval/meeting.js' |
| | | import { ref, reactive, onMounted } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import { Plus } from "@element-plus/icons-vue"; |
| | | import Pagination from "@/components/Pagination/index.vue"; |
| | | import { |
| | | getRoomEnum, |
| | | getDraftList, |
| | | saveDraft, |
| | | delDraft, |
| | | } from "@/api/collaborativeApproval/meeting.js"; |
| | | import dayjs from "dayjs"; |
| | | // æ°æ®å表å è½½ç¶æ |
| | | const loading = ref(false) |
| | | const loading = ref(false); |
| | | |
| | | // æ»æ¡æ° |
| | | const total = ref(0) |
| | | const total = ref(0); |
| | | |
| | | // è稿åè¡¨æ°æ® |
| | | const draftList = ref([]) |
| | | const draftList = ref([]); |
| | | |
| | | // æ¥è¯¢åæ° |
| | | const queryParams = reactive({ |
| | | current: 1, |
| | | size: 10 |
| | | }) |
| | | size: 10, |
| | | }); |
| | | |
| | | // æç´¢è¡¨å |
| | | const searchForm = reactive({ |
| | | title: '', |
| | | meetingDate: '' |
| | | }) |
| | | title: "", |
| | | meetingDate: "", |
| | | }); |
| | | |
| | | // æ¯å¦æ¾ç¤ºå¯¹è¯æ¡ |
| | | const detailDialogVisible = ref(false) |
| | | const editDialogVisible = ref(false) |
| | | const detailDialogVisible = ref(false); |
| | | const editDialogVisible = ref(false); |
| | | |
| | | const roomList = ref([]) |
| | | const roomList = ref([]); |
| | | |
| | | // å¯¹è¯æ¡æ é¢ |
| | | const dialogTitle = ref('') |
| | | const dialogTitle = ref(""); |
| | | |
| | | // å½åæ¥ççè稿 |
| | | const currentDraft = ref(null) |
| | | const currentDraft = ref(null); |
| | | |
| | | // 表åå¼ç¨ |
| | | const meetingFormRef = ref(null) |
| | | const meetingFormRef = ref(null); |
| | | |
| | | // æ¶é´é项ï¼ä»¥åå°æ¶ä¸ºé´éï¼å·¥ä½æ¶é´8:00-18:00ï¼ |
| | | const timeOptions = ref([]) |
| | | const timeOptions = ref([]); |
| | | |
| | | // è¡¨åæ°æ® |
| | | const meetingForm = reactive({ |
| | | id: '', |
| | | meetingId: '', |
| | | title: '', |
| | | roomId: '', |
| | | host: '', |
| | | meetingDate: '', |
| | | startTime: '', |
| | | endTime: '', |
| | | id: "", |
| | | meetingId: "", |
| | | title: "", |
| | | roomId: "", |
| | | host: "", |
| | | meetingDate: "", |
| | | startTime: "", |
| | | endTime: "", |
| | | participants: 0, |
| | | participantList: '', |
| | | description: '', |
| | | createTime: '' |
| | | }) |
| | | participantList: "", |
| | | description: "", |
| | | createTime: "", |
| | | }); |
| | | |
| | | // è¡¨åæ ¡éªè§å |
| | | const rules = { |
| | | title: [{ required: true, message: '请è¾å
¥ä¼è®®ä¸»é¢', trigger: 'blur' }], |
| | | roomId: [{ required: true, message: 'è¯·éæ©ä¼è®®å®¤', trigger: 'change' }], |
| | | host: [{ required: true, message: '请è¾å
¥ä¸»æäºº', trigger: 'blur' }], |
| | | meetingDate: [{ required: true, message: 'è¯·éæ©ä¼è®®æ¥æ', trigger: 'change' }], |
| | | startTime: [{ required: true, message: 'è¯·éæ©å¼å§æ¶é´', trigger: 'change' }], |
| | | endTime: [{ required: true, message: 'è¯·éæ©ç»ææ¶é´', trigger: 'change' }] |
| | | } |
| | | title: [{ required: true, message: "请è¾å
¥ä¼è®®ä¸»é¢", trigger: "blur" }], |
| | | roomId: [{ required: true, message: "è¯·éæ©ä¼è®®å®¤", trigger: "change" }], |
| | | host: [{ required: true, message: "请è¾å
¥ä¸»æäºº", trigger: "blur" }], |
| | | meetingDate: [ |
| | | { required: true, message: "è¯·éæ©ä¼è®®æ¥æ", trigger: "change" }, |
| | | ], |
| | | startTime: [{ required: true, message: "è¯·éæ©å¼å§æ¶é´", trigger: "change" }], |
| | | endTime: [{ required: true, message: "è¯·éæ©ç»ææ¶é´", trigger: "change" }], |
| | | }; |
| | | |
| | | // åå§åæ¶é´é项ï¼ä»¥åå°æ¶ä¸ºé´éï¼å·¥ä½æ¶é´8:00-18:00ï¼ |
| | | const initTimeOptions = () => { |
| | | const options = [] |
| | | const options = []; |
| | | for (let hour = 8; hour <= 18; hour++) { |
| | | // æ¯ä¸ªå°æ¶æ·»å 两个éé¡¹ï¼æ´ç¹ååç¹ |
| | | options.push({ |
| | | value: `${hour.toString().padStart(2, '0')}:00`, |
| | | label: `${hour.toString().padStart(2, '0')}:00` |
| | | }) |
| | | value: `${hour.toString().padStart(2, "0")}:00`, |
| | | label: `${hour.toString().padStart(2, "0")}:00`, |
| | | }); |
| | | |
| | | if (hour < 18) { // 18:00ä¹å没æåç¹é项 |
| | | if (hour < 18) { |
| | | // 18:00ä¹å没æåç¹é项 |
| | | options.push({ |
| | | value: `${hour.toString().padStart(2, '0')}:30`, |
| | | label: `${hour.toString().padStart(2, '0')}:30` |
| | | }) |
| | | value: `${hour.toString().padStart(2, "0")}:30`, |
| | | label: `${hour.toString().padStart(2, "0")}:30`, |
| | | }); |
| | | } |
| | | } |
| | | timeOptions.value = options |
| | | } |
| | | timeOptions.value = options; |
| | | }; |
| | | |
| | | // ç¦ç¨æ¥æï¼ç¦ç¨ä»å¤©ä¹åçæ¥æï¼ |
| | | const disabledDate = (time) => { |
| | | const disabledDate = time => { |
| | | // ç¦ç¨ä»å¤©ä¹åçæ¥æ |
| | | return time.getTime() < Date.now() - 86400000 |
| | | } |
| | | return time.getTime() < Date.now() - 86400000; |
| | | }; |
| | | |
| | | // æ¥è¯¢æ°æ® |
| | | const getList = async () => { |
| | | loading.value = true |
| | | loading.value = true; |
| | | |
| | | let resp = await getDraftList({...queryParams,...searchForm}) |
| | | queryParams.current = resp.data.current |
| | | let resp = await getDraftList({ ...queryParams, ...searchForm }); |
| | | queryParams.current = resp.data.current; |
| | | draftList.value = resp.data.records.map(it=>{ |
| | | it.room = roomList.value.find(room=>it.roomId===room.id).name ?? "" |
| | | it.meetingTime = `${it.meetingDate} ${dayjs(it.startTime).format("HH:mm")} ~ ${dayjs(it.endTime).format("HH:mm")}` |
| | | return it |
| | | }) |
| | | it.room = roomList.value.find(room => it.roomId === room.id).name ?? ""; |
| | | it.meetingTime = `${it.meetingDate} ${dayjs(it.startTime).format( |
| | | "HH:mm" |
| | | )} ~ ${dayjs(it.endTime).format("HH:mm")}`; |
| | | return it; |
| | | }); |
| | | |
| | | loading.value = false |
| | | |
| | | } |
| | | loading.value = false; |
| | | }; |
| | | |
| | | // æç´¢æé®æä½ |
| | | const handleSearch = () => { |
| | | queryParams.pageNum = 1 |
| | | getList() |
| | | } |
| | | queryParams.pageNum = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | // éç½®æç´¢è¡¨å |
| | | const resetSearch = () => { |
| | | Object.assign(searchForm, { |
| | | title: '', |
| | | createTime: [] |
| | | }) |
| | | handleSearch() |
| | | } |
| | | title: "", |
| | | createTime: [], |
| | | }); |
| | | handleSearch(); |
| | | }; |
| | | |
| | | // æ·»å æé®æä½ |
| | | const handleAdd = () => { |
| | | dialogTitle.value = 'æ°å»ºè稿' |
| | | resetForm() |
| | | editDialogVisible.value = true |
| | | } |
| | | dialogTitle.value = "æ°å»ºè稿"; |
| | | resetForm(); |
| | | editDialogVisible.value = true; |
| | | }; |
| | | |
| | | // æ¥çè稿详æ
|
| | | const viewDraft = (row) => { |
| | | currentDraft.value = row |
| | | detailDialogVisible.value = true |
| | | } |
| | | const viewDraft = row => { |
| | | currentDraft.value = row; |
| | | detailDialogVisible.value = true; |
| | | }; |
| | | |
| | | // ç¼è¾è稿 |
| | | const editDraft = (row) => { |
| | | dialogTitle.value = 'ç¼è¾è稿' |
| | | const editDraft = row => { |
| | | dialogTitle.value = "ç¼è¾è稿"; |
| | | Object.assign(meetingForm, { |
| | | id: row.id, |
| | | meetingId: row.meetingId, |
| | |
| | | room: row.room, |
| | | roomId: row.id, |
| | | host: row.host, |
| | | meetingDate: row.meetingTime.split(' ')[0], |
| | | startTime: row.meetingTime.split(' ')[1], |
| | | endTime: row.meetingTime.split(' ')[3], |
| | | meetingDate: row.meetingTime.split(" ")[0], |
| | | startTime: row.meetingTime.split(" ")[1], |
| | | endTime: row.meetingTime.split(" ")[3], |
| | | participants: row.participants, |
| | | participantList: row.participantList, |
| | | description: row.description, |
| | | createTime: row.createTime |
| | | }) |
| | | editDialogVisible.value = true |
| | | } |
| | | createTime: row.createTime, |
| | | }); |
| | | editDialogVisible.value = true; |
| | | }; |
| | | |
| | | // å é¤è稿 |
| | | const deleteDraft = (row) => { |
| | | ElMessageBox.confirm( |
| | | `确认å é¤ä¼è®®è稿 "${row.title}"?`, |
| | | 'å é¤è稿', |
| | | { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | } |
| | | ).then(() => { |
| | | delDraft(row.id).then(resp=>{ |
| | | ElMessage.success('è稿å 餿å') |
| | | getList() |
| | | const deleteDraft = row => { |
| | | ElMessageBox.confirm(`确认å é¤ä¼è®®è稿 "${row.title}"?`, "å é¤è稿", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | |
| | | }).catch(() => {}) |
| | | } |
| | | .then(() => { |
| | | delDraft(row.id).then(resp => { |
| | | ElMessage.success("è稿å 餿å"); |
| | | getList(); |
| | | }); |
| | | }) |
| | | .catch(() => {}); |
| | | }; |
| | | |
| | | // é置表å |
| | | const resetForm = () => { |
| | | Object.assign(meetingForm, { |
| | | id: '', |
| | | meetingId: '', |
| | | title: '', |
| | | room: '', |
| | | host: '', |
| | | meetingDate: '', |
| | | startTime: '', |
| | | endTime: '', |
| | | id: "", |
| | | meetingId: "", |
| | | title: "", |
| | | room: "", |
| | | host: "", |
| | | meetingDate: "", |
| | | startTime: "", |
| | | endTime: "", |
| | | participants: 0, |
| | | participantList: '', |
| | | description: '', |
| | | createTime: '' |
| | | }) |
| | | } |
| | | participantList: "", |
| | | description: "", |
| | | createTime: "", |
| | | }); |
| | | }; |
| | | |
| | | // æäº¤è¡¨å |
| | | const submitForm = () => { |
| | | meetingFormRef.value.validate((valid) => { |
| | | meetingFormRef.value.validate(valid => { |
| | | if (valid) { |
| | | let formData = {...meetingForm} |
| | | formData.startTime = dayjs(meetingForm.meetingDate + ' ' + meetingForm.startTime).format("YYYY-MM-DD HH:mm:ss") |
| | | formData.endTime = dayjs(meetingForm.meetingDate + ' ' + meetingForm.endTime).format("YYYY-MM-DD HH:mm:ss") |
| | | let formData = { ...meetingForm }; |
| | | formData.startTime = dayjs( |
| | | meetingForm.meetingDate + " " + meetingForm.startTime |
| | | ).format("YYYY-MM-DD HH:mm:ss"); |
| | | formData.endTime = dayjs( |
| | | meetingForm.meetingDate + " " + meetingForm.endTime |
| | | ).format("YYYY-MM-DD HH:mm:ss"); |
| | | saveDraft(formData).then(()=>{ |
| | | ElMessage.success('ä¿åæå') |
| | | editDialogVisible.value = false |
| | | getList() |
| | | }) |
| | | ElMessage.success("ä¿åæå"); |
| | | editDialogVisible.value = false; |
| | | getList(); |
| | | }); |
| | | } |
| | | }) |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // æ ¼å¼åæ¥ææ¶é´ |
| | | const formatDateTime = (dateTime) => { |
| | | if (!dateTime) return '' |
| | | return dateTime.replace(' ', '\n') |
| | | } |
| | | const formatDateTime = dateTime => { |
| | | if (!dateTime) return ""; |
| | | return dateTime.replace(" ", "\n"); |
| | | }; |
| | | |
| | | // 页é¢å è½½æ¶è·åæ°æ® |
| | | onMounted(() => { |
| | | initTimeOptions() |
| | | getList() |
| | | getRoomEnum().then((res) => { |
| | | roomList.value = res.data |
| | | }) |
| | | }) |
| | | initTimeOptions(); |
| | | getList(); |
| | | getRoomEnum().then(res => { |
| | | roomList.value = res.data; |
| | | }); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | |
| | | <div class="page-header"> |
| | | <h2>ä¼è®®åå¸</h2> |
| | | </div> |
| | | |
| | | <!-- æç´¢åºå --> |
| | | <el-card class="search-card"> |
| | | <el-form :model="searchForm" inline> |
| | | <el-form :model="searchForm" |
| | | inline> |
| | | <el-form-item label="ä¼è®®ä¸»é¢"> |
| | | <el-input v-model="searchForm.title" placeholder="请è¾å
¥ä¼è®®ä¸»é¢" clearable/> |
| | | <el-input v-model="searchForm.title" |
| | | placeholder="请è¾å
¥ä¼è®®ä¸»é¢" |
| | | clearable /> |
| | | </el-form-item> |
| | | <el-form-item label="ç³è¯·äºº"> |
| | | <el-input v-model="searchForm.applicant" placeholder="请è¾å
¥ç³è¯·äºº" clearable/> |
| | | <el-input v-model="searchForm.applicant" |
| | | placeholder="请è¾å
¥ç³è¯·äºº" |
| | | clearable /> |
| | | </el-form-item> |
| | | <el-form-item label="åå¸ç¶æ"> |
| | | <el-select style="width: 100px" v-model="searchForm.status" placeholder="è¯·éæ©åå¸ç¶æ" clearable> |
| | | <el-option label="å¾
åå¸" value="0"/> |
| | | <el-option label="å·²åå¸" value="1"/> |
| | | <el-select style="width: 100px" |
| | | v-model="searchForm.status" |
| | | placeholder="è¯·éæ©åå¸ç¶æ" |
| | | clearable> |
| | | <el-option label="å¾
åå¸" |
| | | value="0" /> |
| | | <el-option label="å·²åå¸" |
| | | value="1" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleSearch">æç´¢</el-button> |
| | | <el-button type="primary" |
| | | @click="handleSearch">æç´¢</el-button> |
| | | <el-button @click="resetSearch">éç½®</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </el-card> |
| | | |
| | | <!-- ä¼è®®åå¸å表 --> |
| | | <el-card> |
| | | <el-table v-loading="loading" :data="approvalList" border> |
| | | <el-table-column prop="title" label="ä¼è®®ä¸»é¢" align="center" min-width="200" show-overflow-tooltip/> |
| | | <el-table-column prop="applicant" label="ç³è¯·äºº" align="center" width="120"/> |
| | | <el-table-column prop="host" label="主ç人" align="center" width="120"/> |
| | | <el-table-column prop="meetingTime" label="ä¼è®®æ¶é´" align="center" width="180"> |
| | | <el-table v-loading="loading" |
| | | :data="approvalList" |
| | | border> |
| | | <el-table-column prop="title" |
| | | label="ä¼è®®ä¸»é¢" |
| | | align="center" |
| | | min-width="200" |
| | | show-overflow-tooltip /> |
| | | <el-table-column prop="applicant" |
| | | label="ç³è¯·äºº" |
| | | align="center" |
| | | width="120" /> |
| | | <el-table-column prop="host" |
| | | label="主ç人" |
| | | align="center" |
| | | width="120" /> |
| | | <el-table-column prop="meetingTime" |
| | | label="ä¼è®®æ¶é´" |
| | | align="center" |
| | | width="180"> |
| | | <template #default="scope"> |
| | | {{ formatDateTime(scope.row.meetingTime) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="location" label="ä¼è®®å°ç¹" align="center" width="150"/> |
| | | <el-table-column prop="participants" label="åä¼äººæ°" align="center" width="100"> |
| | | <el-table-column prop="location" |
| | | label="ä¼è®®å°ç¹" |
| | | align="center" |
| | | width="150" /> |
| | | <el-table-column prop="participants" |
| | | label="åä¼äººæ°" |
| | | align="center" |
| | | width="100"> |
| | | <template #default="scope"> |
| | | {{ scope.row.participants.length }}人 |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="status" label="åå¸ç¶æ" align="center" width="120"> |
| | | <el-table-column prop="status" |
| | | label="åå¸ç¶æ" |
| | | align="center" |
| | | width="120"> |
| | | <template #default="scope"> |
| | | <el-tag :type="getStatusType(scope.row.status)"> |
| | | {{ getStatusText(scope.row.status) }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æä½" align="center" width="200" fixed="right"> |
| | | <el-table-column label="æä½" |
| | | align="center" |
| | | width="200" |
| | | fixed="right"> |
| | | <template #default="scope"> |
| | | <el-button type="primary" link @click="viewDetail(scope.row)">æ¥ç</el-button> |
| | | <el-button |
| | | v-if="scope.row.status == '0'" |
| | | <el-button type="primary" |
| | | link |
| | | @click="viewDetail(scope.row)">æ¥ç</el-button> |
| | | <el-button v-if="scope.row.status == '0'" |
| | | type="primary" |
| | | link |
| | | @click="handleApproval(scope.row)" |
| | | > |
| | | @click="handleApproval(scope.row)"> |
| | | åå¸ |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <!-- å页 --> |
| | | <pagination |
| | | v-show="total > 0" |
| | | <pagination v-show="total > 0" |
| | | :total="total" |
| | | v-model:page="queryParams.current" |
| | | v-model:limit="queryParams.size" |
| | | @pagination="getList" |
| | | /> |
| | | @pagination="getList" /> |
| | | </el-card> |
| | | |
| | | <!-- ä¼è®®è¯¦æ
å¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | title="ä¼è®®è¯¦æ
" |
| | | <el-dialog title="ä¼è®®è¯¦æ
" |
| | | v-model="detailDialogVisible" |
| | | width="800px" |
| | | > |
| | | width="800px"> |
| | | <div v-if="currentMeeting"> |
| | | <el-descriptions label-width="100px" class="meeting-desc" :column="2" border> |
| | | <el-descriptions-item label="ä¼è®®ä¸»é¢" label-class-name="nowrap-label">{{ |
| | | <el-descriptions label-width="100px" |
| | | class="meeting-desc" |
| | | :column="2" |
| | | border> |
| | | <el-descriptions-item label="ä¼è®®ä¸»é¢" |
| | | label-class-name="nowrap-label">{{ |
| | | currentMeeting.title |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="ç³è¯·äºº" label-class-name="nowrap-label">{{ |
| | | <el-descriptions-item label="ç³è¯·äºº" |
| | | label-class-name="nowrap-label">{{ |
| | | currentMeeting.applicant |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="主ç人" label-class-name="nowrap-label">{{ |
| | | <el-descriptions-item label="主ç人" |
| | | label-class-name="nowrap-label">{{ |
| | | currentMeeting.host |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="ä¼è®®æ¶é´" :span="2" label-class-name="nowrap-label"> |
| | | <el-descriptions-item label="ä¼è®®æ¶é´" |
| | | :span="2" |
| | | label-class-name="nowrap-label"> |
| | | {{ formatDateTime(currentMeeting.meetingTime) }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="ä¼è®®å°ç¹" label-class-name="nowrap-label">{{ |
| | | <el-descriptions-item label="ä¼è®®å°ç¹" |
| | | label-class-name="nowrap-label">{{ |
| | | currentMeeting.location |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="åä¼äººæ°" label-class-name="nowrap-label">{{ |
| | | <el-descriptions-item label="åä¼äººæ°" |
| | | label-class-name="nowrap-label">{{ |
| | | currentMeeting.participants.length |
| | | }}人</el-descriptions-item> |
| | | <el-descriptions-item label="åå¸ç¶æ" label-class-name="nowrap-label"> |
| | | <el-descriptions-item label="åå¸ç¶æ" |
| | | label-class-name="nowrap-label"> |
| | | <el-tag :type="getStatusType(currentMeeting.status)"> |
| | | {{ getStatusText(currentMeeting.status) }} |
| | | </el-tag> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="ç³è¯·æ¶é´" label-class-name="nowrap-label">{{ |
| | | <el-descriptions-item label="ç³è¯·æ¶é´" |
| | | label-class-name="nowrap-label">{{ |
| | | currentMeeting.createTime |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item style="max-height: 400px" label="ä¼è®®è¯´æ" :span="2" |
| | | <el-descriptions-item style="max-height: 400px" |
| | | label="ä¼è®®è¯´æ" |
| | | :span="2" |
| | | label-class-name="nowrap-label">{{ currentMeeting.description }}</el-descriptions-item> |
| | | </el-descriptions> |
| | | |
| | | |
| | | <div class="content-section mt-20"> |
| | | <h4>åä¼äººå</h4> |
| | | <div class="participants-list"> |
| | | <el-tag |
| | | v-for="participant in currentMeeting.participants" |
| | | <el-tag v-for="participant in currentMeeting.participants" |
| | | :key="participant.id" |
| | | style="margin-right: 10px; margin-bottom: 10px;" |
| | | > |
| | | style="margin-right: 10px; margin-bottom: 10px;"> |
| | | {{ participant.name }} |
| | | </el-tag> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button @click="detailDialogVisible = false">å
³ é</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- ä¼è®®åå¸å¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | title="ä¼è®®åå¸" |
| | | v-model="approvalDialogVisible" |
| | | > |
| | | <el-dialog title="ä¼è®®åå¸" |
| | | v-model="approvalDialogVisible"> |
| | | <div v-if="currentMeeting"> |
| | | <el-descriptions :column="2" border> |
| | | <el-descriptions :column="2" |
| | | border> |
| | | <el-descriptions-item label="ä¼è®®ä¸»é¢">{{ currentMeeting.title }}</el-descriptions-item> |
| | | <el-descriptions-item label="ç³è¯·äºº">{{ currentMeeting.applicant }}</el-descriptions-item> |
| | | <el-descriptions-item label="主ç人">{{ currentMeeting.host }}</el-descriptions-item> |
| | | <el-descriptions-item label="ä¼è®®æ¶é´" :span="2"> |
| | | <el-descriptions-item label="ä¼è®®æ¶é´" |
| | | :span="2"> |
| | | {{ formatDateTime(currentMeeting.meetingTime) }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="ä¼è®®å°ç¹">{{ currentMeeting.location }}</el-descriptions-item> |
| | | <el-descriptions-item label="åä¼äººæ°">{{ currentMeeting.participants.length }}人</el-descriptions-item> |
| | | </el-descriptions> |
| | | |
| | | <div class="content-section mt-20"> |
| | | <h4>åä¼äººå</h4> |
| | | <div class="participants-list"> |
| | | <el-tag |
| | | v-for="participant in currentMeeting.participants" |
| | | <el-tag v-for="participant in currentMeeting.participants" |
| | | :key="participant.id" |
| | | style="margin-right: 10px; margin-bottom: 10px;" |
| | | > |
| | | style="margin-right: 10px; margin-bottom: 10px;"> |
| | | {{ participant.name }} |
| | | </el-tag> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="approval-opinion mt-20"> |
| | | <h4>å叿è§</h4> |
| | | <el-input |
| | | v-model="publishComment" |
| | | <el-input v-model="publishComment" |
| | | type="textarea" |
| | | placeholder="请è¾å
¥å叿è§" |
| | | :rows="4" |
| | | /> |
| | | :rows="4" /> |
| | | </div> |
| | | </div> |
| | | |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="submitApproval('1')">å å¸</el-button> |
| | | <el-button @click="approvalDialogVisible = false">å æ¶</el-button> |
| | | <!-- <el-button type="danger" @click="submitApproval('2')">ä¸éè¿</el-button>--> |
| | | <el-button type="primary" @click="submitApproval('1')">å å¸</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref, reactive, onMounted} from 'vue' |
| | | import {ElMessage, ElMessageBox} from 'element-plus' |
| | | import Pagination from '@/components/Pagination/index.vue' |
| | | import {getRoomEnum, getMeetingPublish,saveMeetingApplication} from '@/api/collaborativeApproval/meeting.js' |
| | | import { ref, reactive, onMounted } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import Pagination from "@/components/Pagination/index.vue"; |
| | | import { |
| | | getRoomEnum, |
| | | getMeetingPublish, |
| | | saveMeetingApplication, |
| | | } from "@/api/collaborativeApproval/meeting.js"; |
| | | import {getStaffOnJob} from "@/api/personnelManagement/onboarding.js"; |
| | | import dayjs from "dayjs"; |
| | | |
| | | // æ°æ®å表å è½½ç¶æ |
| | | const loading = ref(false) |
| | | const loading = ref(false); |
| | | |
| | | // æ»æ¡æ° |
| | | const total = ref(0) |
| | | const roomEnum = ref([]) |
| | | const staffList = ref([]) |
| | | const total = ref(0); |
| | | const roomEnum = ref([]); |
| | | const staffList = ref([]); |
| | | // åå¸åè¡¨æ°æ® |
| | | const approvalList = ref([]) |
| | | const approvalList = ref([]); |
| | | |
| | | // æ¥è¯¢åæ° |
| | | const queryParams = reactive({ |
| | | current: 1, |
| | | size: 10 |
| | | }) |
| | | size: 10, |
| | | }); |
| | | |
| | | // æç´¢è¡¨å |
| | | const searchForm = reactive({ |
| | | title: '', |
| | | applicant: '', |
| | | status: '' |
| | | }) |
| | | title: "", |
| | | applicant: "", |
| | | status: "", |
| | | }); |
| | | |
| | | // æ¯å¦æ¾ç¤ºå¯¹è¯æ¡ |
| | | const detailDialogVisible = ref(false) |
| | | const approvalDialogVisible = ref(false) |
| | | const detailDialogVisible = ref(false); |
| | | const approvalDialogVisible = ref(false); |
| | | |
| | | // å½åæ¥ççä¼è®® |
| | | const currentMeeting = ref(null) |
| | | const currentMeeting = ref(null); |
| | | |
| | | // åå¸æè§ |
| | | const publishComment = ref('') |
| | | const publishComment = ref(""); |
| | | |
| | | // æ¥è¯¢æ°æ® |
| | | const getList = async () => { |
| | | loading.value = true |
| | | let resp = await getMeetingPublish({...searchForm, ...queryParams}) |
| | | loading.value = true; |
| | | let resp = await getMeetingPublish({ ...searchForm, ...queryParams }); |
| | | approvalList.value = resp.data.records.map(it => { |
| | | let room = roomEnum.value.find(room => it.roomId === room.id) |
| | | it.location = `${room.name}(${room.location})` |
| | | let staffs = JSON.parse(it.participants) |
| | | it.staffCount = staffs.size |
| | | it.status = it.publishStatus |
| | | it.meetingTime = `${it.meetingDate} ${dayjs(it.startTime).format('HH:mm:ss')} ~ ${dayjs(it.endTime).format('HH:mm:ss')}` |
| | | it.participants = staffList.value.filter(staff => staffs.some(id=>id === staff.id)).map(staff => { |
| | | let room = roomEnum.value.find(room => it.roomId === room.id); |
| | | it.location = `${room.name}(${room.location})`; |
| | | let staffs = JSON.parse(it.participants); |
| | | it.staffCount = staffs.size; |
| | | it.status = it.publishStatus; |
| | | it.meetingTime = `${it.meetingDate} ${dayjs(it.startTime).format( |
| | | "HH:mm:ss" |
| | | )} ~ ${dayjs(it.endTime).format("HH:mm:ss")}`; |
| | | it.participants = staffList.value |
| | | .filter(staff => staffs.some(id => id === staff.id)) |
| | | .map(staff => { |
| | | return { |
| | | id: staff.id, |
| | | name: `${staff.staffName}(${staff.postJob})` |
| | | } |
| | | }) |
| | | name: `${staff.staffName}(${staff.postJob})`, |
| | | }; |
| | | }); |
| | | |
| | | |
| | | return it |
| | | }) |
| | | total.value = resp.data.total |
| | | loading.value = false |
| | | } |
| | | return it; |
| | | }); |
| | | total.value = resp.data.total; |
| | | loading.value = false; |
| | | }; |
| | | |
| | | // æç´¢æé®æä½ |
| | | const handleSearch = () => { |
| | | queryParams.pageNum = 1 |
| | | getList() |
| | | } |
| | | queryParams.pageNum = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | // éç½®æç´¢è¡¨å |
| | | const resetSearch = () => { |
| | | Object.assign(searchForm, { |
| | | title: '', |
| | | applicant: '', |
| | | status: '' |
| | | }) |
| | | handleSearch() |
| | | } |
| | | title: "", |
| | | applicant: "", |
| | | status: "", |
| | | }); |
| | | handleSearch(); |
| | | }; |
| | | |
| | | // æ¥ç详æ
|
| | | const viewDetail = (row) => { |
| | | currentMeeting.value = row |
| | | detailDialogVisible.value = true |
| | | } |
| | | const viewDetail = row => { |
| | | currentMeeting.value = row; |
| | | detailDialogVisible.value = true; |
| | | }; |
| | | |
| | | // å¤çåå¸ |
| | | const handleApproval = (row) => { |
| | | currentMeeting.value = row |
| | | publishComment.value = '' |
| | | approvalDialogVisible.value = true |
| | | } |
| | | const handleApproval = row => { |
| | | currentMeeting.value = row; |
| | | publishComment.value = ""; |
| | | approvalDialogVisible.value = true; |
| | | }; |
| | | |
| | | // è·åç¶æç±»å |
| | | const getStatusType = (status) => { |
| | | const getStatusType = status => { |
| | | const statusMap = { |
| | | '0': 'info', // å¾
åå¸ |
| | | '1': 'success', // å·²éè¿ |
| | | '2': 'danger', // æªéè¿ |
| | | } |
| | | return statusMap[status] || 'info' |
| | | } |
| | | 0: "info", // å¾
åå¸ |
| | | 1: "success", // å·²éè¿ |
| | | 2: "danger", // æªéè¿ |
| | | }; |
| | | return statusMap[status] || "info"; |
| | | }; |
| | | |
| | | // è·åç¶æææ¬ |
| | | const getStatusText = (status) => { |
| | | const getStatusText = status => { |
| | | const statusMap = { |
| | | '0': 'å¾
åå¸', |
| | | '1': 'å·²åå¸', |
| | | '2': '已忶', |
| | | } |
| | | return statusMap[status] || 'æªç¥' |
| | | } |
| | | 0: "å¾
åå¸", |
| | | 1: "å·²åå¸", |
| | | 2: "已忶", |
| | | }; |
| | | return statusMap[status] || "æªç¥"; |
| | | }; |
| | | |
| | | // æ ¼å¼åæ¥ææ¶é´ |
| | | const formatDateTime = (dateTime) => { |
| | | if (!dateTime) return '' |
| | | return dateTime.replace(' ', '\n') |
| | | } |
| | | const formatDateTime = dateTime => { |
| | | if (!dateTime) return ""; |
| | | return dateTime.replace(" ", "\n"); |
| | | }; |
| | | |
| | | // æäº¤åå¸ |
| | | const submitApproval = (status) => { |
| | | const submitApproval = status => { |
| | | // if (status === 'approved' && !publishComment.value.trim()) { |
| | | // ElMessage.warning('请填åå叿è§') |
| | | // return |
| | | // } |
| | | |
| | | ElMessageBox.confirm( |
| | | `确认${status === '1' ? 'åå¸' : 'åæ¶'}该ä¼è®®ï¼`, |
| | | 'åå¸ç¡®è®¤', |
| | | `确认${status === "1" ? "åå¸" : "åæ¶"}该ä¼è®®ï¼`, |
| | | "åå¸ç¡®è®¤", |
| | | { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | } |
| | | ).then(() => { |
| | | ) |
| | | .then(() => { |
| | | saveMeetingApplication({ |
| | | id: currentMeeting.value.id, |
| | | publishStatus: status, |
| | | publishComment: publishComment.value |
| | | publishComment: publishComment.value, |
| | | }).then(resp=>{ |
| | | // æ´æ°ä¼è®®ç¶æ |
| | | currentMeeting.value.status = status |
| | | currentMeeting.value.status = status; |
| | | |
| | | ElMessage.success('åå¸æäº¤æå') |
| | | approvalDialogVisible.value = false |
| | | getList() |
| | | ElMessage.success("åå¸æäº¤æå"); |
| | | approvalDialogVisible.value = false; |
| | | getList(); |
| | | }); |
| | | }) |
| | | |
| | | }).catch(() => { |
| | | }) |
| | | } |
| | | .catch(() => {}); |
| | | }; |
| | | |
| | | // 页é¢å è½½æ¶è·åæ°æ® |
| | | onMounted(async () => { |
| | | const [resp1, resp2]= await Promise.all([getRoomEnum(), getStaffOnJob()]) |
| | | roomEnum.value = resp1.data |
| | | staffList.value = resp2.data |
| | | const [resp1, resp2] = await Promise.all([getRoomEnum(), getStaffOnJob()]); |
| | | roomEnum.value = resp1.data; |
| | | staffList.value = resp2.data; |
| | | |
| | | await getList() |
| | | }) |
| | | await getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | |
| | | <div class="page-header"> |
| | | <h2>ä¼è®®çºªè¦</h2> |
| | | </div> |
| | | |
| | | <!-- æç´¢åºå --> |
| | | <el-card class="search-card"> |
| | | <el-form :model="searchForm" inline> |
| | | <el-form :model="searchForm" |
| | | inline> |
| | | <el-form-item label="ä¼è®®ä¸»é¢"> |
| | | <el-input v-model="searchForm.title" placeholder="请è¾å
¥ä¼è®®ä¸»é¢" clearable /> |
| | | <el-input v-model="searchForm.title" |
| | | placeholder="请è¾å
¥ä¼è®®ä¸»é¢" |
| | | clearable /> |
| | | </el-form-item> |
| | | <el-form-item label="ç³è¯·äºº"> |
| | | <el-input v-model="searchForm.applicant" placeholder="请è¾å
¥ç³è¯·äºº" clearable /> |
| | | <el-input v-model="searchForm.applicant" |
| | | placeholder="请è¾å
¥ç³è¯·äºº" |
| | | clearable /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleSearch">æç´¢</el-button> |
| | | <el-button type="primary" |
| | | @click="handleSearch">æç´¢</el-button> |
| | | <el-button @click="resetSearch">éç½®</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </el-card> |
| | | |
| | | <!-- ä¼è®®å表 --> |
| | | <el-card> |
| | | <el-table v-loading="loading" :data="meetingList" border> |
| | | <el-table-column prop="title" label="ä¼è®®ä¸»é¢" align="center" min-width="200" show-overflow-tooltip /> |
| | | <el-table-column prop="applicant" label="ç³è¯·äºº" align="center" width="120" /> |
| | | <el-table-column prop="host" label="主æäºº" align="center" width="120" /> |
| | | <el-table-column prop="meetingTime" label="ä¼è®®æ¶é´" align="center" width="180"> |
| | | <el-table v-loading="loading" |
| | | :data="meetingList" |
| | | border> |
| | | <el-table-column prop="title" |
| | | label="ä¼è®®ä¸»é¢" |
| | | align="center" |
| | | min-width="200" |
| | | show-overflow-tooltip /> |
| | | <el-table-column prop="applicant" |
| | | label="ç³è¯·äºº" |
| | | align="center" |
| | | width="120" /> |
| | | <el-table-column prop="host" |
| | | label="主æäºº" |
| | | align="center" |
| | | width="120" /> |
| | | <el-table-column prop="meetingTime" |
| | | label="ä¼è®®æ¶é´" |
| | | align="center" |
| | | width="180"> |
| | | <template #default="scope"> |
| | | {{ formatDateTime(scope.row.meetingTime) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="location" label="ä¼è®®å°ç¹" align="center" width="150" /> |
| | | <el-table-column prop="participants" label="åä¼äººæ°" align="center" width="100"> |
| | | <el-table-column prop="location" |
| | | label="ä¼è®®å°ç¹" |
| | | align="center" |
| | | width="150" /> |
| | | <el-table-column prop="participants" |
| | | label="åä¼äººæ°" |
| | | align="center" |
| | | width="100"> |
| | | <template #default="scope"> |
| | | {{ scope.row.participants.length }}人 |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æä½" align="center" width="200" fixed="right"> |
| | | <el-table-column label="æä½" |
| | | align="center" |
| | | width="200" |
| | | fixed="right"> |
| | | <template #default="scope"> |
| | | <el-button type="primary" link @click="viewDetail(scope.row)">æ¥ç</el-button> |
| | | <el-button |
| | | type="primary" |
| | | <el-button type="primary" |
| | | link |
| | | @click="addMinutes(scope.row)" |
| | | > |
| | | @click="viewDetail(scope.row)">æ¥ç</el-button> |
| | | <el-button type="primary" |
| | | link |
| | | @click="addMinutes(scope.row)"> |
| | | æ·»å çºªè¦ |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <!-- å页 --> |
| | | <pagination |
| | | v-show="total > 0" |
| | | <pagination v-show="total > 0" |
| | | :total="total" |
| | | v-model:page="queryParams.current" |
| | | v-model:limit="queryParams.size" |
| | | @pagination="getList" |
| | | /> |
| | | @pagination="getList" /> |
| | | </el-card> |
| | | |
| | | <!-- ä¼è®®è¯¦æ
å¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | title="ä¼è®®è¯¦æ
" |
| | | <el-dialog title="ä¼è®®è¯¦æ
" |
| | | v-model="detailDialogVisible" |
| | | width="800px" |
| | | > |
| | | width="800px"> |
| | | <div v-if="currentMeeting"> |
| | | <el-descriptions label-width="100px" class="meeting-desc" :column="2" border> |
| | | <el-descriptions-item label="ä¼è®®ä¸»é¢" label-class-name="nowrap-label">{{ |
| | | <el-descriptions label-width="100px" |
| | | class="meeting-desc" |
| | | :column="2" |
| | | border> |
| | | <el-descriptions-item label="ä¼è®®ä¸»é¢" |
| | | label-class-name="nowrap-label">{{ |
| | | currentMeeting.title |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="ç³è¯·äºº" label-class-name="nowrap-label">{{ |
| | | <el-descriptions-item label="ç³è¯·äºº" |
| | | label-class-name="nowrap-label">{{ |
| | | currentMeeting.applicant |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="主æäºº" label-class-name="nowrap-label">{{ |
| | | <el-descriptions-item label="主æäºº" |
| | | label-class-name="nowrap-label">{{ |
| | | currentMeeting.host |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="ä¼è®®æ¶é´" :span="2" label-class-name="nowrap-label"> |
| | | <el-descriptions-item label="ä¼è®®æ¶é´" |
| | | :span="2" |
| | | label-class-name="nowrap-label"> |
| | | {{ formatDateTime(currentMeeting.meetingTime) }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="ä¼è®®å°ç¹" label-class-name="nowrap-label">{{ |
| | | <el-descriptions-item label="ä¼è®®å°ç¹" |
| | | label-class-name="nowrap-label">{{ |
| | | currentMeeting.location |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="åä¼äººæ°" label-class-name="nowrap-label">{{ |
| | | <el-descriptions-item label="åä¼äººæ°" |
| | | label-class-name="nowrap-label">{{ |
| | | currentMeeting.participants.length |
| | | }}人</el-descriptions-item> |
| | | <el-descriptions-item label="审æ¹ç¶æ" label-class-name="nowrap-label"> |
| | | <el-descriptions-item label="审æ¹ç¶æ" |
| | | label-class-name="nowrap-label"> |
| | | <el-tag :type="getStatusType(currentMeeting.status)"> |
| | | {{ getStatusText(currentMeeting.status) }} |
| | | </el-tag> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="ç³è¯·æ¶é´" label-class-name="nowrap-label">{{ |
| | | <el-descriptions-item label="ç³è¯·æ¶é´" |
| | | label-class-name="nowrap-label">{{ |
| | | currentMeeting.createTime |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item style="max-height: 400px" label="ä¼è®®è¯´æ" :span="2" |
| | | <el-descriptions-item style="max-height: 400px" |
| | | label="ä¼è®®è¯´æ" |
| | | :span="2" |
| | | label-class-name="nowrap-label">{{ currentMeeting.description }}</el-descriptions-item> |
| | | </el-descriptions> |
| | | |
| | | <div class="content-section mt-20"> |
| | | <h4>åä¼äººå</h4> |
| | | <div class="participants-list"> |
| | | <el-tag |
| | | v-for="participant in currentMeeting.participants" |
| | | <el-tag v-for="participant in currentMeeting.participants" |
| | | :key="participant.id" |
| | | style="margin-right: 10px; margin-bottom: 10px;" |
| | | > |
| | | style="margin-right: 10px; margin-bottom: 10px;"> |
| | | {{ participant.name }} |
| | | </el-tag> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button @click="detailDialogVisible = false">å
³ é</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- æ·»å ä¼è®®çºªè¦å¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | title="æ·»å ä¼è®®çºªè¦" |
| | | <el-dialog title="æ·»å ä¼è®®çºªè¦" |
| | | v-model="minutesDialogVisible" |
| | | width="80%" |
| | | @close="handleCloseMinutesDialog" |
| | | > |
| | | @close="handleCloseMinutesDialog"> |
| | | <div v-if="currentMeeting"> |
| | | <el-descriptions :column="2" border> |
| | | <el-descriptions :column="2" |
| | | border> |
| | | <el-descriptions-item label="ä¼è®®ä¸»é¢">{{ currentMeeting.title }}</el-descriptions-item> |
| | | <el-descriptions-item label="ç³è¯·äºº">{{ currentMeeting.applicant }}</el-descriptions-item> |
| | | <el-descriptions-item label="主æäºº">{{ currentMeeting.host }}</el-descriptions-item> |
| | | <el-descriptions-item label="ä¼è®®æ¶é´" :span="2"> |
| | | <el-descriptions-item label="ä¼è®®æ¶é´" |
| | | :span="2"> |
| | | {{ formatDateTime(currentMeeting.meetingTime) }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="ä¼è®®å°ç¹">{{ currentMeeting.location }}</el-descriptions-item> |
| | | <el-descriptions-item label="åä¼äººæ°">{{ currentMeeting.participants.length }}人</el-descriptions-item> |
| | | </el-descriptions> |
| | | |
| | | <div class="content-section mt-20"> |
| | | <h4>ä¼è®®çºªè¦å
容</h4> |
| | | <div class="editor-container"> |
| | | <Editor |
| | | v-model="minutesContent" |
| | | :min-height="400" |
| | | /> |
| | | <Editor v-model="minutesContent" |
| | | :min-height="400" /> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="submitMinutes">ä¿ å</el-button> |
| | | <el-button @click="minutesDialogVisible = false">å æ¶</el-button> |
| | | <el-button type="primary" @click="submitMinutes">ä¿ å</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted } from 'vue' |
| | | import { ElMessage } from 'element-plus' |
| | | import Pagination from '@/components/Pagination/index.vue' |
| | | import Editor from '@/components/Editor/index.vue' |
| | | import { getRoomEnum, getMeetingPublish ,getMeetingMinutesByMeetingId,saveMeetingMinutes} from '@/api/collaborativeApproval/meeting.js' |
| | | import { getStaffOnJob } from "@/api/personnelManagement/onboarding.js" |
| | | import dayjs from "dayjs" |
| | | import { ref, reactive, onMounted } from "vue"; |
| | | import { ElMessage } from "element-plus"; |
| | | import Pagination from "@/components/Pagination/index.vue"; |
| | | import Editor from "@/components/Editor/index.vue"; |
| | | import { |
| | | getRoomEnum, |
| | | getMeetingPublish, |
| | | getMeetingMinutesByMeetingId, |
| | | saveMeetingMinutes, |
| | | } from "@/api/collaborativeApproval/meeting.js"; |
| | | import { getStaffOnJob } from "@/api/personnelManagement/onboarding.js"; |
| | | import dayjs from "dayjs"; |
| | | |
| | | // æ°æ®å表å è½½ç¶æ |
| | | const loading = ref(false) |
| | | const loading = ref(false); |
| | | |
| | | // æ»æ¡æ° |
| | | const total = ref(0) |
| | | const roomEnum = ref([]) |
| | | const staffList = ref([]) |
| | | const total = ref(0); |
| | | const roomEnum = ref([]); |
| | | const staffList = ref([]); |
| | | |
| | | // ä¼è®®åè¡¨æ°æ® |
| | | const meetingList = ref([]) |
| | | const meetingList = ref([]); |
| | | |
| | | // æ¥è¯¢åæ° |
| | | const queryParams = reactive({ |
| | | current: 1, |
| | | size: 10 |
| | | }) |
| | | size: 10, |
| | | }); |
| | | |
| | | // æç´¢è¡¨å |
| | | const searchForm = reactive({ |
| | | title: '', |
| | | applicant: '', |
| | | title: "", |
| | | applicant: "", |
| | | // status: '1' // é»è®¤åªæ¾ç¤ºå·²éè¿å®¡æ¹çä¼è®® |
| | | }) |
| | | }); |
| | | |
| | | // æ¯å¦æ¾ç¤ºå¯¹è¯æ¡ |
| | | const detailDialogVisible = ref(false) |
| | | const minutesDialogVisible = ref(false) |
| | | const detailDialogVisible = ref(false); |
| | | const minutesDialogVisible = ref(false); |
| | | |
| | | // å½åæ¥ççä¼è®® |
| | | const currentMeeting = ref(null) |
| | | const currentMeeting = ref(null); |
| | | |
| | | // ä¼è®®çºªè¦å
容 |
| | | const minutesContent = ref('') |
| | | const minutesContentId = ref('') |
| | | const minutesContent = ref(""); |
| | | const minutesContentId = ref(""); |
| | | |
| | | // æ¥è¯¢æ°æ® |
| | | const getList = async () => { |
| | | loading.value = true |
| | | let resp = await getMeetingPublish({ ...searchForm, ...queryParams }) |
| | | loading.value = true; |
| | | let resp = await getMeetingPublish({ ...searchForm, ...queryParams }); |
| | | meetingList.value = resp.data.records.map(it => { |
| | | let room = roomEnum.value.find(room => it.roomId === room.id) |
| | | it.location = `${room.name}(${room.location})` |
| | | let staffs = JSON.parse(it.participants) |
| | | it.staffCount = staffs.size |
| | | it.meetingTime = `${it.meetingDate} ${dayjs(it.startTime).format('HH:mm:ss')} ~ ${dayjs(it.endTime).format('HH:mm:ss')}` |
| | | it.participants = staffList.value.filter(staff => staffs.some(id => id === staff.id)).map(staff => { |
| | | let room = roomEnum.value.find(room => it.roomId === room.id); |
| | | it.location = `${room.name}(${room.location})`; |
| | | let staffs = JSON.parse(it.participants); |
| | | it.staffCount = staffs.size; |
| | | it.meetingTime = `${it.meetingDate} ${dayjs(it.startTime).format( |
| | | "HH:mm:ss" |
| | | )} ~ ${dayjs(it.endTime).format("HH:mm:ss")}`; |
| | | it.participants = staffList.value |
| | | .filter(staff => staffs.some(id => id === staff.id)) |
| | | .map(staff => { |
| | | return { |
| | | id: staff.id, |
| | | name: `${staff.staffName}(${staff.postJob})` |
| | | } |
| | | }) |
| | | name: `${staff.staffName}(${staff.postJob})`, |
| | | }; |
| | | }); |
| | | |
| | | return it |
| | | }) |
| | | total.value = resp.data.total |
| | | loading.value = false |
| | | } |
| | | return it; |
| | | }); |
| | | total.value = resp.data.total; |
| | | loading.value = false; |
| | | }; |
| | | |
| | | // æç´¢æé®æä½ |
| | | const handleSearch = () => { |
| | | queryParams.current = 1 |
| | | getList() |
| | | } |
| | | queryParams.current = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | // éç½®æç´¢è¡¨å |
| | | const resetSearch = () => { |
| | | Object.assign(searchForm, { |
| | | title: '', |
| | | applicant: '', |
| | | title: "", |
| | | applicant: "", |
| | | // status: '1' |
| | | }) |
| | | handleSearch() |
| | | } |
| | | }); |
| | | handleSearch(); |
| | | }; |
| | | |
| | | // æ¥ç详æ
|
| | | const viewDetail = (row) => { |
| | | currentMeeting.value = row |
| | | detailDialogVisible.value = true |
| | | } |
| | | const viewDetail = row => { |
| | | currentMeeting.value = row; |
| | | detailDialogVisible.value = true; |
| | | }; |
| | | |
| | | // æ·»å ä¼è®®çºªè¦ |
| | | const addMinutes = async (row) => { |
| | | let resp = await getMeetingMinutesByMeetingId(row.id) |
| | | currentMeeting.value = row |
| | | const addMinutes = async row => { |
| | | let resp = await getMeetingMinutesByMeetingId(row.id); |
| | | currentMeeting.value = row; |
| | | if (resp.data){ |
| | | minutesContent.value = resp.data.content |
| | | minutesContentId.value = resp.data.id |
| | | minutesContent.value = resp.data.content; |
| | | minutesContentId.value = resp.data.id; |
| | | }else { |
| | | minutesContent.value = `<h2>${row.title}ä¼è®®çºªè¦</h2> |
| | | <p><strong>ä¼è®®æ¶é´ï¼</strong>${row.meetingTime}</p> |
| | |
| | | <p><strong>主æäººï¼</strong>${row.host}</p> |
| | | <p><strong>åä¼äººåï¼</strong></p> |
| | | <ol> |
| | | ${row.participants.map(p => `<li>${p.name}</li>`).join('')} |
| | | ${row.participants.map(p => `<li>${p.name}</li>`).join("")} |
| | | </ol> |
| | | <p><strong>ä¼è®®å
容ï¼</strong></p> |
| | | <ol> |
| | |
| | | </ul> |
| | | </li> |
| | | </ol> |
| | | <p><strong>夿³¨ï¼</strong></p>` |
| | | <p><strong>夿³¨ï¼</strong></p>`; |
| | | } |
| | | |
| | | minutesDialogVisible.value = true |
| | | } |
| | | minutesDialogVisible.value = true; |
| | | }; |
| | | |
| | | // æäº¤ä¼è®®çºªè¦ |
| | | const submitMinutes = () => { |
| | | if (!minutesContent.value) { |
| | | ElMessage.warning('请è¾å
¥ä¼è®®çºªè¦å
容') |
| | | return |
| | | ElMessage.warning("请è¾å
¥ä¼è®®çºªè¦å
容"); |
| | | return; |
| | | } |
| | | saveMeetingMinutes({ |
| | | id: minutesContentId.value, |
| | | content: minutesContent.value, |
| | | meetingId: currentMeeting.value.id, |
| | | title: currentMeeting.value.title |
| | | title: currentMeeting.value.title, |
| | | }).then(resp=>{ |
| | | console.log('ä¼è®®çºªè¦å
容:', minutesContent.value) |
| | | ElMessage.success('ä¼è®®çºªè¦ä¿åæå') |
| | | minutesDialogVisible.value = false |
| | | }) |
| | | |
| | | } |
| | | console.log("ä¼è®®çºªè¦å
容:", minutesContent.value); |
| | | ElMessage.success("ä¼è®®çºªè¦ä¿åæå"); |
| | | minutesDialogVisible.value = false; |
| | | }); |
| | | }; |
| | | |
| | | // å
³éä¼è®®çºªè¦å¯¹è¯æ¡ |
| | | const handleCloseMinutesDialog = () => { |
| | | minutesContent.value = '' |
| | | } |
| | | minutesContent.value = ""; |
| | | }; |
| | | |
| | | // è·åç¶æç±»å |
| | | const getStatusType = (status) => { |
| | | const getStatusType = status => { |
| | | const statusMap = { |
| | | '0': 'info', // å¾
å®¡æ¹ |
| | | '1': 'success', // å·²éè¿ |
| | | '2': 'warning', // æªéè¿ |
| | | '3': 'danger' // åæ¶ |
| | | } |
| | | return statusMap[status] || 'info' |
| | | } |
| | | 0: "info", // å¾
å®¡æ¹ |
| | | 1: "success", // å·²éè¿ |
| | | 2: "warning", // æªéè¿ |
| | | 3: "danger", // åæ¶ |
| | | }; |
| | | return statusMap[status] || "info"; |
| | | }; |
| | | |
| | | // è·åç¶æææ¬ |
| | | const getStatusText = (status) => { |
| | | const getStatusText = status => { |
| | | const statusMap = { |
| | | '0': 'å¾
审æ¹', |
| | | '1': 'å·²éè¿', |
| | | '2': 'æªéè¿', |
| | | '3': '已忶' |
| | | } |
| | | return statusMap[status] || 'æªç¥' |
| | | } |
| | | 0: "å¾
审æ¹", |
| | | 1: "å·²éè¿", |
| | | 2: "æªéè¿", |
| | | 3: "已忶", |
| | | }; |
| | | return statusMap[status] || "æªç¥"; |
| | | }; |
| | | |
| | | // æ ¼å¼åæ¥ææ¶é´ |
| | | const formatDateTime = (dateTime) => { |
| | | if (!dateTime) return '' |
| | | return dateTime.replace(' ', '\n') |
| | | } |
| | | const formatDateTime = dateTime => { |
| | | if (!dateTime) return ""; |
| | | return dateTime.replace(" ", "\n"); |
| | | }; |
| | | |
| | | // 页é¢å è½½æ¶è·åæ°æ® |
| | | onMounted(async () => { |
| | | const [resp1, resp2] = await Promise.all([getRoomEnum(), getStaffOnJob()]) |
| | | roomEnum.value = resp1.data |
| | | staffList.value = resp2.data |
| | | const [resp1, resp2] = await Promise.all([getRoomEnum(), getStaffOnJob()]); |
| | | roomEnum.value = resp1.data; |
| | | staffList.value = resp2.data; |
| | | |
| | | await getList() |
| | | }) |
| | | await getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | |
| | | <template #header> |
| | | <div class="card-header"> |
| | | <span>åå
¬ç©èµç³è¯·ç®¡ç</span> |
| | | <el-button type="primary" @click="openShow()"> |
| | | <el-icon><Plus /></el-icon> |
| | | <el-button type="primary" |
| | | @click="openShow()"> |
| | | <el-icon> |
| | | <Plus /> |
| | | </el-icon> |
| | | æ°å»ºç³è¯· |
| | | </el-button> |
| | | </div> |
| | | </template> |
| | | |
| | | <!-- æç´¢åºå --> |
| | | <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch"> |
| | | <el-form-item label="ç³è¯·ç¼å·" prop="code"> |
| | | <el-input |
| | | v-model="queryParams.code" |
| | | <el-form :model="queryParams" |
| | | ref="queryRef" |
| | | :inline="true" |
| | | v-show="showSearch"> |
| | | <el-form-item label="ç³è¯·ç¼å·" |
| | | prop="code"> |
| | | <el-input v-model="queryParams.code" |
| | | placeholder="请è¾å
¥ç³è¯·ç¼å·" |
| | | clearable |
| | | style="width: 200px" |
| | | @keyup.enter="handleQuery" |
| | | /> |
| | | @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="ç³è¯·äºº" prop="applicant"> |
| | | <el-input |
| | | v-model="queryParams.applicant" |
| | | <el-form-item label="ç³è¯·äºº" |
| | | prop="applicant"> |
| | | <el-input v-model="queryParams.applicant" |
| | | placeholder="请è¾å
¥ç³è¯·äºº" |
| | | clearable |
| | | style="width: 200px" |
| | | @keyup.enter="handleQuery" |
| | | /> |
| | | @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="ç³è¯·ç¶æ" prop="status"> |
| | | <el-select v-model="queryParams.status" placeholder="è¯·éæ©ç¶æ" clearable style="width: 200px"> |
| | | <el-option label="å¾
审æ¹" value="1" /> |
| | | <el-option label="å·²éè¿" value="3" /> |
| | | <el-option label="å·²æç»" value="2" /> |
| | | <el-option label="已忾" value="4" /> |
| | | <el-form-item label="ç³è¯·ç¶æ" |
| | | prop="status"> |
| | | <el-select v-model="queryParams.status" |
| | | placeholder="è¯·éæ©ç¶æ" |
| | | clearable |
| | | style="width: 200px"> |
| | | <el-option label="å¾
审æ¹" |
| | | value="1" /> |
| | | <el-option label="å·²éè¿" |
| | | value="3" /> |
| | | <el-option label="å·²æç»" |
| | | value="2" /> |
| | | <el-option label="已忾" |
| | | value="4" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleQuery"> |
| | | <el-icon><Search /></el-icon> |
| | | <el-button type="primary" |
| | | @click="handleQuery"> |
| | | <el-icon> |
| | | <Search /> |
| | | </el-icon> |
| | | æç´¢ |
| | | </el-button> |
| | | <el-button @click="resetQuery"> |
| | | <el-icon><Refresh /></el-icon> |
| | | <el-icon> |
| | | <Refresh /> |
| | | </el-icon> |
| | | éç½® |
| | | </el-button> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleExport"> |
| | | <el-icon><Download /></el-icon> |
| | | <el-button type="primary" |
| | | @click="handleExport"> |
| | | <el-icon> |
| | | <Download /> |
| | | </el-icon> |
| | | å¯¼åº |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <!-- è¡¨æ ¼åºå --> |
| | | <el-table |
| | | v-loading="loading" |
| | | <el-table v-loading="loading" |
| | | :data="officeList" |
| | | @selection-change="handleSelectionChange" |
| | | style="width: 100%" |
| | | > |
| | | <el-table-column type="selection" width="55" align="center" /> |
| | | <el-table-column label="ç³è¯·ç¼å·" align="center" prop="code" width="180" /> |
| | | <el-table-column label="ç³è¯·äºº" align="center" prop="applicant" width="120" /> |
| | | <el-table-column label="é¨é¨" align="center" prop="dept" width="120" /> |
| | | <el-table-column label="ç©èµç±»å" align="center" prop="materialType" width="120"> |
| | | style="width: 100%"> |
| | | <el-table-column type="selection" |
| | | width="55" |
| | | align="center" /> |
| | | <el-table-column label="ç³è¯·ç¼å·" |
| | | align="center" |
| | | prop="code" |
| | | width="180" /> |
| | | <el-table-column label="ç³è¯·äºº" |
| | | align="center" |
| | | prop="applicant" |
| | | width="120" /> |
| | | <el-table-column label="é¨é¨" |
| | | align="center" |
| | | prop="dept" |
| | | width="120" /> |
| | | <el-table-column label="ç©èµç±»å" |
| | | align="center" |
| | | prop="materialType" |
| | | width="120"> |
| | | <template #default="scope"> |
| | | <el-tag v-if="scope.row.materialType === 1" type="info">å
¶ä»</el-tag> |
| | | <el-tag v-if="scope.row.materialType === 2" type="success">æ¸
æ´ç¨å</el-tag> |
| | | <el-tag v-if="scope.row.materialType === 3" type="warning">çµå设å¤</el-tag> |
| | | <el-tag v-if="scope.row.materialType === 4" type="danger">åå
¬ç¨å</el-tag> |
| | | <el-tag v-if="scope.row.materialType === 1" |
| | | type="info">å
¶ä»</el-tag> |
| | | <el-tag v-if="scope.row.materialType === 2" |
| | | type="success">æ¸
æ´ç¨å</el-tag> |
| | | <el-tag v-if="scope.row.materialType === 3" |
| | | type="warning">çµå设å¤</el-tag> |
| | | <el-tag v-if="scope.row.materialType === 4" |
| | | type="danger">åå
¬ç¨å</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="ç³è¯·æ°é" align="center" prop="applyNum" width="100" /> |
| | | <el-table-column label="ç³è¯·åå " align="center" prop="reason" min-width="200" show-overflow-tooltip /> |
| | | <el-table-column label="ç³è¯·ç¶æ" align="center" prop="status" width="100"> |
| | | <el-table-column label="ç³è¯·æ°é" |
| | | align="center" |
| | | prop="applyNum" |
| | | width="100" /> |
| | | <el-table-column label="ç³è¯·åå " |
| | | align="center" |
| | | prop="reason" |
| | | min-width="200" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="ç³è¯·ç¶æ" |
| | | align="center" |
| | | prop="status" |
| | | width="100"> |
| | | <template #default="scope"> |
| | | <el-tag :type="getStatusType(scope.row.status)"> |
| | | {{ getStatusText(scope.row.status) }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="ç³è¯·æ¶é´" align="center" prop="applyTime" width="180" /> |
| | | <el-table-column label="审æ¹äºº" align="center" prop="approval" width="120" /> |
| | | <el-table-column label="å®¡æ¹æ¶é´" align="center" prop="approvalTime" width="180" /> |
| | | <el-table-column label="åæ¾æ¶é´" align="center" prop="issueTime" width="180" /> |
| | | <el-table-column label="æä½" align="center" fixed="right" class-name="small-padding fixed-width" width="200"> |
| | | <el-table-column label="ç³è¯·æ¶é´" |
| | | align="center" |
| | | prop="applyTime" |
| | | width="180" /> |
| | | <el-table-column label="审æ¹äºº" |
| | | align="center" |
| | | prop="approval" |
| | | width="120" /> |
| | | <el-table-column label="å®¡æ¹æ¶é´" |
| | | align="center" |
| | | prop="approvalTime" |
| | | width="180" /> |
| | | <el-table-column label="åæ¾æ¶é´" |
| | | align="center" |
| | | prop="issueTime" |
| | | width="180" /> |
| | | <el-table-column label="æä½" |
| | | align="center" |
| | | fixed="right" |
| | | class-name="small-padding fixed-width" |
| | | width="200"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | v-if="scope.row.status === 1" |
| | | <el-button v-if="scope.row.status === 1" |
| | | type="primary" |
| | | link |
| | | @click="handleApprove(scope.row)" |
| | | > |
| | | @click="handleApprove(scope.row)"> |
| | | å®¡æ¹ |
| | | </el-button> |
| | | <el-button |
| | | v-if="scope.row.status === 3" |
| | | <el-button v-if="scope.row.status === 3" |
| | | type="success" |
| | | link |
| | | @click="handleIssue(scope.row)" |
| | | > |
| | | @click="handleIssue(scope.row)"> |
| | | åæ¾ |
| | | </el-button> |
| | | <el-button |
| | | type="info" |
| | | <el-button type="info" |
| | | link |
| | | @click="handleDetail(scope.row)" |
| | | > |
| | | @click="handleDetail(scope.row)"> |
| | | 详æ
|
| | | </el-button> |
| | | <el-button |
| | | v-if="scope.row.status === 2" |
| | | <el-button v-if="scope.row.status === 2" |
| | | type="danger" |
| | | link |
| | | @click="handleDelete(scope.row)" |
| | | > |
| | | @click="handleDelete(scope.row)"> |
| | | å é¤ |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <!-- å页 --> |
| | | <pagination |
| | | v-show="total > 0" |
| | | <pagination v-show="total > 0" |
| | | :total="total" |
| | | v-model:page="queryParams.current" |
| | | v-model:limit="queryParams.size" |
| | | @pagination="getList" |
| | | /> |
| | | @pagination="getList" /> |
| | | </el-card> |
| | | |
| | | <!-- ç³è¯·å¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | v-model="showApplyDialog" |
| | | <el-dialog v-model="showApplyDialog" |
| | | title="åå
¬ç©èµç³è¯·" |
| | | width="600px" |
| | | append-to-body |
| | | > |
| | | <el-form ref="applyFormRef" :model="applyForm" :rules="applyRules" label-width="100px"> |
| | | <el-form-item label="ç³è¯·äºº" prop="applicant"> |
| | | <el-input v-model="applyForm.applicant" placeholder="请è¾å
¥ç³è¯·äººåç§°" /> |
| | | append-to-body> |
| | | <el-form ref="applyFormRef" |
| | | :model="applyForm" |
| | | :rules="applyRules" |
| | | label-width="100px"> |
| | | <el-form-item label="ç³è¯·äºº" |
| | | prop="applicant"> |
| | | <el-input v-model="applyForm.applicant" |
| | | placeholder="请è¾å
¥ç³è¯·äººåç§°" /> |
| | | </el-form-item> |
| | | <el-form-item label="é¨é¨" prop="dept"> |
| | | <el-input v-model="applyForm.dept" placeholder="请è¾å
¥é¨é¨åç§°" /> |
| | | <el-form-item label="é¨é¨" |
| | | prop="dept"> |
| | | <el-input v-model="applyForm.dept" |
| | | placeholder="请è¾å
¥é¨é¨åç§°" /> |
| | | </el-form-item> |
| | | <el-form-item label="ç©èµç±»å" prop="materialType"> |
| | | <el-select v-model="applyForm.materialType" placeholder="è¯·éæ©ç©èµç±»å" style="width: 100%"> |
| | | <el-option label="åå
¬ç¨å" value="4" /> |
| | | <el-option label="çµå设å¤" value="3" /> |
| | | <el-option label="æ¸
æ´ç¨å" value="2" /> |
| | | <el-option label="å
¶ä»" value="1" /> |
| | | <el-form-item label="ç©èµç±»å" |
| | | prop="materialType"> |
| | | <el-select v-model="applyForm.materialType" |
| | | placeholder="è¯·éæ©ç©èµç±»å" |
| | | style="width: 100%"> |
| | | <el-option label="åå
¬ç¨å" |
| | | value="4" /> |
| | | <el-option label="çµå设å¤" |
| | | value="3" /> |
| | | <el-option label="æ¸
æ´ç¨å" |
| | | value="2" /> |
| | | <el-option label="å
¶ä»" |
| | | value="1" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="å
·ä½ç©å" prop="itemName"> |
| | | <el-input v-model="applyForm.itemName" placeholder="请è¾å
¥å
·ä½ç©ååç§°" /> |
| | | <el-form-item label="å
·ä½ç©å" |
| | | prop="itemName"> |
| | | <el-input v-model="applyForm.itemName" |
| | | placeholder="请è¾å
¥å
·ä½ç©ååç§°" /> |
| | | </el-form-item> |
| | | <el-form-item label="ç³è¯·æ°é" prop="applyNum"> |
| | | <el-input-number v-model="applyForm.applyNum" :min="1" :max="999" style="width: 100%" /> |
| | | <el-form-item label="ç³è¯·æ°é" |
| | | prop="applyNum"> |
| | | <el-input-number v-model="applyForm.applyNum" |
| | | :min="1" |
| | | :max="999" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | <el-form-item label="ç³è¯·åå " prop="reason"> |
| | | <el-input |
| | | v-model="applyForm.reason" |
| | | <el-form-item label="ç³è¯·åå " |
| | | prop="reason"> |
| | | <el-input v-model="applyForm.reason" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥ç³è¯·åå " |
| | | /> |
| | | placeholder="请è¾å
¥ç³è¯·åå " /> |
| | | </el-form-item> |
| | | <el-form-item label="ç´§æ¥ç¨åº¦" prop="urgency"> |
| | | <el-form-item label="ç´§æ¥ç¨åº¦" |
| | | prop="urgency"> |
| | | <el-radio-group v-model="applyForm.urgency"> |
| | | <el-radio label="1">æ®é</el-radio> |
| | | <el-radio label="2">ç´§æ¥</el-radio> |
| | |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="submitApply">ç¡® å®</el-button> |
| | | <el-button @click="showApplyDialog = false">å æ¶</el-button> |
| | | <el-button type="primary" @click="submitApply">ç¡® å®</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- 审æ¹å¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | v-model="showApproveDialog" |
| | | <el-dialog v-model="showApproveDialog" |
| | | title="审æ¹ç³è¯·" |
| | | width="500px" |
| | | append-to-body |
| | | > |
| | | <el-form ref="approveFormRef" :model="approveForm" :rules="approveRules" label-width="100px"> |
| | | <el-form-item label="审æ¹ç»æ" prop="approveResult"> |
| | | append-to-body> |
| | | <el-form ref="approveFormRef" |
| | | :model="approveForm" |
| | | :rules="approveRules" |
| | | label-width="100px"> |
| | | <el-form-item label="审æ¹ç»æ" |
| | | prop="approveResult"> |
| | | <el-radio-group v-model="approveForm.approveResult"> |
| | | <el-radio label="3">éè¿</el-radio> |
| | | <el-radio label="2">æç»</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | <el-form-item label="å®¡æ¹æè§" prop="approvalOpinions"> |
| | | <el-input |
| | | v-model="approveForm.approvalOpinions" |
| | | <el-form-item label="å®¡æ¹æè§" |
| | | prop="approvalOpinions"> |
| | | <el-input v-model="approveForm.approvalOpinions" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥å®¡æ¹æè§" |
| | | /> |
| | | placeholder="请è¾å
¥å®¡æ¹æè§" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="submitApprove">ç¡® å®</el-button> |
| | | <el-button @click="showApproveDialog = false">å æ¶</el-button> |
| | | <el-button type="primary" @click="submitApprove">ç¡® å®</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- 详æ
å¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | v-model="showDetailDialog" |
| | | <el-dialog v-model="showDetailDialog" |
| | | title="ç³è¯·è¯¦æ
" |
| | | width="700px" |
| | | append-to-body |
| | | > |
| | | <el-descriptions :column="2" border> |
| | | append-to-body> |
| | | <el-descriptions :column="2" |
| | | border> |
| | | <el-descriptions-item label="ç³è¯·ç¼å·">{{ currentDetail.code }}</el-descriptions-item> |
| | | <el-descriptions-item label="ç³è¯·äºº">{{ currentDetail.applicant }}</el-descriptions-item> |
| | | <el-descriptions-item label="é¨é¨">{{ currentDetail.dept }}</el-descriptions-item> |
| | | <el-descriptions-item label="ç©èµç±»å">{{ currentDetail.materialType }}</el-descriptions-item> |
| | | <el-descriptions-item label="å
·ä½ç©å">{{ currentDetail.itemName }}</el-descriptions-item> |
| | | <el-descriptions-item label="ç³è¯·æ°é">{{ currentDetail.applyNum }}</el-descriptions-item> |
| | | <el-descriptions-item label="ç³è¯·åå " :span="2">{{ currentDetail.reason }}</el-descriptions-item> |
| | | <el-descriptions-item label="ç³è¯·åå " |
| | | :span="2">{{ currentDetail.reason }}</el-descriptions-item> |
| | | <el-descriptions-item label="ç³è¯·ç¶æ"> |
| | | <el-tag :type="getStatusType(currentDetail.status)"> |
| | | {{ getStatusText(currentDetail.status) }} |
| | |
| | | <el-descriptions-item label="ç³è¯·æ¶é´">{{ currentDetail.applyTime }}</el-descriptions-item> |
| | | <el-descriptions-item label="审æ¹äºº">{{ currentDetail.approval || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="å®¡æ¹æ¶é´">{{ currentDetail.approvalTime || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="å®¡æ¹æè§" :span="2">{{ currentDetail.approvalOpinions || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="å®¡æ¹æè§" |
| | | :span="2">{{ currentDetail.approvalOpinions || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="åæ¾æ¶é´">{{ currentDetail.issueTime || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="åæ¾äºº">{{ currentDetail.issueUser || '-' }}</el-descriptions-item> |
| | | </el-descriptions> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {listPage,add,update,deleteOff} from "@/api/collaborativeApproval/officeSupplies.js" |
| | | import {ref, reactive, onMounted, getCurrentInstance} from 'vue' |
| | | import Cookies from 'js-cookie' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { Plus, Search, Refresh, Download, Check } from '@element-plus/icons-vue' |
| | | import { |
| | | listPage, |
| | | add, |
| | | update, |
| | | deleteOff, |
| | | } from "@/api/collaborativeApproval/officeSupplies.js"; |
| | | import { ref, reactive, onMounted, getCurrentInstance } from "vue"; |
| | | import Cookies from "js-cookie"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import { |
| | | Plus, |
| | | Search, |
| | | Refresh, |
| | | Download, |
| | | Check, |
| | | } from "@element-plus/icons-vue"; |
| | | |
| | | // ååºå¼æ°æ® |
| | | const loading = ref(false) |
| | | const showSearch = ref(true) |
| | | const showApplyDialog = ref(false) |
| | | const showApproveDialog = ref(false) |
| | | const showDetailDialog = ref(false) |
| | | const multipleSelection = ref([]) |
| | | const officeList = ref([]) |
| | | const total = ref(0) |
| | | const suppliesList = ref([]) |
| | | const currentDetail = ref({}) |
| | | const loading = ref(false); |
| | | const showSearch = ref(true); |
| | | const showApplyDialog = ref(false); |
| | | const showApproveDialog = ref(false); |
| | | const showDetailDialog = ref(false); |
| | | const multipleSelection = ref([]); |
| | | const officeList = ref([]); |
| | | const total = ref(0); |
| | | const suppliesList = ref([]); |
| | | const currentDetail = ref({}); |
| | | |
| | | // æ¥è¯¢åæ° |
| | | const queryParams = reactive({ |
| | | current: 1, |
| | | size: 10, |
| | | code: '', |
| | | applicant: '', |
| | | status: '' |
| | | }) |
| | | code: "", |
| | | applicant: "", |
| | | status: "", |
| | | }); |
| | | |
| | | // ç³è¯·è¡¨å |
| | | const applyForm = reactive({ |
| | | applicant: '', |
| | | dept: '', |
| | | materialType: '', |
| | | itemName: '', |
| | | applicant: "", |
| | | dept: "", |
| | | materialType: "", |
| | | itemName: "", |
| | | applyNum: 1, |
| | | reason: '', |
| | | urgency: '1' |
| | | }) |
| | | reason: "", |
| | | urgency: "1", |
| | | }); |
| | | |
| | | // 审æ¹è¡¨å |
| | | const approveForm = reactive({ |
| | | approveResult: '3', |
| | | approvalOpinions: '' |
| | | }) |
| | | approveResult: "3", |
| | | approvalOpinions: "", |
| | | }); |
| | | |
| | | // è¡¨åæ ¡éªè§å |
| | | const applyRules = { |
| | | applicant: [{ required: true, message: 'è¯·éæ©ç©èµç±»å', trigger: 'blur' }], |
| | | dept: [{ required: true, message: 'è¯·éæ©ç©èµç±»å', trigger: 'blur' }], |
| | | materialType: [{ required: true, message: 'è¯·éæ©ç©èµç±»å', trigger: 'change' }], |
| | | itemName: [{ required: true, message: '请è¾å
¥å
·ä½ç©ååç§°', trigger: 'blur' }], |
| | | applyNum: [{ required: true, message: '请è¾å
¥ç³è¯·æ°é', trigger: 'blur' }], |
| | | reason: [{ required: true, message: '请è¾å
¥ç³è¯·åå ', trigger: 'blur' }] |
| | | } |
| | | applicant: [{ required: true, message: "è¯·éæ©ç©èµç±»å", trigger: "blur" }], |
| | | dept: [{ required: true, message: "è¯·éæ©ç©èµç±»å", trigger: "blur" }], |
| | | materialType: [ |
| | | { required: true, message: "è¯·éæ©ç©èµç±»å", trigger: "change" }, |
| | | ], |
| | | itemName: [ |
| | | { required: true, message: "请è¾å
¥å
·ä½ç©ååç§°", trigger: "blur" }, |
| | | ], |
| | | applyNum: [{ required: true, message: "请è¾å
¥ç³è¯·æ°é", trigger: "blur" }], |
| | | reason: [{ required: true, message: "请è¾å
¥ç³è¯·åå ", trigger: "blur" }], |
| | | }; |
| | | |
| | | const approveRules = { |
| | | approveResult: [{ required: true, message: 'è¯·éæ©å®¡æ¹ç»æ', trigger: 'change' }], |
| | | approvalOpinions: [{ required: true, message: '请è¾å
¥å®¡æ¹æè§', trigger: 'blur' }] |
| | | } |
| | | approveResult: [ |
| | | { required: true, message: "è¯·éæ©å®¡æ¹ç»æ", trigger: "change" }, |
| | | ], |
| | | approvalOpinions: [ |
| | | { required: true, message: "请è¾å
¥å®¡æ¹æè§", trigger: "blur" }, |
| | | ], |
| | | }; |
| | | |
| | | const openShow = () => { |
| | | showApplyDialog.value = true |
| | | resetApplyForm() |
| | | } |
| | | showApplyDialog.value = true; |
| | | resetApplyForm(); |
| | | }; |
| | | |
| | | // è·ååè¡¨æ°æ® |
| | | const getList = () => { |
| | | loading.value = true |
| | | loading.value = true; |
| | | listPage(queryParams).then(res => { |
| | | total.value = res.data.total |
| | | loading.value = false |
| | | officeList.value = res.data.records |
| | | }) |
| | | } |
| | | total.value = res.data.total; |
| | | loading.value = false; |
| | | officeList.value = res.data.records; |
| | | }); |
| | | }; |
| | | |
| | | // æ¥è¯¢ |
| | | const handleQuery = () => { |
| | | queryParams.current = 1 |
| | | getList() |
| | | } |
| | | queryParams.current = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | // éç½®æ¥è¯¢ |
| | | const resetQuery = () => { |
| | | queryParams.code = '' |
| | | queryParams.applicant = '' |
| | | queryParams.status = '' |
| | | handleQuery() |
| | | } |
| | | queryParams.code = ""; |
| | | queryParams.applicant = ""; |
| | | queryParams.status = ""; |
| | | handleQuery(); |
| | | }; |
| | | |
| | | // å¤é |
| | | const handleSelectionChange = (selection) => { |
| | | multipleSelection.value = selection |
| | | } |
| | | const handleSelectionChange = selection => { |
| | | multipleSelection.value = selection; |
| | | }; |
| | | |
| | | // è·åç¶æç±»å |
| | | const getStatusType = (status) => { |
| | | const getStatusType = status => { |
| | | const statusMap = { |
| | | 1: 'warning', |
| | | 3: 'success', |
| | | 2: 'danger', |
| | | 4: 'info' |
| | | } |
| | | return statusMap[status] || 'info' |
| | | } |
| | | 1: "warning", |
| | | 3: "success", |
| | | 2: "danger", |
| | | 4: "info", |
| | | }; |
| | | return statusMap[status] || "info"; |
| | | }; |
| | | |
| | | // è·åç¶æææ¬ |
| | | const getStatusText = (status) => { |
| | | const getStatusText = status => { |
| | | const statusMap = { |
| | | 1: 'å¾
审æ¹', |
| | | 3: 'å·²éè¿', |
| | | 2: 'å·²æç»', |
| | | 4: '已忾' |
| | | } |
| | | return statusMap[status] || status |
| | | } |
| | | 1: "å¾
审æ¹", |
| | | 3: "å·²éè¿", |
| | | 2: "å·²æç»", |
| | | 4: "已忾", |
| | | }; |
| | | return statusMap[status] || status; |
| | | }; |
| | | |
| | | // æäº¤ç³è¯· |
| | | const submitApply = () => { |
| | | add(applyForm).then(() => { |
| | | ElMessage.success('ç³è¯·æå') |
| | | getList() |
| | | showApplyDialog.value = false |
| | | resetApplyForm() |
| | | }) |
| | | |
| | | |
| | | |
| | | } |
| | | ElMessage.success("ç³è¯·æå"); |
| | | getList(); |
| | | showApplyDialog.value = false; |
| | | resetApplyForm(); |
| | | }); |
| | | }; |
| | | |
| | | //é置表å |
| | | const resetApplyForm = () => { |
| | | // é置表å |
| | | Object.assign(applyForm, { |
| | | applicant: '', |
| | | dept: '', |
| | | materialType: '', |
| | | itemName: '', |
| | | applicant: "", |
| | | dept: "", |
| | | materialType: "", |
| | | itemName: "", |
| | | applyNum: 1, |
| | | reason: '', |
| | | urgency: '1' |
| | | }) |
| | | } |
| | | reason: "", |
| | | urgency: "1", |
| | | }); |
| | | }; |
| | | |
| | | // å®¡æ¹ |
| | | const handleApprove = (row) => { |
| | | currentDetail.value = row |
| | | showApproveDialog.value = true |
| | | } |
| | | const handleApprove = row => { |
| | | currentDetail.value = row; |
| | | showApproveDialog.value = true; |
| | | }; |
| | | |
| | | const formatDate = (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 sends = String(date.getSeconds()).padStart(2, '0') |
| | | return `${year}-${month}-${day} ${hours}:${minutes}:${sends}` |
| | | } |
| | | const formatDate = 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 sends = String(date.getSeconds()).padStart(2, "0"); |
| | | return `${year}-${month}-${day} ${hours}:${minutes}:${sends}`; |
| | | }; |
| | | |
| | | // æäº¤å®¡æ¹ |
| | | const submitApprove = () => { |
| | | currentDetail.value.status = approveForm.approveResult |
| | | currentDetail.value.status = approveForm.approveResult; |
| | | // ä»cookieä¸è·åå½åç»å½ç¨æ·åç§° |
| | | currentDetail.value.approval = Cookies.get('username') |
| | | currentDetail.value.approvalTime = formatDate(new Date()) |
| | | currentDetail.value.approvalOpinions = approveForm.approvalOpinions |
| | | update(currentDetail.value).then((res) => { |
| | | currentDetail.value.approval = Cookies.get("username"); |
| | | currentDetail.value.approvalTime = formatDate(new Date()); |
| | | currentDetail.value.approvalOpinions = approveForm.approvalOpinions; |
| | | update(currentDetail.value).then(res => { |
| | | if(res.code === 200){ |
| | | showApproveDialog.value = false |
| | | ElMessage.success('审æ¹å®æ') |
| | | getList() |
| | | showApproveDialog.value = false; |
| | | ElMessage.success("审æ¹å®æ"); |
| | | getList(); |
| | | |
| | | // é置表å |
| | | Object.assign(approveForm, { |
| | | approveResult: '3', |
| | | approvalOpinions: '' |
| | | }) |
| | | approveResult: "3", |
| | | approvalOpinions: "", |
| | | }); |
| | | } |
| | | }) |
| | | |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // åæ¾ |
| | | const handleIssue = (row) => { |
| | | row.status = 4 |
| | | row.issueTime = formatDate(new Date()) |
| | | row.issueUser = Cookies.get('username') |
| | | update(row).then((res) =>{ |
| | | const handleIssue = row => { |
| | | row.status = 4; |
| | | row.issueTime = formatDate(new Date()); |
| | | row.issueUser = Cookies.get("username"); |
| | | update(row).then(res => { |
| | | if(res.code === 200){ |
| | | ElMessage.success('忾宿') |
| | | getList() |
| | | ElMessage.success("忾宿"); |
| | | getList(); |
| | | } |
| | | }) |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // æ¥ç详æ
|
| | | const handleDetail = (row) => { |
| | | currentDetail.value = row |
| | | showDetailDialog.value = true |
| | | } |
| | | const handleDetail = row => { |
| | | currentDetail.value = row; |
| | | showDetailDialog.value = true; |
| | | }; |
| | | |
| | | // å é¤ |
| | | const handleDelete = (row) => { |
| | | ElMessageBox.confirm('确认å é¤è¯¥ç³è¯·åï¼', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | const handleDelete = row => { |
| | | ElMessageBox.confirm("确认å é¤è¯¥ç³è¯·åï¼", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).then(() => { |
| | | let ids = [row.id] |
| | | deleteOff(ids).then((res) =>{ |
| | | ElMessage.success('å 餿å') |
| | | getList() |
| | | }) |
| | | }) |
| | | } |
| | | let ids = [row.id]; |
| | | deleteOff(ids).then(res => { |
| | | ElMessage.success("å 餿å"); |
| | | getList(); |
| | | }); |
| | | }); |
| | | }; |
| | | const { proxy } = getCurrentInstance(); |
| | | // å¯¼åº |
| | | const handleExport = () => { |
| | |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | // 页é¢å è½½æ¶è·åæ°æ® |
| | | onMounted(() => { |
| | | getList() |
| | | }) |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | |
| | | <!-- 顶鍿使 --> |
| | | <div class="header-actions"> |
| | | <div class="left-actions"> |
| | | <el-select v-model="currentLevel" placeholder="éæ©è®¡å级å«" style="width: 150px" @change="handleLevelChange"> |
| | | <el-option label="个人计å" value="personal" /> |
| | | <el-option label="å°ç»è®¡å" value="group" /> |
| | | <el-option label="é¨é¨è®¡å" value="department" /> |
| | | <el-option label="å
¬å¸è®¡å" value="company" /> |
| | | <el-select v-model="currentLevel" |
| | | placeholder="éæ©è®¡å级å«" |
| | | style="width: 150px" |
| | | @change="handleLevelChange"> |
| | | <el-option label="个人计å" |
| | | value="personal" /> |
| | | <el-option label="å°ç»è®¡å" |
| | | value="group" /> |
| | | <el-option label="é¨é¨è®¡å" |
| | | value="department" /> |
| | | <el-option label="å
¬å¸è®¡å" |
| | | value="company" /> |
| | | </el-select> |
| | | <el-select v-model="currentPeriod" placeholder="éæ©æ¶é´å¨æ" style="width: 120px; margin-left: 10px" @change="handlePeriodChange"> |
| | | <el-option label="å¨è®¡å" value="week" /> |
| | | <el-option label="æè®¡å" value="month" /> |
| | | <el-option label="年计å" value="year" /> |
| | | <el-select v-model="currentPeriod" |
| | | placeholder="éæ©æ¶é´å¨æ" |
| | | style="width: 120px; margin-left: 10px" |
| | | @change="handlePeriodChange"> |
| | | <el-option label="å¨è®¡å" |
| | | value="week" /> |
| | | <el-option label="æè®¡å" |
| | | value="month" /> |
| | | <el-option label="年计å" |
| | | value="year" /> |
| | | </el-select> |
| | | <el-date-picker |
| | | v-model="currentDate" |
| | | <el-date-picker v-model="currentDate" |
| | | :type="datePickerType" |
| | | placeholder="éæ©æ¥æ" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 180px; margin-left: 10px" |
| | | @change="handleDateChange" |
| | | /> |
| | | @change="handleDateChange" /> |
| | | </div> |
| | | <div class="right-actions"> |
| | | <el-button type="primary" @click="handleAddPlan">æ°å¢è®¡å</el-button> |
| | | <el-button type="primary" |
| | | @click="handleAddPlan">æ°å¢è®¡å</el-button> |
| | | <el-button @click="handleExport">导åºè®¡å</el-button> |
| | | <!-- <el-button @click="handleShare">å
±äº«è®¡å@</el-button> --> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- è®¡åæ¦è§å¡ç --> |
| | | <div class="overview-cards"> |
| | | <el-row :gutter="20"> |
| | |
| | | <el-card class="overview-card"> |
| | | <div class="card-content"> |
| | | <div class="card-icon personal"> |
| | | <el-icon><User /></el-icon> |
| | | <el-icon> |
| | | <User /> |
| | | </el-icon> |
| | | </div> |
| | | <div class="card-info"> |
| | | <div class="card-title">个人计å</div> |
| | | <div class="card-number">{{ overviewData.personal.total }}</div> |
| | | <div class="card-progress"> |
| | | <el-progress :percentage="overviewData.personal.completion" :stroke-width="6" /> |
| | | <el-progress :percentage="overviewData.personal.completion" |
| | | :stroke-width="6" /> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | <el-card class="overview-card"> |
| | | <div class="card-content"> |
| | | <div class="card-icon group"> |
| | | <el-icon><UserFilled /></el-icon> |
| | | <el-icon> |
| | | <UserFilled /> |
| | | </el-icon> |
| | | </div> |
| | | <div class="card-info"> |
| | | <div class="card-title">å°ç»è®¡å</div> |
| | | <div class="card-number">{{ overviewData.group.total }}</div> |
| | | <div class="card-progress"> |
| | | <el-progress :percentage="overviewData.group.completion" :stroke-width="6" /> |
| | | <el-progress :percentage="overviewData.group.completion" |
| | | :stroke-width="6" /> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | <el-card class="overview-card"> |
| | | <div class="card-content"> |
| | | <div class="card-icon department"> |
| | | <el-icon><OfficeBuilding /></el-icon> |
| | | <el-icon> |
| | | <OfficeBuilding /> |
| | | </el-icon> |
| | | </div> |
| | | <div class="card-info"> |
| | | <div class="card-title">é¨é¨è®¡å</div> |
| | | <div class="card-number">{{ overviewData.department.total }}</div> |
| | | <div class="card-progress"> |
| | | <el-progress :percentage="overviewData.department.completion" :stroke-width="6" /> |
| | | <el-progress :percentage="overviewData.department.completion" |
| | | :stroke-width="6" /> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | <el-card class="overview-card"> |
| | | <div class="card-content"> |
| | | <div class="card-icon company"> |
| | | <el-icon><House /></el-icon> |
| | | <el-icon> |
| | | <House /> |
| | | </el-icon> |
| | | </div> |
| | | <div class="card-info"> |
| | | <div class="card-title">å
¬å¸è®¡å</div> |
| | | <div class="card-number">{{ overviewData.company.total }}</div> |
| | | <div class="card-progress"> |
| | | <el-progress :percentage="overviewData.company.completion" :stroke-width="6" /> |
| | | <el-progress :percentage="overviewData.company.completion" |
| | | :stroke-width="6" /> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | |
| | | <!-- 计åå表 --> |
| | | <div class="plan-content"> |
| | | <el-card> |
| | |
| | | <div class="card-header"> |
| | | <span>{{ getCurrentLevelText() }} - {{ getCurrentPeriodText() }}</span> |
| | | <div> |
| | | <el-button size="small" @click="handleRefresh">å·æ°</el-button> |
| | | <el-button size="small" |
| | | @click="handleRefresh">å·æ°</el-button> |
| | | <!-- <el-button size="small" @click="handleFilter">çé@</el-button> --> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <div class="plan-list"> |
| | | <div v-for="plan in planList" :key="plan.id" class="plan-item"> |
| | | <div v-for="plan in planList" |
| | | :key="plan.id" |
| | | class="plan-item"> |
| | | <div class="plan-header"> |
| | | <div class="plan-title"> |
| | | <el-tag :type="getPriorityType(plan.priority)" size="small">{{ getPriorityText(plan.priority) }}</el-tag> |
| | | <el-tag :type="getPriorityType(plan.priority)" |
| | | size="small">{{ getPriorityText(plan.priority) }}</el-tag> |
| | | <span class="title-text">{{ plan.title }}</span> |
| | | </div> |
| | | <div class="plan-actions"> |
| | | <el-button size="small" @click="handleEditPlan(plan)">ç¼è¾</el-button> |
| | | <el-button size="small" @click="handleViewDetail(plan)">详æ
</el-button> |
| | | <el-button size="small" |
| | | @click="handleEditPlan(plan)">ç¼è¾</el-button> |
| | | <el-button size="small" |
| | | @click="handleViewDetail(plan)">详æ
</el-button> |
| | | <el-dropdown @command="(command) => handleMoreAction(plan, command)"> |
| | | <el-button size="small"> |
| | | æ´å¤<el-icon class="el-icon--right"><ArrowDown /></el-icon> |
| | | æ´å¤<el-icon class="el-icon--right"> |
| | | <ArrowDown /> |
| | | </el-icon> |
| | | </el-button> |
| | | <template #dropdown> |
| | | <el-dropdown-menu> |
| | | <!-- <el-dropdown-item command="share">å
񄧮@</el-dropdown-item> --> |
| | | <el-dropdown-item command="copy">å¤å¶</el-dropdown-item> |
| | | <el-dropdown-item command="delete" divided>å é¤</el-dropdown-item> |
| | | <el-dropdown-item command="delete" |
| | | divided>å é¤</el-dropdown-item> |
| | | </el-dropdown-menu> |
| | | </template> |
| | | </el-dropdown> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="plan-content"> |
| | | <div class="plan-description">{{ plan.description }}</div> |
| | | <div class="plan-meta"> |
| | | <div class="meta-item"> |
| | | <el-icon><Calendar /></el-icon> |
| | | <el-icon> |
| | | <Calendar /> |
| | | </el-icon> |
| | | <span>{{ plan.startDate }} - {{ plan.endDate }}</span> |
| | | </div> |
| | | <div class="meta-item"> |
| | | <el-icon><User /></el-icon> |
| | | <el-icon> |
| | | <User /> |
| | | </el-icon> |
| | | <span>{{ plan.assignee }}</span> |
| | | </div> |
| | | <div class="meta-item"> |
| | | <el-icon><Clock /></el-icon> |
| | | <el-icon> |
| | | <Clock /> |
| | | </el-icon> |
| | | <span>è¿åº¦: {{ plan.progress }}%</span> |
| | | </div> |
| | | <div class="meta-item"> |
| | | <el-icon><Flag /></el-icon> |
| | | <el-icon> |
| | | <Flag /> |
| | | </el-icon> |
| | | <span>{{ getStatusText(plan.status) }}</span> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="plan-progress"> |
| | | <el-progress |
| | | :percentage="plan.progress" |
| | | <el-progress :percentage="plan.progress" |
| | | :color="getProgressColor(plan.progress)" |
| | | :stroke-width="8" |
| | | /> |
| | | :stroke-width="8" /> |
| | | </div> |
| | | |
| | | <div class="plan-tags"> |
| | | <el-tag v-for="tag in plan.tags" :key="tag" size="small" style="margin-right: 5px"> |
| | | <el-tag v-for="tag in plan.tags" |
| | | :key="tag" |
| | | size="small" |
| | | style="margin-right: 5px"> |
| | | {{ tag }} |
| | | </el-tag> |
| | | </div> |
| | |
| | | </div> |
| | | </el-card> |
| | | </div> |
| | | |
| | | <!-- æ°å¢/ç¼è¾è®¡åå¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | v-model="planDialogVisible" |
| | | <el-dialog v-model="planDialogVisible" |
| | | :title="operationType === 'add' ? 'åå¸è®¡å' : 'ç¼è¾è®¡å'" |
| | | width="600px" |
| | | @close="handleDialogClose" |
| | | > |
| | | <el-form :model="planForm" :rules="planRules" ref="planFormRef" label-width="100px"> |
| | | <el-form-item label="è®¡åæ é¢" prop="title"> |
| | | <el-input v-model="planForm.title" placeholder="请è¾å
¥è®¡åæ é¢" /> |
| | | @close="handleDialogClose"> |
| | | <el-form :model="planForm" |
| | | :rules="planRules" |
| | | ref="planFormRef" |
| | | label-width="100px"> |
| | | <el-form-item label="è®¡åæ é¢" |
| | | prop="title"> |
| | | <el-input v-model="planForm.title" |
| | | placeholder="请è¾å
¥è®¡åæ é¢" /> |
| | | </el-form-item> |
| | | <el-form-item label="计åæè¿°" prop="description"> |
| | | <el-input |
| | | v-model="planForm.description" |
| | | <el-form-item label="计åæè¿°" |
| | | prop="description"> |
| | | <el-input v-model="planForm.description" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥è®¡åæè¿°" |
| | | /> |
| | | placeholder="请è¾å
¥è®¡åæè¿°" /> |
| | | </el-form-item> |
| | | <el-form-item label="计å级å«" prop="level"> |
| | | <el-select v-model="planForm.level" placeholder="éæ©è®¡å级å«" style="width: 100%"> |
| | | <el-option label="个人计å" value="personal" /> |
| | | <el-option label="å°ç»è®¡å" value="group" /> |
| | | <el-option label="é¨é¨è®¡å" value="department" /> |
| | | <el-option label="å
¬å¸è®¡å" value="company" /> |
| | | <el-form-item label="计å级å«" |
| | | prop="level"> |
| | | <el-select v-model="planForm.level" |
| | | placeholder="éæ©è®¡å级å«" |
| | | style="width: 100%"> |
| | | <el-option label="个人计å" |
| | | value="personal" /> |
| | | <el-option label="å°ç»è®¡å" |
| | | value="group" /> |
| | | <el-option label="é¨é¨è®¡å" |
| | | value="department" /> |
| | | <el-option label="å
¬å¸è®¡å" |
| | | value="company" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="æ¶é´å¨æ" prop="period"> |
| | | <el-select v-model="planForm.period" placeholder="éæ©æ¶é´å¨æ" style="width: 100%"> |
| | | <el-option label="å¨è®¡å" value="week" /> |
| | | <el-option label="æè®¡å" value="month" /> |
| | | <el-option label="年计å" value="year" /> |
| | | <el-form-item label="æ¶é´å¨æ" |
| | | prop="period"> |
| | | <el-select v-model="planForm.period" |
| | | placeholder="éæ©æ¶é´å¨æ" |
| | | style="width: 100%"> |
| | | <el-option label="å¨è®¡å" |
| | | value="week" /> |
| | | <el-option label="æè®¡å" |
| | | value="month" /> |
| | | <el-option label="年计å" |
| | | value="year" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="å¼å§æ¶é´" prop="startDate"> |
| | | <el-date-picker |
| | | v-model="planForm.startDate" |
| | | <el-form-item label="å¼å§æ¶é´" |
| | | prop="startDate"> |
| | | <el-date-picker v-model="planForm.startDate" |
| | | type="date" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | placeholder="éæ©å¼å§æ¶é´" |
| | | style="width: 100%" |
| | | /> |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | <el-form-item label="ç»ææ¶é´" prop="endDate"> |
| | | <el-date-picker |
| | | v-model="planForm.endDate" |
| | | <el-form-item label="ç»ææ¶é´" |
| | | prop="endDate"> |
| | | <el-date-picker v-model="planForm.endDate" |
| | | type="date" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | placeholder="éæ©ç»ææ¶é´" |
| | | style="width: 100%" |
| | | /> |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | <el-form-item label="è´è´£äºº" prop="assignee"> |
| | | <el-input v-model="planForm.assignee" placeholder="请è¾å
¥è´è´£äºº" /> |
| | | <el-form-item label="è´è´£äºº" |
| | | prop="assignee"> |
| | | <el-input v-model="planForm.assignee" |
| | | placeholder="请è¾å
¥è´è´£äºº" /> |
| | | </el-form-item> |
| | | <el-form-item label="ä¼å
级" prop="priority"> |
| | | <el-select v-model="planForm.priority" placeholder="éæ©ä¼å
级" style="width: 100%"> |
| | | <el-option label="é«" value="high" /> |
| | | <el-option label="ä¸" value="medium" /> |
| | | <el-option label="ä½" value="low" /> |
| | | <el-form-item label="ä¼å
级" |
| | | prop="priority"> |
| | | <el-select v-model="planForm.priority" |
| | | placeholder="éæ©ä¼å
级" |
| | | style="width: 100%"> |
| | | <el-option label="é«" |
| | | value="high" /> |
| | | <el-option label="ä¸" |
| | | value="medium" /> |
| | | <el-option label="ä½" |
| | | value="low" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <!-- <el-form-item label="æ ç¾"> |
| | | <el-input v-model="planForm.tags" placeholder="请è¾å
¥æ ç¾ï¼ç¨éå·åé" /> |
| | | </el-form-item> --> |
| | | <el-form-item label="æ ç¾" prop="tags"> |
| | | <el-form-item label="æ ç¾" |
| | | prop="tags"> |
| | | <!-- <el-checkbox-group v-model="planForm.tags"> |
| | | <el-checkbox label="all"></el-checkbox> |
| | | <el-checkbox label="manager">管çå±</el-checkbox> |
| | |
| | | <el-checkbox label="finance">è´¢å¡é¨é¨</el-checkbox> |
| | | <el-checkbox label="tech">ææ¯é¨é¨</el-checkbox> |
| | | </el-checkbox-group> --> |
| | | <el-select |
| | | v-model="planForm.tags" |
| | | <el-select v-model="planForm.tags" |
| | | multiple |
| | | placeholder="è¯·éæ©æ ç¾" |
| | | style="width: 100%" |
| | | > |
| | | <el-option |
| | | v-for="dept in departments" |
| | | style="width: 100%"> |
| | | <el-option v-for="dept in departments" |
| | | :key="dept" |
| | | :label="dept" |
| | | :value="dept" |
| | | /> |
| | | :value="dept" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="ç¶æ" prop="status"> |
| | | <el-select v-model="planForm.status" placeholder="éæ©ç¶æ" style="width: 100%"> |
| | | <el-option label="æªå¼å§" value="not_started" /> |
| | | <el-option label="è¿è¡ä¸" value="in_progress" /> |
| | | <el-option label="已宿" value="completed" /> |
| | | <el-option label="å·²æå" value="paused" /> |
| | | <el-form-item label="ç¶æ" |
| | | prop="status"> |
| | | <el-select v-model="planForm.status" |
| | | placeholder="éæ©ç¶æ" |
| | | style="width: 100%"> |
| | | <el-option label="æªå¼å§" |
| | | value="not_started" /> |
| | | <el-option label="è¿è¡ä¸" |
| | | value="in_progress" /> |
| | | <el-option label="已宿" |
| | | value="completed" /> |
| | | <el-option label="å·²æå" |
| | | value="paused" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="è¿åº¦" prop="progress"> |
| | | <el-input-number |
| | | v-model="planForm.progress" |
| | | <el-form-item label="è¿åº¦" |
| | | prop="progress"> |
| | | <el-input-number v-model="planForm.progress" |
| | | min="0" |
| | | max="100" |
| | | step="1" |
| | | placeholder="请è¾å
¥è¿åº¦" |
| | | style="width: 100%" |
| | | /> |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="handleSavePlan">ä¿å</el-button> |
| | | <el-button @click="planDialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="handleSavePlan">ä¿å</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | <!-- 计å详æ
å¯¹è¯æ¡ --> |
| | | <el-dialog v-model="showPlanDetailDialog" title="计å详æ
" width="700px"> |
| | | <div v-if="currentPlanDetail" class="mb10"> |
| | | <el-descriptions :column="2" border> |
| | | <el-dialog v-model="showPlanDetailDialog" |
| | | title="计å详æ
" |
| | | width="700px"> |
| | | <div v-if="currentPlanDetail" |
| | | class="mb10"> |
| | | <el-descriptions :column="2" |
| | | border> |
| | | <el-descriptions-item label="è®¡åæ é¢">{{ currentPlanDetail.title }}</el-descriptions-item> |
| | | <el-descriptions-item label="计åæè¿°">{{ currentPlanDetail.description }}</el-descriptions-item> |
| | | <el-descriptions-item label="计å级å«">{{ getCurrentLevelText(currentPlanDetail.level) }}</el-descriptions-item> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, computed, onMounted } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { ref, reactive, computed, onMounted } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | const { proxy } = getCurrentInstance(); |
| | | import { |
| | | User, |
| | |
| | | Calendar, |
| | | Clock, |
| | | Flag, |
| | | ArrowDown |
| | | } from '@element-plus/icons-vue' |
| | | import { listDutyPlan, addDutyPlan, updateDutyPlan, delDutyPlan,NumDutyPlan,exportDutyPlan } from '@/api/collaborativeApproval/planTemplate.js' |
| | | ArrowDown, |
| | | } from "@element-plus/icons-vue"; |
| | | import { |
| | | listDutyPlan, |
| | | addDutyPlan, |
| | | updateDutyPlan, |
| | | delDutyPlan, |
| | | NumDutyPlan, |
| | | exportDutyPlan, |
| | | } from "@/api/collaborativeApproval/planTemplate.js"; |
| | | |
| | | // ååºå¼æ°æ® |
| | | const operationType = ref('add') |
| | | const currentLevel = ref('personal') |
| | | const currentPeriod = ref('week') |
| | | const currentDate = ref(new Date()) |
| | | const planDialogVisible = ref(false) |
| | | const dialogTitle = ref('æ°å¢è®¡å') |
| | | const planFormRef = ref() |
| | | const showPlanDetailDialog = ref(false) |
| | | const currentPlanDetail = ref(null) |
| | | const operationType = ref("add"); |
| | | const currentLevel = ref("personal"); |
| | | const currentPeriod = ref("week"); |
| | | const currentDate = ref(new Date()); |
| | | const planDialogVisible = ref(false); |
| | | const dialogTitle = ref("æ°å¢è®¡å"); |
| | | const planFormRef = ref(); |
| | | const showPlanDetailDialog = ref(false); |
| | | const currentPlanDetail = ref(null); |
| | | |
| | | // è¡¨åæ°æ® |
| | | const planForm = reactive({ |
| | | id: '', |
| | | title: '', |
| | | description: '', |
| | | level: 'personal', |
| | | period: 'week', |
| | | startDate: '', |
| | | endDate: '', |
| | | assignee: '', |
| | | priority: 'medium', |
| | | id: "", |
| | | title: "", |
| | | description: "", |
| | | level: "personal", |
| | | period: "week", |
| | | startDate: "", |
| | | endDate: "", |
| | | assignee: "", |
| | | priority: "medium", |
| | | tags: [], |
| | | status: '', |
| | | progress: 0 |
| | | }) |
| | | status: "", |
| | | progress: 0, |
| | | }); |
| | | |
| | | // 表åéªè¯è§å |
| | | const planRules = { |
| | | title: [{ required: true, message: '请è¾å
¥è®¡åæ é¢', trigger: 'blur' }], |
| | | description: [{ required: true, message: '请è¾å
¥è®¡åæè¿°', trigger: 'blur' }], |
| | | level: [{ required: true, message: 'è¯·éæ©è®¡å级å«', trigger: 'change' }], |
| | | period: [{ required: true, message: 'è¯·éæ©æ¶é´å¨æ', trigger: 'change' }], |
| | | startDate: [{ required: true, message: 'è¯·éæ©å¼å§æ¶é´', trigger: 'change' }], |
| | | endDate: [{ required: true, message: 'è¯·éæ©ç»ææ¶é´', trigger: 'change' }], |
| | | assignee: [{ required: true, message: '请è¾å
¥è´è´£äºº', trigger: 'blur' }], |
| | | priority: [{ required: true, message: 'è¯·éæ©ä¼å
级', trigger: 'change' }] |
| | | } |
| | | const departments = ["产å", "åæ", "è°ç ",'ææ¯', 'æ¶æ', '设计','å¸åº', 'æ¨å¹¿', 'è¥é']; |
| | | title: [{ required: true, message: "请è¾å
¥è®¡åæ é¢", trigger: "blur" }], |
| | | description: [{ required: true, message: "请è¾å
¥è®¡åæè¿°", trigger: "blur" }], |
| | | level: [{ required: true, message: "è¯·éæ©è®¡å级å«", trigger: "change" }], |
| | | period: [{ required: true, message: "è¯·éæ©æ¶é´å¨æ", trigger: "change" }], |
| | | startDate: [{ required: true, message: "è¯·éæ©å¼å§æ¶é´", trigger: "change" }], |
| | | endDate: [{ required: true, message: "è¯·éæ©ç»ææ¶é´", trigger: "change" }], |
| | | assignee: [{ required: true, message: "请è¾å
¥è´è´£äºº", trigger: "blur" }], |
| | | priority: [{ required: true, message: "è¯·éæ©ä¼å
级", trigger: "change" }], |
| | | }; |
| | | const departments = [ |
| | | "产å", |
| | | "åæ", |
| | | "è°ç ", |
| | | "ææ¯", |
| | | "æ¶æ", |
| | | "设计", |
| | | "å¸åº", |
| | | "æ¨å¹¿", |
| | | "è¥é", |
| | | ]; |
| | | // æ¦è§æ°æ® |
| | | const overviewData = reactive({ |
| | | personal: { total: 0, completion: 0 }, |
| | | group: { total: 0, completion: 0 }, |
| | | department: { total: 0, completion: 0 }, |
| | | company: { total: 0, completion: 0 } |
| | | }) |
| | | company: { total: 0, completion: 0 }, |
| | | }); |
| | | |
| | | // 计ååè¡¨æ°æ® |
| | | const planList = ref([]) |
| | | const planList = ref([]); |
| | | |
| | | // 计ç®å±æ§ |
| | | const datePickerType = computed(() => { |
| | | switch (currentPeriod.value) { |
| | | case 'week': |
| | | return 'week' |
| | | case 'month': |
| | | return 'month' |
| | | case 'year': |
| | | return 'year' |
| | | case "week": |
| | | return "week"; |
| | | case "month": |
| | | return "month"; |
| | | case "year": |
| | | return "year"; |
| | | default: |
| | | return 'date' |
| | | return "date"; |
| | | } |
| | | }) |
| | | }); |
| | | |
| | | // æ¹æ³ |
| | | const handleLevelChange = (value) => { |
| | | console.log('计å级å«åæ´:', value) |
| | | getPlanList() |
| | | const handleLevelChange = value => { |
| | | console.log("计å级å«åæ´:", value); |
| | | getPlanList(); |
| | | // è¿éå¯ä»¥æ ¹æ®çº§å«çéæ°æ® |
| | | } |
| | | }; |
| | | |
| | | const handlePeriodChange = (value) => { |
| | | console.log('æ¶é´å¨æåæ´:', value) |
| | | getPlanList() |
| | | const handlePeriodChange = value => { |
| | | console.log("æ¶é´å¨æåæ´:", value); |
| | | getPlanList(); |
| | | // è¿éå¯ä»¥æ ¹æ®å¨æçéæ°æ® |
| | | } |
| | | }; |
| | | |
| | | const handleDateChange = (value) => { |
| | | console.log('æ¥æåæ´:', value) |
| | | getPlanList() |
| | | const handleDateChange = value => { |
| | | console.log("æ¥æåæ´:", value); |
| | | getPlanList(); |
| | | // è¿éå¯ä»¥æ ¹æ®æ¥æçéæ°æ® |
| | | } |
| | | }; |
| | | |
| | | const handleAddPlan = () => { |
| | | operationType.value = 'add' |
| | | dialogTitle.value = 'æ°å¢è®¡å' |
| | | planDialogVisible.value = true |
| | | operationType.value = "add"; |
| | | dialogTitle.value = "æ°å¢è®¡å"; |
| | | planDialogVisible.value = true; |
| | | // é置表å |
| | | Object.keys(planForm).forEach(key => { |
| | | planForm[key] = '' |
| | | }) |
| | | planForm.level = 'personal' |
| | | planForm.period = 'week' |
| | | planForm.priority = 'medium' |
| | | planForm.status = 'not_started' |
| | | planForm.progress = 0 |
| | | } |
| | | planForm[key] = ""; |
| | | }); |
| | | planForm.level = "personal"; |
| | | planForm.period = "week"; |
| | | planForm.priority = "medium"; |
| | | planForm.status = "not_started"; |
| | | planForm.progress = 0; |
| | | }; |
| | | |
| | | const handleEditPlan = (plan) => { |
| | | operationType.value = 'edit' |
| | | dialogTitle.value = 'ç¼è¾è®¡å' |
| | | planDialogVisible.value = true |
| | | Object.assign(planForm, plan) |
| | | const handleEditPlan = plan => { |
| | | operationType.value = "edit"; |
| | | dialogTitle.value = "ç¼è¾è®¡å"; |
| | | planDialogVisible.value = true; |
| | | Object.assign(planForm, plan); |
| | | // // å¡«å
è¡¨åæ°æ® |
| | | // Object.keys(planForm).forEach(key => { |
| | | // if (key === 'tags') { |
| | |
| | | // planForm[key] = plan[key] |
| | | // } |
| | | // }) |
| | | } |
| | | }; |
| | | |
| | | const handleViewDetail = (plan) => { |
| | | currentPlanDetail.value = plan |
| | | showPlanDetailDialog.value = true |
| | | const handleViewDetail = plan => { |
| | | currentPlanDetail.value = plan; |
| | | showPlanDetailDialog.value = true; |
| | | // ElMessage.info(`æ¥ç计å详æ
: ${plan.title}`) |
| | | } |
| | | }; |
| | | |
| | | const handleMoreAction = async(plan,command) => { |
| | | let ids = []; |
| | | ids.push(plan.id); |
| | | console.log("ids",ids) |
| | | console.log("ids", ids); |
| | | switch (command) { |
| | | case 'share': |
| | | ElMessage.success('计åå·²å
񄧮') |
| | | break |
| | | case 'copy': |
| | | case "share": |
| | | ElMessage.success("计åå·²å
񄧮"); |
| | | break; |
| | | case "copy": |
| | | const knowledgeText = ` |
| | | è®¡åæ é¢ï¼${plan.title} |
| | | 计åæè¿°ï¼${plan.description} |
| | |
| | | ç»ææ¶é´ï¼${plan.endDate} |
| | | è´è´£äººï¼${plan.assignee} |
| | | ä¼å
级ï¼${getPriorityText(plan.priority)} |
| | | æ ç¾ï¼${plan.tags.join(', ')} |
| | | æ ç¾ï¼${plan.tags.join(", ")} |
| | | ç¶æï¼${getStatusText(plan.status)} |
| | | è¿åº¦ï¼${plan.progress}% |
| | | `.trim(); |
| | | |
| | | // å¤å¶å°åªè´´æ¿ |
| | | navigator.clipboard.writeText(knowledgeText).then(() => { |
| | | navigator.clipboard |
| | | .writeText(knowledgeText) |
| | | .then(() => { |
| | | ElMessage.success("ç¥è¯å
容已å¤å¶å°åªè´´æ¿"); |
| | | }).catch(() => { |
| | | }) |
| | | .catch(() => { |
| | | ElMessage.error("å¤å¶å¤±è´¥ï¼è¯·æå¨å¤å¶"); |
| | | }); |
| | | // ElMessage.success('计åå·²å¤å¶') |
| | | break |
| | | case 'delete': |
| | | ElMessageBox.confirm('ç¡®å®è¦å é¤è¿ä¸ªè®¡ååï¼', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | break; |
| | | case "delete": |
| | | ElMessageBox.confirm("ç¡®å®è¦å é¤è¿ä¸ªè®¡ååï¼", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).then(() => { |
| | | |
| | | delDutyPlan(ids).then(res => { |
| | | if (res.code === 200) { |
| | | ElMessage.success('计åå·²å é¤') |
| | | ElMessage.success("计åå·²å é¤"); |
| | | ids.value = []; |
| | | getPlanList() |
| | | getPlanList(); |
| | | } |
| | | }) |
| | | }) |
| | | break |
| | | }); |
| | | }); |
| | | break; |
| | | } |
| | | } |
| | | }; |
| | | // |
| | | const handleSavePlan = async () => { |
| | | try { |
| | | await planFormRef.value.validate() |
| | | if (operationType.value === 'add') { |
| | | await planFormRef.value.validate(); |
| | | if (operationType.value === "add") { |
| | | addDutyPlan(planForm).then(res => { |
| | | if (res.code === 200) { |
| | | ElMessage.success('计åä¿åæå') |
| | | planDialogVisible.value = false |
| | | ElMessage.success("计åä¿åæå"); |
| | | planDialogVisible.value = false; |
| | | } |
| | | getPlanList() |
| | | }) |
| | | getPlanList(); |
| | | }); |
| | | } else { |
| | | |
| | | updateDutyPlan(planForm).then(res => { |
| | | if (res.code === 200) { |
| | | ElMessage.success('计åä¿åæå') |
| | | planDialogVisible.value = false |
| | | ElMessage.success("计åä¿åæå"); |
| | | planDialogVisible.value = false; |
| | | } |
| | | getPlanList() |
| | | }) |
| | | getPlanList(); |
| | | }); |
| | | } |
| | | } catch (error) { |
| | | console.log('表åéªè¯å¤±è´¥:', error) |
| | | console.log("表åéªè¯å¤±è´¥:", error); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | const handleDialogClose = () => { |
| | | planFormRef.value?.resetFields() |
| | | } |
| | | planFormRef.value?.resetFields(); |
| | | }; |
| | | |
| | | const handleRefresh = () => { |
| | | getPlanList() |
| | | getPlanList(); |
| | | // ElMessage.success('æ°æ®å·²å·æ°') |
| | | } |
| | | }; |
| | | |
| | | const handleFilter = () => { |
| | | ElMessage.info('æå¼çé颿¿') |
| | | } |
| | | ElMessage.info("æå¼çé颿¿"); |
| | | }; |
| | | |
| | | const handleExport = () => { |
| | | ElMessageBox.confirm("æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | |
| | | }); |
| | | }; |
| | | const handleShare = () => { |
| | | ElMessage.success('计åå·²å
񄧮') |
| | | } |
| | | ElMessage.success("计åå·²å
񄧮"); |
| | | }; |
| | | |
| | | const getCurrentLevelText = () => { |
| | | const levelMap = { |
| | | personal: '个人计å', |
| | | group: 'å°ç»è®¡å', |
| | | department: 'é¨é¨è®¡å', |
| | | company: 'å
¬å¸è®¡å' |
| | | } |
| | | return levelMap[currentLevel.value] || '个人计å' |
| | | } |
| | | personal: "个人计å", |
| | | group: "å°ç»è®¡å", |
| | | department: "é¨é¨è®¡å", |
| | | company: "å
¬å¸è®¡å", |
| | | }; |
| | | return levelMap[currentLevel.value] || "个人计å"; |
| | | }; |
| | | |
| | | const getCurrentPeriodText = () => { |
| | | const periodMap = { |
| | | week: 'å¨è®¡å', |
| | | month: 'æè®¡å', |
| | | year: '年计å' |
| | | } |
| | | return periodMap[currentPeriod.value] || 'å¨è®¡å' |
| | | } |
| | | week: "å¨è®¡å", |
| | | month: "æè®¡å", |
| | | year: "年计å", |
| | | }; |
| | | return periodMap[currentPeriod.value] || "å¨è®¡å"; |
| | | }; |
| | | |
| | | const getPriorityType = (priority) => { |
| | | const getPriorityType = priority => { |
| | | const typeMap = { |
| | | high: 'danger', |
| | | medium: 'warning', |
| | | low: 'info' |
| | | } |
| | | return typeMap[priority] || 'info' |
| | | } |
| | | high: "danger", |
| | | medium: "warning", |
| | | low: "info", |
| | | }; |
| | | return typeMap[priority] || "info"; |
| | | }; |
| | | |
| | | const getPriorityText = (priority) => { |
| | | const getPriorityText = priority => { |
| | | const textMap = { |
| | | high: 'é«', |
| | | medium: 'ä¸', |
| | | low: 'ä½' |
| | | } |
| | | return textMap[priority] || 'ä¸' |
| | | } |
| | | high: "é«", |
| | | medium: "ä¸", |
| | | low: "ä½", |
| | | }; |
| | | return textMap[priority] || "ä¸"; |
| | | }; |
| | | |
| | | const getStatusText = (status) => { |
| | | const getStatusText = status => { |
| | | const statusMap = { |
| | | not_started: 'æªå¼å§', |
| | | in_progress: 'è¿è¡ä¸', |
| | | completed: '已宿', |
| | | paused: 'å·²æå' |
| | | } |
| | | return statusMap[status] || 'æªç¥' |
| | | } |
| | | not_started: "æªå¼å§", |
| | | in_progress: "è¿è¡ä¸", |
| | | completed: "已宿", |
| | | paused: "å·²æå", |
| | | }; |
| | | return statusMap[status] || "æªç¥"; |
| | | }; |
| | | |
| | | const getProgressColor = (progress) => { |
| | | if (progress >= 80) return '#67C23A' |
| | | if (progress >= 50) return '#E6A23C' |
| | | return '#F56C6C' |
| | | } |
| | | const getProgressColor = progress => { |
| | | if (progress >= 80) return "#67C23A"; |
| | | if (progress >= 50) return "#E6A23C"; |
| | | return "#F56C6C"; |
| | | }; |
| | | //è·åæ°æ®å表 |
| | | const getPlanList = async () => { |
| | | const params = { |
| | | level: currentLevel.value, |
| | | period: currentPeriod.value, |
| | | queryDate:currentDate.value |
| | | } |
| | | listDutyPlan(params).then(res => { |
| | | queryDate: currentDate.value, |
| | | }; |
| | | listDutyPlan(params) |
| | | .then(res => { |
| | | if (res.code === 200) { |
| | | planList.value = res.data.records |
| | | planList.value = res.data.records; |
| | | } |
| | | }).catch(err => { |
| | | console.log(err) |
| | | }) |
| | | } |
| | | .catch(err => { |
| | | console.log(err); |
| | | }); |
| | | }; |
| | | //è·åæ°æ® |
| | | const getPlanNum = async () => { |
| | | NumDutyPlan().then(res => { |
| | | NumDutyPlan() |
| | | .then(res => { |
| | | if (res.code === 200) { |
| | | // console.log(res.data) |
| | | //è®²ç»æéé¢çæ°æ®æ ¹æ®level èµå¼ç»overviewData |
| | | res.data.forEach(item => { |
| | | overviewData[item.level].total = item.num |
| | | overviewData[item.level].completion = item.completion |
| | | }) |
| | | |
| | | overviewData[item.level].total = item.num; |
| | | overviewData[item.level].completion = item.completion; |
| | | }); |
| | | } |
| | | }).catch(err => { |
| | | console.log(err) |
| | | }) |
| | | } |
| | | .catch(err => { |
| | | console.log(err); |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getPlanList() |
| | | getPlanNum() |
| | | console.log('å¤çº§è®¡å模æ¿é¡µé¢å·²å è½½') |
| | | }) |
| | | getPlanList(); |
| | | getPlanNum(); |
| | | console.log("å¤çº§è®¡å模æ¿é¡µé¢å·²å è½½"); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title">ç¨åºåï¼</span> |
| | | <el-input |
| | | v-model="searchForm.programName" |
| | | <el-input v-model="searchForm.programName" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥ç¨åºåæç´¢" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | /> |
| | | :prefix-icon="Search" /> |
| | | <span class="search_title ml10">æ§è¡ç¶æï¼</span> |
| | | <el-select v-model="searchForm.status" clearable @change="handleQuery" style="width: 240px"> |
| | | <el-option label="è¿è¡ä¸" :value="'running'" /> |
| | | <el-option label="已忢" :value="'stopped'" /> |
| | | <el-option label="å¼å¸¸" :value="'error'" /> |
| | | <el-select v-model="searchForm.status" |
| | | clearable |
| | | @change="handleQuery" |
| | | style="width: 240px"> |
| | | <el-option label="è¿è¡ä¸" |
| | | :value="'running'" /> |
| | | <el-option label="已忢" |
| | | :value="'stopped'" /> |
| | | <el-option label="å¼å¸¸" |
| | | :value="'error'" /> |
| | | </el-select> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px"> |
| | | <el-button type="primary" |
| | | @click="handleQuery" |
| | | style="margin-left: 10px"> |
| | | æç´¢ |
| | | </el-button> |
| | | </div> |
| | | <div> |
| | | <el-button @click="handleExport" style="margin-right: 10px">导åº</el-button> |
| | | <el-button type="primary" @click="openForm('add')">æ°å¢</el-button> |
| | | <el-button type="danger" plain @click="handleDelete">å é¤</el-button> |
| | | <el-button @click="handleExport" |
| | | style="margin-right: 10px">导åº</el-button> |
| | | <el-button type="primary" |
| | | @click="openForm('add')">æ°å¢</el-button> |
| | | <el-button type="danger" |
| | | plain |
| | | @click="handleDelete">å é¤</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | | <PIMTable |
| | | rowKey="id" |
| | | <PIMTable rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | :total="page.total" |
| | | ></PIMTable> |
| | | :total="page.total"></PIMTable> |
| | | </div> |
| | | |
| | | <!-- RPA表åå¼¹çª --> |
| | | <el-dialog |
| | | v-model="dialogVisible" |
| | | <el-dialog v-model="dialogVisible" |
| | | :title="dialogTitle" |
| | | width="500px" |
| | | :close-on-click-modal="false" |
| | | > |
| | | <el-form |
| | | ref="formRef" |
| | | :close-on-click-modal="false"> |
| | | <el-form ref="formRef" |
| | | :model="form" |
| | | :rules="rules" |
| | | label-width="100px" |
| | | > |
| | | <el-form-item label="ç¨åºå" prop="programName"> |
| | | <el-input |
| | | v-model="form.programName" |
| | | label-width="100px"> |
| | | <el-form-item label="ç¨åºå" |
| | | prop="programName"> |
| | | <el-input v-model="form.programName" |
| | | placeholder="请è¾å
¥ç¨åºå" |
| | | clearable |
| | | /> |
| | | clearable /> |
| | | </el-form-item> |
| | | <el-form-item label="æ§è¡ç¶æ" prop="status"> |
| | | <el-select v-model="form.status" placeholder="è¯·éæ©æ§è¡ç¶æ" style="width: 100%"> |
| | | <el-option label="è¿è¡ä¸" value="running" /> |
| | | <el-option label="已忢" value="stopped" /> |
| | | <el-option label="å¼å¸¸" value="error" /> |
| | | <el-form-item label="æ§è¡ç¶æ" |
| | | prop="status"> |
| | | <el-select v-model="form.status" |
| | | placeholder="è¯·éæ©æ§è¡ç¶æ" |
| | | style="width: 100%"> |
| | | <el-option label="è¿è¡ä¸" |
| | | value="running" /> |
| | | <el-option label="已忢" |
| | | value="stopped" /> |
| | | <el-option label="å¼å¸¸" |
| | | value="error" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="æè¿°" prop="description"> |
| | | <el-input |
| | | v-model="form.description" |
| | | <el-form-item label="æè¿°" |
| | | prop="description"> |
| | | <el-input v-model="form.description" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥RPAç¨åºæè¿°" |
| | | clearable |
| | | /> |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="submitForm">ç¡®å®</el-button> |
| | | <el-button @click="dialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="submitForm">ç¡®å®</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | |
| | | import { onMounted, ref, reactive, toRefs, getCurrentInstance } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import PIMTable from "@/components/PIMTable/PIMTable.vue"; |
| | | import {listRpa, addRpa, updateRpa, delRpa, delRpaBatch} from "@/api/collaborativeApproval/rpaManagement.js"; |
| | | import { |
| | | listRpa, |
| | | addRpa, |
| | | updateRpa, |
| | | delRpa, |
| | | delRpaBatch, |
| | | } from "@/api/collaborativeApproval/rpaManagement.js"; |
| | | // ååºå¼æ°æ® |
| | | const data = reactive({ |
| | | searchForm: { |
| | |
| | | form: { |
| | | programName: "", |
| | | status: "", |
| | | description: "" |
| | | description: "", |
| | | }, |
| | | dialogVisible: false, |
| | | dialogTitle: "", |
| | |
| | | tableData: [], |
| | | }); |
| | | |
| | | const { searchForm, form, dialogVisible, dialogTitle, dialogType, selectedIds, tableLoading, page, tableData } = toRefs(data); |
| | | const { |
| | | searchForm, |
| | | form, |
| | | dialogVisible, |
| | | dialogTitle, |
| | | dialogType, |
| | | selectedIds, |
| | | tableLoading, |
| | | page, |
| | | tableData, |
| | | } = toRefs(data); |
| | | |
| | | // 表åå¼ç¨ |
| | | const formRef = ref(); |
| | |
| | | |
| | | // 表åéªè¯è§å |
| | | const rules = { |
| | | programName: [ |
| | | { required: true, message: "请è¾å
¥ç¨åºå", trigger: "blur" } |
| | | ], |
| | | status: [ |
| | | { required: true, message: "è¯·éæ©æ§è¡ç¶æ", trigger: "change" } |
| | | ] |
| | | programName: [{ required: true, message: "请è¾å
¥ç¨åºå", trigger: "blur" }], |
| | | status: [{ required: true, message: "è¯·éæ©æ§è¡ç¶æ", trigger: "change" }], |
| | | }; |
| | | |
| | | // è¡¨æ ¼åé
ç½® |
| | |
| | | prop: "status", |
| | | dataType: "tag", |
| | | // width: 120, |
| | | formatData: (params) => { |
| | | formatData: params => { |
| | | const statusMap = { |
| | | running: "è¿è¡ä¸", |
| | | stopped: "已忢", |
| | | error: "å¼å¸¸" |
| | | error: "å¼å¸¸", |
| | | }; |
| | | return statusMap[params] || params; |
| | | }, |
| | | formatType: (params) => { |
| | | formatType: params => { |
| | | const typeMap = { |
| | | running: "success", |
| | | stopped: "info", |
| | | error: "danger" |
| | | error: "danger", |
| | | }; |
| | | return typeMap[params] || "info"; |
| | | } |
| | | }, |
| | | }, |
| | | { |
| | | label: "æè¿°", |
| | |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | clickFun: row => { |
| | | openForm("edit", row); |
| | | } |
| | | }, |
| | | }, |
| | | // { |
| | | // name: "å¼å§", |
| | |
| | | // }, |
| | | // disabled: (row) => row.status === 'stopped' |
| | | // } |
| | | ] |
| | | } |
| | | ], |
| | | }, |
| | | ]); |
| | | |
| | | |
| | | // çå½å¨æ |
| | | onMounted(() => { |
| | |
| | | listRpa({...page.value, ...searchForm.value}) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records |
| | | tableData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | | }) |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | // å页å¤ç |
| | | const pagination = (obj) => { |
| | | const pagination = obj => { |
| | | page.value.current = obj.page; |
| | | page.value.size = obj.limit; |
| | | handleQuery(); |
| | | }; |
| | | |
| | | // éæ©ååå¤ç |
| | | const handleSelectionChange = (selection) => { |
| | | const handleSelectionChange = selection => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | |
| | |
| | | |
| | | if (dialogType.value === "add") { |
| | | // æ·»å æ°RPA |
| | | addRpa({...form.value}).then(res => { |
| | | addRpa({ ...form.value }) |
| | | .then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("æ·»å æå"); |
| | | form.value = { |
| | | (form.value = { |
| | | programName: "", |
| | | status: "", |
| | | description: "" |
| | | }, |
| | | dialogVisible.value = false; |
| | | description: "", |
| | | }), |
| | | (dialogVisible.value = false); |
| | | getList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | } else { |
| | | // ç¼è¾RPA |
| | | updateRpa({...form.value}).then(res => { |
| | | updateRpa({ ...form.value }) |
| | | .then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("æ´æ°æå"); |
| | | dialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | } |
| | | } catch (error) { |
| | | console.error("表åéªè¯å¤±è´¥:", error); |
| | |
| | | }; |
| | | |
| | | // å¼å§RPA |
| | | const handleStart = (row) => { |
| | | const handleStart = row => { |
| | | ElMessageBox.confirm(`ç¡®å®è¦å¯å¨RPAç¨åº"${row.programName}"åï¼`, "æç¤º", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).then(() => { |
| | | }) |
| | | .then(() => { |
| | | row.status = "running"; |
| | | ElMessage.success("RPAå¯å¨æå"); |
| | | getList(); |
| | | }).catch(() => { |
| | | }) |
| | | .catch(() => { |
| | | // ç¨æ·åæ¶ |
| | | }); |
| | | }; |
| | | |
| | | // 忢RPA |
| | | const handleStop = (row) => { |
| | | const handleStop = row => { |
| | | ElMessageBox.confirm(`ç¡®å®è¦åæ¢RPAç¨åº"${row.programName}"åï¼`, "æç¤º", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).then(() => { |
| | | }) |
| | | .then(() => { |
| | | row.status = "stopped"; |
| | | ElMessage.success("RPA忢æå"); |
| | | getList(); |
| | | }).catch(() => { |
| | | }) |
| | | .catch(() => { |
| | | // ç¨æ·åæ¶ |
| | | }); |
| | | }; |
| | |
| | | const handleDelete = () => { |
| | | let ids = []; |
| | | if (selectedRows.value.length > 0) { |
| | | ids = selectedRows.value.map((item) => item.id); |
| | | ids = selectedRows.value.map(item => item.id); |
| | | } else { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | delRpa(ids).then((res) => { |
| | | delRpa(ids) |
| | | .then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("å 餿å"); |
| | | getList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | |
| | | }; |
| | | |
| | | // 导åºåè½ |
| | | const { proxy } = getCurrentInstance() |
| | | const { proxy } = getCurrentInstance(); |
| | | const handleExport = () => { |
| | | proxy.download('/rpaProcessAutomation/export', { ...searchForm.value }, 'RPA管ç.xlsx') |
| | | } |
| | | proxy.download( |
| | | "/rpaProcessAutomation/export", |
| | | { ...searchForm.value }, |
| | | "RPA管ç.xlsx" |
| | | ); |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped></style> |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | |
| | | <!-- è§ç« å¶åº¦ç®¡ç--> |
| | | <el-card class="box-card"> |
| | | <template #header> |
| | |
| | | </div> |
| | | </template> |
| | | <div class="tab-content"> |
| | | <el-row :gutter="20" class="mb-20"> |
| | | <el-row :gutter="20" |
| | | class="mb-20"> |
| | | <span class="ml-10">å¶åº¦æ é¢ï¼</span> |
| | | <el-col :span="6"> |
| | | <el-input v-model="regulationSearchForm.title" placeholder="请è¾å
¥å¶åº¦æ é¢" clearable /> |
| | | <el-input v-model="regulationSearchForm.title" |
| | | placeholder="请è¾å
¥å¶åº¦æ é¢" |
| | | clearable /> |
| | | </el-col> |
| | | <span class="search_title">å¶åº¦åç±»ï¼</span> |
| | | <el-col :span="4"> |
| | | <el-select v-model="regulationSearchForm.category" placeholder="å¶åº¦åç±»" clearable> |
| | | <el-option label="人äºå¶åº¦" value="hr" /> |
| | | <el-option label="è´¢å¡å¶åº¦" value="finance" /> |
| | | <el-option label="å®å
¨å¶åº¦" value="safety" /> |
| | | <el-option label="ææ¯å¶åº¦" value="tech" /> |
| | | <el-select v-model="regulationSearchForm.category" |
| | | placeholder="å¶åº¦åç±»" |
| | | clearable> |
| | | <el-option label="人äºå¶åº¦" |
| | | value="hr" /> |
| | | <el-option label="è´¢å¡å¶åº¦" |
| | | value="finance" /> |
| | | <el-option label="å®å
¨å¶åº¦" |
| | | value="safety" /> |
| | | <el-option label="ææ¯å¶åº¦" |
| | | value="tech" /> |
| | | </el-select> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-button type="primary" @click="searchRegulations">æç´¢</el-button> |
| | | <el-button type="primary" |
| | | @click="searchRegulations">æç´¢</el-button> |
| | | <el-button @click="resetRegulationSearch">éç½®</el-button> |
| | | <el-button @click="handleExport">导åº</el-button> |
| | | <el-button type="success" @click="handleAdd"> |
| | | <el-button type="success" |
| | | @click="handleAdd"> |
| | | åå¸å¶åº¦ |
| | | </el-button> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-table :data="regulations" border v-loading="tableLoading" style="width: 100%"> |
| | | <el-table-column prop="regulationNum" label="å¶åº¦ç¼å·" width="120" /> |
| | | <el-table-column prop="title" label="å¶åº¦æ é¢" min-width="150" /> |
| | | <el-table-column prop="category" label="åç±»" width="120"> |
| | | <el-table :data="regulations" |
| | | border |
| | | v-loading="tableLoading" |
| | | style="width: 100%"> |
| | | <el-table-column prop="regulationNum" |
| | | label="å¶åº¦ç¼å·" |
| | | width="120" /> |
| | | <el-table-column prop="title" |
| | | label="å¶åº¦æ é¢" |
| | | min-width="150" /> |
| | | <el-table-column prop="category" |
| | | label="åç±»" |
| | | width="120"> |
| | | <template #default="scope"> |
| | | <el-tag>{{ getCategoryText(scope.row.category) }}</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="version" label="çæ¬" width="120" /> |
| | | <el-table-column prop="createUserName" label="åå¸äºº" width="120" /> |
| | | <el-table-column prop="createTime" label="å叿¶é´" width="180" /> |
| | | <el-table-column prop="status" label="ç¶æ" width="100"> |
| | | <el-table-column prop="version" |
| | | label="çæ¬" |
| | | width="120" /> |
| | | <el-table-column prop="createUserName" |
| | | label="åå¸äºº" |
| | | width="120" /> |
| | | <el-table-column prop="createTime" |
| | | label="å叿¶é´" |
| | | width="180" /> |
| | | <el-table-column prop="status" |
| | | label="ç¶æ" |
| | | width="100"> |
| | | <template #default="scope"> |
| | | <el-tag :type="scope.row.status === 'active' ? 'success' : 'info'"> |
| | | {{ scope.row.status === 'active' ? 'çæä¸' : 'å·²åºæ¢' }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="readCount" label="已读人æ°" width="100" /> |
| | | <el-table-column label="æä½" width="250" fixed="right"> |
| | | <el-table-column prop="readCount" |
| | | label="已读人æ°" |
| | | width="100" /> |
| | | <el-table-column label="æä½" |
| | | width="250" |
| | | fixed="right"> |
| | | <template #default="scope"> |
| | | <el-button link @click="viewRegulation(scope.row)">æ¥ç</el-button> |
| | | <el-button link type="primary" @click="handleEdit(scope.row)">ç¼è¾</el-button> |
| | | <el-button link type="danger" @click="repealEdit(scope.row)">åºå¼</el-button> |
| | | <el-button link type="success" @click="viewVersionHistory(scope.row)">çæ¬åå²</el-button> |
| | | <el-button link type="warning" @click="viewReadStatus(scope.row)">é
è¯»ç¶æ</el-button> |
| | | <el-button link |
| | | @click="viewRegulation(scope.row)">æ¥ç</el-button> |
| | | <el-button link |
| | | type="primary" |
| | | @click="handleEdit(scope.row)">ç¼è¾</el-button> |
| | | <el-button link |
| | | type="danger" |
| | | @click="repealEdit(scope.row)">åºå¼</el-button> |
| | | <el-button link |
| | | type="success" |
| | | @click="viewVersionHistory(scope.row)">çæ¬åå²</el-button> |
| | | <el-button link |
| | | type="warning" |
| | | @click="viewReadStatus(scope.row)">é
è¯»ç¶æ</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </el-card> |
| | | |
| | | <!-- ç¨å°ç³è¯·å¯¹è¯æ¡ --> |
| | | <!-- <el-dialog v-model="showSealApplyDialog" title="ç³è¯·ç¨å°" width="600px"> |
| | | <el-form :model="sealForm" :rules="sealRules" ref="sealFormRef" label-width="100px"> |
| | |
| | | </span> |
| | | </template> |
| | | </el-dialog> --> |
| | | |
| | | <!-- è§ç« å¶åº¦åå¸å¯¹è¯æ¡ --> |
| | | <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-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 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-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 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 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 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-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="tech">ææ¯é¨é¨</el-checkbox> |
| | | </el-checkbox-group> |
| | | </el-form-item> |
| | | <el-form-item label="æ¯å¦éè¦ç¡®è®¤" prop="requireConfirm"> |
| | | <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 type="primary" |
| | | @click="submitRegulation">åå¸å¶åº¦</el-button> |
| | | <el-button @click="showRegulationDialog = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="submitRegulation">åå¸å¶åº¦</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- ç¨å°è¯¦æ
å¯¹è¯æ¡ --> |
| | | <!-- <el-dialog v-model="showSealDetailDialog" title="ç¨å°ç³è¯·è¯¦æ
" width="700px"> |
| | | <div v-if="currentSealDetail" class="mb10"> |
| | |
| | | </el-descriptions> |
| | | </div> |
| | | </el-dialog> --> |
| | | |
| | | <!-- è§ç« å¶åº¦è¯¦æ
å¯¹è¯æ¡ --> |
| | | <el-dialog v-model="showRegulationDetailDialog" title="è§ç« å¶åº¦è¯¦æ
" width="800px"> |
| | | <el-dialog v-model="showRegulationDetailDialog" |
| | | title="è§ç« å¶åº¦è¯¦æ
" |
| | | width="800px"> |
| | | <div v-if="currentRegulationDetail"> |
| | | <el-descriptions :column="2" border> |
| | | <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> |
| | |
| | | <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 style="margin: 10px 0;" |
| | | v-if="tableData && tableData.length > 0"> |
| | | <el-button type="success" |
| | | @click="resetForm(currentRegulationDetail)">确认æ¥ç</el-button> |
| | | </div> |
| | | </div> |
| | | </el-dialog> |
| | | |
| | | <!-- çæ¬åå²å¯¹è¯æ¡ --> |
| | | <el-dialog v-model="showVersionHistoryDialog" title="çæ¬åå²" width="800px"> |
| | | <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="åæ´è¯´æ"> |
| | | <el-dialog v-model="showVersionHistoryDialog" |
| | | title="çæ¬åå²" |
| | | width="800px"> |
| | | <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-table-column> |
| | | </el-table> |
| | | </el-dialog> |
| | | |
| | | <!-- é
è¯»ç¶æå¯¹è¯æ¡ --> |
| | | <el-dialog v-model="showReadStatusDialog" title="é
è¯»ç¶æ" width="800px"> |
| | | <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"> |
| | | <el-dialog v-model="showReadStatusDialog" |
| | | title="é
è¯»ç¶æ" |
| | | width="800px"> |
| | | <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' ? '已确认' : 'æªç¡®è®¤' }} |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted, getCurrentInstance } from 'vue' |
| | | 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 } from '@/api/system/user.js' |
| | | import {staffJoinDel, staffJoinListPage} from "@/api/personnelManagement/onboarding.js"; |
| | | import useUserStore from '@/store/modules/user' |
| | | import { userLoginFacotryList } from "@/api/system/user.js" |
| | | import { ref, reactive, onMounted, getCurrentInstance } from "vue"; |
| | | 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 } from "@/api/system/user.js"; |
| | | import { |
| | | staffJoinDel, |
| | | staffJoinListPage, |
| | | } from "@/api/personnelManagement/onboarding.js"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { userLoginFacotryList } from "@/api/system/user.js"; |
| | | |
| | | // ååºå¼æ°æ® |
| | | const currentUser = ref(null) |
| | | const activeTab = ref('seal') |
| | | const operationType = ref('add') |
| | | const tableData = ref([]) |
| | | const currentUser = ref(null); |
| | | const activeTab = ref("seal"); |
| | | const operationType = ref("add"); |
| | | const tableData = ref([]); |
| | | // ç¨å°ç³è¯·ç¸å
³ |
| | | const userStore = useUserStore() |
| | | const showSealApplyDialog = ref(false) |
| | | const tableLoading = ref(false) |
| | | const showSealDetailDialog = ref(false) |
| | | const currentSealDetail = ref(null) |
| | | const sealFormRef = ref() |
| | | const userStore = useUserStore(); |
| | | const showSealApplyDialog = ref(false); |
| | | const tableLoading = ref(false); |
| | | const showSealDetailDialog = ref(false); |
| | | const currentSealDetail = ref(null); |
| | | const sealFormRef = ref(); |
| | | const sealForm = reactive({ |
| | | applicationNum: '', |
| | | title: '', |
| | | sealType: '', |
| | | reason: '', |
| | | urgency: 'normal', |
| | | status: 'pending' |
| | | }) |
| | | applicationNum: "", |
| | | title: "", |
| | | sealType: "", |
| | | reason: "", |
| | | urgency: "normal", |
| | | status: "pending", |
| | | }); |
| | | |
| | | const sealRules = { |
| | | applicationNum: [{ required: true, message: '请è¾å
¥ç³è¯·ç¼å·', trigger: 'blur' }], |
| | | title: [{ required: true, message: '请è¾å
¥ç³è¯·æ é¢', trigger: 'blur' }], |
| | | sealType: [{ required: true, message: 'è¯·éæ©ç¨å°ç±»å', trigger: 'change' }], |
| | | reason: [{ required: true, message: '请è¾å
¥ç³è¯·åå ', trigger: 'blur' }] |
| | | } |
| | | applicationNum: [ |
| | | { required: true, message: "请è¾å
¥ç³è¯·ç¼å·", trigger: "blur" }, |
| | | ], |
| | | title: [{ required: true, message: "请è¾å
¥ç³è¯·æ é¢", trigger: "blur" }], |
| | | sealType: [{ required: true, message: "è¯·éæ©ç¨å°ç±»å", trigger: "change" }], |
| | | reason: [{ required: true, message: "请è¾å
¥ç³è¯·åå ", trigger: "blur" }], |
| | | }; |
| | | |
| | | const sealSearchForm = reactive({ |
| | | title: '', |
| | | status: '' |
| | | }) |
| | | title: "", |
| | | status: "", |
| | | }); |
| | | // å页忰 |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 10, |
| | | total: 0 |
| | | }) |
| | | 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 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', |
| | | id: "", |
| | | regulationNum: "", |
| | | title: "", |
| | | category: "", |
| | | content: "", |
| | | version: "", |
| | | status: "active", |
| | | readCount: 0, |
| | | effectiveTime: '', |
| | | effectiveTime: "", |
| | | scope: [], |
| | | requireConfirm: false |
| | | }) |
| | | requireConfirm: false, |
| | | }); |
| | | |
| | | const readStatus = ref({ |
| | | id: '', |
| | | ruleId: '', |
| | | employee: '', |
| | | department: '', |
| | | createTime: '', |
| | | confirmTime: '', |
| | | status: 'unconfirmed' |
| | | }) |
| | | 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' }] |
| | | } |
| | | 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: '' |
| | | }) |
| | | title: "", |
| | | category: "", |
| | | }); |
| | | |
| | | // åæ°æ® |
| | | const sealApplications = ref([]) |
| | | const sealApplications = ref([]); |
| | | |
| | | const regulations = ref([]) |
| | | const regulations = ref([]); |
| | | |
| | | const versionHistory = ref([]) |
| | | const versionHistory = ref([]); |
| | | |
| | | const readStatusList = 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) => { |
| | | const getStatusType = status => { |
| | | const statusMap = { |
| | | pending: 'warning', |
| | | approved: 'success', |
| | | rejected: 'danger' |
| | | } |
| | | return statusMap[status] || 'info' |
| | | } |
| | | pending: "warning", |
| | | approved: "success", |
| | | rejected: "danger", |
| | | }; |
| | | return statusMap[status] || "info"; |
| | | }; |
| | | // å¶åº¦ç¶æ |
| | | const getStatusText = (status) => { |
| | | const getStatusText = status => { |
| | | const statusMap = { |
| | | pending: 'å¾
审æ¹', |
| | | approved: 'å·²éè¿', |
| | | rejected: 'å·²æç»' |
| | | } |
| | | return statusMap[status] || 'æªç¥' |
| | | } |
| | | pending: "å¾
审æ¹", |
| | | approved: "å·²éè¿", |
| | | rejected: "å·²æç»", |
| | | }; |
| | | return statusMap[status] || "æªç¥"; |
| | | }; |
| | | // ç¨å°ç±»å |
| | | const getSealTypeText = (sealType) => { |
| | | const getSealTypeText = sealType => { |
| | | const sealTypeMap = { |
| | | official: 'å
¬ç« ', |
| | | contract: 'ååä¸ç¨ç« ', |
| | | finance: 'è´¢å¡ä¸ç¨ç« ', |
| | | tegal: 'ææ¯ä¸ç¨ç« ' |
| | | } |
| | | return sealTypeMap[sealType] || 'æªç¥' |
| | | } |
| | | official: "å
¬ç« ", |
| | | contract: "ååä¸ç¨ç« ", |
| | | finance: "è´¢å¡ä¸ç¨ç« ", |
| | | tegal: "ææ¯ä¸ç¨ç« ", |
| | | }; |
| | | return sealTypeMap[sealType] || "æªç¥"; |
| | | }; |
| | | // å¶åº¦åç±» |
| | | const getCategoryText = (category) => { |
| | | const getCategoryText = category => { |
| | | const categoryMap = { |
| | | hr: '人äºå¶åº¦', |
| | | finance: 'è´¢å¡å¶åº¦', |
| | | safety: 'å®å
¨å¶åº¦', |
| | | tech: 'ææ¯å¶åº¦' |
| | | } |
| | | return categoryMap[category] || 'æªç¥' |
| | | } |
| | | hr: "人äºå¶åº¦", |
| | | finance: "è´¢å¡å¶åº¦", |
| | | safety: "å®å
¨å¶åº¦", |
| | | tech: "ææ¯å¶åº¦", |
| | | }; |
| | | return categoryMap[category] || "æªç¥"; |
| | | }; |
| | | // æç´¢å°ç« ç³è¯· |
| | | const searchSealApplications = () => { |
| | | page.current=1 |
| | | getSealApplicationList() |
| | | page.current = 1; |
| | | getSealApplicationList(); |
| | | |
| | | // ElMessage.success('æç´¢å®æ') |
| | | } |
| | | }; |
| | | // éç½®å°ç« ç³è¯·æç´¢ |
| | | const resetSealSearch = () => { |
| | | sealSearchForm.title = '' |
| | | sealSearchForm.status = '' |
| | | searchSealApplications() |
| | | } |
| | | sealSearchForm.title = ""; |
| | | sealSearchForm.status = ""; |
| | | searchSealApplications(); |
| | | }; |
| | | // æç´¢å¶åº¦ |
| | | const searchRegulations = () => { |
| | | page.current=1 |
| | | getRegulationList() |
| | | } |
| | | page.current = 1; |
| | | getRegulationList(); |
| | | }; |
| | | // éç½®å¶åº¦æç´¢ |
| | | const resetRegulationSearch = () => { |
| | | regulationSearchForm.title = '' |
| | | regulationSearchForm.category = '' |
| | | searchRegulations() |
| | | } |
| | | regulationSearchForm.title = ""; |
| | | regulationSearchForm.category = ""; |
| | | searchRegulations(); |
| | | }; |
| | | // æäº¤ç¨å°ç³è¯· |
| | | const submitSealApplication = async () => { |
| | | try { |
| | | await sealFormRef.value.validate() |
| | | addSealApplication(sealForm).then(res => { |
| | | await sealFormRef.value.validate(); |
| | | addSealApplication(sealForm) |
| | | .then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('ç³è¯·æäº¤æå') |
| | | showSealApplyDialog.value = false |
| | | getSealApplicationList() |
| | | ElMessage.success("ç³è¯·æäº¤æå"); |
| | | showSealApplyDialog.value = false; |
| | | getSealApplicationList(); |
| | | Object.assign(sealForm, { |
| | | applicationNum: '', |
| | | title: '', |
| | | sealType: '', |
| | | reason: '', |
| | | urgency: 'normal', |
| | | status: 'pending' |
| | | }) |
| | | applicationNum: "", |
| | | title: "", |
| | | sealType: "", |
| | | reason: "", |
| | | urgency: "normal", |
| | | status: "pending", |
| | | }); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg) |
| | | }) |
| | | |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | } catch (error) { |
| | | ElMessage.error('请å®åç³è¯·ä¿¡æ¯') |
| | | ElMessage.error("请å®åç³è¯·ä¿¡æ¯"); |
| | | } |
| | | } |
| | | }; |
| | | // æ°å¢ |
| | | const handleAdd = () => { |
| | | operationType.value = 'add' |
| | | resetRegulationForm() |
| | | showRegulationDialog.value = true |
| | | } |
| | | operationType.value = "add"; |
| | | resetRegulationForm(); |
| | | showRegulationDialog.value = true; |
| | | }; |
| | | |
| | | // ç¼è¾ |
| | | const handleEdit = (row) => { |
| | | operationType.value = 'edit' |
| | | Object.assign(regulationForm, row) |
| | | 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(() => { |
| | | 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('å¶åº¦åºå¼æå') |
| | | ElMessage.success("å¶åº¦åºå¼æå"); |
| | | // showRegulationDialog.value = false |
| | | getRegulationList() |
| | | resetRegulationForm() |
| | | getRegulationList(); |
| | | resetRegulationForm(); |
| | | } |
| | | }); |
| | | }) |
| | | }).catch(() => { |
| | | .catch(() => { |
| | | ElMessage({ |
| | | type: 'info', |
| | | message: '已忶åºå¼' |
| | | }) |
| | | }) |
| | | } |
| | | type: "info", |
| | | message: "已忶åºå¼", |
| | | }); |
| | | }); |
| | | }; |
| | | // åå¸å¶åº¦ |
| | | const submitRegulation = async () => { |
| | | try { |
| | | await regulationFormRef.value.validate() |
| | | if(operationType.value == 'add'){ |
| | | await regulationFormRef.value.validate(); |
| | | if (operationType.value == "add") { |
| | | addRuleManagement(regulationForm).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('å¶åº¦å叿å') |
| | | showRegulationDialog.value = false |
| | | getRegulationList() |
| | | resetRegulationForm() |
| | | ElMessage.success("å¶åº¦å叿å"); |
| | | showRegulationDialog.value = false; |
| | | getRegulationList(); |
| | | resetRegulationForm(); |
| | | } |
| | | }) |
| | | }); |
| | | }else{ |
| | | updateRuleManagement(regulationForm).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('å¶åº¦ç¼è¾æå') |
| | | showRegulationDialog.value = false |
| | | resetRegulationForm() |
| | | getRegulationList() |
| | | }})} |
| | | ElMessage.success("å¶åº¦ç¼è¾æå"); |
| | | showRegulationDialog.value = false; |
| | | resetRegulationForm(); |
| | | getRegulationList(); |
| | | } |
| | | }); |
| | | } |
| | | }catch(err){ |
| | | ElMessage.error(err.msg) |
| | | ElMessage.error(err.msg); |
| | | } |
| | | } |
| | | }; |
| | | //éç½®å¶åº¦è¡¨å |
| | | const resetRegulationForm = () => { |
| | | Object.assign(regulationForm, { |
| | | id: '', |
| | | regulationNum: '', |
| | | title: '', |
| | | category: '', |
| | | content: '', |
| | | version: '', |
| | | status: 'active', |
| | | id: "", |
| | | regulationNum: "", |
| | | title: "", |
| | | category: "", |
| | | content: "", |
| | | version: "", |
| | | status: "active", |
| | | readCount: 0, |
| | | effectiveTime: '', |
| | | effectiveTime: "", |
| | | scope: [], |
| | | requireConfirm: false |
| | | }) |
| | | } |
| | | |
| | | requireConfirm: false, |
| | | }); |
| | | }; |
| | | |
| | | // æ¥çç¨å°ç³è¯·è¯¦æ
|
| | | const viewSealDetail = (row) => { |
| | | currentSealDetail.value = row |
| | | showSealDetailDialog.value = true |
| | | } |
| | | const viewSealDetail = row => { |
| | | currentSealDetail.value = row; |
| | | showSealDetailDialog.value = true; |
| | | }; |
| | | // 审æ¹ç¨å°ç³è¯· |
| | | const approveSeal = (row) => { |
| | | console.log(row) |
| | | ElMessageBox.confirm('确认éè¿è¯¥ç¨å°ç³è¯·ï¼', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | const approveSeal = row => { |
| | | console.log(row); |
| | | ElMessageBox.confirm("确认éè¿è¯¥ç¨å°ç³è¯·ï¼", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).then(() => { |
| | | row.status = 'approved' |
| | | row.status = "approved"; |
| | | updateSealApplication(row).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('审æ¹éè¿') |
| | | ElMessage.success("审æ¹éè¿"); |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | }); |
| | | }); |
| | | }; |
| | | // æç»ç¨å°ç³è¯· |
| | | const rejectSeal = (row) => { |
| | | ElMessageBox.prompt('请è¾å
¥æç»åå ', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | const rejectSeal = row => { |
| | | ElMessageBox.prompt("请è¾å
¥æç»åå ", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | inputPattern: /\S+/, |
| | | inputErrorMessage: 'æç»åå ä¸è½ä¸ºç©º' |
| | | inputErrorMessage: "æç»åå ä¸è½ä¸ºç©º", |
| | | }).then(({ value }) => { |
| | | row.status = 'rejected' |
| | | row.status = "rejected"; |
| | | updateSealApplication(row).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('å®¡æ¹æç»') |
| | | ElMessage.success("å®¡æ¹æç»"); |
| | | } |
| | | }) |
| | | 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 |
| | | console.log(res.data.userName); |
| | | currentUser.value = res.data.userName; |
| | | } |
| | | }) |
| | | staffJoinListPage({staffState: 1}).then(res => { |
| | | }); |
| | | staffJoinListPage({ staffState: 1 }) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | // tableData.value = res.data.records |
| | | // //çéåºåcurrentUserååç人å |
| | | tableData.value = res.data.records.filter(item => item.staffName === currentUser.value) |
| | | console.log("tableData",tableData.value) |
| | | tableData.value = res.data.records.filter( |
| | | item => item.staffName === currentUser.value |
| | | ); |
| | | console.log("tableData", tableData.value); |
| | | page.total = res.data.total; |
| | | |
| | | if(tableData.value.length == 0){ |
| | | ElMessage.error('å½åç¨æ·æªå å
¥ä»»ä½é¨é¨') |
| | | ElMessage.error("å½åç¨æ·æªå å
¥ä»»ä½é¨é¨"); |
| | | } |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | | }) |
| | | |
| | | |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | // æ¥çå¶åº¦çæ¬åå² |
| | | const viewVersionHistory = (row) => { |
| | | showVersionHistoryDialog.value = true |
| | | const viewVersionHistory = row => { |
| | | showVersionHistoryDialog.value = true; |
| | | const params = { |
| | | |
| | | category: row.category |
| | | } |
| | | category: row.category, |
| | | }; |
| | | listRuleManagement(page,params).then(res => { |
| | | if(res.code == 200){ |
| | | versionHistory.value = res.data.records |
| | | versionHistory.value = res.data.records; |
| | | } |
| | | }) |
| | | } |
| | | }); |
| | | }; |
| | | // æ¥çå¶åº¦è¯¦æ
|
| | | const viewRegulation = (row) => { |
| | | getList() |
| | | currentRegulationDetail.value = row |
| | | showRegulationDetailDialog.value = true |
| | | const viewRegulation = row => { |
| | | getList(); |
| | | currentRegulationDetail.value = row; |
| | | showRegulationDetailDialog.value = true; |
| | | getReadingStatusByRuleId(row.id).then(res => { |
| | | if(res.code == 200){ |
| | | readStatusList.value = res.data |
| | | 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' |
| | | } |
| | | status: "unconfirmed", |
| | | }; |
| | | addReadingStatus(params).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('å¶åº¦é
读æå') |
| | | ElMessage.success("å¶åº¦é
读æå"); |
| | | } |
| | | }) |
| | | }); |
| | | } |
| | | } |
| | | }) |
| | | |
| | | } |
| | | }); |
| | | }; |
| | | // æ¥çå¶åº¦é
è¯»ç¶æ |
| | | const viewReadStatus = (row) => { |
| | | showReadStatusDialog.value = true |
| | | const viewReadStatus = row => { |
| | | showReadStatusDialog.value = true; |
| | | //æ¥çé
è¯»ç¶æå表 |
| | | getReadingStatusByRuleId(row.id).then(res => { |
| | | if(res.code == 200){ |
| | | readStatusList.value = res.data |
| | | readStatusList.value = res.data; |
| | | } |
| | | }) |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | //确认æ¥ç |
| | | const resetForm = (row) => { |
| | | console.log("row",row) |
| | | row.readCount = row.readCount + 1 |
| | | const resetForm = row => { |
| | | console.log("row", row); |
| | | row.readCount = row.readCount + 1; |
| | | |
| | | updateRuleManagement(row).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('æ¥çæ°éä¿®æ¹æå') |
| | | ElMessage.success("æ¥çæ°éä¿®æ¹æå"); |
| | | //ä¿®æ¹é
è¯»ç¶æ |
| | | //æ ¹æ®å¶åº¦idåå½åç»å½çåå·¥å¾å°é
è¯»ç¶æ |
| | | // let item = readStatusList.value.filter(item => item.employee == tableData.value[0].staffName ) |
| | |
| | | // 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); |
| | | let statusItem = readStatusList.value.find( |
| | | item => |
| | | item.employee === tableData.value[0].staffName && |
| | | item.ruleId === row.id |
| | | ); |
| | | |
| | | if (statusItem) { |
| | | // 妿æ¾å°è®°å½ï¼æ´æ°ç¶æå确认æ¶é´ |
| | | statusItem.status = 'confirmed'; |
| | | 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 = `${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('å¶åº¦é
è¯»ç¶æä¿®æ¹æå') |
| | | ElMessage.success("å¶åº¦é
è¯»ç¶æä¿®æ¹æå"); |
| | | } |
| | | }) |
| | | }); |
| | | } |
| | | |
| | | } |
| | | }) |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // 导åºè§ç« å¶åº¦ |
| | | const { proxy } = getCurrentInstance() |
| | | const { proxy } = getCurrentInstance(); |
| | | const handleExport = () => { |
| | | proxy.download('/rulesRegulationsManagement/export', { ...regulationSearchForm }, 'è§ç« å¶åº¦.xlsx') |
| | | } |
| | | proxy.download( |
| | | "/rulesRegulationsManagement/export", |
| | | { ...regulationSearchForm }, |
| | | "è§ç« å¶åº¦.xlsx" |
| | | ); |
| | | }; |
| | | |
| | | // è·åå°ç« ç³è¯·åè¡¨æ°æ® |
| | | const getSealApplicationList = async () => { |
| | | tableLoading.value = true |
| | | tableLoading.value = true; |
| | | listSealApplication(page,sealSearchForm) |
| | | .then(res => { |
| | | //è·åå½åç»å½çé¨é¨ä¿¡æ¯ |
| | | // è·åå½åç»å½çé¨é¨ä¿¡æ¯å¹¶è¿æ»¤æ°æ® |
| | | const currentFactoryName = userStore.currentFactoryName |
| | | const currentFactoryName = userStore.currentFactoryName; |
| | | if (currentFactoryName) { |
| | | // æ ¹æ®currentFactoryNameè¿æ»¤åºdepartmentç¸åçæ°æ® |
| | | sealApplications.value = res.data.records.filter(item => item.department === currentFactoryName) |
| | | sealApplications.value = res.data.records.filter( |
| | | item => item.department === currentFactoryName |
| | | ); |
| | | // æ´æ°è¿æ»¤åçæ»æ° |
| | | page.value.total = sealApplications.value.length |
| | | page.value.total = sealApplications.value.length; |
| | | } else { |
| | | // å¦ææ²¡æcurrentFactoryNameï¼åæ¾ç¤ºæææ°æ® |
| | | sealApplications.value = res.data.records |
| | | page.value.total = res.data.total |
| | | sealApplications.value = res.data.records; |
| | | page.value.total = res.data.total; |
| | | } |
| | | // sealApplications.value = res.data.records |
| | | // page.value.total = res.data.total; |
| | | tableLoading.value = false; |
| | | |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | | }) |
| | | } |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | // è·åè§ç« å¶åº¦åè¡¨æ°æ® |
| | | const getRegulationList = async () => { |
| | | tableLoading.value = true |
| | | tableLoading.value = true; |
| | | listRuleManagement(page,regulationSearchForm) |
| | | .then(res => { |
| | | |
| | | regulations.value = res.data.records |
| | | regulations.value = res.data.records; |
| | | // è¿æ»¤æå·²åºå¼çå¶åº¦ |
| | | // regulations.value = res.data.records.filter(item => item.status !== 'repealed') |
| | | page.value.total = res.data.total; |
| | | tableLoading.value = false; |
| | | |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | | }) |
| | | } |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | // åå§å |
| | | getSealApplicationList() |
| | | getRegulationList() |
| | | }) |
| | | getSealApplicationList(); |
| | | getRegulationList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | |
| | | <span>ç¨å°ç®¡çåå¸</span> |
| | | </div> |
| | | </template> |
| | | |
| | | |
| | | <!-- ç¨å°ç³è¯·ç®¡ç --> |
| | | <div class="tab-content"> |
| | | <el-row :gutter="20" class="mb-20 "> |
| | | <el-row :gutter="20" |
| | | class="mb-20 "> |
| | | <span class="ml-10">ç¨å°æ é¢ï¼</span> |
| | | <el-col :span="6"> |
| | | <el-input v-model="sealSearchForm.title" placeholder="请è¾å
¥ç³è¯·æ é¢" clearable /> |
| | | <el-input v-model="sealSearchForm.title" |
| | | placeholder="请è¾å
¥ç³è¯·æ é¢" |
| | | clearable /> |
| | | </el-col> |
| | | <span class="search_title">审æ¹ç¶æï¼</span> |
| | | <el-col :span="6"> |
| | | <el-select v-model="sealSearchForm.status" placeholder="审æ¹ç¶æ" clearable> |
| | | <el-option label="å¾
审æ¹" value="pending" /> |
| | | <el-option label="å·²éè¿" value="approved" /> |
| | | <el-option label="å·²æç»" value="rejected" /> |
| | | <el-select v-model="sealSearchForm.status" |
| | | placeholder="审æ¹ç¶æ" |
| | | clearable> |
| | | <el-option label="å¾
审æ¹" |
| | | value="pending" /> |
| | | <el-option label="å·²éè¿" |
| | | value="approved" /> |
| | | <el-option label="å·²æç»" |
| | | value="rejected" /> |
| | | </el-select> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-button type="primary" @click="searchSealApplications">æç´¢</el-button> |
| | | <el-button type="primary" |
| | | @click="searchSealApplications">æç´¢</el-button> |
| | | <el-button @click="resetSealSearch">éç½®</el-button> |
| | | <el-button @click="handleExport">导åº</el-button> |
| | | <el-button type="primary" @click="showSealApplyDialog = true">ç³è¯·ç¨å° |
| | | <el-button type="primary" |
| | | @click="showSealApplyDialog = true">ç³è¯·ç¨å° |
| | | </el-button> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-table :data="sealApplications" border v-loading="tableLoading" style="width: 100%"> |
| | | <el-table-column prop="applicationNum" label="ç³è¯·ç¼å·" width="120" /> |
| | | <el-table-column prop="title" label="ç³è¯·æ é¢" min-width="200" /> |
| | | <el-table-column prop="createUserName" label="ç³è¯·äºº" width="120" /> |
| | | <el-table-column prop="department" label="æå±é¨é¨" width="150" /> |
| | | <el-table-column prop="sealType" label="ç¨å°ç±»å" width="120"> |
| | | <el-table :data="sealApplications" |
| | | border |
| | | v-loading="tableLoading" |
| | | style="width: 100%"> |
| | | <el-table-column prop="applicationNum" |
| | | label="ç³è¯·ç¼å·" |
| | | width="120" /> |
| | | <el-table-column prop="title" |
| | | label="ç³è¯·æ é¢" |
| | | min-width="200" /> |
| | | <el-table-column prop="createUserName" |
| | | label="ç³è¯·äºº" |
| | | width="120" /> |
| | | <el-table-column prop="department" |
| | | label="æå±é¨é¨" |
| | | width="150" /> |
| | | <el-table-column prop="sealType" |
| | | label="ç¨å°ç±»å" |
| | | width="120"> |
| | | <template #default="scope"> |
| | | {{ getSealTypeText(scope.row.sealType) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="createTime" label="ç³è¯·æ¶é´" width="180" /> |
| | | <el-table-column prop="status" label="ç¶æ" width="100"> |
| | | <el-table-column prop="createTime" |
| | | label="ç³è¯·æ¶é´" |
| | | width="180" /> |
| | | <el-table-column prop="status" |
| | | label="ç¶æ" |
| | | width="100"> |
| | | <template #default="scope"> |
| | | <el-tag :type="getStatusType(scope.row.status)"> |
| | | {{ getStatusText(scope.row.status) }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æä½" width="200" fixed="right"> |
| | | <el-table-column label="æä½" |
| | | width="200" |
| | | fixed="right"> |
| | | <template #default="scope"> |
| | | <el-button link @click="viewSealDetail(scope.row)">æ¥ç</el-button> |
| | | <el-button |
| | | v-if="scope.row.status === 'pending'" |
| | | <el-button link |
| | | @click="viewSealDetail(scope.row)">æ¥ç</el-button> |
| | | <el-button v-if="scope.row.status === 'pending'" |
| | | link |
| | | type="primary" |
| | | @click="approveSeal(scope.row)" |
| | | > |
| | | @click="approveSeal(scope.row)"> |
| | | å®¡æ¹ |
| | | </el-button> |
| | | <el-button |
| | | v-if="scope.row.status === 'pending'" |
| | | <el-button v-if="scope.row.status === 'pending'" |
| | | link |
| | | type="danger" |
| | | @click="rejectSeal(scope.row)" |
| | | > |
| | | @click="rejectSeal(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> |
| | | </el-card> |
| | | |
| | | <!-- ç¨å°ç³è¯·å¯¹è¯æ¡ --> |
| | | <el-dialog v-model="showSealApplyDialog" title="ç³è¯·ç¨å°" width="600px"> |
| | | <el-form :model="sealForm" :rules="sealRules" ref="sealFormRef" label-width="100px"> |
| | | <el-form-item label="ç³è¯·ç¼å·" prop="applicationNum"> |
| | | <el-input v-model="sealForm.applicationNum" placeholder="请è¾å
¥ç³è¯·ç¼å·" /> |
| | | <el-dialog v-model="showSealApplyDialog" |
| | | title="ç³è¯·ç¨å°" |
| | | width="600px"> |
| | | <el-form :model="sealForm" |
| | | :rules="sealRules" |
| | | ref="sealFormRef" |
| | | label-width="100px"> |
| | | <el-form-item label="ç³è¯·ç¼å·" |
| | | prop="applicationNum"> |
| | | <el-input v-model="sealForm.applicationNum" |
| | | placeholder="请è¾å
¥ç³è¯·ç¼å·" /> |
| | | </el-form-item> |
| | | <el-form-item label="ç³è¯·æ é¢" prop="title"> |
| | | <el-input v-model="sealForm.title" placeholder="请è¾å
¥ç³è¯·æ é¢" /> |
| | | <el-form-item label="ç³è¯·æ é¢" |
| | | prop="title"> |
| | | <el-input v-model="sealForm.title" |
| | | placeholder="请è¾å
¥ç³è¯·æ é¢" /> |
| | | </el-form-item> |
| | | <el-form-item label="ç¨å°ç±»å" prop="sealType"> |
| | | <el-select v-model="sealForm.sealType" placeholder="è¯·éæ©ç¨å°ç±»å" style="width: 100%"> |
| | | <el-option label="å
¬ç« " value="official" /> |
| | | <el-option label="ååä¸ç¨ç« " value="contract" /> |
| | | <el-option label="è´¢å¡ä¸ç¨ç« " value="finance" /> |
| | | <el-option label="æ³äººç« " value="legal" /> |
| | | <el-form-item label="ç¨å°ç±»å" |
| | | prop="sealType"> |
| | | <el-select v-model="sealForm.sealType" |
| | | placeholder="è¯·éæ©ç¨å°ç±»å" |
| | | style="width: 100%"> |
| | | <el-option label="å
¬ç« " |
| | | value="official" /> |
| | | <el-option label="ååä¸ç¨ç« " |
| | | value="contract" /> |
| | | <el-option label="è´¢å¡ä¸ç¨ç« " |
| | | value="finance" /> |
| | | <el-option label="æ³äººç« " |
| | | value="legal" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="ç³è¯·åå " prop="reason"> |
| | | <el-input v-model="sealForm.reason" type="textarea" :rows="4" placeholder="请详ç»è¯´æç¨å°åå " /> |
| | | <el-form-item label="ç³è¯·åå " |
| | | prop="reason"> |
| | | <el-input v-model="sealForm.reason" |
| | | type="textarea" |
| | | :rows="4" |
| | | placeholder="请详ç»è¯´æç¨å°åå " /> |
| | | </el-form-item> |
| | | <el-form-item label="ç´§æ¥ç¨åº¦" prop="urgency"> |
| | | <el-form-item label="ç´§æ¥ç¨åº¦" |
| | | prop="urgency"> |
| | | <el-radio-group v-model="sealForm.urgency"> |
| | | <el-radio label="normal">æ®é</el-radio> |
| | | <el-radio label="urgent">ç´§æ¥</el-radio> |
| | |
| | | </el-form> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="submitSealApplication">æäº¤ç³è¯·</el-button> |
| | | <el-button @click="showSealApplyDialog = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="submitSealApplication">æäº¤ç³è¯·</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- è§ç« å¶åº¦åå¸å¯¹è¯æ¡ --> |
| | | <!-- <el-dialog v-model="showRegulationDialog" :title="operationType === 'add' ? 'åå¸å¶åº¦' : 'ç¼è¾å¶åº¦'" width="800px"> |
| | | <el-form :model="regulationForm" :rules="regulationRules" ref="regulationFormRef" label-width="100px"> |
| | |
| | | </span> |
| | | </template> |
| | | </el-dialog> --> |
| | | |
| | | <!-- ç¨å°è¯¦æ
å¯¹è¯æ¡ --> |
| | | <el-dialog v-model="showSealDetailDialog" title="ç¨å°ç³è¯·è¯¦æ
" width="700px"> |
| | | <div v-if="currentSealDetail" class="mb10"> |
| | | <el-descriptions :column="2" border> |
| | | <el-dialog v-model="showSealDetailDialog" |
| | | title="ç¨å°ç³è¯·è¯¦æ
" |
| | | width="700px"> |
| | | <div v-if="currentSealDetail" |
| | | class="mb10"> |
| | | <el-descriptions :column="2" |
| | | border> |
| | | <el-descriptions-item label="ç³è¯·ç¼å·">{{ currentSealDetail.id }}</el-descriptions-item> |
| | | <el-descriptions-item label="ç³è¯·æ é¢">{{ currentSealDetail.title }}</el-descriptions-item> |
| | | <el-descriptions-item label="ç³è¯·äºº">{{ currentSealDetail.createUserName }}</el-descriptions-item> |
| | |
| | | {{ getStatusText(currentSealDetail.status) }} |
| | | </el-tag> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="ç³è¯·åå " :span="2">{{ currentSealDetail.reason }}</el-descriptions-item> |
| | | <el-descriptions-item label="ç³è¯·åå " |
| | | :span="2">{{ currentSealDetail.reason }}</el-descriptions-item> |
| | | </el-descriptions> |
| | | </div> |
| | | </el-dialog> |
| | | |
| | | <!-- è§ç« å¶åº¦è¯¦æ
å¯¹è¯æ¡ --> |
| | | <el-dialog v-model="showRegulationDetailDialog" title="è§ç« å¶åº¦è¯¦æ
" width="800px"> |
| | | <el-dialog v-model="showRegulationDetailDialog" |
| | | title="è§ç« å¶åº¦è¯¦æ
" |
| | | width="800px"> |
| | | <div v-if="currentRegulationDetail"> |
| | | <el-descriptions :column="2" border> |
| | | <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> |
| | |
| | | <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 style="margin: 10px 0;" |
| | | v-if="tableData && tableData.length > 0"> |
| | | <el-button type="success" |
| | | @click="resetForm(currentRegulationDetail)">确认æ¥ç</el-button> |
| | | </div> |
| | | </div> |
| | | </el-dialog> |
| | | |
| | | <!-- çæ¬åå²å¯¹è¯æ¡ --> |
| | | <el-dialog v-model="showVersionHistoryDialog" title="çæ¬åå²" width="800px"> |
| | | <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="åæ´è¯´æ"> |
| | | <el-dialog v-model="showVersionHistoryDialog" |
| | | title="çæ¬åå²" |
| | | width="800px"> |
| | | <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-table-column> |
| | | </el-table> |
| | | </el-dialog> |
| | | |
| | | <!-- é
è¯»ç¶æå¯¹è¯æ¡ --> |
| | | <el-dialog v-model="showReadStatusDialog" title="é
è¯»ç¶æ" width="800px"> |
| | | <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"> |
| | | <el-dialog v-model="showReadStatusDialog" |
| | | title="é
è¯»ç¶æ" |
| | | width="800px"> |
| | | <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' ? '已确认' : 'æªç¡®è®¤' }} |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted, getCurrentInstance } from 'vue' |
| | | 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 } from '@/api/system/user.js' |
| | | import {staffJoinDel, staffJoinListPage} from "@/api/personnelManagement/onboarding.js"; |
| | | import useUserStore from '@/store/modules/user' |
| | | import { userLoginFacotryList } from "@/api/system/user.js" |
| | | import { ref, reactive, onMounted, getCurrentInstance } from "vue"; |
| | | 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 } from "@/api/system/user.js"; |
| | | import { |
| | | staffJoinDel, |
| | | staffJoinListPage, |
| | | } from "@/api/personnelManagement/onboarding.js"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { userLoginFacotryList } from "@/api/system/user.js"; |
| | | |
| | | // ååºå¼æ°æ® |
| | | const currentUser = ref(null) |
| | | const activeTab = ref('seal') |
| | | const operationType = ref('add') |
| | | const tableData = ref([]) |
| | | const currentUser = ref(null); |
| | | const activeTab = ref("seal"); |
| | | const operationType = ref("add"); |
| | | const tableData = ref([]); |
| | | // ç¨å°ç³è¯·ç¸å
³ |
| | | const userStore = useUserStore() |
| | | const showSealApplyDialog = ref(false) |
| | | const tableLoading = ref(false) |
| | | const showSealDetailDialog = ref(false) |
| | | const currentSealDetail = ref(null) |
| | | const sealFormRef = ref() |
| | | const userStore = useUserStore(); |
| | | const showSealApplyDialog = ref(false); |
| | | const tableLoading = ref(false); |
| | | const showSealDetailDialog = ref(false); |
| | | const currentSealDetail = ref(null); |
| | | const sealFormRef = ref(); |
| | | const sealForm = reactive({ |
| | | applicationNum: '', |
| | | title: '', |
| | | sealType: '', |
| | | reason: '', |
| | | urgency: 'normal', |
| | | status: 'pending' |
| | | }) |
| | | applicationNum: "", |
| | | title: "", |
| | | sealType: "", |
| | | reason: "", |
| | | urgency: "normal", |
| | | status: "pending", |
| | | }); |
| | | |
| | | const sealRules = { |
| | | applicationNum: [{ required: true, message: '请è¾å
¥ç³è¯·ç¼å·', trigger: 'blur' }], |
| | | title: [{ required: true, message: '请è¾å
¥ç³è¯·æ é¢', trigger: 'blur' }], |
| | | sealType: [{ required: true, message: 'è¯·éæ©ç¨å°ç±»å', trigger: 'change' }], |
| | | reason: [{ required: true, message: '请è¾å
¥ç³è¯·åå ', trigger: 'blur' }] |
| | | } |
| | | applicationNum: [ |
| | | { required: true, message: "请è¾å
¥ç³è¯·ç¼å·", trigger: "blur" }, |
| | | ], |
| | | title: [{ required: true, message: "请è¾å
¥ç³è¯·æ é¢", trigger: "blur" }], |
| | | sealType: [{ required: true, message: "è¯·éæ©ç¨å°ç±»å", trigger: "change" }], |
| | | reason: [{ required: true, message: "请è¾å
¥ç³è¯·åå ", trigger: "blur" }], |
| | | }; |
| | | |
| | | const sealSearchForm = reactive({ |
| | | title: '', |
| | | status: '' |
| | | }) |
| | | title: "", |
| | | status: "", |
| | | }); |
| | | // å页忰 |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0 |
| | | }) |
| | | 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 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', |
| | | id: "", |
| | | regulationNum: "", |
| | | title: "", |
| | | category: "", |
| | | content: "", |
| | | version: "", |
| | | status: "active", |
| | | readCount: 0, |
| | | effectiveTime: '', |
| | | effectiveTime: "", |
| | | scope: [], |
| | | requireConfirm: false |
| | | }) |
| | | requireConfirm: false, |
| | | }); |
| | | |
| | | const readStatus = ref({ |
| | | id: '', |
| | | ruleId: '', |
| | | employee: '', |
| | | department: '', |
| | | createTime: '', |
| | | confirmTime: '', |
| | | status: 'unconfirmed' |
| | | }) |
| | | 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' }] |
| | | } |
| | | 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: '' |
| | | }) |
| | | title: "", |
| | | category: "", |
| | | }); |
| | | |
| | | // åæ°æ® |
| | | const sealApplications = ref([]) |
| | | const sealApplications = ref([]); |
| | | |
| | | const regulations = ref([]) |
| | | const regulations = ref([]); |
| | | |
| | | const versionHistory = ref([]) |
| | | const versionHistory = ref([]); |
| | | |
| | | const readStatusList = 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) => { |
| | | const getStatusType = status => { |
| | | const statusMap = { |
| | | pending: 'warning', |
| | | approved: 'success', |
| | | rejected: 'danger' |
| | | } |
| | | return statusMap[status] || 'info' |
| | | } |
| | | pending: "warning", |
| | | approved: "success", |
| | | rejected: "danger", |
| | | }; |
| | | return statusMap[status] || "info"; |
| | | }; |
| | | // å¶åº¦ç¶æ |
| | | const getStatusText = (status) => { |
| | | const getStatusText = status => { |
| | | const statusMap = { |
| | | pending: 'å¾
审æ¹', |
| | | approved: 'å·²éè¿', |
| | | rejected: 'å·²æç»' |
| | | } |
| | | return statusMap[status] || 'æªç¥' |
| | | } |
| | | pending: "å¾
审æ¹", |
| | | approved: "å·²éè¿", |
| | | rejected: "å·²æç»", |
| | | }; |
| | | return statusMap[status] || "æªç¥"; |
| | | }; |
| | | // ç¨å°ç±»å |
| | | const getSealTypeText = (sealType) => { |
| | | const getSealTypeText = sealType => { |
| | | const sealTypeMap = { |
| | | official: 'å
¬ç« ', |
| | | contract: 'ååä¸ç¨ç« ', |
| | | finance: 'è´¢å¡ä¸ç¨ç« ', |
| | | tegal: 'ææ¯ä¸ç¨ç« ' |
| | | } |
| | | return sealTypeMap[sealType] || 'æªç¥' |
| | | } |
| | | official: "å
¬ç« ", |
| | | contract: "ååä¸ç¨ç« ", |
| | | finance: "è´¢å¡ä¸ç¨ç« ", |
| | | tegal: "ææ¯ä¸ç¨ç« ", |
| | | }; |
| | | return sealTypeMap[sealType] || "æªç¥"; |
| | | }; |
| | | // å¶åº¦åç±» |
| | | const getCategoryText = (category) => { |
| | | const getCategoryText = category => { |
| | | const categoryMap = { |
| | | hr: '人äºå¶åº¦', |
| | | finance: 'è´¢å¡å¶åº¦', |
| | | safety: 'å®å
¨å¶åº¦', |
| | | tech: 'ææ¯å¶åº¦' |
| | | } |
| | | return categoryMap[category] || 'æªç¥' |
| | | } |
| | | hr: "人äºå¶åº¦", |
| | | finance: "è´¢å¡å¶åº¦", |
| | | safety: "å®å
¨å¶åº¦", |
| | | tech: "ææ¯å¶åº¦", |
| | | }; |
| | | return categoryMap[category] || "æªç¥"; |
| | | }; |
| | | // æç´¢å°ç« ç³è¯· |
| | | const searchSealApplications = () => { |
| | | page.current=1 |
| | | getSealApplicationList() |
| | | page.current = 1; |
| | | getSealApplicationList(); |
| | | |
| | | // ElMessage.success('æç´¢å®æ') |
| | | } |
| | | }; |
| | | // éç½®å°ç« ç³è¯·æç´¢ |
| | | const resetSealSearch = () => { |
| | | sealSearchForm.title = '' |
| | | sealSearchForm.status = '' |
| | | searchSealApplications() |
| | | } |
| | | sealSearchForm.title = ""; |
| | | sealSearchForm.status = ""; |
| | | searchSealApplications(); |
| | | }; |
| | | // æç´¢å¶åº¦ |
| | | const searchRegulations = () => { |
| | | page.current=1 |
| | | getRegulationList() |
| | | } |
| | | page.current = 1; |
| | | getRegulationList(); |
| | | }; |
| | | // éç½®å¶åº¦æç´¢ |
| | | const resetRegulationSearch = () => { |
| | | regulationSearchForm.title = '' |
| | | regulationSearchForm.category = '' |
| | | searchRegulations() |
| | | } |
| | | regulationSearchForm.title = ""; |
| | | regulationSearchForm.category = ""; |
| | | searchRegulations(); |
| | | }; |
| | | // æäº¤ç¨å°ç³è¯· |
| | | const submitSealApplication = async () => { |
| | | try { |
| | | await sealFormRef.value.validate() |
| | | addSealApplication(sealForm).then(res => { |
| | | await sealFormRef.value.validate(); |
| | | addSealApplication(sealForm) |
| | | .then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('ç³è¯·æäº¤æå') |
| | | showSealApplyDialog.value = false |
| | | getSealApplicationList() |
| | | ElMessage.success("ç³è¯·æäº¤æå"); |
| | | showSealApplyDialog.value = false; |
| | | getSealApplicationList(); |
| | | Object.assign(sealForm, { |
| | | applicationNum: '', |
| | | title: '', |
| | | sealType: '', |
| | | reason: '', |
| | | urgency: 'normal', |
| | | status: 'pending' |
| | | }) |
| | | applicationNum: "", |
| | | title: "", |
| | | sealType: "", |
| | | reason: "", |
| | | urgency: "normal", |
| | | status: "pending", |
| | | }); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg) |
| | | }) |
| | | |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | } catch (error) { |
| | | ElMessage.error('请å®åç³è¯·ä¿¡æ¯') |
| | | ElMessage.error("请å®åç³è¯·ä¿¡æ¯"); |
| | | } |
| | | } |
| | | }; |
| | | // æ°å¢ |
| | | const handleAdd = () => { |
| | | operationType.value = 'add' |
| | | resetRegulationForm() |
| | | showRegulationDialog.value = true |
| | | } |
| | | operationType.value = "add"; |
| | | resetRegulationForm(); |
| | | showRegulationDialog.value = true; |
| | | }; |
| | | |
| | | // ç¼è¾ |
| | | const handleEdit = (row) => { |
| | | operationType.value = 'edit' |
| | | Object.assign(regulationForm, row) |
| | | 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(() => { |
| | | 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('å¶åº¦åºå¼æå') |
| | | ElMessage.success("å¶åº¦åºå¼æå"); |
| | | // showRegulationDialog.value = false |
| | | getRegulationList() |
| | | resetRegulationForm() |
| | | getRegulationList(); |
| | | resetRegulationForm(); |
| | | } |
| | | }); |
| | | }) |
| | | }).catch(() => { |
| | | .catch(() => { |
| | | ElMessage({ |
| | | type: 'info', |
| | | message: '已忶åºå¼' |
| | | }) |
| | | }) |
| | | } |
| | | type: "info", |
| | | message: "已忶åºå¼", |
| | | }); |
| | | }); |
| | | }; |
| | | // åå¸å¶åº¦ |
| | | const submitRegulation = async () => { |
| | | try { |
| | | await regulationFormRef.value.validate() |
| | | if(operationType.value == 'add'){ |
| | | await regulationFormRef.value.validate(); |
| | | if (operationType.value == "add") { |
| | | addRuleManagement(regulationForm).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('å¶åº¦å叿å') |
| | | showRegulationDialog.value = false |
| | | getRegulationList() |
| | | resetRegulationForm() |
| | | ElMessage.success("å¶åº¦å叿å"); |
| | | showRegulationDialog.value = false; |
| | | getRegulationList(); |
| | | resetRegulationForm(); |
| | | } |
| | | }) |
| | | }); |
| | | }else{ |
| | | updateRuleManagement(regulationForm).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('å¶åº¦ç¼è¾æå') |
| | | showRegulationDialog.value = false |
| | | resetRegulationForm() |
| | | getRegulationList() |
| | | }})} |
| | | ElMessage.success("å¶åº¦ç¼è¾æå"); |
| | | showRegulationDialog.value = false; |
| | | resetRegulationForm(); |
| | | getRegulationList(); |
| | | } |
| | | }); |
| | | } |
| | | }catch(err){ |
| | | ElMessage.error(err.msg) |
| | | ElMessage.error(err.msg); |
| | | } |
| | | } |
| | | }; |
| | | //éç½®å¶åº¦è¡¨å |
| | | const resetRegulationForm = () => { |
| | | Object.assign(regulationForm, { |
| | | id: '', |
| | | regulationNum: '', |
| | | title: '', |
| | | category: '', |
| | | content: '', |
| | | version: '', |
| | | status: 'active', |
| | | id: "", |
| | | regulationNum: "", |
| | | title: "", |
| | | category: "", |
| | | content: "", |
| | | version: "", |
| | | status: "active", |
| | | readCount: 0, |
| | | effectiveTime: '', |
| | | effectiveTime: "", |
| | | scope: [], |
| | | requireConfirm: false |
| | | }) |
| | | } |
| | | |
| | | requireConfirm: false, |
| | | }); |
| | | }; |
| | | |
| | | // æ¥çç¨å°ç³è¯·è¯¦æ
|
| | | const viewSealDetail = (row) => { |
| | | currentSealDetail.value = row |
| | | showSealDetailDialog.value = true |
| | | } |
| | | const viewSealDetail = row => { |
| | | currentSealDetail.value = row; |
| | | showSealDetailDialog.value = true; |
| | | }; |
| | | // 审æ¹ç¨å°ç³è¯· |
| | | const approveSeal = (row) => { |
| | | console.log(row) |
| | | ElMessageBox.confirm('确认éè¿è¯¥ç¨å°ç³è¯·ï¼', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | const approveSeal = row => { |
| | | console.log(row); |
| | | ElMessageBox.confirm("确认éè¿è¯¥ç¨å°ç³è¯·ï¼", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).then(() => { |
| | | row.status = 'approved' |
| | | row.status = "approved"; |
| | | updateSealApplication(row).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('审æ¹éè¿') |
| | | ElMessage.success("审æ¹éè¿"); |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | }); |
| | | }); |
| | | }; |
| | | // æç»ç¨å°ç³è¯· |
| | | const rejectSeal = (row) => { |
| | | ElMessageBox.prompt('请è¾å
¥æç»åå ', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | const rejectSeal = row => { |
| | | ElMessageBox.prompt("请è¾å
¥æç»åå ", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | inputPattern: /\S+/, |
| | | inputErrorMessage: 'æç»åå ä¸è½ä¸ºç©º' |
| | | inputErrorMessage: "æç»åå ä¸è½ä¸ºç©º", |
| | | }).then(({ value }) => { |
| | | row.status = 'rejected' |
| | | row.status = "rejected"; |
| | | updateSealApplication(row).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('å®¡æ¹æç»') |
| | | ElMessage.success("å®¡æ¹æç»"); |
| | | } |
| | | }) |
| | | 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 |
| | | console.log(res.data.userName); |
| | | currentUser.value = res.data.userName; |
| | | } |
| | | }) |
| | | staffJoinListPage({staffState: 1, ...page}).then(res => { |
| | | }); |
| | | staffJoinListPage({ 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) |
| | | tableData.value = res.data.records.filter( |
| | | item => item.staffName === currentUser.value |
| | | ); |
| | | page.total = res.data.total; |
| | | |
| | | if(tableData.value.length == 0){ |
| | | ElMessage.error('å½åç¨æ·æªå å
¥ä»»ä½é¨é¨') |
| | | ElMessage.error("å½åç¨æ·æªå å
¥ä»»ä½é¨é¨"); |
| | | } |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | | }) |
| | | |
| | | |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | // æ¥çå¶åº¦çæ¬åå² |
| | | const viewVersionHistory = (row) => { |
| | | showVersionHistoryDialog.value = true |
| | | const viewVersionHistory = row => { |
| | | showVersionHistoryDialog.value = true; |
| | | const params = { |
| | | |
| | | category: row.category |
| | | } |
| | | category: row.category, |
| | | }; |
| | | listRuleManagement(page,params).then(res => { |
| | | if(res.code == 200){ |
| | | versionHistory.value = res.data.records |
| | | versionHistory.value = res.data.records; |
| | | } |
| | | }) |
| | | } |
| | | }); |
| | | }; |
| | | // æ¥çå¶åº¦è¯¦æ
|
| | | const viewRegulation = (row) => { |
| | | getList() |
| | | currentRegulationDetail.value = row |
| | | showRegulationDetailDialog.value = true |
| | | const viewRegulation = row => { |
| | | getList(); |
| | | currentRegulationDetail.value = row; |
| | | showRegulationDetailDialog.value = true; |
| | | getReadingStatusByRuleId(row.id).then(res => { |
| | | if(res.code == 200){ |
| | | readStatusList.value = res.data |
| | | 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' |
| | | } |
| | | status: "unconfirmed", |
| | | }; |
| | | addReadingStatus(params).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('å¶åº¦é
读æå') |
| | | ElMessage.success("å¶åº¦é
读æå"); |
| | | } |
| | | }) |
| | | }); |
| | | } |
| | | } |
| | | }) |
| | | |
| | | } |
| | | }); |
| | | }; |
| | | // æ¥çå¶åº¦é
è¯»ç¶æ |
| | | const viewReadStatus = (row) => { |
| | | showReadStatusDialog.value = true |
| | | const viewReadStatus = row => { |
| | | showReadStatusDialog.value = true; |
| | | //æ¥çé
è¯»ç¶æå表 |
| | | getReadingStatusByRuleId(row.id).then(res => { |
| | | if(res.code == 200){ |
| | | readStatusList.value = res.data |
| | | readStatusList.value = res.data; |
| | | } |
| | | }) |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | //确认æ¥ç |
| | | const resetForm = (row) => { |
| | | console.log("row",row) |
| | | row.readCount = row.readCount + 1 |
| | | const resetForm = row => { |
| | | console.log("row", row); |
| | | row.readCount = row.readCount + 1; |
| | | |
| | | updateRuleManagement(row).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('æ¥çæ°éä¿®æ¹æå') |
| | | ElMessage.success("æ¥çæ°éä¿®æ¹æå"); |
| | | //ä¿®æ¹é
è¯»ç¶æ |
| | | //æ ¹æ®å¶åº¦idåå½åç»å½çåå·¥å¾å°é
è¯»ç¶æ |
| | | // let item = readStatusList.value.filter(item => item.employee == tableData.value[0].staffName ) |
| | |
| | | // 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); |
| | | let statusItem = readStatusList.value.find( |
| | | item => |
| | | item.employee === tableData.value[0].staffName && |
| | | item.ruleId === row.id |
| | | ); |
| | | |
| | | if (statusItem) { |
| | | // 妿æ¾å°è®°å½ï¼æ´æ°ç¶æå确认æ¶é´ |
| | | statusItem.status = 'confirmed'; |
| | | 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 = `${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('å¶åº¦é
è¯»ç¶æä¿®æ¹æå') |
| | | ElMessage.success("å¶åº¦é
è¯»ç¶æä¿®æ¹æå"); |
| | | } |
| | | }) |
| | | }); |
| | | } |
| | | |
| | | } |
| | | }) |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // 导åºç¨å°ç³è¯· |
| | | const { proxy } = getCurrentInstance() |
| | | const { proxy } = getCurrentInstance(); |
| | | const handleExport = () => { |
| | | proxy.download('/sealApplicationManagement/export', { ...sealSearchForm }, 'ç¨å°ç³è¯·.xlsx') |
| | | } |
| | | proxy.download( |
| | | "/sealApplicationManagement/export", |
| | | { ...sealSearchForm }, |
| | | "ç¨å°ç³è¯·.xlsx" |
| | | ); |
| | | }; |
| | | |
| | | // è·åå°ç« ç³è¯·åè¡¨æ°æ® |
| | | const getSealApplicationList = async () => { |
| | | tableLoading.value = true |
| | | tableLoading.value = true; |
| | | listSealApplication(page,sealSearchForm) |
| | | .then(res => { |
| | | //è·åå½åç»å½çé¨é¨ä¿¡æ¯ |
| | | // è·åå½åç»å½çé¨é¨ä¿¡æ¯å¹¶è¿æ»¤æ°æ® |
| | | const currentFactoryName = userStore.currentFactoryName |
| | | const currentFactoryName = userStore.currentFactoryName; |
| | | if (currentFactoryName) { |
| | | // æ ¹æ®currentFactoryNameè¿æ»¤åºdepartmentç¸åçæ°æ® |
| | | sealApplications.value = res.data.records.filter(item => item.department === currentFactoryName) |
| | | sealApplications.value = res.data.records.filter( |
| | | item => item.department === currentFactoryName |
| | | ); |
| | | // æ´æ°è¿æ»¤åçæ»æ° |
| | | page.total = sealApplications.value.length |
| | | page.total = sealApplications.value.length; |
| | | } else { |
| | | // å¦ææ²¡æcurrentFactoryNameï¼åæ¾ç¤ºæææ°æ® |
| | | sealApplications.value = res.data.records |
| | | page.total = res.data.total |
| | | sealApplications.value = res.data.records; |
| | | page.total = res.data.total; |
| | | } |
| | | // sealApplications.value = res.data.records |
| | | // page.value.total = res.data.total; |
| | | tableLoading.value = false; |
| | | |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | | }) |
| | | } |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | // è·åè§ç« å¶åº¦åè¡¨æ°æ® |
| | | const getRegulationList = async () => { |
| | | tableLoading.value = true |
| | | tableLoading.value = true; |
| | | listRuleManagement(page,regulationSearchForm) |
| | | .then(res => { |
| | | |
| | | regulations.value = res.data.records |
| | | 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; |
| | | }) |
| | | } |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | // åå§å |
| | | getSealApplicationList() |
| | | getRegulationList() |
| | | }) |
| | | getSealApplicationList(); |
| | | getRegulationList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | |
| | | <div class="defect-management"> |
| | | <!-- æä½æé® --> |
| | | <div class="actions"> |
| | | <el-button type="primary" @click="showRegisterDialog = true">ç»è®°ç¼ºé·</el-button> |
| | | <el-button type="primary" |
| | | @click="showRegisterDialog = true">ç»è®°ç¼ºé·</el-button> |
| | | </div> |
| | | |
| | | <!-- 缺é·å表 --> |
| | | <el-table :data="defectList" style="width: 100%; margin-top: 10px;" border> |
| | | <el-table-column prop="deviceName" label="设å¤åç§°" width="180"></el-table-column> |
| | | <el-table-column prop="defectDescription" label="ç¼ºé·æè¿°" win-width="300"></el-table-column> |
| | | <el-table-column prop="status" label="ç¶æ" width="220"> |
| | | <el-table :data="defectList" |
| | | style="width: 100%; margin-top: 10px;" |
| | | border> |
| | | <el-table-column prop="deviceName" |
| | | label="设å¤åç§°" |
| | | width="180"></el-table-column> |
| | | <el-table-column prop="defectDescription" |
| | | label="ç¼ºé·æè¿°" |
| | | win-width="300"></el-table-column> |
| | | <el-table-column prop="status" |
| | | label="ç¶æ" |
| | | width="220"> |
| | | <template #default="{ row }"> |
| | | <el-tag :type="row.status === '严é缺é·' ? 'danger' : 'success'"> |
| | | {{ row.status }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æä½" width="220"> |
| | | <el-table-column label="æä½" |
| | | width="220"> |
| | | <template #default="{ row }"> |
| | | <el-button |
| | | v-if="row.status === '严é缺é·' || row.status === 'ä¸è¬ç¼ºé·'" |
| | | <el-button v-if="row.status === '严é缺é·' || row.status === 'ä¸è¬ç¼ºé·'" |
| | | type="text" |
| | | @click="eliminateDefect(row)" |
| | | > |
| | | @click="eliminateDefect(row)"> |
| | | æ¶é¤ç¼ºé· |
| | | </el-button> |
| | | <!-- <el-button |
| | |
| | | > |
| | | 转维修å |
| | | </el-button> --> |
| | | <el-button type="text" @click="getLedger(row.deviceLedgerId)"> |
| | | <el-button type="text" |
| | | @click="getLedger(row.deviceLedgerId)"> |
| | | æ¥çå°è´¦ |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <!-- 缺é·ç»è®°å¯¹è¯æ¡ --> |
| | | <el-dialog title="ç»è®°è®¾å¤ç¼ºé·" v-model="showRegisterDialog" width="50%"> |
| | | <el-form :model="defectForm" :rules="defectRules" ref="defectFormRef" label-width="100px"> |
| | | <el-form-item label="设å¤åç§°" prop="deviceName"> |
| | | <el-select v-model="defectForm.deviceLedgerId" @change="setDeviceModel"> |
| | | <el-option |
| | | v-for="(item, index) in deviceOptions" |
| | | <el-dialog title="ç»è®°è®¾å¤ç¼ºé·" |
| | | v-model="showRegisterDialog" |
| | | width="50%"> |
| | | <el-form :model="defectForm" |
| | | :rules="defectRules" |
| | | ref="defectFormRef" |
| | | label-width="100px"> |
| | | <el-form-item label="设å¤åç§°" |
| | | prop="deviceName"> |
| | | <el-select v-model="defectForm.deviceLedgerId" |
| | | @change="setDeviceModel"> |
| | | <el-option v-for="(item, index) in deviceOptions" |
| | | :key="index" |
| | | :label="item.deviceName" |
| | | :value="item.id" |
| | | ></el-option> |
| | | :value="item.id"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="ç¼ºé·æè¿°" prop="defectDescription"> |
| | | <el-input type="textarea" v-model="defectForm.defectDescription"></el-input> |
| | | <el-form-item label="ç¼ºé·æè¿°" |
| | | prop="defectDescription"> |
| | | <el-input type="textarea" |
| | | v-model="defectForm.defectDescription"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="设å¤ç¶æ" prop="status"> |
| | | <el-form-item label="设å¤ç¶æ" |
| | | prop="status"> |
| | | <el-radio-group v-model="defectForm.status"> |
| | | <el-radio label="æ£å¸¸">æ£å¸¸</el-radio> |
| | | <el-radio label="ä¸è¬ç¼ºé·">ä¸è¬ç¼ºé·</el-radio> |
| | |
| | | </el-form> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="submitDefectForm">ç¡®å®</el-button> |
| | | <el-button @click="showRegisterDialog = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="submitDefectForm">ç¡®å®</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- 缺é·è®¾å¤å°è´¦å¯¹è¯æ¡ --> |
| | | <el-dialog title="缺é·è®¾å¤å°è´¦" v-model="showLedgerDialog" width="80%"> |
| | | <el-table :data="ledgerList" style="width: 100%; margin-top: 10px;" border> |
| | | <el-table-column prop="deviceName" label="设å¤åç§°"></el-table-column> |
| | | <el-table-column prop="defectDescription" label="ç¼ºé·æè¿°"></el-table-column> |
| | | <el-table-column prop="status" label="ç¶æ"></el-table-column> |
| | | <el-table-column prop="eliminateTime" label="æ¶ç¼ºæ¶é´"></el-table-column> |
| | | <el-dialog title="缺é·è®¾å¤å°è´¦" |
| | | v-model="showLedgerDialog" |
| | | width="80%"> |
| | | <el-table :data="ledgerList" |
| | | style="width: 100%; margin-top: 10px;" |
| | | border> |
| | | <el-table-column prop="deviceName" |
| | | label="设å¤åç§°"></el-table-column> |
| | | <el-table-column prop="defectDescription" |
| | | label="ç¼ºé·æè¿°"></el-table-column> |
| | | <el-table-column prop="status" |
| | | label="ç¶æ"></el-table-column> |
| | | <el-table-column prop="eliminateTime" |
| | | label="æ¶ç¼ºæ¶é´"></el-table-column> |
| | | </el-table> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive } from 'vue'; |
| | | import { ElMessage } from 'element-plus'; |
| | | import { ref, reactive } from "vue"; |
| | | import { ElMessage } from "element-plus"; |
| | | import { getDeviceLedger } from "@/api/equipmentManagement/ledger"; |
| | | // åè®¾ä»¥ä¸æ¯å端æ¥å£ |
| | | import { |
| | |
| | | getDefectList, |
| | | eliminateDefect as apiEliminateDefect, |
| | | getDefectLedger, |
| | | deleteDefect |
| | | } from '@/api/equipmentManagement/defectManagement'; |
| | | deleteDefect, |
| | | } from "@/api/equipmentManagement/defectManagement"; |
| | | |
| | | // 缺é·å表 |
| | | const defectList = ref([]); |
| | |
| | | const showLedgerDialog = ref(false); |
| | | // 缺é·è¡¨å |
| | | const defectForm = reactive({ |
| | | deviceLedgerId: '', |
| | | defectDescription: '', |
| | | status: '', |
| | | deviceLedgerId: "", |
| | | defectDescription: "", |
| | | status: "", |
| | | }); |
| | | const deviceOptions = ref([]); |
| | | // 表åéªè¯è§å |
| | | const defectRules = reactive({ |
| | | deviceLedgerId: [{ required: true, message: '请è¾å
¥è®¾å¤åç§°', trigger: 'blur' }], |
| | | defectDescription: [{ required: true, message: '请è¾å
¥ç¼ºé·æè¿°', trigger: 'blur' }] |
| | | deviceLedgerId: [ |
| | | { required: true, message: "请è¾å
¥è®¾å¤åç§°", trigger: "blur" }, |
| | | ], |
| | | defectDescription: [ |
| | | { required: true, message: "请è¾å
¥ç¼ºé·æè¿°", trigger: "blur" }, |
| | | ], |
| | | }); |
| | | // 表åå¼ç¨ |
| | | const defectFormRef = ref(null); |
| | |
| | | if (res.code === 200) { |
| | | defectList.value = res.data.records; |
| | | } else { |
| | | ElMessage.error(res.message || 'è·å缺é·å表失败'); |
| | | ElMessage.error(res.message || "è·å缺é·å表失败"); |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error('è·å缺é·å表失败'); |
| | | ElMessage.error("è·å缺é·å表失败"); |
| | | } |
| | | }; |
| | | |
| | |
| | | await defectFormRef.value.validate(); |
| | | const res = await registerDefect(defectForm); |
| | | if (res.code === 200) { |
| | | ElMessage.success('缺é·ç»è®°æå'); |
| | | ElMessage.success("缺é·ç»è®°æå"); |
| | | showRegisterDialog.value = false; |
| | | fetchDefectList(); |
| | | } else { |
| | | ElMessage.error(res.message || '缺é·ç»è®°å¤±è´¥'); |
| | | ElMessage.error(res.message || "缺é·ç»è®°å¤±è´¥"); |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error('请填å宿´è¡¨åä¿¡æ¯'); |
| | | ElMessage.error("请填å宿´è¡¨åä¿¡æ¯"); |
| | | } |
| | | }; |
| | | |
| | | // æ¶é¤ç¼ºé· |
| | | const eliminateDefect = async (row) => { |
| | | |
| | | const eliminateDefect = async row => { |
| | | try { |
| | | const res = await apiEliminateDefect(row); |
| | | if (res.code === 200) { |
| | | ElMessage.success('ç¼ºé·æ¶é¤æå'); |
| | | ElMessage.success("ç¼ºé·æ¶é¤æå"); |
| | | fetchDefectList(); |
| | | } else { |
| | | ElMessage.error(res.message || 'ç¼ºé·æ¶é¤å¤±è´¥'); |
| | | ElMessage.error(res.message || "ç¼ºé·æ¶é¤å¤±è´¥"); |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error('ç¼ºé·æ¶é¤å¤±è´¥'); |
| | | ElMessage.error("ç¼ºé·æ¶é¤å¤±è´¥"); |
| | | } |
| | | }; |
| | | |
| | |
| | | // }; |
| | | |
| | | // è·å缺é·è®¾å¤å°è´¦ |
| | | const getLedger = async (deviceLedgerId) => { |
| | | const getLedger = async deviceLedgerId => { |
| | | try { |
| | | const res = await getDefectLedger(deviceLedgerId); |
| | | if (res.code === 200) { |
| | | ledgerList.value = res.data.records; |
| | | showLedgerDialog.value = true; |
| | | } else { |
| | | ElMessage.error(res.message || 'è·å缺é·è®¾å¤å°è´¦å¤±è´¥'); |
| | | ElMessage.error(res.message || "è·å缺é·è®¾å¤å°è´¦å¤±è´¥"); |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error('è·å缺é·è®¾å¤å°è´¦å¤±è´¥'); |
| | | ElMessage.error("è·å缺é·è®¾å¤å°è´¦å¤±è´¥"); |
| | | } |
| | | }; |
| | | |
| | |
| | | <template> |
| | | <div> |
| | | <el-dialog :title="operationType === 'add' ? 'æ°å¢å·¡æ£ä»»å¡' : 'ç¼è¾å·¡æ£ä»»å¡'" |
| | | v-model="dialogVisitable" width="800px" @close="cancel"> |
| | | <el-form ref="formRef" :model="form" :rules="rules" label-width="120px"> |
| | | v-model="dialogVisitable" |
| | | width="800px" |
| | | @close="cancel"> |
| | | <el-form ref="formRef" |
| | | :model="form" |
| | | :rules="rules" |
| | | label-width="120px"> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="设å¤åç§°" prop="taskId"> |
| | | <el-select v-model="form.taskId" @change="setDeviceModel" filterable> |
| | | <el-option |
| | | v-for="(item, index) in deviceOptions" |
| | | <el-form-item label="设å¤åç§°" |
| | | prop="taskId"> |
| | | <el-select v-model="form.taskId" |
| | | @change="setDeviceModel" |
| | | filterable> |
| | | <el-option v-for="(item, index) in deviceOptions" |
| | | :key="index" |
| | | :label="item.deviceName" |
| | | :value="item.id" |
| | | ></el-option> |
| | | :value="item.id"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å·¡æ£äºº" prop="inspector"> |
| | | <el-select v-model="form.inspector" filterable |
| | | <el-form-item label="å·¡æ£äºº" |
| | | prop="inspector"> |
| | | <el-select v-model="form.inspector" |
| | | filterable |
| | | default-first-option |
| | | :reserve-keyword="false" placeholder="è¯·éæ©" multiple clearable> |
| | | <el-option v-for="item in userList" :label="item.nickName" :value="item.userId" :key="item.userId"/> |
| | | :reserve-keyword="false" |
| | | placeholder="è¯·éæ©" |
| | | multiple |
| | | clearable> |
| | | <el-option v-for="item in userList" |
| | | :label="item.nickName" |
| | | :value="item.userId" |
| | | :key="item.userId" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="夿³¨" prop="remarks"> |
| | | <el-input v-model="form.remarks" placeholder="请è¾å
¥å¤æ³¨" type="textarea" /> |
| | | <el-form-item label="夿³¨" |
| | | prop="remarks"> |
| | | <el-input v-model="form.remarks" |
| | | placeholder="请è¾å
¥å¤æ³¨" |
| | | type="textarea" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç»è®°æ¶é´" prop="dateStr"> |
| | | <el-date-picker |
| | | v-model="form.dateStr" |
| | | <el-form-item label="ç»è®°æ¶é´" |
| | | prop="dateStr"> |
| | | <el-date-picker v-model="form.dateStr" |
| | | type="date" |
| | | placeholder="éæ©ç»è®°æ¥æ" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 100%" |
| | | /> |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä»»å¡é¢ç" prop="frequencyType"> |
| | | <el-select v-model="form.frequencyType" placeholder="è¯·éæ©" clearable> |
| | | <el-option label="æ¯æ¥" value="DAILY"/> |
| | | <el-option label="æ¯å¨" value="WEEKLY"/> |
| | | <el-option label="æ¯æ" value="MONTHLY"/> |
| | | <el-form-item label="ä»»å¡é¢ç" |
| | | prop="frequencyType"> |
| | | <el-select v-model="form.frequencyType" |
| | | placeholder="è¯·éæ©" |
| | | clearable> |
| | | <el-option label="æ¯æ¥" |
| | | value="DAILY" /> |
| | | <el-option label="æ¯å¨" |
| | | value="WEEKLY" /> |
| | | <el-option label="æ¯æ" |
| | | value="MONTHLY" /> |
| | | <!-- <el-option label="å£åº¦" value="QUARTERLY"/> --> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12" v-if="form.frequencyType === 'DAILY' && form.frequencyType"> |
| | | <el-form-item label="æ¥æ" prop="frequencyDetail"> |
| | | <el-time-picker v-model="form.frequencyDetail" placeholder="éæ©æ¶é´" format="HH:mm" |
| | | <el-col :span="12" |
| | | v-if="form.frequencyType === 'DAILY' && form.frequencyType"> |
| | | <el-form-item label="æ¥æ" |
| | | prop="frequencyDetail"> |
| | | <el-time-picker v-model="form.frequencyDetail" |
| | | placeholder="éæ©æ¶é´" |
| | | format="HH:mm" |
| | | value-format="HH:mm" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12" v-if="form.frequencyType === 'WEEKLY' && form.frequencyType"> |
| | | <el-form-item label="æ¥æ" prop="frequencyDetail"> |
| | | <el-select v-model="form.week" placeholder="è¯·éæ©" clearable style="width: 50%"> |
| | | <el-option label="å¨ä¸" value="MON"/> |
| | | <el-option label="å¨äº" value="TUE"/> |
| | | <el-option label="å¨ä¸" value="WED"/> |
| | | <el-option label="å¨å" value="THU"/> |
| | | <el-option label="å¨äº" value="FRI"/> |
| | | <el-option label="å¨å
" value="SAT"/> |
| | | <el-option label="卿¥" value="SUN"/> |
| | | <el-col :span="12" |
| | | v-if="form.frequencyType === 'WEEKLY' && form.frequencyType"> |
| | | <el-form-item label="æ¥æ" |
| | | prop="frequencyDetail"> |
| | | <el-select v-model="form.week" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | style="width: 50%"> |
| | | <el-option label="å¨ä¸" |
| | | value="MON" /> |
| | | <el-option label="å¨äº" |
| | | value="TUE" /> |
| | | <el-option label="å¨ä¸" |
| | | value="WED" /> |
| | | <el-option label="å¨å" |
| | | value="THU" /> |
| | | <el-option label="å¨äº" |
| | | value="FRI" /> |
| | | <el-option label="å¨å
" |
| | | value="SAT" /> |
| | | <el-option label="卿¥" |
| | | value="SUN" /> |
| | | </el-select> |
| | | <el-time-picker v-model="form.time" placeholder="éæ©æ¶é´" format="HH:mm" |
| | | value-format="HH:mm" style="width: 50%"/> |
| | | <el-time-picker v-model="form.time" |
| | | placeholder="éæ©æ¶é´" |
| | | format="HH:mm" |
| | | value-format="HH:mm" |
| | | style="width: 50%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12" v-if="form.frequencyType === 'MONTHLY' && form.frequencyType"> |
| | | <el-form-item label="æ¥æ" prop="frequencyDetail"> |
| | | <el-date-picker |
| | | v-model="form.frequencyDetail" |
| | | <el-col :span="12" |
| | | v-if="form.frequencyType === 'MONTHLY' && form.frequencyType"> |
| | | <el-form-item label="æ¥æ" |
| | | prop="frequencyDetail"> |
| | | <el-date-picker v-model="form.frequencyDetail" |
| | | type="datetime" |
| | | clearable |
| | | placeholder="éæ©å¼å§æ¥æ" |
| | | format="DD,HH:mm" |
| | | value-format="DD,HH:mm" |
| | | /> |
| | | value-format="DD,HH:mm" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12" v-if="form.frequencyType === 'QUARTERLY' && form.frequencyType"> |
| | | <el-form-item label="æ¥æ" prop="frequencyDetail"> |
| | | <el-date-picker |
| | | v-model="form.frequencyDetail" |
| | | <el-col :span="12" |
| | | v-if="form.frequencyType === 'QUARTERLY' && form.frequencyType"> |
| | | <el-form-item label="æ¥æ" |
| | | prop="frequencyDetail"> |
| | | <el-date-picker v-model="form.frequencyDetail" |
| | | type="datetime" |
| | | clearable |
| | | placeholder="éæ©å¼å§æ¥æ" |
| | | format="MM,DD,HH:mm" |
| | | value-format="MM,DD,HH:mm" |
| | | /> |
| | | value-format="MM,DD,HH:mm" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="submitForm">ä¿å</el-button> |
| | | <el-button @click="cancel">åæ¶</el-button> |
| | | <el-button type="primary" @click="submitForm">ä¿å</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | |
| | | |
| | | <script setup> |
| | | import {reactive, ref} from "vue"; |
| | | import useUserStore from '@/store/modules/user' |
| | | import useUserStore from "@/store/modules/user"; |
| | | import {addOrEditTimingTask} from "@/api/inspectionManagement/index.js"; |
| | | import {userListNoPageByTenantId} from "@/api/system/user.js"; |
| | | import { getDeviceLedger } from "@/api/equipmentManagement/ledger"; |
| | | |
| | | const { proxy } = getCurrentInstance() |
| | | const emit = defineEmits() |
| | | const userStore = useUserStore() |
| | | const { proxy } = getCurrentInstance(); |
| | | const emit = defineEmits(); |
| | | const userStore = useUserStore(); |
| | | const dialogVisitable = ref(false); |
| | | const operationType = ref('add'); |
| | | const operationType = ref("add"); |
| | | const deviceOptions = ref([]); |
| | | const data = reactive({ |
| | | form: { |
| | | taskId: undefined, |
| | | taskName: undefined, |
| | | inspector: '', |
| | | inspectorIds: '', |
| | | remarks: '', |
| | | frequencyType: '', |
| | | frequencyDetail: '', |
| | | week: '', |
| | | time: '', |
| | | dateStr: '' |
| | | inspector: "", |
| | | inspectorIds: "", |
| | | remarks: "", |
| | | frequencyType: "", |
| | | frequencyDetail: "", |
| | | week: "", |
| | | time: "", |
| | | dateStr: "", |
| | | }, |
| | | rules: { |
| | | taskId: [{ required: true, message: "è¯·éæ©è®¾å¤", trigger: "change" },], |
| | | inspector: [{ required: true, message: "请è¾å
¥å·¡æ£äºº", trigger: "blur" },], |
| | | dateStr: [{ required: true, message: "è¯·éæ©ç»è®°æ¶é´", trigger: "change" }] |
| | | } |
| | | }) |
| | | const { form, rules } = toRefs(data) |
| | | const userList = ref([]) |
| | | taskId: [{ required: true, message: "è¯·éæ©è®¾å¤", trigger: "change" }], |
| | | inspector: [{ required: true, message: "请è¾å
¥å·¡æ£äºº", trigger: "blur" }], |
| | | dateStr: [{ required: true, message: "è¯·éæ©ç»è®°æ¶é´", trigger: "change" }], |
| | | }, |
| | | }); |
| | | const { form, rules } = toRefs(data); |
| | | const userList = ref([]); |
| | | |
| | | const loadDeviceName = async () => { |
| | | const { data } = await getDeviceLedger(); |
| | | deviceOptions.value = data; |
| | | }; |
| | | |
| | | const setDeviceModel = (id) => { |
| | | const option = deviceOptions.value.find((item) => item.id === id); |
| | | const setDeviceModel = id => { |
| | | const option = deviceOptions.value.find(item => item.id === id); |
| | | if (option) { |
| | | form.value.taskName = option.deviceName; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openDialog = async (type, row) => { |
| | | dialogVisitable.value = true |
| | | operationType.value = type |
| | | dialogVisitable.value = true; |
| | | operationType.value = type; |
| | | |
| | | // é置表å |
| | | resetForm(); |
| | | |
| | | // å è½½ç¨æ·å表 |
| | | userListNoPageByTenantId().then((res) => { |
| | | userListNoPageByTenantId().then(res => { |
| | | userList.value = res.data; |
| | | }); |
| | | |
| | | // å 载设å¤å表 |
| | | await loadDeviceName(); |
| | | |
| | | if (type === 'edit' && row) { |
| | | form.value = {...row} |
| | | form.value.inspector = form.value.inspectorIds.split(',').map(Number) |
| | | if (type === "edit" && row) { |
| | | form.value = { ...row }; |
| | | form.value.inspector = form.value.inspectorIds.split(",").map(Number); |
| | | |
| | | // 妿æè®¾å¤IDï¼èªå¨è®¾ç½®è®¾å¤ä¿¡æ¯ |
| | | if (form.value.taskId) { |
| | | setDeviceModel(form.value.taskId); |
| | | } |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // å
³éå¯¹è¯æ¡ |
| | | const cancel = () => { |
| | | resetForm() |
| | | dialogVisitable.value = false |
| | | emit('closeDia') |
| | | } |
| | | resetForm(); |
| | | dialogVisitable.value = false; |
| | | emit("closeDia"); |
| | | }; |
| | | |
| | | // é置表å彿° |
| | | const resetForm = () => { |
| | | if (proxy.$refs.formRef) { |
| | | proxy.$refs.formRef.resetFields() |
| | | proxy.$refs.formRef.resetFields(); |
| | | } |
| | | // éç½®è¡¨åæ°æ®ç¡®ä¿è®¾å¤ä¿¡æ¯æ£ç¡®éç½® |
| | | form.value = { |
| | | taskId: undefined, |
| | | taskName: undefined, |
| | | inspector: '', |
| | | inspectorIds: '', |
| | | remarks: '', |
| | | frequencyType: '', |
| | | frequencyDetail: '', |
| | | week: '', |
| | | time: '' |
| | | } |
| | | } |
| | | inspector: "", |
| | | inspectorIds: "", |
| | | remarks: "", |
| | | frequencyType: "", |
| | | frequencyDetail: "", |
| | | week: "", |
| | | time: "", |
| | | }; |
| | | }; |
| | | |
| | | // æäº¤è¡¨å |
| | | const submitForm = () => { |
| | | proxy.$refs["formRef"].validate(async valid => { |
| | | if (valid) { |
| | | try { |
| | | form.value.inspectorIds = form.value.inspector.join(',') |
| | | delete form.value.inspector |
| | | form.value.inspectorIds = form.value.inspector.join(","); |
| | | delete form.value.inspector; |
| | | |
| | | if (form.value.frequencyType === 'WEEKLY') { |
| | | let frequencyDetail = '' |
| | | frequencyDetail = form.value.week + ',' + form.value.time |
| | | form.value.frequencyDetail = frequencyDetail |
| | | if (form.value.frequencyType === "WEEKLY") { |
| | | let frequencyDetail = ""; |
| | | frequencyDetail = form.value.week + "," + form.value.time; |
| | | form.value.frequencyDetail = frequencyDetail; |
| | | } |
| | | |
| | | let res = await userStore.getInfo() |
| | | form.value.registrantId = res.user.userId |
| | | let res = await userStore.getInfo(); |
| | | form.value.registrantId = res.user.userId; |
| | | |
| | | await addOrEditTimingTask(form.value) |
| | | cancel() |
| | | proxy.$modal.msgSuccess('æäº¤æå') |
| | | await addOrEditTimingTask(form.value); |
| | | cancel(); |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | } catch (error) { |
| | | proxy.$modal.msgError('æäº¤å¤±è´¥ï¼è¯·éè¯') |
| | | proxy.$modal.msgError("æäº¤å¤±è´¥ï¼è¯·éè¯"); |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | defineExpose({ openDialog }) |
| | | }); |
| | | }; |
| | | defineExpose({ openDialog }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | |
| | | </style> |
| | |
| | | <div class="spare-part-category"> |
| | | <div class="table_list"> |
| | | <div class="actions"> |
| | | <el-text class="mx-1" size="large">设å¤åç±»</el-text> |
| | | <el-text class="mx-1" |
| | | size="large">设å¤åç±»</el-text> |
| | | <div> |
| | | <el-button @click="fetchTreeData" :loading="loading">å·æ°</el-button> |
| | | <el-button type="primary" @click="addCategory" >æ°å¢</el-button> |
| | | <el-button @click="fetchTreeData" |
| | | :loading="loading">å·æ°</el-button> |
| | | <el-button type="primary" |
| | | @click="addCategory">æ°å¢</el-button> |
| | | </div> |
| | | </div> |
| | | <el-table |
| | | v-loading="loading" |
| | | <el-table v-loading="loading" |
| | | :data="renderTableData" |
| | | style="width: 100%; margin-top: 10px;" |
| | | border |
| | | row-key="id" |
| | | :tree-props="{ children: 'children', hasChildren: 'hasChildren' }" |
| | | > |
| | | <el-table-column prop="name" label="åç±»åç§°" width="450"> |
| | | :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"> |
| | | <el-table-column prop="name" |
| | | label="åç±»åç§°" |
| | | width="450"> |
| | | <template #default="{ row }"> |
| | | <span :style="{ paddingLeft: getIndentation(row) + 'px' }"> |
| | | {{ row.name }} |
| | | </span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="sparePartsNo" label="åç±»ç¼å·" width="200"></el-table-column> |
| | | <el-table-column prop="status" label="ç¶æ" width="100"> |
| | | <el-table-column prop="sparePartsNo" |
| | | label="åç±»ç¼å·" |
| | | width="200"></el-table-column> |
| | | <el-table-column prop="status" |
| | | label="ç¶æ" |
| | | width="100"> |
| | | <template #default="{ row }"> |
| | | <el-tag type="success" size="small">{{ row.status }}</el-tag> |
| | | <el-tag type="success" |
| | | size="small">{{ row.status }}</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="description" label="æè¿°" win-width="330"></el-table-column> |
| | | <el-table-column label="æä½" width="180" fixed="right"> |
| | | <el-table-column prop="description" |
| | | label="æè¿°" |
| | | win-width="330"></el-table-column> |
| | | <el-table-column label="æä½" |
| | | width="180" |
| | | fixed="right"> |
| | | <template #default="{ row }"> |
| | | <el-button |
| | | type="text" |
| | | <el-button type="text" |
| | | size="small" |
| | | @click="() => editCategory(row)" |
| | | :disabled="loading" |
| | | > |
| | | :disabled="loading"> |
| | | ç¼è¾ |
| | | </el-button> |
| | | <el-button |
| | | link |
| | | <el-button type="text" |
| | | size="small" |
| | | @click="() => deleteCategory(row.id)" |
| | | style="color: #f56c6c;" |
| | | :disabled="loading" |
| | | > |
| | | :disabled="loading"> |
| | | å é¤ |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | <el-dialog title="å类管ç" v-model="dialogVisible" width="60%"> |
| | | <el-form :model="form" :rules="rules" ref="formRef" label-width="100px"> |
| | | <el-form-item label="åç±»åç§°" prop="name"> |
| | | <el-dialog title="å类管ç" |
| | | v-model="dialogVisible" |
| | | width="60%"> |
| | | <el-form :model="form" |
| | | :rules="rules" |
| | | ref="formRef" |
| | | label-width="100px"> |
| | | <el-form-item label="åç±»åç§°" |
| | | prop="name"> |
| | | <el-input v-model="form.name"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="åç±»ç¼å·" prop="sparePartsNo"> |
| | | <el-form-item label="åç±»ç¼å·" |
| | | prop="sparePartsNo"> |
| | | <el-input v-model="form.sparePartsNo"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="ç¶æ" prop="status"> |
| | | <el-select v-model="form.status" placeholder="è¯·éæ©ç¶æ"> |
| | | <el-option label="æ£å¸¸" value="æ£å¸¸"></el-option> |
| | | <el-option label="ç¦ç¨" value="ç¦ç¨"></el-option> |
| | | <el-form-item label="ç¶æ" |
| | | prop="status"> |
| | | <el-select v-model="form.status" |
| | | placeholder="è¯·éæ©ç¶æ"> |
| | | <el-option label="æ£å¸¸" |
| | | value="æ£å¸¸"></el-option> |
| | | <el-option label="ç¦ç¨" |
| | | value="ç¦ç¨"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="æè¿°" prop="description"> |
| | | <el-form-item label="æè¿°" |
| | | prop="description"> |
| | | <el-input v-model="form.description"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="ä»·æ ¼" prop="price"> |
| | | <el-input-number |
| | | v-model="form.price" |
| | | placeholder="请è¾å
¥ä»·æ ¼" |
| | | :min="0" |
| | | :step="0.01" |
| | | :precision="2" |
| | | style="width: 100%" |
| | | ></el-input-number> |
| | | <el-form-item label="ä¸çº§åç±»" |
| | | prop="parentId"> |
| | | <el-select v-model="form.parentId" |
| | | placeholder="è¯·éæ©ä¸çº§åç±»"> |
| | | <el-option label="æ ä¸çº§åç±»" |
| | | :value="null"></el-option> |
| | | <el-option v-for="(item, index) in categories" |
| | | :key="index" |
| | | :label="item.name" |
| | | :value="item.id"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button @click="dialogVisible = false" :disabled="formLoading">åæ¶</el-button> |
| | | <el-button type="primary" @click="submitForm" :loading="formLoading">ç¡®å®</el-button> |
| | | <el-button type="primary" |
| | | @click="submitForm" |
| | | :loading="formLoading">ç¡®å®</el-button> |
| | | <el-button @click="dialogVisible = false" |
| | | :disabled="formLoading">åæ¶</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, computed, onMounted, reactive, watch } from 'vue'; |
| | | import { ElMessage, ElMessageBox } from 'element-plus'; |
| | | import { getSparePartsList, addSparePart, editSparePart, delSparePart,getSparePartsTree } from "@/api/equipmentManagement/spareParts"; |
| | | import { ref, computed, onMounted, reactive, watch } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import { |
| | | getSparePartsList, |
| | | addSparePart, |
| | | editSparePart, |
| | | delSparePart, |
| | | getSparePartsTree, |
| | | } from "@/api/equipmentManagement/spareParts"; |
| | | |
| | | // å è½½ç¶æ |
| | | const loading = ref(false); |
| | |
| | | // 渲æç¨çè¡¨æ ¼æ°æ® |
| | | // const renderTableData = computed(() => buildTree(categories.value)); |
| | | const renderTableData = ref([]); |
| | | const operationType = ref('add') |
| | | const operationType = ref("add"); |
| | | // 表åå¼ç¨ |
| | | const formRef = ref(null); |
| | | // è¡¨åæ°æ® |
| | | const form = reactive({ |
| | | id:'', |
| | | name: '', |
| | | sparePartsNo: '', |
| | | status: '', |
| | | description: '', |
| | | parentId: null |
| | | id: "", |
| | | name: "", |
| | | sparePartsNo: "", |
| | | status: "", |
| | | description: "", |
| | | parentId: null, |
| | | }); |
| | | |
| | | // 表åéªè¯è§å |
| | | const rules = reactive({ |
| | | name: [ |
| | | { required: true, message: '请è¾å
¥åç±»åç§°', trigger: 'blur' } |
| | | ], |
| | | name: [{ required: true, message: "请è¾å
¥åç±»åç§°", trigger: "blur" }], |
| | | sparePartsNo: [ |
| | | { required: true, message: '请è¾å
¥åç±»ç¼å·', trigger: 'blur' } |
| | | { required: true, message: "请è¾å
¥åç±»ç¼å·", trigger: "blur" }, |
| | | ], |
| | | status: [ |
| | | { required: true, message: 'è¯·éæ©ç¶æ', trigger: 'change' } |
| | | ] |
| | | status: [{ required: true, message: "è¯·éæ©ç¶æ", trigger: "change" }], |
| | | }); |
| | | // è·å缩è¿é |
| | | const getIndentation = (row) => { |
| | | const getIndentation = row => { |
| | | // è¿éç®åè¿å 20ï¼å¯æ ¹æ®å®é
éæ±å®ç°å±çº§ç¼©è¿é»è¾ |
| | | return 20; |
| | | }; |
| | | // å®ä¹ buildTree 彿° |
| | | const buildTree = (flatData) => { |
| | | const buildTree = flatData => { |
| | | const map = {}; |
| | | const result = []; |
| | | if(flatData){ |
| | |
| | | if (res.code === 200) { |
| | | renderTableData.value = res.data; |
| | | } else { |
| | | ElMessage.error(res.message || 'è·ååç±»å表失败'); |
| | | ElMessage.error(res.message || "è·ååç±»å表失败"); |
| | | } |
| | | }catch (error) { |
| | | ElMessage.error('è·ååç±»å表失败'); |
| | | ElMessage.error("è·ååç±»å表失败"); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // è·ååç±»å表 |
| | | const fetchCategories = async () => { |
| | |
| | | if (res.code === 200) { |
| | | categories.value = res.data.records; |
| | | } else { |
| | | ElMessage.error(res.message || 'è·ååç±»å表失败'); |
| | | ElMessage.error(res.message || "è·ååç±»å表失败"); |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error('è·ååç±»å表失败'); |
| | | ElMessage.error("è·ååç±»å表失败"); |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | |
| | | |
| | | // æ°å¢åç±» |
| | | const addCategory = () => { |
| | | form.id = ''; |
| | | form.name = ''; |
| | | form.sparePartsNo = ''; |
| | | form.status = ''; |
| | | form.description = ''; |
| | | form.id = ""; |
| | | form.name = ""; |
| | | form.sparePartsNo = ""; |
| | | form.status = ""; |
| | | form.description = ""; |
| | | form.parentId = null; |
| | | operationType.value = 'add' |
| | | operationType.value = "add"; |
| | | dialogVisible.value = true; |
| | | console.log('dialogVisible æ´æ°ä¸º', dialogVisible.value); |
| | | console.log("dialogVisible æ´æ°ä¸º", dialogVisible.value); |
| | | }; |
| | | |
| | | // ç¼è¾åç±» |
| | | const editCategory = (row) => { |
| | | const editCategory = row => { |
| | | Object.assign(form, row); |
| | | operationType.value = 'edit' |
| | | operationType.value = "edit"; |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | // å é¤åç±» |
| | | const deleteCategory = async (id) => { |
| | | const deleteCategory = async id => { |
| | | try { |
| | | await ElMessageBox.confirm('æ¤æä½å°æ°¸ä¹
å é¤è¯¥åç±»ï¼æ¯å¦ç»§ç»?', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | await ElMessageBox.confirm("æ¤æä½å°æ°¸ä¹
å é¤è¯¥åç±»ï¼æ¯å¦ç»§ç»?", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }); |
| | | loading.value = true; |
| | | const res = await delSparePart(id); |
| | | if (res.code === 200) { |
| | | ElMessage.success('å 餿å'); |
| | | ElMessage.success("å 餿å"); |
| | | fetchTreeData(); |
| | | } else { |
| | | ElMessage.error(res.message || 'å é¤å¤±è´¥'); |
| | | ElMessage.error(res.message || "å é¤å¤±è´¥"); |
| | | } |
| | | } catch (error) { |
| | | if (error !== 'cancel') { |
| | | ElMessage.error('å é¤å¤±è´¥'); |
| | | if (error !== "cancel") { |
| | | ElMessage.error("å é¤å¤±è´¥"); |
| | | } |
| | | } finally { |
| | | loading.value = false; |
| | |
| | | try { |
| | | await formRef.value.validate(); |
| | | formLoading.value = true; |
| | | if (operationType.value === 'edit') { |
| | | if (operationType.value === "edit") { |
| | | let res = await editSparePart(form); |
| | | if (res.code === 200) { |
| | | ElMessage.success('ç¼è¾æå'); |
| | | ElMessage.success("ç¼è¾æå"); |
| | | dialogVisible.value = false; |
| | | fetchTreeData(); |
| | | } |
| | | } else { |
| | | let res = await addSparePart(form); |
| | | if (res.code === 200) { |
| | | ElMessage.success('ç¼è¾æå'); |
| | | ElMessage.success("ç¼è¾æå"); |
| | | dialogVisible.value = false; |
| | | fetchTreeData(); |
| | | } |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error('请填å宿´è¡¨åä¿¡æ¯'); |
| | | ElMessage.error("请填å宿´è¡¨åä¿¡æ¯"); |
| | | } finally { |
| | | formLoading.value = false; |
| | | } |
| | |
| | | |
| | | /* ç©ºç¶ææ ·å¼ */ |
| | | .el-table .cell:empty::before { |
| | | content: '-'; |
| | | content: "-"; |
| | | color: #c0c4cc; |
| | | } |
| | | |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <div class="search-form"> |
| | | <el-form :inline="true" :model="searchForm"> |
| | | <el-form :inline="true" |
| | | :model="searchForm"> |
| | | <el-form-item label="é¨é¨"> |
| | | <el-input |
| | | v-model="searchForm.department" |
| | | <el-input v-model="searchForm.department" |
| | | placeholder="请è¾å
¥é¨é¨åç§°" |
| | | clearable |
| | | style="width: 200px" |
| | | /> |
| | | style="width: 200px" /> |
| | | </el-form-item> |
| | | <el-form-item label="å§å"> |
| | | <el-input |
| | | v-model="searchForm.name" |
| | | <el-input v-model="searchForm.name" |
| | | placeholder="请è¾å
¥å§å" |
| | | clearable |
| | | style="width: 200px" |
| | | /> |
| | | style="width: 200px" /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleSearch">æç´¢</el-button> |
| | | <el-button type="primary" |
| | | @click="handleSearch">æç´¢</el-button> |
| | | <el-button @click="handleReset">éç½®</el-button> |
| | | <el-button type="success" @click="handleAdd">æ°å¢</el-button> |
| | | <el-button type="success" |
| | | @click="handleAdd">æ°å¢</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | |
| | | <div class="table-container"> |
| | | <DynamicTable |
| | | ref="dynamicTableRef" |
| | | <DynamicTable ref="dynamicTableRef" |
| | | :data="tableData" |
| | | :dict-types="dictTypes" |
| | | :loading="loading" |
| | |
| | | @select-change="handleSelectChange" |
| | | @input-change="handleInputChange" |
| | | @size-change="handleSizeChange" |
| | | @current-change="handleCurrentChange" |
| | | /> |
| | | @current-change="handleCurrentChange" /> |
| | | </div> |
| | | |
| | | <!-- æ°å¢/ç¼è¾å¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | v-model="dialogVisible" |
| | | <el-dialog v-model="dialogVisible" |
| | | :title="dialogTitle" |
| | | width="600px" |
| | | append-to-body |
| | | > |
| | | <el-form |
| | | ref="formRef" |
| | | append-to-body> |
| | | <el-form ref="formRef" |
| | | :model="form" |
| | | :rules="rules" |
| | | label-width="100px" |
| | | > |
| | | <el-form-item label="é¨é¨" prop="department"> |
| | | <el-input v-model="form.department" placeholder="请è¾å
¥é¨é¨" /> |
| | | label-width="100px"> |
| | | <el-form-item label="é¨é¨" |
| | | prop="department"> |
| | | <el-input v-model="form.department" |
| | | placeholder="请è¾å
¥é¨é¨" /> |
| | | </el-form-item> |
| | | <el-form-item label="å§å" prop="name"> |
| | | <el-input v-model="form.name" placeholder="请è¾å
¥å§å" /> |
| | | <el-form-item label="å§å" |
| | | prop="name"> |
| | | <el-input v-model="form.name" |
| | | placeholder="请è¾å
¥å§å" /> |
| | | </el-form-item> |
| | | <el-form-item label="å·¥å·" prop="employeeId"> |
| | | <el-input v-model="form.employeeId" placeholder="请è¾å
¥å·¥å·" /> |
| | | <el-form-item label="å·¥å·" |
| | | prop="employeeId"> |
| | | <el-input v-model="form.employeeId" |
| | | placeholder="请è¾å
¥å·¥å·" /> |
| | | </el-form-item> |
| | | |
| | | <!-- å¨æè¡¨åé¡¹ï¼æ ¹æ®åå
¸çæ --> |
| | | <el-form-item |
| | | v-for="dictItem in dynamicFormItems" |
| | | <el-form-item v-for="dictItem in dynamicFormItems" |
| | | :key="dictItem.value" |
| | | :label="dictItem.label" |
| | | :prop="dictItem.value" |
| | | > |
| | | <el-select |
| | | v-model="form[dictItem.value]" |
| | | :prop="dictItem.value"> |
| | | <el-select v-model="form[dictItem.value]" |
| | | placeholder="è¯·éæ©" |
| | | style="width: 100%" |
| | | > |
| | | <el-option |
| | | v-for="option in dictItem.options" |
| | | style="width: 100%"> |
| | | <el-option v-for="option in dictItem.options" |
| | | :key="option.value" |
| | | :label="option.label" |
| | | :value="option.value" |
| | | /> |
| | | :value="option.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="handleSubmit">ç¡®å®</el-button> |
| | | <el-button @click="dialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="handleSubmit">ç¡®å®</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, computed, onMounted } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import DynamicTable from '@/components/DynamicTable/index.vue' |
| | | import { ref, reactive, computed, onMounted } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import DynamicTable from "@/components/DynamicTable/index.vue"; |
| | | |
| | | // ååºå¼æ°æ® |
| | | const loading = ref(false) |
| | | const dialogVisible = ref(false) |
| | | const dialogTitle = ref('') |
| | | const editIndex = ref(-1) |
| | | const selectedRows = ref([]) |
| | | const loading = ref(false); |
| | | const dialogVisible = ref(false); |
| | | const dialogTitle = ref(""); |
| | | const editIndex = ref(-1); |
| | | const selectedRows = ref([]); |
| | | |
| | | // æç´¢è¡¨å |
| | | const searchForm = reactive({ |
| | | department: '', |
| | | name: '' |
| | | }) |
| | | department: "", |
| | | name: "", |
| | | }); |
| | | |
| | | // è¡¨æ ¼æ°æ® |
| | | const tableData = ref([ |
| | | { |
| | | id: 1, |
| | | department: 'ææ¯é¨', |
| | | name: 'å¼ ä¸', |
| | | employeeId: 'EMP001', |
| | | status: '1', |
| | | level: '2', |
| | | position: '1' |
| | | department: "ææ¯é¨", |
| | | name: "å¼ ä¸", |
| | | employeeId: "EMP001", |
| | | status: "1", |
| | | level: "2", |
| | | position: "1", |
| | | }, |
| | | { |
| | | id: 2, |
| | | department: '人äºé¨', |
| | | name: 'æå', |
| | | employeeId: 'EMP002', |
| | | status: '0', |
| | | level: '1', |
| | | position: '2' |
| | | department: "人äºé¨", |
| | | name: "æå", |
| | | employeeId: "EMP002", |
| | | status: "0", |
| | | level: "1", |
| | | position: "2", |
| | | }, |
| | | { |
| | | id: 3, |
| | | department: 'è´¢å¡é¨', |
| | | name: 'çäº', |
| | | employeeId: 'EMP003', |
| | | status: '1', |
| | | level: '3', |
| | | position: '1' |
| | | } |
| | | ]) |
| | | department: "è´¢å¡é¨", |
| | | name: "çäº", |
| | | employeeId: "EMP003", |
| | | status: "1", |
| | | level: "3", |
| | | position: "1", |
| | | }, |
| | | ]); |
| | | |
| | | // åå
¸ç±»åé
ç½® |
| | | const dictTypes = ref([ |
| | | 'sys_normal_disable', // ç¶æåå
¸ |
| | | 'sys_user_level', // 级å«åå
¸ |
| | | 'sys_user_position' // èä½åå
¸ |
| | | ]) |
| | | "sys_normal_disable", // ç¶æåå
¸ |
| | | "sys_user_level", // 级å«åå
¸ |
| | | "sys_user_position", // èä½åå
¸ |
| | | ]); |
| | | |
| | | // å页é
ç½® |
| | | const pagination = reactive({ |
| | | current: 1, |
| | | size: 10, |
| | | total: 0 |
| | | }) |
| | | total: 0, |
| | | }); |
| | | |
| | | // è¡¨åæ°æ® |
| | | const form = reactive({ |
| | | department: '', |
| | | name: '', |
| | | employeeId: '', |
| | | status: '', |
| | | level: '', |
| | | position: '' |
| | | }) |
| | | department: "", |
| | | name: "", |
| | | employeeId: "", |
| | | status: "", |
| | | level: "", |
| | | position: "", |
| | | }); |
| | | |
| | | // 表åéªè¯è§å |
| | | const rules = { |
| | | department: [ |
| | | { required: true, message: '请è¾å
¥é¨é¨', trigger: 'blur' } |
| | | ], |
| | | name: [ |
| | | { required: true, message: '请è¾å
¥å§å', trigger: 'blur' } |
| | | ], |
| | | employeeId: [ |
| | | { required: true, message: '请è¾å
¥å·¥å·', trigger: 'blur' } |
| | | ] |
| | | } |
| | | department: [{ required: true, message: "请è¾å
¥é¨é¨", trigger: "blur" }], |
| | | name: [{ required: true, message: "请è¾å
¥å§å", trigger: "blur" }], |
| | | employeeId: [{ required: true, message: "请è¾å
¥å·¥å·", trigger: "blur" }], |
| | | }; |
| | | |
| | | // å¨æè¡¨å项 |
| | | const dynamicFormItems = computed(() => { |
| | | // è¿éå¯ä»¥æ ¹æ®åå
¸æ°æ®å¨æçæè¡¨å项 |
| | | return [ |
| | | { |
| | | label: 'ç¶æ', |
| | | value: 'status', |
| | | label: "ç¶æ", |
| | | value: "status", |
| | | options: [ |
| | | { label: 'å¯ç¨', value: '1' }, |
| | | { label: 'ç¦ç¨', value: '0' } |
| | | ] |
| | | { label: "å¯ç¨", value: "1" }, |
| | | { label: "ç¦ç¨", value: "0" }, |
| | | ], |
| | | }, |
| | | { |
| | | label: '级å«', |
| | | value: 'level', |
| | | label: "级å«", |
| | | value: "level", |
| | | options: [ |
| | | { label: 'å级', value: '1' }, |
| | | { label: 'ä¸çº§', value: '2' }, |
| | | { label: 'é«çº§', value: '3' } |
| | | ] |
| | | { label: "å级", value: "1" }, |
| | | { label: "ä¸çº§", value: "2" }, |
| | | { label: "é«çº§", value: "3" }, |
| | | ], |
| | | }, |
| | | { |
| | | label: 'èä½', |
| | | value: 'position', |
| | | label: "èä½", |
| | | value: "position", |
| | | options: [ |
| | | { label: 'åå·¥', value: '1' }, |
| | | { label: '主管', value: '2' }, |
| | | { label: 'ç»ç', value: '3' } |
| | | ] |
| | | } |
| | | ] |
| | | }) |
| | | { label: "åå·¥", value: "1" }, |
| | | { label: "主管", value: "2" }, |
| | | { label: "ç»ç", value: "3" }, |
| | | ], |
| | | }, |
| | | ]; |
| | | }); |
| | | |
| | | // ç»ä»¶å¼ç¨ |
| | | const dynamicTableRef = ref(null) |
| | | const formRef = ref(null) |
| | | const dynamicTableRef = ref(null); |
| | | const formRef = ref(null); |
| | | |
| | | // äºä»¶å¤ç彿° |
| | | const handleSearch = () => { |
| | | // å®ç°æç´¢é»è¾ |
| | | console.log('æç´¢æ¡ä»¶:', searchForm) |
| | | ElMessage.success('æç´¢åè½å¾
å®ç°') |
| | | } |
| | | console.log("æç´¢æ¡ä»¶:", searchForm); |
| | | ElMessage.success("æç´¢åè½å¾
å®ç°"); |
| | | }; |
| | | |
| | | const handleReset = () => { |
| | | searchForm.department = '' |
| | | searchForm.name = '' |
| | | } |
| | | searchForm.department = ""; |
| | | searchForm.name = ""; |
| | | }; |
| | | |
| | | const handleAdd = () => { |
| | | dialogTitle.value = 'æ°å¢åå·¥' |
| | | editIndex.value = -1 |
| | | resetForm() |
| | | dialogVisible.value = true |
| | | } |
| | | dialogTitle.value = "æ°å¢åå·¥"; |
| | | editIndex.value = -1; |
| | | resetForm(); |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | const handleEdit = (row, index) => { |
| | | dialogTitle.value = 'ç¼è¾åå·¥' |
| | | editIndex.value = index |
| | | Object.assign(form, row) |
| | | dialogVisible.value = true |
| | | } |
| | | dialogTitle.value = "ç¼è¾åå·¥"; |
| | | editIndex.value = index; |
| | | Object.assign(form, row); |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | const handleDelete = async (row, index) => { |
| | | try { |
| | | await ElMessageBox.confirm('ç¡®å®è¦å é¤è¿æ¡è®°å½åï¼', 'æç¤º', { |
| | | type: 'warning' |
| | | }) |
| | | await ElMessageBox.confirm("ç¡®å®è¦å é¤è¿æ¡è®°å½åï¼", "æç¤º", { |
| | | type: "warning", |
| | | }); |
| | | |
| | | tableData.value.splice(index, 1) |
| | | ElMessage.success('å 餿å') |
| | | tableData.value.splice(index, 1); |
| | | ElMessage.success("å 餿å"); |
| | | } catch (error) { |
| | | // ç¨æ·åæ¶å é¤ |
| | | } |
| | | } |
| | | }; |
| | | |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection |
| | | } |
| | | const handleSelectionChange = selection => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | |
| | | const handleSelectChange = (row, prop, value) => { |
| | | console.log('éæ©åå:', row, prop, value) |
| | | console.log("éæ©åå:", row, prop, value); |
| | | // å¯ä»¥å¨è¿éå¤çæ°æ®æ´æ°é»è¾ |
| | | } |
| | | }; |
| | | |
| | | const handleInputChange = (row, prop, value) => { |
| | | console.log('è¾å
¥åå:', row, prop, value) |
| | | console.log("è¾å
¥åå:", row, prop, value); |
| | | // å¯ä»¥å¨è¿éå¤çæ°æ®æ´æ°é»è¾ |
| | | } |
| | | }; |
| | | |
| | | const handleSizeChange = (size) => { |
| | | pagination.size = size |
| | | const handleSizeChange = size => { |
| | | pagination.size = size; |
| | | // éæ°å è½½æ°æ® |
| | | } |
| | | }; |
| | | |
| | | const handleCurrentChange = (current) => { |
| | | pagination.current = current |
| | | const handleCurrentChange = current => { |
| | | pagination.current = current; |
| | | // éæ°å è½½æ°æ® |
| | | } |
| | | }; |
| | | |
| | | const handleSubmit = async () => { |
| | | try { |
| | | await formRef.value.validate() |
| | | await formRef.value.validate(); |
| | | |
| | | if (editIndex.value === -1) { |
| | | // æ°å¢ |
| | | const newRow = { |
| | | id: Date.now(), |
| | | ...form |
| | | } |
| | | tableData.value.push(newRow) |
| | | ElMessage.success('æ°å¢æå') |
| | | ...form, |
| | | }; |
| | | tableData.value.push(newRow); |
| | | ElMessage.success("æ°å¢æå"); |
| | | } else { |
| | | // ç¼è¾ |
| | | Object.assign(tableData.value[editIndex.value], form) |
| | | ElMessage.success('ç¼è¾æå') |
| | | Object.assign(tableData.value[editIndex.value], form); |
| | | ElMessage.success("ç¼è¾æå"); |
| | | } |
| | | |
| | | dialogVisible.value = false |
| | | dialogVisible.value = false; |
| | | } catch (error) { |
| | | console.error('表åéªè¯å¤±è´¥:', error) |
| | | console.error("表åéªè¯å¤±è´¥:", error); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | const resetForm = () => { |
| | | Object.assign(form, { |
| | | department: '', |
| | | name: '', |
| | | employeeId: '', |
| | | status: '', |
| | | level: '', |
| | | position: '' |
| | | }) |
| | | formRef.value?.resetFields() |
| | | } |
| | | department: "", |
| | | name: "", |
| | | employeeId: "", |
| | | status: "", |
| | | level: "", |
| | | position: "", |
| | | }); |
| | | formRef.value?.resetFields(); |
| | | }; |
| | | |
| | | // ç»ä»¶æè½½æ¶åå§åæ°æ® |
| | | onMounted(() => { |
| | | pagination.total = tableData.value.length |
| | | }) |
| | | pagination.total = tableData.value.length; |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | |
| | | <template> |
| | | <div class="sample"> |
| | | <div class="main-content" v-if="!isDetail"> |
| | | <div class="main-content" |
| | | v-if="!isDetail"> |
| | | <div class="search"> |
| | | <div class="search_thing"> |
| | | <div class="search_label">ä»åºåç§°ï¼</div> |
| | | <div class="search_input"> |
| | | <el-select v-model="entity.warehouseId" placeholder="éæ©ä»åº" size="small" @change="warehouseChange"> |
| | | <el-option v-for="item in warehouse" :key="item.id" :label="item.label" :value="item.id"> |
| | | <el-select v-model="entity.warehouseId" |
| | | placeholder="éæ©ä»åº" |
| | | size="small" |
| | | @change="warehouseChange"> |
| | | <el-option v-for="item in warehouse" |
| | | :key="item.id" |
| | | :label="item.label" |
| | | :value="item.id"> |
| | | </el-option> |
| | | </el-select> |
| | | </div> |
| | |
| | | <div class="search_thing"> |
| | | <div class="search_label">è´§æ¶ï¼</div> |
| | | <div class="search_input"> |
| | | <el-select v-model="entity.shelfId" placeholder="éæ©è´§æ¶" size="small" @change="handleShelf"> |
| | | <el-option v-for="item in shelf" :key="item.id" :label="item.label" :value="item.id"> |
| | | <el-select v-model="entity.shelfId" |
| | | placeholder="éæ©è´§æ¶" |
| | | size="small" |
| | | @change="handleShelf"> |
| | | <el-option v-for="item in shelf" |
| | | :key="item.id" |
| | | :label="item.label" |
| | | :value="item.id"> |
| | | </el-option> |
| | | </el-select> |
| | | </div> |
| | |
| | | <el-button size="small" type="primary" @click="handleShelf(entity.shelfId)">æ¥è¯¢</el-button> |
| | | </div> --> |
| | | <div class="btns"> |
| | | <el-button size="small" style="color:#3A7BFA" @click="keepVisible=true">ç»´æ¤</el-button> |
| | | <el-button size="small" style="color:#3A7BFA" @click="warehouseVisible=true,isEdit=false">æ·»å ä»åº</el-button> |
| | | <el-button size="small" style="color:#3A7BFA" @click="shelvesVisible=true,isEdit=false" |
| | | <el-button size="small" |
| | | style="color:#3A7BFA" |
| | | @click="keepVisible=true">ç»´æ¤</el-button> |
| | | <el-button size="small" |
| | | style="color:#3A7BFA" |
| | | @click="warehouseVisible=true,isEdit=false">æ·»å ä»åº</el-button> |
| | | <el-button size="small" |
| | | style="color:#3A7BFA" |
| | | @click="shelvesVisible=true,isEdit=false" |
| | | :disabled="entity.warehouseId==null">æ·»å è´§æ¶</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="table" v-loading="tableLoading"> |
| | | <table class="tables" style="table-layout:fixed;" v-if="tableList.length>0"> |
| | | <div class="table" |
| | | v-loading="tableLoading"> |
| | | <table class="tables" |
| | | style="table-layout:fixed;" |
| | | v-if="tableList.length>0"> |
| | | <tbody> |
| | | <tr v-for="(item,index) in tableList" :key="index"> |
| | | <td v-for="(m,i) in item" :key="i" class="content"> |
| | | <tr v-for="(item,index) in tableList" |
| | | :key="index"> |
| | | <td v-for="(m,i) in item" |
| | | :key="i" |
| | | class="content"> |
| | | <h4 v-if="m.row!=undefined">{{ m.row }} - {{ m.col }}</h4> |
| | | <ul> |
| | | <el-tooltip |
| | | effect="dark" |
| | | <el-tooltip effect="dark" |
| | | placement="top" |
| | | v-for="(n,j) in m.documentationDtoList" |
| | | :key="j"> |
| | |
| | | </td> |
| | | </tr> |
| | | <tr> |
| | | <td v-for="(item,index) in rowList" :key="index" style="background: ghostwhite;height: 20px;">{{ item }} |
| | | <td v-for="(item,index) in rowList" |
| | | :key="index" |
| | | style="background: ghostwhite;height: 20px;">{{ item }} |
| | | </td> |
| | | </tr> |
| | | </tbody> |
| | | </table> |
| | | <span v-else style="color: rgb(144, 147, 153);display: inline-block;position: absolute;top: 60%;left: 50%;transform: translate(-50%,-50%);">ææ æ°æ®</span> |
| | | <span v-else |
| | | style="color: rgb(144, 147, 153);display: inline-block;position: absolute;top: 60%;left: 50%;transform: translate(-50%,-50%);">ææ æ°æ®</span> |
| | | </div> |
| | | </div> |
| | | <Detail v-else @hanldeBack="isDetail=false" :current="current" /> |
| | | |
| | | <Detail v-else |
| | | @hanldeBack="isDetail=false" |
| | | :current="current" /> |
| | | <!-- åºä½ç»´æ¤å¯¹è¯æ¡ --> |
| | | <el-dialog v-model="keepVisible" title="åºä½ç»´æ¤" width="350px" :append-to-body="true"> |
| | | <el-tree :data="warehouse" ref="tree" node-key="id" |
| | | highlight-current v-if="keepVisible" |
| | | <el-dialog v-model="keepVisible" |
| | | title="åºä½ç»´æ¤" |
| | | width="350px" |
| | | :append-to-body="true"> |
| | | <el-tree :data="warehouse" |
| | | ref="tree" |
| | | node-key="id" |
| | | highlight-current |
| | | v-if="keepVisible" |
| | | empty-text="ææ æ°æ®"> |
| | | <template #default="{ node, data }"> |
| | | <div class="custom-tree-node" style="width: 100%;"> |
| | | <div class="custom-tree-node" |
| | | style="width: 100%;"> |
| | | <el-row style="width: 100%;display: flex;align-items: center;"> |
| | | <el-col :span="14"> |
| | | <span> |
| | | <el-icon v-if="node.level < 2" class="folder-icon"> |
| | | <el-icon v-if="node.level < 2" |
| | | class="folder-icon"> |
| | | <FolderOpened /> |
| | | </el-icon> |
| | | <el-icon v-else class="file-icon"> |
| | | <el-icon v-else |
| | | class="file-icon"> |
| | | <Document /> |
| | | </el-icon> |
| | | {{ data.label }} |
| | | </span> |
| | | </el-col> |
| | | <el-col :span="10" v-if="node.level<3"> |
| | | <el-button type="link" size="small" :icon="Edit" @click.stop="handleEdit(data,node.level)"> |
| | | <el-col :span="10" |
| | | v-if="node.level<3"> |
| | | <el-button type="link" |
| | | size="small" |
| | | :icon="Edit" |
| | | @click.stop="handleEdit(data,node.level)"> |
| | | </el-button> |
| | | <el-button type="danger" size="small" :icon="Delete" @click.stop="handleDelete(data,node.level)"> |
| | | <el-button type="danger" |
| | | size="small" |
| | | :icon="Delete" |
| | | @click.stop="handleDelete(data,node.level)"> |
| | | </el-button> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | </el-tree> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="keepVisible = false">ç¡® å®</el-button> |
| | | <el-button @click="keepVisible = false">å æ¶</el-button> |
| | | <el-button type="primary" @click="keepVisible = false" >ç¡® å®</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- ä»åºæ°å¢/ä¿®æ¹å¯¹è¯æ¡ --> |
| | | <el-dialog v-model="warehouseVisible" :title="isEdit?'ä»åºä¿®æ¹':'ä»åºæ°å¢'" width="350px"> |
| | | <el-dialog v-model="warehouseVisible" |
| | | :title="isEdit?'ä»åºä¿®æ¹':'ä»åºæ°å¢'" |
| | | width="350px"> |
| | | <el-row> |
| | | <el-col class="search_thing" :span="24"> |
| | | <el-col class="search_thing" |
| | | :span="24"> |
| | | <div class="search_label"><span class="required-span">* </span>ä»åºåç§°ï¼</div> |
| | | <div class="search_input"> |
| | | <el-input v-model="name" size="small" @keyup.enter="confirmWarehouse"></el-input> |
| | | <el-input v-model="name" |
| | | size="small" |
| | | @keyup.enter="confirmWarehouse"></el-input> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="confirmWarehouse" |
| | | :loading="upLoadWarehouse">ç¡® å®</el-button> |
| | | <el-button @click="warehouseVisible = false">å æ¶</el-button> |
| | | <el-button type="primary" @click="confirmWarehouse" :loading="upLoadWarehouse">ç¡® å®</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- è´§æ¶æ°å¢/ä¿®æ¹å¯¹è¯æ¡ --> |
| | | <el-dialog v-model="shelvesVisible" :title="isEdit?'è´§æ¶ä¿®æ¹':'è´§æ¶æ°å¢'" width="350px"> |
| | | <el-dialog v-model="shelvesVisible" |
| | | :title="isEdit?'è´§æ¶ä¿®æ¹':'è´§æ¶æ°å¢'" |
| | | width="350px"> |
| | | <el-row> |
| | | <el-col class="search_thing" :span="24"> |
| | | <el-col class="search_thing" |
| | | :span="24"> |
| | | <div class="search_label"><span class="required-span">* </span>è´§æ¶åç§°ï¼</div> |
| | | <div class="search_input"> |
| | | <el-input v-model="shelves.name" size="small"></el-input> |
| | | <el-input v-model="shelves.name" |
| | | size="small"></el-input> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col class="search_thing" :span="24"> |
| | | <el-col class="search_thing" |
| | | :span="24"> |
| | | <div class="search_label"><span class="required-span">* </span>è´§æ¶å±æ°ï¼</div> |
| | | <div class="search_input"> |
| | | <el-input v-model="shelves.row" size="small"></el-input> |
| | | <el-input v-model="shelves.row" |
| | | size="small"></el-input> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col class="search_thing" :span="24"> |
| | | <el-col class="search_thing" |
| | | :span="24"> |
| | | <div class="search_label"><span class="required-span">* </span>è´§æ¶åæ°ï¼</div> |
| | | <div class="search_input"> |
| | | <el-input v-model="shelves.col" size="small"></el-input> |
| | | <el-input v-model="shelves.col" |
| | | size="small"></el-input> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="confirmShelves" |
| | | :loading="upLoadShelves">ç¡® å®</el-button> |
| | | <el-button @click="shelvesVisible = false">å æ¶</el-button> |
| | | <el-button type="primary" @click="confirmShelves" :loading="upLoadShelves">ç¡® å®</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted, watch } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { Edit, Delete, FolderOpened, Document } from '@element-plus/icons-vue' |
| | | import { getWarehouseList, addWarehouse, updateWarehouse, deleteWarehouse, getWarehouseStructure, addShelf, updateShelf, deleteShelf } from '@/api/fileManagement/bookshelf' |
| | | import Detail from './detail.vue' |
| | | import { ref, reactive, onMounted, watch } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import { Edit, Delete, FolderOpened, Document } from "@element-plus/icons-vue"; |
| | | import { |
| | | getWarehouseList, |
| | | addWarehouse, |
| | | updateWarehouse, |
| | | deleteWarehouse, |
| | | getWarehouseStructure, |
| | | addShelf, |
| | | updateShelf, |
| | | deleteShelf, |
| | | } from "@/api/fileManagement/bookshelf"; |
| | | import Detail from "./detail.vue"; |
| | | |
| | | // ååºå¼æ°æ® |
| | | const entity = reactive({ |
| | | warehouseId: null, |
| | | shelfId: null |
| | | }) |
| | | shelfId: null, |
| | | }); |
| | | |
| | | const warehouse = ref([]) |
| | | const shelf = ref([]) |
| | | const keepVisible = ref(false) |
| | | const warehouseVisible = ref(false) |
| | | const shelvesVisible = ref(false) |
| | | const upLoadWarehouse = ref(false) |
| | | const upLoadShelves = ref(false) |
| | | const tableList = ref([]) |
| | | const rowList = ref([]) |
| | | const value = ref('') |
| | | const name = ref('') |
| | | const shelves = reactive({}) |
| | | const isEdit = ref(false) |
| | | const isDetail = ref(false) |
| | | const currentEdit = ref(null) |
| | | const tableLoading = ref(false) |
| | | const current = ref({}) |
| | | const warehouse = ref([]); |
| | | const shelf = ref([]); |
| | | const keepVisible = ref(false); |
| | | const warehouseVisible = ref(false); |
| | | const shelvesVisible = ref(false); |
| | | const upLoadWarehouse = ref(false); |
| | | const upLoadShelves = ref(false); |
| | | const tableList = ref([]); |
| | | const rowList = ref([]); |
| | | const value = ref(""); |
| | | const name = ref(""); |
| | | const shelves = reactive({}); |
| | | const isEdit = ref(false); |
| | | const isDetail = ref(false); |
| | | const currentEdit = ref(null); |
| | | const tableLoading = ref(false); |
| | | const current = ref({}); |
| | | |
| | | // 模æ¿å¼ç¨ |
| | | const organization = ref(null) |
| | | const organization = ref(null); |
| | | |
| | | // çå¬å¨ |
| | | watch(isEdit, (newVal) => { |
| | | watch(isEdit, newVal => { |
| | | if (!newVal) { |
| | | Object.keys(shelves).forEach(key => delete shelves[key]) |
| | | Object.keys(shelves).forEach(key => delete shelves[key]); |
| | | } |
| | | }) |
| | | }); |
| | | |
| | | // æ¹æ³ |
| | | |
| | | const selectList = async () => { |
| | | // è¿ééè¦æ¿æ¢ä¸ºå®é
çAPIè°ç¨ |
| | | const res = await getWarehouseList() |
| | | warehouse.value = res.data |
| | | const res = await getWarehouseList(); |
| | | warehouse.value = res.data; |
| | | |
| | | if (warehouse.value.length == 0) { |
| | | entity.warehouseId = '' |
| | | entity.shelfId = '' |
| | | tableList.value = [] |
| | | entity.warehouseId = ""; |
| | | entity.shelfId = ""; |
| | | tableList.value = []; |
| | | } |
| | | |
| | | |
| | | |
| | | if (!entity.warehouseId && warehouse.value.length > 0) { |
| | | entity.warehouseId = warehouse.value[0].id |
| | | warehouseChange(entity.warehouseId) |
| | | entity.warehouseId = warehouse.value[0].id; |
| | | warehouseChange(entity.warehouseId); |
| | | if (shelf.value.length > 0) { |
| | | entity.shelfId = shelf.value[0].id |
| | | handleShelf(entity.shelfId) |
| | | entity.shelfId = shelf.value[0].id; |
| | | handleShelf(entity.shelfId); |
| | | } else { |
| | | tableList.value = [] |
| | | tableList.value = []; |
| | | } |
| | | } else if (warehouse.value.length > 0) { |
| | | warehouseChange(entity.warehouseId) |
| | | warehouseChange(entity.warehouseId); |
| | | if (shelf.value.length > 0) { |
| | | entity.shelfId = shelf.value[0].id |
| | | handleShelf(entity.shelfId) |
| | | entity.shelfId = shelf.value[0].id; |
| | | handleShelf(entity.shelfId); |
| | | } else { |
| | | tableList.value = [] |
| | | tableList.value = []; |
| | | } |
| | | } |
| | | } |
| | | }; |
| | | |
| | | const confirmWarehouse = () => { |
| | | if (!name.value) { |
| | | ElMessage.error('请填åä»åºåç§°') |
| | | return |
| | | ElMessage.error("请填åä»åºåç§°"); |
| | | return; |
| | | } |
| | | upLoadWarehouse.value = true |
| | | upLoadWarehouse.value = true; |
| | | |
| | | if (currentEdit.value && currentEdit.value.id) { |
| | | // ä¿®æ¹ä»åº |
| | | // è¿ééè¦æ¿æ¢ä¸ºå®é
çAPIè°ç¨ |
| | | updateWarehouse({ |
| | | id: currentEdit.value.id, |
| | | warehouseName: name.value |
| | | warehouseName: name.value, |
| | | }).then(res => { |
| | | upLoadWarehouse.value = false |
| | | warehouseVisible.value = false |
| | | currentEdit.value = null |
| | | ElMessage.success('ä¿®æ¹æå') |
| | | selectList() |
| | | name.value = '' |
| | | warehouseChange(entity.warehouseId) |
| | | }) |
| | | |
| | | upLoadWarehouse.value = false; |
| | | warehouseVisible.value = false; |
| | | currentEdit.value = null; |
| | | ElMessage.success("ä¿®æ¹æå"); |
| | | selectList(); |
| | | name.value = ""; |
| | | warehouseChange(entity.warehouseId); |
| | | }); |
| | | } else { |
| | | // æ°å¢ä»åº |
| | | // è¿ééè¦æ¿æ¢ä¸ºå®é
çAPIè°ç¨ |
| | | addWarehouse({ |
| | | warehouseName: name.value |
| | | warehouseName: name.value, |
| | | }).then(res => { |
| | | upLoadWarehouse.value = false |
| | | warehouseVisible.value = false |
| | | ElMessage.success('æ·»å æå') |
| | | selectList() |
| | | name.value = '' |
| | | warehouseChange(entity.warehouseId) |
| | | }) |
| | | upLoadWarehouse.value = false; |
| | | warehouseVisible.value = false; |
| | | ElMessage.success("æ·»å æå"); |
| | | selectList(); |
| | | name.value = ""; |
| | | warehouseChange(entity.warehouseId); |
| | | }); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | const confirmShelves = () => { |
| | | if (!shelves.name) { |
| | | ElMessage.error('请填åè´§æ¶åç§°') |
| | | return |
| | | ElMessage.error("请填åè´§æ¶åç§°"); |
| | | return; |
| | | } |
| | | if (!shelves.row) { |
| | | ElMessage.error('请填åè´§æ¶å±æ°') |
| | | return |
| | | ElMessage.error("请填åè´§æ¶å±æ°"); |
| | | return; |
| | | } |
| | | if (!shelves.col) { |
| | | ElMessage.error('请填åè´§æ¶åæ°') |
| | | return |
| | | ElMessage.error("请填åè´§æ¶åæ°"); |
| | | return; |
| | | } |
| | | upLoadShelves.value = true |
| | | upLoadShelves.value = true; |
| | | |
| | | if (currentEdit.value && currentEdit.value.id) { |
| | | // ä¿®æ¹ |
| | |
| | | name: shelves.name, |
| | | row: Number(shelves.row), |
| | | col: Number(shelves.col), |
| | | warehouseId: entity.warehouseId |
| | | }).then(res => { |
| | | upLoadShelves.value = false |
| | | shelvesVisible.value = false |
| | | ElMessage.success('ä¿®æ¹æå') |
| | | selectList() |
| | | currentEdit.value = {} |
| | | }).catch(err => { |
| | | upLoadShelves.value = false |
| | | shelvesVisible.value = false |
| | | ElMessage.error('ä¿®æ¹å¤±è´¥') |
| | | warehouseId: entity.warehouseId, |
| | | }) |
| | | |
| | | .then(res => { |
| | | upLoadShelves.value = false; |
| | | shelvesVisible.value = false; |
| | | ElMessage.success("ä¿®æ¹æå"); |
| | | selectList(); |
| | | currentEdit.value = {}; |
| | | }) |
| | | .catch(err => { |
| | | upLoadShelves.value = false; |
| | | shelvesVisible.value = false; |
| | | ElMessage.error("ä¿®æ¹å¤±è´¥"); |
| | | }); |
| | | } else { |
| | | // æ°å¢ |
| | | // è¿ééè¦æ¿æ¢ä¸ºå®é
çAPIè°ç¨ |
| | |
| | | name: shelves.name, |
| | | row: Number(shelves.row), |
| | | col: Number(shelves.col), |
| | | warehouseId: entity.warehouseId |
| | | }).then(res => { |
| | | upLoadShelves.value = false |
| | | shelvesVisible.value = false |
| | | ElMessage.success('æ·»å æå') |
| | | selectList() |
| | | Object.keys(shelves).forEach(key => delete shelves[key]) |
| | | }).catch(err => { |
| | | upLoadShelves.value = false |
| | | shelvesVisible.value = false |
| | | ElMessage.error('æ·»å 失败') |
| | | warehouseId: entity.warehouseId, |
| | | }) |
| | | .then(res => { |
| | | upLoadShelves.value = false; |
| | | shelvesVisible.value = false; |
| | | ElMessage.success("æ·»å æå"); |
| | | selectList(); |
| | | Object.keys(shelves).forEach(key => delete shelves[key]); |
| | | }) |
| | | .catch(err => { |
| | | upLoadShelves.value = false; |
| | | shelvesVisible.value = false; |
| | | ElMessage.error("æ·»å 失败"); |
| | | }); |
| | | } |
| | | warehouseChange(entity.warehouseId) |
| | | } |
| | | |
| | | |
| | | warehouseChange(entity.warehouseId); |
| | | }; |
| | | |
| | | const handleDelete = (row, level) => { |
| | | ElMessageBox.confirm('æ¯å¦å é¤å½åæ°æ®?', "è¦å", { |
| | | ElMessageBox.confirm("æ¯å¦å é¤å½åæ°æ®?", "è¦å", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning" |
| | | }).then(() => { |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | if (level == 1) { |
| | | // å é¤ä»åº |
| | | deleteWarehouse([row.id]).then(res => { |
| | | ElMessage.success('å 餿å') |
| | | selectList() |
| | | }) |
| | | ElMessage.success("å 餿å"); |
| | | selectList(); |
| | | }); |
| | | } else { |
| | | // å é¤è´§æ¶ |
| | | deleteShelf({ |
| | | id: row.id |
| | | id: row.id, |
| | | }).then(res => { |
| | | ElMessage.success('å 餿å') |
| | | selectList() |
| | | ElMessage.success("å 餿å"); |
| | | selectList(); |
| | | }); |
| | | } |
| | | warehouseChange(entity.warehouseId); |
| | | }) |
| | | } |
| | | warehouseChange(entity.warehouseId) |
| | | }).catch(() => {}) |
| | | } |
| | | .catch(() => {}); |
| | | }; |
| | | |
| | | const handleEdit = (data, level) => { |
| | | isEdit.value = true |
| | | isEdit.value = true; |
| | | if (level == 1) { |
| | | warehouseVisible.value = true |
| | | currentEdit.value = data |
| | | name.value = data.label |
| | | warehouseVisible.value = true; |
| | | currentEdit.value = data; |
| | | name.value = data.label; |
| | | } else { |
| | | shelvesVisible.value = true |
| | | currentEdit.value = data |
| | | shelvesVisible.value = true; |
| | | currentEdit.value = data; |
| | | Object.assign(shelves, { |
| | | name: data.label, |
| | | row: data.row, |
| | | col: data.col, |
| | | warehouseId: data.warehouseId |
| | | }) |
| | | warehouseId: data.warehouseId, |
| | | }); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | const handelDetail = (row) => { |
| | | current.value = row |
| | | isDetail.value = true |
| | | } |
| | | const handelDetail = row => { |
| | | current.value = row; |
| | | isDetail.value = true; |
| | | }; |
| | | |
| | | // æ ¹æ®ææ¡£ç¶æè¿å对åºçé¢è² |
| | | const getStatusColor = (status) => { |
| | | if (status === 'æ£å¸¸') { |
| | | return '#34BD66' // ç»¿è² |
| | | } else if (status === 'ååº') { |
| | | return '#F56C6C' // çº¢è² |
| | | const getStatusColor = status => { |
| | | if (status === "æ£å¸¸") { |
| | | return "#34BD66"; // ç»¿è² |
| | | } else if (status === "ååº") { |
| | | return "#F56C6C"; // çº¢è² |
| | | } |
| | | return '#606266' // é»è®¤é¢è² |
| | | } |
| | | return "#606266"; // é»è®¤é¢è² |
| | | }; |
| | | |
| | | const warehouseChange = (val) => { |
| | | tableList.value = [] |
| | | const warehouseChange = val => { |
| | | tableList.value = []; |
| | | let map = warehouse.value.find(a => { |
| | | return a && a.id === val ? a : null |
| | | }) |
| | | return a && a.id === val ? a : null; |
| | | }); |
| | | if (map && map.children) { |
| | | shelf.value = map.children |
| | | entity.shelfId = '' |
| | | shelf.value = map.children; |
| | | entity.shelfId = ""; |
| | | } else { |
| | | shelf.value = [] |
| | | shelf.value = []; |
| | | } |
| | | currentEdit.value = null |
| | | } |
| | | currentEdit.value = null; |
| | | }; |
| | | |
| | | const handleShelf = async(e) => { |
| | | const handleShelf = async e => { |
| | | if (e) { |
| | | tableLoading.value = true |
| | | let data = [] |
| | | const res = await getWarehouseStructure({warehouseGoodsShelvesId:e}) |
| | | tableLoading.value = true; |
| | | let data = []; |
| | | const res = await getWarehouseStructure({ warehouseGoodsShelvesId: e }); |
| | | if(res.code == 200){ |
| | | data = res.data.map(m=>{ |
| | | m.books = m.documentationDtoList|[] |
| | | return m |
| | | }) |
| | | m.books = m.documentationDtoList | []; |
| | | return m; |
| | | }); |
| | | }else{ |
| | | ElMessage.error(res.message) |
| | | ElMessage.error(res.message); |
| | | } |
| | | setTimeout(() => { |
| | | tableLoading.value = false |
| | | let set = new Set() |
| | | tableList.value = [] |
| | | let arr = [] |
| | | tableLoading.value = false; |
| | | let set = new Set(); |
| | | tableList.value = []; |
| | | let arr = []; |
| | | |
| | | if (data && data.length > 0) { |
| | | data.forEach(m => { |
| | | if (m && m.row && m.col) { |
| | | set.add(m.col) |
| | | set.add(m.col); |
| | | if (arr.length > 0) { |
| | | if (arr.find(n => n.row == m.row)) { |
| | | arr.push(m) |
| | | arr.push(m); |
| | | } else { |
| | | tableList.value.push(arr) |
| | | arr = [] |
| | | arr.push(m) |
| | | tableList.value.push(arr); |
| | | arr = []; |
| | | arr.push(m); |
| | | } |
| | | } else { |
| | | arr.push(m) |
| | | arr.push(m); |
| | | } |
| | | } |
| | | }) |
| | | }); |
| | | |
| | | if (arr.length > 0) { |
| | | tableList.value.push(arr) |
| | | tableList.value.push(arr); |
| | | } |
| | | } |
| | | |
| | | rowList.value = [] |
| | | rowList.value = []; |
| | | for (let i = 0; i < set.size; i++) { |
| | | rowList.value.push(`${i + 1} å`) |
| | | rowList.value.push(`${i + 1} å`); |
| | | } |
| | | console.log(6666, tableList.value,rowList.value,data) |
| | | }, 1000) |
| | | console.log(6666, tableList.value, rowList.value, data); |
| | | }, 1000); |
| | | } |
| | | } |
| | | |
| | | |
| | | }; |
| | | |
| | | // çå½å¨æ |
| | | onMounted(() => { |
| | | selectList() |
| | | }) |
| | | selectList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | |
| | | } |
| | | |
| | | li:hover i { |
| | | background: #3A7BFA; |
| | | background: #3a7bfa; |
| | | } |
| | | |
| | | li:hover .num { |
| | | color: #3A7BFA; |
| | | color: #3a7bfa; |
| | | } |
| | | |
| | | .green { |
| | | background: #E0F6EA; |
| | | background: #e0f6ea; |
| | | } |
| | | |
| | | .green i { |
| | | background: #34BD66; |
| | | background: #34bd66; |
| | | } |
| | | |
| | | .green .num { |
| | | color: #34BD66; |
| | | color: #34bd66; |
| | | } |
| | | |
| | | .el-dialog { |
| | |
| | | display: flex; |
| | | align-items: center; |
| | | font-size: 14px; |
| | | color: #3A7BFA; |
| | | color: #3a7bfa; |
| | | position: absolute; |
| | | top: 23px; |
| | | right: 54px; |
| | |
| | | |
| | | const changeDaterange = (value) => { |
| | | if (value) { |
| | | filters.entryDate = value; |
| | | filters.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD"); |
| | | filters.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD"); |
| | | } else { |
| | | filters.entryDate = null; |
| | | filters.entryDateStart = undefined; |
| | | filters.entryDateEnd = undefined; |
| | | } |
| | |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | filters.entryDate = [ |
| | | dayjs().format("YYYY-MM-DD"), |
| | | dayjs().add(1, "day").format("YYYY-MM-DD"), |
| | | ] |
| | | filters.entryDateStart = dayjs().format("YYYY-MM-DD") |
| | | filters.entryDateEnd = dayjs().add(1, "day").format("YYYY-MM-DD") |
| | | getTableData(); |
| | | }); |
| | | </script> |
| | |
| | | /> |
| | | </div> |
| | | </el-tab-pane> |
| | | |
| | | <el-tab-pane label="ææåºåº" name="manual"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title ml10">åºåºæ¥æï¼</span> |
| | | <el-date-picker |
| | | v-model="searchForm.timeStr" |
| | | type="date" |
| | | placeholder="è¯·éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | @change="handleQuery" |
| | | /> |
| | | <span class="search_title ml10">产å大类ï¼</span> |
| | | <el-input |
| | | v-model="searchForm.productCategory" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px">æç´¢</el-button> |
| | | </div> |
| | | <div> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | <el-button type="danger" plain @click="handleDelete">å é¤</el-button> |
| | | <el-button type="primary" plain @click="handlePrint">æå°</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) => row.id" |
| | | show-summary |
| | | style="width: 100%" |
| | | :summary-method="summarizeMainTable" |
| | | 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="createTime" show-overflow-tooltip width="130"/> |
| | | <el-table-column label="æ¹æ¬¡å·" prop="code" width="130" show-overflow-tooltip /> |
| | | <el-table-column label="产å大类" prop="productCategory" show-overflow-tooltip /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" show-overflow-tooltip /> |
| | | <el-table-column label="åä½" prop="unit" show-overflow-tooltip /> |
| | | <el-table-column label="ç©åç±»å" prop="itemType" show-overflow-tooltip /> |
| | | <el-table-column label="åºåºæ°é" prop="inboundNum" show-overflow-tooltip /> |
| | | <el-table-column label="åä»·(å
)" prop="taxInclusiveUnitPrice" width="150"></el-table-column> |
| | | <el-table-column label="æ»ä»·(å
)" prop="taxInclusiveTotalPrice" width="150"></el-table-column> |
| | | <el-table-column label="åºåºäºº" prop="createBy" show-overflow-tooltip /> |
| | | </el-table> |
| | | <pagination |
| | | v-show="total > 0" |
| | | :total="total" |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | :page="page.current" |
| | | :limit="page.size" |
| | | @pagination="paginationChange" |
| | | /> |
| | | </div> |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | | |
| | | <!-- æå°é¢è§å¼¹çª --> |
| | |
| | | <div v-for="(item, index) in printData" :key="index" class="print-page"> |
| | | <div class="delivery-note"> |
| | | <div class="header"> |
| | | <div class="company-name">æµ·å·å¼å¿é£åæéå
¬å¸</div> |
| | | <div class="company-name">åæ³°ä¼ä¸ï¼å¤©æ´¥ï¼æéå
¬å¸</div> |
| | | <div class="document-title">é¶å®åè´§å</div> |
| | | </div> |
| | | |
| | |
| | | } from "@/api/inventoryManagement/stockOut.js"; |
| | | import { |
| | | getStockInPageByProduct, |
| | | getStockInPageByCustom, |
| | | } from "@/api/inventoryManagement/stockIn.js"; |
| | | |
| | | const userStore = useUserStore(); |
| | |
| | | supplierName: "", |
| | | customerName: "", |
| | | productCategory:'', |
| | | timeStr: getCurrentDate(), |
| | | timeStr: '', |
| | | }, |
| | | form: { |
| | | supplierId: null, |
| | |
| | | // æ ¹æ®ä¸åç tab ç±»åè°ç¨ä¸åçæ¥å£ |
| | | const apiCall = activeTab.value === 'production' |
| | | ? getStockInPageByProduct(params) |
| | | : activeTab.value === 'manual' |
| | | ? getStockInPageByCustom(params) |
| | | : getStockOutPage(params) |
| | | |
| | | apiCall |
| | |
| | | const unitPrice = Number(item.unitPrice) || 0; |
| | | item.totalPrice = (unitPrice * inboundNum).toFixed(2); |
| | | } else { |
| | | // åæåææåºåºï¼æ»ä»· = taxInclusiveUnitPrice à inboundNum |
| | | // åæåºåºï¼æ»ä»· = taxInclusiveUnitPrice à inboundNum |
| | | const taxInclusiveUnitPrice = Number(item.taxInclusiveUnitPrice) || 0; |
| | | item.taxInclusiveTotalPrice = (taxInclusiveUnitPrice * inboundNum).toFixed(2); |
| | | } |
| | |
| | | let exportUrl = "/stockmanagement/export" |
| | | if (activeTab.value === 'production') { |
| | | exportUrl = "/stockmanagement/exportone" |
| | | } else if (activeTab.value === 'manual') { |
| | | exportUrl = "/stockmanagement/exportTwo" |
| | | } |
| | | proxy.download(exportUrl, {}, "åºåºå°è´¦.xlsx"); |
| | | }) |
| | |
| | | <div class="print-page"> |
| | | <div class="delivery-note"> |
| | | <div class="header"> |
| | | <div class="company-name">æµ·å·å¼å¿é£åæéå
¬å¸</div> |
| | | <div class="company-name">åæ³°ä¼ä¸ï¼å¤©æ´¥ï¼æéå
¬å¸</div> |
| | | <div class="document-title">é¶å®åè´§å</div> |
| | | </div> |
| | | |
| | |
| | | :page="page.current" :limit="page.size" @pagination="paginationChange" /> |
| | | </div> |
| | | </el-tab-pane> |
| | | |
| | | <el-tab-pane label="ææåºåº" name="manual"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title ml10">产å大类ï¼</span> |
| | | <el-input |
| | | v-model="searchForm.productCategory" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px">æç´¢</el-button> |
| | | </div> |
| | | <div> |
| | | <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 => row.id" show-summary style="width: 100%" |
| | | :summary-method="summarizeMainTable" 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="code" width="130" show-overflow-tooltip /> |
| | | <el-table-column label="产å大类" prop="productCategory" show-overflow-tooltip /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" show-overflow-tooltip /> |
| | | <el-table-column label="åä½" prop="unit" width="70" show-overflow-tooltip /> |
| | | <el-table-column label="ç©åç±»å" prop="itemType" show-overflow-tooltip /> |
| | | <el-table-column label="å©ä½åºå" prop="inboundNum0" width="90" show-overflow-tooltip /> |
| | | <el-table-column fixed="right" label="æä½" width="100" align="center"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" size="small" @click="openForm(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" /> |
| | | </div> |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | | <el-dialog v-model="dialogFormVisible" :title="getDialogTitle()" width="40%" @close="closeDia"> |
| | | <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef"> |
| | |
| | | import { |
| | | getStockInPage, |
| | | getStockInPageByProduction, |
| | | getStockInPageByCustom, getInPageByCustom |
| | | } from "@/api/inventoryManagement/stockIn.js"; |
| | | import { |
| | | getStockManagePage, |
| | |
| | | nickName: '', |
| | | userId: '', |
| | | productCategory:'', |
| | | timeStr: getCurrentDate(), |
| | | timeStr: '', |
| | | }, |
| | | form: { |
| | | productrecordId: '', |
| | |
| | | let apiCall |
| | | if (activeTab.value === 'production') { |
| | | apiCall = getStockInPageByProduction(params) |
| | | } else if (activeTab.value === 'manual') { |
| | | apiCall = getInPageByCustom(params) |
| | | } else { |
| | | apiCall = getStockInPage(params) |
| | | } |
| | |
| | | } |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | if (valid && currentRowId.value) { |
| | | const typeMap = { production: 2, purchase: 1, manual: 3 } |
| | | const typeMap = { production: 2, purchase: 1 } |
| | | const outData = { |
| | | id: currentRowId.value, // åå§è®°å½ID |
| | | salesLedgerProductId: activeTab.value === 'manual' ? 0 : salesLedgerProductId.value, |
| | | salesLedgerProductId: salesLedgerProductId.value, |
| | | quantity: form.value.inboundQuantity, // åºåºæ°é |
| | | time: form.value.inboundTime, // åºåºæ¶é´ |
| | | userId: form.value.nickName, // æä½äºº |
| | | type: typeMap[activeTab.value] // åºåºç±»åï¼éè´1ï¼ç产2ï¼èªå®ä¹3 |
| | | type: typeMap[activeTab.value] // åºåºç±»åï¼éè´1ï¼ç产2 |
| | | } |
| | | console.log(outData) |
| | | |
| | |
| | | let exportUrl = "/stockin/export" |
| | | if (activeTab.value === 'production') { |
| | | exportUrl = "/stockin/exportOne" |
| | | } else if (activeTab.value === 'manual') { |
| | | exportUrl = "/stockin/exportTwo" |
| | | } |
| | | proxy.download(exportUrl, {}, 'å
¥åºå°è´¦.xlsx') |
| | | }).catch(() => { |
| | |
| | | const getDialogTitle = () => { |
| | | const titleMap = { |
| | | production: 'æ°å¢åè´§', |
| | | purchase: 'æ°å¢é¢ç¨', |
| | | manual: 'æ°å¢é¢ç¨' |
| | | purchase: 'æ°å¢é¢ç¨' |
| | | }; |
| | | return titleMap[activeTab.value] || 'æ°å¢åºåº'; |
| | | }; |
| | |
| | | const getAvailableQuantityText = () => { |
| | | const textMap = { |
| | | production: 'å¯åè´§æ°é', |
| | | purchase: 'å¯é¢ç¨æ°é', |
| | | manual: 'å¯é¢ç¨æ°é' |
| | | purchase: 'å¯é¢ç¨æ°é' |
| | | }; |
| | | return textMap[activeTab.value] || 'å¯åºåºæ°é'; |
| | | }; |
| | |
| | | const getQuantityLabel = () => { |
| | | const labelMap = { |
| | | production: 'åè´§æ°éï¼', |
| | | purchase: 'é¢ç¨æ°éï¼', |
| | | manual: 'é¢ç¨æ°éï¼' |
| | | purchase: 'é¢ç¨æ°éï¼' |
| | | }; |
| | | return labelMap[activeTab.value] || 'åºåºæ°éï¼'; |
| | | }; |
| | |
| | | const getDateLabel = () => { |
| | | const labelMap = { |
| | | production: 'åè´§æ¥æï¼', |
| | | purchase: 'é¢ç¨æ¥æï¼', |
| | | manual: 'é¢ç¨æ¥æï¼' |
| | | purchase: 'é¢ç¨æ¥æï¼' |
| | | }; |
| | | return labelMap[activeTab.value] || 'åºåºæ¥æï¼'; |
| | | }; |
| | |
| | | const getPersonLabel = () => { |
| | | const labelMap = { |
| | | production: 'å货人ï¼', |
| | | purchase: 'é¢ç¨äººï¼', |
| | | manual: 'é¢ç¨äººï¼' |
| | | purchase: 'é¢ç¨äººï¼' |
| | | }; |
| | | return labelMap[activeTab.value] || 'åºåºäººï¼'; |
| | | }; |
| | |
| | | :page="page.current" :limit="page.size" @pagination="paginationChange" /> |
| | | </div> |
| | | </el-tab-pane> |
| | | |
| | | <el-tab-pane label="ææå
¥åº" name="manual"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title ml10">å
¥åºæ¥æï¼</span> |
| | | <el-date-picker |
| | | v-model="searchForm.timeStr" |
| | | type="date" |
| | | placeholder="è¯·éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | @change="handleQuery" |
| | | /> |
| | | <span class="search_title ml10">产å大类ï¼</span> |
| | | <el-input |
| | | v-model="searchForm.productCategory" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px">æç´¢</el-button> |
| | | </div> |
| | | <div> |
| | | <el-button type="primary" @click="openForm('add', 'manual')">æ°å¢å
¥åº</el-button> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | <el-button type="danger" plain @click="handleDelete">å é¤</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 => row.id" show-summary style="width: 100%" |
| | | :summary-method="summarizeMainTable" 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="inboundDate" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="æ¹æ¬¡å·" prop="code" width="130" show-overflow-tooltip /> |
| | | <el-table-column label="产å大类" prop="productCategory" show-overflow-tooltip /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" show-overflow-tooltip /> |
| | | <el-table-column label="åä½" prop="unit" width="70" show-overflow-tooltip /> |
| | | <el-table-column label="ç©åç±»å" prop="itemType" show-overflow-tooltip /> |
| | | <el-table-column label="å
¥åºæ°é" prop="inboundNum" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="å©ä½åºå" prop="inboundNum0" show-overflow-tooltip /> |
| | | <el-table-column label="åä»·(å
)" prop="taxInclusiveUnitPrice" width="150"></el-table-column> |
| | | <el-table-column label="æ»ä»·(å
)" prop="taxInclusiveTotalPrice" width="150"></el-table-column> |
| | | <el-table-column label="å
¥åºäºº" prop="createBy" width="80" show-overflow-tooltip /> |
| | | <el-table-column fixed="right" label="æä½" width="100" align="center"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" size="small" @click="openForm('edit', scope.row, 'manual');">ç¼è¾</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" /> |
| | | </div> |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | | |
| | | <form-dia ref="formDia" @close="handleQuery" @success="handleQuery"></form-dia> |
| | | <form-dia-manual ref="formDiaManual" @close="handleQuery" @success="handleQuery"></form-dia-manual> |
| | | <form-dia-product ref="formDiaProduct" @close="handleQuery" @success="handleQuery"></form-dia-product> |
| | | </div> |
| | | </template> |
| | |
| | | getStockInPage, |
| | | getStockInPageByProduction, |
| | | delStockIn, |
| | | delStockInCustom, getInPageByCustom, |
| | | } from "@/api/inventoryManagement/stockIn.js"; |
| | | import FormDia from './components/formDia.vue' |
| | | import FormDiaManual from './components/formDiaManual.vue' |
| | | import FormDiaProduct from './components/formDiaProduct.vue' |
| | | |
| | | // è·åå½åæ¥æ |
| | |
| | | const selectedRows = ref([]) |
| | | const tableLoading = ref(false) |
| | | const formDia = ref() |
| | | const formDiaManual = ref() |
| | | const formDiaProduct = ref() |
| | | const activeTab = ref('production') // å½åæ¿æ´»ç tab |
| | | |
| | |
| | | supplierName: '', |
| | | customerName: '', |
| | | productCategory:'', |
| | | timeStr: getCurrentDate(), |
| | | timeStr: '', |
| | | }, |
| | | }) |
| | | const { searchForm } = toRefs(data) |
| | |
| | | // æ ¹æ®ä¸åç tab ç±»åè°ç¨ä¸åçæ¥å£ |
| | | const apiCall = activeTab.value === 'production' |
| | | ? getStockInPageByProduction(params) |
| | | : activeTab.value === 'manual' |
| | | ? getInPageByCustom(params) |
| | | : getStockInPage(params) |
| | | |
| | | apiCall.then(res => { |
| | |
| | | const openForm = async (type, row, tabType) => { |
| | | const currentTab = tabType || activeTab.value |
| | | await nextTick(() => { |
| | | if (currentTab === 'manual') { |
| | | formDiaManual.value?.openDialog(type, row) |
| | | } else if (currentTab === 'production') { |
| | | if (currentTab === 'production') { |
| | | formDiaProduct.value?.openDialog(type, row) |
| | | }else { |
| | | formDia.value?.openDialog(type, row) |
| | |
| | | let exportUrl = "/stockin/export" |
| | | if (activeTab.value === 'production') { |
| | | exportUrl = "/stockin/exportOne" |
| | | } else if (activeTab.value === 'manual') { |
| | | exportUrl = "/stockin/exportTwo" |
| | | } |
| | | proxy.download(exportUrl, {}, 'å
¥åºå°è´¦.xlsx') |
| | | }).catch(() => { |
| | |
| | | // æåå é¤ï¼typeä¼ 2 |
| | | deleteApi = delStockIn |
| | | deleteParams = { ids, type: 2 } |
| | | } else if (activeTab.value === 'purchase') { |
| | | } else { |
| | | // åæå é¤ï¼typeä¼ 1 |
| | | deleteApi = delStockIn |
| | | deleteParams = { ids, type: 1 } |
| | | } else { |
| | | // ææå
¥åº |
| | | deleteApi = delStockInCustom |
| | | deleteParams = { ids } |
| | | } |
| | | |
| | | deleteApi(deleteParams).then(() => { |
| | |
| | | :page="page.current" :limit="page.size" @pagination="paginationChange" /> |
| | | </div> |
| | | </el-tab-pane> |
| | | |
| | | <el-tab-pane label="ææåºå" name="manual"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title ml10">å
¥åºæ¥æï¼</span> |
| | | <el-date-picker |
| | | v-model="searchForm.timeStr" |
| | | type="date" |
| | | placeholder="è¯·éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | @change="handleQuery" |
| | | /> |
| | | <span class="search_title ml10">产å大类ï¼</span> |
| | | <el-input |
| | | v-model="searchForm.productCategory" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px">æç´¢</el-button> |
| | | </div> |
| | | <div> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | <!-- <el-button type="danger" plain @click="handleDelete">å é¤</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 => row.id" show-summary style="width: 100%" |
| | | :row-class-name="tableRowClassName" |
| | | :summary-method="summarizeMainTable" 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="inboundDate" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="æ¹æ¬¡å·" prop="code" width="130" show-overflow-tooltip /> |
| | | <el-table-column label="产å大类" prop="productCategory" show-overflow-tooltip /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" show-overflow-tooltip /> |
| | | <el-table-column label="åä½" prop="unit" width="80" show-overflow-tooltip /> |
| | | <el-table-column label="ç©åç±»å" prop="itemType" width="120" show-overflow-tooltip /> |
| | | <el-table-column label="å·²åºåºæ°é" prop="totalInboundNum" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="å©ä½åºå" prop="inboundNum0" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="åä»·(å
)" prop="taxInclusiveUnitPrice" width="150"></el-table-column> |
| | | <el-table-column label="æ»ä»·(å
)" prop="taxInclusiveTotalPrice" width="150"></el-table-column> |
| | | <el-table-column fixed="right" label="æä½" width="100" align="center"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" size="small" @click="openForm('edit', 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" /> |
| | | </div> |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | | |
| | | <!-- æååºåå¼¹æ¡ --> |
| | |
| | | @submit="submitForm" |
| | | @close="closeDia" |
| | | /> |
| | | |
| | | <!-- ææåºåå¼¹æ¡ --> |
| | | <FormDiaManual |
| | | v-model:dialogFormVisible="manualDialogVisible" |
| | | :operationType="operationType" |
| | | :formData="form" |
| | | @submit="submitForm" |
| | | @close="closeDia" |
| | | /> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | import { |
| | | getStockManagePage, |
| | | getStockManagePageByProduction, |
| | | getStockManagePageByCustom, |
| | | delStockManage, |
| | | } from "@/api/inventoryManagement/stockManage.js"; |
| | | import { |
| | | updateManagement, updateManagementByCustom, updateStockIn |
| | | } from "@/api/inventoryManagement/stockIn.js"; |
| | | |
| | | // 导å
¥ä¸ä¸ªç¬ç«çå¼¹æ¡ç»ä»¶ |
| | | // 导å
¥ä¸¤ä¸ªç¬ç«çå¼¹æ¡ç»ä»¶ |
| | | import FormDiaProduction from './components/FormDiaProduction.vue' |
| | | import FormDiaPurchase from './components/FormDiaPurchase.vue' |
| | | import FormDiaManual from './components/FormDiaManual.vue' |
| | | |
| | | const userStore = useUserStore() |
| | | const { proxy } = getCurrentInstance() |
| | |
| | | const operationType = ref('') |
| | | const activeTab = ref('production') |
| | | |
| | | // ä¸ä¸ªç¬ç«çå¼¹æ¡æ¾ç¤ºç¶æ |
| | | // å¼¹æ¡æ¾ç¤ºç¶æ |
| | | const productionDialogVisible = ref(false) |
| | | const purchaseDialogVisible = ref(false) |
| | | const manualDialogVisible = ref(false) |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | // supplierName: '', |
| | | productCategory:'', |
| | | customerName: '', |
| | | timeStr: getCurrentDate(), |
| | | timeStr: '', |
| | | }, |
| | | form: { |
| | | supplierId: null, |
| | |
| | | const getList = () => { |
| | | tableLoading.value = true |
| | | const params = buildQueryParams() |
| | | let apiCall |
| | | if (activeTab.value === 'production') { |
| | | apiCall = getStockManagePageByProduction(params) |
| | | } else if (activeTab.value === 'manual') { |
| | | apiCall = getStockManagePageByCustom(params) |
| | | } else { |
| | | apiCall = getStockManagePage(params) |
| | | } |
| | | const apiCall = activeTab.value === 'production' |
| | | ? getStockManagePageByProduction(params) |
| | | : getStockManagePage(params) |
| | | apiCall.then(res => { |
| | | tableLoading.value = false |
| | | tableData.value = res.data.records |
| | |
| | | item.totalPrice = (unitPrice * remainingStock).toFixed(2) |
| | | } else if (activeTab.value === 'purchase') { |
| | | // åæåºåï¼å«ç¨æ»ä»· = å«ç¨åä»· à å©ä½åºå |
| | | const taxInclusiveUnitPrice = parseFloat(item.taxInclusiveUnitPrice) || 0 |
| | | item.taxInclusiveTotalPrice = (taxInclusiveUnitPrice * remainingStock).toFixed(2) |
| | | } else if (activeTab.value === 'manual') { |
| | | // ææåºåï¼å«ç¨æ»ä»· = å«ç¨åä»· à å©ä½åºå |
| | | const taxInclusiveUnitPrice = parseFloat(item.taxInclusiveUnitPrice) || 0 |
| | | item.taxInclusiveTotalPrice = (taxInclusiveUnitPrice * remainingStock).toFixed(2) |
| | | } |
| | |
| | | productionDialogVisible.value = true |
| | | } else if (activeTab.value === 'purchase') { |
| | | purchaseDialogVisible.value = true |
| | | } else if (activeTab.value === 'manual') { |
| | | manualDialogVisible.value = true |
| | | } |
| | | } |
| | | |
| | |
| | | } else if (activeTab.value === 'purchase') { |
| | | // åæåºåï¼ç§»é¤å«ç¨æ»ä»·å段 |
| | | delete submitData.taxInclusiveTotalPrice |
| | | } else if (activeTab.value === 'manual') { |
| | | // ææåºåï¼ç§»é¤å«ç¨æ»ä»·å段 |
| | | delete submitData.taxInclusiveTotalPrice |
| | | } |
| | | |
| | | // ç§»é¤å
¶ä»å¯è½çæ»ä»·å段 |
| | |
| | | if (activeTab.value === 'production') { |
| | | // æååºåä½¿ç¨ updateManagement æ¥å£ |
| | | apiCall = updateManagement(submitData) |
| | | } else if (activeTab.value === 'manual') { |
| | | // ææåºåä½¿ç¨ updateManagementByCustom æ¥å£ |
| | | apiCall = updateManagementByCustom(submitData) |
| | | } else { |
| | | // åæåºåä½¿ç¨ updateManagementByCustom æ¥å£ |
| | | apiCall = updateManagementByCustom(submitData) |
| | |
| | | proxy.resetForm("formRef") |
| | | productionDialogVisible.value = false |
| | | purchaseDialogVisible.value = false |
| | | manualDialogVisible.value = false |
| | | } |
| | | |
| | | // å¯¼åº |
| | |
| | | let exportUrl = "/stockin/exportCopy" |
| | | if (activeTab.value === 'production') { |
| | | exportUrl = "/stockin/exportCopyOne" |
| | | } else if (activeTab.value === 'manual') { |
| | | exportUrl = "/stockin/exportCopyTwo" |
| | | } |
| | | proxy.download(exportUrl, exportParams, 'åºåä¿¡æ¯.xlsx') |
| | | }).catch(() => { |
| | |
| | | |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button @click="closeDialog">åæ¶</el-button> |
| | | <el-button type="primary" @click="submitForm">确认</el-button> |
| | | <el-button @click="closeDialog">åæ¶</el-button> |
| | | |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | |
| | | <template> |
| | | <div class="milestone-list-container"> |
| | | <el-timeline> |
| | | <el-timeline-item |
| | | v-for="milestone in milestoneList" |
| | | <el-timeline-item v-for="milestone in milestoneList" |
| | | :key="milestone.phaseId" |
| | | :timestamp="milestone.endDate" |
| | | > |
| | | :timestamp="milestone.endDate"> |
| | | <el-card> |
| | | <template #header> |
| | | <div class="card-header"> |
| | | <span>{{ milestone.phaseName }}</span> |
| | | <div class="milestone-actions"> |
| | | <el-button type="text" size="small" @click="handleEdit(milestone)">ç¼è¾</el-button> |
| | | <el-button type="text" size="small" @click="handleDelete(milestone)" danger>å é¤</el-button> |
| | | <el-button type="text" |
| | | size="small" |
| | | @click="handleEdit(milestone)">ç¼è¾</el-button> |
| | | <el-button type="text" |
| | | size="small" |
| | | @click="handleDelete(milestone)" |
| | | danger>å é¤</el-button> |
| | | </div> |
| | | </div> |
| | | </template> |
| | |
| | | </el-card> |
| | | </el-timeline-item> |
| | | </el-timeline> |
| | | |
| | | <!-- æ éç¨ç¢æ¶çæç¤º --> |
| | | <div v-if="milestoneList.length === 0" class="empty-tip"> |
| | | <div v-if="milestoneList.length === 0" |
| | | class="empty-tip"> |
| | | <el-empty description="ææ éç¨ç¢æ°æ®" /> |
| | | </div> |
| | | |
| | | <!-- ç¼è¾éç¨ç¢å¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | v-model="dialogVisible" |
| | | <el-dialog v-model="dialogVisible" |
| | | :title="'ç¼è¾éç¨ç¢: ' + (form.phaseName || '')" |
| | | width="600px" |
| | | :close-on-click-modal="false" |
| | | > |
| | | <el-form |
| | | ref="formRef" |
| | | :close-on-click-modal="false"> |
| | | <el-form ref="formRef" |
| | | :model="form" |
| | | :rules="rules" |
| | | label-width="100px" |
| | | > |
| | | <el-form-item label="éç¨ç¢åç§°" prop="phaseName"> |
| | | <el-input v-model="form.phaseName" placeholder="请è¾å
¥éç¨ç¢åç§°" /> |
| | | label-width="100px"> |
| | | <el-form-item label="éç¨ç¢åç§°" |
| | | prop="phaseName"> |
| | | <el-input v-model="form.phaseName" |
| | | placeholder="请è¾å
¥éç¨ç¢åç§°" /> |
| | | </el-form-item> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å¼å§æ¥æ" prop="startDate"> |
| | | <el-date-picker |
| | | v-model="form.startDate" |
| | | <el-form-item label="å¼å§æ¥æ" |
| | | prop="startDate"> |
| | | <el-date-picker v-model="form.startDate" |
| | | type="date" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | placeholder="éæ©å¼å§æ¥æ" |
| | | style="width: 100%" |
| | | /> |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç»ææ¥æ" prop="endDate"> |
| | | <el-date-picker |
| | | v-model="form.endDate" |
| | | <el-form-item label="ç»ææ¥æ" |
| | | prop="endDate"> |
| | | <el-date-picker v-model="form.endDate" |
| | | type="date" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | placeholder="éæ©ç»ææ¥æ" |
| | | style="width: 100%" |
| | | /> |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-form-item label="ç¶æ" prop="status"> |
| | | <el-select v-model="form.status" placeholder="è¯·éæ©ç¶æ"> |
| | | <el-option label="æªå¼å§" value="notStarted" /> |
| | | <el-option label="已宿" value="completed" /> |
| | | <el-option label="已延è¿" value="delayed" /> |
| | | <el-form-item label="ç¶æ" |
| | | prop="status"> |
| | | <el-select v-model="form.status" |
| | | placeholder="è¯·éæ©ç¶æ"> |
| | | <el-option label="æªå¼å§" |
| | | value="notStarted" /> |
| | | <el-option label="已宿" |
| | | value="completed" /> |
| | | <el-option label="已延è¿" |
| | | value="delayed" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="submitEditForm">ç¡®å®</el-button> |
| | | <el-button @click="dialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="submitEditForm">ç¡®å®</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted, watch, reactive } from 'vue'; |
| | | import { ElMessage, ElMessageBox } from 'element-plus'; |
| | | import { getProject, listProjectPhase, updateProjectPhase,delProjectPhase } from '@/api/oaSystem/projectManagement'; |
| | | import { ref, onMounted, watch, reactive } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import { |
| | | getProject, |
| | | listProjectPhase, |
| | | updateProjectPhase, |
| | | delProjectPhase, |
| | | } from "@/api/oaSystem/projectManagement"; |
| | | |
| | | const props = defineProps({ |
| | | projectId: { |
| | | type: String, |
| | | required: true |
| | | } |
| | | required: true, |
| | | }, |
| | | }); |
| | | |
| | | const emit = defineEmits(['refresh']); |
| | | const emit = defineEmits(["refresh"]); |
| | | |
| | | const milestoneList = ref([]); |
| | | const dialogVisible = ref(false); |
| | | const formRef = ref(null); |
| | | const form = reactive({ |
| | | phaseId: '', |
| | | phaseName: '', |
| | | startDate: '', |
| | | endDate: '', |
| | | status: 'notStarted', |
| | | projectId: props.projectId |
| | | phaseId: "", |
| | | phaseName: "", |
| | | startDate: "", |
| | | endDate: "", |
| | | status: "notStarted", |
| | | projectId: props.projectId, |
| | | }); |
| | | |
| | | // 表åéªè¯è§å |
| | | const rules = { |
| | | phaseName: [ |
| | | { required: true, message: '请è¾å
¥éç¨ç¢åç§°', trigger: 'blur' }, |
| | | { min: 2, max: 50, message: 'é¿åº¦å¨ 2 å° 50 个å符', trigger: 'blur' } |
| | | { required: true, message: "请è¾å
¥éç¨ç¢åç§°", trigger: "blur" }, |
| | | { min: 2, max: 50, message: "é¿åº¦å¨ 2 å° 50 个å符", trigger: "blur" }, |
| | | ], |
| | | status: [ |
| | | { required: true, message: 'è¯·éæ©ç¶æ', trigger: 'change' } |
| | | ] |
| | | status: [{ required: true, message: "è¯·éæ©ç¶æ", trigger: "change" }], |
| | | }; |
| | | |
| | | // è·åéç¨ç¢å表 |
| | |
| | | milestoneList.value = res.data.rows || res.data; |
| | | // æç®æ æ¥ææåº |
| | | // milestoneList.value.sort((a, b) => new Date(a.endDate) - new Date(b.endDate)); |
| | | }) |
| | | }); |
| | | } catch (error) { |
| | | ElMessage.error('è·åéç¨ç¢å表失败'); |
| | | console.error('è·åéç¨ç¢å表失败:', error); |
| | | ElMessage.error("è·åéç¨ç¢å表失败"); |
| | | console.error("è·åéç¨ç¢å表失败:", error); |
| | | } |
| | | }; |
| | | |
| | | // ç¼è¾éç¨ç¢ |
| | | const handleEdit = (milestone) => { |
| | | const handleEdit = milestone => { |
| | | // å¤å¶éç¨ç¢æ°æ®å°è¡¨å |
| | | Object.assign(form, { |
| | | phaseId: milestone.phaseId, |
| | |
| | | description: milestone.description, |
| | | endDate: milestone.endDate, |
| | | status: milestone.status, |
| | | projectId: props.projectId |
| | | projectId: props.projectId, |
| | | }); |
| | | dialogVisible.value = true; |
| | | }; |
| | |
| | | const res = await updateProjectPhase(form); |
| | | |
| | | if (res.code === 200) { |
| | | ElMessage.success('éç¨ç¢ç¼è¾æå'); |
| | | ElMessage.success("éç¨ç¢ç¼è¾æå"); |
| | | dialogVisible.value = false; |
| | | getMilestoneList(); // å·æ°å表 |
| | | emit('refresh'); // éç¥ç¶ç»ä»¶å·æ° |
| | | emit("refresh"); // éç¥ç¶ç»ä»¶å·æ° |
| | | } else { |
| | | ElMessage.error(res.msg || 'éç¨ç¢ç¼è¾å¤±è´¥'); |
| | | ElMessage.error(res.msg || "éç¨ç¢ç¼è¾å¤±è´¥"); |
| | | } |
| | | } catch (error) { |
| | | if (error.name === 'ValidationError') { |
| | | if (error.name === "ValidationError") { |
| | | // 表åéªè¯å¤±è´¥ï¼Element Plusä¼èªå¨æç¤º |
| | | return; |
| | | } |
| | | ElMessage.error('éç¨ç¢ç¼è¾å¤±è´¥'); |
| | | console.error('ç¼è¾éç¨ç¢å¤±è´¥:', error); |
| | | ElMessage.error("éç¨ç¢ç¼è¾å¤±è´¥"); |
| | | console.error("ç¼è¾éç¨ç¢å¤±è´¥:", error); |
| | | } |
| | | }; |
| | | |
| | | // å é¤éç¨ç¢ |
| | | const handleDelete = (milestone) => { |
| | | const handleDelete = milestone => { |
| | | ElMessageBox.confirm( |
| | | `ç¡®å®è¦å é¤éç¨ç¢ "${milestone.phaseName}" åï¼å é¤åå°æ æ³æ¢å¤ã`, |
| | | 'å é¤ç¡®è®¤', |
| | | "å é¤ç¡®è®¤", |
| | | { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | } |
| | | ) |
| | | .then(async () => { |
| | |
| | | const res = await delProjectPhase(milestone.phaseId); |
| | | |
| | | if (res.code === 200) { |
| | | ElMessage.success('éç¨ç¢å 餿å'); |
| | | ElMessage.success("éç¨ç¢å 餿å"); |
| | | getMilestoneList(); // å·æ°å表 |
| | | emit('refresh'); // éç¥ç¶ç»ä»¶å·æ° |
| | | emit("refresh"); // éç¥ç¶ç»ä»¶å·æ° |
| | | } else { |
| | | ElMessage.error(res.msg || 'éç¨ç¢å é¤å¤±è´¥'); |
| | | ElMessage.error(res.msg || "éç¨ç¢å é¤å¤±è´¥"); |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error('éç¨ç¢å é¤å¤±è´¥'); |
| | | console.error('å é¤éç¨ç¢å¤±è´¥:', error); |
| | | ElMessage.error("éç¨ç¢å é¤å¤±è´¥"); |
| | | console.error("å é¤éç¨ç¢å¤±è´¥:", error); |
| | | } |
| | | }) |
| | | .catch(() => { |
| | | // ç¨æ·åæ¶å é¤ |
| | | ElMessage.info('已忶å é¤'); |
| | | ElMessage.info("已忶å é¤"); |
| | | }); |
| | | }; |
| | | |
| | | // è·åç¶ææ ç¾ç±»å |
| | | const getStatusType = (status) => { |
| | | const getStatusType = status => { |
| | | const statusTypeMap = { |
| | | notStarted: 'info', |
| | | completed: 'success', |
| | | delayed: 'danger' |
| | | notStarted: "info", |
| | | completed: "success", |
| | | delayed: "danger", |
| | | }; |
| | | return statusTypeMap[status] || 'default'; |
| | | return statusTypeMap[status] || "default"; |
| | | }; |
| | | |
| | | // è·åç¶æææ¬ |
| | | const getStatusText = (status) => { |
| | | const getStatusText = status => { |
| | | const statusTextMap = { |
| | | notStarted: 'æªå¼å§', |
| | | completed: '已宿', |
| | | delayed: '已延è¿' |
| | | notStarted: "æªå¼å§", |
| | | completed: "已宿", |
| | | delayed: "已延è¿", |
| | | }; |
| | | return statusTextMap[status] || status; |
| | | }; |
| | | |
| | | // çå¬é¡¹ç®IDåå |
| | | watch(() => props.projectId, () => { |
| | | watch( |
| | | () => props.projectId, |
| | | () => { |
| | | if (props.projectId) { |
| | | getMilestoneList(); |
| | | } |
| | | }); |
| | | } |
| | | ); |
| | | |
| | | // åå§å |
| | | onMounted(() => { |
| | |
| | | <div class="task-tree-container"> |
| | | <!-- 任塿 æä½æé® --> |
| | | <div class="tree-actions mb10"> |
| | | <el-button type="primary" size="small" icon="Plus" @click="handleAddTask">æ·»å ä»»å¡</el-button> |
| | | <el-button type="success" size="small" icon="RefreshRight" @click="refreshTree">å·æ°</el-button> |
| | | <el-button type="info" size="small" icon="Filter" @click="toggleFilter"> |
| | | <el-button type="primary" |
| | | size="small" |
| | | icon="Plus" |
| | | @click="handleAddTask">æ·»å ä»»å¡</el-button> |
| | | <el-button type="success" |
| | | size="small" |
| | | icon="RefreshRight" |
| | | @click="refreshTree">å·æ°</el-button> |
| | | <el-button type="info" |
| | | size="small" |
| | | icon="Filter" |
| | | @click="toggleFilter"> |
| | | {{ showFilter ? 'éèçé' : 'æ¾ç¤ºçé' }} |
| | | </el-button> |
| | | </div> |
| | | |
| | | <!-- ç鿡件 --> |
| | | <div v-if="showFilter" class="filter-section mb10"> |
| | | <el-form :inline="true" :model="filterParams"> |
| | | <div v-if="showFilter" |
| | | class="filter-section mb10"> |
| | | <el-form :inline="true" |
| | | :model="filterParams"> |
| | | <el-form-item label="ä»»å¡ç¶æ"> |
| | | <el-select v-model="filterParams.status" placeholder="å
¨é¨" clearable style="width: 120px"> |
| | | <el-option label="æªå¼å§" value="notStarted" /> |
| | | <el-option label="è¿è¡ä¸" value="inProgress" /> |
| | | <el-option label="已宿" value="completed" /> |
| | | <el-option label="已龿" value="overdue" /> |
| | | <el-select v-model="filterParams.status" |
| | | placeholder="å
¨é¨" |
| | | clearable |
| | | style="width: 120px"> |
| | | <el-option label="æªå¼å§" |
| | | value="notStarted" /> |
| | | <el-option label="è¿è¡ä¸" |
| | | value="inProgress" /> |
| | | <el-option label="已宿" |
| | | value="completed" /> |
| | | <el-option label="已龿" |
| | | value="overdue" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="è´è´£äºº"> |
| | | <el-input v-model="filterParams.assignee" placeholder="è¾å
¥è´è´£äºº" clearable style="width: 150px" /> |
| | | <el-input v-model="filterParams.assignee" |
| | | placeholder="è¾å
¥è´è´£äºº" |
| | | clearable |
| | | style="width: 150px" /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" size="small" @click="filterTree">çé</el-button> |
| | | <el-button size="small" @click="resetFilter">éç½®</el-button> |
| | | <el-button type="primary" |
| | | size="small" |
| | | @click="filterTree">çé</el-button> |
| | | <el-button size="small" |
| | | @click="resetFilter">éç½®</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | |
| | | <!-- 任塿 --> |
| | | <div class="tree-content"> |
| | | <el-tree |
| | | v-loading="loading" |
| | | <el-tree v-loading="loading" |
| | | :data="taskTreeData" |
| | | :props="defaultProps" |
| | | :expand-on-click-node="false" |
| | | node-key="nodeId" |
| | | ref="treeRef" |
| | | @node-contextmenu="handleContextMenu" |
| | | @node-click="handleNodeClick" |
| | | > |
| | | @node-click="handleNodeClick"> |
| | | <template #default="{ node, data }"> |
| | | <!-- èç¹å
容 --> |
| | | <div class="tree-node-content" :class="{ 'phase-node': data.type === 'phase', 'task-node': data.type === 'task' }"> |
| | | <div class="tree-node-content" |
| | | :class="{ 'phase-node': data.type === 'phase', 'task-node': data.type === 'task' }"> |
| | | <!-- èç¹å¾æ --> |
| | | <div class="node-icon"> |
| | | <i v-if="data.type === 'phase'" class="el-icon-folder text-primary" /> |
| | | <i v-else-if="data.status === 'completed'" class="el-icon-circle-check text-success" /> |
| | | <i v-else-if="data.status === 'inProgress'" class="el-icon-circle-check text-primary" /> |
| | | <i v-else-if="data.status === 'overdue'" class="el-icon-alarm-clock text-danger" /> |
| | | <i v-else class="el-icon-circle-close text-gray-400" /> |
| | | <i v-if="data.type === 'phase'" |
| | | class="el-icon-folder text-primary" /> |
| | | <i v-else-if="data.status === 'completed'" |
| | | class="el-icon-circle-check text-success" /> |
| | | <i v-else-if="data.status === 'inProgress'" |
| | | class="el-icon-circle-check text-primary" /> |
| | | <i v-else-if="data.status === 'overdue'" |
| | | class="el-icon-alarm-clock text-danger" /> |
| | | <i v-else |
| | | class="el-icon-circle-close text-gray-400" /> |
| | | </div> |
| | | |
| | | <!-- èç¹æ é¢åæè¿° --> |
| | | <div class="node-info"> |
| | | <div class="node-title" :class="{ 'overdue-title': data.type === 'task' && data.status === 'overdue' }"> |
| | | <div class="node-title" |
| | | :class="{ 'overdue-title': data.type === 'task' && data.status === 'overdue' }"> |
| | | {{ node.label }} |
| | | <span v-if="data.type === 'task' && data.priority === 'high'" class="priority-tag">é«ä¼</span> |
| | | <span v-else-if="data.type === 'task' && data.priority === 'medium'" class="priority-tag medium">ä¸ä¼</span> |
| | | <span v-if="data.type === 'task' && data.priority === 'high'" |
| | | class="priority-tag">é«ä¼</span> |
| | | <span v-else-if="data.type === 'task' && data.priority === 'medium'" |
| | | class="priority-tag medium">ä¸ä¼</span> |
| | | </div> |
| | | <div v-if="data.description" class="node-description">{{ data.description }}</div> |
| | | |
| | | <div v-if="data.description" |
| | | class="node-description">{{ data.description }}</div> |
| | | <!-- ä»»å¡å
ä¿¡æ¯ --> |
| | | <div v-if="data.type === 'task'" class="task-meta"> |
| | | <div v-if="data.type === 'task'" |
| | | class="task-meta"> |
| | | <span class="meta-item"> |
| | | <i class="el-icon-user"></i> |
| | | {{ data.assigneeName || 'æªåé
' }} |
| | |
| | | </span> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- ä»»å¡è¿åº¦æ¡ --> |
| | | <div v-if="data.type === 'task'" class="task-progress"> |
| | | <el-progress :percentage="data.progress || 0" :stroke-width="4" :show-text="false" /> |
| | | <div v-if="data.type === 'task'" |
| | | class="task-progress"> |
| | | <el-progress :percentage="data.progress || 0" |
| | | :stroke-width="4" |
| | | :show-text="false" /> |
| | | </div> |
| | | |
| | | <!-- æä½æé® --> |
| | | <div class="node-actions"> |
| | | <el-button |
| | | v-if="data.type === 'task'" |
| | | <el-button v-if="data.type === 'task'" |
| | | type="text" |
| | | size="small" |
| | | icon="Edit" |
| | | @click.stop="handleEditTask(data)" |
| | | v-hasPermi="['oaSystem:task:edit']" |
| | | /> |
| | | <el-button |
| | | v-if="data.type === 'phase'" |
| | | v-hasPermi="['oaSystem:task:edit']" /> |
| | | <el-button v-if="data.type === 'phase'" |
| | | type="text" |
| | | size="small" |
| | | icon="Plus" |
| | | @click.stop="handleAddTaskUnderPhase(data)" |
| | | v-hasPermi="['oaSystem:task:add']" |
| | | /> |
| | | <el-button |
| | | type="text" |
| | | v-hasPermi="['oaSystem:task:add']" /> |
| | | <el-button type="text" |
| | | size="small" |
| | | icon="Delete" |
| | | @click.stop="handleDeleteNode(data)" |
| | | v-hasPermi="['oaSystem:task:remove']" |
| | | /> |
| | | v-hasPermi="['oaSystem:task:remove']" /> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | </el-tree> |
| | | </div> |
| | | |
| | | <!-- å³é®èå --> |
| | | <div v-if="showContextMenu" :style="contextMenuStyle" class="context-menu"> |
| | | <div v-if="showContextMenu" |
| | | :style="contextMenuStyle" |
| | | class="context-menu"> |
| | | <el-menu @select="handleContextMenuSelect"> |
| | | <el-menu-item v-if="selectedNode.type === 'task'" index="edit">ç¼è¾ä»»å¡</el-menu-item> |
| | | <el-menu-item v-if="selectedNode.type === 'phase'" index="addTask">æ·»å åä»»å¡</el-menu-item> |
| | | <el-menu-item v-if="selectedNode.type === 'task'" |
| | | index="edit">ç¼è¾ä»»å¡</el-menu-item> |
| | | <el-menu-item v-if="selectedNode.type === 'phase'" |
| | | index="addTask">æ·»å åä»»å¡</el-menu-item> |
| | | <el-menu-item index="delete">å é¤</el-menu-item> |
| | | <el-menu-item index="expandAll">å±å¼å
¨é¨</el-menu-item> |
| | | <el-menu-item index="collapseAll">æ¶èµ·å
¨é¨</el-menu-item> |
| | | </el-menu> |
| | | </div> |
| | | |
| | | <!-- ä»»å¡è¡¨åå¯¹è¯æ¡ --> |
| | | <el-dialog :title="dialogTitle" v-model="dialogOpen" width="600px" append-to-body> |
| | | <el-form ref="taskFormRef" :model="taskForm" :rules="taskRules" label-width="80px"> |
| | | <el-form-item label="ä»»å¡åç§°" prop="taskName"> |
| | | <el-input v-model="taskForm.taskName" placeholder="请è¾å
¥ä»»å¡åç§°" /> |
| | | <el-dialog :title="dialogTitle" |
| | | v-model="dialogOpen" |
| | | width="600px" |
| | | append-to-body> |
| | | <el-form ref="taskFormRef" |
| | | :model="taskForm" |
| | | :rules="taskRules" |
| | | label-width="80px"> |
| | | <el-form-item label="ä»»å¡åç§°" |
| | | prop="taskName"> |
| | | <el-input v-model="taskForm.taskName" |
| | | placeholder="请è¾å
¥ä»»å¡åç§°" /> |
| | | </el-form-item> |
| | | <el-form-item label="è´è´£äºº" prop="assigneeId"> |
| | | <el-input v-model="taskForm.assigneeId" placeholder="请è¾å
¥è´è´£äººID" /> |
| | | <el-form-item label="è´è´£äºº" |
| | | prop="assigneeId"> |
| | | <el-input v-model="taskForm.assigneeId" |
| | | placeholder="请è¾å
¥è´è´£äººID" /> |
| | | </el-form-item> |
| | | <el-form-item label="å¼å§æ¥æ" prop="startDate"> |
| | | <el-date-picker |
| | | v-model="taskForm.startDate" |
| | | <el-form-item label="å¼å§æ¥æ" |
| | | prop="startDate"> |
| | | <el-date-picker v-model="taskForm.startDate" |
| | | type="date" |
| | | placeholder="éæ©å¼å§æ¥æ" |
| | | style="width: 100%" |
| | | /> |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | <el-form-item label="ç»ææ¥æ" prop="endDate"> |
| | | <el-date-picker |
| | | v-model="taskForm.endDate" |
| | | <el-form-item label="ç»ææ¥æ" |
| | | prop="endDate"> |
| | | <el-date-picker v-model="taskForm.endDate" |
| | | type="date" |
| | | placeholder="éæ©ç»ææ¥æ" |
| | | style="width: 100%" |
| | | /> |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | <el-form-item label="ä¼å
级" prop="priority"> |
| | | <el-select v-model="taskForm.priority" placeholder="éæ©ä¼å
级"> |
| | | <el-option label="ä½" value="low" /> |
| | | <el-option label="ä¸" value="medium" /> |
| | | <el-option label="é«" value="high" /> |
| | | <el-form-item label="ä¼å
级" |
| | | prop="priority"> |
| | | <el-select v-model="taskForm.priority" |
| | | placeholder="éæ©ä¼å
级"> |
| | | <el-option label="ä½" |
| | | value="low" /> |
| | | <el-option label="ä¸" |
| | | value="medium" /> |
| | | <el-option label="é«" |
| | | value="high" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="è¿åº¦" prop="progress"> |
| | | <el-input-number v-model="taskForm.progress" :min="0" :max="100" style="width: 100%" /> |
| | | <el-form-item label="è¿åº¦" |
| | | prop="progress"> |
| | | <el-input-number v-model="taskForm.progress" |
| | | :min="0" |
| | | :max="100" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | <el-form-item label="æè¿°" prop="description"> |
| | | <el-input v-model="taskForm.description" type="textarea" placeholder="请è¾å
¥ä»»å¡æè¿°" /> |
| | | <el-form-item label="æè¿°" |
| | | prop="description"> |
| | | <el-input v-model="taskForm.description" |
| | | type="textarea" |
| | | placeholder="请è¾å
¥ä»»å¡æè¿°" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="submitTaskForm">ç¡®å®</el-button> |
| | | <el-button @click="dialogOpen = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="submitTaskForm">ç¡®å®</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, computed, watch, onMounted } from 'vue'; |
| | | import { ElMessage, ElMessageBox, ElMenu, ElMenuItem } from 'element-plus'; |
| | | import { ref, reactive, computed, watch, onMounted } from "vue"; |
| | | import { ElMessage, ElMessageBox, ElMenu, ElMenuItem } from "element-plus"; |
| | | // import { getProject, addTask, updateTask, deleteTask, deletePhase } from '@/api/oaSystem/projectManagement'; |
| | | |
| | | const props = defineProps({ |
| | | projectId: { |
| | | type: String, |
| | | required: true |
| | | } |
| | | required: true, |
| | | }, |
| | | }); |
| | | |
| | | const emit = defineEmits(['refresh']); |
| | | const emit = defineEmits(["refresh"]); |
| | | |
| | | // ç»ä»¶ç¶æ |
| | | const loading = ref(false); |
| | |
| | | const selectedNode = ref({}); |
| | | const showFilter = ref(false); |
| | | const dialogOpen = ref(false); |
| | | const dialogTitle = ref(''); |
| | | const dialogTitle = ref(""); |
| | | const taskFormRef = ref(); |
| | | |
| | | // çéåæ° |
| | | const filterParams = reactive({ |
| | | status: '', |
| | | assignee: '' |
| | | status: "", |
| | | assignee: "", |
| | | }); |
| | | |
| | | // ä»»å¡è¡¨åæ°æ® |
| | | const taskForm = reactive({ |
| | | taskId: undefined, |
| | | taskName: '', |
| | | description: '', |
| | | startDate: '', |
| | | endDate: '', |
| | | assigneeId: '', |
| | | assigneeName: '', |
| | | status: 'notStarted', |
| | | taskName: "", |
| | | description: "", |
| | | startDate: "", |
| | | endDate: "", |
| | | assigneeId: "", |
| | | assigneeName: "", |
| | | status: "notStarted", |
| | | progress: 0, |
| | | priority: 'medium', |
| | | phaseId: '', |
| | | projectId: props.projectId |
| | | priority: "medium", |
| | | phaseId: "", |
| | | projectId: props.projectId, |
| | | }); |
| | | |
| | | // 表åéªè¯è§å |
| | | const taskRules = { |
| | | taskName: [ |
| | | { required: true, message: 'ä»»å¡åç§°ä¸è½ä¸ºç©º', trigger: 'blur' }, |
| | | { min: 2, max: 50, message: 'ä»»å¡åç§°é¿åº¦å¨ 2 å° 50 个å符', trigger: 'blur' } |
| | | { required: true, message: "ä»»å¡åç§°ä¸è½ä¸ºç©º", trigger: "blur" }, |
| | | { |
| | | min: 2, |
| | | max: 50, |
| | | message: "ä»»å¡åç§°é¿åº¦å¨ 2 å° 50 个å符", |
| | | trigger: "blur", |
| | | }, |
| | | ], |
| | | startDate: [ |
| | | { required: true, message: 'å¼å§æ¥æä¸è½ä¸ºç©º', trigger: 'change' } |
| | | { required: true, message: "å¼å§æ¥æä¸è½ä¸ºç©º", trigger: "change" }, |
| | | ], |
| | | endDate: [ |
| | | { required: true, message: 'ç»ææ¥æä¸è½ä¸ºç©º', trigger: 'change' } |
| | | ], |
| | | assigneeId: [ |
| | | { required: true, message: 'è´è´£äººä¸è½ä¸ºç©º', trigger: 'blur' } |
| | | ], |
| | | endDate: [{ required: true, message: "ç»ææ¥æä¸è½ä¸ºç©º", trigger: "change" }], |
| | | assigneeId: [{ required: true, message: "è´è´£äººä¸è½ä¸ºç©º", trigger: "blur" }], |
| | | progress: [ |
| | | { required: true, message: 'è¿åº¦ä¸è½ä¸ºç©º', trigger: 'blur' }, |
| | | { type: 'number', min: 0, max: 100, message: 'è¿åº¦å¿
é¡»å¨ 0 å° 100 ä¹é´', trigger: 'blur' } |
| | | ] |
| | | { required: true, message: "è¿åº¦ä¸è½ä¸ºç©º", trigger: "blur" }, |
| | | { |
| | | type: "number", |
| | | min: 0, |
| | | max: 100, |
| | | message: "è¿åº¦å¿
é¡»å¨ 0 å° 100 ä¹é´", |
| | | trigger: "blur", |
| | | }, |
| | | ], |
| | | }; |
| | | |
| | | // 任塿 æ°æ® |
| | |
| | | |
| | | // 模æä»»å¡æ°æ® |
| | | const mockTaskData = { |
| | | 'PRJ2023001': [ |
| | | PRJ2023001: [ |
| | | { |
| | | phaseId: 'PHASE001', |
| | | phaseName: 'éæ±åæ', |
| | | startDate: '2023-11-01', |
| | | endDate: '2023-11-15', |
| | | status: 'completed', |
| | | phaseId: "PHASE001", |
| | | phaseName: "éæ±åæ", |
| | | startDate: "2023-11-01", |
| | | endDate: "2023-11-15", |
| | | status: "completed", |
| | | tasks: [ |
| | | { |
| | | taskId: 'TASK001', |
| | | taskName: 'éæ±è°ç ', |
| | | description: 'è°ç ç¨æ·éæ±åä¸å¡æµç¨', |
| | | startDate: '2023-11-01', |
| | | endDate: '2023-11-05', |
| | | assigneeId: 'USER001', |
| | | assigneeName: 'å¼ ä¸', |
| | | status: 'completed', |
| | | taskId: "TASK001", |
| | | taskName: "éæ±è°ç ", |
| | | description: "è°ç ç¨æ·éæ±åä¸å¡æµç¨", |
| | | startDate: "2023-11-01", |
| | | endDate: "2023-11-05", |
| | | assigneeId: "USER001", |
| | | assigneeName: "å¼ ä¸", |
| | | status: "completed", |
| | | progress: 100, |
| | | priority: 'medium' |
| | | priority: "medium", |
| | | }, |
| | | { |
| | | taskId: 'TASK002', |
| | | taskName: 'éæ±ææ¡£ç¼å', |
| | | description: 'ç¼å详ç»çéæ±è§æ ¼è¯´æä¹¦', |
| | | startDate: '2023-11-06', |
| | | endDate: '2023-11-15', |
| | | assigneeId: 'USER002', |
| | | assigneeName: 'æå', |
| | | status: 'completed', |
| | | taskId: "TASK002", |
| | | taskName: "éæ±ææ¡£ç¼å", |
| | | description: "ç¼å详ç»çéæ±è§æ ¼è¯´æä¹¦", |
| | | startDate: "2023-11-06", |
| | | endDate: "2023-11-15", |
| | | assigneeId: "USER002", |
| | | assigneeName: "æå", |
| | | status: "completed", |
| | | progress: 100, |
| | | priority: 'high' |
| | | } |
| | | ] |
| | | priority: "high", |
| | | }, |
| | | ], |
| | | }, |
| | | { |
| | | phaseId: 'PHASE002', |
| | | phaseName: 'ç³»ç»è®¾è®¡', |
| | | startDate: '2023-11-16', |
| | | endDate: '2023-12-10', |
| | | status: 'completed', |
| | | phaseId: "PHASE002", |
| | | phaseName: "ç³»ç»è®¾è®¡", |
| | | startDate: "2023-11-16", |
| | | endDate: "2023-12-10", |
| | | status: "completed", |
| | | tasks: [ |
| | | { |
| | | taskId: 'TASK003', |
| | | taskName: 'ç³»ç»æ¶æè®¾è®¡', |
| | | description: 'è®¾è®¡ç³»ç»æ´ä½æ¶æ', |
| | | startDate: '2023-11-16', |
| | | endDate: '2023-11-25', |
| | | assigneeId: 'USER003', |
| | | assigneeName: 'çäº', |
| | | status: 'completed', |
| | | taskId: "TASK003", |
| | | taskName: "ç³»ç»æ¶æè®¾è®¡", |
| | | description: "è®¾è®¡ç³»ç»æ´ä½æ¶æ", |
| | | startDate: "2023-11-16", |
| | | endDate: "2023-11-25", |
| | | assigneeId: "USER003", |
| | | assigneeName: "çäº", |
| | | status: "completed", |
| | | progress: 100, |
| | | priority: 'high' |
| | | priority: "high", |
| | | }, |
| | | { |
| | | taskId: 'TASK004', |
| | | taskName: 'æ°æ®åºè®¾è®¡', |
| | | description: 'è®¾è®¡æ°æ®åºè¡¨ç»æåå
³ç³»', |
| | | startDate: '2023-11-26', |
| | | endDate: '2023-12-10', |
| | | assigneeId: 'USER004', |
| | | assigneeName: 'èµµå
', |
| | | status: 'completed', |
| | | taskId: "TASK004", |
| | | taskName: "æ°æ®åºè®¾è®¡", |
| | | description: "è®¾è®¡æ°æ®åºè¡¨ç»æåå
³ç³»", |
| | | startDate: "2023-11-26", |
| | | endDate: "2023-12-10", |
| | | assigneeId: "USER004", |
| | | assigneeName: "èµµå
", |
| | | status: "completed", |
| | | progress: 100, |
| | | priority: 'medium' |
| | | } |
| | | ] |
| | | priority: "medium", |
| | | }, |
| | | ], |
| | | }, |
| | | { |
| | | phaseId: 'PHASE003', |
| | | phaseName: 'å¼åå®ç°', |
| | | startDate: '2023-12-11', |
| | | endDate: '2024-01-31', |
| | | status: 'inProgress', |
| | | phaseId: "PHASE003", |
| | | phaseName: "å¼åå®ç°", |
| | | startDate: "2023-12-11", |
| | | endDate: "2024-01-31", |
| | | status: "inProgress", |
| | | tasks: [ |
| | | { |
| | | taskId: 'TASK005', |
| | | taskName: 'å端å¼å', |
| | | description: 'å¼åç¨æ·çé¢å交äºé»è¾', |
| | | startDate: '2023-12-11', |
| | | endDate: '2024-01-15', |
| | | assigneeId: 'USER005', |
| | | assigneeName: 'é±ä¸', |
| | | status: 'inProgress', |
| | | taskId: "TASK005", |
| | | taskName: "å端å¼å", |
| | | description: "å¼åç¨æ·çé¢å交äºé»è¾", |
| | | startDate: "2023-12-11", |
| | | endDate: "2024-01-15", |
| | | assigneeId: "USER005", |
| | | assigneeName: "é±ä¸", |
| | | status: "inProgress", |
| | | progress: 70, |
| | | priority: 'high' |
| | | priority: "high", |
| | | }, |
| | | { |
| | | taskId: 'TASK006', |
| | | taskName: 'å端å¼å', |
| | | description: 'å¼åä¸å¡é»è¾åAPIæ¥å£', |
| | | startDate: '2023-12-11', |
| | | endDate: '2024-01-20', |
| | | assigneeId: 'USER006', |
| | | assigneeName: 'åå
«', |
| | | status: 'inProgress', |
| | | taskId: "TASK006", |
| | | taskName: "å端å¼å", |
| | | description: "å¼åä¸å¡é»è¾åAPIæ¥å£", |
| | | startDate: "2023-12-11", |
| | | endDate: "2024-01-20", |
| | | assigneeId: "USER006", |
| | | assigneeName: "åå
«", |
| | | status: "inProgress", |
| | | progress: 60, |
| | | priority: 'high' |
| | | } |
| | | ] |
| | | } |
| | | priority: "high", |
| | | }, |
| | | ], |
| | | }, |
| | | ], |
| | | // é»è®¤æ°æ® |
| | | default: [ |
| | | { |
| | | phaseId: 'PHASE_DEFAULT1', |
| | | phaseName: 'åå¤é¶æ®µ', |
| | | startDate: '2023-01-01', |
| | | endDate: '2023-03-31', |
| | | status: 'completed', |
| | | phaseId: "PHASE_DEFAULT1", |
| | | phaseName: "åå¤é¶æ®µ", |
| | | startDate: "2023-01-01", |
| | | endDate: "2023-03-31", |
| | | status: "completed", |
| | | tasks: [ |
| | | { |
| | | taskId: 'TASK_DEFAULT1', |
| | | taskName: '项ç®å¯å¨', |
| | | description: 'å¬å¼é¡¹ç®å¯å¨ä¼è®®', |
| | | startDate: '2023-01-01', |
| | | endDate: '2023-01-05', |
| | | assigneeId: 'USER_DEFAULT1', |
| | | assigneeName: 'è´è´£äººA', |
| | | status: 'completed', |
| | | taskId: "TASK_DEFAULT1", |
| | | taskName: "项ç®å¯å¨", |
| | | description: "å¬å¼é¡¹ç®å¯å¨ä¼è®®", |
| | | startDate: "2023-01-01", |
| | | endDate: "2023-01-05", |
| | | assigneeId: "USER_DEFAULT1", |
| | | assigneeName: "è´è´£äººA", |
| | | status: "completed", |
| | | progress: 100, |
| | | priority: 'high' |
| | | } |
| | | ] |
| | | priority: "high", |
| | | }, |
| | | ], |
| | | }, |
| | | { |
| | | phaseId: 'PHASE_DEFAULT2', |
| | | phaseName: 'æ§è¡é¶æ®µ', |
| | | startDate: '2023-04-01', |
| | | endDate: '2023-09-30', |
| | | status: 'inProgress', |
| | | phaseId: "PHASE_DEFAULT2", |
| | | phaseName: "æ§è¡é¶æ®µ", |
| | | startDate: "2023-04-01", |
| | | endDate: "2023-09-30", |
| | | status: "inProgress", |
| | | tasks: [ |
| | | { |
| | | taskId: 'TASK_DEFAULT2', |
| | | taskName: 'æ ¸å¿åè½å¼å', |
| | | description: 'å¼åç³»ç»æ ¸å¿åè½æ¨¡å', |
| | | startDate: '2023-04-01', |
| | | endDate: '2023-06-30', |
| | | assigneeId: 'USER_DEFAULT2', |
| | | assigneeName: 'è´è´£äººB', |
| | | status: 'inProgress', |
| | | taskId: "TASK_DEFAULT2", |
| | | taskName: "æ ¸å¿åè½å¼å", |
| | | description: "å¼åç³»ç»æ ¸å¿åè½æ¨¡å", |
| | | startDate: "2023-04-01", |
| | | endDate: "2023-06-30", |
| | | assigneeId: "USER_DEFAULT2", |
| | | assigneeName: "è´è´£äººB", |
| | | status: "inProgress", |
| | | progress: 50, |
| | | priority: 'high' |
| | | } |
| | | ] |
| | | } |
| | | ] |
| | | priority: "high", |
| | | }, |
| | | ], |
| | | }, |
| | | ], |
| | | }; |
| | | |
| | | const taskTreeData = computed(() => { |
| | |
| | | const filteredData = JSON.parse(JSON.stringify(rawTaskTreeData.value)); |
| | | |
| | | // éå½çéèç¹ |
| | | const filterNodes = (nodes) => { |
| | | const filterNodes = nodes => { |
| | | const result = []; |
| | | |
| | | nodes.forEach(node => { |
| | | // 对äºé¶æ®µèç¹ï¼æ£æ¥å
¶å任塿¯å¦ç¬¦åç鿡件 |
| | | if (node.type === 'phase' && node.children) { |
| | | if (node.type === "phase" && node.children) { |
| | | const filteredChildren = filterNodes(node.children); |
| | | if (filteredChildren.length > 0) { |
| | | // ä¿çè³å°æä¸ä¸ªåä»»å¡ç¬¦åæ¡ä»¶çé¶æ®µ |
| | |
| | | } |
| | | } |
| | | // 对äºä»»å¡èç¹ï¼ç´æ¥åºç¨ç鿡件 |
| | | else if (node.type === 'task') { |
| | | const statusMatch = !filterParams.status || node.status === filterParams.status; |
| | | const assigneeMatch = !filterParams.assignee || |
| | | (node.assigneeName && node.assigneeName.includes(filterParams.assignee)); |
| | | else if (node.type === "task") { |
| | | const statusMatch = |
| | | !filterParams.status || node.status === filterParams.status; |
| | | const assigneeMatch = |
| | | !filterParams.assignee || |
| | | (node.assigneeName && |
| | | node.assigneeName.includes(filterParams.assignee)); |
| | | |
| | | if (statusMatch && assigneeMatch) { |
| | | result.push(node); |
| | |
| | | |
| | | // æ èç¹é
ç½® |
| | | const defaultProps = { |
| | | children: 'children', |
| | | label: (data) => { |
| | | if (data.type === 'phase') { |
| | | children: "children", |
| | | label: data => { |
| | | if (data.type === "phase") { |
| | | return `${data.phaseName}`; |
| | | } else { |
| | | return `${data.taskName}`; |
| | | } |
| | | } |
| | | }, |
| | | }; |
| | | |
| | | // å è½½ä»»å¡æ æ°æ® |
| | |
| | | const phases = mockTaskData[props.projectId] || mockTaskData.default; |
| | | rawTaskTreeData.value = buildTaskTree(phases); |
| | | } catch (error) { |
| | | ElMessage.error('å è½½ä»»å¡æ 失败'); |
| | | console.error('å è½½ä»»å¡æ 失败:', error); |
| | | ElMessage.error("å è½½ä»»å¡æ 失败"); |
| | | console.error("å è½½ä»»å¡æ 失败:", error); |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | | }; |
| | | |
| | | // æå»ºä»»å¡æ |
| | | const buildTaskTree = (phases) => { |
| | | const buildTaskTree = phases => { |
| | | return phases.map(phase => ({ |
| | | nodeId: phase.phaseId, |
| | | phaseId: phase.phaseId, |
| | | phaseName: phase.phaseName, |
| | | type: 'phase', |
| | | type: "phase", |
| | | children: (phase.tasks || []).map(task => ({ |
| | | nodeId: task.taskId, |
| | | taskId: task.taskId, |
| | |
| | | priority: task.priority, |
| | | phaseId: task.phaseId, |
| | | projectId: props.projectId, |
| | | type: 'task' |
| | | })) |
| | | type: "task", |
| | | })), |
| | | })); |
| | | }; |
| | | |
| | | // æ ¼å¼åæ¥æèå´ |
| | | const formatDateRange = (startDate, endDate) => { |
| | | if (!startDate || !endDate) return ''; |
| | | if (!startDate || !endDate) return ""; |
| | | return `${startDate} - ${endDate}`; |
| | | }; |
| | | |
| | |
| | | const refreshTree = () => { |
| | | loadTaskTree(); |
| | | // éç¥ç¶ç»ä»¶å·æ°æ°æ® |
| | | emit('refresh'); |
| | | emit("refresh"); |
| | | }; |
| | | |
| | | // 忢çé颿¿ |
| | |
| | | |
| | | // éç½®çé |
| | | const resetFilter = () => { |
| | | filterParams.status = ''; |
| | | filterParams.assignee = ''; |
| | | filterParams.status = ""; |
| | | filterParams.assignee = ""; |
| | | }; |
| | | |
| | | // å¤çèç¹ç¹å» |
| | | const handleNodeClick = (data, node) => { |
| | | // 忢å±å¼/æ¶èµ·ç¶æ |
| | | if (data.type === 'phase') { |
| | | if (data.type === "phase") { |
| | | node.expanded = !node.expanded; |
| | | } |
| | | }; |
| | |
| | | event.preventDefault(); |
| | | selectedNode.value = data; |
| | | contextMenuStyle.value = { |
| | | position: 'fixed', |
| | | position: "fixed", |
| | | left: `${event.clientX}px`, |
| | | top: `${event.clientY}px`, |
| | | zIndex: 1000 |
| | | zIndex: 1000, |
| | | }; |
| | | showContextMenu.value = true; |
| | | }; |
| | | |
| | | // å¤çå³é®èåéæ© |
| | | const handleContextMenuSelect = (index) => { |
| | | const handleContextMenuSelect = index => { |
| | | showContextMenu.value = false; |
| | | switch (index) { |
| | | case 'edit': |
| | | if (selectedNode.value.type === 'task') { |
| | | case "edit": |
| | | if (selectedNode.value.type === "task") { |
| | | handleEditTask(selectedNode.value); |
| | | } |
| | | break; |
| | | case 'addTask': |
| | | if (selectedNode.value.type === 'phase') { |
| | | case "addTask": |
| | | if (selectedNode.value.type === "phase") { |
| | | handleAddTaskUnderPhase(selectedNode.value); |
| | | } |
| | | break; |
| | | case 'delete': |
| | | case "delete": |
| | | handleDeleteNode(selectedNode.value); |
| | | break; |
| | | case 'expandAll': |
| | | case "expandAll": |
| | | treeRef.value?.expandAll(); |
| | | break; |
| | | case 'collapseAll': |
| | | case "collapseAll": |
| | | treeRef.value?.collapseAll(); |
| | | break; |
| | | } |
| | |
| | | // æ·»å ä»»å¡ |
| | | const handleAddTask = () => { |
| | | resetTaskForm(); |
| | | dialogTitle.value = 'æ·»å ä»»å¡'; |
| | | dialogTitle.value = "æ·»å ä»»å¡"; |
| | | dialogOpen.value = true; |
| | | }; |
| | | |
| | | // 卿å®é¶æ®µä¸æ·»å ä»»å¡ |
| | | const handleAddTaskUnderPhase = (phase) => { |
| | | const handleAddTaskUnderPhase = phase => { |
| | | resetTaskForm(); |
| | | taskForm.phaseId = phase.phaseId; |
| | | dialogTitle.value = 'æ·»å åä»»å¡'; |
| | | dialogTitle.value = "æ·»å åä»»å¡"; |
| | | dialogOpen.value = true; |
| | | }; |
| | | |
| | | // ç¼è¾ä»»å¡ |
| | | const handleEditTask = (task) => { |
| | | const handleEditTask = task => { |
| | | resetTaskForm(); |
| | | Object.assign(taskForm, { ...task }); |
| | | dialogTitle.value = 'ç¼è¾ä»»å¡'; |
| | | dialogTitle.value = "ç¼è¾ä»»å¡"; |
| | | dialogOpen.value = true; |
| | | }; |
| | | |
| | | // å é¤èç¹ |
| | | const handleDeleteNode = async (node) => { |
| | | const confirmMessage = node.type === 'phase' |
| | | const handleDeleteNode = async node => { |
| | | const confirmMessage = |
| | | node.type === "phase" |
| | | ? `ç¡®å®è¦å é¤é¶æ®µ "${node.phaseName}" åå
¶ææåä»»å¡åï¼` |
| | | : `ç¡®å®è¦å é¤ä»»å¡ "${node.taskName}" åï¼`; |
| | | |
| | | await ElMessageBox.confirm(confirmMessage, '确认æä½', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | await ElMessageBox.confirm(confirmMessage, "确认æä½", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).catch(() => { |
| | | throw new Error('åæ¶å é¤'); |
| | | throw new Error("åæ¶å é¤"); |
| | | }); |
| | | |
| | | try { |
| | | if (node.type === 'phase') { |
| | | if (node.type === "phase") { |
| | | await deletePhase(node.phaseId); |
| | | } else { |
| | | await deleteTask(node.taskId); |
| | | } |
| | | ElMessage.success('å 餿å'); |
| | | ElMessage.success("å 餿å"); |
| | | refreshTree(); |
| | | } catch (error) { |
| | | if (error.message !== 'åæ¶å é¤') { |
| | | ElMessage.error('å é¤å¤±è´¥'); |
| | | console.error('å é¤å¤±è´¥:', error); |
| | | if (error.message !== "åæ¶å é¤") { |
| | | ElMessage.error("å é¤å¤±è´¥"); |
| | | console.error("å é¤å¤±è´¥:", error); |
| | | } |
| | | } |
| | | }; |
| | |
| | | // é置任å¡è¡¨å |
| | | const resetTaskForm = () => { |
| | | taskForm.taskId = undefined; |
| | | taskForm.taskName = ''; |
| | | taskForm.description = ''; |
| | | taskForm.startDate = ''; |
| | | taskForm.endDate = ''; |
| | | taskForm.assigneeId = ''; |
| | | taskForm.assigneeName = ''; |
| | | taskForm.status = 'notStarted'; |
| | | taskForm.taskName = ""; |
| | | taskForm.description = ""; |
| | | taskForm.startDate = ""; |
| | | taskForm.endDate = ""; |
| | | taskForm.assigneeId = ""; |
| | | taskForm.assigneeName = ""; |
| | | taskForm.status = "notStarted"; |
| | | taskForm.progress = 0; |
| | | taskForm.priority = 'medium'; |
| | | taskForm.phaseId = ''; |
| | | taskForm.priority = "medium"; |
| | | taskForm.phaseId = ""; |
| | | taskForm.projectId = props.projectId; |
| | | |
| | | if (taskFormRef.value) { |
| | |
| | | |
| | | if (taskForm.taskId) { |
| | | await updateTask(taskForm); |
| | | ElMessage.success('ä¿®æ¹ä»»å¡æå'); |
| | | ElMessage.success("ä¿®æ¹ä»»å¡æå"); |
| | | } else { |
| | | await addTask(taskForm); |
| | | ElMessage.success('æ·»å 任塿å'); |
| | | ElMessage.success("æ·»å 任塿å"); |
| | | } |
| | | |
| | | dialogOpen.value = false; |
| | | refreshTree(); |
| | | } catch (error) { |
| | | console.error('æäº¤è¡¨å失败:', error); |
| | | console.error("æäº¤è¡¨å失败:", error); |
| | | } |
| | | }; |
| | | |
| | | // ç¹å»å
¶ä»åºåå
³éå³é®èå |
| | | document.addEventListener('click', () => { |
| | | document.addEventListener("click", () => { |
| | | if (showContextMenu.value) { |
| | | showContextMenu.value = false; |
| | | } |
| | | }); |
| | | |
| | | // çå¬é¡¹ç®IDåå |
| | | watch(() => props.projectId, (newProjectId) => { |
| | | watch( |
| | | () => props.projectId, |
| | | newProjectId => { |
| | | if (newProjectId) { |
| | | loadTaskTree(); |
| | | } |
| | | }); |
| | | } |
| | | ); |
| | | |
| | | // åå§å |
| | | onMounted(() => { |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <!-- é¡¶é¨æç´¢åæä½æ --> |
| | | <el-form :model="queryParams" ref="queryRef" :inline="true" label-width="80px"> |
| | | <el-form-item label="项ç®åç§°" prop="projectName"> |
| | | <el-input |
| | | v-model="queryParams.projectName" |
| | | <el-form :model="queryParams" |
| | | ref="queryRef" |
| | | :inline="true" |
| | | label-width="80px"> |
| | | <el-form-item label="项ç®åç§°" |
| | | prop="projectName"> |
| | | <el-input v-model="queryParams.projectName" |
| | | placeholder="请è¾å
¥é¡¹ç®åç§°" |
| | | clearable |
| | | style="width: 240px" |
| | | @keyup.enter="handleQuery" |
| | | /> |
| | | @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="è´è´£äºº" prop="managerName"> |
| | | <el-input |
| | | v-model="queryParams.managerName" |
| | | <el-form-item label="è´è´£äºº" |
| | | prop="managerName"> |
| | | <el-input v-model="queryParams.managerName" |
| | | placeholder="请è¾å
¥è´è´£äººå§å" |
| | | clearable |
| | | style="width: 240px" |
| | | @keyup.enter="handleQuery" |
| | | /> |
| | | @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="ç¶æ" prop="status"> |
| | | <el-select |
| | | v-model="queryParams.status" |
| | | <el-form-item label="ç¶æ" |
| | | prop="status"> |
| | | <el-select v-model="queryParams.status" |
| | | placeholder="项ç®ç¶æ" |
| | | clearable |
| | | style="width: 150px" |
| | | > |
| | | <el-option label="è§åä¸" value="planning" /> |
| | | <el-option label="è¿è¡ä¸" value="inProgress" /> |
| | | <el-option label="已宿" value="completed" /> |
| | | <el-option label="å·²æå" value="paused" /> |
| | | style="width: 150px"> |
| | | <el-option label="è§åä¸" |
| | | value="planning" /> |
| | | <el-option label="è¿è¡ä¸" |
| | | value="inProgress" /> |
| | | <el-option label="已宿" |
| | | value="completed" /> |
| | | <el-option label="å·²æå" |
| | | value="paused" /> |
| | | </el-select> |
| | | </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" |
| | | <el-button type="primary" |
| | | plain |
| | | icon="Plus" |
| | | @click="handleAdd" |
| | | v-hasPermi="['oaSystem:project:add']" |
| | | >æ°å¢é¡¹ç®</el-button> |
| | | v-hasPermi="['oaSystem:project:add']">æ°å¢é¡¹ç®</el-button> |
| | | </el-col> |
| | | <!-- <el-col :span="1.5"> |
| | | <el-button |
| | |
| | | >å é¤é¡¹ç®</el-button> |
| | | </el-col> --> |
| | | <el-col :span="1.5"> |
| | | <el-button |
| | | type="warning" |
| | | <el-button type="warning" |
| | | plain |
| | | icon="Download" |
| | | @click="handleExport" |
| | | v-hasPermi="['oaSystem:project:export']" |
| | | >导åºé¡¹ç®</el-button> |
| | | v-hasPermi="['oaSystem:project:export']">导åºé¡¹ç®</el-button> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <!-- 项ç®åè¡¨è¡¨æ ¼ --> |
| | | <el-table |
| | | v-loading="loading" |
| | | <el-table v-loading="loading" |
| | | :data="projectList" |
| | | @selection-change="handleSelectionChange" |
| | | > |
| | | <el-table-column type="selection" width="50" align="center" /> |
| | | <el-table-column |
| | | label="项ç®ç¼å·" |
| | | @selection-change="handleSelectionChange"> |
| | | <el-table-column type="selection" |
| | | width="50" |
| | | align="center" /> |
| | | <el-table-column label="项ç®ç¼å·" |
| | | align="center" |
| | | prop="projectId" |
| | | width="100" |
| | | /> |
| | | <el-table-column |
| | | label="项ç®åç§°" |
| | | width="100" /> |
| | | <el-table-column label="项ç®åç§°" |
| | | align="center" |
| | | prop="projectName" |
| | | :show-overflow-tooltip="true" |
| | | /> |
| | | <el-table-column |
| | | label="è´è´£äºº" |
| | | :show-overflow-tooltip="true" /> |
| | | <el-table-column label="è´è´£äºº" |
| | | align="center" |
| | | prop="managerName" |
| | | /> |
| | | <el-table-column |
| | | label="å¼å§æ¥æ" |
| | | prop="managerName" /> |
| | | <el-table-column label="å¼å§æ¥æ" |
| | | align="center" |
| | | prop="startDate" |
| | | width="120" |
| | | /> |
| | | <el-table-column |
| | | label="ç»ææ¥æ" |
| | | width="120" /> |
| | | <el-table-column label="ç»ææ¥æ" |
| | | align="center" |
| | | prop="endDate" |
| | | width="120" |
| | | /> |
| | | <el-table-column |
| | | label="ç¶æ" |
| | | width="120" /> |
| | | <el-table-column label="ç¶æ" |
| | | align="center" |
| | | prop="status" |
| | | width="90" |
| | | > |
| | | width="90"> |
| | | <template #default="scope"> |
| | | <el-tag :type="getStatusType(scope.row.status)">{{ getStatusText(scope.row.status) }}</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="å®æåº¦" |
| | | <el-table-column label="å®æåº¦" |
| | | align="center" |
| | | prop="completionRate" |
| | | width="100" |
| | | > |
| | | width="100"> |
| | | <template #default="scope"> |
| | | <el-progress :percentage="scope.row.completionRate" :stroke-width="6" /> |
| | | <el-progress :percentage="scope.row.completionRate" |
| | | :stroke-width="6" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="æä½" |
| | | <el-table-column label="æä½" |
| | | align="center" |
| | | width="180" |
| | | class-name="small-padding fixed-width" |
| | | > |
| | | class-name="small-padding fixed-width"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | link |
| | | <el-button link |
| | | type="primary" |
| | | icon="Search" |
| | | @click="handleView(scope.row)" |
| | | v-hasPermi="['oaSystem:project:query']" |
| | | >详æ
</el-button> |
| | | <el-button |
| | | link |
| | | v-hasPermi="['oaSystem:project:query']">详æ
</el-button> |
| | | <el-button link |
| | | type="primary" |
| | | icon="Edit" |
| | | @click="handleUpdate(scope.row)" |
| | | v-hasPermi="['oaSystem:project:edit']" |
| | | >ç¼è¾</el-button> |
| | | <el-button |
| | | link |
| | | v-hasPermi="['oaSystem:project:edit']">ç¼è¾</el-button> |
| | | <el-button link |
| | | type="danger" |
| | | icon="Delete" |
| | | @click="handleDelete(scope.row)" |
| | | v-hasPermi="['oaSystem:project:remove']" |
| | | >å é¤</el-button> |
| | | v-hasPermi="['oaSystem:project:remove']">å é¤</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <!-- å页ç»ä»¶ --> |
| | | <pagination |
| | | v-show="total > 0" |
| | | <pagination v-show="total > 0" |
| | | :total="total" |
| | | v-model:page="queryParams.pageNum" |
| | | v-model:limit="queryParams.pageSize" |
| | | @pagination="getList" |
| | | /> |
| | | |
| | | @pagination="getList" /> |
| | | <!-- 项ç®è¡¨åå¯¹è¯æ¡ --> |
| | | <el-dialog :title="title" v-model="open" width="600px" append-to-body> |
| | | <project-form |
| | | ref="projectFormRef" |
| | | <el-dialog :title="title" |
| | | v-model="open" |
| | | width="600px" |
| | | append-to-body> |
| | | <project-form ref="projectFormRef" |
| | | :form="form" |
| | | :rules="rules" |
| | | :visible="open" |
| | | /> |
| | | :visible="open" /> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="submitForm">ç¡®å®</el-button> |
| | | <el-button @click="cancel">åæ¶</el-button> |
| | | <el-button type="primary" @click="submitForm">ç¡®å®</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, computed, onMounted } from 'vue'; |
| | | import { ElMessage, ElMessageBox } from 'element-plus'; |
| | | import Pagination from '@/components/Pagination'; |
| | | import ProjectForm from './components/projectForm.vue'; |
| | | import { useRouter } from 'vue-router'; |
| | | import { ref, reactive, computed, onMounted } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import Pagination from "@/components/Pagination"; |
| | | import ProjectForm from "./components/projectForm.vue"; |
| | | import { useRouter } from "vue-router"; |
| | | const { proxy } = getCurrentInstance(); |
| | | // 导å
¥é¡¹ç®ç®¡çAPIæ¥å£ |
| | | import { listProject, addProject, updateProject, delProject, exportProject } from '@/api/oaSystem/projectManagement'; |
| | | import { |
| | | listProject, |
| | | addProject, |
| | | updateProject, |
| | | delProject, |
| | | exportProject, |
| | | } from "@/api/oaSystem/projectManagement"; |
| | | // import { listUser } from '@/api/system/user'; // 导å
¥ç¨æ·å表APIæ¥å£ |
| | | |
| | | // å建routerå®ä¾ |
| | |
| | | const queryParams = reactive({ |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | projectName: '', |
| | | managerName: '', |
| | | status: '' |
| | | projectName: "", |
| | | managerName: "", |
| | | status: "", |
| | | }); |
| | | |
| | | // è¡¨åæ°æ® |
| | | const form = reactive({ |
| | | projectId: undefined, |
| | | projectName: '', |
| | | description: '', |
| | | startDate: '', |
| | | endDate: '', |
| | | managerId: '', |
| | | managerName: '', |
| | | status: 'planning', |
| | | completionRate: 0 |
| | | projectName: "", |
| | | description: "", |
| | | startDate: "", |
| | | endDate: "", |
| | | managerId: "", |
| | | managerName: "", |
| | | status: "planning", |
| | | completionRate: 0, |
| | | }); |
| | | |
| | | // è¡¨åæ ¡éªè§å |
| | | const rules = { |
| | | projectName: [ |
| | | { required: true, message: '项ç®åç§°ä¸è½ä¸ºç©º', trigger: 'blur' }, |
| | | { min: 2, max: 50, message: '项ç®åç§°é¿åº¦å¨ 2 å° 50 个å符', trigger: 'blur' } |
| | | { required: true, message: "项ç®åç§°ä¸è½ä¸ºç©º", trigger: "blur" }, |
| | | { |
| | | min: 2, |
| | | max: 50, |
| | | message: "项ç®åç§°é¿åº¦å¨ 2 å° 50 个å符", |
| | | trigger: "blur", |
| | | }, |
| | | ], |
| | | startDate: [ |
| | | { required: true, message: 'å¼å§æ¥æä¸è½ä¸ºç©º', trigger: 'change' } |
| | | { required: true, message: "å¼å§æ¥æä¸è½ä¸ºç©º", trigger: "change" }, |
| | | ], |
| | | endDate: [ |
| | | { required: true, message: 'ç»ææ¥æä¸è½ä¸ºç©º', trigger: 'change' } |
| | | ], |
| | | managerId: [ |
| | | { required: true, message: 'è´è´£äººä¸è½ä¸ºç©º', trigger: 'blur' } |
| | | ] |
| | | endDate: [{ required: true, message: "ç»ææ¥æä¸è½ä¸ºç©º", trigger: "change" }], |
| | | managerId: [{ required: true, message: "è´è´£äººä¸è½ä¸ºç©º", trigger: "blur" }], |
| | | }; |
| | | |
| | | // å¯¹è¯æ¡ç¶æ |
| | | const open = ref(false); |
| | | const title = ref(''); |
| | | const title = ref(""); |
| | | const projectFormRef = ref(); |
| | | const queryRef = ref(); |
| | | |
| | |
| | | projectList.value = data.records; |
| | | total.value = data.total; |
| | | } catch (error) { |
| | | ElMessage.error('è·å项ç®å表失败'); |
| | | console.error('è·å项ç®å表失败:', error); |
| | | ElMessage.error("è·å项ç®å表失败"); |
| | | console.error("è·å项ç®å表失败:", error); |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | |
| | | }; |
| | | |
| | | // éä¸è¡åå |
| | | const handleSelectionChange = (selection) => { |
| | | const handleSelectionChange = selection => { |
| | | selectedRowKeys.value = selection.map(item => item.projectId); |
| | | }; |
| | | |
| | |
| | | const handleAdd = () => { |
| | | resetForm(); |
| | | open.value = true; |
| | | title.value = 'æ°å¢é¡¹ç®'; |
| | | title.value = "æ°å¢é¡¹ç®"; |
| | | }; |
| | | |
| | | // ç¼è¾é¡¹ç® |
| | | const handleUpdate = async (row) => { |
| | | const handleUpdate = async row => { |
| | | resetForm(); |
| | | const projectId = row.projectId || selectedRowKeys.value[0]; |
| | | try { |
| | | // const { data } = await getProject(projectId); |
| | | Object.assign(form, row); |
| | | open.value = true; |
| | | title.value = 'ç¼è¾é¡¹ç®'; |
| | | title.value = "ç¼è¾é¡¹ç®"; |
| | | } catch (error) { |
| | | ElMessage.error('è·å项ç®è¯¦æ
失败'); |
| | | console.error('è·å项ç®è¯¦æ
失败:', error); |
| | | ElMessage.error("è·å项ç®è¯¦æ
失败"); |
| | | console.error("è·å项ç®è¯¦æ
失败:", error); |
| | | } |
| | | }; |
| | | |
| | | // å é¤é¡¹ç® |
| | | const handleDelete = async (row) => { |
| | | const handleDelete = async row => { |
| | | // const projectIds = row.projectId ? [row.projectId] : selectedRowKeys.value; |
| | | const projectNames = row.projectName ? [row.projectName] : |
| | | projectList.value.filter(item => projectIds.includes(item.projectId)).map(item => item.projectName); |
| | | const projectNames = row.projectName |
| | | ? [row.projectName] |
| | | : projectList.value |
| | | .filter(item => projectIds.includes(item.projectId)) |
| | | .map(item => item.projectName); |
| | | |
| | | const confirmMessage = `ç¡®å®è¦å é¤é¡¹ç® "${projectNames.join('ã')}" åï¼`; |
| | | await ElMessageBox.confirm(confirmMessage, '确认æä½', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | const confirmMessage = `ç¡®å®è¦å é¤é¡¹ç® "${projectNames.join("ã")}" åï¼`; |
| | | await ElMessageBox.confirm(confirmMessage, "确认æä½", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).catch(() => { |
| | | throw new Error('åæ¶å é¤'); |
| | | throw new Error("åæ¶å é¤"); |
| | | }); |
| | | |
| | | try { |
| | |
| | | // } else { |
| | | // await delProjectBatch(projectIds); |
| | | // } |
| | | ElMessage.success('å 餿å'); |
| | | ElMessage.success("å 餿å"); |
| | | getList(); |
| | | } catch (error) { |
| | | if (error.message !== 'åæ¶å é¤') { |
| | | ElMessage.error('å é¤å¤±è´¥'); |
| | | console.error('å é¤é¡¹ç®å¤±è´¥:', error); |
| | | if (error.message !== "åæ¶å é¤") { |
| | | ElMessage.error("å é¤å¤±è´¥"); |
| | | console.error("å é¤é¡¹ç®å¤±è´¥:", error); |
| | | } |
| | | } |
| | | // try { |
| | |
| | | // // 模æç½ç»å»¶è¿ |
| | | // await new Promise(resolve => setTimeout(resolve, 300)); |
| | | |
| | | |
| | | // ElMessage.success('å 餿å'); |
| | | // getList(); |
| | | // } catch (error) { |
| | |
| | | }; |
| | | |
| | | // æ¥ç项ç®è¯¦æ
|
| | | const handleView = (row) => { |
| | | const handleView = row => { |
| | | const projectId = row.projectId; |
| | | // 跳转å°é¡¹ç®è¯¦æ
é¡µé¢ |
| | | router.push({ |
| | | path: `/oaSystem/projectManagement/projectDetail/${projectId}`, |
| | | query: { projectName: row.projectName } |
| | | query: { projectName: row.projectName }, |
| | | }); |
| | | }; |
| | | |
| | |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download(`/oA/project/export/${ids.join(',')}`, {}, "é¡¹ç®æ°æ®.xlsx"); |
| | | proxy.download( |
| | | `/oA/project/export/${ids.join(",")}`, |
| | | {}, |
| | | "é¡¹ç®æ°æ®.xlsx" |
| | | ); |
| | | ElMessage.success("å¯¼åºæå"); |
| | | ids = []; |
| | | }) |
| | |
| | | |
| | | if (form.projectId) { |
| | | await updateProject(form); |
| | | ElMessage.success('ä¿®æ¹é¡¹ç®æå'); |
| | | ElMessage.success("ä¿®æ¹é¡¹ç®æå"); |
| | | } else { |
| | | console.log("form",form); |
| | | await addProject(form); |
| | | ElMessage.success('æ°å¢é¡¹ç®æå'); |
| | | ElMessage.success("æ°å¢é¡¹ç®æå"); |
| | | } |
| | | open.value = false; |
| | | getList(); |
| | | } catch (error) { |
| | | console.error('æäº¤è¡¨å失败:', error); |
| | | console.error("æäº¤è¡¨å失败:", error); |
| | | } |
| | | }; |
| | | |
| | |
| | | // é置表å |
| | | const resetForm = () => { |
| | | form.projectId = undefined; |
| | | form.projectName = ''; |
| | | form.description = ''; |
| | | form.startDate = ''; |
| | | form.endDate = ''; |
| | | form.managerId = ''; |
| | | form.managerName = ''; |
| | | form.status = 'planning'; |
| | | form.projectName = ""; |
| | | form.description = ""; |
| | | form.startDate = ""; |
| | | form.endDate = ""; |
| | | form.managerId = ""; |
| | | form.managerName = ""; |
| | | form.status = "planning"; |
| | | form.completionRate = 0; |
| | | if (projectFormRef.value) { |
| | | projectFormRef.value.resetFields(); |
| | |
| | | }; |
| | | |
| | | // è·åç¶ææ ç¾ç±»å |
| | | const getStatusType = (status) => { |
| | | const getStatusType = status => { |
| | | const statusTypeMap = { |
| | | planning: 'info', |
| | | inProgress: 'primary', |
| | | completed: 'success', |
| | | paused: 'warning' |
| | | planning: "info", |
| | | inProgress: "primary", |
| | | completed: "success", |
| | | paused: "warning", |
| | | }; |
| | | return statusTypeMap[status] || 'default'; |
| | | return statusTypeMap[status] || "default"; |
| | | }; |
| | | |
| | | // è·åç¶æææ¬ |
| | | const getStatusText = (status) => { |
| | | const getStatusText = status => { |
| | | const statusTextMap = { |
| | | planning: 'è§åä¸', |
| | | inProgress: 'è¿è¡ä¸', |
| | | completed: '已宿', |
| | | paused: 'å·²æå' |
| | | planning: "è§åä¸", |
| | | inProgress: "è¿è¡ä¸", |
| | | completed: "已宿", |
| | | paused: "å·²æå", |
| | | }; |
| | | return statusTextMap[status] || status; |
| | | }; |
| | |
| | | <span>项ç®åºæ¬ä¿¡æ¯</span> |
| | | </div> |
| | | </template> |
| | | <el-descriptions :column="2" border> |
| | | <el-descriptions :column="2" |
| | | border> |
| | | <el-descriptions-item label="项ç®åç§°">{{ projectInfo.projectName }}</el-descriptions-item> |
| | | <el-descriptions-item label="项ç®è´è´£äºº">{{ projectInfo.managerName }}</el-descriptions-item> |
| | | <el-descriptions-item label="å¼å§æ¥æ">{{ projectInfo.startDate }}</el-descriptions-item> |
| | |
| | | <el-tag :type="getStatusType(projectInfo.status)">{{ getStatusText(projectInfo.status) }}</el-tag> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="å®æåº¦"> |
| | | <el-progress :percentage="projectInfo.completionRate" :stroke-width="6" /> |
| | | <el-progress :percentage="projectInfo.completionRate" |
| | | :stroke-width="6" /> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="é¡¹ç®æè¿°" :span="2">{{ projectInfo.description || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="é¡¹ç®æè¿°" |
| | | :span="2">{{ projectInfo.description || '-' }}</el-descriptions-item> |
| | | </el-descriptions> |
| | | </el-card> |
| | | |
| | | <!-- 项ç®è¿åº¦æ¦è§ --> |
| | | <el-card class="mb20"> |
| | | <template #header> |
| | |
| | | </el-col> |
| | | </el-row> |
| | | </el-card> |
| | | |
| | | <!-- é¶æ®µåä»»å¡ç®¡ç --> |
| | | <!-- <el-card class="mb20"> |
| | | <template #header> |
| | |
| | | </template> |
| | | <task-tree :project-id="projectId" @refresh="getProjectDetail" /> |
| | | </el-card> --> |
| | | |
| | | <!-- éç¨ç¢ç®¡ç --> |
| | | <el-card class="mb20"> |
| | | <template #header> |
| | | <div class="card-header"> |
| | | <span>项ç®é¶æ®µéç¨ç¢</span> |
| | | <el-button type="primary" size="small" @click="handleAddMilestone">æ·»å éç¨ç¢</el-button> |
| | | <el-button type="primary" |
| | | size="small" |
| | | @click="handleAddMilestone">æ·»å éç¨ç¢</el-button> |
| | | </div> |
| | | </template> |
| | | <milestone-list :project-id="projectId" @refresh="getProjectDetail" :key="`milestone-${refreshProjectId}`"/> |
| | | <milestone-list :project-id="projectId" |
| | | @refresh="getProjectDetail" |
| | | :key="`milestone-${refreshProjectId}`" /> |
| | | </el-card> |
| | | |
| | | <!-- é¶æ®µç®æ 管ç --> |
| | | <el-card> |
| | | <template #header> |
| | | <div class="card-header"> |
| | | <span>é¶æ®µä»»å¡</span> |
| | | <el-button type="primary" size="small" @click="handleAddPhaseGoal">æ·»å é¶æ®µç®æ </el-button> |
| | | <el-button type="primary" |
| | | size="small" |
| | | @click="handleAddPhaseGoal">æ·»å é¶æ®µç®æ </el-button> |
| | | </div> |
| | | </template> |
| | | <phase-goal-list :project-id="projectId" @refresh="getProjectDetail" @editGoal="handleEditPhaseGoal" :key="`phaseGoal-${refreshProjectId}`"/> |
| | | <phase-goal-list :project-id="projectId" |
| | | @refresh="getProjectDetail" |
| | | @editGoal="handleEditPhaseGoal" |
| | | :key="`phaseGoal-${refreshProjectId}`" /> |
| | | </el-card> |
| | | |
| | | <!-- éç¨ç¢ç®¡çå¼¹æ¡ --> |
| | | <el-dialog :title="title" v-model="open" width="600px" append-to-body> |
| | | <el-form :model="form" ref="formRef" label-width="100px"> |
| | | <el-form-item label="项ç®é¶æ®µåç§°" prop="phaseName"> |
| | | <el-input |
| | | v-model="form.phaseName" |
| | | <el-dialog :title="title" |
| | | v-model="open" |
| | | width="600px" |
| | | append-to-body> |
| | | <el-form :model="form" |
| | | ref="formRef" |
| | | label-width="100px"> |
| | | <el-form-item label="项ç®é¶æ®µåç§°" |
| | | prop="phaseName"> |
| | | <el-input v-model="form.phaseName" |
| | | placeholder="请è¾å
¥é¡¹ç®é¶æ®µåç§°" |
| | | maxlength="50" |
| | | /> |
| | | maxlength="50" /> |
| | | </el-form-item> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å¼å§æ¥æ" prop="startDate"> |
| | | <el-date-picker |
| | | v-model="form.startDate" |
| | | <el-form-item label="å¼å§æ¥æ" |
| | | prop="startDate"> |
| | | <el-date-picker v-model="form.startDate" |
| | | type="date" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | placeholder="éæ©å¼å§æ¥æ" |
| | | style="width: 100%" |
| | | /> |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç»ææ¥æ" prop="endDate"> |
| | | <el-date-picker |
| | | v-model="form.endDate" |
| | | <el-form-item label="ç»ææ¥æ" |
| | | prop="endDate"> |
| | | <el-date-picker v-model="form.endDate" |
| | | type="date" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | placeholder="éæ©ç»ææ¥æ" |
| | | style="width: 100%" |
| | | /> |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-form-item label="ç¶æ" prop="status"> |
| | | <el-form-item label="ç¶æ" |
| | | prop="status"> |
| | | <el-radio-group v-model="form.status"> |
| | | <el-radio label="notStarted">æªå¼å§</el-radio> |
| | | <el-radio label="completed">已宿</el-radio> |
| | |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="submitForm">ç¡®å®</el-button> |
| | | <el-button @click="cancel">åæ¶</el-button> |
| | | <el-button type="primary" @click="submitForm">ç¡®å®</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- é¶æ®µä»»å¡ç®¡çå¼¹æ¡ --> |
| | | <el-dialog :title="goalTitle" v-model="goalOpen" width="600px" append-to-body> |
| | | <el-form :model="goalForm" ref="goalFormRef" label-width="100px"> |
| | | <el-form-item label="æå±é¶æ®µ" prop="phaseId"> |
| | | <el-select v-model="goalForm.phaseId" placeholder="è¯·éæ©æå±é¶æ®µ"> |
| | | <el-option |
| | | v-for="phase in phaseList" |
| | | <el-dialog :title="goalTitle" |
| | | v-model="goalOpen" |
| | | width="600px" |
| | | append-to-body> |
| | | <el-form :model="goalForm" |
| | | ref="goalFormRef" |
| | | label-width="100px"> |
| | | <el-form-item label="æå±é¶æ®µ" |
| | | prop="phaseId"> |
| | | <el-select v-model="goalForm.phaseId" |
| | | placeholder="è¯·éæ©æå±é¶æ®µ"> |
| | | <el-option v-for="phase in phaseList" |
| | | :key="phase.phaseId" |
| | | :label="phase.phaseName" |
| | | :value="phase.phaseId" |
| | | /> |
| | | :value="phase.phaseId" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="ç®æ åç§°" prop="taskName"> |
| | | <el-input |
| | | v-model="goalForm.taskName" |
| | | <el-form-item label="ç®æ åç§°" |
| | | prop="taskName"> |
| | | <el-input v-model="goalForm.taskName" |
| | | placeholder="请è¾å
¥ç®æ åç§°" |
| | | maxlength="50" |
| | | /> |
| | | maxlength="50" /> |
| | | </el-form-item> |
| | | <el-form-item label="ç®æ å¼" prop="targetValue"> |
| | | <el-input-number |
| | | v-model="goalForm.targetValue" |
| | | <el-form-item label="ç®æ å¼" |
| | | prop="targetValue"> |
| | | <el-input-number v-model="goalForm.targetValue" |
| | | :min="0" |
| | | :precision="2" |
| | | placeholder="请è¾å
¥ç®æ å¼" |
| | | style="width: 100%" |
| | | /> |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | <el-form-item label="å½åå¼" prop="currentValue"> |
| | | <el-input-number |
| | | v-model="goalForm.currentValue" |
| | | <el-form-item label="å½åå¼" |
| | | prop="currentValue"> |
| | | <el-input-number v-model="goalForm.currentValue" |
| | | :min="0" |
| | | :precision="2" |
| | | placeholder="请è¾å
¥å½åå¼" |
| | | style="width: 100%" |
| | | /> |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | <el-form-item label="åä½" prop="unit"> |
| | | <el-input |
| | | v-model="goalForm.unit" |
| | | <el-form-item label="åä½" |
| | | prop="unit"> |
| | | <el-input v-model="goalForm.unit" |
| | | placeholder="请è¾å
¥åä½" |
| | | maxlength="10" |
| | | /> |
| | | maxlength="10" /> |
| | | </el-form-item> |
| | | <el-form-item label="ä»»å¡å®ææ¥æ" prop="targetDate"> |
| | | <el-date-picker |
| | | v-model="goalForm.targetDate" |
| | | <el-form-item label="ä»»å¡å®ææ¥æ" |
| | | prop="targetDate"> |
| | | <el-date-picker v-model="goalForm.targetDate" |
| | | type="date" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | placeholder="éæ©ç®æ æ¥æ" |
| | | style="width: 100%" |
| | | /> |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | <el-form-item label="å¼å§æ¥æ" prop="startDate"> |
| | | <el-date-picker |
| | | v-model="goalForm.startDate" |
| | | <el-form-item label="å¼å§æ¥æ" |
| | | prop="startDate"> |
| | | <el-date-picker v-model="goalForm.startDate" |
| | | type="date" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | placeholder="éæ©ç®æ æ¥æ" |
| | | style="width: 100%" |
| | | /> |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | <el-form-item label="ç»ææ¥æ" prop="endDate"> |
| | | <el-date-picker |
| | | v-model="goalForm.endDate" |
| | | <el-form-item label="ç»ææ¥æ" |
| | | prop="endDate"> |
| | | <el-date-picker v-model="goalForm.endDate" |
| | | type="date" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | placeholder="éæ©ç®æ æ¥æ" |
| | | style="width: 100%" |
| | | /> |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | <el-form-item label="ç¶æ" prop="status"> |
| | | <el-select v-model="goalForm.status" placeholder="è¯·éæ©ç¶æ"> |
| | | <el-option label="æªå¼å§" value="notStarted" /> |
| | | <el-option label="è¿è¡ä¸" value="inProgress" /> |
| | | <el-option label="已宿" value="completed" /> |
| | | <el-option label="已延è¿" value="delayed" /> |
| | | <el-form-item label="ç¶æ" |
| | | prop="status"> |
| | | <el-select v-model="goalForm.status" |
| | | placeholder="è¯·éæ©ç¶æ"> |
| | | <el-option label="æªå¼å§" |
| | | value="notStarted" /> |
| | | <el-option label="è¿è¡ä¸" |
| | | value="inProgress" /> |
| | | <el-option label="已宿" |
| | | value="completed" /> |
| | | <el-option label="已延è¿" |
| | | value="delayed" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <!-- <el-form-item label="å®æåº¦" prop="completionRate"> |
| | |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="submitGoalForm">ç¡®å®</el-button> |
| | | <el-button @click="cancelGoal">åæ¶</el-button> |
| | | <el-button type="primary" @click="submitGoalForm">ç¡®å®</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted, watch } from 'vue'; |
| | | import { useRoute, useRouter } from 'vue-router'; |
| | | import { ElMessage } from 'element-plus'; |
| | | import TaskTree from './components/taskTree.vue'; |
| | | import MilestoneList from './components/milestoneList.vue'; |
| | | import ProjectForm from './components/projectForm.vue'; |
| | | import PhaseGoalList from './components/phaseGoalList.vue'; |
| | | import { getProject, addProjectPhase, listProjectPhase, addProjectTask, updateProjectTask } from '@/api/oaSystem/projectManagement'; |
| | | import { ref, reactive, onMounted, watch } from "vue"; |
| | | import { useRoute, useRouter } from "vue-router"; |
| | | import { ElMessage } from "element-plus"; |
| | | import TaskTree from "./components/taskTree.vue"; |
| | | import MilestoneList from "./components/milestoneList.vue"; |
| | | import ProjectForm from "./components/projectForm.vue"; |
| | | import PhaseGoalList from "./components/phaseGoalList.vue"; |
| | | import { |
| | | getProject, |
| | | addProjectPhase, |
| | | listProjectPhase, |
| | | addProjectTask, |
| | | updateProjectTask, |
| | | } from "@/api/oaSystem/projectManagement"; |
| | | |
| | | const route = useRoute(); |
| | | const router = useRouter(); |
| | | const open = ref(false); |
| | | const title = ref(''); |
| | | const title = ref(""); |
| | | const projectFormRef = ref(); |
| | | const formRef = ref(); |
| | | // 项ç®ID |
| | |
| | | |
| | | // 项ç®ä¿¡æ¯ |
| | | const projectInfo = reactive({ |
| | | projectId: '', |
| | | projectName: '', |
| | | description: '', |
| | | startDate: '', |
| | | endDate: '', |
| | | managerId: '', |
| | | managerName: '', |
| | | status: 'planning', |
| | | completionRate: 0 |
| | | projectId: "", |
| | | projectName: "", |
| | | description: "", |
| | | startDate: "", |
| | | endDate: "", |
| | | managerId: "", |
| | | managerName: "", |
| | | status: "planning", |
| | | completionRate: 0, |
| | | }); |
| | | |
| | | // ç»è®¡ä¿¡æ¯ |
| | | const statistics = reactive({ |
| | | totalPhases: 0, |
| | | totalTasks: 0, |
| | | completedTasks: 0 |
| | | completedTasks: 0, |
| | | }); |
| | | const form = reactive({ |
| | | phaseId: '', |
| | | phaseName: '', |
| | | startDate: '', |
| | | endDate: '', |
| | | status: 'planning', |
| | | phaseId: "", |
| | | phaseName: "", |
| | | startDate: "", |
| | | endDate: "", |
| | | status: "planning", |
| | | oaProjectId: projectId.value, |
| | | }) |
| | | }); |
| | | |
| | | // é¶æ®µç®æ ç¸å
³ |
| | | const goalOpen = ref(false); |
| | | const goalTitle = ref(''); |
| | | const goalTitle = ref(""); |
| | | const goalFormRef = ref(); |
| | | const phaseList = ref([]); |
| | | const goalForm = reactive({ |
| | | taskId: '', |
| | | phaseId: '', |
| | | taskName: '', |
| | | taskId: "", |
| | | phaseId: "", |
| | | taskName: "", |
| | | targetValue: 100, |
| | | currentValue: 0, |
| | | unit: '%', |
| | | targetDate: '', |
| | | startDate: '', |
| | | endDate: '', |
| | | status: 'notStarted', |
| | | completionRate: 0 |
| | | unit: "%", |
| | | targetDate: "", |
| | | startDate: "", |
| | | endDate: "", |
| | | status: "notStarted", |
| | | completionRate: 0, |
| | | }); |
| | | |
| | | // è·å项ç®è¯¦æ
|
| | | const getProjectDetail = async () => { |
| | | try { |
| | | getProject().then((res)=>{ |
| | | console.log("项ç®è¯¦æ
",res) |
| | | getProject().then(res => { |
| | | console.log("项ç®è¯¦æ
", res); |
| | | const projectData = res.data[projectId.value]; |
| | | // æ´æ°é¡¹ç®ä¿¡æ¯ |
| | | Object.assign(projectInfo, projectData); |
| | |
| | | // å¼ºå¶æ´æ°DOM以确ä¿åç»ä»¶è½æ£ç¡®å·æ° |
| | | // è¿ééè¿è§¦årefreshProjectIdäºä»¶æ¥å¼ºå¶å·æ°åç»ä»¶ |
| | | refreshProjectId.value++; |
| | | }) |
| | | }); |
| | | } catch (error) { |
| | | ElMessage.error('è·å项ç®è¯¦æ
失败'); |
| | | console.error('è·å项ç®è¯¦æ
失败:', error); |
| | | ElMessage.error("è·å项ç®è¯¦æ
失败"); |
| | | console.error("è·å项ç®è¯¦æ
失败:", error); |
| | | } |
| | | }; |
| | | |
| | | // æ´æ°ç»è®¡ä¿¡æ¯ |
| | | const updateStatistics = (projectData) => { |
| | | const updateStatistics = projectData => { |
| | | // è¿éå设projectDataä¸å
å«äºç»è®¡ä¿¡æ¯ |
| | | // å¦ææ²¡æï¼éè¦åç¬è¯·æ±ç»è®¡æ°æ® |
| | | statistics.totalPhases = projectData.phases ? projectData.phases.length : 0; |
| | | statistics.totalTasks = projectData.tasks ? projectData.tasks.length : 0; |
| | | statistics.completedTasks = projectData.tasks ? |
| | | projectData.tasks.filter(task => task.status === 'completed').length : 0; |
| | | statistics.completedTasks = projectData.tasks |
| | | ? projectData.tasks.filter(task => task.status === "completed").length |
| | | : 0; |
| | | }; |
| | | |
| | | // è·å项ç®é¶æ®µå表 |
| | |
| | | const { data } = await listProjectPhase(projectId.value); |
| | | phaseList.value = data.rows || data; |
| | | } catch (error) { |
| | | ElMessage.error('è·å项ç®é¶æ®µå表失败'); |
| | | console.error('è·å项ç®é¶æ®µå表失败:', error); |
| | | ElMessage.error("è·å项ç®é¶æ®µå表失败"); |
| | | console.error("è·å项ç®é¶æ®µå表失败:", error); |
| | | } |
| | | }; |
| | | |
| | | // 计ç®å®æåº¦ |
| | | const calculateCompletionRate = () => { |
| | | if (goalForm.targetValue > 0) { |
| | | goalForm.completionRate = Math.min(Math.round((goalForm.currentValue / goalForm.targetValue) * 100), 100); |
| | | goalForm.completionRate = Math.min( |
| | | Math.round((goalForm.currentValue / goalForm.targetValue) * 100), |
| | | 100 |
| | | ); |
| | | } else { |
| | | goalForm.completionRate = 0; |
| | | } |
| | |
| | | // æ·»å é¶æ®µ |
| | | const handleAddPhase = () => { |
| | | // resetForm(); |
| | | ElMessage.info('æ·»å é¶æ®µåè½å¾
å®ç°'); |
| | | ElMessage.info("æ·»å é¶æ®µåè½å¾
å®ç°"); |
| | | }; |
| | | |
| | | // æ·»å éç¨ç¢ |
| | | const handleAddMilestone = () => { |
| | | resetForm(); |
| | | open.value = true; |
| | | title.value = 'æ°å¢é¡¹ç®é¶æ®µ'; |
| | | title.value = "æ°å¢é¡¹ç®é¶æ®µ"; |
| | | }; |
| | | |
| | | // æ·»å é¶æ®µä»»å¡ |
| | | const handleAddPhaseGoal = () => { |
| | | goalForm.taskId = ''; |
| | | goalForm.phaseId = ''; |
| | | goalForm.taskName = ''; |
| | | goalForm.taskId = ""; |
| | | goalForm.phaseId = ""; |
| | | goalForm.taskName = ""; |
| | | goalForm.targetValue = 0; |
| | | goalForm.currentValue = 0; |
| | | goalForm.unit = '%'; |
| | | goalForm.targetDate = ''; |
| | | goalForm.startDate = ''; |
| | | goalForm.endDate = ''; |
| | | goalForm.status = 'notStarted'; |
| | | goalForm.unit = "%"; |
| | | goalForm.targetDate = ""; |
| | | goalForm.startDate = ""; |
| | | goalForm.endDate = ""; |
| | | goalForm.status = "notStarted"; |
| | | goalForm.completionRate = 0; |
| | | if (goalFormRef.value) { |
| | | goalFormRef.value.resetFields(); |
| | | } |
| | | getPhaseList(); |
| | | goalTitle.value = 'æ°å¢é¶æ®µç®æ '; |
| | | goalTitle.value = "æ°å¢é¶æ®µç®æ "; |
| | | goalOpen.value = true; |
| | | }; |
| | | |
| | |
| | | } else { |
| | | console.log("form",form); |
| | | await addProjectPhase(form); |
| | | ElMessage.success('æ°å¢é¡¹ç®é¶æ®µæå'); |
| | | ElMessage.success("æ°å¢é¡¹ç®é¶æ®µæå"); |
| | | getProjectDetail(); |
| | | } |
| | | open.value = false; |
| | | } catch (error) { |
| | | console.error('æäº¤è¡¨å失败:', error); |
| | | console.error("æäº¤è¡¨å失败:", error); |
| | | } |
| | | }; |
| | | |
| | |
| | | |
| | | const goalData = { |
| | | ...goalForm, |
| | | oaProjectId: projectId.value |
| | | oaProjectId: projectId.value, |
| | | }; |
| | | |
| | | if (goalForm.taskId) { |
| | | await updateProjectTask(goalData); |
| | | ElMessage.success('ä¿®æ¹é¶æ®µç®æ æå'); |
| | | |
| | | ElMessage.success("ä¿®æ¹é¶æ®µç®æ æå"); |
| | | } else { |
| | | await addProjectTask(goalData); |
| | | ElMessage.success('æ°å¢é¶æ®µç®æ æå'); |
| | | |
| | | ElMessage.success("æ°å¢é¶æ®µç®æ æå"); |
| | | } |
| | | // è°ç¨getProjectDetailå·æ°ææç¸å
³æ°æ® |
| | | getProjectDetail(); |
| | | goalOpen.value = false; |
| | | |
| | | } catch (error) { |
| | | console.error('æäº¤é¶æ®µç®æ 表å失败:', error); |
| | | console.error("æäº¤é¶æ®µç®æ 表å失败:", error); |
| | | } |
| | | }; |
| | | |
| | | // éç½®éç¨ç¢è¡¨å |
| | | const resetForm = () => { |
| | | form.phaseId = ''; |
| | | form.phaseName = ''; |
| | | form.startDate = ''; |
| | | form.endDate = ''; |
| | | form.status = 'planning'; |
| | | form.phaseId = ""; |
| | | form.phaseName = ""; |
| | | form.startDate = ""; |
| | | form.endDate = ""; |
| | | form.status = "planning"; |
| | | form.oaProjectId = projectId.value; |
| | | if (formRef.value) { |
| | | formRef.value.resetFields(); |
| | |
| | | open.value = false; |
| | | }; |
| | | // ç¼è¾é¶æ®µä»»å¡ |
| | | const handleEditPhaseGoal = async (goal) => { |
| | | const handleEditPhaseGoal = async goal => { |
| | | // å¤å¶ç®æ æ°æ®å°è¡¨å |
| | | Object.assign(goalForm, goal); |
| | | |
| | |
| | | await getPhaseList(); |
| | | |
| | | // æå¼ç¼è¾å¼¹çª |
| | | goalTitle.value = 'ç¼è¾é¶æ®µç®æ '; |
| | | goalTitle.value = "ç¼è¾é¶æ®µç®æ "; |
| | | goalOpen.value = true; |
| | | }; |
| | | // è·åç¶ææ ç¾ç±»å |
| | | const getStatusType = (status) => { |
| | | const getStatusType = status => { |
| | | const statusTypeMap = { |
| | | planning: 'info', |
| | | inProgress: 'primary', |
| | | completed: 'success', |
| | | paused: 'warning' |
| | | planning: "info", |
| | | inProgress: "primary", |
| | | completed: "success", |
| | | paused: "warning", |
| | | }; |
| | | return statusTypeMap[status] || 'default'; |
| | | return statusTypeMap[status] || "default"; |
| | | }; |
| | | |
| | | // è·åç¶æææ¬ |
| | | const getStatusText = (status) => { |
| | | const getStatusText = status => { |
| | | const statusTextMap = { |
| | | planning: 'è§åä¸', |
| | | inProgress: 'è¿è¡ä¸', |
| | | completed: '已宿', |
| | | paused: 'å·²æå' |
| | | planning: "è§åä¸", |
| | | inProgress: "è¿è¡ä¸", |
| | | completed: "已宿", |
| | | paused: "å·²æå", |
| | | }; |
| | | return statusTextMap[status] || status; |
| | | }; |
| | | |
| | | // çå¬è·¯ç±åæ°åå |
| | | watch(() => route.params.projectId, (newProjectId) => { |
| | | watch( |
| | | () => route.params.projectId, |
| | | newProjectId => { |
| | | // console.log('è·¯ç±åæ°åå:', projectId); |
| | | if (newProjectId) { |
| | | projectId.value = newProjectId; |
| | | getProjectDetail(); |
| | | } |
| | | }); |
| | | } |
| | | ); |
| | | |
| | | // çå¬å½åå¼åç®æ å¼ååï¼éæ°è®¡ç®å®æåº¦ |
| | | watch(() => [goalForm.currentValue, goalForm.targetValue], () => { |
| | | watch( |
| | | () => [goalForm.currentValue, goalForm.targetValue], |
| | | () => { |
| | | calculateCompletionRate(); |
| | | }); |
| | | } |
| | | ); |
| | | |
| | | // åå§å |
| | | onMounted(() => { |
| | |
| | | <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" |
| | | <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> |
| | | 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" |
| | | <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" |
| | | /> |
| | | @current-change="handleCurrentChange" /> |
| | | </div> |
| | | </el-card> |
| | | |
| | | <!-- æ°å¢/ç¼è¾å¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | v-model="dialogVisible" |
| | | <el-dialog v-model="dialogVisible" |
| | | :title="dialogType === 'add' ? 'æ°å¢éè´è®¡å' : 'ç¼è¾éè´è®¡å'" |
| | | width="1000px" |
| | | :close-on-click-modal="false" |
| | | > |
| | | :close-on-click-modal="false"> |
| | | <div class="form-container"> |
| | | <!-- åºæ¬ä¿¡æ¯ --> |
| | | <div class="form-section"> |
| | | <div class="section-title">åºæ¬ä¿¡æ¯</div> |
| | | <el-form |
| | | ref="formRef" |
| | | <el-form ref="formRef" |
| | | :model="formData" |
| | | :rules="formRules" |
| | | label-width="120px" |
| | | > |
| | | 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" |
| | | <el-form-item label="æè¿°" |
| | | prop="description"> |
| | | <el-input v-model="formData.description" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥è®¡åæè¿°" |
| | | /> |
| | | 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-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" |
| | | <el-form-item label="计ç®å
¬å¼" |
| | | prop="formula" |
| | | required> |
| | | <el-input v-model="formData.formula" |
| | | placeholder="ä¾å¦: é¢è®¡åºåºæ°é - ç°æåºå + å®å
¨åºå - é¢è®¡å
¥åºæ°é" |
| | | @input="validateFormula" |
| | | /> |
| | | @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> |
| | | </div> |
| | | |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="handleSubmit" |
| | | :loading="submitLoading">ç¡®å®</el-button> |
| | | <el-button @click="dialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="handleSubmit" :loading="submitLoading">ç¡®å®</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- 产åéæ©å¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | v-model="productSelectDialogVisible" |
| | | <el-dialog v-model="productSelectDialogVisible" |
| | | title="éæ©äº§å" |
| | | width="800px" |
| | | :close-on-click-modal="false" |
| | | > |
| | | :close-on-click-modal="false"> |
| | | <div class="product-select"> |
| | | <el-alert |
| | | title="è¯·éæ©è¦è®¡ç®ç产å" |
| | | <el-alert title="è¯·éæ©è¦è®¡ç®ç产å" |
| | | type="info" |
| | | :closable="false" |
| | | show-icon |
| | | > |
| | | show-icon> |
| | | <template #default> |
| | | <p>éæ©äº§ååï¼ç³»ç»å°æ ¹æ®å½å计ç®å
¬å¼å产ååºåæ
åµè¿è¡è®¡ç®ã</p> |
| | | </template> |
| | | </el-alert> |
| | | |
| | | <el-table |
| | | v-loading="productLoading" |
| | | <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" /> |
| | | 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> |
| | | |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button @click="productSelectDialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="handleConfirmProductSelection" :disabled="selectedProducts.length === 0"> |
| | | <el-button type="primary" |
| | | @click="handleConfirmProductSelection" |
| | | :disabled="selectedProducts.length === 0"> |
| | | ç¡®è®¤è®¡ç® |
| | | </el-button> |
| | | <el-button @click="productSelectDialogVisible = false">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- 计ç®ç»æå¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | v-model="calculateDialogVisible" |
| | | <el-dialog v-model="calculateDialogVisible" |
| | | title="éè´è®¡ç®ç»æ" |
| | | width="1000px" |
| | | :close-on-click-modal="false" |
| | | > |
| | | :close-on-click-modal="false"> |
| | | <div class="calculate-result"> |
| | | <el-alert |
| | | title="计ç®ç»æ" |
| | | <el-alert title="计ç®ç»æ" |
| | | type="success" |
| | | :closable="false" |
| | | show-icon |
| | | > |
| | | 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> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="handleCreatePurchaseOrder">确认</el-button> |
| | | <el-button @click="calculateDialogVisible = false">å
³é</el-button> |
| | | <el-button type="primary" @click="handleCreatePurchaseOrder">确认</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | 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 { 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"; |
| | | |
| | | // ååºå¼æ°æ® |
| | | 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: '' |
| | | }) |
| | | planName: "", |
| | | status: "", |
| | | }); |
| | | |
| | | // åé¡µæ°æ® |
| | | const pagination = reactive({ |
| | | current: 1, |
| | | size: 20 |
| | | }) |
| | | size: 20, |
| | | }); |
| | | |
| | | // è¡¨åæ°æ® |
| | | const formData = reactive({ |
| | | code: '', |
| | | planName: '', |
| | | description: '', |
| | | status: '', |
| | | code: "", |
| | | planName: "", |
| | | description: "", |
| | | status: "", |
| | | isSystemPreset: false, |
| | | formula: '', |
| | | formula: "", |
| | | // 计ç®åæ° |
| | | considerExistingStock: false, |
| | | warehouseControl: false, |
| | |
| | | // æ±æ»åå¹¶é项 |
| | | summaryMaterial: false, |
| | | summaryAuxAttributes: false, |
| | | summaryDemandDate: false |
| | | }) |
| | | summaryDemandDate: false, |
| | | }); |
| | | |
| | | // å½åæ¿æ´»çæ ç¾é¡µ |
| | | const activeTab = ref('demand') |
| | | const activeTab = ref("demand"); |
| | | |
| | | // 表åéªè¯è§å |
| | | const formRules = { |
| | | planName: [ |
| | | { required: true, message: '请è¾å
¥è®¡ååç§°', trigger: 'blur' } |
| | | ], |
| | | status: [ |
| | | { required: true, message: 'è¯·éæ©ç¶æ', trigger: 'change' } |
| | | ], |
| | | formula: [ |
| | | { required: true, message: '请è¾å
¥è®¡ç®å
¬å¼', trigger: 'blur' } |
| | | ] |
| | | } |
| | | planName: [{ required: true, message: "请è¾å
¥è®¡ååç§°", trigger: "blur" }], |
| | | status: [{ required: true, message: "è¯·éæ©ç¶æ", trigger: "change" }], |
| | | formula: [{ required: true, message: "请è¾å
¥è®¡ç®å
¬å¼", trigger: "blur" }], |
| | | }; |
| | | |
| | | // è¡¨æ ¼æ°æ® |
| | | const tableData = ref([]) |
| | | const tableData = ref([]); |
| | | |
| | | // 产ååè¡¨æ°æ® |
| | | const productList = ref([ |
| | | { |
| | | id: 4, |
| | | productName: '产åD', |
| | | productCode: 'PD004', |
| | | productName: "产åD", |
| | | productCode: "PD004", |
| | | existingStock: 90, |
| | | safetyStock: 40, |
| | | expectedOutbound: 160, |
| | | expectedInbound: 35 |
| | | } |
| | | ]) |
| | | expectedInbound: 35, |
| | | }, |
| | | ]); |
| | | |
| | | // 计ç®ç»ææ°æ® |
| | | const calculateResult = ref([ |
| | | { |
| | | productName: '产åA', |
| | | productName: "产åA", |
| | | existingStock: 100, |
| | | safetyStock: 50, |
| | | expectedOutbound: 200, |
| | | expectedInbound: 30, |
| | | weeklyNetDemand: 120, |
| | | suggestedPurchase: 150 |
| | | suggestedPurchase: 150, |
| | | }, |
| | | { |
| | | productName: '产åB', |
| | | productName: "产åB", |
| | | existingStock: 80, |
| | | safetyStock: 30, |
| | | expectedOutbound: 150, |
| | | expectedInbound: 20, |
| | | weeklyNetDemand: 100, |
| | | suggestedPurchase: 120 |
| | | } |
| | | ]) |
| | | const total = ref(0) |
| | | suggestedPurchase: 120, |
| | | }, |
| | | ]); |
| | | const total = ref(0); |
| | | // æ¹æ³ |
| | | const handleSearch = () => { |
| | | pagination.current = 1 |
| | | loadData() |
| | | } |
| | | pagination.current = 1; |
| | | loadData(); |
| | | }; |
| | | |
| | | const handleReset = () => { |
| | | Object.assign(searchForm, { |
| | | planName: '', |
| | | status: '' |
| | | }) |
| | | handleSearch() |
| | | } |
| | | planName: "", |
| | | status: "", |
| | | }); |
| | | handleSearch(); |
| | | }; |
| | | |
| | | const loadData = () => { |
| | | loading.value = true |
| | | 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 |
| | | tableData.value = res.data.records; |
| | | total.value = res.data.total; |
| | | loading.value = false; |
| | | } |
| | | }) |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | const handleAdd = () => { |
| | | dialogType.value = 'add' |
| | | resetForm() |
| | | dialogType.value = "add"; |
| | | resetForm(); |
| | | // èªå¨çæç¼ç |
| | | formData.code = 'CGJH' + String(Date.now()).slice(-4) |
| | | dialogVisible.value = true |
| | | } |
| | | 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 handleEdit = row => { |
| | | dialogType.value = "edit"; |
| | | Object.assign(formData, row); |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | const handleDelete = async (row) => { |
| | | const handleDelete = async row => { |
| | | try { |
| | | await ElMessageBox.confirm('ç¡®å®è¦å é¤è¿ä¸ªéè´è®¡ååï¼', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | }) |
| | | let ids = [row.id] |
| | | await ElMessageBox.confirm("ç¡®å®è¦å é¤è¿ä¸ªéè´è®¡ååï¼", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }); |
| | | let ids = [row.id]; |
| | | del(ids).then(res =>{ |
| | | if(res.code === 200){ |
| | | ElMessage.success('å 餿å') |
| | | loadData() |
| | | ElMessage.success("å 餿å"); |
| | | loadData(); |
| | | } |
| | | }) |
| | | }); |
| | | } catch { |
| | | // ç¨æ·åæ¶å é¤ |
| | | } |
| | | } |
| | | }; |
| | | |
| | | const handleSubmit = async () => { |
| | | try { |
| | | // 表åéªè¯ |
| | | if (!formData.planName || !formData.formula) { |
| | | ElMessage.error('请填åå¿
填项') |
| | | return |
| | | ElMessage.error("请填åå¿
填项"); |
| | | return; |
| | | } |
| | | |
| | | submitLoading.value = true |
| | | submitLoading.value = true; |
| | | |
| | | if (dialogType.value === 'add') { |
| | | if (dialogType.value === "add") { |
| | | add(formData).then(res => { |
| | | if(res.code === 200){ |
| | | ElMessage.success('æ°å¢æå') |
| | | dialogVisible.value = false |
| | | loadData() |
| | | ElMessage.success("æ°å¢æå"); |
| | | dialogVisible.value = false; |
| | | loadData(); |
| | | } |
| | | }) |
| | | }); |
| | | } else { |
| | | // ç¼è¾ |
| | | update(formData).then(res => { |
| | | if(res.code === 200){ |
| | | ElMessage.success('ç¼è¾æå') |
| | | dialogVisible.value = false |
| | | loadData() |
| | | ElMessage.success("ç¼è¾æå"); |
| | | dialogVisible.value = false; |
| | | loadData(); |
| | | } |
| | | }) |
| | | }); |
| | | } |
| | | |
| | | |
| | | } catch (error) { |
| | | ElMessage.error('æä½å¤±è´¥') |
| | | ElMessage.error("æä½å¤±è´¥"); |
| | | } finally { |
| | | submitLoading.value = false |
| | | submitLoading.value = false; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | const resetForm = () => { |
| | | Object.assign(formData, { |
| | | code: '', |
| | | planName: '', |
| | | description: '', |
| | | status: '', |
| | | code: "", |
| | | planName: "", |
| | | description: "", |
| | | status: "", |
| | | isSystemPreset: false, |
| | | formula: 'é¢è®¡åºåºæ°é - ç°æåºå + å®å
¨åºå - é¢è®¡å
¥åºæ°é', |
| | | formula: "é¢è®¡åºåºæ°é - ç°æåºå + å®å
¨åºå - é¢è®¡å
¥åºæ°é", |
| | | // 计ç®åæ° |
| | | considerExistingStock: false, |
| | | warehouseControl: false, |
| | |
| | | // æ±æ»åå¹¶é项 |
| | | summaryMaterial: false, |
| | | summaryAuxAttributes: false, |
| | | summaryDemandDate: false |
| | | }) |
| | | activeTab.value = 'demand' |
| | | } |
| | | summaryDemandDate: false, |
| | | }); |
| | | activeTab.value = "demand"; |
| | | }; |
| | | |
| | | const validateFormula = () => { |
| | | // ç®åçå
¬å¼éªè¯ |
| | | const formula = formData.formula |
| | | const formula = formData.formula; |
| | | if (formula && !/^[a-zA-Z\u4e00-\u9fa5\s\*\+\-\/\(\)\d\.]+$/.test(formula)) { |
| | | ElMessage.warning('å
¬å¼æ ¼å¼å¯è½ä¸æ£ç¡®ï¼è¯·æ£æ¥') |
| | | ElMessage.warning("å
¬å¼æ ¼å¼å¯è½ä¸æ£ç¡®ï¼è¯·æ£æ¥"); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | const handleCalculate = (row) => { |
| | | currentPlan.value = row |
| | | productSelectDialogVisible.value = true |
| | | loadProductList() |
| | | } |
| | | const handleCalculate = row => { |
| | | currentPlan.value = row; |
| | | productSelectDialogVisible.value = true; |
| | | loadProductList(); |
| | | }; |
| | | |
| | | const loadProductList = () => { |
| | | productLoading.value = true |
| | | productLoading.value = true; |
| | | // 模æå è½½äº§åæ°æ® |
| | | listPageCopy({size:-1}).then(res => { |
| | | if(res.code === 200){ |
| | | productList.value = res.data.records |
| | | productLoading.value = false |
| | | productList.value = res.data.records; |
| | | productLoading.value = false; |
| | | } |
| | | }) |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | const handleProductSelectionChange = (selection) => { |
| | | selectedProducts.value = selection |
| | | } |
| | | const handleProductSelectionChange = selection => { |
| | | selectedProducts.value = selection; |
| | | }; |
| | | |
| | | const handleConfirmProductSelection = () => { |
| | | if (selectedProducts.value.length === 0) { |
| | | ElMessage.warning('è¯·éæ©è¦è®¡ç®ç产å') |
| | | return |
| | | ElMessage.warning("è¯·éæ©è¦è®¡ç®ç产å"); |
| | | return; |
| | | } |
| | | |
| | | ElMessage.success(`æ£å¨è®¡ç® ${currentPlan.value.planName} çéè´éæ±...`) |
| | | productSelectDialogVisible.value = false |
| | | ElMessage.success(`æ£å¨è®¡ç® ${currentPlan.value.planName} çéè´éæ±...`); |
| | | productSelectDialogVisible.value = false; |
| | | |
| | | // æ ¹æ®éæ©ç产åå计ç®å
¬å¼è¿è¡è®¡ç® |
| | | calculateWithSelectedProducts() |
| | | } |
| | | 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) |
| | | const weeklyNetDemand = |
| | | product.inboundNum - |
| | | product.inboundNum0 + |
| | | product.inboundNum - |
| | | product.inboundNum0; |
| | | const suggestedPurchase = Math.max(0, weeklyNetDemand); |
| | | |
| | | return { |
| | | productCategory: product.productCategory, |
| | |
| | | inboundNum0: product.inboundNum0, |
| | | inboundNum: product.inboundNum, |
| | | weeklyNetDemand: weeklyNetDemand, |
| | | suggestedPurchase: suggestedPurchase |
| | | } |
| | | }) |
| | | suggestedPurchase: suggestedPurchase, |
| | | }; |
| | | }); |
| | | |
| | | calculateResult.value = result |
| | | calculateDialogVisible.value = true |
| | | } |
| | | |
| | | calculateResult.value = result; |
| | | calculateDialogVisible.value = true; |
| | | }; |
| | | |
| | | const handleCreatePurchaseOrder = () => { |
| | | calculateDialogVisible.value = false |
| | | } |
| | | calculateDialogVisible.value = false; |
| | | }; |
| | | const { proxy } = getCurrentInstance(); |
| | | const handleExport = () => { |
| | | ElMessageBox.confirm("å
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | |
| | | .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() |
| | | }) |
| | | loadData(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | |
| | | <div class="app-container"> |
| | | <el-card class="box-card"> |
| | | <!-- æç´¢åºå --> |
| | | <el-row :gutter="20" class="search-row"> |
| | | <el-row :gutter="20" |
| | | class="search-row"> |
| | | <el-col :span="6"> |
| | | <el-input |
| | | v-model="searchForm.productName" |
| | | <el-input v-model="searchForm.productName" |
| | | placeholder="请è¾å
¥äº§ååç§°" |
| | | clearable |
| | | @keyup.enter="handleSearch" |
| | | > |
| | | @keyup.enter="handleSearch"> |
| | | <template #prefix> |
| | | <el-icon><Search /></el-icon> |
| | | <el-icon> |
| | | <Search /> |
| | | </el-icon> |
| | | </template> |
| | | </el-input> |
| | | </el-col> |
| | | <el-col :span="6"> |
| | | <el-select v-model="searchForm.identifierType" placeholder="è¯·éæ©æ è¯ç±»å" clearable> |
| | | <el-option label="äºç»´ç " value="äºç»´ç "></el-option> |
| | | <el-option label="é²ä¼ªç " value="é²ä¼ªç "></el-option> |
| | | <el-select v-model="searchForm.identifierType" |
| | | placeholder="è¯·éæ©æ è¯ç±»å" |
| | | clearable> |
| | | <el-option label="äºç»´ç " |
| | | value="äºç»´ç "></el-option> |
| | | <el-option label="é²ä¼ªç " |
| | | value="é²ä¼ªç "></el-option> |
| | | </el-select> |
| | | </el-col> |
| | | <el-col :span="6"> |
| | | <el-select v-model="searchForm.status" placeholder="è¯·éæ©ç¶æ" clearable> |
| | | <el-option label="å·²çæ" value="å·²çæ"></el-option> |
| | | <el-option label="å·²åé
" value="å·²åé
"></el-option> |
| | | <el-option label="已使ç¨" value="已使ç¨"></el-option> |
| | | <el-option label="å·²ä½åº" value="å·²ä½åº"></el-option> |
| | | <el-select v-model="searchForm.status" |
| | | placeholder="è¯·éæ©ç¶æ" |
| | | clearable> |
| | | <el-option label="å·²çæ" |
| | | value="å·²çæ"></el-option> |
| | | <el-option label="å·²åé
" |
| | | value="å·²åé
"></el-option> |
| | | <el-option label="已使ç¨" |
| | | value="已使ç¨"></el-option> |
| | | <el-option label="å·²ä½åº" |
| | | value="å·²ä½åº"></el-option> |
| | | </el-select> |
| | | </el-col> |
| | | <el-col :span="6"> |
| | | <el-button type="primary" @click="handleSearch">æç´¢</el-button> |
| | | <el-button type="primary" |
| | | @click="handleSearch">æç´¢</el-button> |
| | | <el-button @click="resetSearch">éç½®</el-button> |
| | | <el-button style="float: right;" type="primary" @click="handleAdd"> |
| | | <el-button style="float: right;" |
| | | type="primary" |
| | | @click="handleAdd"> |
| | | æ°å¢æ è¯ |
| | | </el-button> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <!-- äº§åæ è¯å表 --> |
| | | <el-table |
| | | :data="filteredList" |
| | | <el-table :data="filteredList" |
| | | style="width: 100%" |
| | | v-loading="loading" |
| | | border |
| | | stripe |
| | | height="calc(100vh - 22em)" |
| | | > |
| | | <el-table-column prop="id" label="ID" width="80" align="center"/> |
| | | <el-table-column prop="productName" label="产ååç§°" width="150" /> |
| | | <el-table-column prop="productCode" label="产åç¼ç " width="120" /> |
| | | <el-table-column prop="batchNo" label="æ¹æ¬¡å·" width="120" /> |
| | | <el-table-column prop="identifierType" label="æ è¯ç±»å" width="100"> |
| | | height="calc(100vh - 22em)"> |
| | | <el-table-column prop="id" |
| | | label="ID" |
| | | width="80" |
| | | align="center" /> |
| | | <el-table-column prop="productName" |
| | | label="产ååç§°" |
| | | width="150" /> |
| | | <el-table-column prop="productCode" |
| | | label="产åç¼ç " |
| | | width="120" /> |
| | | <el-table-column prop="batchNo" |
| | | label="æ¹æ¬¡å·" |
| | | width="120" /> |
| | | <el-table-column prop="identifierType" |
| | | label="æ è¯ç±»å" |
| | | width="100"> |
| | | <template #default="scope"> |
| | | <el-tag :type="getIdentifierTypeType(scope.row.identifierType)"> |
| | | {{ scope.row.identifierType }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="identifierCode" label="æ è¯ç " /> |
| | | <el-table-column prop="status" label="ç¶æ" width="100"> |
| | | <el-table-column prop="identifierCode" |
| | | label="æ è¯ç " /> |
| | | <el-table-column prop="status" |
| | | label="ç¶æ" |
| | | width="100"> |
| | | <template #default="scope"> |
| | | <el-tag :type="getStatusType(scope.row.status)"> |
| | | {{ scope.row.status }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="generateTime" label="çææ¶é´" width="160" /> |
| | | <el-table-column label="æä½" fixed="right" align="center" width="280"> |
| | | <el-table-column prop="generateTime" |
| | | label="çææ¶é´" |
| | | width="160" /> |
| | | <el-table-column label="æä½" |
| | | fixed="right" |
| | | align="center" |
| | | width="280"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" @click="handleView(scope.row)">æ¥ç</el-button> |
| | | <el-button link type="primary" @click="handleEdit(scope.row)">ç¼è¾</el-button> |
| | | <el-button link type="success" @click="generateQRCode(scope.row)">çæäºç»´ç </el-button> |
| | | <el-button link type="primary" @click="handleExport(scope.row)">导åº</el-button> |
| | | <el-button link type="primary" @click="handleReassign(scope.row)" v-if="scope.row.status === 'å·²åé
'">éæ°åé
</el-button> |
| | | <el-button link type="danger" @click="handleDelete(scope.row)">å é¤</el-button> |
| | | <el-button link |
| | | type="primary" |
| | | @click="handleView(scope.row)">æ¥ç</el-button> |
| | | <el-button link |
| | | type="primary" |
| | | @click="handleEdit(scope.row)">ç¼è¾</el-button> |
| | | <el-button link |
| | | type="success" |
| | | @click="generateQRCode(scope.row)">çæäºç»´ç </el-button> |
| | | <el-button link |
| | | type="primary" |
| | | @click="handleExport(scope.row)">导åº</el-button> |
| | | <el-button link |
| | | type="primary" |
| | | @click="handleReassign(scope.row)" |
| | | v-if="scope.row.status === 'å·²åé
'">éæ°åé
</el-button> |
| | | <el-button link |
| | | type="danger" |
| | | @click="handleDelete(scope.row)">å é¤</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <!-- å页 --> |
| | | <pagination |
| | | :total="pagination.total" |
| | | <pagination :total="pagination.total" |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | :page="pagination.currentPage" |
| | | :limit="pagination.pageSize" |
| | | @pagination="handleCurrentChange" |
| | | /> |
| | | @pagination="handleCurrentChange" /> |
| | | </el-card> |
| | | |
| | | <!-- æ°å¢/ç¼è¾å¯¹è¯æ¡ --> |
| | | <el-dialog v-model="dialogVisible" :title="dialogTitle" width="700px"> |
| | | <el-form :model="form" :rules="rules" ref="formRef" label-width="100px"> |
| | | <el-dialog v-model="dialogVisible" |
| | | :title="dialogTitle" |
| | | width="700px"> |
| | | <el-form :model="form" |
| | | :rules="rules" |
| | | ref="formRef" |
| | | label-width="100px"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="产ååç§°" prop="productName"> |
| | | <el-input v-model="form.productName" placeholder="请è¾å
¥äº§ååç§°"></el-input> |
| | | <el-form-item label="产ååç§°" |
| | | prop="productName"> |
| | | <el-input v-model="form.productName" |
| | | placeholder="请è¾å
¥äº§ååç§°"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="产åç¼ç " prop="productCode"> |
| | | <el-input v-model="form.productCode" placeholder="请è¾å
¥äº§åç¼ç "></el-input> |
| | | <el-form-item label="产åç¼ç " |
| | | prop="productCode"> |
| | | <el-input v-model="form.productCode" |
| | | placeholder="请è¾å
¥äº§åç¼ç "></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ¹æ¬¡å·" prop="batchNo"> |
| | | <el-input v-model="form.batchNo" placeholder="请è¾å
¥æ¹æ¬¡å·"></el-input> |
| | | <el-form-item label="æ¹æ¬¡å·" |
| | | prop="batchNo"> |
| | | <el-input v-model="form.batchNo" |
| | | placeholder="请è¾å
¥æ¹æ¬¡å·"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ è¯ç±»å" prop="identifierType"> |
| | | <el-select v-model="form.identifierType" placeholder="è¯·éæ©æ è¯ç±»å" style="width: 100%"> |
| | | <el-option label="äºç»´ç " value="äºç»´ç "></el-option> |
| | | <el-option label="é²ä¼ªç " value="é²ä¼ªç "></el-option> |
| | | <el-form-item label="æ è¯ç±»å" |
| | | prop="identifierType"> |
| | | <el-select v-model="form.identifierType" |
| | | placeholder="è¯·éæ©æ è¯ç±»å" |
| | | style="width: 100%"> |
| | | <el-option label="äºç»´ç " |
| | | value="äºç»´ç "></el-option> |
| | | <el-option label="é²ä¼ªç " |
| | | value="é²ä¼ªç "></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="çææ°é" prop="quantity"> |
| | | <el-input-number v-model="form.quantity" :min="1" :max="10000" style="width: 100%"></el-input-number> |
| | | <el-form-item label="çææ°é" |
| | | prop="quantity"> |
| | | <el-input-number v-model="form.quantity" |
| | | :min="1" |
| | | :max="10000" |
| | | style="width: 100%"></el-input-number> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç¶æ" prop="status"> |
| | | <el-select v-model="form.status" placeholder="è¯·éæ©ç¶æ" style="width: 100%"> |
| | | <el-option label="å·²çæ" value="å·²çæ"></el-option> |
| | | <el-option label="å·²åé
" value="å·²åé
"></el-option> |
| | | <el-option label="已使ç¨" value="已使ç¨"></el-option> |
| | | <el-option label="å·²ä½åº" value="å·²ä½åº"></el-option> |
| | | <el-form-item label="ç¶æ" |
| | | prop="status"> |
| | | <el-select v-model="form.status" |
| | | placeholder="è¯·éæ©ç¶æ" |
| | | style="width: 100%"> |
| | | <el-option label="å·²çæ" |
| | | value="å·²çæ"></el-option> |
| | | <el-option label="å·²åé
" |
| | | value="å·²åé
"></el-option> |
| | | <el-option label="已使ç¨" |
| | | value="已使ç¨"></el-option> |
| | | <el-option label="å·²ä½åº" |
| | | value="å·²ä½åº"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="夿³¨" prop="remark"> |
| | | <el-input type="textarea" v-model="form.remark" placeholder="请è¾å
¥å¤æ³¨ä¿¡æ¯" rows="3"></el-input> |
| | | <el-form-item label="夿³¨" |
| | | prop="remark"> |
| | | <el-input type="textarea" |
| | | v-model="form.remark" |
| | | placeholder="请è¾å
¥å¤æ³¨ä¿¡æ¯" |
| | | rows="3"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="handleSubmit">ç¡® å®</el-button> |
| | | <el-button @click="dialogVisible = false">å æ¶</el-button> |
| | | <el-button type="primary" @click="handleSubmit">ç¡® å®</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- æ è¯çæå¯¹è¯æ¡ --> |
| | | <el-dialog v-model="generateDialogVisible" title="æ è¯çæ" width="500px"> |
| | | <el-dialog v-model="generateDialogVisible" |
| | | title="æ è¯çæ" |
| | | width="500px"> |
| | | <el-form label-width="100px"> |
| | | <el-form-item label="产ååç§°"> |
| | | <span>{{ currentProduct.productName }}</span> |
| | |
| | | <el-form-item label="æ è¯ç±»å"> |
| | | <span>{{ currentProduct.identifierType }}</span> |
| | | </el-form-item> |
| | | <el-form-item label="çææ°é" prop="generateQuantity"> |
| | | <el-input-number v-model="generateQuantity" :min="1" :max="10000" style="width: 100%"></el-input-number> |
| | | <el-form-item label="çææ°é" |
| | | prop="generateQuantity"> |
| | | <el-input-number v-model="generateQuantity" |
| | | :min="1" |
| | | :max="10000" |
| | | style="width: 100%"></el-input-number> |
| | | </el-form-item> |
| | | <el-form-item label="ç¼ç è§å" prop="codeRule"> |
| | | <el-select v-model="codeRule" placeholder="è¯·éæ©ç¼ç è§å" style="width: 100%"> |
| | | <el-option label="产åç¼ç +æ¹æ¬¡å·+åºå·" value="产åç¼ç +æ¹æ¬¡å·+åºå·"></el-option> |
| | | <el-option label="æ¶é´æ³+éæºæ°" value="æ¶é´æ³+éæºæ°"></el-option> |
| | | <el-option label="èªå®ä¹è§å" value="èªå®ä¹è§å"></el-option> |
| | | <el-form-item label="ç¼ç è§å" |
| | | prop="codeRule"> |
| | | <el-select v-model="codeRule" |
| | | placeholder="è¯·éæ©ç¼ç è§å" |
| | | style="width: 100%"> |
| | | <el-option label="产åç¼ç +æ¹æ¬¡å·+åºå·" |
| | | value="产åç¼ç +æ¹æ¬¡å·+åºå·"></el-option> |
| | | <el-option label="æ¶é´æ³+éæºæ°" |
| | | value="æ¶é´æ³+éæºæ°"></el-option> |
| | | <el-option label="èªå®ä¹è§å" |
| | | value="èªå®ä¹è§å"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="èªå®ä¹åç¼" prop="customPrefix" v-if="codeRule === 'èªå®ä¹è§å'"> |
| | | <el-input v-model="customPrefix" placeholder="请è¾å
¥èªå®ä¹åç¼"></el-input> |
| | | <el-form-item label="èªå®ä¹åç¼" |
| | | prop="customPrefix" |
| | | v-if="codeRule === 'èªå®ä¹è§å'"> |
| | | <el-input v-model="customPrefix" |
| | | placeholder="请è¾å
¥èªå®ä¹åç¼"></el-input> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="generateIdentifiers">ç æ</el-button> |
| | | <el-button @click="generateDialogVisible = false">å æ¶</el-button> |
| | | <el-button type="primary" @click="generateIdentifiers">ç æ</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- éæ°åé
å¯¹è¯æ¡ --> |
| | | <el-dialog v-model="reassignDialogVisible" title="éæ°åé
æ è¯" width="500px"> |
| | | <el-dialog v-model="reassignDialogVisible" |
| | | title="éæ°åé
æ è¯" |
| | | width="500px"> |
| | | <el-form label-width="100px"> |
| | | <el-form-item label="产ååç§°"> |
| | | <span>{{ currentProduct.productName }}</span> |
| | |
| | | <el-form-item label="æ è¯ç "> |
| | | <span>{{ currentProduct.identifierCode }}</span> |
| | | </el-form-item> |
| | | <el-form-item label="æ°æ¹æ¬¡å·" prop="newBatchNo"> |
| | | <el-input v-model="newBatchNo" placeholder="请è¾å
¥æ°æ¹æ¬¡å·"></el-input> |
| | | <el-form-item label="æ°æ¹æ¬¡å·" |
| | | prop="newBatchNo"> |
| | | <el-input v-model="newBatchNo" |
| | | placeholder="请è¾å
¥æ°æ¹æ¬¡å·"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="åé
åå " prop="reassignReason"> |
| | | <el-input type="textarea" v-model="reassignReason" rows="3" placeholder="请è¾å
¥éæ°åé
åå "></el-input> |
| | | <el-form-item label="åé
åå " |
| | | prop="reassignReason"> |
| | | <el-input type="textarea" |
| | | v-model="reassignReason" |
| | | rows="3" |
| | | placeholder="请è¾å
¥éæ°åé
åå "></el-input> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="saveReassign">ç¡® å®</el-button> |
| | | <el-button @click="reassignDialogVisible = false">å æ¶</el-button> |
| | | <el-button type="primary" @click="saveReassign">ç¡® å®</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- äºç»´ç é¢è§å¯¹è¯æ¡ --> |
| | | <el-dialog v-model="qrCodeDialogVisible" title="äºç»´ç é¢è§" width="500px" center> |
| | | <el-dialog v-model="qrCodeDialogVisible" |
| | | title="äºç»´ç é¢è§" |
| | | width="500px" |
| | | center> |
| | | <div class="qr-preview-container"> |
| | | <div v-if="qrCodeUrl" class="qr-image-container"> |
| | | <img :src="qrCodeUrl" alt="äºç»´ç " class="qr-image" /> |
| | | <div v-if="qrCodeUrl" |
| | | class="qr-image-container"> |
| | | <img :src="qrCodeUrl" |
| | | alt="äºç»´ç " |
| | | class="qr-image" /> |
| | | <div class="qr-info"> |
| | | <p><strong>产ååç§°ï¼</strong>{{ currentQRProduct.productName }}</p> |
| | | <p><strong>产åç¼ç ï¼</strong>{{ currentQRProduct.productCode }}</p> |
| | |
| | | <p><strong>æ è¯ç±»åï¼</strong>{{ currentQRProduct.identifierType }}</p> |
| | | </div> |
| | | </div> |
| | | <div v-else class="qr-loading"> |
| | | <el-icon class="is-loading"><Loading /></el-icon> |
| | | <div v-else |
| | | class="qr-loading"> |
| | | <el-icon class="is-loading"> |
| | | <Loading /> |
| | | </el-icon> |
| | | <p>æ£å¨çæäºç»´ç ...</p> |
| | | </div> |
| | | </div> |
| | | |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button @click="qrCodeDialogVisible = false">å
³é</el-button> |
| | | <el-button |
| | | v-if="qrCodeUrl" |
| | | <el-button v-if="qrCodeUrl" |
| | | type="primary" |
| | | @click="copyQRContent" |
| | | icon="CopyDocument" |
| | | > |
| | | icon="CopyDocument"> |
| | | å¤å¶å
容 |
| | | </el-button> |
| | | <el-button |
| | | v-if="qrCodeUrl" |
| | | <el-button v-if="qrCodeUrl" |
| | | type="success" |
| | | @click="downloadQRCode" |
| | | icon="Download" |
| | | > |
| | | icon="Download"> |
| | | ä¸è½½äºç»´ç |
| | | </el-button> |
| | | </div> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, computed } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { Plus, Search, Loading, Download } from '@element-plus/icons-vue' |
| | | import Pagination from '@/components/PIMTable/Pagination.vue' |
| | | import QRCode from 'qrcode' |
| | | import { ref, reactive, computed } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import { Plus, Search, Loading, Download } from "@element-plus/icons-vue"; |
| | | import Pagination from "@/components/PIMTable/Pagination.vue"; |
| | | import QRCode from "qrcode"; |
| | | |
| | | // ååºå¼æ°æ® |
| | | const loading = ref(false) |
| | | const loading = ref(false); |
| | | const searchForm = reactive({ |
| | | productName: '', |
| | | identifierType: '', |
| | | status: '' |
| | | }) |
| | | productName: "", |
| | | identifierType: "", |
| | | status: "", |
| | | }); |
| | | |
| | | const identifierList = ref([ |
| | | { |
| | | id: 1, |
| | | productName: 'å·¥ä¸ä¼ æå¨Aå', |
| | | productCode: 'SENSOR001', |
| | | batchNo: 'B202312001', |
| | | identifierType: 'äºç»´ç ', |
| | | identifierCode: 'QR_SENSOR001_B202312001_001', |
| | | status: 'å·²åé
', |
| | | generateTime: '2023-12-01 10:00:00', |
| | | remark: 'éè¦äº§åæ è¯' |
| | | productName: "å·¥ä¸ä¼ æå¨Aå", |
| | | productCode: "SENSOR001", |
| | | batchNo: "B202312001", |
| | | identifierType: "äºç»´ç ", |
| | | identifierCode: "QR_SENSOR001_B202312001_001", |
| | | status: "å·²åé
", |
| | | generateTime: "2023-12-01 10:00:00", |
| | | remark: "éè¦äº§åæ è¯", |
| | | }, |
| | | { |
| | | id: 2, |
| | | productName: 'æ§å¶é¢æ¿Bå', |
| | | productCode: 'PANEL002', |
| | | batchNo: 'B202312002', |
| | | identifierType: 'é²ä¼ªç ', |
| | | identifierCode: 'SEC_PANEL002_B202312002_001', |
| | | status: 'å·²çæ', |
| | | generateTime: '2023-12-02 14:30:00', |
| | | remark: '常è§äº§åæ è¯' |
| | | productName: "æ§å¶é¢æ¿Bå", |
| | | productCode: "PANEL002", |
| | | batchNo: "B202312002", |
| | | identifierType: "é²ä¼ªç ", |
| | | identifierCode: "SEC_PANEL002_B202312002_001", |
| | | status: "å·²çæ", |
| | | generateTime: "2023-12-02 14:30:00", |
| | | remark: "常è§äº§åæ è¯", |
| | | }, |
| | | { |
| | | id: 3, |
| | | productName: 'æ°æ®ééå¨Cå', |
| | | productCode: 'COLLECTOR003', |
| | | batchNo: 'B202312003', |
| | | identifierType: 'é²ä¼ªç ', |
| | | identifierCode: 'SEC_COLLECTOR003_B202312003_001', |
| | | status: '已使ç¨', |
| | | generateTime: '2023-12-03 09:15:00', |
| | | remark: 'æµè¯äº§åæ è¯' |
| | | } |
| | | ]) |
| | | productName: "æ°æ®ééå¨Cå", |
| | | productCode: "COLLECTOR003", |
| | | batchNo: "B202312003", |
| | | identifierType: "é²ä¼ªç ", |
| | | identifierCode: "SEC_COLLECTOR003_B202312003_001", |
| | | status: "已使ç¨", |
| | | generateTime: "2023-12-03 09:15:00", |
| | | remark: "æµè¯äº§åæ è¯", |
| | | }, |
| | | ]); |
| | | |
| | | const pagination = reactive({ |
| | | total: 3, |
| | | currentPage: 1, |
| | | pageSize: 10 |
| | | }) |
| | | pageSize: 10, |
| | | }); |
| | | |
| | | const dialogVisible = ref(false) |
| | | const dialogTitle = ref('æ°å¢æ è¯') |
| | | const dialogVisible = ref(false); |
| | | const dialogTitle = ref("æ°å¢æ è¯"); |
| | | const form = reactive({ |
| | | productName: '', |
| | | productCode: '', |
| | | batchNo: '', |
| | | identifierType: '', |
| | | productName: "", |
| | | productCode: "", |
| | | batchNo: "", |
| | | identifierType: "", |
| | | quantity: 1, |
| | | status: 'å·²çæ', |
| | | remark: '' |
| | | }) |
| | | status: "å·²çæ", |
| | | remark: "", |
| | | }); |
| | | |
| | | const rules = { |
| | | productName: [{ required: true, message: '请è¾å
¥äº§ååç§°', trigger: 'blur' }], |
| | | productCode: [{ required: true, message: '请è¾å
¥äº§åç¼ç ', trigger: 'blur' }], |
| | | batchNo: [{ required: true, message: '请è¾å
¥æ¹æ¬¡å·', trigger: 'blur' }], |
| | | identifierType: [{ required: true, message: 'è¯·éæ©æ è¯ç±»å', trigger: 'change' }], |
| | | quantity: [{ required: true, message: '请è¾å
¥çææ°é', trigger: 'blur' }], |
| | | status: [{ required: true, message: 'è¯·éæ©ç¶æ', trigger: 'change' }] |
| | | } |
| | | productName: [{ required: true, message: "请è¾å
¥äº§ååç§°", trigger: "blur" }], |
| | | productCode: [{ required: true, message: "请è¾å
¥äº§åç¼ç ", trigger: "blur" }], |
| | | batchNo: [{ required: true, message: "请è¾å
¥æ¹æ¬¡å·", trigger: "blur" }], |
| | | identifierType: [ |
| | | { required: true, message: "è¯·éæ©æ è¯ç±»å", trigger: "change" }, |
| | | ], |
| | | quantity: [{ required: true, message: "请è¾å
¥çææ°é", trigger: "blur" }], |
| | | status: [{ required: true, message: "è¯·éæ©ç¶æ", trigger: "change" }], |
| | | }; |
| | | |
| | | const isEdit = ref(false) |
| | | const editId = ref(null) |
| | | const generateDialogVisible = ref(false) |
| | | const reassignDialogVisible = ref(false) |
| | | const currentProduct = ref({}) |
| | | const generateQuantity = ref(1) |
| | | const codeRule = ref('') |
| | | const customPrefix = ref('') |
| | | const newBatchNo = ref('') |
| | | const reassignReason = ref('') |
| | | const formRef = ref() |
| | | const isEdit = ref(false); |
| | | const editId = ref(null); |
| | | const generateDialogVisible = ref(false); |
| | | const reassignDialogVisible = ref(false); |
| | | const currentProduct = ref({}); |
| | | const generateQuantity = ref(1); |
| | | const codeRule = ref(""); |
| | | const customPrefix = ref(""); |
| | | const newBatchNo = ref(""); |
| | | const reassignReason = ref(""); |
| | | const formRef = ref(); |
| | | |
| | | // äºç»´ç ç¸å
³åé |
| | | const qrCodeDialogVisible = ref(false) |
| | | const qrCodeUrl = ref('') |
| | | const currentQRProduct = ref({}) |
| | | const qrCodeDialogVisible = ref(false); |
| | | const qrCodeUrl = ref(""); |
| | | const currentQRProduct = ref({}); |
| | | |
| | | // 计ç®å±æ§ |
| | | const filteredList = computed(() => { |
| | | let list = identifierList.value |
| | | let list = identifierList.value; |
| | | if (searchForm.productName) { |
| | | list = list.filter(item => item.productName.includes(searchForm.productName)) |
| | | list = list.filter(item => |
| | | item.productName.includes(searchForm.productName) |
| | | ); |
| | | } |
| | | if (searchForm.identifierType) { |
| | | list = list.filter(item => item.identifierType === searchForm.identifierType) |
| | | list = list.filter( |
| | | item => item.identifierType === searchForm.identifierType |
| | | ); |
| | | } |
| | | if (searchForm.status) { |
| | | list = list.filter(item => item.status === searchForm.status) |
| | | list = list.filter(item => item.status === searchForm.status); |
| | | } |
| | | return list |
| | | }) |
| | | return list; |
| | | }); |
| | | |
| | | // æ¹æ³ |
| | | const getIdentifierTypeType = (type) => { |
| | | const getIdentifierTypeType = type => { |
| | | const typeMap = { |
| | | 'äºç»´ç ': 'success', |
| | | 'é²ä¼ªç ': 'warning' |
| | | } |
| | | return typeMap[type] || 'info' |
| | | } |
| | | äºç»´ç : "success", |
| | | é²ä¼ªç : "warning", |
| | | }; |
| | | return typeMap[type] || "info"; |
| | | }; |
| | | |
| | | const getStatusType = (status) => { |
| | | const getStatusType = status => { |
| | | const statusMap = { |
| | | 'å·²çæ': 'info', |
| | | 'å·²åé
': 'primary', |
| | | '已使ç¨': 'success', |
| | | 'å·²ä½åº': 'danger' |
| | | } |
| | | return statusMap[status] || 'info' |
| | | } |
| | | å·²çæ: "info", |
| | | å·²åé
: "primary", |
| | | 已使ç¨: "success", |
| | | å·²ä½åº: "danger", |
| | | }; |
| | | return statusMap[status] || "info"; |
| | | }; |
| | | |
| | | const handleSearch = () => { |
| | | // æç´¢é»è¾å·²å¨computedä¸å¤ç |
| | | } |
| | | }; |
| | | |
| | | const resetSearch = () => { |
| | | searchForm.productName = '' |
| | | searchForm.identifierType = '' |
| | | searchForm.status = '' |
| | | } |
| | | searchForm.productName = ""; |
| | | searchForm.identifierType = ""; |
| | | searchForm.status = ""; |
| | | }; |
| | | |
| | | const handleAdd = () => { |
| | | dialogTitle.value = 'æ°å¢æ è¯' |
| | | isEdit.value = false |
| | | form.productName = '' |
| | | form.productCode = '' |
| | | form.batchNo = '' |
| | | form.identifierType = '' |
| | | form.quantity = 1 |
| | | form.status = 'å·²çæ' |
| | | form.remark = '' |
| | | dialogVisible.value = true |
| | | } |
| | | dialogTitle.value = "æ°å¢æ è¯"; |
| | | isEdit.value = false; |
| | | form.productName = ""; |
| | | form.productCode = ""; |
| | | form.batchNo = ""; |
| | | form.identifierType = ""; |
| | | form.quantity = 1; |
| | | form.status = "å·²çæ"; |
| | | form.remark = ""; |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | const handleView = (row) => { |
| | | const handleView = row => { |
| | | // æ¥çæ è¯è¯¦æ
|
| | | ElMessage.info('æ¥çæ è¯è¯¦æ
åè½å¾
å®ç°') |
| | | } |
| | | ElMessage.info("æ¥çæ è¯è¯¦æ
åè½å¾
å®ç°"); |
| | | }; |
| | | |
| | | const handleEdit = (row) => { |
| | | dialogTitle.value = 'ç¼è¾æ è¯' |
| | | isEdit.value = true |
| | | editId.value = row.id |
| | | Object.assign(form, row) |
| | | dialogVisible.value = true |
| | | } |
| | | const handleEdit = row => { |
| | | dialogTitle.value = "ç¼è¾æ è¯"; |
| | | isEdit.value = true; |
| | | editId.value = row.id; |
| | | Object.assign(form, row); |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | const handleExport = (row) => { |
| | | const handleExport = row => { |
| | | // å¯¼åºæ è¯ |
| | | ElMessage.success(`å·²å¯¼åºæ è¯: ${row.identifierCode}`) |
| | | } |
| | | ElMessage.success(`å·²å¯¼åºæ è¯: ${row.identifierCode}`); |
| | | }; |
| | | |
| | | const handleReassign = (row) => { |
| | | currentProduct.value = row |
| | | newBatchNo.value = '' |
| | | reassignReason.value = '' |
| | | reassignDialogVisible.value = true |
| | | } |
| | | const handleReassign = row => { |
| | | currentProduct.value = row; |
| | | newBatchNo.value = ""; |
| | | reassignReason.value = ""; |
| | | reassignDialogVisible.value = true; |
| | | }; |
| | | |
| | | const handleDelete = (row) => { |
| | | ElMessageBox.confirm('确认å é¤è¯¥æ è¯åï¼', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | const handleDelete = row => { |
| | | ElMessageBox.confirm("确认å é¤è¯¥æ è¯åï¼", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).then(() => { |
| | | const index = identifierList.value.findIndex(item => item.id === row.id) |
| | | const index = identifierList.value.findIndex(item => item.id === row.id); |
| | | if (index > -1) { |
| | | identifierList.value.splice(index, 1) |
| | | pagination.total-- |
| | | ElMessage.success('å 餿å') |
| | | identifierList.value.splice(index, 1); |
| | | pagination.total--; |
| | | ElMessage.success("å 餿å"); |
| | | } |
| | | }) |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // çæäºç»´ç |
| | | const generateQRCode = async (row) => { |
| | | const generateQRCode = async row => { |
| | | try { |
| | | // æ£æ¥å¿
è¦å段 |
| | | if (!row.productName || !row.productCode || !row.batchNo) { |
| | | ElMessage.warning('产åä¿¡æ¯ä¸å®æ´ï¼æ æ³çæäºç»´ç ') |
| | | return |
| | | ElMessage.warning("产åä¿¡æ¯ä¸å®æ´ï¼æ æ³çæäºç»´ç "); |
| | | return; |
| | | } |
| | | |
| | | currentQRProduct.value = row |
| | | qrCodeUrl.value = '' |
| | | qrCodeDialogVisible.value = true |
| | | currentQRProduct.value = row; |
| | | qrCodeUrl.value = ""; |
| | | qrCodeDialogVisible.value = true; |
| | | |
| | | // æå»ºäºç»´ç å
容 |
| | | let qrContent = '' |
| | | if (row.identifierType === 'äºç»´ç ') { |
| | | qrContent = `${row.productName}|${row.productCode}|${row.batchNo}|${row.identifierCode}` |
| | | } else if (row.identifierType === 'é²ä¼ªç ') { |
| | | let qrContent = ""; |
| | | if (row.identifierType === "äºç»´ç ") { |
| | | qrContent = `${row.productName}|${row.productCode}|${row.batchNo}|${row.identifierCode}`; |
| | | } else if (row.identifierType === "é²ä¼ªç ") { |
| | | // é²ä¼ªç æ ¼å¼ï¼SEC_产åç¼ç _æ¹æ¬¡å·_æ¶é´æ³_éæºæ° |
| | | const timestamp = Date.now() |
| | | const random = Math.random().toString(36).substr(2, 8) |
| | | qrContent = `SEC_${row.productCode}_${row.batchNo}_${timestamp}_${random}` |
| | | const timestamp = Date.now(); |
| | | const random = Math.random().toString(36).substr(2, 8); |
| | | qrContent = `SEC_${row.productCode}_${row.batchNo}_${timestamp}_${random}`; |
| | | } |
| | | |
| | | // çæäºç»´ç |
| | |
| | | width: 256, |
| | | margin: 2, |
| | | color: { |
| | | dark: '#000000', |
| | | light: '#FFFFFF' |
| | | dark: "#000000", |
| | | light: "#FFFFFF", |
| | | }, |
| | | errorCorrectionLevel: row.identifierType === 'é²ä¼ªç ' ? 'H' : 'M' |
| | | }) |
| | | errorCorrectionLevel: row.identifierType === "é²ä¼ªç " ? "H" : "M", |
| | | }); |
| | | |
| | | ElMessage.success('äºç»´ç çææåï¼') |
| | | |
| | | ElMessage.success("äºç»´ç çææåï¼"); |
| | | } catch (error) { |
| | | console.error('çæäºç»´ç 失败:', error) |
| | | ElMessage.error('çæäºç»´ç 失败ï¼' + error.message) |
| | | qrCodeDialogVisible.value = false |
| | | console.error("çæäºç»´ç 失败:", error); |
| | | ElMessage.error("çæäºç»´ç 失败ï¼" + error.message); |
| | | qrCodeDialogVisible.value = false; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // ä¸è½½äºç»´ç |
| | | const downloadQRCode = () => { |
| | | if (!qrCodeUrl.value) { |
| | | ElMessage.warning('请å
çæäºç»´ç ') |
| | | return |
| | | ElMessage.warning("请å
çæäºç»´ç "); |
| | | return; |
| | | } |
| | | |
| | | const a = document.createElement('a') |
| | | a.href = qrCodeUrl.value |
| | | a.download = `${currentQRProduct.value.productName}_${currentQRProduct.value.identifierType}_${new Date().getTime()}.png` |
| | | document.body.appendChild(a) |
| | | a.click() |
| | | document.body.removeChild(a) |
| | | ElMessage.success('ä¸è½½æåï¼') |
| | | } |
| | | const a = document.createElement("a"); |
| | | a.href = qrCodeUrl.value; |
| | | a.download = `${currentQRProduct.value.productName}_${ |
| | | currentQRProduct.value.identifierType |
| | | }_${new Date().getTime()}.png`; |
| | | document.body.appendChild(a); |
| | | a.click(); |
| | | document.body.removeChild(a); |
| | | ElMessage.success("ä¸è½½æåï¼"); |
| | | }; |
| | | |
| | | // å¤å¶äºç»´ç å
容 |
| | | const copyQRContent = async () => { |
| | | if (!currentQRProduct.value) { |
| | | ElMessage.warning('没æå¯å¤å¶çå
容') |
| | | return |
| | | ElMessage.warning("没æå¯å¤å¶çå
容"); |
| | | return; |
| | | } |
| | | |
| | | try { |
| | | let content = '' |
| | | if (currentQRProduct.value.identifierType === 'äºç»´ç ') { |
| | | content = `${currentQRProduct.value.productName}|${currentQRProduct.value.productCode}|${currentQRProduct.value.batchNo}|${currentQRProduct.value.identifierCode}` |
| | | } else if (currentQRProduct.value.identifierType === 'é²ä¼ªç ') { |
| | | const timestamp = Date.now() |
| | | const random = Math.random().toString(36).substr(2, 8) |
| | | content = `SEC_${currentQRProduct.value.productCode}_${currentQRProduct.value.batchNo}_${timestamp}_${random}` |
| | | let content = ""; |
| | | if (currentQRProduct.value.identifierType === "äºç»´ç ") { |
| | | content = `${currentQRProduct.value.productName}|${currentQRProduct.value.productCode}|${currentQRProduct.value.batchNo}|${currentQRProduct.value.identifierCode}`; |
| | | } else if (currentQRProduct.value.identifierType === "é²ä¼ªç ") { |
| | | const timestamp = Date.now(); |
| | | const random = Math.random().toString(36).substr(2, 8); |
| | | content = `SEC_${currentQRProduct.value.productCode}_${currentQRProduct.value.batchNo}_${timestamp}_${random}`; |
| | | } |
| | | |
| | | await navigator.clipboard.writeText(content) |
| | | ElMessage.success('å
容已å¤å¶å°åªè´´æ¿') |
| | | await navigator.clipboard.writeText(content); |
| | | ElMessage.success("å
容已å¤å¶å°åªè´´æ¿"); |
| | | } catch (error) { |
| | | // éçº§æ¹æ¡ |
| | | const textArea = document.createElement('textarea') |
| | | textArea.value = content |
| | | document.body.appendChild(textArea) |
| | | textArea.select() |
| | | document.execCommand('copy') |
| | | document.body.removeChild(textArea) |
| | | ElMessage.success('å
容已å¤å¶å°åªè´´æ¿') |
| | | const textArea = document.createElement("textarea"); |
| | | textArea.value = content; |
| | | document.body.appendChild(textArea); |
| | | textArea.select(); |
| | | document.execCommand("copy"); |
| | | document.body.removeChild(textArea); |
| | | ElMessage.success("å
容已å¤å¶å°åªè´´æ¿"); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | const generateIdentifiers = () => { |
| | | if (!codeRule.value) { |
| | | ElMessage.warning('è¯·éæ©ç¼ç è§å') |
| | | return |
| | | ElMessage.warning("è¯·éæ©ç¼ç è§å"); |
| | | return; |
| | | } |
| | | |
| | | // çææ è¯çé»è¾ |
| | | const newIdentifiers = [] |
| | | const newIdentifiers = []; |
| | | for (let i = 1; i <= generateQuantity.value; i++) { |
| | | let identifierCode = '' |
| | | if (codeRule.value === '产åç¼ç +æ¹æ¬¡å·+åºå·') { |
| | | identifierCode = `${currentProduct.value.productCode}_${currentProduct.value.batchNo}_${String(i).padStart(3, '0')}` |
| | | } else if (codeRule.value === 'æ¶é´æ³+éæºæ°') { |
| | | identifierCode = `TS_${Date.now()}_${Math.floor(Math.random() * 1000)}` |
| | | } else if (codeRule.value === 'èªå®ä¹è§å') { |
| | | identifierCode = `${customPrefix.value || 'CUSTOM'}_${Date.now()}_${i}` |
| | | let identifierCode = ""; |
| | | if (codeRule.value === "产åç¼ç +æ¹æ¬¡å·+åºå·") { |
| | | identifierCode = `${currentProduct.value.productCode}_${ |
| | | currentProduct.value.batchNo |
| | | }_${String(i).padStart(3, "0")}`; |
| | | } else if (codeRule.value === "æ¶é´æ³+éæºæ°") { |
| | | identifierCode = `TS_${Date.now()}_${Math.floor(Math.random() * 1000)}`; |
| | | } else if (codeRule.value === "èªå®ä¹è§å") { |
| | | identifierCode = `${customPrefix.value || "CUSTOM"}_${Date.now()}_${i}`; |
| | | } |
| | | |
| | | newIdentifiers.push({ |
| | |
| | | batchNo: currentProduct.value.batchNo, |
| | | identifierType: currentProduct.value.identifierType, |
| | | identifierCode: identifierCode, |
| | | status: 'å·²çæ', |
| | | status: "å·²çæ", |
| | | generateTime: new Date().toLocaleString(), |
| | | remark: 'æ¹éçæ' |
| | | }) |
| | | remark: "æ¹éçæ", |
| | | }); |
| | | } |
| | | |
| | | identifierList.value.push(...newIdentifiers) |
| | | pagination.total += newIdentifiers.length |
| | | ElMessage.success(`æåçæ ${newIdentifiers.length} 个æ è¯`) |
| | | generateDialogVisible.value = false |
| | | } |
| | | identifierList.value.push(...newIdentifiers); |
| | | pagination.total += newIdentifiers.length; |
| | | ElMessage.success(`æåçæ ${newIdentifiers.length} 个æ è¯`); |
| | | generateDialogVisible.value = false; |
| | | }; |
| | | |
| | | const saveReassign = () => { |
| | | if (!newBatchNo.value) { |
| | | ElMessage.warning('请è¾å
¥æ°æ¹æ¬¡å·') |
| | | return |
| | | ElMessage.warning("请è¾å
¥æ°æ¹æ¬¡å·"); |
| | | return; |
| | | } |
| | | |
| | | const index = identifierList.value.findIndex(item => item.id === currentProduct.value.id) |
| | | const index = identifierList.value.findIndex( |
| | | item => item.id === currentProduct.value.id |
| | | ); |
| | | if (index > -1) { |
| | | identifierList.value[index].batchNo = newBatchNo.value |
| | | identifierList.value[index].status = 'å·²åé
' |
| | | ElMessage.success('æ è¯éæ°åé
æå') |
| | | reassignDialogVisible.value = false |
| | | identifierList.value[index].batchNo = newBatchNo.value; |
| | | identifierList.value[index].status = "å·²åé
"; |
| | | ElMessage.success("æ è¯éæ°åé
æå"); |
| | | reassignDialogVisible.value = false; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | const handleSubmit = () => { |
| | | formRef.value.validate((valid) => { |
| | | formRef.value.validate(valid => { |
| | | if (valid) { |
| | | if (isEdit.value) { |
| | | // ç¼è¾ |
| | | const index = identifierList.value.findIndex(item => item.id === editId.value) |
| | | const index = identifierList.value.findIndex( |
| | | item => item.id === editId.value |
| | | ); |
| | | if (index > -1) { |
| | | identifierList.value[index] = { ...form, id: editId.value } |
| | | ElMessage.success('ç¼è¾æå') |
| | | identifierList.value[index] = { ...form, id: editId.value }; |
| | | ElMessage.success("ç¼è¾æå"); |
| | | } |
| | | } else { |
| | | // æ°å¢ |
| | | const newId = Math.max(...identifierList.value.map(item => item.id)) + 1 |
| | | const newId = |
| | | Math.max(...identifierList.value.map(item => item.id)) + 1; |
| | | |
| | | // æ ¹æ®æ è¯ç±»åçæä¸åçæ è¯ç |
| | | let identifierCode = '' |
| | | if (form.identifierType === 'äºç»´ç ') { |
| | | identifierCode = `QR_${form.productCode}_${form.batchNo}_001` |
| | | } else if (form.identifierType === 'é²ä¼ªç ') { |
| | | identifierCode = `SEC_${form.productCode}_${form.batchNo}_001` |
| | | let identifierCode = ""; |
| | | if (form.identifierType === "äºç»´ç ") { |
| | | identifierCode = `QR_${form.productCode}_${form.batchNo}_001`; |
| | | } else if (form.identifierType === "é²ä¼ªç ") { |
| | | identifierCode = `SEC_${form.productCode}_${form.batchNo}_001`; |
| | | } |
| | | |
| | | identifierList.value.push({ |
| | | ...form, |
| | | id: newId, |
| | | identifierCode: identifierCode, |
| | | generateTime: new Date().toLocaleString() |
| | | }) |
| | | pagination.total++ |
| | | ElMessage.success('æ°å¢æå') |
| | | generateTime: new Date().toLocaleString(), |
| | | }); |
| | | pagination.total++; |
| | | ElMessage.success("æ°å¢æå"); |
| | | } |
| | | dialogVisible.value = false |
| | | dialogVisible.value = false; |
| | | } |
| | | }) |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | const handleCurrentChange = (val) => { |
| | | pagination.currentPage = val.page |
| | | pagination.pageSize = val.limit |
| | | } |
| | | const handleCurrentChange = val => { |
| | | pagination.currentPage = val.page; |
| | | pagination.pageSize = val.limit; |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped> |
| | |
| | | |
| | | .qr-loading .el-icon { |
| | | font-size: 32px; |
| | | color: #409EFF; |
| | | color: #409eff; |
| | | } |
| | | |
| | | .qr-loading p { |
| | |
| | | @close="closeModal" |
| | | > |
| | | <el-form label-width="140px" :model="formState" label-position="top" ref="formRef"> |
| | | <el-form-item label="产å大类ï¼" prop="productId"> |
| | | <el-form-item |
| | | label="产å大类ï¼" |
| | | prop="productId" |
| | | :rules="[ |
| | | { |
| | | required: true, |
| | | message: 'è¯·éæ©äº§å大类', |
| | | } |
| | | ]" |
| | | > |
| | | <el-tree-select |
| | | v-model="formState.productId" |
| | | placeholder="è¯·éæ©" |
| | |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="è§æ ¼åå·ï¼" prop="productModelId"> |
| | | <el-form-item |
| | | label="è§æ ¼åå·ï¼" |
| | | prop="productModelId" |
| | | :rules="[ |
| | | { |
| | | required: true, |
| | | message: 'è¯·éæ©è§æ ¼åå·', |
| | | } |
| | | ]" |
| | | > |
| | | <el-select |
| | | v-model="formState.productModelId" |
| | | placeholder="è¯·éæ©" |
| | |
| | | @close="closeModal" |
| | | > |
| | | <el-form label-width="140px" :model="formState" label-position="top" ref="formRef"> |
| | | <el-form-item label="产å大类ï¼" prop="productId"> |
| | | <el-form-item |
| | | label="产å大类ï¼" |
| | | prop="productId" |
| | | :rules="[ |
| | | { |
| | | required: true, |
| | | message: 'è¯·éæ©äº§å大类', |
| | | } |
| | | ]" |
| | | > |
| | | <el-tree-select |
| | | v-model="formState.productId" |
| | | placeholder="è¯·éæ©" |
| | |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="è§æ ¼åå·ï¼" prop="productModelId"> |
| | | <el-form-item |
| | | label="è§æ ¼åå·ï¼" |
| | | prop="productModelId" |
| | | :rules="[ |
| | | { |
| | | required: true, |
| | | message: 'è¯·éæ©è§æ ¼åå·', |
| | | } |
| | | ]" |
| | | > |
| | | <el-select |
| | | v-model="formState.productModelId" |
| | | placeholder="è¯·éæ©" |
| | |
| | | <template> |
| | | <el-dialog |
| | | v-model="visible" |
| | | <el-dialog v-model="visible" |
| | | title="ç»æ" |
| | | width="1200" |
| | | close-on-click-modal |
| | | @close="visible = false" |
| | | > |
| | | <el-button |
| | | v-if="dataValue.isEdit" |
| | | @close="visible = false"> |
| | | <el-button v-if="dataValue.isEdit" |
| | | type="primary" |
| | | @click="addItem" |
| | | style="margin-bottom: 10px" |
| | | >æ·»å |
| | | style="margin-bottom: 10px">æ·»å |
| | | </el-button> |
| | | <el-button |
| | | v-if="!dataValue.isEdit" |
| | | <el-button v-if="!dataValue.isEdit" |
| | | type="primary" |
| | | @click="dataValue.isEdit = true" |
| | | style="margin-bottom: 10px" |
| | | >ç¼è¾ |
| | | style="margin-bottom: 10px">ç¼è¾ |
| | | </el-button> |
| | | <el-button |
| | | v-if="dataValue.isEdit" |
| | | <el-button v-if="dataValue.isEdit" |
| | | type="primary" |
| | | @click="cancelEdit" |
| | | style="margin-bottom: 10px" |
| | | >åæ¶ |
| | | style="margin-bottom: 10px">åæ¶ |
| | | </el-button> |
| | | <el-form |
| | | ref="form" |
| | | :model="dataValue" |
| | | > |
| | | <el-table :data="dataValue.dataList" style="width: 100%"> |
| | | <el-table-column prop="productName" label="产å" width="150"/> |
| | | <el-table-column prop="model" label="è§æ ¼" width="150"> |
| | | <el-form ref="form" |
| | | :model="dataValue"> |
| | | <el-table :data="dataValue.dataList" |
| | | style="width: 100%"> |
| | | <el-table-column prop="productName" |
| | | label="产å" |
| | | width="150" /> |
| | | <el-table-column prop="model" |
| | | label="è§æ ¼" |
| | | width="150"> |
| | | <template #default="{ row, $index }"> |
| | | <el-form-item |
| | | v-if="dataValue.isEdit" |
| | | <el-form-item v-if="dataValue.isEdit" |
| | | :prop="`dataList.${$index}.model`" |
| | | :rules="[{ required: true, message: 'è¯·éæ©è§æ ¼', trigger: ['blur','change'] }]" |
| | | style="margin: 0" |
| | | > |
| | | <el-select |
| | | v-model="row.model" |
| | | style="margin: 0"> |
| | | <el-select v-model="row.model" |
| | | placeholder="è¯·éæ©äº§å" |
| | | clearable |
| | | :disabled="!dataValue.isEdit" |
| | | style="width: 100%" |
| | | @visible-change="(v) => { if (v) openDialog($index) }" |
| | | > |
| | | <el-option v-if="row.model" :label="row.model" :value="row.model" /> |
| | | @visible-change="(v) => { if (v) openDialog($index) }"> |
| | | <el-option v-if="row.model" |
| | | :label="row.model" |
| | | :value="row.model" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column prop="processId" label="æ¶èå·¥åº" width="150"> |
| | | <el-table-column prop="processId" |
| | | label="æ¶èå·¥åº" |
| | | width="150"> |
| | | <template #default="{ row, $index }"> |
| | | <el-form-item |
| | | :prop="`dataList.${$index}.processId`" |
| | | <el-form-item :prop="`dataList.${$index}.processId`" |
| | | :rules="[{ required: true, message: 'è¯·éæ©æ¶èå·¥åº', trigger: 'change' }]" |
| | | style="margin: 0" |
| | | > |
| | | <el-select |
| | | v-model="row.processId" |
| | | style="margin: 0"> |
| | | <el-select v-model="row.processId" |
| | | placeholder="è¯·éæ©" |
| | | filterable |
| | | clearable |
| | | style="width: 100%" |
| | | :disabled="!dataValue.isEdit" |
| | | > |
| | | <el-option |
| | | v-for="item in dataValue.processOptions" |
| | | :disabled="!dataValue.isEdit"> |
| | | <el-option v-for="item in dataValue.processOptions" |
| | | :key="item.id" |
| | | :label="item.name" |
| | | :value="item.id" |
| | | /> |
| | | :value="item.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column prop="unitQuantity" label="åä½äº§åºæéæ°é" width="150"> |
| | | <el-table-column prop="unitQuantity" |
| | | label="åä½äº§åºæéæ°é" |
| | | width="150"> |
| | | <template #default="{ row, $index }"> |
| | | <el-form-item |
| | | :prop="`dataList.${$index}.unitQuantity`" |
| | | <el-form-item :prop="`dataList.${$index}.unitQuantity`" |
| | | :rules="[{ required: true, message: '请è¾å
¥åä½äº§åºæéæ°é', trigger: ['blur','change'] }]" |
| | | style="margin: 0" |
| | | > |
| | | <el-input-number |
| | | v-model="row.unitQuantity" |
| | | style="margin: 0"> |
| | | <el-input-number v-model="row.unitQuantity" |
| | | :min="0" |
| | | :precision="2" |
| | | :step="1" |
| | | controls-position="right" |
| | | style="width: 100%" |
| | | :disabled="!dataValue.isEdit" |
| | | /> |
| | | :disabled="!dataValue.isEdit" /> |
| | | </el-form-item> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column prop="demandedQuantity" label="éæ±æ»é" width="150"> |
| | | <el-table-column prop="demandedQuantity" |
| | | label="éæ±æ»é" |
| | | width="150"> |
| | | <template #default="{ row, $index }"> |
| | | <el-form-item |
| | | :prop="`dataList.${$index}.demandedQuantity`" |
| | | <el-form-item :prop="`dataList.${$index}.demandedQuantity`" |
| | | :rules="[{ required: true, message: '请è¾å
¥éæ±æ»é', trigger: ['blur','change'] }]" |
| | | style="margin: 0" |
| | | > |
| | | <el-input-number |
| | | v-model="row.demandedQuantity" |
| | | style="margin: 0"> |
| | | <el-input-number v-model="row.demandedQuantity" |
| | | :min="0" |
| | | :precision="2" |
| | | :step="1" |
| | | controls-position="right" |
| | | style="width: 100%" |
| | | :disabled="!dataValue.isEdit" |
| | | /> |
| | | :disabled="!dataValue.isEdit" /> |
| | | </el-form-item> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column prop="unit" label="åä½" width="150"> |
| | | <el-table-column prop="unit" |
| | | label="åä½" |
| | | width="150"> |
| | | <template #default="{ row, $index }"> |
| | | <el-form-item |
| | | :prop="`dataList.${$index}.unit`" |
| | | <el-form-item :prop="`dataList.${$index}.unit`" |
| | | :rules="[{ required: true, message: '请è¾å
¥åä½', trigger: ['blur','change'] }]" |
| | | style="margin: 0" |
| | | > |
| | | <el-input |
| | | v-model="row.unit" |
| | | style="margin: 0"> |
| | | <el-input v-model="row.unit" |
| | | placeholder="请è¾å
¥åä½" |
| | | clearable |
| | | :disabled="!dataValue.isEdit" |
| | | /> |
| | | :disabled="!dataValue.isEdit" /> |
| | | </el-form-item> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column prop="diskQuantity" label="çæ°ï¼çï¼" width="150"> |
| | | <el-table-column prop="diskQuantity" |
| | | label="çæ°ï¼çï¼" |
| | | width="150"> |
| | | <template #default="{ row, $index }"> |
| | | <el-form-item |
| | | :prop="`dataList.${$index}.diskQuantity`" |
| | | <el-form-item :prop="`dataList.${$index}.diskQuantity`" |
| | | :rules="[{ required: true, message: '请è¾å
¥çæ°', trigger: ['blur','change'] }]" |
| | | style="margin: 0" |
| | | > |
| | | <el-input-number |
| | | v-model="row.diskQuantity" |
| | | style="margin: 0"> |
| | | <el-input-number v-model="row.diskQuantity" |
| | | :min="0" |
| | | :precision="0" |
| | | :step="1" |
| | | controls-position="right" |
| | | style="width: 100%" |
| | | :disabled="!dataValue.isEdit" |
| | | /> |
| | | :disabled="!dataValue.isEdit" /> |
| | | </el-form-item> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column label="æä½"> |
| | | <template #default="{ row, $index }"> |
| | | <el-button |
| | | type="danger" |
| | | <el-button type="danger" |
| | | text |
| | | @click="dataValue.dataList.splice($index, 1)" |
| | | >å é¤ |
| | | @click="dataValue.dataList.splice($index, 1)">å é¤ |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-form> |
| | | |
| | | <product-select-dialog |
| | | v-if="dataValue.showProductDialog" |
| | | <product-select-dialog v-if="dataValue.showProductDialog" |
| | | v-model:model-value="dataValue.showProductDialog" |
| | | @confirm="handleProduct"/> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button @click="visible = false">åæ¶</el-button> |
| | | <el-button type="primary" :loading="dataValue.loading" @click="submit" :disabled="!dataValue.isEdit"> |
| | | <el-button type="primary" |
| | | :loading="dataValue.loading" |
| | | @click="submit" |
| | | :disabled="!dataValue.isEdit"> |
| | | 确认 |
| | | </el-button> |
| | | <el-button @click="visible = false">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import {computed, defineAsyncComponent, defineComponent, onMounted, reactive, ref} from "vue"; |
| | | import {queryList, add} from '@/api/productionManagement/productStructure.js' |
| | | import {list} from '@/api/productionManagement/productionProcess' |
| | | import { |
| | | computed, |
| | | defineAsyncComponent, |
| | | defineComponent, |
| | | onMounted, |
| | | reactive, |
| | | ref, |
| | | } from "vue"; |
| | | import { queryList, add } from "@/api/productionManagement/productStructure.js"; |
| | | import { list } from "@/api/productionManagement/productionProcess"; |
| | | import {ElMessage} from "element-plus"; |
| | | |
| | | |
| | | defineComponent({ |
| | | name: "StructureEdit", |
| | | }) |
| | | }); |
| | | |
| | | const ProductSelectDialog = defineAsyncComponent(() => import('@/views/basicData/product/ProductSelectDialog.vue')) |
| | | const form = ref() |
| | | |
| | | |
| | | const ProductSelectDialog = defineAsyncComponent( |
| | | () => import("@/views/basicData/product/ProductSelectDialog.vue") |
| | | ); |
| | | const form = ref(); |
| | | |
| | | const props = defineProps({ |
| | | showModel: { |
| | | type: Boolean, |
| | | default: false |
| | | default: false, |
| | | }, |
| | | productModelId: { |
| | | type: Number, |
| | | required: true |
| | | } |
| | | }) |
| | | required: true, |
| | | }, |
| | | }); |
| | | |
| | | const emits = defineEmits(['update:showModel']) |
| | | const emits = defineEmits(["update:showModel"]); |
| | | const visible = computed({ |
| | | get() { |
| | | return props.showModel |
| | | return props.showModel; |
| | | }, |
| | | set(val) { |
| | | emits('update:showModel', val) |
| | | } |
| | | }) |
| | | emits("update:showModel", val); |
| | | }, |
| | | }); |
| | | |
| | | const dataValue = reactive({ |
| | | dataList: [], |
| | |
| | | isEdit: false, |
| | | }); |
| | | |
| | | const openDialog = (index) => { |
| | | dataValue.currentRowIndex = index |
| | | dataValue.showProductDialog = true |
| | | } |
| | | const openDialog = index => { |
| | | dataValue.currentRowIndex = index; |
| | | dataValue.showProductDialog = true; |
| | | }; |
| | | |
| | | const fetchData = async () => { |
| | | const {data} = await queryList(props.productModelId) |
| | | dataValue.dataList = data |
| | | } |
| | | const { data } = await queryList(props.productModelId); |
| | | dataValue.dataList = data; |
| | | }; |
| | | |
| | | const fetchProcessOptions = async () => { |
| | | const {data} = await list(props.productModelId) |
| | | dataValue.processOptions = data |
| | | } |
| | | const { data } = await list(props.productModelId); |
| | | dataValue.processOptions = data; |
| | | }; |
| | | |
| | | const handleProduct = (row) => { |
| | | const handleProduct = row => { |
| | | if (row?.length > 1) { |
| | | ElMessage.error('åªè½éæ©ä¸ä¸ªäº§å') |
| | | ElMessage.error("åªè½éæ©ä¸ä¸ªäº§å"); |
| | | } |
| | | dataValue.dataList[dataValue.currentRowIndex].productName = row[0].productName |
| | | dataValue.dataList[dataValue.currentRowIndex].model = row[0].model |
| | | dataValue.dataList[dataValue.currentRowIndex].productModelId = row[0].id |
| | | dataValue.showProductDialog = false |
| | | } |
| | | dataValue.dataList[dataValue.currentRowIndex].productName = |
| | | row[0].productName; |
| | | dataValue.dataList[dataValue.currentRowIndex].model = row[0].model; |
| | | dataValue.dataList[dataValue.currentRowIndex].productModelId = row[0].id; |
| | | dataValue.showProductDialog = false; |
| | | }; |
| | | |
| | | const submit = () => { |
| | | form.value.validate(valid => { |
| | | dataValue.loading = true |
| | | form.value |
| | | .validate(valid => { |
| | | dataValue.loading = true; |
| | | if (valid) { |
| | | add({ |
| | | parentId: props.productModelId, |
| | | productStructureList: dataValue.dataList || [] |
| | | productStructureList: dataValue.dataList || [], |
| | | }).then(res => { |
| | | ElMessage.success('ä¿åæå') |
| | | visible.value = false |
| | | dataValue.loading = false |
| | | }) |
| | | ElMessage.success("ä¿åæå"); |
| | | visible.value = false; |
| | | dataValue.loading = false; |
| | | }); |
| | | } |
| | | }).finally(() => { |
| | | dataValue.loading = false |
| | | }) |
| | | } |
| | | .finally(() => { |
| | | dataValue.loading = false; |
| | | }); |
| | | }; |
| | | |
| | | const addItem = () => { |
| | | dataValue.dataList.push({ |
| | | productName: '', |
| | | productId: '', |
| | | productName: "", |
| | | productId: "", |
| | | model: undefined, |
| | | productModelId: undefined, |
| | | processId: '', |
| | | processId: "", |
| | | unitQuantity: 0, |
| | | demandedQuantity: 0, |
| | | unit: '', |
| | | unit: "", |
| | | diskQuantity: 0, |
| | | }) |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | const cancelEdit = () => { |
| | | dataValue.isEdit = false |
| | | dataValue.dataList = dataValue.dataList.filter(item => item.id !== undefined) |
| | | } |
| | | dataValue.isEdit = false; |
| | | dataValue.dataList = dataValue.dataList.filter(item => item.id !== undefined); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | fetchData() |
| | | fetchProcessOptions() |
| | | }) |
| | | |
| | | |
| | | fetchData(); |
| | | fetchProcessOptions(); |
| | | }); |
| | | </script> |
| | |
| | | style="width: 200px;" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="项ç®åç§°:"> |
| | | <el-input v-model="searchForm.projectName" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | prefix-icon="Search" |
| | | style="width: 200px;" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="产ååç§°:"> |
| | | <el-input v-model="searchForm.productCategory" |
| | | placeholder="请è¾å
¥" |
| | |
| | | { |
| | | label: "ç产订åå·", |
| | | prop: "npsNo", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "éå®ååå·", |
| | | prop: "salesContractNo", |
| | | width: 220, |
| | | }, |
| | | { |
| | | label: "项ç®åç§°", |
| | | prop: "projectName", |
| | | width: 300, |
| | | }, |
| | | { |
| | | label: "客æ·åç§°", |
| | | prop: "customerName", |
| | | width: 250, |
| | | }, |
| | | { |
| | | label: "产ååç§°", |
| | | prop: "productCategory", |
| | | width: 250, |
| | | }, |
| | | { |
| | | label: "è§æ ¼", |
| | | prop: "specificationModel", |
| | | width: 250, |
| | | }, |
| | | { |
| | | dataType: "action", |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <div class="search_form"> |
| | | <el-form :model="searchForm" :inline="true"> |
| | | <el-form :model="searchForm" |
| | | :inline="true"> |
| | | <el-form-item label="å·¥åºåç§°:"> |
| | | <el-input v-model="searchForm.name" placeholder="请è¾å
¥" clearable prefix-icon="Search" |
| | | <el-input v-model="searchForm.name" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | prefix-icon="Search" |
| | | style="width: 200px;" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="å·¥åºç¼å·:"> |
| | | <el-input v-model="searchForm.no" placeholder="请è¾å
¥" clearable prefix-icon="Search" |
| | | <el-input v-model="searchForm.no" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | prefix-icon="Search" |
| | | style="width: 200px;" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleQuery">æç´¢</el-button> |
| | | <el-button type="primary" |
| | | @click="handleQuery">æç´¢</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | <div class="table_list"> |
| | | <div style="text-align: right" class="mb10"> |
| | | <el-button type="primary" @click="showNewModal">æ°å¢å·¥åº</el-button> |
| | | <el-button type="danger" @click="handleDelete" :disabled="selectedRows.length === 0" plain>å é¤å·¥åº</el-button> |
| | | <div style="text-align: right" |
| | | class="mb10"> |
| | | <el-button type="primary" |
| | | @click="showNewModal">æ°å¢å·¥åº</el-button> |
| | | <el-button type="danger" |
| | | @click="handleDelete" |
| | | :disabled="selectedRows.length === 0" |
| | | plain>å é¤å·¥åº</el-button> |
| | | </div> |
| | | <PIMTable |
| | | rowKey="id" |
| | | <PIMTable rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | :total="page.total" |
| | | ></PIMTable> |
| | | :total="page.total"></PIMTable> |
| | | </div> |
| | | <new-process |
| | | v-if="isShowNewModal" |
| | | <new-process v-if="isShowNewModal" |
| | | v-model:visible="isShowNewModal" |
| | | @completed="getList" |
| | | /> |
| | | |
| | | <edit-process |
| | | v-if="isShowEditModal" |
| | | @completed="getList" /> |
| | | <edit-process v-if="isShowEditModal" |
| | | v-model:visible="isShowEditModal" |
| | | :record="record" |
| | | @completed="getList" |
| | | /> |
| | | @completed="getList" /> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | clickFun: row => { |
| | | showEditModal(row); |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | const { proxy } = getCurrentInstance() |
| | | const { proxy } = getCurrentInstance(); |
| | | |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | |
| | | getList(); |
| | | }; |
| | | |
| | | const pagination = (obj) => { |
| | | 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 |
| | | listPage(params).then(res => { |
| | | params.entryDate = undefined; |
| | | listPage(params) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records.map(item => ({ |
| | | ...item, |
| | | })); |
| | | page.total = res.data.total; |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | | }) |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | | const handleSelectionChange = selection => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | |
| | | // æå¼æ°å¢å¼¹æ¡ |
| | | const showNewModal = () => { |
| | | isShowNewModal.value = true |
| | | isShowNewModal.value = true; |
| | | }; |
| | | |
| | | const showEditModal = (row) => { |
| | | isShowEditModal.value = true |
| | | record.value = row |
| | | const showEditModal = row => { |
| | | isShowEditModal.value = true; |
| | | record.value = row; |
| | | }; |
| | | |
| | | // å é¤ |
| | | function handleDelete() { |
| | | const no = selectedRows.value.map((item) => item.no); |
| | | const ids = selectedRows.value.map((item) => item.id); |
| | | const no = selectedRows.value.map(item => item.no); |
| | | const ids = selectedRows.value.map(item => item.id); |
| | | if (no.length > 2) { |
| | | proxy.$modal |
| | | .confirm( |
| | | 'æ¯å¦ç¡®è®¤å é¤å·¥åºç¼å·ä¸º"' + |
| | | no[0] + |
| | | "ã" + |
| | | no[1] + |
| | | '"ç' + |
| | | no.length + |
| | | "æ¡æ°æ®é¡¹ï¼" |
| | | ) |
| | | .then(function () { |
| | | return del(ids); |
| | | }) |
| | | .then(() => { |
| | | getList(); |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | }) |
| | | .catch(() => {}); |
| | | } else { |
| | | proxy.$modal |
| | | .confirm('æ¯å¦ç¡®è®¤å é¤å·¥åºç¼å·ä¸º"' + no + '"çæ°æ®é¡¹ï¼') |
| | | .then(function () { |
| | |
| | | }) |
| | | .catch(() => {}); |
| | | } |
| | | } |
| | | |
| | | // å¯¼åº |
| | | // const handleOut = () => { |
| | |
| | | <template> |
| | | <div> |
| | | <el-dialog |
| | | v-model="isShow" |
| | | <el-dialog v-model="isShow" |
| | | title="产åº" |
| | | @close="closeModal" |
| | | > |
| | | <PIMTable |
| | | rowKey="id" |
| | | @close="closeModal"> |
| | | <PIMTable rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="data" |
| | | :page="page" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | ></PIMTable> |
| | | @pagination="pagination"></PIMTable> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="closeModal">å
³é</el-button> |
| | | <el-button type="primary" |
| | | @click="closeModal">å
³é</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | |
| | | }, |
| | | }); |
| | | |
| | | const emit = defineEmits(['update:visible', 'completed']); |
| | | const emit = defineEmits(["update:visible", "completed"]); |
| | | |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0 |
| | | total: 0, |
| | | }); |
| | | |
| | | const pagination = (obj) => { |
| | | const pagination = obj => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | fetchData(); |
| | |
| | | |
| | | const tableColumn = [ |
| | | { |
| | | label: 'æ¥å·¥åå·', |
| | | prop: 'productNo', |
| | | label: "æ¥å·¥åå·", |
| | | prop: "productNo", |
| | | }, |
| | | { |
| | | label: '产ååå·', |
| | | prop: 'model', |
| | | label: "产ååå·", |
| | | prop: "model", |
| | | }, |
| | | { |
| | | label: 'æå
¥æ°é', |
| | | prop: 'quantity', |
| | | label: "äº§åºæ°é", |
| | | prop: "quantity", |
| | | }, |
| | | ] |
| | | ]; |
| | | |
| | | const isShow = computed({ |
| | | get() { |
| | | return props.visible; |
| | | }, |
| | | set(val) { |
| | | emit('update:visible', val); |
| | | emit("update:visible", val); |
| | | }, |
| | | }); |
| | | |
| | | const data = ref([]) |
| | | const data = ref([]); |
| | | |
| | | const closeModal = () => { |
| | | isShow.value = false; |
| | |
| | | tableLoading.value = true; |
| | | const params = { productMainId: props.productionProductMainId, ...page }; |
| | | |
| | | productionProductOutputListPage(params).then(res => { |
| | | productionProductOutputListPage(params) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | data.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | | }) |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | defineExpose({ |
| | |
| | | }); |
| | | |
| | | onMounted(() => { |
| | | fetchData() |
| | | }) |
| | | fetchData(); |
| | | }); |
| | | </script> |
| | |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 200, |
| | | width: 230, |
| | | operation: [ |
| | | { |
| | | name: "æ¥çæå
¥", |
| | |
| | | </el-form> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button @click="editDialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" |
| | | @click="handleUpdate">ç¡®å®</el-button> |
| | | <el-button @click="editDialogVisible = false">åæ¶</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | |
| | | <el-form :model="reportForm" |
| | | label-width="120px"> |
| | | <el-form-item label="å¾
ç产æ°é"> |
| | | <el-input v-model="reportForm.remainingQuantity" |
| | | <el-input v-model="reportForm.planQuantity" |
| | | readonly |
| | | style="width: 300px" /> |
| | | </el-form-item> |
| | |
| | | </el-form> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button @click="reportDialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" |
| | | @click="handleReport">ç¡®å®</el-button> |
| | | <el-button @click="reportDialogVisible = false">åæ¶</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | |
| | | { |
| | | label: "å·¥åç¼å·", |
| | | prop: "workOrderNo", |
| | | width: "140", |
| | | }, |
| | | { |
| | | label: "ç产订åå·", |
| | | prop: "productOrderNpsNo", |
| | | width: "140", |
| | | }, |
| | | { |
| | | label: "产ååç§°", |
| | | prop: "productName", |
| | | width: "140", |
| | | }, |
| | | { |
| | | label: "è§æ ¼", |
| | |
| | | prop: "processName", |
| | | }, |
| | | { |
| | | label: "å¾
ç产æ°é", |
| | | prop: "planQuantity", |
| | | width: "140", |
| | | }, |
| | | { |
| | | label: "计åç产æ°é", |
| | | prop: "quantity", |
| | | width: "140", |
| | | }, |
| | | { |
| | | label: "计åå¼å§æ¶é´", |
| | | prop: "planStartTime", |
| | | width: "140", |
| | | }, |
| | | { |
| | | label: "计åç»ææ¶é´", |
| | | prop: "planEndTime", |
| | | width: "140", |
| | | }, |
| | | { |
| | | label: "å®é
å¼å§æ¶é´", |
| | | prop: "actualStartTime", |
| | | width: "140", |
| | | }, |
| | | { |
| | | label: "å®é
ç»ææ¶é´", |
| | | prop: "actualEndTime", |
| | | width: "140", |
| | | }, |
| | | { |
| | | label: "æä½", |
| | |
| | | clickFun: row => { |
| | | showReportDialog(row); |
| | | }, |
| | | disabled: row => row.planQuantity <= 0, |
| | | }, |
| | | ], |
| | | }, |
| | |
| | | const transferCardRowData = ref(null); |
| | | const reportDialogVisible = ref(false); |
| | | const reportForm = reactive({ |
| | | remainingQuantity: 0, |
| | | planQuantity: 0, |
| | | quantity: 0, |
| | | userName: "", |
| | | workOrderId: "", |
| | |
| | | |
| | | const showReportDialog = row => { |
| | | currentReportRowData.value = row; |
| | | reportForm.remainingQuantity = 1; |
| | | reportForm.planQuantity = row.planQuantity; |
| | | reportForm.quantity = row.quantity; |
| | | reportForm.productProcessRouteItemId = row.productProcessRouteItemId; |
| | | reportForm.workOrderId = row.id; |
| | |
| | | }; |
| | | |
| | | const handleReport = () => { |
| | | if (reportForm.planQuantity <= 0) { |
| | | ElMessageBox.alert("å¾
ç产æ°é为0ï¼æ æ³æ¥å·¥", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | }); |
| | | return; |
| | | } |
| | | if (!reportForm.quantity || reportForm.quantity <= 0) { |
| | | ElMessageBox.alert("请è¾å
¥ææçæ¬æ¬¡ç产æ°é", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | }); |
| | | return; |
| | | } |
| | | if (reportForm.quantity > reportForm.remainingQuantity) { |
| | | if (reportForm.quantity > reportForm.planQuantity) { |
| | | ElMessageBox.alert("æ¬æ¬¡ç产æ°éä¸è½è¶
è¿å¾
ç产æ°é", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | }); |
| | |
| | | v-model="form.supplier" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | filterable |
| | | > |
| | | <el-option |
| | | v-for="item in supplierList" |
| | |
| | | <div class="app-container"> |
| | | <el-card class="box-card"> |
| | | <!-- æç´¢åºå --> |
| | | <el-row :gutter="20" class="search-row"> |
| | | <el-row :gutter="20" |
| | | class="search-row"> |
| | | <el-col :span="6"> |
| | | <el-input |
| | | v-model="searchForm.name" |
| | | <el-input v-model="searchForm.name" |
| | | placeholder="请è¾å
¥å®¢æ·åç§°" |
| | | clearable |
| | | @keyup.enter="handleSearch" |
| | | > |
| | | @keyup.enter="handleSearch"> |
| | | <template #prefix> |
| | | <el-icon><Search /></el-icon> |
| | | <el-icon> |
| | | <Search /> |
| | | </el-icon> |
| | | </template> |
| | | </el-input> |
| | | </el-col> |
| | | <el-col :span="6"> |
| | | <el-select v-model="searchForm.region" placeholder="è¯·éæ©åºå" clearable> |
| | | <el-option label="åä¸åº" value="åä¸åº"></el-option> |
| | | <el-option label="åååº" value="åååº"></el-option> |
| | | <el-option label="åååº" value="åååº"></el-option> |
| | | <el-option label="西ååº" value="西ååº"></el-option> |
| | | <el-select v-model="searchForm.region" |
| | | placeholder="è¯·éæ©åºå" |
| | | clearable> |
| | | <el-option label="åä¸åº" |
| | | value="åä¸åº"></el-option> |
| | | <el-option label="åååº" |
| | | value="åååº"></el-option> |
| | | <el-option label="åååº" |
| | | value="åååº"></el-option> |
| | | <el-option label="西ååº" |
| | | value="西ååº"></el-option> |
| | | </el-select> |
| | | </el-col> |
| | | <el-col :span="6"> |
| | | <el-select v-model="searchForm.level" placeholder="è¯·éæ©å®¢æ·ç级" clearable> |
| | | <el-option label="VIP客æ·" value="VIP客æ·"></el-option> |
| | | <el-option label="éè¦å®¢æ·" value="éè¦å®¢æ·"></el-option> |
| | | <el-option label="æ®é客æ·" value="æ®é客æ·"></el-option> |
| | | <el-select v-model="searchForm.level" |
| | | placeholder="è¯·éæ©å®¢æ·ç级" |
| | | clearable> |
| | | <el-option label="VIP客æ·" |
| | | value="VIP客æ·"></el-option> |
| | | <el-option label="éè¦å®¢æ·" |
| | | value="éè¦å®¢æ·"></el-option> |
| | | <el-option label="æ®é客æ·" |
| | | value="æ®é客æ·"></el-option> |
| | | </el-select> |
| | | </el-col> |
| | | <el-col :span="6"> |
| | | <el-button type="primary" @click="handleSearch">æç´¢</el-button> |
| | | <el-button type="primary" |
| | | @click="handleSearch">æç´¢</el-button> |
| | | <el-button @click="resetSearch">éç½®</el-button> |
| | | <el-button style="float: right;" type="primary" @click="handleAdd"> |
| | | <el-button style="float: right;" |
| | | type="primary" |
| | | @click="handleAdd"> |
| | | æ°å¢å®¢æ· |
| | | </el-button> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <!-- 客æ·å表 --> |
| | | <el-table |
| | | :data="filteredList" |
| | | <el-table :data="filteredList" |
| | | style="width: 100%" |
| | | v-loading="loading" |
| | | border |
| | | stripe |
| | | height="calc(100vh - 22em)" |
| | | > |
| | | <el-table-column prop="id" label="ID" width="80" align="center"/> |
| | | <el-table-column prop="name" label="客æ·åç§°" width="150" /> |
| | | <el-table-column prop="contactPerson" label="è系人" width="100" /> |
| | | <el-table-column prop="phone" label="èç³»çµè¯" width="140" /> |
| | | <el-table-column prop="email" label="é®ç®±" /> |
| | | <el-table-column prop="region" label="åºå" width="100" /> |
| | | <el-table-column prop="level" label="客æ·ç级" width="100"> |
| | | height="calc(100vh - 22em)"> |
| | | <el-table-column prop="id" |
| | | label="ID" |
| | | width="80" |
| | | align="center" /> |
| | | <el-table-column prop="name" |
| | | label="客æ·åç§°" |
| | | width="150" /> |
| | | <el-table-column prop="contactPerson" |
| | | label="è系人" |
| | | width="100" /> |
| | | <el-table-column prop="phone" |
| | | label="èç³»çµè¯" |
| | | width="140" /> |
| | | <el-table-column prop="email" |
| | | label="é®ç®±" /> |
| | | <el-table-column prop="region" |
| | | label="åºå" |
| | | width="100" /> |
| | | <el-table-column prop="level" |
| | | label="客æ·ç级" |
| | | width="100"> |
| | | <template #default="scope"> |
| | | <el-tag :type="getLevelType(scope.row.level)"> |
| | | {{ scope.row.level }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="salesperson" label="è´è´£ä¸å¡å" width="120" /> |
| | | <el-table-column prop="status" label="ç¶æ" width="80"> |
| | | <el-table-column prop="salesperson" |
| | | label="è´è´£ä¸å¡å" |
| | | width="120" /> |
| | | <el-table-column prop="status" |
| | | label="ç¶æ" |
| | | width="80"> |
| | | <template #default="scope"> |
| | | <el-tag :type="getStatusType(scope.row.status)"> |
| | | {{ scope.row.status }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æä½" width="200" fixed="right" align="center"> |
| | | <el-table-column label="æä½" |
| | | width="200" |
| | | fixed="right" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" @click="handleEdit(scope.row)">ç¼è¾</el-button> |
| | | <el-button link type="primary" @click="handleAllocation(scope.row)">åé
</el-button> |
| | | <el-button link type="danger" @click="handleDelete(scope.row)">å é¤</el-button> |
| | | <el-button link |
| | | type="primary" |
| | | @click="handleEdit(scope.row)">ç¼è¾</el-button> |
| | | <el-button link |
| | | type="primary" |
| | | @click="handleAllocation(scope.row)">åé
</el-button> |
| | | <el-button link |
| | | type="danger" |
| | | @click="handleDelete(scope.row)">å é¤</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <!-- å页 --> |
| | | <pagination |
| | | :total="pagination.total" |
| | | <pagination :total="pagination.total" |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | :page="pagination.currentPage" |
| | | :limit="pagination.pageSize" |
| | | @pagination="handleCurrentChange" |
| | | /> |
| | | @pagination="handleCurrentChange" /> |
| | | </el-card> |
| | | |
| | | <!-- æ°å¢/ç¼è¾å¯¹è¯æ¡ --> |
| | | <el-dialog v-model="dialogVisible" :title="dialogTitle" width="600px"> |
| | | <el-form :model="form" :rules="rules" ref="formRef" label-width="100px"> |
| | | <el-dialog v-model="dialogVisible" |
| | | :title="dialogTitle" |
| | | width="600px"> |
| | | <el-form :model="form" |
| | | :rules="rules" |
| | | ref="formRef" |
| | | label-width="100px"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="客æ·åç§°" prop="name"> |
| | | <el-input v-model="form.name" placeholder="请è¾å
¥å®¢æ·åç§°"></el-input> |
| | | <el-form-item label="客æ·åç§°" |
| | | prop="name"> |
| | | <el-input v-model="form.name" |
| | | placeholder="请è¾å
¥å®¢æ·åç§°"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="è系人" prop="contactPerson"> |
| | | <el-input v-model="form.contactPerson" placeholder="请è¾å
¥è系人"></el-input> |
| | | <el-form-item label="è系人" |
| | | prop="contactPerson"> |
| | | <el-input v-model="form.contactPerson" |
| | | placeholder="请è¾å
¥è系人"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="èç³»çµè¯" prop="phone"> |
| | | <el-input v-model="form.phone" placeholder="请è¾å
¥èç³»çµè¯"></el-input> |
| | | <el-form-item label="èç³»çµè¯" |
| | | prop="phone"> |
| | | <el-input v-model="form.phone" |
| | | placeholder="请è¾å
¥èç³»çµè¯"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="é®ç®±" prop="email"> |
| | | <el-input v-model="form.email" placeholder="请è¾å
¥é®ç®±"></el-input> |
| | | <el-form-item label="é®ç®±" |
| | | prop="email"> |
| | | <el-input v-model="form.email" |
| | | placeholder="请è¾å
¥é®ç®±"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="åºå" prop="region"> |
| | | <el-select v-model="form.region" placeholder="è¯·éæ©åºå" style="width: 100%"> |
| | | <el-option label="åä¸åº" value="åä¸åº"></el-option> |
| | | <el-option label="åååº" value="åååº"></el-option> |
| | | <el-option label="åååº" value="åååº"></el-option> |
| | | <el-option label="西ååº" value="西ååº"></el-option> |
| | | <el-form-item label="åºå" |
| | | prop="region"> |
| | | <el-select v-model="form.region" |
| | | placeholder="è¯·éæ©åºå" |
| | | style="width: 100%"> |
| | | <el-option label="åä¸åº" |
| | | value="åä¸åº"></el-option> |
| | | <el-option label="åååº" |
| | | value="åååº"></el-option> |
| | | <el-option label="åååº" |
| | | value="åååº"></el-option> |
| | | <el-option label="西ååº" |
| | | value="西ååº"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="客æ·ç级" prop="level"> |
| | | <el-select v-model="form.level" placeholder="è¯·éæ©å®¢æ·ç级" style="width: 100%"> |
| | | <el-option label="VIP客æ·" value="VIP客æ·"></el-option> |
| | | <el-option label="éè¦å®¢æ·" value="éè¦å®¢æ·"></el-option> |
| | | <el-option label="æ®é客æ·" value="æ®é客æ·"></el-option> |
| | | <el-form-item label="客æ·ç级" |
| | | prop="level"> |
| | | <el-select v-model="form.level" |
| | | placeholder="è¯·éæ©å®¢æ·ç级" |
| | | style="width: 100%"> |
| | | <el-option label="VIP客æ·" |
| | | value="VIP客æ·"></el-option> |
| | | <el-option label="éè¦å®¢æ·" |
| | | value="éè¦å®¢æ·"></el-option> |
| | | <el-option label="æ®é客æ·" |
| | | value="æ®é客æ·"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="è´è´£ä¸å¡å" prop="salesperson"> |
| | | <el-select v-model="form.salesperson" placeholder="è¯·éæ©ä¸å¡å" style="width: 100%"> |
| | | <el-option label="éå¿å¼º" value="éå¿å¼º"></el-option> |
| | | <el-option label="åé
å©·" value="åé
å©·"></el-option> |
| | | <el-option label="ç建å½" value="ç建å½"></el-option> |
| | | <el-form-item label="è´è´£ä¸å¡å" |
| | | prop="salesperson"> |
| | | <el-select v-model="form.salesperson" |
| | | placeholder="è¯·éæ©ä¸å¡å" |
| | | style="width: 100%"> |
| | | <el-option label="éå¿å¼º" |
| | | value="éå¿å¼º"></el-option> |
| | | <el-option label="åé
å©·" |
| | | value="åé
å©·"></el-option> |
| | | <el-option label="ç建å½" |
| | | value="ç建å½"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç¶æ" prop="status"> |
| | | <el-select v-model="form.status" placeholder="è¯·éæ©ç¶æ" style="width: 100%"> |
| | | <el-option label="æ´»è·" value="æ´»è·"></el-option> |
| | | <el-option label="æ½å¨" value="æ½å¨"></el-option> |
| | | <el-option label="æµå¤±" value="æµå¤±"></el-option> |
| | | <el-form-item label="ç¶æ" |
| | | prop="status"> |
| | | <el-select v-model="form.status" |
| | | placeholder="è¯·éæ©ç¶æ" |
| | | style="width: 100%"> |
| | | <el-option label="æ´»è·" |
| | | value="æ´»è·"></el-option> |
| | | <el-option label="æ½å¨" |
| | | value="æ½å¨"></el-option> |
| | | <el-option label="æµå¤±" |
| | | value="æµå¤±"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="handleSubmit">ç¡® å®</el-button> |
| | | <el-button @click="dialogVisible = false">å æ¶</el-button> |
| | | <el-button type="primary" @click="handleSubmit">ç¡® å®</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- 客æ·åé
å¯¹è¯æ¡ --> |
| | | <el-dialog v-model="allocationDialogVisible" title="客æ·åé
" width="500px"> |
| | | <el-dialog v-model="allocationDialogVisible" |
| | | title="客æ·åé
" |
| | | width="500px"> |
| | | <el-form label-width="100px"> |
| | | <el-form-item label="客æ·åç§°"> |
| | | <span>{{ currentCustomer.name }}</span> |
| | |
| | | <span>{{ currentCustomer.salesperson }}</span> |
| | | </el-form-item> |
| | | <el-form-item label="éæ°åé
"> |
| | | <el-select v-model="newSalesperson" placeholder="è¯·éæ©æ°ä¸å¡å" style="width: 100%"> |
| | | <el-option label="éå¿å¼º" value="éå¿å¼º"></el-option> |
| | | <el-option label="åé
å©·" value="åé
å©·"></el-option> |
| | | <el-option label="ç建å½" value="ç建å½"></el-option> |
| | | <el-select v-model="newSalesperson" |
| | | placeholder="è¯·éæ©æ°ä¸å¡å" |
| | | style="width: 100%"> |
| | | <el-option label="éå¿å¼º" |
| | | value="éå¿å¼º"></el-option> |
| | | <el-option label="åé
å©·" |
| | | value="åé
å©·"></el-option> |
| | | <el-option label="ç建å½" |
| | | value="ç建å½"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="åé
åå "> |
| | | <el-input v-model="allocationReason" type="textarea" rows="3" placeholder="请è¾å
¥åé
åå "></el-input> |
| | | <el-input v-model="allocationReason" |
| | | type="textarea" |
| | | rows="3" |
| | | placeholder="请è¾å
¥åé
åå "></el-input> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="saveAllocation">ç¡® å®</el-button> |
| | | <el-button @click="allocationDialogVisible = false">å æ¶</el-button> |
| | | <el-button type="primary" @click="saveAllocation">ç¡® å®</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, computed } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { Plus, Search } from '@element-plus/icons-vue' |
| | | import Pagination from '@/components/PIMTable/Pagination.vue' |
| | | import { ref, reactive, computed } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import { Plus, Search } from "@element-plus/icons-vue"; |
| | | import Pagination from "@/components/PIMTable/Pagination.vue"; |
| | | |
| | | // ååºå¼æ°æ® |
| | | const loading = ref(false) |
| | | const loading = ref(false); |
| | | const searchForm = reactive({ |
| | | name: '', |
| | | region: '', |
| | | level: '' |
| | | }) |
| | | name: "", |
| | | region: "", |
| | | level: "", |
| | | }); |
| | | |
| | | const customerList = ref([ |
| | | { |
| | | id: 1, |
| | | name: '䏿µ·ç§ææéå
¬å¸', |
| | | contactPerson: 'éå¿å¼º', |
| | | phone: '021-12345678', |
| | | email: 'zhang@shanghai-tech.com', |
| | | region: 'åä¸åº', |
| | | level: 'VIP客æ·', |
| | | salesperson: 'éå¿å¼º', |
| | | status: 'æ´»è·' |
| | | name: "䏿µ·ç§ææéå
¬å¸", |
| | | contactPerson: "éå¿å¼º", |
| | | phone: "021-12345678", |
| | | email: "zhang@shanghai-tech.com", |
| | | region: "åä¸åº", |
| | | level: "VIP客æ·", |
| | | salesperson: "éå¿å¼º", |
| | | status: "æ´»è·", |
| | | }, |
| | | { |
| | | id: 2, |
| | | name: 'æ·±å³çµåæéå
¬å¸', |
| | | contactPerson: 'åé
å©·', |
| | | phone: '0755-87654321', |
| | | email: 'li@shenzhen-elec.com', |
| | | region: 'åååº', |
| | | level: 'éè¦å®¢æ·', |
| | | salesperson: 'åé
å©·', |
| | | status: 'æ´»è·' |
| | | name: "æ·±å³çµåæéå
¬å¸", |
| | | contactPerson: "åé
å©·", |
| | | phone: "0755-87654321", |
| | | email: "li@shenzhen-elec.com", |
| | | region: "åååº", |
| | | level: "éè¦å®¢æ·", |
| | | salesperson: "åé
å©·", |
| | | status: "æ´»è·", |
| | | }, |
| | | { |
| | | id: 3, |
| | | name: 'å京贸æå
¬å¸', |
| | | contactPerson: 'ç建å½', |
| | | phone: '010-11223344', |
| | | email: 'wang@beijing-trade.com', |
| | | region: 'åååº', |
| | | level: 'æ®é客æ·', |
| | | salesperson: 'ç建å½', |
| | | status: 'æ½å¨' |
| | | } |
| | | ]) |
| | | name: "å京贸æå
¬å¸", |
| | | contactPerson: "ç建å½", |
| | | phone: "010-11223344", |
| | | email: "wang@beijing-trade.com", |
| | | region: "åååº", |
| | | level: "æ®é客æ·", |
| | | salesperson: "ç建å½", |
| | | status: "æ½å¨", |
| | | }, |
| | | ]); |
| | | |
| | | const pagination = reactive({ |
| | | total: 3, |
| | | currentPage: 1, |
| | | pageSize: 10 |
| | | }) |
| | | pageSize: 10, |
| | | }); |
| | | |
| | | const dialogVisible = ref(false) |
| | | const dialogTitle = ref('æ°å¢å®¢æ·') |
| | | const dialogVisible = ref(false); |
| | | const dialogTitle = ref("æ°å¢å®¢æ·"); |
| | | const form = reactive({ |
| | | name: '', |
| | | contactPerson: '', |
| | | phone: '', |
| | | email: '', |
| | | region: '', |
| | | level: '', |
| | | salesperson: '', |
| | | status: 'æ´»è·' |
| | | }) |
| | | name: "", |
| | | contactPerson: "", |
| | | phone: "", |
| | | email: "", |
| | | region: "", |
| | | level: "", |
| | | salesperson: "", |
| | | status: "æ´»è·", |
| | | }); |
| | | |
| | | const rules = { |
| | | name: [{ required: true, message: '请è¾å
¥å®¢æ·åç§°', trigger: 'blur' }], |
| | | contactPerson: [{ required: true, message: '请è¾å
¥è系人', trigger: 'blur' }], |
| | | phone: [{ required: true, message: '请è¾å
¥èç³»çµè¯', trigger: 'blur' }], |
| | | email: [{ required: true, message: '请è¾å
¥é®ç®±', trigger: 'blur' }], |
| | | region: [{ required: true, message: 'è¯·éæ©åºå', trigger: 'change' }], |
| | | level: [{ required: true, message: 'è¯·éæ©å®¢æ·ç级', trigger: 'change' }], |
| | | salesperson: [{ required: true, message: 'è¯·éæ©ä¸å¡å', trigger: 'change' }], |
| | | status: [{ required: true, message: 'è¯·éæ©ç¶æ', trigger: 'change' }] |
| | | } |
| | | name: [{ required: true, message: "请è¾å
¥å®¢æ·åç§°", trigger: "blur" }], |
| | | contactPerson: [{ required: true, message: "请è¾å
¥è系人", trigger: "blur" }], |
| | | phone: [{ required: true, message: "请è¾å
¥èç³»çµè¯", trigger: "blur" }], |
| | | email: [{ required: true, message: "请è¾å
¥é®ç®±", trigger: "blur" }], |
| | | region: [{ required: true, message: "è¯·éæ©åºå", trigger: "change" }], |
| | | level: [{ required: true, message: "è¯·éæ©å®¢æ·ç级", trigger: "change" }], |
| | | salesperson: [{ required: true, message: "è¯·éæ©ä¸å¡å", trigger: "change" }], |
| | | status: [{ required: true, message: "è¯·éæ©ç¶æ", trigger: "change" }], |
| | | }; |
| | | |
| | | const isEdit = ref(false) |
| | | const editId = ref(null) |
| | | const allocationDialogVisible = ref(false) |
| | | const currentCustomer = ref({}) |
| | | const newSalesperson = ref('') |
| | | const allocationReason = ref('') |
| | | const formRef = ref() |
| | | const isEdit = ref(false); |
| | | const editId = ref(null); |
| | | const allocationDialogVisible = ref(false); |
| | | const currentCustomer = ref({}); |
| | | const newSalesperson = ref(""); |
| | | const allocationReason = ref(""); |
| | | const formRef = ref(); |
| | | |
| | | // 计ç®å±æ§ |
| | | const filteredList = computed(() => { |
| | | let list = customerList.value |
| | | let list = customerList.value; |
| | | if (searchForm.name) { |
| | | list = list.filter(item => item.name.includes(searchForm.name)) |
| | | list = list.filter(item => item.name.includes(searchForm.name)); |
| | | } |
| | | if (searchForm.region) { |
| | | list = list.filter(item => item.region === searchForm.region) |
| | | list = list.filter(item => item.region === searchForm.region); |
| | | } |
| | | if (searchForm.level) { |
| | | list = list.filter(item => item.level === searchForm.level) |
| | | list = list.filter(item => item.level === searchForm.level); |
| | | } |
| | | return list |
| | | }) |
| | | return list; |
| | | }); |
| | | |
| | | // æ¹æ³ |
| | | const getLevelType = (level) => { |
| | | const getLevelType = level => { |
| | | const levelMap = { |
| | | 'VIP客æ·': 'danger', |
| | | 'éè¦å®¢æ·': 'warning', |
| | | 'æ®é客æ·': 'info' |
| | | } |
| | | return levelMap[level] || 'info' |
| | | } |
| | | VIP客æ·: "danger", |
| | | éè¦å®¢æ·: "warning", |
| | | æ®é客æ·: "info", |
| | | }; |
| | | return levelMap[level] || "info"; |
| | | }; |
| | | |
| | | const getStatusType = (status) => { |
| | | const getStatusType = status => { |
| | | const statusMap = { |
| | | 'æ´»è·': 'success', |
| | | 'æ½å¨': 'warning', |
| | | 'æµå¤±': 'danger' |
| | | } |
| | | return statusMap[status] || 'info' |
| | | } |
| | | æ´»è·: "success", |
| | | æ½å¨: "warning", |
| | | æµå¤±: "danger", |
| | | }; |
| | | return statusMap[status] || "info"; |
| | | }; |
| | | |
| | | const handleSearch = () => { |
| | | // æç´¢é»è¾å·²å¨computedä¸å¤ç |
| | | } |
| | | }; |
| | | |
| | | const resetSearch = () => { |
| | | searchForm.name = '' |
| | | searchForm.region = '' |
| | | searchForm.level = '' |
| | | } |
| | | searchForm.name = ""; |
| | | searchForm.region = ""; |
| | | searchForm.level = ""; |
| | | }; |
| | | |
| | | const handleAdd = () => { |
| | | dialogTitle.value = 'æ°å¢å®¢æ·' |
| | | isEdit.value = false |
| | | form.name = '' |
| | | form.contactPerson = '' |
| | | form.phone = '' |
| | | form.email = '' |
| | | form.region = '' |
| | | form.level = '' |
| | | form.salesperson = '' |
| | | form.status = 'æ´»è·' |
| | | dialogVisible.value = true |
| | | } |
| | | dialogTitle.value = "æ°å¢å®¢æ·"; |
| | | isEdit.value = false; |
| | | form.name = ""; |
| | | form.contactPerson = ""; |
| | | form.phone = ""; |
| | | form.email = ""; |
| | | form.region = ""; |
| | | form.level = ""; |
| | | form.salesperson = ""; |
| | | form.status = "æ´»è·"; |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | const handleEdit = (row) => { |
| | | dialogTitle.value = 'ç¼è¾å®¢æ·' |
| | | isEdit.value = true |
| | | editId.value = row.id |
| | | Object.assign(form, row) |
| | | dialogVisible.value = true |
| | | } |
| | | const handleEdit = row => { |
| | | dialogTitle.value = "ç¼è¾å®¢æ·"; |
| | | isEdit.value = true; |
| | | editId.value = row.id; |
| | | Object.assign(form, row); |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | const handleDelete = (row) => { |
| | | ElMessageBox.confirm('确认å é¤è¯¥å®¢æ·åï¼', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | const handleDelete = row => { |
| | | ElMessageBox.confirm("确认å é¤è¯¥å®¢æ·åï¼", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).then(() => { |
| | | const index = customerList.value.findIndex(item => item.id === row.id) |
| | | const index = customerList.value.findIndex(item => item.id === row.id); |
| | | if (index > -1) { |
| | | customerList.value.splice(index, 1) |
| | | pagination.total-- |
| | | ElMessage.success('å 餿å') |
| | | customerList.value.splice(index, 1); |
| | | pagination.total--; |
| | | ElMessage.success("å 餿å"); |
| | | } |
| | | }) |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | const handleAllocation = (row) => { |
| | | currentCustomer.value = row |
| | | newSalesperson.value = '' |
| | | allocationReason.value = '' |
| | | allocationDialogVisible.value = true |
| | | } |
| | | const handleAllocation = row => { |
| | | currentCustomer.value = row; |
| | | newSalesperson.value = ""; |
| | | allocationReason.value = ""; |
| | | allocationDialogVisible.value = true; |
| | | }; |
| | | |
| | | const saveAllocation = () => { |
| | | if (!newSalesperson.value) { |
| | | ElMessage.warning('è¯·éæ©æ°ä¸å¡å') |
| | | return |
| | | ElMessage.warning("è¯·éæ©æ°ä¸å¡å"); |
| | | return; |
| | | } |
| | | |
| | | const index = customerList.value.findIndex(item => item.id === currentCustomer.value.id) |
| | | const index = customerList.value.findIndex( |
| | | item => item.id === currentCustomer.value.id |
| | | ); |
| | | if (index > -1) { |
| | | customerList.value[index].salesperson = newSalesperson.value |
| | | ElMessage.success('客æ·åé
æå') |
| | | allocationDialogVisible.value = false |
| | | customerList.value[index].salesperson = newSalesperson.value; |
| | | ElMessage.success("客æ·åé
æå"); |
| | | allocationDialogVisible.value = false; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | const handleSubmit = () => { |
| | | formRef.value.validate((valid) => { |
| | | formRef.value.validate(valid => { |
| | | if (valid) { |
| | | if (isEdit.value) { |
| | | // ç¼è¾ |
| | | const index = customerList.value.findIndex(item => item.id === editId.value) |
| | | const index = customerList.value.findIndex( |
| | | item => item.id === editId.value |
| | | ); |
| | | if (index > -1) { |
| | | customerList.value[index] = { ...form, id: editId.value } |
| | | ElMessage.success('ç¼è¾æå') |
| | | customerList.value[index] = { ...form, id: editId.value }; |
| | | ElMessage.success("ç¼è¾æå"); |
| | | } |
| | | } else { |
| | | // æ°å¢ |
| | | const newId = Math.max(...customerList.value.map(item => item.id)) + 1 |
| | | const newId = Math.max(...customerList.value.map(item => item.id)) + 1; |
| | | customerList.value.push({ |
| | | ...form, |
| | | id: newId |
| | | }) |
| | | pagination.total++ |
| | | ElMessage.success('æ°å¢æå') |
| | | id: newId, |
| | | }); |
| | | pagination.total++; |
| | | ElMessage.success("æ°å¢æå"); |
| | | } |
| | | dialogVisible.value = false |
| | | dialogVisible.value = false; |
| | | } |
| | | }) |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | const handleCurrentChange = (val) => { |
| | | pagination.currentPage = val.page |
| | | pagination.pageSize = val.limit |
| | | } |
| | | const handleCurrentChange = val => { |
| | | pagination.currentPage = val.page; |
| | | pagination.pageSize = val.limit; |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped> |
| src/views/salesManagement/orderManagement/index.vue
src/views/salesManagement/paymentShipping/index.vue
src/views/salesManagement/salesLedger/index.vue
src/views/salesManagement/salesQuotation/index.vue
src/views/salesManagement/salespersonManagement/index.vue
src/views/tool/gen/importTable.vue |