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" |
| | | placeholder="请è¾å
¥è¦ç¼ç çå
容" |
| | | :type="form.type === 'security' ? 'textarea' : 'text'" |
| | | :rows="form.type === 'security' ? 3 : 1" |
| | | ></el-input> |
| | | <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> |
| | | </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" |
| | | :min="100" |
| | | :max="500" |
| | | :step="50" |
| | | style="width: 100%" |
| | | ></el-input-number> |
| | | <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> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <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> |
| | | <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> |
| | | </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" |
| | | :key="index" |
| | | class="batch-item" |
| | | > |
| | | <img :src="code.url" :alt="code.content" /> |
| | | <div v-for="(code, index) in batchCodes" |
| | | :key="index" |
| | | 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' |
| | | }) |
| | | // å®ä¹ç»ä»¶åç§° |
| | | defineOptions({ |
| | | name: "QRCodeGenerator", |
| | | }); |
| | | |
| | | // è¡¨åæ°æ® |
| | | const form = reactive({ |
| | | type: 'qrcode', |
| | | content: '', |
| | | size: 200, |
| | | margin: 2, |
| | | foregroundColor: '#000000', |
| | | backgroundColor: '#FFFFFF' |
| | | }) |
| | | // è¡¨åæ°æ® |
| | | const form = reactive({ |
| | | type: "qrcode", |
| | | content: "", |
| | | size: 200, |
| | | margin: 2, |
| | | foregroundColor: "#000000", |
| | | backgroundColor: "#FFFFFF", |
| | | }); |
| | | |
| | | // 表åéªè¯è§å |
| | | const rules = { |
| | | type: [{ required: true, message: 'è¯·éæ©æ è¯ç±»å', trigger: 'change' }], |
| | | content: [{ required: true, message: '请è¾å
¥å
容', trigger: 'blur' }] |
| | | } |
| | | // 表åéªè¯è§å |
| | | const rules = { |
| | | 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 batchForm = reactive({ |
| | | quantity: 10, |
| | | prefix: '', |
| | | startNumber: 1 |
| | | }) |
| | | const batchCodes = ref([]) |
| | | // ååºå¼æ°æ® |
| | | 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([]); |
| | | |
| | | // çæäºç»´ç æé²ä¼ªç |
| | | const generateCode = async () => { |
| | | try { |
| | | await formRef.value.validate() |
| | | |
| | | if (!form.content.trim()) { |
| | | ElMessage.warning('请è¾å
¥è¦ç¼ç çå
容') |
| | | return |
| | | } |
| | | |
| | | generating.value = true |
| | | |
| | | if (form.type === 'qrcode') { |
| | | // çæäºç»´ç |
| | | generatedCodeUrl.value = await QRCode.toDataURL(form.content, { |
| | | width: form.size, |
| | | margin: form.margin, |
| | | color: { |
| | | dark: form.foregroundColor, |
| | | light: form.backgroundColor |
| | | }, |
| | | errorCorrectionLevel: 'M' |
| | | }) |
| | | } else { |
| | | // çæé²ä¼ªç ï¼ä½¿ç¨äºç»´ç ææ¯ï¼ä½å
å®¹æ ¼å¼ä¸åï¼ |
| | | const securityContent = generateSecurityCode(form.content) |
| | | generatedCodeUrl.value = await QRCode.toDataURL(securityContent, { |
| | | width: form.size, |
| | | margin: form.margin, |
| | | color: { |
| | | dark: form.foregroundColor, |
| | | light: form.backgroundColor |
| | | }, |
| | | errorCorrectionLevel: 'H' // é²ä¼ªç ä½¿ç¨æé«çº éçº§å« |
| | | }) |
| | | } |
| | | |
| | | generateTime.value = new Date().toLocaleString() |
| | | ElMessage.success('çææåï¼') |
| | | |
| | | } catch (error) { |
| | | console.error('çæå¤±è´¥:', error) |
| | | ElMessage.error('çæå¤±è´¥ï¼' + error.message) |
| | | } finally { |
| | | generating.value = false |
| | | } |
| | | } |
| | | // çæäºç»´ç æé²ä¼ªç |
| | | const generateCode = async () => { |
| | | try { |
| | | await formRef.value.validate(); |
| | | |
| | | // çæé²ä¼ªç å
容 |
| | | const generateSecurityCode = (content) => { |
| | | const timestamp = Date.now() |
| | | const random = Math.random().toString(36).substr(2, 8) |
| | | return `SEC_${content}_${timestamp}_${random}` |
| | | } |
| | | if (!form.content.trim()) { |
| | | ElMessage.warning("请è¾å
¥è¦ç¼ç çå
容"); |
| | | return; |
| | | } |
| | | |
| | | // ä¸è½½çæçç |
| | | const downloadCode = () => { |
| | | if (!generatedCodeUrl.value) { |
| | | 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('ä¸è½½æåï¼') |
| | | } |
| | | generating.value = true; |
| | | |
| | | // å¤å¶å
容å°åªè´´æ¿ |
| | | const copyToClipboard = async () => { |
| | | try { |
| | | 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 printCode = () => { |
| | | if (!generatedCodeUrl.value) { |
| | | ElMessage.warning('请å
çæç ') |
| | | return |
| | | } |
| | | |
| | | const printWindow = window.open('', '_blank') |
| | | printWindow.document.write(` |
| | | <html> |
| | | <head> |
| | | <title>æå°${form.type === 'qrcode' ? 'äºç»´ç ' : 'é²ä¼ªç '}</title> |
| | | <style> |
| | | body { text-align: center; padding: 20px; } |
| | | img { max-width: 100%; height: auto; } |
| | | .info { margin: 20px 0; } |
| | | </style> |
| | | </head> |
| | | <body> |
| | | <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() |
| | | } |
| | | |
| | | // é置表å |
| | | const resetForm = () => { |
| | | formRef.value.resetFields() |
| | | generatedCodeUrl.value = '' |
| | | generateTime.value = '' |
| | | batchCodes.value = [] |
| | | } |
| | | |
| | | // æ¹éçæ |
| | | const generateBatchCodes = async () => { |
| | | if (!batchForm.prefix.trim()) { |
| | | ElMessage.warning('请è¾å
¥åç¼') |
| | | return |
| | | } |
| | | |
| | | 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')}` |
| | | |
| | | let codeUrl |
| | | if (form.type === 'qrcode') { |
| | | codeUrl = await QRCode.toDataURL(content, { |
| | | 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", |
| | | }); |
| | | } else { |
| | | const securityContent = generateSecurityCode(content) |
| | | codeUrl = await QRCode.toDataURL(securityContent, { |
| | | // çæé²ä¼ªç ï¼ä½¿ç¨äºç»´ç ææ¯ï¼ä½å
å®¹æ ¼å¼ä¸åï¼ |
| | | 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", // é²ä¼ªç ä½¿ç¨æé«çº éçº§å« |
| | | }); |
| | | } |
| | | |
| | | batchCodes.value.push({ |
| | | content, |
| | | url: codeUrl |
| | | }) |
| | | |
| | | generateTime.value = new Date().toLocaleString(); |
| | | ElMessage.success("çææåï¼"); |
| | | } catch (error) { |
| | | console.error("çæå¤±è´¥:", error); |
| | | ElMessage.error("çæå¤±è´¥ï¼" + error.message); |
| | | } finally { |
| | | generating.value = false; |
| | | } |
| | | |
| | | ElMessage.success(`æ¹éçæå®æï¼å
±çæ ${batchForm.quantity} 个ç `) |
| | | batchDialogVisible.value = false |
| | | |
| | | } catch (error) { |
| | | console.error('æ¹éçæå¤±è´¥:', error) |
| | | ElMessage.error('æ¹éçæå¤±è´¥ï¼' + error.message) |
| | | } finally { |
| | | 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 generateSecurityCode = content => { |
| | | const timestamp = Date.now(); |
| | | const random = Math.random().toString(36).substr(2, 8); |
| | | return `SEC_${content}_${timestamp}_${random}`; |
| | | }; |
| | | |
| | | // ä¸è½½æææ¹éçæçç |
| | | const downloadAllCodes = async () => { |
| | | if (batchCodes.value.length === 0) { |
| | | ElMessage.warning('没æå¯ä¸è½½çç ') |
| | | return |
| | | } |
| | | |
| | | try { |
| | | // 使ç¨JSZipæå
ä¸è½½ |
| | | 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) |
| | | for (let i = 0; i < byteCharacters.length; i++) { |
| | | byteNumbers[i] = byteCharacters.charCodeAt(i) |
| | | // ä¸è½½çæçç |
| | | const downloadCode = () => { |
| | | if (!generatedCodeUrl.value) { |
| | | 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 copyToClipboard = async () => { |
| | | try { |
| | | 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 printCode = () => { |
| | | if (!generatedCodeUrl.value) { |
| | | ElMessage.warning("请å
çæç "); |
| | | return; |
| | | } |
| | | |
| | | const printWindow = window.open("", "_blank"); |
| | | printWindow.document.write(` |
| | | <html> |
| | | <head> |
| | | <title>æå°${form.type === "qrcode" ? "äºç»´ç " : "é²ä¼ªç "}</title> |
| | | <style> |
| | | body { text-align: center; padding: 20px; } |
| | | img { max-width: 100%; height: auto; } |
| | | .info { margin: 20px 0; } |
| | | </style> |
| | | </head> |
| | | <body> |
| | | <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(); |
| | | }; |
| | | |
| | | // é置表å |
| | | const resetForm = () => { |
| | | formRef.value.resetFields(); |
| | | generatedCodeUrl.value = ""; |
| | | generateTime.value = ""; |
| | | batchCodes.value = []; |
| | | }; |
| | | |
| | | // æ¹éçæ |
| | | const generateBatchCodes = async () => { |
| | | if (!batchForm.prefix.trim()) { |
| | | ElMessage.warning("请è¾å
¥åç¼"); |
| | | return; |
| | | } |
| | | |
| | | 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")}`; |
| | | |
| | | let codeUrl; |
| | | if (form.type === "qrcode") { |
| | | codeUrl = await QRCode.toDataURL(content, { |
| | | width: form.size, |
| | | margin: form.margin, |
| | | color: { |
| | | dark: form.foregroundColor, |
| | | light: form.backgroundColor, |
| | | }, |
| | | }); |
| | | } else { |
| | | const securityContent = generateSecurityCode(content); |
| | | codeUrl = await QRCode.toDataURL(securityContent, { |
| | | width: form.size, |
| | | margin: form.margin, |
| | | color: { |
| | | dark: form.foregroundColor, |
| | | light: form.backgroundColor, |
| | | }, |
| | | }); |
| | | } |
| | | |
| | | batchCodes.value.push({ |
| | | content, |
| | | url: codeUrl, |
| | | }); |
| | | } |
| | | const byteArray = new Uint8Array(byteNumbers) |
| | | |
| | | 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) |
| | | |
| | | ElMessage.success('æ¹éä¸è½½å®æï¼') |
| | | } catch (error) { |
| | | console.error('æ¹éä¸è½½å¤±è´¥:', error) |
| | | ElMessage.error('æ¹éä¸è½½å¤±è´¥ï¼è¯·é个ä¸è½½') |
| | | } |
| | | } |
| | | |
| | | // æ¸
空æ¹éçæç»æ |
| | | const clearBatchCodes = () => { |
| | | batchCodes.value = [] |
| | | } |
| | | ElMessage.success(`æ¹éçæå®æï¼å
±çæ ${batchForm.quantity} 个ç `); |
| | | batchDialogVisible.value = false; |
| | | } catch (error) { |
| | | console.error("æ¹éçæå¤±è´¥:", error); |
| | | ElMessage.error("æ¹éçæå¤±è´¥ï¼" + error.message); |
| | | } finally { |
| | | generating.value = false; |
| | | } |
| | | }; |
| | | |
| | | // æ´é²æ¹æ³ç»ç¶ç»ä»¶ |
| | | defineExpose({ |
| | | generateCode, |
| | | downloadCode, |
| | | resetForm, |
| | | form |
| | | }) |
| | | // ä¸è½½å个æ¹éçæçç |
| | | 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; |
| | | } |
| | | |
| | | try { |
| | | // 使ç¨JSZipæå
ä¸è½½ |
| | | 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); |
| | | for (let i = 0; i < byteCharacters.length; i++) { |
| | | byteNumbers[i] = byteCharacters.charCodeAt(i); |
| | | } |
| | | const byteArray = new Uint8Array(byteNumbers); |
| | | |
| | | 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); |
| | | |
| | | ElMessage.success("æ¹éä¸è½½å®æï¼"); |
| | | } catch (error) { |
| | | console.error("æ¹éä¸è½½å¤±è´¥:", error); |
| | | ElMessage.error("æ¹éä¸è½½å¤±è´¥ï¼è¯·é个ä¸è½½"); |
| | | } |
| | | }; |
| | | |
| | | // æ¸
空æ¹éçæç»æ |
| | | const clearBatchCodes = () => { |
| | | batchCodes.value = []; |
| | | }; |
| | | |
| | | // æ´é²æ¹æ³ç»ç¶ç»ä»¶ |
| | | defineExpose({ |
| | | generateCode, |
| | | downloadCode, |
| | | resetForm, |
| | | form, |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .qr-code-generator { |
| | | padding: 20px; |
| | | } |
| | | .qr-code-generator { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .qr-form { |
| | | background: #f8f9fa; |
| | | padding: 20px; |
| | | border-radius: 8px; |
| | | margin-bottom: 20px; |
| | | } |
| | | .qr-form { |
| | | background: #f8f9fa; |
| | | padding: 20px; |
| | | border-radius: 8px; |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .code-display { |
| | | margin-top: 30px; |
| | | } |
| | | .code-display { |
| | | margin-top: 30px; |
| | | } |
| | | |
| | | .code-container { |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: flex-start; |
| | | gap: 40px; |
| | | margin: 20px 0; |
| | | } |
| | | |
| | | .code-image img { |
| | | border: 2px solid #e0e0e0; |
| | | border-radius: 8px; |
| | | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); |
| | | } |
| | | |
| | | .code-info { |
| | | text-align: left; |
| | | min-width: 200px; |
| | | } |
| | | |
| | | .code-info p { |
| | | margin: 8px 0; |
| | | color: #666; |
| | | } |
| | | |
| | | .code-actions { |
| | | text-align: center; |
| | | margin: 20px 0; |
| | | } |
| | | |
| | | .code-actions .el-button { |
| | | margin: 0 10px; |
| | | } |
| | | |
| | | .batch-results { |
| | | margin-top: 30px; |
| | | } |
| | | |
| | | .batch-grid { |
| | | display: grid; |
| | | grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); |
| | | gap: 20px; |
| | | margin: 20px 0; |
| | | } |
| | | |
| | | .batch-item { |
| | | text-align: center; |
| | | padding: 15px; |
| | | border: 1px solid #e0e0e0; |
| | | border-radius: 8px; |
| | | background: #fff; |
| | | } |
| | | |
| | | .batch-item img { |
| | | width: 100px; |
| | | height: 100px; |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .batch-content { |
| | | font-size: 12px; |
| | | color: #666; |
| | | margin: 10px 0; |
| | | word-break: break-all; |
| | | } |
| | | |
| | | .batch-actions { |
| | | text-align: center; |
| | | margin: 20px 0; |
| | | } |
| | | |
| | | .batch-actions .el-button { |
| | | margin: 0 10px; |
| | | } |
| | | |
| | | @media (max-width: 768px) { |
| | | .code-container { |
| | | flex-direction: column; |
| | | align-items: center; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: flex-start; |
| | | gap: 40px; |
| | | margin: 20px 0; |
| | | } |
| | | |
| | | |
| | | .code-image img { |
| | | border: 2px solid #e0e0e0; |
| | | border-radius: 8px; |
| | | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); |
| | | } |
| | | |
| | | .code-info { |
| | | text-align: left; |
| | | min-width: 200px; |
| | | } |
| | | |
| | | .code-info p { |
| | | margin: 8px 0; |
| | | color: #666; |
| | | } |
| | | |
| | | .code-actions { |
| | | text-align: center; |
| | | margin: 20px 0; |
| | | } |
| | | |
| | | .code-actions .el-button { |
| | | margin: 0 10px; |
| | | } |
| | | |
| | | .batch-results { |
| | | margin-top: 30px; |
| | | } |
| | | |
| | | .batch-grid { |
| | | grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); |
| | | display: grid; |
| | | grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); |
| | | gap: 20px; |
| | | margin: 20px 0; |
| | | } |
| | | } |
| | | |
| | | .batch-item { |
| | | text-align: center; |
| | | padding: 15px; |
| | | border: 1px solid #e0e0e0; |
| | | border-radius: 8px; |
| | | background: #fff; |
| | | } |
| | | |
| | | .batch-item img { |
| | | width: 100px; |
| | | height: 100px; |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .batch-content { |
| | | font-size: 12px; |
| | | color: #666; |
| | | margin: 10px 0; |
| | | word-break: break-all; |
| | | } |
| | | |
| | | .batch-actions { |
| | | text-align: center; |
| | | margin: 20px 0; |
| | | } |
| | | |
| | | .batch-actions .el-button { |
| | | margin: 0 10px; |
| | | } |
| | | |
| | | @media (max-width: 768px) { |
| | | .code-container { |
| | | flex-direction: column; |
| | | align-items: center; |
| | | } |
| | | |
| | | .batch-grid { |
| | | grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); |
| | | } |
| | | } |
| | | </style> |
| | |
| | | proxy.$refs.modelFormRef.validate((valid) => { |
| | | if (valid) { |
| | | let _modelForm = { ...modelForm.value }; |
| | | |
| | | |
| | | if(_modelForm.otherModel){ |
| | | _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" |
| | | type="date" |
| | | placeholder="éæ©æ¥æ" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | style="margin-right: 10px;" |
| | | @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" /> |
| | | <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" |
| | | 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" /> |
| | | </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()" |
| | | :key="option.value" |
| | | :label="option.label" |
| | | :value="option.value" |
| | | /> |
| | | <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" /> |
| | | </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()" |
| | | :key="option.value" |
| | | :label="option.label" |
| | | :value="option.value" |
| | | /> |
| | | <el-option v-for="option in getTypeOptions()" |
| | | :key="option.value" |
| | | :label="option.label" |
| | | :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" |
| | | type="daterange" |
| | | range-separator="è³" |
| | | start-placeholder="å¼å§æ¥æ" |
| | | end-placeholder="ç»ææ¥æ" |
| | | style="width: 100%" |
| | | @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="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" /> |
| | | </el-form-item> |
| | | |
| | | <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')" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <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')" |
| | | /> |
| | | </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="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="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')" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <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')" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="å¼¹æ§ä¸ç" prop="flexibleStart" v-if="currentType === 'worktime'"> |
| | | <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')" /> |
| | | </el-form-item> |
| | | <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')" /> |
| | | </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> |
| | | <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')" /> |
| | | </el-form-item> |
| | | <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')" /> |
| | | </el-form-item> |
| | | <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-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-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 page = { |
| | | // å¼¹çªç¸å
³ |
| | | 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: '', |
| | | dateRange: [], |
| | | startDate: '', |
| | | endDate: '', |
| | | days: 0, |
| | | employeeType: '', |
| | | workYears: '', |
| | | annualDays: 0, |
| | | maxCarryOver: 0, |
| | | startTime: '', // å çå¼å§æ¶é´ |
| | | endTime: '', // å çç»ææ¶é´ |
| | | workStartTime: '', // ä¸çæ¶é´ |
| | | workEndTime: '', // ä¸çæ¶é´ |
| | | rate: 1.5, |
| | | flexibleStart: false, |
| | | flexibleMinutes: 30, |
| | | 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: [{ |
| | | required: true, |
| | | message: 'è¯·éæ©å¼å§æ¶é´', |
| | | trigger: 'change', |
| | | validator: (rule, value, callback) => { |
| | | if (!value) { |
| | | callback(new Error('è¯·éæ©å¼å§æ¶é´')) |
| | | } else { |
| | | callback() |
| | | } |
| | | } |
| | | }], |
| | | endTime: [{ |
| | | required: true, |
| | | message: 'è¯·éæ©ç»ææ¶é´', |
| | | trigger: 'change', |
| | | validator: (rule, value, callback) => { |
| | | if (!value) { |
| | | callback(new Error('è¯·éæ©ç»ææ¶é´')) |
| | | } else { |
| | | callback() |
| | | } |
| | | } |
| | | }], |
| | | workStartTime: [{ |
| | | required: true, |
| | | message: 'è¯·éæ©ä¸çæ¶é´', |
| | | trigger: 'change', |
| | | validator: (rule, value, callback) => { |
| | | if (!value) { |
| | | callback(new Error('è¯·éæ©ä¸çæ¶é´')) |
| | | } else { |
| | | callback() |
| | | } |
| | | } |
| | | }], |
| | | workEndTime: [{ |
| | | required: true, |
| | | message: 'è¯·éæ©ä¸çæ¶é´', |
| | | trigger: 'change', |
| | | validator: (rule, value, callback) => { |
| | | if (!value) { |
| | | callback(new Error('è¯·éæ©ä¸çæ¶é´')) |
| | | } else { |
| | | callback() |
| | | } |
| | | } |
| | | }], |
| | | rate: [{ required: true, message: '请è¾å
¥åç', trigger: 'blur' }] |
| | | } |
| | | // å·¥å
·å½æ° |
| | | 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' |
| | | } |
| | | |
| | | const getTypeLabel = (type) => { |
| | | const labelMap = { |
| | | legal: 'æ³å®è忥', adjustment: 'è°ä¼æ¥', special: 'ç¹æ®åæ', company: 'å
¬å¸åæ', |
| | | weekday: '工使¥å ç', weekend: '卿«å ç', holiday: 'è忥å ç', night: 'æ·±å¤å ç', |
| | | regular: 'æ£å¼åå·¥', probation: 'è¯ç¨æåå·¥', intern: 'å®ä¹ ç' |
| | | } |
| | | return labelMap[type] || type |
| | | } |
| | | |
| | | // æå¡è®°å½ç¸å
³å·¥å
·å½æ° |
| | | const getAttendanceTagType = (status) => { |
| | | const tagMap = { |
| | | normal: 'success', |
| | | late: 'warning', |
| | | early: 'warning', |
| | | absent: 'danger' |
| | | } |
| | | return tagMap[status] || 'info' |
| | | } |
| | | |
| | | const getAttendanceStatusLabel = (status) => { |
| | | const labelMap = { |
| | | normal: 'æ£å¸¸', |
| | | late: 'è¿å°', |
| | | early: 'æ©é', |
| | | absent: '缺å¤' |
| | | } |
| | | return labelMap[status] || status |
| | | } |
| | | |
| | | const getTypeOptions = () => { |
| | | if (currentType.value === 'holiday') { |
| | | return [ |
| | | { 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') { |
| | | return [ |
| | | { label: 'æ£å¼åå·¥', value: 'regular' }, |
| | | { label: 'è¯ç¨æåå·¥', value: 'probation' }, |
| | | { label: 'å®ä¹ ç', value: 'intern' } |
| | | ] |
| | | } |
| | | 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 (isNaN(start.getTime()) || isNaN(end.getTime())) { |
| | | console.warn('æ æçæ¥ææ ¼å¼') |
| | | return |
| | | } |
| | | |
| | | const diffTime = Math.abs(end - start) |
| | | const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)) + 1 |
| | | form.days = diffDays |
| | | } |
| | | } catch (error) { |
| | | console.error('计ç®å¤©æ°å¤±è´¥:', error) |
| | | } |
| | | } |
| | | |
| | | // éªè¯æ¶é´æ ¼å¼ |
| | | // const validateTime = (time) => { |
| | | // if (!time) return '' |
| | | // if (typeof time === 'string') return time |
| | | // if (time instanceof Date) { |
| | | // return time.toTimeString().slice(0, 5) |
| | | // } |
| | | // return '' |
| | | // } |
| | | |
| | | // éªè¯æ¶é´å段 |
| | | const validateTimeField = (fieldName) => { |
| | | try { |
| | | 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}` |
| | | } |
| | | } catch (error) { |
| | | console.error(`éªè¯æ¶é´å段 ${fieldName} 失败:`, error) |
| | | form[fieldName] = '' |
| | | } |
| | | } |
| | | |
| | | // æå¼å¼¹çª |
| | | const openDialog = (type, action, row = null) => { |
| | | try { |
| | | 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) |
| | | } |
| | | |
| | | dialogVisible.value = true |
| | | } catch (error) { |
| | | console.error('æå¼å¼¹çªå¤±è´¥:', error) |
| | | ElMessage.error('æå¼å¼¹çªå¤±è´¥ï¼è¯·éè¯') |
| | | } |
| | | } |
| | | |
| | | const getTypeName = (type) => { |
| | | const nameMap = { |
| | | holiday: 'åæ', |
| | | annual: 'å¹´åè§å', |
| | | overtime: 'å çè§å', |
| | | worktime: 'æ¶é´æ®µ' |
| | | } |
| | | return nameMap[type] || '' |
| | | } |
| | | |
| | | const resetForm = () => { |
| | | Object.assign(form, { |
| | | name: '', |
| | | type: '', |
| | | // è¡¨åæ°æ® |
| | | const form = reactive({ |
| | | 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') { |
| | | Object.assign(form, { |
| | | name: row.name, |
| | | type: row.type, |
| | | dateRange: [new Date(row.startDate), new Date(row.endDate)], |
| | | startDate: row.startDate, |
| | | endDate: row.endDate, |
| | | days: row.days, |
| | | 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') { |
| | | Object.assign(form, { |
| | | name: row.name, |
| | | type: row.type, |
| | | startTime: row.startTime || '', |
| | | endTime: row.endTime || '', |
| | | rate: row.rate, |
| | | status: row.status |
| | | }) |
| | | } else if (currentType.value === 'worktime') { |
| | | Object.assign(form, { |
| | | name: row.name, |
| | | workStartTime: row.startTime || '', |
| | | workEndTime: row.endTime || '', |
| | | flexibleStart: row.flexibleStart, |
| | | flexibleMinutes: row.flexibleMinutes, |
| | | status: row.status |
| | | }) |
| | | } |
| | | } |
| | | // 表åéªè¯è§å |
| | | 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: [ |
| | | { |
| | | required: true, |
| | | message: "è¯·éæ©å¼å§æ¶é´", |
| | | trigger: "change", |
| | | validator: (rule, value, callback) => { |
| | | if (!value) { |
| | | callback(new Error("è¯·éæ©å¼å§æ¶é´")); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, |
| | | }, |
| | | ], |
| | | endTime: [ |
| | | { |
| | | required: true, |
| | | message: "è¯·éæ©ç»ææ¶é´", |
| | | trigger: "change", |
| | | validator: (rule, value, callback) => { |
| | | if (!value) { |
| | | callback(new Error("è¯·éæ©ç»ææ¶é´")); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, |
| | | }, |
| | | ], |
| | | workStartTime: [ |
| | | { |
| | | required: true, |
| | | message: "è¯·éæ©ä¸çæ¶é´", |
| | | trigger: "change", |
| | | validator: (rule, value, callback) => { |
| | | if (!value) { |
| | | callback(new Error("è¯·éæ©ä¸çæ¶é´")); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, |
| | | }, |
| | | ], |
| | | workEndTime: [ |
| | | { |
| | | required: true, |
| | | message: "è¯·éæ©ä¸çæ¶é´", |
| | | trigger: "change", |
| | | validator: (rule, value, callback) => { |
| | | if (!value) { |
| | | callback(new Error("è¯·éæ©ä¸çæ¶é´")); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, |
| | | }, |
| | | ], |
| | | rate: [{ required: true, message: "请è¾å
¥åç", trigger: "blur" }], |
| | | }; |
| | | // å·¥å
·å½æ° |
| | | 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"; |
| | | }; |
| | | |
| | | // æäº¤è¡¨å |
| | | const submitForm = async () => { |
| | | try { |
| | | if (!formRef.value) { |
| | | ElMessage.error('表åå¼ç¨ä¸åå¨') |
| | | return |
| | | const getTypeLabel = type => { |
| | | const labelMap = { |
| | | legal: "æ³å®è忥", |
| | | adjustment: "è°ä¼æ¥", |
| | | special: "ç¹æ®åæ", |
| | | company: "å
¬å¸åæ", |
| | | weekday: "工使¥å ç", |
| | | weekend: "卿«å ç", |
| | | holiday: "è忥å ç", |
| | | night: "æ·±å¤å ç", |
| | | regular: "æ£å¼åå·¥", |
| | | probation: "è¯ç¨æåå·¥", |
| | | intern: "å®ä¹ ç", |
| | | }; |
| | | return labelMap[type] || type; |
| | | }; |
| | | |
| | | // æå¡è®°å½ç¸å
³å·¥å
·å½æ° |
| | | const getAttendanceTagType = status => { |
| | | const tagMap = { |
| | | normal: "success", |
| | | late: "warning", |
| | | early: "warning", |
| | | absent: "danger", |
| | | }; |
| | | return tagMap[status] || "info"; |
| | | }; |
| | | |
| | | const getAttendanceStatusLabel = status => { |
| | | const labelMap = { |
| | | normal: "æ£å¸¸", |
| | | late: "è¿å°", |
| | | early: "æ©é", |
| | | absent: "缺å¤", |
| | | }; |
| | | return labelMap[status] || status; |
| | | }; |
| | | |
| | | const getTypeOptions = () => { |
| | | if (currentType.value === "holiday") { |
| | | return [ |
| | | { 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") { |
| | | return [ |
| | | { label: "æ£å¼åå·¥", value: "regular" }, |
| | | { label: "è¯ç¨æåå·¥", value: "probation" }, |
| | | { label: "å®ä¹ ç", value: "intern" }, |
| | | ]; |
| | | } |
| | | return []; |
| | | }; |
| | | |
| | | await formRef.value.validate() |
| | | // 计ç®åæå¤©æ° |
| | | 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 (currentAction.value === 'add') { |
| | | addItem() |
| | | } else if (currentAction.value === 'edit') { |
| | | editItem() |
| | | } |
| | | |
| | | dialogVisible.value = false |
| | | ElMessage.success('æä½æå') |
| | | } catch (error) { |
| | | console.error('表åéªè¯å¤±è´¥:', error) |
| | | ElMessage.error('表åéªè¯å¤±è´¥ï¼è¯·æ£æ¥è¾å
¥') |
| | | } |
| | | } |
| | | |
| | | const addItem = () => { |
| | | |
| | | 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 => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("æ·»å æå"); |
| | | // dialogVisible.value = false; |
| | | getHolidaySettingsList() |
| | | } |
| | | }).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 => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("æ·»å æå"); |
| | | // dialogVisible.value = false; |
| | | getAnnualLeaveSettingList() |
| | | } |
| | | }).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 || '', |
| | | rate: form.rate, |
| | | status: form.status |
| | | } |
| | | addOvertimeSetting(params).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("æ·»å æå"); |
| | | // dialogVisible.value = false; |
| | | getOvertimeSettingList() |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | // newItem.startTime = form.startTime || '' |
| | | // newItem.endTime = form.endTime || '' |
| | | // overtimeData.value.push(newItem) |
| | | } else if (currentType.value === 'worktime') { |
| | | const params = { |
| | | name: form.name, |
| | | startTime: form.workStartTime || '', |
| | | endTime: form.workEndTime || '', |
| | | flexibleStart: form.flexibleStart, |
| | | flexibleMinutes: form.flexibleMinutes, |
| | | status: form.status |
| | | } |
| | | addWorkingHoursSetting(params).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("æ·»å æå"); |
| | | getWorkingHoursSettingList() |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | // newItem.startTime = form.workStartTime || '' |
| | | // newItem.endTime = form.workEndTime || '' |
| | | // worktimeData.value.push(newItem) |
| | | } |
| | | } |
| | | |
| | | const editItem = () => { |
| | | let dataArray |
| | | let index |
| | | |
| | | 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], |
| | | days: form.days, |
| | | status: form.status |
| | | } |
| | | updateHolidaySettings(params).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("æ´æ°æå"); |
| | | // dialogVisible.value = false; |
| | | getHolidaySettingsList() |
| | | } |
| | | }).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 => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("æ´æ°æå"); |
| | | getAnnualLeaveSettingList() |
| | | } |
| | | }).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 || '', |
| | | rate: form.rate, |
| | | status: form.status |
| | | } |
| | | updateOvertimeSetting(params).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("æ´æ°æå"); |
| | | getOvertimeSettingList() |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | |
| | | // dataArray = overtimeData.value |
| | | // index = dataArray.findIndex(item => item.id === currentEditId.value) |
| | | // if (index > -1) { |
| | | // dataArray[index] = { |
| | | // ...dataArray[index], |
| | | // name: form.name, |
| | | // type: form.type, |
| | | // startTime: form.startTime || '', |
| | | // endTime: form.endTime || '', |
| | | // rate: form.rate, |
| | | // status: form.status |
| | | // } |
| | | // } |
| | | } else if (currentType.value === 'worktime') { |
| | | const params = { |
| | | id: currentEditId.value, |
| | | name: form.name, |
| | | startTime: form.workStartTime || '', |
| | | endTime: form.workEndTime || '', |
| | | flexibleStart: form.flexibleStart, |
| | | flexibleMinutes: form.flexibleMinutes, |
| | | status: form.status |
| | | } |
| | | updateWorkingHoursSetting(params).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("æ´æ°æå"); |
| | | getWorkingHoursSettingList() |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | // dataArray = worktimeData.value |
| | | // index = dataArray.findIndex(item => item.id === currentEditId.value) |
| | | // if (index > -1) { |
| | | // dataArray[index] = { |
| | | // ...dataArray[index], |
| | | // name: form.name, |
| | | // startTime: form.workStartTime || '', |
| | | // endTime: form.workEndTime || '', |
| | | // flexibleStart: form.flexibleStart, |
| | | // flexibleMinutes: form.flexibleMinutes, |
| | | // status: form.status |
| | | // } |
| | | // } |
| | | } |
| | | } |
| | | |
| | | // æå¡è®°å½è¿æ»¤åè½ |
| | | const filterAttendanceData = () => { |
| | | let filtered = attendanceData.value |
| | | |
| | | // ææ¥æè¿æ»¤ |
| | | if (attendanceDate.value) { |
| | | filtered = filtered.filter(item => item.date === attendanceDate.value) |
| | | } |
| | | |
| | | // æç¶æè¿æ»¤ |
| | | if (attendanceStatus.value) { |
| | | filtered = filtered.filter(item => item.status === attendanceStatus.value) |
| | | } |
| | | |
| | | filteredAttendanceData.value = filtered |
| | | } |
| | | |
| | | // å¯¼åºæå¡è®°å½ |
| | | const exportAttendance = () => { |
| | | 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: '' |
| | | }, |
| | | { |
| | | id: 2, |
| | | 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: '' |
| | | }, |
| | | { |
| | | id: 4, |
| | | 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: 'å ç' |
| | | }, |
| | | { |
| | | id: 6, |
| | | 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: '' |
| | | }, |
| | | { |
| | | id: 8, |
| | | 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: '' |
| | | }, |
| | | { |
| | | id: 10, |
| | | 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: '' |
| | | }, |
| | | { |
| | | id: 12, |
| | | 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: '' |
| | | }, |
| | | { |
| | | id: 14, |
| | | 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: '' |
| | | }, |
| | | { |
| | | id: 16, |
| | | 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: '' |
| | | }, |
| | | { |
| | | id: 18, |
| | | 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 |
| | | } |
| | | |
| | | // å é¤é¡¹ç® |
| | | const deleteItem = (type, row) => { |
| | | ElMessageBox.confirm('ç¡®å®è¦å é¤è¿ä¸ªé¡¹ç®åï¼', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | }).then(() => { |
| | | let ids = []; |
| | | let dataArray |
| | | if (type === 'holiday') { |
| | | ids.push(row.id) |
| | | delHolidaySettings(ids).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("å 餿å"); |
| | | ids = [] |
| | | getHolidaySettingsList() |
| | | if (isNaN(start.getTime()) || isNaN(end.getTime())) { |
| | | console.warn("æ æçæ¥ææ ¼å¼"); |
| | | return; |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | |
| | | const diffTime = Math.abs(end - start); |
| | | const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)) + 1; |
| | | form.days = diffDays; |
| | | } |
| | | } catch (error) { |
| | | console.error("计ç®å¤©æ°å¤±è´¥:", error); |
| | | } |
| | | else if (type === 'annual') { |
| | | ids.push(row.id) |
| | | delAnnualLeaveSetting(ids).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("å 餿å"); |
| | | ids = [] |
| | | getAnnualLeaveSettingList() |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | }; |
| | | |
| | | // éªè¯æ¶é´æ ¼å¼ |
| | | // const validateTime = (time) => { |
| | | // if (!time) return '' |
| | | // if (typeof time === 'string') return time |
| | | // if (time instanceof Date) { |
| | | // return time.toTimeString().slice(0, 5) |
| | | // } |
| | | // return '' |
| | | // } |
| | | |
| | | // éªè¯æ¶é´å段 |
| | | const validateTimeField = fieldName => { |
| | | try { |
| | | 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}`; |
| | | } |
| | | } catch (error) { |
| | | console.error(`éªè¯æ¶é´å段 ${fieldName} 失败:`, error); |
| | | form[fieldName] = ""; |
| | | } |
| | | else if (type === 'overtime') { |
| | | ids.push(row.id) |
| | | delOvertimeSetting(ids).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("å 餿å"); |
| | | ids = [] |
| | | getOvertimeSettingList() |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | }; |
| | | |
| | | // æå¼å¼¹çª |
| | | const openDialog = (type, action, row = null) => { |
| | | try { |
| | | 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); |
| | | } |
| | | |
| | | dialogVisible.value = true; |
| | | } catch (error) { |
| | | console.error("æå¼å¼¹çªå¤±è´¥:", error); |
| | | ElMessage.error("æå¼å¼¹çªå¤±è´¥ï¼è¯·éè¯"); |
| | | } |
| | | else if (type === 'worktime') { |
| | | ids.push(row.id) |
| | | delWorkingHoursSetting(ids).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("å 餿å"); |
| | | ids = [] |
| | | getWorkingHoursSettingList() |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | }; |
| | | |
| | | const getTypeName = type => { |
| | | const nameMap = { |
| | | holiday: "åæ", |
| | | annual: "å¹´åè§å", |
| | | overtime: "å çè§å", |
| | | worktime: "æ¶é´æ®µ", |
| | | }; |
| | | return nameMap[type] || ""; |
| | | }; |
| | | |
| | | const resetForm = () => { |
| | | Object.assign(form, { |
| | | name: "", |
| | | type: "", |
| | | dateRange: [], |
| | | startDate: "", |
| | | endDate: "", |
| | | days: 0, |
| | | employeeType: "", |
| | | workYears: "", |
| | | annualDays: 0, |
| | | maxCarryOver: 0, |
| | | startTime: "", |
| | | endTime: "", |
| | | workStartTime: "", |
| | | workEndTime: "", |
| | | rate: 1.5, |
| | | flexibleStart: false, |
| | | flexibleMinutes: 30, |
| | | status: "active", |
| | | }); |
| | | }; |
| | | |
| | | const fillForm = row => { |
| | | if (currentType.value === "holiday") { |
| | | Object.assign(form, { |
| | | name: row.name, |
| | | type: row.type, |
| | | dateRange: [new Date(row.startDate), new Date(row.endDate)], |
| | | startDate: row.startDate, |
| | | endDate: row.endDate, |
| | | days: row.days, |
| | | 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") { |
| | | Object.assign(form, { |
| | | name: row.name, |
| | | type: row.type, |
| | | startTime: row.startTime || "", |
| | | endTime: row.endTime || "", |
| | | rate: row.rate, |
| | | status: row.status, |
| | | }); |
| | | } else if (currentType.value === "worktime") { |
| | | Object.assign(form, { |
| | | name: row.name, |
| | | workStartTime: row.startTime || "", |
| | | workEndTime: row.endTime || "", |
| | | flexibleStart: row.flexibleStart, |
| | | flexibleMinutes: row.flexibleMinutes, |
| | | status: row.status, |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | // æäº¤è¡¨å |
| | | const submitForm = async () => { |
| | | try { |
| | | if (!formRef.value) { |
| | | ElMessage.error("表åå¼ç¨ä¸åå¨"); |
| | | return; |
| | | } |
| | | |
| | | await formRef.value.validate(); |
| | | |
| | | if (currentAction.value === "add") { |
| | | addItem(); |
| | | } else if (currentAction.value === "edit") { |
| | | editItem(); |
| | | } |
| | | |
| | | dialogVisible.value = false; |
| | | ElMessage.success("æä½æå"); |
| | | } catch (error) { |
| | | console.error("表åéªè¯å¤±è´¥:", error); |
| | | ElMessage.error("表åéªè¯å¤±è´¥ï¼è¯·æ£æ¥è¾å
¥"); |
| | | } |
| | | }; |
| | | |
| | | const addItem = () => { |
| | | 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 => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("æ·»å æå"); |
| | | // dialogVisible.value = false; |
| | | getHolidaySettingsList(); |
| | | } |
| | | }) |
| | | .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 => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("æ·»å æå"); |
| | | // dialogVisible.value = false; |
| | | getAnnualLeaveSettingList(); |
| | | } |
| | | }) |
| | | .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 || "", |
| | | rate: form.rate, |
| | | status: form.status, |
| | | }; |
| | | addOvertimeSetting(params) |
| | | .then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("æ·»å æå"); |
| | | // dialogVisible.value = false; |
| | | getOvertimeSettingList(); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | // newItem.startTime = form.startTime || '' |
| | | // newItem.endTime = form.endTime || '' |
| | | // overtimeData.value.push(newItem) |
| | | } else if (currentType.value === "worktime") { |
| | | const params = { |
| | | name: form.name, |
| | | startTime: form.workStartTime || "", |
| | | endTime: form.workEndTime || "", |
| | | flexibleStart: form.flexibleStart, |
| | | flexibleMinutes: form.flexibleMinutes, |
| | | status: form.status, |
| | | }; |
| | | addWorkingHoursSetting(params) |
| | | .then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("æ·»å æå"); |
| | | getWorkingHoursSettingList(); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | // newItem.startTime = form.workStartTime || '' |
| | | // newItem.endTime = form.workEndTime || '' |
| | | // worktimeData.value.push(newItem) |
| | | } |
| | | }; |
| | | |
| | | const editItem = () => { |
| | | let dataArray; |
| | | let index; |
| | | |
| | | 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], |
| | | days: form.days, |
| | | status: form.status, |
| | | }; |
| | | updateHolidaySettings(params) |
| | | .then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("æ´æ°æå"); |
| | | // dialogVisible.value = false; |
| | | getHolidaySettingsList(); |
| | | } |
| | | }) |
| | | .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 => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("æ´æ°æå"); |
| | | getAnnualLeaveSettingList(); |
| | | } |
| | | }) |
| | | .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 || "", |
| | | rate: form.rate, |
| | | status: form.status, |
| | | }; |
| | | updateOvertimeSetting(params) |
| | | .then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("æ´æ°æå"); |
| | | getOvertimeSettingList(); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | |
| | | // dataArray = overtimeData.value |
| | | // index = dataArray.findIndex(item => item.id === currentEditId.value) |
| | | // if (index > -1) { |
| | | // dataArray[index] = { |
| | | // ...dataArray[index], |
| | | // name: form.name, |
| | | // type: form.type, |
| | | // startTime: form.startTime || '', |
| | | // endTime: form.endTime || '', |
| | | // rate: form.rate, |
| | | // status: form.status |
| | | // } |
| | | // } |
| | | } else if (currentType.value === "worktime") { |
| | | const params = { |
| | | id: currentEditId.value, |
| | | name: form.name, |
| | | startTime: form.workStartTime || "", |
| | | endTime: form.workEndTime || "", |
| | | flexibleStart: form.flexibleStart, |
| | | flexibleMinutes: form.flexibleMinutes, |
| | | status: form.status, |
| | | }; |
| | | updateWorkingHoursSetting(params) |
| | | .then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("æ´æ°æå"); |
| | | getWorkingHoursSettingList(); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | // dataArray = worktimeData.value |
| | | // index = dataArray.findIndex(item => item.id === currentEditId.value) |
| | | // if (index > -1) { |
| | | // dataArray[index] = { |
| | | // ...dataArray[index], |
| | | // name: form.name, |
| | | // startTime: form.workStartTime || '', |
| | | // endTime: form.workEndTime || '', |
| | | // flexibleStart: form.flexibleStart, |
| | | // flexibleMinutes: form.flexibleMinutes, |
| | | // status: form.status |
| | | // } |
| | | // } |
| | | } |
| | | }; |
| | | |
| | | // æå¡è®°å½è¿æ»¤åè½ |
| | | const filterAttendanceData = () => { |
| | | let filtered = attendanceData.value; |
| | | |
| | | // ææ¥æè¿æ»¤ |
| | | if (attendanceDate.value) { |
| | | filtered = filtered.filter(item => item.date === attendanceDate.value); |
| | | } |
| | | |
| | | // const index = dataArray.findIndex(item => item.id === row.id) |
| | | // if (index > -1) { |
| | | // dataArray.splice(index, 1) |
| | | // ElMessage.success('å 餿å') |
| | | // } |
| | | }) |
| | | } |
| | | // è·ååæè®¾ç½®å表 |
| | | const getHolidaySettingsList = () => { |
| | | // tableLoading.value = true; |
| | | listHolidaySettings({...page.value}) |
| | | .then(res => { |
| | | // tableLoading.value = false; |
| | | holidayData.value = res.data.records |
| | | page.total = res.data.total; |
| | | }).catch(err => { |
| | | // tableLoading.value = false; |
| | | }) |
| | | }; |
| | | // è·åå¹´åè§åå表 |
| | | const getAnnualLeaveSettingList = () => { |
| | | // æç¶æè¿æ»¤ |
| | | if (attendanceStatus.value) { |
| | | filtered = filtered.filter(item => item.status === attendanceStatus.value); |
| | | } |
| | | |
| | | listAnnualLeaveSettingList({...page.value}) |
| | | .then(res => { |
| | | // console.log(res.data) |
| | | annualData.value = res.data.records |
| | | page.total = res.data.total; |
| | | }).catch(err => { |
| | | }) |
| | | }; |
| | | // è·åå çè§åå表 |
| | | const getOvertimeSettingList = () => { |
| | | filteredAttendanceData.value = filtered; |
| | | }; |
| | | |
| | | listOvertimeSettingList({...page.value}) |
| | | .then(res => { |
| | | // console.log(res.data) |
| | | overtimeData.value = res.data.records |
| | | page.total = res.data.total; |
| | | }).catch(err => { |
| | | }) |
| | | }; |
| | | // è·å工使¶é´è§åå表 |
| | | const getWorkingHoursSettingList = () => { |
| | | // å¯¼åºæå¡è®°å½ |
| | | const exportAttendance = () => { |
| | | ElMessage.success("导åºåè½å¼åä¸..."); |
| | | }; |
| | | |
| | | listWorkingHoursSettingList({...page.value}) |
| | | .then(res => { |
| | | // console.log(res.data) |
| | | worktimeData.value = res.data.records |
| | | page.total = res.data.total; |
| | | }).catch(err => { |
| | | }) |
| | | }; |
| | | onMounted(() => { |
| | | getHolidaySettingsList() |
| | | getAnnualLeaveSettingList() |
| | | getOvertimeSettingList() |
| | | getWorkingHoursSettingList() |
| | | initAttendanceData() |
| | | console.log('èå¤ç®¡ç页é¢å è½½å®æ') |
| | | }) |
| | | // åå§åæå¡è®°å½åæ°æ® |
| | | 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: "", |
| | | }, |
| | | { |
| | | id: 2, |
| | | 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: "", |
| | | }, |
| | | { |
| | | id: 4, |
| | | 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: "å ç", |
| | | }, |
| | | { |
| | | id: 6, |
| | | 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: "", |
| | | }, |
| | | { |
| | | id: 8, |
| | | 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: "", |
| | | }, |
| | | { |
| | | id: 10, |
| | | 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: "", |
| | | }, |
| | | { |
| | | id: 12, |
| | | 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: "", |
| | | }, |
| | | { |
| | | id: 14, |
| | | 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: "", |
| | | }, |
| | | { |
| | | id: 16, |
| | | 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: "", |
| | | }, |
| | | { |
| | | id: 18, |
| | | employeeName: "æ¾å°çº¢", |
| | | department: "客æé¨", |
| | | date: "2025-09-11", |
| | | clockInTime: "09:02:00", |
| | | clockOutTime: "18:00:00", |
| | | workHours: "7.97h", |
| | | status: "normal", |
| | | location: "å
¬å¸æ»é¨", |
| | | remark: "", |
| | | }, |
| | | ]; |
| | | |
| | | onUnmounted(() => { |
| | | // æ¸
çå·¥ä½ |
| | | dialogVisible.value = false |
| | | currentType.value = '' |
| | | currentAction.value = '' |
| | | currentEditId.value = '' |
| | | }) |
| | | attendanceData.value = mockData; |
| | | filteredAttendanceData.value = mockData; |
| | | }; |
| | | |
| | | // å é¤é¡¹ç® |
| | | const deleteItem = (type, row) => { |
| | | ElMessageBox.confirm("ç¡®å®è¦å é¤è¿ä¸ªé¡¹ç®åï¼", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).then(() => { |
| | | let ids = []; |
| | | let dataArray; |
| | | if (type === "holiday") { |
| | | ids.push(row.id); |
| | | delHolidaySettings(ids) |
| | | .then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("å 餿å"); |
| | | ids = []; |
| | | getHolidaySettingsList(); |
| | | } |
| | | }) |
| | | .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(); |
| | | } |
| | | }) |
| | | .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(); |
| | | } |
| | | }) |
| | | .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(); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | } |
| | | |
| | | // const index = dataArray.findIndex(item => item.id === row.id) |
| | | // if (index > -1) { |
| | | // dataArray.splice(index, 1) |
| | | // ElMessage.success('å 餿å') |
| | | // } |
| | | }); |
| | | }; |
| | | // è·ååæè®¾ç½®å表 |
| | | const getHolidaySettingsList = () => { |
| | | // tableLoading.value = true; |
| | | listHolidaySettings({ ...page.value }) |
| | | .then(res => { |
| | | // tableLoading.value = false; |
| | | holidayData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }) |
| | | .catch(err => { |
| | | // tableLoading.value = false; |
| | | }); |
| | | }; |
| | | // è·åå¹´åè§åå表 |
| | | const getAnnualLeaveSettingList = () => { |
| | | listAnnualLeaveSettingList({ ...page.value }) |
| | | .then(res => { |
| | | // console.log(res.data) |
| | | annualData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }) |
| | | .catch(err => {}); |
| | | }; |
| | | // è·åå çè§åå表 |
| | | const getOvertimeSettingList = () => { |
| | | listOvertimeSettingList({ ...page.value }) |
| | | .then(res => { |
| | | // console.log(res.data) |
| | | overtimeData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }) |
| | | .catch(err => {}); |
| | | }; |
| | | // è·å工使¶é´è§åå表 |
| | | const getWorkingHoursSettingList = () => { |
| | | listWorkingHoursSettingList({ ...page.value }) |
| | | .then(res => { |
| | | // console.log(res.data) |
| | | worktimeData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }) |
| | | .catch(err => {}); |
| | | }; |
| | | onMounted(() => { |
| | | getHolidaySettingsList(); |
| | | getAnnualLeaveSettingList(); |
| | | getOvertimeSettingList(); |
| | | getWorkingHoursSettingList(); |
| | | initAttendanceData(); |
| | | console.log("èå¤ç®¡ç页é¢å è½½å®æ"); |
| | | }); |
| | | |
| | | onUnmounted(() => { |
| | | // æ¸
çå·¥ä½ |
| | | dialogVisible.value = false; |
| | | currentType.value = ""; |
| | | currentAction.value = ""; |
| | | currentEditId.value = ""; |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .app-container { |
| | | padding: 20px; |
| | | } |
| | | .app-container { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .tab-content { |
| | | padding: 20px 0; |
| | | } |
| | | .tab-content { |
| | | padding: 20px 0; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | text-align: right; |
| | | } |
| | | .dialog-footer { |
| | | text-align: right; |
| | | } |
| | | |
| | | :deep(.el-tabs__content) { |
| | | padding: 20px; |
| | | } |
| | | :deep(.el-tabs__content) { |
| | | padding: 20px; |
| | | } |
| | | |
| | | :deep(.el-form-item) { |
| | | margin-bottom: 20px; |
| | | } |
| | | :deep(.el-form-item) { |
| | | margin-bottom: 20px; |
| | | } |
| | | </style> |
| | |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title">ç¥è¯æ é¢ï¼</span> |
| | | <el-input |
| | | v-model="searchForm.title" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥ç¥è¯æ é¢æç´¢" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | /> |
| | | <el-input v-model="searchForm.title" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥ç¥è¯æ é¢æç´¢" |
| | | @change="handleQuery" |
| | | clearable |
| | | :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" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | :total="page.total" |
| | | ></PIMTable> |
| | | <PIMTable rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | :total="page.total"></PIMTable> |
| | | </div> |
| | | |
| | | <!-- æ°å¢/ç¼è¾ç¥è¯å¼¹çª --> |
| | | <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"> |
| | | <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"> |
| | | <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" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请æè¿°éå°çé®é¢" |
| | | /> |
| | | <el-form-item label="é®é¢æè¿°" |
| | | prop="problem"> |
| | | <el-input v-model="form.problem" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请æè¿°éå°çé®é¢" /> |
| | | </el-form-item> |
| | | <el-form-item label="è§£å³æ¹æ¡" prop="solution"> |
| | | <el-input |
| | | v-model="form.solution" |
| | | type="textarea" |
| | | :rows="4" |
| | | placeholder="è¯·è¯¦ç»æè¿°è§£å³æ¹æ¡" |
| | | /> |
| | | <el-form-item label="è§£å³æ¹æ¡" |
| | | prop="solution"> |
| | | <el-input v-model="form.solution" |
| | | type="textarea" |
| | | :rows="4" |
| | | placeholder="è¯·è¯¦ç»æè¿°è§£å³æ¹æ¡" /> |
| | | </el-form-item> |
| | | <el-form-item label="å
³é®è¦ç¹" prop="keyPoints"> |
| | | <el-input |
| | | v-model="form.keyPoints" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥å
³é®è¦ç¹ï¼ç¨éå·åé" |
| | | /> |
| | | <el-form-item label="å
³é®è¦ç¹" |
| | | prop="keyPoints"> |
| | | <el-input v-model="form.keyPoints" |
| | | type="textarea" |
| | | :rows="3" |
| | | 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" |
| | | title="ç¥è¯è¯¦æ
" |
| | | width="900px" |
| | | :close-on-click-modal="false" |
| | | > |
| | | <el-dialog v-model="viewDialogVisible" |
| | | title="ç¥è¯è¯¦æ
" |
| | | width="900px" |
| | | :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(',')" |
| | | :key="index" |
| | | type="success" |
| | | style="margin-right: 8px; margin-bottom: 8px;" |
| | | > |
| | | <el-tag v-for="(point, index) in currentKnowledge.keyPoints.split(',')" |
| | | :key="index" |
| | | type="success" |
| | | 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> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | 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 { Search } from "@element-plus/icons-vue"; |
| | | 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"; |
| | | |
| | | // 表åéªè¯è§å |
| | | const rules = { |
| | | title: [ |
| | | { required: true, message: "请è¾å
¥ç¥è¯æ é¢", trigger: "blur" } |
| | | ], |
| | | type: [ |
| | | { required: true, message: "è¯·éæ©ç¥è¯ç±»å", trigger: "change" } |
| | | ], |
| | | problem: [ |
| | | { required: true, message: "请æè¿°éå°çé®é¢", trigger: "blur" } |
| | | ], |
| | | solution: [ |
| | | { required: true, message: "è¯·è¯¦ç»æè¿°è§£å³æ¹æ¡", trigger: "blur" } |
| | | ] |
| | | }; |
| | | |
| | | // ååºå¼æ°æ® |
| | | const data = reactive({ |
| | | searchForm: { |
| | | title: "", |
| | | type: "", |
| | | }, |
| | | tableLoading: false, |
| | | page: { |
| | | current: 1, |
| | | size: 20, |
| | | total: 0, |
| | | }, |
| | | tableData: [], |
| | | selectedIds: [], |
| | | form: { |
| | | title: "", |
| | | type: "", |
| | | scenario: "", |
| | | efficiency: "", |
| | | problem: "", |
| | | solution: "", |
| | | keyPoints: "", |
| | | creator: "", |
| | | usageCount: 0 |
| | | }, |
| | | dialogVisible: false, |
| | | dialogTitle: "", |
| | | dialogType: "add", |
| | | viewDialogVisible: false, |
| | | currentKnowledge: {} |
| | | }); |
| | | |
| | | const { |
| | | searchForm, |
| | | tableLoading, |
| | | page, |
| | | tableData, |
| | | selectedIds, |
| | | form, |
| | | dialogVisible, |
| | | dialogTitle, |
| | | dialogType, |
| | | viewDialogVisible, |
| | | currentKnowledge |
| | | } = toRefs(data); |
| | | |
| | | // 表åå¼ç¨ |
| | | const formRef = ref(); |
| | | |
| | | // è¡¨æ ¼åé
ç½® |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "ç¥è¯æ é¢", |
| | | prop: "title", |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "ç¥è¯ç±»å", |
| | | prop: "type", |
| | | dataType: "tag", |
| | | formatData: (params) => { |
| | | const typeMap = { |
| | | contract: "ååç¹æ¹", |
| | | approval: "å®¡æ¹æ¡ä¾", |
| | | solution: "è§£å³æ¹æ¡", |
| | | experience: "ç»éªæ»ç»", |
| | | guide: "æä½æå" |
| | | }; |
| | | return typeMap[params] || params; |
| | | }, |
| | | formatType: (params) => { |
| | | const typeMap = { |
| | | contract: "success", |
| | | approval: "warning", |
| | | solution: "primary", |
| | | experience: "info", |
| | | guide: "danger" |
| | | }; |
| | | return typeMap[params] || "info"; |
| | | } |
| | | }, |
| | | { |
| | | label: "éç¨åºæ¯", |
| | | prop: "scenario", |
| | | width: 150, |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "è§£å³æç", |
| | | prop: "efficiency", |
| | | dataType: "tag", |
| | | formatData: (params) => { |
| | | const efficiencyMap = { |
| | | high: "æ¾èæå", |
| | | medium: "ä¸è¬æå", |
| | | low: "轻微æå" |
| | | }; |
| | | return efficiencyMap[params] || params; |
| | | }, |
| | | formatType: (params) => { |
| | | const typeMap = { |
| | | high: "success", |
| | | medium: "warning", |
| | | low: "info" |
| | | }; |
| | | return typeMap[params] || "info"; |
| | | } |
| | | }, |
| | | { |
| | | label: "ä½¿ç¨æ¬¡æ°", |
| | | prop: "usageCount", |
| | | width: 100, |
| | | align: "center" |
| | | }, |
| | | { |
| | | label: "å建人", |
| | | prop: "creator", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "å建æ¶é´", |
| | | prop: "createTime", |
| | | width: 180, |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 200, |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openForm("edit", row); |
| | | } |
| | | }, |
| | | { |
| | | name: "æ¥ç", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | viewKnowledge(row); |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | ]); |
| | | |
| | | // æ¨¡ææ°æ® |
| | | // let mockData = [ |
| | | // { |
| | | // id: "1", |
| | | // title: "ç¹æ®ååå®¡æ¹æµç¨ä¼åæ¹æ¡", |
| | | // type: "contract", |
| | | // scenario: "大é¢ååå¿«é审æ¹", |
| | | // efficiency: "high", |
| | | // problem: "大é¢ååå®¡æ¹æµç¨å¤æï¼å®¡æ¹æ¶é´é¿ï¼å½±åä¸å¡è¿å±", |
| | | // solution: "建ç«ç»¿è²ééï¼å¯¹ç¬¦åæ¡ä»¶çååéç¨ç®åå®¡æ¹æµç¨ï¼ç±é¨é¨è´è´£äººç´æ¥å®¡æ¹ï¼å¹³åå®¡æ¹æ¶é´ä»3天缩çè³1天", |
| | | // keyPoints: "绿è²é鿡件,ç®åæµç¨,å®¡æ¹æé,æ¶é´æ§å¶", |
| | | // creator: "å¼ ç»ç", |
| | | // usageCount: 15, |
| | | // createTime: "2024-01-15 10:30:00" |
| | | // }, |
| | | // { |
| | | // id: "2", |
| | | // title: "è·¨é¨é¨åä½å®¡æ¹ç»éªæ»ç»", |
| | | // type: "experience", |
| | | // scenario: "å¤é¨é¨åä½é¡¹ç®", |
| | | // efficiency: "medium", |
| | | // problem: "è·¨é¨é¨é¡¹ç®å®¡æ¹æ¶ï¼åé¨é¨æè§ä¸ç»ä¸ï¼å®¡æ¹è¿åº¦ç¼æ
¢", |
| | | // solution: "建ç«é¡¹ç®åè°æºå¶ï¼æå®é¡¹ç®è´è´£äººï¼å®æå¬å¼åè°ä¼è®®ï¼ç»ä¸åæ¹æè§ååè¿è¡å®¡æ¹", |
| | | // keyPoints: "项ç®åè°,宿ä¼è®®,ç»ä¸æè§,è´è´£äººå¶åº¦", |
| | | // creator: "æä¸»ç®¡", |
| | | // usageCount: 8, |
| | | // createTime: "2024-01-14 15:20:00" |
| | | // }, |
| | | // { |
| | | // id: "3", |
| | | // title: "ç´§æ¥éè´å®¡æ¹æä½æå", |
| | | // type: "guide", |
| | | // scenario: "ç´§æ¥éè´éæ±", |
| | | // efficiency: "high", |
| | | // problem: "ç´§æ¥éè´æ¶å®¡æ¹æµç¨å¤æï¼æ æ³æ»¡è¶³ç´§æ¥éæ±", |
| | | // solution: "å¶å®ç´§æ¥éè´å®¡æ¹æ åï¼æç¡®ç´§æ¥ç¨åº¦å级ï¼ä¸å级å«éç¨ä¸åå®¡æ¹æµç¨ï¼ç¡®ä¿ç´§æ¥éæ±å¾å°åæ¶å¤ç", |
| | | // keyPoints: "ç´§æ¥å级,æ åå¶å®,æµç¨ç®å,åæ¶å¤ç", |
| | | // creator: "çä¸å", |
| | | // usageCount: 12, |
| | | // createTime: "2024-01-13 09:15:00" |
| | | // } |
| | | // ]; |
| | | |
| | | // ç¥è¯æ 颿¨¡æ¿ |
| | | const titleTemplates = [ |
| | | "{type}å®¡æ¹æµç¨ä¼åæ¹æ¡", |
| | | "{scenario}å¤çç»éªæ»ç»", |
| | | "{type}ç¹æ®æ
åµå¤çæå", |
| | | "{scenario}å¿«éå®¡æ¹æ¹æ¡", |
| | | "{type}æ ååæä½æµç¨", |
| | | "{scenario}é®é¢è§£å³æ¹æ¡", |
| | | "{type}æä½³å®è·µæ»ç»", |
| | | "{scenario}æçæåæ¹æ¡" |
| | | ]; |
| | | |
| | | // ç¥è¯ç±»åé
ç½® |
| | | const knowledgeTypes = [ |
| | | { type: "contract", label: "ååç¹æ¹", efficiency: "high" }, |
| | | { type: "approval", label: "å®¡æ¹æ¡ä¾", efficiency: "medium" }, |
| | | { type: "solution", label: "è§£å³æ¹æ¡", efficiency: "high" }, |
| | | { type: "experience", label: "ç»éªæ»ç»", efficiency: "medium" }, |
| | | { type: "guide", label: "æä½æå", efficiency: "low" } |
| | | ]; |
| | | |
| | | // åºæ¯å表 |
| | | 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)]; |
| | | |
| | | // çæéæºæ é¢ |
| | | let title = titleTemplates[Math.floor(Math.random() * titleTemplates.length)]; |
| | | title = title |
| | | .replace('{type}', randomType.label) |
| | | .replace('{scenario}', randomScenario); |
| | | |
| | | const newKnowledge = { |
| | | id: newId, |
| | | title: title, |
| | | type: randomType.type, |
| | | scenario: randomScenario, |
| | | efficiency: randomType.efficiency, |
| | | problem: `å¨${randomScenario}è¿ç¨ä¸éå°çé®é¢æè¿°...`, |
| | | solution: `é对${randomScenario}çè§£å³æ¹æ¡åæä½æ¥éª¤...`, |
| | | keyPoints: "å
³é®è¦ç¹1,å
³é®è¦ç¹2,å
³é®è¦ç¹3,å
³é®è¦ç¹4", |
| | | creator: ["å¼ ç»ç", "æä¸»ç®¡", "çä¸å", "åæ»ç"][Math.floor(Math.random() * 4)], |
| | | usageCount: Math.floor(Math.random() * 20) + 1, |
| | | createTime: now.toLocaleString() |
| | | // 表åéªè¯è§å |
| | | const rules = { |
| | | title: [{ required: true, message: "请è¾å
¥ç¥è¯æ é¢", trigger: "blur" }], |
| | | type: [{ required: true, message: "è¯·éæ©ç¥è¯ç±»å", trigger: "change" }], |
| | | problem: [{ required: true, message: "请æè¿°éå°çé®é¢", trigger: "blur" }], |
| | | solution: [ |
| | | { required: true, message: "è¯·è¯¦ç»æè¿°è§£å³æ¹æ¡", trigger: "blur" }, |
| | | ], |
| | | }; |
| | | |
| | | // æ·»å å°æ°æ®å¼å¤´ |
| | | mockData.unshift(newKnowledge); |
| | | |
| | | // ä¿ææ°æ®éå¨åçèå´å
ï¼æå¤ä¿ç30æ¡ï¼ |
| | | if (mockData.length > 30) { |
| | | mockData = mockData.slice(0, 30); |
| | | } |
| | | |
| | | console.log(`[${new Date().toLocaleString()}] èªå¨çææ°ç¥è¯: ${title}`); |
| | | }; |
| | | |
| | | // çå½å¨æ |
| | | onMounted(() => { |
| | | getList(); |
| | | startAutoRefresh(); |
| | | }); |
| | | |
| | | // å¼å§èªå¨å·æ° |
| | | const startAutoRefresh = () => { |
| | | setInterval(() => { |
| | | generateNewData(); |
| | | getList(); |
| | | }, 600000); // 10åéå·æ°ä¸æ¬¡ (10 * 60 * 1000 = 600000ms) |
| | | }; |
| | | |
| | | // æ¥è¯¢æ°æ® |
| | | const handleQuery = () => { |
| | | page.value.current = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | listKnowledgeBase({...page.value, ...searchForm.value}) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records |
| | | page.total = res.data.total; |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | | }) |
| | | }; |
| | | |
| | | // å页å¤ç |
| | | const pagination = (obj) => { |
| | | page.value.current = obj.page; |
| | | page.value.size = obj.limit; |
| | | handleQuery(); |
| | | }; |
| | | |
| | | // éæ©ååå¤ç |
| | | const handleSelectionChange = (selection) => { |
| | | selectedIds.value = selection.map(item => item.id); |
| | | }; |
| | | |
| | | // æå¼è¡¨å |
| | | const openForm = (type, row = null) => { |
| | | dialogType.value = type; |
| | | if (type === "add") { |
| | | dialogTitle.value = "æ°å¢ç¥è¯"; |
| | | // é置表å |
| | | Object.assign(form.value, { |
| | | // ååºå¼æ°æ® |
| | | const data = reactive({ |
| | | searchForm: { |
| | | title: "", |
| | | type: "", |
| | | }, |
| | | tableLoading: false, |
| | | page: { |
| | | current: 1, |
| | | size: 20, |
| | | total: 0, |
| | | }, |
| | | tableData: [], |
| | | selectedIds: [], |
| | | form: { |
| | | title: "", |
| | | type: "", |
| | | scenario: "", |
| | |
| | | solution: "", |
| | | keyPoints: "", |
| | | creator: "", |
| | | usageCount: 0 |
| | | }); |
| | | } else if (type === "edit" && row) { |
| | | dialogTitle.value = "ç¼è¾ç¥è¯"; |
| | | Object.assign(form.value, { |
| | | id: row.id, |
| | | title: row.title, |
| | | type: row.type, |
| | | scenario: row.scenario, |
| | | efficiency: row.efficiency, |
| | | problem: row.problem, |
| | | solution: row.solution, |
| | | keyPoints: row.keyPoints, |
| | | creator: row.creator, |
| | | usageCount: row.usageCount |
| | | }); |
| | | } |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | // æ¥çç¥è¯è¯¦æ
|
| | | const viewKnowledge = (row) => { |
| | | currentKnowledge.value = { ...row }; |
| | | viewDialogVisible.value = true; |
| | | }; |
| | | |
| | | // è·åç±»åæ ç¾ç±»å |
| | | const getTypeTagType = (type) => { |
| | | const typeMap = { |
| | | contract: "success", |
| | | approval: "warning", |
| | | solution: "primary", |
| | | experience: "info", |
| | | guide: "danger" |
| | | }; |
| | | return typeMap[type] || "info"; |
| | | }; |
| | | |
| | | // è·åç±»åæ ç¾ææ¬ |
| | | const getTypeLabel = (type) => { |
| | | const typeMap = { |
| | | contract: "ååç¹æ¹", |
| | | approval: "å®¡æ¹æ¡ä¾", |
| | | solution: "è§£å³æ¹æ¡", |
| | | experience: "ç»éªæ»ç»", |
| | | guide: "æä½æå" |
| | | }; |
| | | return typeMap[type] || type; |
| | | }; |
| | | |
| | | // è·åæçæ ç¾ç±»å |
| | | const getEfficiencyTagType = (efficiency) => { |
| | | const typeMap = { |
| | | high: "success", |
| | | medium: "warning", |
| | | low: "info" |
| | | }; |
| | | return typeMap[efficiency] || "info"; |
| | | }; |
| | | |
| | | // è·åæçæ ç¾ææ¬ |
| | | const getEfficiencyLabel = (efficiency) => { |
| | | const efficiencyMap = { |
| | | high: "æ¾èæå", |
| | | medium: "ä¸è¬æå", |
| | | low: "轻微æå" |
| | | }; |
| | | return efficiencyMap[efficiency] || efficiency; |
| | | }; |
| | | |
| | | // è·åæçæåç¾åæ¯ |
| | | const getEfficiencyScore = (efficiency) => { |
| | | const scoreMap = { |
| | | high: 40, |
| | | medium: 25, |
| | | low: 15 |
| | | }; |
| | | return scoreMap[efficiency] || 0; |
| | | }; |
| | | |
| | | // è·åå¹³åèçæ¶é´ |
| | | const getTimeSaved = (efficiency) => { |
| | | const timeMap = { |
| | | high: "2-3天", |
| | | medium: "1-2天", |
| | | low: "0.5-1天" |
| | | }; |
| | | return timeMap[efficiency] || "æªç¥"; |
| | | }; |
| | | |
| | | // å¤å¶ç¥è¯ |
| | | const copyKnowledge = () => { |
| | | const knowledgeText = ` |
| | | ç¥è¯æ é¢ï¼${currentKnowledge.value.title} |
| | | ç¥è¯ç±»åï¼${getTypeLabel(currentKnowledge.value.type)} |
| | | éç¨åºæ¯ï¼${currentKnowledge.value.scenario} |
| | | é®é¢æè¿°ï¼${currentKnowledge.value.problem} |
| | | è§£å³æ¹æ¡ï¼${currentKnowledge.value.solution} |
| | | å
³é®è¦ç¹ï¼${currentKnowledge.value.keyPoints} |
| | | å建人ï¼${currentKnowledge.value.creator} |
| | | `.trim(); |
| | | |
| | | // å¤å¶å°åªè´´æ¿ |
| | | navigator.clipboard.writeText(knowledgeText).then(() => { |
| | | ElMessage.success("ç¥è¯å
容已å¤å¶å°åªè´´æ¿"); |
| | | }).catch(() => { |
| | | ElMessage.error("å¤å¶å¤±è´¥ï¼è¯·æå¨å¤å¶"); |
| | | usageCount: 0, |
| | | }, |
| | | dialogVisible: false, |
| | | dialogTitle: "", |
| | | dialogType: "add", |
| | | viewDialogVisible: false, |
| | | currentKnowledge: {}, |
| | | }); |
| | | }; |
| | | |
| | | // æ¶èç¥è¯ |
| | | const markAsFavorite = () => { |
| | | // å¢å ä½¿ç¨æ¬¡æ° |
| | | const index = mockData.findIndex(item => item.id === currentKnowledge.value.id); |
| | | if (index !== -1) { |
| | | mockData[index].usageCount += 1; |
| | | currentKnowledge.value.usageCount += 1; |
| | | } |
| | | const { |
| | | searchForm, |
| | | tableLoading, |
| | | page, |
| | | tableData, |
| | | selectedIds, |
| | | form, |
| | | dialogVisible, |
| | | dialogTitle, |
| | | dialogType, |
| | | viewDialogVisible, |
| | | currentKnowledge, |
| | | } = toRefs(data); |
| | | |
| | | ElMessage.success("å·²æ¶èï¼ä½¿ç¨æ¬¡æ°+1"); |
| | | }; |
| | | // 表åå¼ç¨ |
| | | const formRef = ref(); |
| | | |
| | | // æäº¤ç¥è¯è¡¨å |
| | | const submitForm = async () => { |
| | | try { |
| | | await formRef.value.validate(); |
| | | if (dialogType.value === "add") { |
| | | // æ°å¢ç¥è¯ |
| | | addKnowledgeBase({...form.value}).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("æ·»å æå"); |
| | | dialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | } else { |
| | | updateKnowledgeBase({...form.value}).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("æ´æ°æå"); |
| | | dialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | // è¡¨æ ¼åé
ç½® |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "ç¥è¯æ é¢", |
| | | prop: "title", |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "ç¥è¯ç±»å", |
| | | prop: "type", |
| | | dataType: "tag", |
| | | formatData: params => { |
| | | const typeMap = { |
| | | contract: "ååç¹æ¹", |
| | | approval: "å®¡æ¹æ¡ä¾", |
| | | solution: "è§£å³æ¹æ¡", |
| | | experience: "ç»éªæ»ç»", |
| | | guide: "æä½æå", |
| | | }; |
| | | return typeMap[params] || params; |
| | | }, |
| | | formatType: params => { |
| | | const typeMap = { |
| | | contract: "success", |
| | | approval: "warning", |
| | | solution: "primary", |
| | | experience: "info", |
| | | guide: "danger", |
| | | }; |
| | | return typeMap[params] || "info"; |
| | | }, |
| | | }, |
| | | { |
| | | label: "éç¨åºæ¯", |
| | | prop: "scenario", |
| | | width: 150, |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "è§£å³æç", |
| | | prop: "efficiency", |
| | | dataType: "tag", |
| | | formatData: params => { |
| | | const efficiencyMap = { |
| | | high: "æ¾èæå", |
| | | medium: "ä¸è¬æå", |
| | | low: "轻微æå", |
| | | }; |
| | | return efficiencyMap[params] || params; |
| | | }, |
| | | formatType: params => { |
| | | const typeMap = { |
| | | high: "success", |
| | | medium: "warning", |
| | | low: "info", |
| | | }; |
| | | return typeMap[params] || "info"; |
| | | }, |
| | | }, |
| | | { |
| | | label: "ä½¿ç¨æ¬¡æ°", |
| | | prop: "usageCount", |
| | | width: 100, |
| | | align: "center", |
| | | }, |
| | | { |
| | | label: "å建人", |
| | | prop: "creator", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "å建æ¶é´", |
| | | prop: "createTime", |
| | | width: 180, |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 200, |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: row => { |
| | | openForm("edit", row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "æ¥ç", |
| | | type: "text", |
| | | clickFun: row => { |
| | | viewKnowledge(row); |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | | |
| | | // æ¨¡ææ°æ® |
| | | // let mockData = [ |
| | | // { |
| | | // id: "1", |
| | | // title: "ç¹æ®ååå®¡æ¹æµç¨ä¼åæ¹æ¡", |
| | | // type: "contract", |
| | | // scenario: "大é¢ååå¿«é审æ¹", |
| | | // efficiency: "high", |
| | | // problem: "大é¢ååå®¡æ¹æµç¨å¤æï¼å®¡æ¹æ¶é´é¿ï¼å½±åä¸å¡è¿å±", |
| | | // solution: "建ç«ç»¿è²ééï¼å¯¹ç¬¦åæ¡ä»¶çååéç¨ç®åå®¡æ¹æµç¨ï¼ç±é¨é¨è´è´£äººç´æ¥å®¡æ¹ï¼å¹³åå®¡æ¹æ¶é´ä»3天缩çè³1天", |
| | | // keyPoints: "绿è²é鿡件,ç®åæµç¨,å®¡æ¹æé,æ¶é´æ§å¶", |
| | | // creator: "å¼ ç»ç", |
| | | // usageCount: 15, |
| | | // createTime: "2024-01-15 10:30:00" |
| | | // }, |
| | | // { |
| | | // id: "2", |
| | | // title: "è·¨é¨é¨åä½å®¡æ¹ç»éªæ»ç»", |
| | | // type: "experience", |
| | | // scenario: "å¤é¨é¨åä½é¡¹ç®", |
| | | // efficiency: "medium", |
| | | // problem: "è·¨é¨é¨é¡¹ç®å®¡æ¹æ¶ï¼åé¨é¨æè§ä¸ç»ä¸ï¼å®¡æ¹è¿åº¦ç¼æ
¢", |
| | | // solution: "建ç«é¡¹ç®åè°æºå¶ï¼æå®é¡¹ç®è´è´£äººï¼å®æå¬å¼åè°ä¼è®®ï¼ç»ä¸åæ¹æè§ååè¿è¡å®¡æ¹", |
| | | // keyPoints: "项ç®åè°,宿ä¼è®®,ç»ä¸æè§,è´è´£äººå¶åº¦", |
| | | // creator: "æä¸»ç®¡", |
| | | // usageCount: 8, |
| | | // createTime: "2024-01-14 15:20:00" |
| | | // }, |
| | | // { |
| | | // id: "3", |
| | | // title: "ç´§æ¥éè´å®¡æ¹æä½æå", |
| | | // type: "guide", |
| | | // scenario: "ç´§æ¥éè´éæ±", |
| | | // efficiency: "high", |
| | | // problem: "ç´§æ¥éè´æ¶å®¡æ¹æµç¨å¤æï¼æ æ³æ»¡è¶³ç´§æ¥éæ±", |
| | | // solution: "å¶å®ç´§æ¥éè´å®¡æ¹æ åï¼æç¡®ç´§æ¥ç¨åº¦å级ï¼ä¸å级å«éç¨ä¸åå®¡æ¹æµç¨ï¼ç¡®ä¿ç´§æ¥éæ±å¾å°åæ¶å¤ç", |
| | | // keyPoints: "ç´§æ¥å级,æ åå¶å®,æµç¨ç®å,åæ¶å¤ç", |
| | | // creator: "çä¸å", |
| | | // usageCount: 12, |
| | | // createTime: "2024-01-13 09:15:00" |
| | | // } |
| | | // ]; |
| | | |
| | | // ç¥è¯æ 颿¨¡æ¿ |
| | | const titleTemplates = [ |
| | | "{type}å®¡æ¹æµç¨ä¼åæ¹æ¡", |
| | | "{scenario}å¤çç»éªæ»ç»", |
| | | "{type}ç¹æ®æ
åµå¤çæå", |
| | | "{scenario}å¿«éå®¡æ¹æ¹æ¡", |
| | | "{type}æ ååæä½æµç¨", |
| | | "{scenario}é®é¢è§£å³æ¹æ¡", |
| | | "{type}æä½³å®è·µæ»ç»", |
| | | "{scenario}æçæåæ¹æ¡", |
| | | ]; |
| | | |
| | | // ç¥è¯ç±»åé
ç½® |
| | | const knowledgeTypes = [ |
| | | { type: "contract", label: "ååç¹æ¹", efficiency: "high" }, |
| | | { type: "approval", label: "å®¡æ¹æ¡ä¾", efficiency: "medium" }, |
| | | { type: "solution", label: "è§£å³æ¹æ¡", efficiency: "high" }, |
| | | { type: "experience", label: "ç»éªæ»ç»", efficiency: "medium" }, |
| | | { type: "guide", label: "æä½æå", efficiency: "low" }, |
| | | ]; |
| | | |
| | | // åºæ¯å表 |
| | | 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)]; |
| | | |
| | | // çæéæºæ é¢ |
| | | let title = titleTemplates[Math.floor(Math.random() * titleTemplates.length)]; |
| | | title = title |
| | | .replace("{type}", randomType.label) |
| | | .replace("{scenario}", randomScenario); |
| | | |
| | | const newKnowledge = { |
| | | id: newId, |
| | | title: title, |
| | | type: randomType.type, |
| | | scenario: randomScenario, |
| | | efficiency: randomType.efficiency, |
| | | problem: `å¨${randomScenario}è¿ç¨ä¸éå°çé®é¢æè¿°...`, |
| | | solution: `é对${randomScenario}çè§£å³æ¹æ¡åæä½æ¥éª¤...`, |
| | | keyPoints: "å
³é®è¦ç¹1,å
³é®è¦ç¹2,å
³é®è¦ç¹3,å
³é®è¦ç¹4", |
| | | creator: ["å¼ ç»ç", "æä¸»ç®¡", "çä¸å", "åæ»ç"][ |
| | | Math.floor(Math.random() * 4) |
| | | ], |
| | | usageCount: Math.floor(Math.random() * 20) + 1, |
| | | createTime: now.toLocaleString(), |
| | | }; |
| | | |
| | | // æ·»å å°æ°æ®å¼å¤´ |
| | | mockData.unshift(newKnowledge); |
| | | |
| | | // ä¿ææ°æ®éå¨åçèå´å
ï¼æå¤ä¿ç30æ¡ï¼ |
| | | if (mockData.length > 30) { |
| | | mockData = mockData.slice(0, 30); |
| | | } |
| | | } catch (error) { |
| | | console.error("表åéªè¯å¤±è´¥:", error); |
| | | } |
| | | }; |
| | | |
| | | // å é¤ç¥è¯ |
| | | const handleDelete = () => { |
| | | if (selectedIds.value.length === 0) { |
| | | ElMessage.warning("è¯·éæ©è¦å é¤çç¥è¯"); |
| | | return; |
| | | } |
| | | console.log(`[${new Date().toLocaleString()}] èªå¨çææ°ç¥è¯: ${title}`); |
| | | }; |
| | | |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "å é¤", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).then(() => { |
| | | // console.log(selectedIds.value); |
| | | delKnowledgeBase(selectedIds.value).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("å 餿å"); |
| | | selectedIds.value = []; |
| | | getList(); |
| | | } |
| | | }) |
| | | }).catch(() => { |
| | | // ç¨æ·åæ¶ |
| | | // çå½å¨æ |
| | | onMounted(() => { |
| | | getList(); |
| | | startAutoRefresh(); |
| | | }); |
| | | }; |
| | | |
| | | // å¯¼åº |
| | | const { proxy } = getCurrentInstance() |
| | | const handleExport = () => { |
| | | proxy.download('/knowledgeBase/export', { ...searchForm.value }, 'ç¥è¯åº.xlsx') |
| | | } |
| | | // å¼å§èªå¨å·æ° |
| | | const startAutoRefresh = () => { |
| | | setInterval(() => { |
| | | generateNewData(); |
| | | getList(); |
| | | }, 600000); // 10åéå·æ°ä¸æ¬¡ (10 * 60 * 1000 = 600000ms) |
| | | }; |
| | | |
| | | // æ¥è¯¢æ°æ® |
| | | const handleQuery = () => { |
| | | page.value.current = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | listKnowledgeBase({ ...page.value, ...searchForm.value }) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }) |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | // å页å¤ç |
| | | const pagination = obj => { |
| | | page.value.current = obj.page; |
| | | page.value.size = obj.limit; |
| | | handleQuery(); |
| | | }; |
| | | |
| | | // éæ©ååå¤ç |
| | | const handleSelectionChange = selection => { |
| | | selectedIds.value = selection.map(item => item.id); |
| | | }; |
| | | |
| | | // æå¼è¡¨å |
| | | const openForm = (type, row = null) => { |
| | | dialogType.value = type; |
| | | if (type === "add") { |
| | | dialogTitle.value = "æ°å¢ç¥è¯"; |
| | | // é置表å |
| | | Object.assign(form.value, { |
| | | title: "", |
| | | type: "", |
| | | scenario: "", |
| | | efficiency: "", |
| | | problem: "", |
| | | solution: "", |
| | | keyPoints: "", |
| | | creator: "", |
| | | usageCount: 0, |
| | | }); |
| | | } else if (type === "edit" && row) { |
| | | dialogTitle.value = "ç¼è¾ç¥è¯"; |
| | | Object.assign(form.value, { |
| | | id: row.id, |
| | | title: row.title, |
| | | type: row.type, |
| | | scenario: row.scenario, |
| | | efficiency: row.efficiency, |
| | | problem: row.problem, |
| | | solution: row.solution, |
| | | keyPoints: row.keyPoints, |
| | | creator: row.creator, |
| | | usageCount: row.usageCount, |
| | | }); |
| | | } |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | // æ¥çç¥è¯è¯¦æ
|
| | | const viewKnowledge = row => { |
| | | currentKnowledge.value = { ...row }; |
| | | viewDialogVisible.value = true; |
| | | }; |
| | | |
| | | // è·åç±»åæ ç¾ç±»å |
| | | const getTypeTagType = type => { |
| | | const typeMap = { |
| | | contract: "success", |
| | | approval: "warning", |
| | | solution: "primary", |
| | | experience: "info", |
| | | guide: "danger", |
| | | }; |
| | | return typeMap[type] || "info"; |
| | | }; |
| | | |
| | | // è·åç±»åæ ç¾ææ¬ |
| | | const getTypeLabel = type => { |
| | | const typeMap = { |
| | | contract: "ååç¹æ¹", |
| | | approval: "å®¡æ¹æ¡ä¾", |
| | | solution: "è§£å³æ¹æ¡", |
| | | experience: "ç»éªæ»ç»", |
| | | guide: "æä½æå", |
| | | }; |
| | | return typeMap[type] || type; |
| | | }; |
| | | |
| | | // è·åæçæ ç¾ç±»å |
| | | const getEfficiencyTagType = efficiency => { |
| | | const typeMap = { |
| | | high: "success", |
| | | medium: "warning", |
| | | low: "info", |
| | | }; |
| | | return typeMap[efficiency] || "info"; |
| | | }; |
| | | |
| | | // è·åæçæ ç¾ææ¬ |
| | | const getEfficiencyLabel = efficiency => { |
| | | const efficiencyMap = { |
| | | high: "æ¾èæå", |
| | | medium: "ä¸è¬æå", |
| | | low: "轻微æå", |
| | | }; |
| | | return efficiencyMap[efficiency] || efficiency; |
| | | }; |
| | | |
| | | // è·åæçæåç¾åæ¯ |
| | | const getEfficiencyScore = efficiency => { |
| | | const scoreMap = { |
| | | high: 40, |
| | | medium: 25, |
| | | low: 15, |
| | | }; |
| | | return scoreMap[efficiency] || 0; |
| | | }; |
| | | |
| | | // è·åå¹³åèçæ¶é´ |
| | | const getTimeSaved = efficiency => { |
| | | const timeMap = { |
| | | high: "2-3天", |
| | | medium: "1-2天", |
| | | low: "0.5-1天", |
| | | }; |
| | | return timeMap[efficiency] || "æªç¥"; |
| | | }; |
| | | |
| | | // å¤å¶ç¥è¯ |
| | | const copyKnowledge = () => { |
| | | const knowledgeText = ` |
| | | ç¥è¯æ é¢ï¼${currentKnowledge.value.title} |
| | | ç¥è¯ç±»åï¼${getTypeLabel(currentKnowledge.value.type)} |
| | | éç¨åºæ¯ï¼${currentKnowledge.value.scenario} |
| | | é®é¢æè¿°ï¼${currentKnowledge.value.problem} |
| | | è§£å³æ¹æ¡ï¼${currentKnowledge.value.solution} |
| | | å
³é®è¦ç¹ï¼${currentKnowledge.value.keyPoints} |
| | | å建人ï¼${currentKnowledge.value.creator} |
| | | `.trim(); |
| | | |
| | | // å¤å¶å°åªè´´æ¿ |
| | | navigator.clipboard |
| | | .writeText(knowledgeText) |
| | | .then(() => { |
| | | ElMessage.success("ç¥è¯å
容已å¤å¶å°åªè´´æ¿"); |
| | | }) |
| | | .catch(() => { |
| | | ElMessage.error("å¤å¶å¤±è´¥ï¼è¯·æå¨å¤å¶"); |
| | | }); |
| | | }; |
| | | |
| | | // æ¶èç¥è¯ |
| | | const markAsFavorite = () => { |
| | | // å¢å ä½¿ç¨æ¬¡æ° |
| | | const index = mockData.findIndex( |
| | | item => item.id === currentKnowledge.value.id |
| | | ); |
| | | if (index !== -1) { |
| | | mockData[index].usageCount += 1; |
| | | currentKnowledge.value.usageCount += 1; |
| | | } |
| | | |
| | | ElMessage.success("å·²æ¶èï¼ä½¿ç¨æ¬¡æ°+1"); |
| | | }; |
| | | |
| | | // æäº¤ç¥è¯è¡¨å |
| | | const submitForm = async () => { |
| | | try { |
| | | await formRef.value.validate(); |
| | | if (dialogType.value === "add") { |
| | | // æ°å¢ç¥è¯ |
| | | addKnowledgeBase({ ...form.value }) |
| | | .then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("æ·»å æå"); |
| | | dialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | } else { |
| | | updateKnowledgeBase({ ...form.value }) |
| | | .then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("æ´æ°æå"); |
| | | dialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | } |
| | | } catch (error) { |
| | | console.error("表åéªè¯å¤±è´¥:", error); |
| | | } |
| | | }; |
| | | |
| | | // å é¤ç¥è¯ |
| | | const handleDelete = () => { |
| | | if (selectedIds.value.length === 0) { |
| | | ElMessage.warning("è¯·éæ©è¦å é¤çç¥è¯"); |
| | | return; |
| | | } |
| | | |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "å é¤", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | // console.log(selectedIds.value); |
| | | delKnowledgeBase(selectedIds.value).then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("å 餿å"); |
| | | selectedIds.value = []; |
| | | getList(); |
| | | } |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | // ç¨æ·åæ¶ |
| | | }); |
| | | }; |
| | | |
| | | // å¯¼åº |
| | | const { proxy } = getCurrentInstance(); |
| | | const handleExport = () => { |
| | | proxy.download( |
| | | "/knowledgeBase/export", |
| | | { ...searchForm.value }, |
| | | "ç¥è¯åº.xlsx" |
| | | ); |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .auto-refresh-info { |
| | | margin-bottom: 15px; |
| | | } |
| | | .auto-refresh-info { |
| | | margin-bottom: 15px; |
| | | } |
| | | |
| | | .auto-refresh-info .el-alert { |
| | | border-radius: 8px; |
| | | } |
| | | .auto-refresh-info .el-alert { |
| | | border-radius: 8px; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | text-align: right; |
| | | } |
| | | .dialog-footer { |
| | | text-align: right; |
| | | } |
| | | |
| | | .knowledge-detail { |
| | | padding: 20px 0; |
| | | } |
| | | .knowledge-detail { |
| | | padding: 20px 0; |
| | | } |
| | | |
| | | .detail-title { |
| | | font-size: 18px; |
| | | font-weight: bold; |
| | | color: #303133; |
| | | } |
| | | .detail-title { |
| | | font-size: 18px; |
| | | font-weight: bold; |
| | | color: #303133; |
| | | } |
| | | |
| | | .detail-section { |
| | | margin-top: 24px; |
| | | } |
| | | .detail-section { |
| | | margin-top: 24px; |
| | | } |
| | | |
| | | .detail-section h4 { |
| | | margin: 0 0 12px 0; |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | border-left: 4px solid #409eff; |
| | | padding-left: 12px; |
| | | } |
| | | .detail-section h4 { |
| | | margin: 0 0 12px 0; |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | border-left: 4px solid #409eff; |
| | | padding-left: 12px; |
| | | } |
| | | |
| | | .detail-content { |
| | | background: #f8f9fa; |
| | | padding: 16px; |
| | | border-radius: 6px; |
| | | line-height: 1.6; |
| | | color: #606266; |
| | | white-space: pre-wrap; |
| | | } |
| | | .detail-content { |
| | | background: #f8f9fa; |
| | | padding: 16px; |
| | | border-radius: 6px; |
| | | line-height: 1.6; |
| | | color: #606266; |
| | | white-space: pre-wrap; |
| | | } |
| | | |
| | | .key-points { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 8px; |
| | | } |
| | | .key-points { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .usage-stats { |
| | | margin-top: 16px; |
| | | } |
| | | .usage-stats { |
| | | margin-top: 16px; |
| | | } |
| | | |
| | | .stat-item { |
| | | text-align: center; |
| | | padding: 20px; |
| | | background: #f8f9fa; |
| | | border-radius: 8px; |
| | | } |
| | | .stat-item { |
| | | text-align: center; |
| | | padding: 20px; |
| | | background: #f8f9fa; |
| | | border-radius: 8px; |
| | | } |
| | | |
| | | .stat-number { |
| | | font-size: 24px; |
| | | font-weight: bold; |
| | | color: #409eff; |
| | | margin-bottom: 8px; |
| | | } |
| | | .stat-number { |
| | | font-size: 24px; |
| | | font-weight: bold; |
| | | color: #409eff; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .stat-label { |
| | | font-size: 14px; |
| | | color: #909399; |
| | | } |
| | | .stat-label { |
| | | font-size: 14px; |
| | | color: #909399; |
| | | } |
| | | </style> |
| | |
| | | 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" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥éç¥æ é¢æç´¢" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | /> |
| | | <el-input v-model="searchForm.title" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥éç¥æ é¢æç´¢" |
| | | @change="handleQuery" |
| | | clearable |
| | | :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" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | :total="page.total" |
| | | ></PIMTable> |
| | | <PIMTable rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | :total="page.total"></PIMTable> |
| | | </div> |
| | | |
| | | <!-- æ°å¢/ç¼è¾éç¥å¼¹çª --> |
| | | <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"> |
| | | <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"> |
| | | <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" |
| | | type="date" |
| | | placeholder="è¯·éæ©æææ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | style="width: 100%" |
| | | /> |
| | | <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%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-form-item label="æ¥æ¶é¨é¨" prop="departments"> |
| | | <el-select |
| | | v-model="form.departments" |
| | | multiple |
| | | placeholder="è¯·éæ©æ¥æ¶é¨é¨" |
| | | style="width: 100%" |
| | | > |
| | | <el-option |
| | | v-for="dept in departments" |
| | | :key="dept" |
| | | :label="dept" |
| | | :value="dept" |
| | | /> |
| | | <el-form-item label="æ¥æ¶é¨é¨" |
| | | prop="departments"> |
| | | <el-select v-model="form.departments" |
| | | multiple |
| | | placeholder="è¯·éæ©æ¥æ¶é¨é¨" |
| | | style="width: 100%"> |
| | | <el-option v-for="dept in departments" |
| | | :key="dept" |
| | | :label="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" |
| | | :key="method.value" |
| | | :label="method.value" |
| | | > |
| | | <el-checkbox v-for="method in syncMethods" |
| | | :key="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" |
| | | type="textarea" |
| | | :rows="4" |
| | | placeholder="请è¾å
¥éç¥å
容" |
| | | /> |
| | | <el-form-item label="éç¥å
容" |
| | | prop="content"> |
| | | <el-input v-model="form.content" |
| | | type="textarea" |
| | | :rows="4" |
| | | 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" |
| | | 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="请è¾å
¥ä¼è®®æ é¢" /> |
| | | <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="请è¾å
¥ä¼è®®æ é¢" /> |
| | | </el-form-item> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <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%" |
| | | /> |
| | | <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%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¼è®®æ¶é¿" prop="duration"> |
| | | <el-input-number |
| | | v-model="meetingForm.duration" |
| | | :min="15" |
| | | :max="480" |
| | | :step="15" |
| | | style="width: 100%" |
| | | /> |
| | | <el-form-item label="ä¼è®®æ¶é¿" |
| | | prop="duration"> |
| | | <el-input-number v-model="meetingForm.duration" |
| | | :min="15" |
| | | :max="480" |
| | | :step="15" |
| | | 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" |
| | | :key="platform.value" |
| | | :label="platform.label" |
| | | :value="platform.value" |
| | | /> |
| | | <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" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <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" |
| | | :key="group.label" |
| | | :label="group.label" |
| | | > |
| | | <el-option |
| | | v-for="employee in group.options" |
| | | :key="employee.value" |
| | | :label="`${employee.label} (${employee.dept})`" |
| | | :value="employee.value" |
| | | > |
| | | <div style="display: flex; justify-content: space-between; align-items: center;"> |
| | | <div> |
| | | <div style="font-weight: 500;">{{ employee.label }}</div> |
| | | <div style="color: #909399; font-size: 12px;">{{ employee.dept }}</div> |
| | | </div> |
| | | <div style="text-align: right; font-size: 12px; color: #909399;"> |
| | | <div v-if="employee.phone">{{ employee.phone }}</div> |
| | | <div v-if="employee.email">{{ employee.email }}</div> |
| | | </div> |
| | | </div> |
| | | </el-option> |
| | | <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" |
| | | :key="group.label" |
| | | :label="group.label"> |
| | | <el-option v-for="employee in group.options" |
| | | :key="employee.value" |
| | | :label="`${employee.label} (${employee.dept})`" |
| | | :value="employee.value"> |
| | | <div style="display: flex; justify-content: space-between; align-items: center;"> |
| | | <div> |
| | | <div style="font-weight: 500;">{{ employee.label }}</div> |
| | | <div style="color: #909399; font-size: 12px;">{{ employee.dept }}</div> |
| | | </div> |
| | | <div style="text-align: right; font-size: 12px; color: #909399;"> |
| | | <div v-if="employee.phone">{{ employee.phone }}</div> |
| | | <div v-if="employee.email">{{ employee.email }}</div> |
| | | </div> |
| | | </div> |
| | | </el-option> |
| | | </el-option-group> |
| | | </el-select> |
| | | <div style="margin-top: 8px; color: #909399; font-size: 12px;"> |
| | | 已鿩 {{ meetingForm.participants.length }} 人 |
| | | </div> |
| | | <!-- å·²éæ©äººå详æ
--> |
| | | <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;" |
| | | > |
| | | <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;"> |
| | | {{ getEmployeeName(participantId) }} |
| | | </el-tag> |
| | | </div> |
| | | </el-form-item> |
| | | <el-form-item label="ä¼è®®æè¿°" prop="description"> |
| | | <el-input |
| | | v-model="meetingForm.description" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥ä¼è®®æè¿°" |
| | | /> |
| | | <el-form-item label="ä¼è®®æè¿°" |
| | | prop="description"> |
| | | <el-input v-model="meetingForm.description" |
| | | type="textarea" |
| | | :rows="3" |
| | | 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" |
| | | 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="请è¾å
¥å
±äº«æ é¢" /> |
| | | <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="请è¾å
¥å
±äº«æ é¢" /> |
| | | </el-form-item> |
| | | <el-form-item label="å
±äº«æè¿°" prop="description"> |
| | | <el-input |
| | | v-model="fileShareForm.description" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥å
±äº«æè¿°" |
| | | /> |
| | | <el-form-item label="å
±äº«æè¿°" |
| | | prop="description"> |
| | | <el-input v-model="fileShareForm.description" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥å
±äº«æè¿°" /> |
| | | </el-form-item> |
| | | <el-form-item label="æ¥æ¶é¨é¨" prop="departments"> |
| | | <el-select |
| | | v-model="fileShareForm.departments" |
| | | multiple |
| | | placeholder="è¯·éæ©æ¥æ¶é¨é¨" |
| | | style="width: 100%" |
| | | > |
| | | <el-option |
| | | v-for="dept in departments" |
| | | :key="dept" |
| | | :label="dept" |
| | | :value="dept" |
| | | /> |
| | | <el-form-item label="æ¥æ¶é¨é¨" |
| | | prop="departments"> |
| | | <el-select v-model="fileShareForm.departments" |
| | | multiple |
| | | placeholder="è¯·éæ©æ¥æ¶é¨é¨" |
| | | style="width: 100%"> |
| | | <el-option v-for="dept in departments" |
| | | :key="dept" |
| | | :label="dept" |
| | | :value="dept" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <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" |
| | | > |
| | | <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"> |
| | | <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> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import { onMounted, ref, reactive, toRefs, computed } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | 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 { id } from "element-plus/es/locales.mjs"; |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import { onMounted, ref, reactive, toRefs, computed } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | 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 { 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" } |
| | | ] |
| | | }; |
| | | |
| | | const meetingRules = { |
| | | title: [ |
| | | { required: true, message: "请è¾å
¥ä¼è®®æ é¢", trigger: "blur" } |
| | | ], |
| | | startTime: [ |
| | | { required: true, message: "è¯·éæ©ä¼è®®å¼å§æ¶é´", trigger: "change" } |
| | | ], |
| | | participants: [ |
| | | { required: true, message: "è¯·éæ©åä¼äººå", trigger: "change" } |
| | | ] |
| | | }; |
| | | |
| | | const fileShareRules = { |
| | | title: [ |
| | | { required: true, message: "请è¾å
¥å
±äº«æ é¢", trigger: "blur" } |
| | | ], |
| | | description: [ |
| | | { required: true, message: "请è¾å
¥å
±äº«æè¿°", trigger: "blur" } |
| | | ] |
| | | }; |
| | | |
| | | // ååºå¼æ°æ® |
| | | const data = reactive({ |
| | | searchForm: { |
| | | title: "", |
| | | type: "", |
| | | status: "", |
| | | }, |
| | | tableLoading: false, |
| | | page: { |
| | | current: 1, |
| | | size: 20, |
| | | total: 0, |
| | | }, |
| | | tableData: [], |
| | | selectedIds: [], |
| | | // æ°å¢éç¥ç¸å
³ |
| | | form: { |
| | | title: "", |
| | | type: "", |
| | | priority: "", |
| | | content: "", |
| | | departments: [], |
| | | expireDate: "", |
| | | syncMethods: [] |
| | | }, |
| | | dialogVisible: false, |
| | | dialogTitle: "", |
| | | dialogType: "add", |
| | | // å¨çº¿ä¼è®®ç¸å
³ |
| | | meetingDialogVisible: false, |
| | | meetingForm: { |
| | | title: "", |
| | | startTime: "", |
| | | duration: 60, |
| | | participants: [], |
| | | description: "", |
| | | platform: "wechat" |
| | | }, |
| | | // æä»¶å
±äº«ç¸å
³ |
| | | fileShareDialogVisible: false, |
| | | fileShareForm: { |
| | | title: "", |
| | | description: "", |
| | | departments: [], |
| | | files: [] |
| | | }, |
| | | fileList: [] |
| | | }); |
| | | |
| | | const { |
| | | searchForm, |
| | | tableLoading, |
| | | page, |
| | | tableData, |
| | | selectedIds, |
| | | form, |
| | | dialogVisible, |
| | | dialogTitle, |
| | | dialogType, |
| | | meetingDialogVisible, |
| | | meetingForm, |
| | | fileShareDialogVisible, |
| | | fileShareForm, |
| | | fileList |
| | | } = toRefs(data); |
| | | |
| | | // 表åå¼ç¨ |
| | | const formRef = ref(); |
| | | const meetingFormRef = ref(); |
| | | const fileShareFormRef = ref(); |
| | | |
| | | // è¡¨æ ¼åé
ç½® |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "éç¥æ é¢", |
| | | prop: "title", |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "éç¥ç±»å", |
| | | prop: "type", |
| | | dataType: "tag", |
| | | formatData: (params) => { |
| | | const typeMap = { |
| | | holiday: "æ¾åéç¥", |
| | | penalty: "å¤ç½éç¥", |
| | | meeting: "å¼ä¼éç¥", |
| | | temporary: "临æ¶éç¥", |
| | | formal: "æ£å¼éç¥" |
| | | }; |
| | | return typeMap[params] || params; |
| | | }, |
| | | formatType: (params) => { |
| | | const typeMap = { |
| | | holiday: "success", |
| | | penalty: "danger", |
| | | meeting: "warning", |
| | | temporary: "info", |
| | | formal: "primary" |
| | | }; |
| | | return typeMap[params] || "info"; |
| | | } |
| | | }, |
| | | { |
| | | label: "ä¼å
级", |
| | | prop: "priority", |
| | | dataType: "tag", |
| | | formatData: (params) => { |
| | | const priorityMap = { |
| | | low: "æ®é", |
| | | medium: "éè¦", |
| | | high: "ç´§æ¥" |
| | | }; |
| | | return priorityMap[params] || params; |
| | | }, |
| | | formatType: (params) => { |
| | | const typeMap = { |
| | | low: "info", |
| | | medium: "warning", |
| | | high: "danger" |
| | | }; |
| | | return typeMap[params] || "info"; |
| | | } |
| | | }, |
| | | { |
| | | label: "ç¶æ", |
| | | prop: "status", |
| | | dataType: "tag", |
| | | formatData: (params) => { |
| | | const statusMap = { |
| | | draft: "è稿", |
| | | published: "å·²åå¸", |
| | | expired: "å·²è¿æ" |
| | | }; |
| | | return statusMap[params] || params; |
| | | }, |
| | | formatType: (params) => { |
| | | const typeMap = { |
| | | draft: "info", |
| | | published: "success", |
| | | expired: "danger" |
| | | }; |
| | | return typeMap[params] || "info"; |
| | | } |
| | | }, |
| | | { |
| | | label: "æ¥æ¶é¨é¨", |
| | | prop: "departments", |
| | | width: 150, |
| | | showOverflowTooltip: true, |
| | | formatData: (params) => { |
| | | if (!params || params.length === 0) return "å
¨é¨é¨é¨"; |
| | | return params.join(", "); |
| | | } |
| | | }, |
| | | { |
| | | label: "æææè³", |
| | | prop: "expireDate", |
| | | width: 150, |
| | | formatData: (params) => { |
| | | if (!params) return "æ°¸ä¹
ææ"; |
| | | return params; |
| | | } |
| | | }, |
| | | { |
| | | label: "å建æ¶é´", |
| | | prop: "createTime", |
| | | width: 180, |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 280, |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openForm("edit", row); |
| | | } |
| | | }, |
| | | { |
| | | name: "åå¸", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | publishNotification(row); |
| | | }, |
| | | // disabled: (row) => row.status === "published" |
| | | }, |
| | | { |
| | | name: "æ¤å", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | revokeNotification(row); |
| | | }, |
| | | // disabled: (row) => row.status !== "published" |
| | | } |
| | | ] |
| | | } |
| | | ]); |
| | | // éç¥æ 颿¨¡æ¿ |
| | | const titleTemplates = [ |
| | | "å
³äº{year}å¹´{holiday}æ¾å宿çéç¥", |
| | | "{dept}é¨é¨{meeting}ä¼è®®éç¥", |
| | | "åå·¥{behavior}è¡ä¸ºè§èæé", |
| | | "{company}éè¦äºé¡¹éç¥", |
| | | "{dept}é¨é¨å·¥ä½å®æéç¥", |
| | | "å
³äº{project}项ç®è¿åº¦çéç¥", |
| | | "{dept}é¨é¨äººåè°æ´éç¥", |
| | | "å
¬å¸{policy}æ¿çæ´æ°éç¥" |
| | | ]; |
| | | |
| | | // éç¥ç±»åé
ç½® |
| | | const notificationTypes = [ |
| | | { type: "holiday", label: "æ¾åéç¥", priority: "high" }, |
| | | { type: "meeting", label: "å¼ä¼éç¥", priority: "medium" }, |
| | | { type: "penalty", label: "å¤ç½éç¥", priority: "high" }, |
| | | { type: "temporary", label: "临æ¶éç¥", priority: "low" }, |
| | | { type: "formal", label: "æ£å¼éç¥", priority: "medium" } |
| | | ]; |
| | | |
| | | // é¨é¨å表 |
| | | const departments = ["ææ¯é¨", "éå®é¨", "人äºé¨", "è´¢å¡é¨", "è¿è¥é¨", "å¸åºé¨", "客æé¨"]; |
| | | |
| | | // 人åå表 |
| | | const employees = ref([]); |
| | | const employeesLoading = ref(false); |
| | | |
| | | // è·åå¨èåå·¥å表 |
| | | const getEmployeesList = async () => { |
| | | try { |
| | | employeesLoading.value = true; |
| | | // ä¼å
使ç¨ç³»ç»ç¨æ·æ¥å£ï¼æç§æ·è·åï¼ |
| | | const userResponse = await userListNoPageByTenantId(); |
| | | |
| | | if (userResponse.data) { |
| | | 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'); // åªæ¾ç¤ºæ£å¸¸ç¶æçç¨æ· |
| | | } else { |
| | | // å¦æç³»ç»ç¨æ·æ¥å£å¤±è´¥ï¼ä½¿ç¨åå·¥å°è´¦æ¥å£ |
| | | const response = await staffOnJobListPage({ |
| | | pageNum: 1, |
| | | pageSize: 1000, |
| | | staffState: 1 // å¨èç¶æ |
| | | }); |
| | | |
| | | if (response.data && response.data.records) { |
| | | employees.value = response.data.records.map(employee => ({ |
| | | 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' |
| | | })); |
| | | } |
| | | } |
| | | } catch (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" } |
| | | ]; |
| | | } finally { |
| | | employeesLoading.value = false; |
| | | } |
| | | }; |
| | | |
| | | // åå·¥åç» |
| | | const employeeGroups = computed(() => { |
| | | const groups = {}; |
| | | employees.value.forEach(employee => { |
| | | const dept = employee.dept || 'å
¶ä»é¨é¨'; |
| | | if (!groups[dept]) { |
| | | groups[dept] = []; |
| | | } |
| | | groups[dept].push(employee); |
| | | }); |
| | | |
| | | // æé¨é¨åç§°æåºï¼ç¡®ä¿æ¾ç¤ºé¡ºåºä¸è´ |
| | | return Object.keys(groups) |
| | | .sort() |
| | | .map(dept => ({ |
| | | label: dept, |
| | | options: groups[dept].sort((a, b) => a.label.localeCompare(b.label, 'zh-CN')) |
| | | })); |
| | | }); |
| | | |
| | | // è¿æ»¤åå·¥ï¼è¿ç¨æç´¢ï¼ |
| | | const filterEmployees = (query) => { |
| | | if (query !== '') { |
| | | const lowerQuery = query.toLowerCase(); |
| | | return employees.value.filter(employee => |
| | | employee.label.toLowerCase().includes(lowerQuery) || |
| | | employee.dept.toLowerCase().includes(lowerQuery) || |
| | | (employee.phone && employee.phone.includes(query)) || |
| | | (employee.email && employee.email.toLowerCase().includes(lowerQuery)) |
| | | ); |
| | | } else { |
| | | return employees.value; |
| | | } |
| | | }; |
| | | |
| | | // å·æ°åå·¥å表 |
| | | const refreshEmployees = async () => { |
| | | ElMessage.info("æ£å¨å·æ°åå·¥å表..."); |
| | | await getEmployeesList(); |
| | | |
| | | // ç»è®¡åé¨é¨äººæ° |
| | | const deptStats = {}; |
| | | employees.value.forEach(emp => { |
| | | const dept = emp.dept || 'å
¶ä»é¨é¨'; |
| | | deptStats[dept] = (deptStats[dept] || 0) + 1; |
| | | }); |
| | | |
| | | const deptInfo = Object.entries(deptStats) |
| | | .map(([dept, count]) => `${dept}: ${count}人`) |
| | | .join(', '); |
| | | |
| | | ElMessage.success(`åå·¥åè¡¨å·æ°å®æï¼å
± ${employees.value.length} 人 (${deptInfo})`); |
| | | }; |
| | | |
| | | // è·ååå·¥å§å |
| | | const getEmployeeName = (employeeId) => { |
| | | const employee = employees.value.find(emp => emp.value === employeeId); |
| | | return employee ? employee.label : 'æªç¥äººå'; |
| | | }; |
| | | |
| | | // è·åå工详ç»ä¿¡æ¯ |
| | | const getEmployeeInfo = (employeeId) => { |
| | | const employee = employees.value.find(emp => emp.value === employeeId); |
| | | if (!employee) return null; |
| | | |
| | | return { |
| | | name: employee.label, |
| | | dept: employee.dept, |
| | | phone: employee.phone, |
| | | email: employee.email |
| | | }; |
| | | }; |
| | | |
| | | // ç§»é¤åä¼äººå |
| | | const removeParticipant = (participantId) => { |
| | | const index = meetingForm.value.participants.indexOf(participantId); |
| | | if (index > -1) { |
| | | meetingForm.value.participants.splice(index, 1); |
| | | } |
| | | }; |
| | | |
| | | // 忥æ¹å¼é项 |
| | | const syncMethods = [ |
| | | { label: "ä¼ä¸å¾®ä¿¡", value: "wechat" }, |
| | | { label: "éé", value: "dingtalk" }, |
| | | { label: "é®ä»¶", value: "email" }, |
| | | { label: "çä¿¡", value: "sms" } |
| | | ]; |
| | | |
| | | // ä¼è®®å¹³å°é项 |
| | | const meetingPlatforms = [ |
| | | { label: "ä¼ä¸å¾®ä¿¡ä¼è®®", value: "wechat" }, |
| | | { label: "ééä¼è®®", value: "dingtalk" }, |
| | | { label: "è
¾è®¯ä¼è®®", value: "tencent" }, |
| | | { 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)]; |
| | | |
| | | // çæéæºæ é¢ |
| | | 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)]); |
| | | |
| | | // éæºç¶æ |
| | | 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 newNotification = { |
| | | id: newId, |
| | | title: title, |
| | | type: randomType.type, |
| | | priority: randomPriority, |
| | | status: randomStatus, |
| | | content: `è¿æ¯${title}ç详ç»å
容ï¼è¯·ç¸å
³äººåæ³¨ææ¥ç...`, |
| | | departments: [randomDept], |
| | | expireDate: new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000).toISOString().split('T')[0], // 30天åè¿æ |
| | | syncMethods: ["wechat", "dingtalk"], |
| | | createTime: now.toLocaleString() |
| | | // 表åéªè¯è§å |
| | | const rules = { |
| | | title: [{ required: true, message: "请è¾å
¥éç¥æ é¢", trigger: "blur" }], |
| | | type: [{ required: true, message: "è¯·éæ©éç¥ç±»å", trigger: "change" }], |
| | | content: [{ required: true, message: "请è¾å
¥éç¥å
容", trigger: "blur" }], |
| | | }; |
| | | |
| | | // æ·»å å°æ°æ®å¼å¤´ |
| | | mockData.unshift(newNotification); |
| | | const meetingRules = { |
| | | title: [{ required: true, message: "请è¾å
¥ä¼è®®æ é¢", trigger: "blur" }], |
| | | startTime: [ |
| | | { required: true, message: "è¯·éæ©ä¼è®®å¼å§æ¶é´", trigger: "change" }, |
| | | ], |
| | | participants: [ |
| | | { required: true, message: "è¯·éæ©åä¼äººå", trigger: "change" }, |
| | | ], |
| | | }; |
| | | |
| | | // ä¿ææ°æ®éå¨åçèå´å
ï¼æå¤ä¿ç20æ¡ï¼ |
| | | if (mockData.length > 20) { |
| | | mockData = mockData.slice(0, 20); |
| | | } |
| | | const fileShareRules = { |
| | | title: [{ required: true, message: "请è¾å
¥å
±äº«æ é¢", trigger: "blur" }], |
| | | description: [{ required: true, message: "请è¾å
¥å
±äº«æè¿°", trigger: "blur" }], |
| | | }; |
| | | |
| | | console.log(`[${new Date().toLocaleString()}] èªå¨çææ°éç¥: ${title}`); |
| | | }; |
| | | |
| | | // çå½å¨æ |
| | | onMounted(() => { |
| | | getList(); |
| | | getEmployeesList(); // è·ååå·¥å表 |
| | | startAutoRefresh(); |
| | | }); |
| | | |
| | | // å¼å§èªå¨å·æ° |
| | | const startAutoRefresh = () => { |
| | | setInterval(() => { |
| | | generateNewData(); |
| | | getList(); |
| | | }, 600000); // 10åéå·æ°ä¸æ¬¡ (10 * 60 * 1000 = 600000ms) |
| | | }; |
| | | |
| | | // æ¥è¯¢æ°æ® |
| | | const handleQuery = () => { |
| | | page.value.current = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | listNotification({...page.value, ...searchForm.value}) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records |
| | | page.value.total = res.data.total; |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | | }) |
| | | }; |
| | | |
| | | // å页å¤ç |
| | | const pagination = (obj) => { |
| | | page.value.current = obj.page; |
| | | page.value.size = obj.limit; |
| | | handleQuery(); |
| | | }; |
| | | |
| | | // éæ©ååå¤ç |
| | | const handleSelectionChange = (selection) => { |
| | | selectedIds.value = selection.map(item => item.id); |
| | | }; |
| | | |
| | | // æå¼è¡¨å |
| | | const openForm = (type, row = null) => { |
| | | dialogType.value = type; |
| | | if (type === "add") { |
| | | dialogTitle.value = "æ°å¢éç¥"; |
| | | // é置表å |
| | | Object.assign(form.value, { |
| | | id: "", |
| | | // ååºå¼æ°æ® |
| | | const data = reactive({ |
| | | searchForm: { |
| | | title: "", |
| | | type: "", |
| | | status: "", |
| | | }, |
| | | tableLoading: false, |
| | | page: { |
| | | current: 1, |
| | | size: 20, |
| | | total: 0, |
| | | }, |
| | | tableData: [], |
| | | selectedIds: [], |
| | | // æ°å¢éç¥ç¸å
³ |
| | | form: { |
| | | title: "", |
| | | type: "", |
| | | priority: "", |
| | | content: "", |
| | | departments: [], |
| | | expireDate: "", |
| | | status: "draft", |
| | | syncMethods: [] |
| | | syncMethods: [], |
| | | }, |
| | | dialogVisible: false, |
| | | dialogTitle: "", |
| | | dialogType: "add", |
| | | // å¨çº¿ä¼è®®ç¸å
³ |
| | | meetingDialogVisible: false, |
| | | meetingForm: { |
| | | title: "", |
| | | startTime: "", |
| | | duration: 60, |
| | | participants: [], |
| | | description: "", |
| | | platform: "wechat", |
| | | }, |
| | | // æä»¶å
±äº«ç¸å
³ |
| | | fileShareDialogVisible: false, |
| | | fileShareForm: { |
| | | title: "", |
| | | description: "", |
| | | departments: [], |
| | | files: [], |
| | | }, |
| | | fileList: [], |
| | | }); |
| | | |
| | | const { |
| | | searchForm, |
| | | tableLoading, |
| | | page, |
| | | tableData, |
| | | selectedIds, |
| | | form, |
| | | dialogVisible, |
| | | dialogTitle, |
| | | dialogType, |
| | | meetingDialogVisible, |
| | | meetingForm, |
| | | fileShareDialogVisible, |
| | | fileShareForm, |
| | | fileList, |
| | | } = toRefs(data); |
| | | |
| | | // 表åå¼ç¨ |
| | | const formRef = ref(); |
| | | const meetingFormRef = ref(); |
| | | const fileShareFormRef = ref(); |
| | | |
| | | // è¡¨æ ¼åé
ç½® |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "éç¥æ é¢", |
| | | prop: "title", |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "éç¥ç±»å", |
| | | prop: "type", |
| | | dataType: "tag", |
| | | formatData: params => { |
| | | const typeMap = { |
| | | holiday: "æ¾åéç¥", |
| | | penalty: "å¤ç½éç¥", |
| | | meeting: "å¼ä¼éç¥", |
| | | temporary: "临æ¶éç¥", |
| | | formal: "æ£å¼éç¥", |
| | | }; |
| | | return typeMap[params] || params; |
| | | }, |
| | | formatType: params => { |
| | | const typeMap = { |
| | | holiday: "success", |
| | | penalty: "danger", |
| | | meeting: "warning", |
| | | temporary: "info", |
| | | formal: "primary", |
| | | }; |
| | | return typeMap[params] || "info"; |
| | | }, |
| | | }, |
| | | { |
| | | label: "ä¼å
级", |
| | | prop: "priority", |
| | | dataType: "tag", |
| | | formatData: params => { |
| | | const priorityMap = { |
| | | low: "æ®é", |
| | | medium: "éè¦", |
| | | high: "ç´§æ¥", |
| | | }; |
| | | return priorityMap[params] || params; |
| | | }, |
| | | formatType: params => { |
| | | const typeMap = { |
| | | low: "info", |
| | | medium: "warning", |
| | | high: "danger", |
| | | }; |
| | | return typeMap[params] || "info"; |
| | | }, |
| | | }, |
| | | { |
| | | label: "ç¶æ", |
| | | prop: "status", |
| | | dataType: "tag", |
| | | formatData: params => { |
| | | const statusMap = { |
| | | draft: "è稿", |
| | | published: "å·²åå¸", |
| | | expired: "å·²è¿æ", |
| | | }; |
| | | return statusMap[params] || params; |
| | | }, |
| | | formatType: params => { |
| | | const typeMap = { |
| | | draft: "info", |
| | | published: "success", |
| | | expired: "danger", |
| | | }; |
| | | return typeMap[params] || "info"; |
| | | }, |
| | | }, |
| | | { |
| | | label: "æ¥æ¶é¨é¨", |
| | | prop: "departments", |
| | | width: 150, |
| | | showOverflowTooltip: true, |
| | | formatData: params => { |
| | | if (!params || params.length === 0) return "å
¨é¨é¨é¨"; |
| | | return params.join(", "); |
| | | }, |
| | | }, |
| | | { |
| | | label: "æææè³", |
| | | prop: "expireDate", |
| | | width: 150, |
| | | formatData: params => { |
| | | if (!params) return "æ°¸ä¹
ææ"; |
| | | return params; |
| | | }, |
| | | }, |
| | | { |
| | | label: "å建æ¶é´", |
| | | prop: "createTime", |
| | | width: 180, |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 280, |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: row => { |
| | | openForm("edit", row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "åå¸", |
| | | type: "text", |
| | | clickFun: row => { |
| | | publishNotification(row); |
| | | }, |
| | | // disabled: (row) => row.status === "published" |
| | | }, |
| | | { |
| | | name: "æ¤å", |
| | | type: "text", |
| | | clickFun: row => { |
| | | revokeNotification(row); |
| | | }, |
| | | // disabled: (row) => row.status !== "published" |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | | // éç¥æ 颿¨¡æ¿ |
| | | const titleTemplates = [ |
| | | "å
³äº{year}å¹´{holiday}æ¾å宿çéç¥", |
| | | "{dept}é¨é¨{meeting}ä¼è®®éç¥", |
| | | "åå·¥{behavior}è¡ä¸ºè§èæé", |
| | | "{company}éè¦äºé¡¹éç¥", |
| | | "{dept}é¨é¨å·¥ä½å®æéç¥", |
| | | "å
³äº{project}项ç®è¿åº¦çéç¥", |
| | | "{dept}é¨é¨äººåè°æ´éç¥", |
| | | "å
¬å¸{policy}æ¿çæ´æ°éç¥", |
| | | ]; |
| | | |
| | | // éç¥ç±»åé
ç½® |
| | | const notificationTypes = [ |
| | | { type: "holiday", label: "æ¾åéç¥", priority: "high" }, |
| | | { type: "meeting", label: "å¼ä¼éç¥", priority: "medium" }, |
| | | { type: "penalty", label: "å¤ç½éç¥", priority: "high" }, |
| | | { type: "temporary", label: "临æ¶éç¥", priority: "low" }, |
| | | { type: "formal", label: "æ£å¼éç¥", priority: "medium" }, |
| | | ]; |
| | | |
| | | // é¨é¨å表 |
| | | const departments = [ |
| | | "ææ¯é¨", |
| | | "éå®é¨", |
| | | "人äºé¨", |
| | | "è´¢å¡é¨", |
| | | "è¿è¥é¨", |
| | | "å¸åºé¨", |
| | | "客æé¨", |
| | | ]; |
| | | |
| | | // 人åå表 |
| | | const employees = ref([]); |
| | | const employeesLoading = ref(false); |
| | | |
| | | // è·åå¨èåå·¥å表 |
| | | const getEmployeesList = async () => { |
| | | try { |
| | | employeesLoading.value = true; |
| | | // ä¼å
使ç¨ç³»ç»ç¨æ·æ¥å£ï¼æç§æ·è·åï¼ |
| | | const userResponse = await userListNoPageByTenantId(); |
| | | |
| | | if (userResponse.data) { |
| | | 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"); // åªæ¾ç¤ºæ£å¸¸ç¶æçç¨æ· |
| | | } else { |
| | | // å¦æç³»ç»ç¨æ·æ¥å£å¤±è´¥ï¼ä½¿ç¨åå·¥å°è´¦æ¥å£ |
| | | const response = await staffOnJobListPage({ |
| | | pageNum: 1, |
| | | pageSize: 1000, |
| | | staffState: 1, // å¨èç¶æ |
| | | }); |
| | | |
| | | if (response.data && response.data.records) { |
| | | employees.value = response.data.records.map(employee => ({ |
| | | 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", |
| | | })); |
| | | } |
| | | } |
| | | } catch (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", |
| | | }, |
| | | ]; |
| | | } finally { |
| | | employeesLoading.value = false; |
| | | } |
| | | }; |
| | | |
| | | // åå·¥åç» |
| | | const employeeGroups = computed(() => { |
| | | const groups = {}; |
| | | employees.value.forEach(employee => { |
| | | const dept = employee.dept || "å
¶ä»é¨é¨"; |
| | | if (!groups[dept]) { |
| | | groups[dept] = []; |
| | | } |
| | | groups[dept].push(employee); |
| | | }); |
| | | } else if (type === "edit" && row) { |
| | | dialogTitle.value = "ç¼è¾éç¥"; |
| | | |
| | | // æé¨é¨åç§°æåºï¼ç¡®ä¿æ¾ç¤ºé¡ºåºä¸è´ |
| | | return Object.keys(groups) |
| | | .sort() |
| | | .map(dept => ({ |
| | | label: dept, |
| | | options: groups[dept].sort((a, b) => |
| | | a.label.localeCompare(b.label, "zh-CN") |
| | | ), |
| | | })); |
| | | }); |
| | | |
| | | // è¿æ»¤åå·¥ï¼è¿ç¨æç´¢ï¼ |
| | | const filterEmployees = query => { |
| | | if (query !== "") { |
| | | const lowerQuery = query.toLowerCase(); |
| | | return employees.value.filter( |
| | | employee => |
| | | employee.label.toLowerCase().includes(lowerQuery) || |
| | | employee.dept.toLowerCase().includes(lowerQuery) || |
| | | (employee.phone && employee.phone.includes(query)) || |
| | | (employee.email && employee.email.toLowerCase().includes(lowerQuery)) |
| | | ); |
| | | } else { |
| | | return employees.value; |
| | | } |
| | | }; |
| | | |
| | | // å·æ°åå·¥å表 |
| | | const refreshEmployees = async () => { |
| | | ElMessage.info("æ£å¨å·æ°åå·¥å表..."); |
| | | await getEmployeesList(); |
| | | |
| | | // ç»è®¡åé¨é¨äººæ° |
| | | const deptStats = {}; |
| | | employees.value.forEach(emp => { |
| | | const dept = emp.dept || "å
¶ä»é¨é¨"; |
| | | deptStats[dept] = (deptStats[dept] || 0) + 1; |
| | | }); |
| | | |
| | | const deptInfo = Object.entries(deptStats) |
| | | .map(([dept, count]) => `${dept}: ${count}人`) |
| | | .join(", "); |
| | | |
| | | ElMessage.success( |
| | | `åå·¥åè¡¨å·æ°å®æï¼å
± ${employees.value.length} 人 (${deptInfo})` |
| | | ); |
| | | }; |
| | | |
| | | // è·ååå·¥å§å |
| | | const getEmployeeName = employeeId => { |
| | | const employee = employees.value.find(emp => emp.value === employeeId); |
| | | return employee ? employee.label : "æªç¥äººå"; |
| | | }; |
| | | |
| | | // è·åå工详ç»ä¿¡æ¯ |
| | | const getEmployeeInfo = employeeId => { |
| | | const employee = employees.value.find(emp => emp.value === employeeId); |
| | | if (!employee) return null; |
| | | |
| | | return { |
| | | name: employee.label, |
| | | dept: employee.dept, |
| | | phone: employee.phone, |
| | | email: employee.email, |
| | | }; |
| | | }; |
| | | |
| | | // ç§»é¤åä¼äººå |
| | | const removeParticipant = participantId => { |
| | | const index = meetingForm.value.participants.indexOf(participantId); |
| | | if (index > -1) { |
| | | meetingForm.value.participants.splice(index, 1); |
| | | } |
| | | }; |
| | | |
| | | // 忥æ¹å¼é项 |
| | | const syncMethods = [ |
| | | { label: "ä¼ä¸å¾®ä¿¡", value: "wechat" }, |
| | | { label: "éé", value: "dingtalk" }, |
| | | { label: "é®ä»¶", value: "email" }, |
| | | { label: "çä¿¡", value: "sms" }, |
| | | ]; |
| | | |
| | | // ä¼è®®å¹³å°é项 |
| | | const meetingPlatforms = [ |
| | | { label: "ä¼ä¸å¾®ä¿¡ä¼è®®", value: "wechat" }, |
| | | { label: "ééä¼è®®", value: "dingtalk" }, |
| | | { label: "è
¾è®¯ä¼è®®", value: "tencent" }, |
| | | { 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)]; |
| | | |
| | | // çæéæºæ é¢ |
| | | 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)] |
| | | ); |
| | | |
| | | // éæºç¶æ |
| | | 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 newNotification = { |
| | | id: newId, |
| | | title: title, |
| | | type: randomType.type, |
| | | priority: randomPriority, |
| | | status: randomStatus, |
| | | content: `è¿æ¯${title}ç详ç»å
容ï¼è¯·ç¸å
³äººåæ³¨ææ¥ç...`, |
| | | departments: [randomDept], |
| | | expireDate: new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000) |
| | | .toISOString() |
| | | .split("T")[0], // 30天åè¿æ |
| | | syncMethods: ["wechat", "dingtalk"], |
| | | createTime: now.toLocaleString(), |
| | | }; |
| | | |
| | | // æ·»å å°æ°æ®å¼å¤´ |
| | | mockData.unshift(newNotification); |
| | | |
| | | // ä¿ææ°æ®éå¨åçèå´å
ï¼æå¤ä¿ç20æ¡ï¼ |
| | | if (mockData.length > 20) { |
| | | mockData = mockData.slice(0, 20); |
| | | } |
| | | |
| | | console.log(`[${new Date().toLocaleString()}] èªå¨çææ°éç¥: ${title}`); |
| | | }; |
| | | |
| | | // çå½å¨æ |
| | | onMounted(() => { |
| | | getList(); |
| | | getEmployeesList(); // è·ååå·¥å表 |
| | | startAutoRefresh(); |
| | | }); |
| | | |
| | | // å¼å§èªå¨å·æ° |
| | | const startAutoRefresh = () => { |
| | | setInterval(() => { |
| | | generateNewData(); |
| | | getList(); |
| | | }, 600000); // 10åéå·æ°ä¸æ¬¡ (10 * 60 * 1000 = 600000ms) |
| | | }; |
| | | |
| | | // æ¥è¯¢æ°æ® |
| | | const handleQuery = () => { |
| | | page.value.current = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | listNotification({ ...page.value, ...searchForm.value }) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | page.value.total = res.data.total; |
| | | }) |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | // å页å¤ç |
| | | const pagination = obj => { |
| | | page.value.current = obj.page; |
| | | page.value.size = obj.limit; |
| | | handleQuery(); |
| | | }; |
| | | |
| | | // éæ©ååå¤ç |
| | | const handleSelectionChange = selection => { |
| | | selectedIds.value = selection.map(item => item.id); |
| | | }; |
| | | |
| | | // æå¼è¡¨å |
| | | const openForm = (type, row = null) => { |
| | | dialogType.value = type; |
| | | if (type === "add") { |
| | | dialogTitle.value = "æ°å¢éç¥"; |
| | | // é置表å |
| | | Object.assign(form.value, { |
| | | id: "", |
| | | title: "", |
| | | type: "", |
| | | priority: "", |
| | | content: "", |
| | | departments: [], |
| | | expireDate: "", |
| | | status: "draft", |
| | | syncMethods: [], |
| | | }); |
| | | } else if (type === "edit" && row) { |
| | | dialogTitle.value = "ç¼è¾éç¥"; |
| | | Object.assign(form.value, { |
| | | id: row.id, |
| | | title: row.title, |
| | | type: row.type, |
| | | priority: row.priority, |
| | | content: row.content || "", |
| | | departments: row.departments || [], |
| | | expireDate: row.expireDate || "", |
| | | status: row.status, |
| | | syncMethods: row.syncMethods || [], |
| | | }); |
| | | } |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | // æå¼å¨çº¿ä¼è®®å¼¹çª |
| | | const openMeetingDialog = () => { |
| | | // é置表å |
| | | Object.assign(meetingForm.value, { |
| | | title: "", |
| | | startTime: "", |
| | | duration: 60, |
| | | participants: [], |
| | | description: "", |
| | | platform: "wechat", |
| | | }); |
| | | meetingDialogVisible.value = true; |
| | | }; |
| | | |
| | | // æå¼æä»¶å
±äº«å¼¹çª |
| | | const openFileShareDialog = () => { |
| | | // é置表å |
| | | Object.assign(fileShareForm.value, { |
| | | title: "", |
| | | description: "", |
| | | departments: [], |
| | | files: [], |
| | | }); |
| | | fileList.value = []; |
| | | fileShareDialogVisible.value = true; |
| | | }; |
| | | |
| | | // æå¨å·æ°æ°æ® |
| | | const manualRefresh = () => { |
| | | generateNewData(); |
| | | getList(); |
| | | ElMessage.success("æå¨å·æ°å®æï¼å·²çææ°éç¥"); |
| | | }; |
| | | |
| | | // æäº¤éç¥è¡¨å |
| | | const submitForm = async () => { |
| | | try { |
| | | await formRef.value.validate(); |
| | | |
| | | if (dialogType.value === "add") { |
| | | // æ°å¢éç¥ |
| | | addNotification({ ...form.value }) |
| | | .then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("æ·»å æå"); |
| | | dialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | } else { |
| | | // ç¼è¾éç¥ |
| | | updateNotification({ ...form.value }) |
| | | .then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("æ´æ°æå"); |
| | | dialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | } |
| | | } catch (error) { |
| | | console.error("表åéªè¯å¤±è´¥:", error); |
| | | } |
| | | }; |
| | | |
| | | // å建ä¼è®® |
| | | const createMeeting = async () => { |
| | | try { |
| | | await meetingFormRef.value.validate(); |
| | | |
| | | // 模æå建ä¼è®® |
| | | const meetingInfo = { |
| | | title: meetingForm.value.title, |
| | | startTime: meetingForm.value.startTime, |
| | | duration: meetingForm.value.duration, |
| | | participants: meetingForm.value.participants, |
| | | description: meetingForm.value.description, |
| | | platform: meetingForm.value.platform, |
| | | }; |
| | | // æ°å¢ä¼è®® |
| | | addOnlineMeeting({ ...meetingInfo }) |
| | | .then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("ä¼è®®æ·»å æå"); |
| | | meetingDialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }) |
| | | .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 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); |
| | | |
| | | // å°ä¼è®®ä¿¡æ¯æ·»å å°éç¥å表 |
| | | const meetingNotification = { |
| | | title: `[ä¼è®®éç¥] ${meetingInfo.title}`, |
| | | type: "meeting", |
| | | priority: "high", |
| | | status: "published", |
| | | content: `ä¼è®®æ¶é´: ${meetingInfo.startTime}ï¼æ¶é¿: ${ |
| | | meetingInfo.duration |
| | | }åéï¼å¹³å°: ${ |
| | | meetingPlatforms.find(p => p.value === meetingForm.value.platform) |
| | | ?.label || "æªç¥å¹³å°" |
| | | }ï¼åä¼äººå: ${participantNames}ï¼å
±${participantDetails.length}人`, |
| | | departments: [], |
| | | expireDate: "", |
| | | syncMethods: [meetingForm.value.platform], |
| | | }; |
| | | addNotification({ ...meetingNotification }) |
| | | .then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("æ·»å æå"); |
| | | // dialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | // mockData.unshift(meetingNotification); |
| | | // getList(); |
| | | } catch (error) { |
| | | console.error("ä¼è®®è¡¨åéªè¯å¤±è´¥:", error); |
| | | } |
| | | }; |
| | | |
| | | // æä»¶ä¸ä¼ å¤ç |
| | | const handleFileChange = file => { |
| | | const isLt10M = file.size / 1024 / 1024 < 10; |
| | | if (!isLt10M) { |
| | | ElMessage.error("ä¸ä¼ æä»¶å¤§å°ä¸è½è¶
è¿ 10MB!"); |
| | | return false; |
| | | } |
| | | |
| | | const fileInfo = { |
| | | name: file.name, |
| | | size: file.size, |
| | | type: file.type, |
| | | uid: file.uid, |
| | | }; |
| | | |
| | | fileList.value.push(fileInfo); |
| | | fileShareForm.value.files.push(fileInfo.name); |
| | | return false; // 黿¢èªå¨ä¸ä¼ |
| | | }; |
| | | |
| | | // ç§»é¤æä»¶ |
| | | 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 |
| | | ); |
| | | if (index2 !== -1) { |
| | | fileShareForm.value.files.splice(index2, 1); |
| | | } |
| | | fileList.value.splice(index, 1); |
| | | } |
| | | }; |
| | | |
| | | // å
±äº«æä»¶ |
| | | const shareFiles = async () => { |
| | | try { |
| | | await fileShareFormRef.value.validate(); |
| | | |
| | | if (fileShareForm.value.files.length === 0) { |
| | | ElMessage.warning("请è³å°éæ©ä¸ä¸ªæä»¶"); |
| | | return; |
| | | } |
| | | |
| | | // 模ææä»¶å
񄧮 |
| | | const shareInfo = { |
| | | title: fileShareForm.value.title, |
| | | description: fileShareForm.value.description, |
| | | departments: fileShareForm.value.departments, |
| | | files: fileShareForm.value.files, |
| | | }; |
| | | addFileSharing({ ...shareInfo }) |
| | | .then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("æä»¶å
±äº«æå"); |
| | | fileShareDialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | |
| | | // ElMessage.success(`æä»¶å
±äº«æåï¼å
±äº«ID: ${shareInfo.shareId}ï¼å·²éç¥ç¸å
³é¨é¨`); |
| | | |
| | | // å°æä»¶å
±äº«ä¿¡æ¯æ·»å å°éç¥å表 |
| | | const fileShareNotification = { |
| | | title: `[æä»¶å
񄧮] ${shareInfo.title}`, |
| | | type: "temporary", |
| | | priority: "medium", |
| | | status: "published", |
| | | content: `å
±äº«æè¿°: ${shareInfo.description}ï¼æä»¶æ°é: ${shareInfo.files.length}个`, |
| | | departments: shareInfo.departments, |
| | | expireDate: "", |
| | | syncMethods: ["wechat", "dingtalk"], |
| | | }; |
| | | addNotification({ ...fileShareNotification }) |
| | | .then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("æ·»å æå"); |
| | | // dialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | |
| | | // mockData.unshift(fileShareNotification); |
| | | // getList(); |
| | | } catch (error) { |
| | | console.error("æä»¶å
±äº«è¡¨åéªè¯å¤±è´¥:", error); |
| | | } |
| | | }; |
| | | |
| | | // åå¸éç¥ |
| | | 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 || [], |
| | | }); |
| | | } |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | // æå¼å¨çº¿ä¼è®®å¼¹çª |
| | | const openMeetingDialog = () => { |
| | | // é置表å |
| | | Object.assign(meetingForm.value, { |
| | | title: "", |
| | | startTime: "", |
| | | duration: 60, |
| | | participants: [], |
| | | description: "", |
| | | platform: "wechat" |
| | | }); |
| | | meetingDialogVisible.value = true; |
| | | }; |
| | | |
| | | // æå¼æä»¶å
±äº«å¼¹çª |
| | | const openFileShareDialog = () => { |
| | | // é置表å |
| | | Object.assign(fileShareForm.value, { |
| | | title: "", |
| | | description: "", |
| | | departments: [], |
| | | files: [] |
| | | }); |
| | | fileList.value = []; |
| | | fileShareDialogVisible.value = true; |
| | | }; |
| | | |
| | | // æå¨å·æ°æ°æ® |
| | | const manualRefresh = () => { |
| | | generateNewData(); |
| | | getList(); |
| | | ElMessage.success("æå¨å·æ°å®æï¼å·²çææ°éç¥"); |
| | | }; |
| | | |
| | | // æäº¤éç¥è¡¨å |
| | | const submitForm = async () => { |
| | | try { |
| | | await formRef.value.validate(); |
| | | |
| | | if (dialogType.value === "add") { |
| | | // æ°å¢éç¥ |
| | | addNotification({...form.value}).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("æ·»å æå"); |
| | | dialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | } else { |
| | | // ç¼è¾éç¥ |
| | | updateNotification({...form.value}).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("æ´æ°æå"); |
| | | dialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | } |
| | | } catch (error) { |
| | | console.error("表åéªè¯å¤±è´¥:", error); |
| | | } |
| | | }; |
| | | |
| | | // å建ä¼è®® |
| | | const createMeeting = async () => { |
| | | try { |
| | | await meetingFormRef.value.validate(); |
| | | |
| | | // 模æå建ä¼è®® |
| | | const meetingInfo = { |
| | | title: meetingForm.value.title, |
| | | startTime: meetingForm.value.startTime, |
| | | duration: meetingForm.value.duration, |
| | | participants: meetingForm.value.participants, |
| | | description: meetingForm.value.description, |
| | | platform: meetingForm.value.platform |
| | | }; |
| | | // æ°å¢ä¼è®® |
| | | addOnlineMeeting({...meetingInfo}).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("ä¼è®®æ·»å æå"); |
| | | meetingDialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }).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 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); |
| | | |
| | | // å°ä¼è®®ä¿¡æ¯æ·»å å°éç¥å表 |
| | | const meetingNotification = { |
| | | title: `[ä¼è®®éç¥] ${meetingInfo.title}`, |
| | | type: "meeting", |
| | | priority: "high", |
| | | status: "published", |
| | | content: `ä¼è®®æ¶é´: ${meetingInfo.startTime}ï¼æ¶é¿: ${meetingInfo.duration}åéï¼å¹³å°: ${meetingPlatforms.find(p => p.value === meetingForm.value.platform)?.label || "æªç¥å¹³å°"}ï¼åä¼äººå: ${participantNames}ï¼å
±${participantDetails.length}人`, |
| | | departments: [], |
| | | expireDate: "", |
| | | syncMethods: [meetingForm.value.platform] |
| | | }; |
| | | addNotification({...meetingNotification}).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("æ·»å æå"); |
| | | // dialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | // mockData.unshift(meetingNotification); |
| | | // getList(); |
| | | } catch (error) { |
| | | console.error("ä¼è®®è¡¨åéªè¯å¤±è´¥:", error); |
| | | } |
| | | }; |
| | | |
| | | // æä»¶ä¸ä¼ å¤ç |
| | | const handleFileChange = (file) => { |
| | | const isLt10M = file.size / 1024 / 1024 < 10; |
| | | if (!isLt10M) { |
| | | ElMessage.error("ä¸ä¼ æä»¶å¤§å°ä¸è½è¶
è¿ 10MB!"); |
| | | return false; |
| | | } |
| | | |
| | | const fileInfo = { |
| | | name: file.name, |
| | | size: file.size, |
| | | type: file.type, |
| | | uid: file.uid |
| | | }; |
| | | |
| | | fileList.value.push(fileInfo); |
| | | fileShareForm.value.files.push(fileInfo.name); |
| | | return false; // 黿¢èªå¨ä¸ä¼ |
| | | }; |
| | | |
| | | // ç§»é¤æä»¶ |
| | | 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); |
| | | if (index2 !== -1) { |
| | | fileShareForm.value.files.splice(index2, 1); |
| | | } |
| | | fileList.value.splice(index, 1); |
| | | } |
| | | }; |
| | | |
| | | // å
±äº«æä»¶ |
| | | const shareFiles = async () => { |
| | | try { |
| | | await fileShareFormRef.value.validate(); |
| | | |
| | | if (fileShareForm.value.files.length === 0) { |
| | | ElMessage.warning("请è³å°éæ©ä¸ä¸ªæä»¶"); |
| | | return; |
| | | } |
| | | |
| | | // 模ææä»¶å
񄧮 |
| | | const shareInfo = { |
| | | title: fileShareForm.value.title, |
| | | description: fileShareForm.value.description, |
| | | departments: fileShareForm.value.departments, |
| | | files: fileShareForm.value.files, |
| | | }; |
| | | addFileSharing({...shareInfo}).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("æä»¶å
±äº«æå"); |
| | | fileShareDialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | |
| | | // ElMessage.success(`æä»¶å
±äº«æåï¼å
±äº«ID: ${shareInfo.shareId}ï¼å·²éç¥ç¸å
³é¨é¨`); |
| | | |
| | | |
| | | // å°æä»¶å
±äº«ä¿¡æ¯æ·»å å°éç¥å表 |
| | | const fileShareNotification = { |
| | | title: `[æä»¶å
񄧮] ${shareInfo.title}`, |
| | | type: "temporary", |
| | | priority: "medium", |
| | | status: "published", |
| | | content: `å
±äº«æè¿°: ${shareInfo.description}ï¼æä»¶æ°é: ${shareInfo.files.length}个`, |
| | | departments: shareInfo.departments, |
| | | expireDate: "", |
| | | syncMethods: ["wechat", "dingtalk"], |
| | | }; |
| | | addNotification({...fileShareNotification}).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("æ·»å æå"); |
| | | // dialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | |
| | | // mockData.unshift(fileShareNotification); |
| | | // getList(); |
| | | } catch (error) { |
| | | console.error("æä»¶å
±äº«è¡¨åéªè¯å¤±è´¥:", error); |
| | | } |
| | | }; |
| | | |
| | | // åå¸éç¥ |
| | | const publishNotification = (row) => { |
| | | Object.assign(form.value, { |
| | | id: row.id, |
| | | title: row.title, |
| | | type: row.type, |
| | | priority: row.priority, |
| | | content: row.content || "", |
| | | departments: row.departments || [], |
| | | expireDate: row.expireDate || "", |
| | | status: row.status, |
| | | syncMethods: row.syncMethods || [] |
| | | }); |
| | | form.value.status = "published"; |
| | | updateNotification({...form.value}).then(res => { |
| | | if(res.code == 200){ |
| | | form.value.status = "published"; |
| | | 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, |
| | | type: row.type, |
| | | priority: row.priority, |
| | | content: row.content || "", |
| | | departments: row.departments || [], |
| | | expireDate: row.expireDate || "", |
| | | status: row.status, |
| | | syncMethods: row.syncMethods || [] |
| | | }); |
| | | form.value.status = "draft"; |
| | | updateNotification({...form.value}).then(res => { |
| | | if(res.code == 200){ |
| | | id: row.id, |
| | | title: row.title, |
| | | type: row.type, |
| | | priority: row.priority, |
| | | content: row.content || "", |
| | | departments: row.departments || [], |
| | | expireDate: row.expireDate || "", |
| | | status: row.status, |
| | | syncMethods: row.syncMethods || [], |
| | | }); |
| | | form.value.status = "draft"; |
| | | 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 handleDelete = () => { |
| | | let ids = []; |
| | | if (selectedIds.value.length > 0) { |
| | | ids = selectedIds.value; |
| | | }else{ |
| | | ElMessage.warning("è¯·éæ©è¦å é¤çéç¥"); |
| | | return; |
| | | } |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "å é¤", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).then(() => { |
| | | delNotification(ids).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("å 餿å"); |
| | | selectedIds.value = []; |
| | | getList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | // å é¤éç¥ |
| | | const handleDelete = () => { |
| | | let ids = []; |
| | | if (selectedIds.value.length > 0) { |
| | | ids = selectedIds.value; |
| | | } else { |
| | | ElMessage.warning("è¯·éæ©è¦å é¤çéç¥"); |
| | | return; |
| | | } |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "å é¤", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | }).catch(() => { |
| | | // ç¨æ·åæ¶ |
| | | }); |
| | | }; |
| | | .then(() => { |
| | | delNotification(ids) |
| | | .then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("å 餿å"); |
| | | selectedIds.value = []; |
| | | getList(); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | // ç¨æ·åæ¶ |
| | | }); |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .auto-refresh-info { |
| | | margin-bottom: 15px; |
| | | } |
| | | .auto-refresh-info { |
| | | margin-bottom: 15px; |
| | | } |
| | | |
| | | .auto-refresh-info .el-alert { |
| | | border-radius: 8px; |
| | | } |
| | | .auto-refresh-info .el-alert { |
| | | border-radius: 8px; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | text-align: right; |
| | | } |
| | | .dialog-footer { |
| | | text-align: right; |
| | | } |
| | | |
| | | .el-upload__tip { |
| | | color: #909399; |
| | | font-size: 12px; |
| | | margin-top: 8px; |
| | | } |
| | | .el-upload__tip { |
| | | color: #909399; |
| | | font-size: 12px; |
| | | margin-top: 8px; |
| | | } |
| | | |
| | | .el-checkbox-group { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 10px; |
| | | } |
| | | .el-checkbox-group { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 10px; |
| | | } |
| | | |
| | | .el-checkbox { |
| | | margin-right: 0; |
| | | } |
| | | .el-checkbox { |
| | | margin-right: 0; |
| | | } |
| | | </style> |
| | |
| | | <!-- 页颿 é¢ --> |
| | | <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" |
| | | type="date" |
| | | placeholder="è¯·éæ©ä¼è®®æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | style="width: 100%" |
| | | /> |
| | | <el-date-picker v-model="searchForm.meetingDate" |
| | | type="date" |
| | | placeholder="è¯·éæ©ä¼è®®æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | 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" |
| | | :total="total" |
| | | v-model:page="queryParams.current" |
| | | v-model:limit="queryParams.size" |
| | | @pagination="getList" |
| | | /> |
| | | <pagination v-show="total > 0" |
| | | :total="total" |
| | | v-model:page="queryParams.current" |
| | | v-model:limit="queryParams.size" |
| | | @pagination="getList" /> |
| | | </el-card> |
| | | |
| | | <!-- ä¼è®®è稿详æ
å¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | title="ä¼è®®è稿详æ
" |
| | | v-model="detailDialogVisible" |
| | | width="800px" |
| | | > |
| | | <el-dialog title="ä¼è®®è稿详æ
" |
| | | v-model="detailDialogVisible" |
| | | 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" |
| | | 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="请è¾å
¥ä¼è®®ä¸»é¢" /> |
| | | <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="请è¾å
¥ä¼è®®ä¸»é¢" /> |
| | | </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" |
| | | type="date" |
| | | placeholder="è¯·éæ©ä¼è®®æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | :disabled-date="disabledDate" |
| | | style="width: 100%" |
| | | /> |
| | | <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%" /> |
| | | </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" |
| | | placeholder="è¯·éæ©å¼å§æ¶é´" |
| | | style="width: 100%" |
| | | > |
| | | <el-option |
| | | v-for="time in timeOptions" |
| | | :key="time.value" |
| | | :label="time.label" |
| | | :value="time.value" |
| | | /> |
| | | <el-form-item label="å¼å§æ¶é´" |
| | | prop="startTime"> |
| | | <el-select v-model="meetingForm.startTime" |
| | | placeholder="è¯·éæ©å¼å§æ¶é´" |
| | | style="width: 100%"> |
| | | <el-option v-for="time in timeOptions" |
| | | :key="time.value" |
| | | :label="time.label" |
| | | :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" |
| | | placeholder="è¯·éæ©ç»ææ¶é´" |
| | | style="width: 100%" |
| | | > |
| | | <el-option |
| | | v-for="time in timeOptions" |
| | | :key="time.value" |
| | | :label="time.label" |
| | | :value="time.value" |
| | | /> |
| | | <el-form-item label="ç»ææ¶é´" |
| | | prop="endTime"> |
| | | <el-select v-model="meetingForm.endTime" |
| | | placeholder="è¯·éæ©ç»ææ¶é´" |
| | | style="width: 100%"> |
| | | <el-option v-for="time in timeOptions" |
| | | :key="time.value" |
| | | :label="time.label" |
| | | :value="time.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-form-item label="åä¼äººæ°" prop="participants"> |
| | | <el-input |
| | | v-model="meetingForm.participants" |
| | | type="number" |
| | | placeholder="请è¾å
¥åä¼äººæ°" |
| | | /> |
| | | <el-form-item label="åä¼äººæ°" |
| | | prop="participants"> |
| | | <el-input v-model="meetingForm.participants" |
| | | type="number" |
| | | placeholder="请è¾å
¥åä¼äººæ°" /> |
| | | </el-form-item> |
| | | <el-form-item label="åä¼äººå" prop="participants"> |
| | | <el-input |
| | | v-model="meetingForm.participantList" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥åä¼äººåï¼ç¨éå·åé" |
| | | /> |
| | | <el-form-item label="åä¼äººå" |
| | | prop="participants"> |
| | | <el-input v-model="meetingForm.participantList" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥åä¼äººåï¼ç¨éå·åé" /> |
| | | </el-form-item> |
| | | <el-form-item label="ä¼è®®è¯´æ"> |
| | | <el-input |
| | | v-model="meetingForm.description" |
| | | type="textarea" |
| | | :rows="4" |
| | | placeholder="请è¾å
¥ä¼è®®è¯´æ" |
| | | /> |
| | | <el-input v-model="meetingForm.description" |
| | | type="textarea" |
| | | :rows="4" |
| | | 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 dayjs from "dayjs"; |
| | | // æ°æ®å表å è½½ç¶æ |
| | | const loading = ref(false) |
| | | 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 total = ref(0) |
| | | // æ»æ¡æ° |
| | | const total = ref(0); |
| | | |
| | | // è稿åè¡¨æ°æ® |
| | | const draftList = ref([]) |
| | | // è稿åè¡¨æ°æ® |
| | | const draftList = ref([]); |
| | | |
| | | // æ¥è¯¢åæ° |
| | | const queryParams = reactive({ |
| | | current: 1, |
| | | size: 10 |
| | | }) |
| | | // æ¥è¯¢åæ° |
| | | const queryParams = reactive({ |
| | | current: 1, |
| | | size: 10, |
| | | }); |
| | | |
| | | // æç´¢è¡¨å |
| | | const searchForm = reactive({ |
| | | title: '', |
| | | meetingDate: '' |
| | | }) |
| | | // æç´¢è¡¨å |
| | | const searchForm = reactive({ |
| | | 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([]) |
| | | // æ¶é´é项ï¼ä»¥åå°æ¶ä¸ºé´éï¼å·¥ä½æ¶é´8:00-18:00ï¼ |
| | | const timeOptions = ref([]); |
| | | |
| | | // è¡¨åæ°æ® |
| | | const meetingForm = reactive({ |
| | | id: '', |
| | | meetingId: '', |
| | | title: '', |
| | | roomId: '', |
| | | host: '', |
| | | meetingDate: '', |
| | | startTime: '', |
| | | endTime: '', |
| | | participants: 0, |
| | | 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' }] |
| | | } |
| | | |
| | | // åå§åæ¶é´é项ï¼ä»¥åå°æ¶ä¸ºé´éï¼å·¥ä½æ¶é´8:00-18:00ï¼ |
| | | const initTimeOptions = () => { |
| | | 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` |
| | | }) |
| | | |
| | | if (hour < 18) { // 18:00ä¹å没æåç¹é项 |
| | | options.push({ |
| | | value: `${hour.toString().padStart(2, '0')}:30`, |
| | | label: `${hour.toString().padStart(2, '0')}:30` |
| | | }) |
| | | } |
| | | } |
| | | timeOptions.value = options |
| | | } |
| | | |
| | | // ç¦ç¨æ¥æï¼ç¦ç¨ä»å¤©ä¹åçæ¥æï¼ |
| | | const disabledDate = (time) => { |
| | | // ç¦ç¨ä»å¤©ä¹åçæ¥æ |
| | | return time.getTime() < Date.now() - 86400000 |
| | | } |
| | | |
| | | // æ¥è¯¢æ°æ® |
| | | const getList = async () => { |
| | | loading.value = true |
| | | |
| | | 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 |
| | | }) |
| | | |
| | | loading.value = false |
| | | |
| | | } |
| | | |
| | | // æç´¢æé®æä½ |
| | | const handleSearch = () => { |
| | | queryParams.pageNum = 1 |
| | | getList() |
| | | } |
| | | |
| | | // éç½®æç´¢è¡¨å |
| | | const resetSearch = () => { |
| | | Object.assign(searchForm, { |
| | | title: '', |
| | | createTime: [] |
| | | }) |
| | | handleSearch() |
| | | } |
| | | |
| | | // æ·»å æé®æä½ |
| | | const handleAdd = () => { |
| | | dialogTitle.value = 'æ°å»ºè稿' |
| | | resetForm() |
| | | editDialogVisible.value = true |
| | | } |
| | | |
| | | // æ¥çè稿详æ
|
| | | const viewDraft = (row) => { |
| | | currentDraft.value = row |
| | | detailDialogVisible.value = true |
| | | } |
| | | |
| | | // ç¼è¾è稿 |
| | | const editDraft = (row) => { |
| | | dialogTitle.value = 'ç¼è¾è稿' |
| | | Object.assign(meetingForm, { |
| | | id: row.id, |
| | | meetingId: row.meetingId, |
| | | title: row.title, |
| | | room: row.room, |
| | | roomId: row.id, |
| | | host: row.host, |
| | | 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 |
| | | } |
| | | |
| | | // å é¤è稿 |
| | | const deleteDraft = (row) => { |
| | | ElMessageBox.confirm( |
| | | `确认å é¤ä¼è®®è稿 "${row.title}"?`, |
| | | 'å é¤è稿', |
| | | { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | } |
| | | ).then(() => { |
| | | delDraft(row.id).then(resp=>{ |
| | | ElMessage.success('è稿å 餿å') |
| | | getList() |
| | | }) |
| | | |
| | | }).catch(() => {}) |
| | | } |
| | | |
| | | // é置表å |
| | | const resetForm = () => { |
| | | Object.assign(meetingForm, { |
| | | id: '', |
| | | meetingId: '', |
| | | title: '', |
| | | room: '', |
| | | host: '', |
| | | meetingDate: '', |
| | | startTime: '', |
| | | endTime: '', |
| | | // è¡¨åæ°æ® |
| | | const meetingForm = reactive({ |
| | | id: "", |
| | | meetingId: "", |
| | | title: "", |
| | | roomId: "", |
| | | host: "", |
| | | meetingDate: "", |
| | | startTime: "", |
| | | endTime: "", |
| | | participants: 0, |
| | | participantList: '', |
| | | description: '', |
| | | createTime: '' |
| | | }) |
| | | } |
| | | participantList: "", |
| | | description: "", |
| | | createTime: "", |
| | | }); |
| | | |
| | | // æäº¤è¡¨å |
| | | const submitForm = () => { |
| | | 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") |
| | | saveDraft(formData).then(()=>{ |
| | | ElMessage.success('ä¿åæå') |
| | | editDialogVisible.value = false |
| | | getList() |
| | | }) |
| | | // è¡¨åæ ¡éªè§å |
| | | 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" }], |
| | | }; |
| | | |
| | | // åå§åæ¶é´é项ï¼ä»¥åå°æ¶ä¸ºé´éï¼å·¥ä½æ¶é´8:00-18:00ï¼ |
| | | const initTimeOptions = () => { |
| | | 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`, |
| | | }); |
| | | |
| | | if (hour < 18) { |
| | | // 18:00ä¹å没æåç¹é项 |
| | | options.push({ |
| | | value: `${hour.toString().padStart(2, "0")}:30`, |
| | | label: `${hour.toString().padStart(2, "0")}:30`, |
| | | }); |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | timeOptions.value = options; |
| | | }; |
| | | |
| | | // æ ¼å¼åæ¥ææ¶é´ |
| | | const formatDateTime = (dateTime) => { |
| | | if (!dateTime) return '' |
| | | return dateTime.replace(' ', '\n') |
| | | } |
| | | // ç¦ç¨æ¥æï¼ç¦ç¨ä»å¤©ä¹åçæ¥æï¼ |
| | | const disabledDate = time => { |
| | | // ç¦ç¨ä»å¤©ä¹åçæ¥æ |
| | | return time.getTime() < Date.now() - 86400000; |
| | | }; |
| | | |
| | | // 页é¢å è½½æ¶è·åæ°æ® |
| | | onMounted(() => { |
| | | initTimeOptions() |
| | | getList() |
| | | getRoomEnum().then((res) => { |
| | | roomList.value = res.data |
| | | }) |
| | | }) |
| | | // æ¥è¯¢æ°æ® |
| | | const getList = async () => { |
| | | loading.value = true; |
| | | |
| | | 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; |
| | | }); |
| | | |
| | | loading.value = false; |
| | | }; |
| | | |
| | | // æç´¢æé®æä½ |
| | | const handleSearch = () => { |
| | | queryParams.pageNum = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | // éç½®æç´¢è¡¨å |
| | | const resetSearch = () => { |
| | | Object.assign(searchForm, { |
| | | title: "", |
| | | createTime: [], |
| | | }); |
| | | handleSearch(); |
| | | }; |
| | | |
| | | // æ·»å æé®æä½ |
| | | const handleAdd = () => { |
| | | dialogTitle.value = "æ°å»ºè稿"; |
| | | resetForm(); |
| | | editDialogVisible.value = true; |
| | | }; |
| | | |
| | | // æ¥çè稿详æ
|
| | | const viewDraft = row => { |
| | | currentDraft.value = row; |
| | | detailDialogVisible.value = true; |
| | | }; |
| | | |
| | | // ç¼è¾è稿 |
| | | const editDraft = row => { |
| | | dialogTitle.value = "ç¼è¾è稿"; |
| | | Object.assign(meetingForm, { |
| | | id: row.id, |
| | | meetingId: row.meetingId, |
| | | title: row.title, |
| | | room: row.room, |
| | | roomId: row.id, |
| | | host: row.host, |
| | | 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; |
| | | }; |
| | | |
| | | // å é¤è稿 |
| | | const deleteDraft = row => { |
| | | ElMessageBox.confirm(`确认å é¤ä¼è®®è稿 "${row.title}"?`, "å é¤è稿", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | delDraft(row.id).then(resp => { |
| | | ElMessage.success("è稿å 餿å"); |
| | | getList(); |
| | | }); |
| | | }) |
| | | .catch(() => {}); |
| | | }; |
| | | |
| | | // é置表å |
| | | const resetForm = () => { |
| | | Object.assign(meetingForm, { |
| | | id: "", |
| | | meetingId: "", |
| | | title: "", |
| | | room: "", |
| | | host: "", |
| | | meetingDate: "", |
| | | startTime: "", |
| | | endTime: "", |
| | | participants: 0, |
| | | participantList: "", |
| | | description: "", |
| | | createTime: "", |
| | | }); |
| | | }; |
| | | |
| | | // æäº¤è¡¨å |
| | | const submitForm = () => { |
| | | 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"); |
| | | saveDraft(formData).then(() => { |
| | | ElMessage.success("ä¿åæå"); |
| | | editDialogVisible.value = false; |
| | | getList(); |
| | | }); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // æ ¼å¼åæ¥ææ¶é´ |
| | | const formatDateTime = dateTime => { |
| | | if (!dateTime) return ""; |
| | | return dateTime.replace(" ", "\n"); |
| | | }; |
| | | |
| | | // 页é¢å è½½æ¶è·åæ°æ® |
| | | onMounted(() => { |
| | | initTimeOptions(); |
| | | getList(); |
| | | getRoomEnum().then(res => { |
| | | roomList.value = res.data; |
| | | }); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .app-container { |
| | | padding: 20px; |
| | | } |
| | | .app-container { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .page-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 20px; |
| | | } |
| | | .page-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .page-header h2 { |
| | | margin: 0; |
| | | color: #303133; |
| | | } |
| | | .page-header h2 { |
| | | margin: 0; |
| | | color: #303133; |
| | | } |
| | | |
| | | .search-card { |
| | | margin-bottom: 20px; |
| | | } |
| | | .search-card { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | gap: 10px; |
| | | } |
| | | .dialog-footer { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | gap: 10px; |
| | | } |
| | | |
| | | .content-section h4 { |
| | | margin: 0 0 15px 0; |
| | | color: #303133; |
| | | } |
| | | .content-section h4 { |
| | | margin: 0 0 15px 0; |
| | | color: #303133; |
| | | } |
| | | |
| | | .mt-20 { |
| | | margin-top: 20px; |
| | | } |
| | | .mt-20 { |
| | | margin-top: 20px; |
| | | } |
| | | |
| | | .participants-list { |
| | | min-height: 40px; |
| | | padding: 15px; |
| | | border-radius: 4px; |
| | | line-height: 1.6; |
| | | } |
| | | .participants-list { |
| | | min-height: 40px; |
| | | padding: 15px; |
| | | border-radius: 4px; |
| | | line-height: 1.6; |
| | | } |
| | | |
| | | .meeting-description { |
| | | padding: 15px; |
| | | border-radius: 4px; |
| | | line-height: 1.6; |
| | | white-space: pre-wrap; |
| | | } |
| | | .meeting-description { |
| | | padding: 15px; |
| | | border-radius: 4px; |
| | | line-height: 1.6; |
| | | white-space: pre-wrap; |
| | | } |
| | | </style> |
| | |
| | | <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'" |
| | | type="primary" |
| | | link |
| | | @click="handleApproval(scope.row)" |
| | | > |
| | | <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)"> |
| | | åå¸ |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <!-- å页 --> |
| | | <pagination |
| | | v-show="total > 0" |
| | | :total="total" |
| | | v-model:page="queryParams.current" |
| | | v-model:limit="queryParams.size" |
| | | @pagination="getList" |
| | | /> |
| | | <pagination v-show="total > 0" |
| | | :total="total" |
| | | v-model:page="queryParams.current" |
| | | v-model:limit="queryParams.size" |
| | | @pagination="getList" /> |
| | | </el-card> |
| | | |
| | | <!-- ä¼è®®è¯¦æ
å¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | title="ä¼è®®è¯¦æ
" |
| | | v-model="detailDialogVisible" |
| | | width="800px" |
| | | > |
| | | <el-dialog title="ä¼è®®è¯¦æ
" |
| | | v-model="detailDialogVisible" |
| | | 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" |
| | | :key="participant.id" |
| | | style="margin-right: 10px; margin-bottom: 10px;" |
| | | > |
| | | <el-tag v-for="participant in currentMeeting.participants" |
| | | :key="participant.id" |
| | | 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" |
| | | :key="participant.id" |
| | | style="margin-right: 10px; margin-bottom: 10px;" |
| | | > |
| | | <el-tag v-for="participant in currentMeeting.participants" |
| | | :key="participant.id" |
| | | 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" |
| | | type="textarea" |
| | | placeholder="请è¾å
¥å叿è§" |
| | | :rows="4" |
| | | /> |
| | | <el-input v-model="publishComment" |
| | | type="textarea" |
| | | placeholder="请è¾å
¥å叿è§" |
| | | :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> |
| | | <!-- <el-button type="danger" @click="submitApproval('2')">ä¸éè¿</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 {getStaffOnJob} from "@/api/personnelManagement/onboarding.js"; |
| | | import dayjs from "dayjs"; |
| | | 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 approvalList = ref([]) |
| | | // æ»æ¡æ° |
| | | const total = ref(0); |
| | | const roomEnum = ref([]); |
| | | const staffList = ref([]); |
| | | // åå¸åè¡¨æ°æ® |
| | | const approvalList = ref([]); |
| | | |
| | | // æ¥è¯¢åæ° |
| | | const queryParams = reactive({ |
| | | current: 1, |
| | | size: 10 |
| | | }) |
| | | // æ¥è¯¢åæ° |
| | | const queryParams = reactive({ |
| | | current: 1, |
| | | size: 10, |
| | | }); |
| | | |
| | | // æç´¢è¡¨å |
| | | const searchForm = reactive({ |
| | | title: '', |
| | | applicant: '', |
| | | status: '' |
| | | }) |
| | | // æç´¢è¡¨å |
| | | const searchForm = reactive({ |
| | | 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}) |
| | | 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 => { |
| | | return { |
| | | id: staff.id, |
| | | name: `${staff.staffName}(${staff.postJob})` |
| | | } |
| | | }) |
| | | // æ¥è¯¢æ°æ® |
| | | const getList = async () => { |
| | | 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 => { |
| | | return { |
| | | id: staff.id, |
| | | 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(); |
| | | }; |
| | | |
| | | // æç´¢æé®æä½ |
| | | const handleSearch = () => { |
| | | queryParams.pageNum = 1 |
| | | getList() |
| | | } |
| | | // éç½®æç´¢è¡¨å |
| | | const resetSearch = () => { |
| | | Object.assign(searchForm, { |
| | | title: "", |
| | | applicant: "", |
| | | status: "", |
| | | }); |
| | | handleSearch(); |
| | | }; |
| | | |
| | | // éç½®æç´¢è¡¨å |
| | | const resetSearch = () => { |
| | | Object.assign(searchForm, { |
| | | 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 statusMap = { |
| | | 0: "info", // å¾
åå¸ |
| | | 1: "success", // å·²éè¿ |
| | | 2: "danger", // æªéè¿ |
| | | }; |
| | | return statusMap[status] || "info"; |
| | | }; |
| | | |
| | | // è·åç¶æç±»å |
| | | const getStatusType = (status) => { |
| | | const statusMap = { |
| | | '0': 'info', // å¾
åå¸ |
| | | '1': 'success', // å·²éè¿ |
| | | '2': 'danger', // æªéè¿ |
| | | } |
| | | return statusMap[status] || 'info' |
| | | } |
| | | // è·åç¶æææ¬ |
| | | const getStatusText = status => { |
| | | const statusMap = { |
| | | 0: "å¾
åå¸", |
| | | 1: "å·²åå¸", |
| | | 2: "已忶", |
| | | }; |
| | | return statusMap[status] || "æªç¥"; |
| | | }; |
| | | |
| | | // è·åç¶æææ¬ |
| | | const getStatusText = (status) => { |
| | | const statusMap = { |
| | | '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 => { |
| | | // if (status === 'approved' && !publishComment.value.trim()) { |
| | | // ElMessage.warning('请填åå叿è§') |
| | | // return |
| | | // } |
| | | |
| | | // æäº¤åå¸ |
| | | const submitApproval = (status) => { |
| | | // if (status === 'approved' && !publishComment.value.trim()) { |
| | | // ElMessage.warning('请填åå叿è§') |
| | | // return |
| | | // } |
| | | |
| | | ElMessageBox.confirm( |
| | | `确认${status === '1' ? 'åå¸' : 'åæ¶'}该ä¼è®®ï¼`, |
| | | 'åå¸ç¡®è®¤', |
| | | ElMessageBox.confirm( |
| | | `确认${status === "1" ? "åå¸" : "åæ¶"}该ä¼è®®ï¼`, |
| | | "åå¸ç¡®è®¤", |
| | | { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | } |
| | | ).then(() => { |
| | | saveMeetingApplication({ |
| | | id: currentMeeting.value.id, |
| | | publishStatus: status, |
| | | publishComment: publishComment.value |
| | | }).then(resp=>{ |
| | | // æ´æ°ä¼è®®ç¶æ |
| | | currentMeeting.value.status = status |
| | | ) |
| | | .then(() => { |
| | | saveMeetingApplication({ |
| | | id: currentMeeting.value.id, |
| | | publishStatus: status, |
| | | publishComment: publishComment.value, |
| | | }).then(resp => { |
| | | // æ´æ°ä¼è®®ç¶æ |
| | | 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; |
| | | |
| | | // 页é¢å è½½æ¶è·åæ°æ® |
| | | onMounted(async () => { |
| | | const [resp1, resp2]= await Promise.all([getRoomEnum(), getStaffOnJob()]) |
| | | roomEnum.value = resp1.data |
| | | staffList.value = resp2.data |
| | | |
| | | await getList() |
| | | }) |
| | | await getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .app-container { |
| | | padding: 20px; |
| | | } |
| | | .app-container { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .page-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 20px; |
| | | } |
| | | .page-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .page-header h2 { |
| | | margin: 0; |
| | | color: #303133; |
| | | } |
| | | .page-header h2 { |
| | | margin: 0; |
| | | color: #303133; |
| | | } |
| | | |
| | | .search-card { |
| | | margin-bottom: 20px; |
| | | } |
| | | .search-card { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | gap: 10px; |
| | | } |
| | | .dialog-footer { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | gap: 10px; |
| | | } |
| | | |
| | | .content-section h4 { |
| | | margin: 0 0 15px 0; |
| | | color: #303133; |
| | | } |
| | | .content-section h4 { |
| | | margin: 0 0 15px 0; |
| | | color: #303133; |
| | | } |
| | | |
| | | .mt-20 { |
| | | margin-top: 20px; |
| | | } |
| | | .mt-20 { |
| | | margin-top: 20px; |
| | | } |
| | | |
| | | .participants-list { |
| | | min-height: 40px; |
| | | padding: 15px; |
| | | border-radius: 4px; |
| | | line-height: 1.6; |
| | | } |
| | | .participants-list { |
| | | min-height: 40px; |
| | | padding: 15px; |
| | | border-radius: 4px; |
| | | line-height: 1.6; |
| | | } |
| | | |
| | | .approval-opinion h4 { |
| | | margin: 0 0 15px 0; |
| | | color: #303133; |
| | | } |
| | | .approval-opinion h4 { |
| | | margin: 0 0 15px 0; |
| | | color: #303133; |
| | | } |
| | | |
| | | .nowrap-label { |
| | | white-space: nowrap !important; |
| | | } |
| | | .nowrap-label { |
| | | white-space: nowrap !important; |
| | | } |
| | | |
| | | .description-content { |
| | | white-space: pre-wrap; |
| | | word-wrap: break-word; |
| | | line-height: 1.6; |
| | | padding: 10px; |
| | | background-color: #f5f7fa; |
| | | border-radius: 4px; |
| | | min-height: 60px; |
| | | } |
| | | .description-content { |
| | | white-space: pre-wrap; |
| | | word-wrap: break-word; |
| | | line-height: 1.6; |
| | | padding: 10px; |
| | | background-color: #f5f7fa; |
| | | border-radius: 4px; |
| | | min-height: 60px; |
| | | } |
| | | </style> |
| | |
| | | <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" |
| | | link |
| | | @click="addMinutes(scope.row)" |
| | | > |
| | | <el-button type="primary" |
| | | link |
| | | @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" |
| | | :total="total" |
| | | v-model:page="queryParams.current" |
| | | v-model:limit="queryParams.size" |
| | | @pagination="getList" |
| | | /> |
| | | <pagination v-show="total > 0" |
| | | :total="total" |
| | | v-model:page="queryParams.current" |
| | | v-model:limit="queryParams.size" |
| | | @pagination="getList" /> |
| | | </el-card> |
| | | |
| | | <!-- ä¼è®®è¯¦æ
å¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | title="ä¼è®®è¯¦æ
" |
| | | v-model="detailDialogVisible" |
| | | width="800px" |
| | | > |
| | | <el-dialog title="ä¼è®®è¯¦æ
" |
| | | v-model="detailDialogVisible" |
| | | 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" |
| | | label-class-name="nowrap-label">{{ currentMeeting.description }}</el-descriptions-item> |
| | | <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" |
| | | :key="participant.id" |
| | | style="margin-right: 10px; margin-bottom: 10px;" |
| | | > |
| | | <el-tag v-for="participant in currentMeeting.participants" |
| | | :key="participant.id" |
| | | 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="minutesDialogVisible" |
| | | width="80%" |
| | | @close="handleCloseMinutesDialog" |
| | | > |
| | | <el-dialog title="æ·»å ä¼è®®çºªè¦" |
| | | v-model="minutesDialogVisible" |
| | | width="80%" |
| | | @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 |
| | | }) |
| | | // æ¥è¯¢åæ° |
| | | const queryParams = reactive({ |
| | | current: 1, |
| | | size: 10, |
| | | }); |
| | | |
| | | // æç´¢è¡¨å |
| | | const searchForm = reactive({ |
| | | title: '', |
| | | applicant: '', |
| | | // status: '1' // é»è®¤åªæ¾ç¤ºå·²éè¿å®¡æ¹çä¼è®® |
| | | }) |
| | | // æç´¢è¡¨å |
| | | const searchForm = reactive({ |
| | | 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 }) |
| | | 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 => { |
| | | return { |
| | | id: staff.id, |
| | | name: `${staff.staffName}(${staff.postJob})` |
| | | } |
| | | }) |
| | | // æ¥è¯¢æ°æ® |
| | | const getList = async () => { |
| | | 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 => { |
| | | return { |
| | | id: staff.id, |
| | | 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() |
| | | } |
| | | // æç´¢æé®æä½ |
| | | const handleSearch = () => { |
| | | queryParams.current = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | // éç½®æç´¢è¡¨å |
| | | const resetSearch = () => { |
| | | Object.assign(searchForm, { |
| | | title: '', |
| | | applicant: '', |
| | | // status: '1' |
| | | }) |
| | | handleSearch() |
| | | } |
| | | // éç½®æç´¢è¡¨å |
| | | const resetSearch = () => { |
| | | Object.assign(searchForm, { |
| | | title: "", |
| | | applicant: "", |
| | | // status: '1' |
| | | }); |
| | | 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 |
| | | if (resp.data){ |
| | | 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.location}</p> |
| | | <p><strong>主æäººï¼</strong>${row.host}</p> |
| | | <p><strong>åä¼äººåï¼</strong></p> |
| | | <ol> |
| | | ${row.participants.map(p => `<li>${p.name}</li>`).join('')} |
| | | </ol> |
| | | <p><strong>ä¼è®®å
容ï¼</strong></p> |
| | | <ol> |
| | | <li>è®®é¢ä¸ï¼ |
| | | <ul> |
| | | <li>讨论å
容ï¼</li> |
| | | <li>å³è®®äºé¡¹ï¼</li> |
| | | </ul> |
| | | </li> |
| | | <li>è®®é¢äºï¼ |
| | | <ul> |
| | | <li>讨论å
容ï¼</li> |
| | | <li>å³è®®äºé¡¹ï¼</li> |
| | | </ul> |
| | | </li> |
| | | </ol> |
| | | <p><strong>夿³¨ï¼</strong></p>` |
| | | } |
| | | // æ·»å ä¼è®®çºªè¦ |
| | | 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; |
| | | } else { |
| | | minutesContent.value = `<h2>${row.title}ä¼è®®çºªè¦</h2> |
| | | <p><strong>ä¼è®®æ¶é´ï¼</strong>${row.meetingTime}</p> |
| | | <p><strong>ä¼è®®å°ç¹ï¼</strong>${row.location}</p> |
| | | <p><strong>主æäººï¼</strong>${row.host}</p> |
| | | <p><strong>åä¼äººåï¼</strong></p> |
| | | <ol> |
| | | ${row.participants.map(p => `<li>${p.name}</li>`).join("")} |
| | | </ol> |
| | | <p><strong>ä¼è®®å
容ï¼</strong></p> |
| | | <ol> |
| | | <li>è®®é¢ä¸ï¼ |
| | | <ul> |
| | | <li>讨论å
容ï¼</li> |
| | | <li>å³è®®äºé¡¹ï¼</li> |
| | | </ul> |
| | | </li> |
| | | <li>è®®é¢äºï¼ |
| | | <ul> |
| | | <li>讨论å
容ï¼</li> |
| | | <li>å³è®®äºé¡¹ï¼</li> |
| | | </ul> |
| | | </li> |
| | | </ol> |
| | | <p><strong>夿³¨ï¼</strong></p>`; |
| | | } |
| | | |
| | | minutesDialogVisible.value = true |
| | | } |
| | | minutesDialogVisible.value = true; |
| | | }; |
| | | |
| | | // æäº¤ä¼è®®çºªè¦ |
| | | const submitMinutes = () => { |
| | | if (!minutesContent.value) { |
| | | ElMessage.warning('请è¾å
¥ä¼è®®çºªè¦å
容') |
| | | return |
| | | } |
| | | saveMeetingMinutes({ |
| | | id: minutesContentId.value, |
| | | content: minutesContent.value, |
| | | meetingId: currentMeeting.value.id, |
| | | title: currentMeeting.value.title |
| | | }).then(resp=>{ |
| | | console.log('ä¼è®®çºªè¦å
容:', minutesContent.value) |
| | | ElMessage.success('ä¼è®®çºªè¦ä¿åæå') |
| | | minutesDialogVisible.value = false |
| | | }) |
| | | // æäº¤ä¼è®®çºªè¦ |
| | | const submitMinutes = () => { |
| | | if (!minutesContent.value) { |
| | | ElMessage.warning("请è¾å
¥ä¼è®®çºªè¦å
容"); |
| | | return; |
| | | } |
| | | saveMeetingMinutes({ |
| | | id: minutesContentId.value, |
| | | content: minutesContent.value, |
| | | meetingId: currentMeeting.value.id, |
| | | title: currentMeeting.value.title, |
| | | }).then(resp => { |
| | | console.log("ä¼è®®çºªè¦å
容:", minutesContent.value); |
| | | ElMessage.success("ä¼è®®çºªè¦ä¿åæå"); |
| | | minutesDialogVisible.value = false; |
| | | }); |
| | | }; |
| | | |
| | | } |
| | | // å
³éä¼è®®çºªè¦å¯¹è¯æ¡ |
| | | const handleCloseMinutesDialog = () => { |
| | | minutesContent.value = ""; |
| | | }; |
| | | |
| | | // å
³éä¼è®®çºªè¦å¯¹è¯æ¡ |
| | | const handleCloseMinutesDialog = () => { |
| | | minutesContent.value = '' |
| | | } |
| | | // è·åç¶æç±»å |
| | | const getStatusType = status => { |
| | | const statusMap = { |
| | | 0: "info", // å¾
å®¡æ¹ |
| | | 1: "success", // å·²éè¿ |
| | | 2: "warning", // æªéè¿ |
| | | 3: "danger", // åæ¶ |
| | | }; |
| | | return statusMap[status] || "info"; |
| | | }; |
| | | |
| | | // è·åç¶æç±»å |
| | | const getStatusType = (status) => { |
| | | const statusMap = { |
| | | '0': 'info', // å¾
å®¡æ¹ |
| | | '1': 'success', // å·²éè¿ |
| | | '2': 'warning', // æªéè¿ |
| | | '3': 'danger' // åæ¶ |
| | | } |
| | | return statusMap[status] || 'info' |
| | | } |
| | | // è·åç¶æææ¬ |
| | | const getStatusText = status => { |
| | | const statusMap = { |
| | | 0: "å¾
审æ¹", |
| | | 1: "å·²éè¿", |
| | | 2: "æªéè¿", |
| | | 3: "已忶", |
| | | }; |
| | | return statusMap[status] || "æªç¥"; |
| | | }; |
| | | |
| | | // è·åç¶æææ¬ |
| | | const getStatusText = (status) => { |
| | | const statusMap = { |
| | | '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; |
| | | |
| | | // 页é¢å è½½æ¶è·åæ°æ® |
| | | onMounted(async () => { |
| | | const [resp1, resp2] = await Promise.all([getRoomEnum(), getStaffOnJob()]) |
| | | roomEnum.value = resp1.data |
| | | staffList.value = resp2.data |
| | | |
| | | await getList() |
| | | }) |
| | | await getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .app-container { |
| | | padding: 20px; |
| | | } |
| | | .app-container { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .page-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 20px; |
| | | } |
| | | .page-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .page-header h2 { |
| | | margin: 0; |
| | | color: #303133; |
| | | } |
| | | .page-header h2 { |
| | | margin: 0; |
| | | color: #303133; |
| | | } |
| | | |
| | | .search-card { |
| | | margin-bottom: 20px; |
| | | } |
| | | .search-card { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | gap: 10px; |
| | | } |
| | | .dialog-footer { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | gap: 10px; |
| | | } |
| | | |
| | | .content-section h4 { |
| | | margin: 0 0 15px 0; |
| | | color: #303133; |
| | | } |
| | | .content-section h4 { |
| | | margin: 0 0 15px 0; |
| | | color: #303133; |
| | | } |
| | | |
| | | .mt-20 { |
| | | margin-top: 20px; |
| | | } |
| | | .mt-20 { |
| | | margin-top: 20px; |
| | | } |
| | | |
| | | .participants-list { |
| | | min-height: 40px; |
| | | padding: 15px; |
| | | border-radius: 4px; |
| | | line-height: 1.6; |
| | | } |
| | | .participants-list { |
| | | min-height: 40px; |
| | | padding: 15px; |
| | | border-radius: 4px; |
| | | line-height: 1.6; |
| | | } |
| | | |
| | | .nowrap-label { |
| | | white-space: nowrap !important; |
| | | } |
| | | .nowrap-label { |
| | | white-space: nowrap !important; |
| | | } |
| | | |
| | | .editor-container { |
| | | border: 1px solid #dcdfe6; |
| | | border-radius: 4px; |
| | | } |
| | | .editor-container { |
| | | border: 1px solid #dcdfe6; |
| | | border-radius: 4px; |
| | | } |
| | | </style> |
| | |
| | | <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" |
| | | placeholder="请è¾å
¥ç³è¯·ç¼å·" |
| | | clearable |
| | | style="width: 200px" |
| | | @keyup.enter="handleQuery" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="ç³è¯·äºº" prop="applicant"> |
| | | <el-input |
| | | v-model="queryParams.applicant" |
| | | placeholder="请è¾å
¥ç³è¯·äºº" |
| | | clearable |
| | | style="width: 200px" |
| | | @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-select> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleQuery"> |
| | | <el-icon><Search /></el-icon> |
| | | æç´¢ |
| | | </el-button> |
| | | <el-button @click="resetQuery"> |
| | | <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-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" /> |
| | | </el-form-item> |
| | | <el-form-item label="ç³è¯·äºº" |
| | | prop="applicant"> |
| | | <el-input v-model="queryParams.applicant" |
| | | placeholder="请è¾å
¥ç³è¯·äºº" |
| | | clearable |
| | | style="width: 200px" |
| | | @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-select> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" |
| | | @click="handleQuery"> |
| | | <el-icon> |
| | | <Search /> |
| | | </el-icon> |
| | | æç´¢ |
| | | </el-button> |
| | | <el-button @click="resetQuery"> |
| | | <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> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | </el-form-item> |
| | | </el-form> |
| | | <!-- è¡¨æ ¼åºå --> |
| | | <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"> |
| | | <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"> |
| | | <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" |
| | | type="primary" |
| | | link |
| | | @click="handleApprove(scope.row)" |
| | | > |
| | | <el-button v-if="scope.row.status === 1" |
| | | type="primary" |
| | | link |
| | | @click="handleApprove(scope.row)"> |
| | | å®¡æ¹ |
| | | </el-button> |
| | | <el-button |
| | | v-if="scope.row.status === 3" |
| | | type="success" |
| | | link |
| | | @click="handleIssue(scope.row)" |
| | | > |
| | | <el-button v-if="scope.row.status === 3" |
| | | type="success" |
| | | link |
| | | @click="handleIssue(scope.row)"> |
| | | åæ¾ |
| | | </el-button> |
| | | <el-button |
| | | type="info" |
| | | link |
| | | @click="handleDetail(scope.row)" |
| | | > |
| | | <el-button type="info" |
| | | link |
| | | @click="handleDetail(scope.row)"> |
| | | 详æ
|
| | | </el-button> |
| | | <el-button |
| | | v-if="scope.row.status === 2" |
| | | type="danger" |
| | | link |
| | | @click="handleDelete(scope.row)" |
| | | > |
| | | <el-button v-if="scope.row.status === 2" |
| | | type="danger" |
| | | link |
| | | @click="handleDelete(scope.row)"> |
| | | å é¤ |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <!-- å页 --> |
| | | <pagination |
| | | v-show="total > 0" |
| | | :total="total" |
| | | v-model:page="queryParams.current" |
| | | v-model:limit="queryParams.size" |
| | | @pagination="getList" |
| | | /> |
| | | <pagination v-show="total > 0" |
| | | :total="total" |
| | | v-model:page="queryParams.current" |
| | | v-model:limit="queryParams.size" |
| | | @pagination="getList" /> |
| | | </el-card> |
| | | |
| | | <!-- ç³è¯·å¯¹è¯æ¡ --> |
| | | <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="请è¾å
¥ç³è¯·äººåç§°" /> |
| | | <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="请è¾å
¥ç³è¯·äººåç§°" /> |
| | | </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" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥ç³è¯·åå " |
| | | /> |
| | | <el-form-item label="ç³è¯·åå " |
| | | prop="reason"> |
| | | <el-input v-model="applyForm.reason" |
| | | type="textarea" |
| | | :rows="3" |
| | | 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" |
| | | title="审æ¹ç³è¯·" |
| | | width="500px" |
| | | append-to-body |
| | | > |
| | | <el-form ref="approveFormRef" :model="approveForm" :rules="approveRules" label-width="100px"> |
| | | <el-form-item label="审æ¹ç»æ" prop="approveResult"> |
| | | <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"> |
| | | <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" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥å®¡æ¹æè§" |
| | | /> |
| | | <el-form-item label="å®¡æ¹æè§" |
| | | prop="approvalOpinions"> |
| | | <el-input v-model="approveForm.approvalOpinions" |
| | | type="textarea" |
| | | :rows="3" |
| | | 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" |
| | | title="ç³è¯·è¯¦æ
" |
| | | width="700px" |
| | | append-to-body |
| | | > |
| | | <el-descriptions :column="2" border> |
| | | <el-dialog v-model="showDetailDialog" |
| | | title="ç³è¯·è¯¦æ
" |
| | | width="700px" |
| | | 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: '' |
| | | }) |
| | | // æ¥è¯¢åæ° |
| | | const queryParams = reactive({ |
| | | current: 1, |
| | | size: 10, |
| | | code: "", |
| | | applicant: "", |
| | | status: "", |
| | | }); |
| | | |
| | | // ç³è¯·è¡¨å |
| | | const applyForm = reactive({ |
| | | applicant: '', |
| | | dept: '', |
| | | materialType: '', |
| | | itemName: '', |
| | | applyNum: 1, |
| | | reason: '', |
| | | urgency: '1' |
| | | }) |
| | | |
| | | // 审æ¹è¡¨å |
| | | const approveForm = reactive({ |
| | | 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' }] |
| | | } |
| | | |
| | | const approveRules = { |
| | | approveResult: [{ required: true, message: 'è¯·éæ©å®¡æ¹ç»æ', trigger: 'change' }], |
| | | approvalOpinions: [{ required: true, message: '请è¾å
¥å®¡æ¹æè§', trigger: 'blur' }] |
| | | } |
| | | |
| | | const openShow = () => { |
| | | showApplyDialog.value = true |
| | | resetApplyForm() |
| | | } |
| | | |
| | | // è·ååè¡¨æ°æ® |
| | | const getList = () => { |
| | | loading.value = true |
| | | listPage(queryParams).then(res => { |
| | | total.value = res.data.total |
| | | loading.value = false |
| | | officeList.value = res.data.records |
| | | }) |
| | | } |
| | | |
| | | // æ¥è¯¢ |
| | | const handleQuery = () => { |
| | | queryParams.current = 1 |
| | | getList() |
| | | } |
| | | |
| | | // éç½®æ¥è¯¢ |
| | | const resetQuery = () => { |
| | | queryParams.code = '' |
| | | queryParams.applicant = '' |
| | | queryParams.status = '' |
| | | handleQuery() |
| | | } |
| | | |
| | | // å¤é |
| | | const handleSelectionChange = (selection) => { |
| | | multipleSelection.value = selection |
| | | } |
| | | |
| | | // è·åç¶æç±»å |
| | | const getStatusType = (status) => { |
| | | const statusMap = { |
| | | 1: 'warning', |
| | | 3: 'success', |
| | | 2: 'danger', |
| | | 4: 'info' |
| | | } |
| | | return statusMap[status] || 'info' |
| | | } |
| | | |
| | | // è·åç¶æææ¬ |
| | | const getStatusText = (status) => { |
| | | const statusMap = { |
| | | 1: 'å¾
审æ¹', |
| | | 3: 'å·²éè¿', |
| | | 2: 'å·²æç»', |
| | | 4: '已忾' |
| | | } |
| | | return statusMap[status] || status |
| | | } |
| | | |
| | | // æäº¤ç³è¯· |
| | | const submitApply = () => { |
| | | add(applyForm).then(() => { |
| | | ElMessage.success('ç³è¯·æå') |
| | | getList() |
| | | showApplyDialog.value = false |
| | | resetApplyForm() |
| | | }) |
| | | |
| | | |
| | | |
| | | } |
| | | |
| | | //é置表å |
| | | const resetApplyForm = () => { |
| | | // é置表å |
| | | Object.assign(applyForm, { |
| | | applicant: '', |
| | | dept: '', |
| | | materialType: '', |
| | | itemName: '', |
| | | // ç³è¯·è¡¨å |
| | | const applyForm = reactive({ |
| | | applicant: "", |
| | | dept: "", |
| | | materialType: "", |
| | | itemName: "", |
| | | applyNum: 1, |
| | | reason: '', |
| | | urgency: '1' |
| | | }) |
| | | } |
| | | reason: "", |
| | | urgency: "1", |
| | | }); |
| | | |
| | | // å®¡æ¹ |
| | | const handleApprove = (row) => { |
| | | currentDetail.value = row |
| | | showApproveDialog.value = true |
| | | } |
| | | // 审æ¹è¡¨å |
| | | const approveForm = reactive({ |
| | | approveResult: "3", |
| | | approvalOpinions: "", |
| | | }); |
| | | |
| | | 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 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" }], |
| | | }; |
| | | |
| | | // æäº¤å®¡æ¹ |
| | | const submitApprove = () => { |
| | | 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) => { |
| | | if(res.code === 200){ |
| | | showApproveDialog.value = false |
| | | ElMessage.success('审æ¹å®æ') |
| | | getList() |
| | | const approveRules = { |
| | | approveResult: [ |
| | | { required: true, message: "è¯·éæ©å®¡æ¹ç»æ", trigger: "change" }, |
| | | ], |
| | | approvalOpinions: [ |
| | | { required: true, message: "请è¾å
¥å®¡æ¹æè§", trigger: "blur" }, |
| | | ], |
| | | }; |
| | | |
| | | // é置表å |
| | | Object.assign(approveForm, { |
| | | approveResult: '3', |
| | | approvalOpinions: '' |
| | | }) |
| | | } |
| | | }) |
| | | const openShow = () => { |
| | | showApplyDialog.value = true; |
| | | resetApplyForm(); |
| | | }; |
| | | |
| | | } |
| | | // è·ååè¡¨æ°æ® |
| | | const getList = () => { |
| | | loading.value = true; |
| | | listPage(queryParams).then(res => { |
| | | total.value = res.data.total; |
| | | loading.value = false; |
| | | officeList.value = res.data.records; |
| | | }); |
| | | }; |
| | | |
| | | // åæ¾ |
| | | 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() |
| | | } |
| | | }) |
| | | } |
| | | // æ¥è¯¢ |
| | | const handleQuery = () => { |
| | | queryParams.current = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | // æ¥ç详æ
|
| | | const handleDetail = (row) => { |
| | | currentDetail.value = row |
| | | showDetailDialog.value = true |
| | | } |
| | | // éç½®æ¥è¯¢ |
| | | const resetQuery = () => { |
| | | queryParams.code = ""; |
| | | queryParams.applicant = ""; |
| | | queryParams.status = ""; |
| | | handleQuery(); |
| | | }; |
| | | |
| | | // å é¤ |
| | | const handleDelete = (row) => { |
| | | ElMessageBox.confirm('确认å é¤è¯¥ç³è¯·åï¼', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | }).then(() => { |
| | | let ids = [row.id] |
| | | deleteOff(ids).then((res) =>{ |
| | | ElMessage.success('å 餿å') |
| | | getList() |
| | | // å¤é |
| | | const handleSelectionChange = selection => { |
| | | multipleSelection.value = selection; |
| | | }; |
| | | |
| | | // è·åç¶æç±»å |
| | | const getStatusType = status => { |
| | | const statusMap = { |
| | | 1: "warning", |
| | | 3: "success", |
| | | 2: "danger", |
| | | 4: "info", |
| | | }; |
| | | return statusMap[status] || "info"; |
| | | }; |
| | | |
| | | // è·åç¶æææ¬ |
| | | const getStatusText = status => { |
| | | const statusMap = { |
| | | 1: "å¾
审æ¹", |
| | | 3: "å·²éè¿", |
| | | 2: "å·²æç»", |
| | | 4: "已忾", |
| | | }; |
| | | return statusMap[status] || status; |
| | | }; |
| | | |
| | | // æäº¤ç³è¯· |
| | | const submitApply = () => { |
| | | add(applyForm).then(() => { |
| | | ElMessage.success("ç³è¯·æå"); |
| | | getList(); |
| | | showApplyDialog.value = false; |
| | | resetApplyForm(); |
| | | }); |
| | | }; |
| | | |
| | | //é置表å |
| | | const resetApplyForm = () => { |
| | | // é置表å |
| | | Object.assign(applyForm, { |
| | | applicant: "", |
| | | dept: "", |
| | | materialType: "", |
| | | itemName: "", |
| | | applyNum: 1, |
| | | reason: "", |
| | | urgency: "1", |
| | | }); |
| | | }; |
| | | |
| | | // å®¡æ¹ |
| | | 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 submitApprove = () => { |
| | | 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 => { |
| | | if (res.code === 200) { |
| | | showApproveDialog.value = false; |
| | | ElMessage.success("审æ¹å®æ"); |
| | | getList(); |
| | | |
| | | // é置表å |
| | | Object.assign(approveForm, { |
| | | approveResult: "3", |
| | | approvalOpinions: "", |
| | | }); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // åæ¾ |
| | | 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(); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // æ¥ç详æ
|
| | | const handleDetail = row => { |
| | | currentDetail.value = row; |
| | | showDetailDialog.value = true; |
| | | }; |
| | | |
| | | // å é¤ |
| | | const handleDelete = row => { |
| | | ElMessageBox.confirm("确认å é¤è¯¥ç³è¯·åï¼", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).then(() => { |
| | | let ids = [row.id]; |
| | | deleteOff(ids).then(res => { |
| | | ElMessage.success("å 餿å"); |
| | | getList(); |
| | | }); |
| | | }); |
| | | }; |
| | | const { proxy } = getCurrentInstance(); |
| | | // å¯¼åº |
| | | const handleExport = () => { |
| | | ElMessageBox.confirm("ææçå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | }) |
| | | } |
| | | const { proxy } = getCurrentInstance(); |
| | | // å¯¼åº |
| | | const handleExport = () => { |
| | | ElMessageBox.confirm("ææçå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/officeSupplies/export", {}, "åå
¬ç©èµ.xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | // 页é¢å è½½æ¶è·åæ°æ® |
| | | onMounted(() => { |
| | | getList() |
| | | }) |
| | | // 页é¢å è½½æ¶è·åæ°æ® |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .app-container { |
| | | padding: 20px; |
| | | } |
| | | .app-container { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .card-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | .card-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | |
| | | .mb8 { |
| | | margin-bottom: 8px; |
| | | } |
| | | .mb8 { |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | text-align: right; |
| | | } |
| | | .dialog-footer { |
| | | text-align: right; |
| | | } |
| | | |
| | | :deep(.el-descriptions__label) { |
| | | width: 120px; |
| | | } |
| | | :deep(.el-descriptions__label) { |
| | | width: 120px; |
| | | } |
| | | </style> |
| | |
| | | <!-- 顶鍿使 --> |
| | | <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" |
| | | :type="datePickerType" |
| | | placeholder="éæ©æ¥æ" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 180px; margin-left: 10px" |
| | | @change="handleDateChange" |
| | | /> |
| | | <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" /> |
| | | </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" |
| | | :color="getProgressColor(plan.progress)" |
| | | :stroke-width="8" |
| | | /> |
| | | <el-progress :percentage="plan.progress" |
| | | :color="getProgressColor(plan.progress)" |
| | | :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" |
| | | :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="请è¾å
¥è®¡åæ é¢" /> |
| | | <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="请è¾å
¥è®¡åæ é¢" /> |
| | | </el-form-item> |
| | | <el-form-item label="计åæè¿°" prop="description"> |
| | | <el-input |
| | | v-model="planForm.description" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥è®¡åæè¿°" |
| | | /> |
| | | <el-form-item label="计åæè¿°" |
| | | prop="description"> |
| | | <el-input v-model="planForm.description" |
| | | type="textarea" |
| | | :rows="3" |
| | | 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" |
| | | type="date" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | placeholder="éæ©å¼å§æ¶é´" |
| | | style="width: 100%" |
| | | /> |
| | | <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%" /> |
| | | </el-form-item> |
| | | <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%" |
| | | /> |
| | | <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%" /> |
| | | </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" |
| | | multiple |
| | | placeholder="è¯·éæ©æ ç¾" |
| | | style="width: 100%" |
| | | > |
| | | <el-option |
| | | v-for="dept in departments" |
| | | :key="dept" |
| | | :label="dept" |
| | | :value="dept" |
| | | /> |
| | | <el-select v-model="planForm.tags" |
| | | multiple |
| | | placeholder="è¯·éæ©æ ç¾" |
| | | style="width: 100%"> |
| | | <el-option v-for="dept in departments" |
| | | :key="dept" |
| | | :label="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" |
| | | min="0" |
| | | max="100" |
| | | step="1" |
| | | placeholder="请è¾å
¥è¿åº¦" |
| | | style="width: 100%" |
| | | /> |
| | | <el-form-item label="è¿åº¦" |
| | | prop="progress"> |
| | | <el-input-number v-model="planForm.progress" |
| | | min="0" |
| | | max="100" |
| | | step="1" |
| | | placeholder="请è¾å
¥è¿åº¦" |
| | | 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' |
| | | const { proxy } = getCurrentInstance(); |
| | | import { |
| | | User, |
| | | UserFilled, |
| | | OfficeBuilding, |
| | | House, |
| | | Calendar, |
| | | Clock, |
| | | Flag, |
| | | ArrowDown |
| | | } from '@element-plus/icons-vue' |
| | | import { listDutyPlan, addDutyPlan, updateDutyPlan, delDutyPlan,NumDutyPlan,exportDutyPlan } from '@/api/collaborativeApproval/planTemplate.js' |
| | | import { ref, reactive, computed, onMounted } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | const { proxy } = getCurrentInstance(); |
| | | import { |
| | | User, |
| | | UserFilled, |
| | | OfficeBuilding, |
| | | House, |
| | | Calendar, |
| | | Clock, |
| | | Flag, |
| | | 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', |
| | | tags: [], |
| | | status: '', |
| | | progress: 0 |
| | | }) |
| | | // è¡¨åæ°æ® |
| | | const planForm = reactive({ |
| | | id: "", |
| | | title: "", |
| | | description: "", |
| | | level: "personal", |
| | | period: "week", |
| | | startDate: "", |
| | | endDate: "", |
| | | assignee: "", |
| | | priority: "medium", |
| | | tags: [], |
| | | 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 = ["产å", "åæ", "è°ç ",'ææ¯', 'æ¶æ', '设计','å¸åº', 'æ¨å¹¿', 'è¥é']; |
| | | // æ¦è§æ°æ® |
| | | const overviewData = reactive({ |
| | | personal: { total: 0, completion: 0 }, |
| | | group: { total: 0, completion: 0 }, |
| | | department: { total: 0, completion: 0 }, |
| | | company: { total: 0, completion: 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 = [ |
| | | "产å", |
| | | "åæ", |
| | | "è°ç ", |
| | | "ææ¯", |
| | | "æ¶æ", |
| | | "设计", |
| | | "å¸åº", |
| | | "æ¨å¹¿", |
| | | "è¥é", |
| | | ]; |
| | | // æ¦è§æ°æ® |
| | | const overviewData = reactive({ |
| | | personal: { total: 0, completion: 0 }, |
| | | group: { total: 0, completion: 0 }, |
| | | department: { 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' |
| | | default: |
| | | return 'date' |
| | | } |
| | | }) |
| | | // 计ç®å±æ§ |
| | | const datePickerType = computed(() => { |
| | | switch (currentPeriod.value) { |
| | | case "week": |
| | | return "week"; |
| | | case "month": |
| | | return "month"; |
| | | case "year": |
| | | return "year"; |
| | | default: |
| | | 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 |
| | | // é置表å |
| | | Object.keys(planForm).forEach(key => { |
| | | planForm[key] = '' |
| | | }) |
| | | planForm.level = 'personal' |
| | | planForm.period = 'week' |
| | | planForm.priority = 'medium' |
| | | planForm.status = 'not_started' |
| | | planForm.progress = 0 |
| | | } |
| | | const handleAddPlan = () => { |
| | | 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; |
| | | }; |
| | | |
| | | 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].join(', ') |
| | | // } else { |
| | | // planForm[key] = plan[key] |
| | | // } |
| | | // }) |
| | | } |
| | | 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].join(', ') |
| | | // } else { |
| | | // planForm[key] = plan[key] |
| | | // } |
| | | // }) |
| | | }; |
| | | |
| | | const handleViewDetail = (plan) => { |
| | | currentPlanDetail.value = plan |
| | | showPlanDetailDialog.value = true |
| | | // ElMessage.info(`æ¥ç计å详æ
: ${plan.title}`) |
| | | } |
| | | 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) |
| | | switch (command) { |
| | | case 'share': |
| | | ElMessage.success('计åå·²å
񄧮') |
| | | break |
| | | case 'copy': |
| | | const knowledgeText = ` |
| | | è®¡åæ é¢ï¼${plan.title} |
| | | 计åæè¿°ï¼${plan.description} |
| | | 计å级å«ï¼${getCurrentLevelText(plan.level)} |
| | | æ¶é´å¨æï¼${getCurrentPeriodText(plan.period)} |
| | | å¼å§æ¶é´ï¼${plan.startDate} |
| | | ç»ææ¶é´ï¼${plan.endDate} |
| | | è´è´£äººï¼${plan.assignee} |
| | | ä¼å
级ï¼${getPriorityText(plan.priority)} |
| | | æ ç¾ï¼${plan.tags.join(', ')} |
| | | ç¶æï¼${getStatusText(plan.status)} |
| | | è¿åº¦ï¼${plan.progress}% |
| | | `.trim(); |
| | | const handleMoreAction = async (plan, command) => { |
| | | let ids = []; |
| | | ids.push(plan.id); |
| | | console.log("ids", ids); |
| | | switch (command) { |
| | | case "share": |
| | | ElMessage.success("计åå·²å
񄧮"); |
| | | break; |
| | | case "copy": |
| | | const knowledgeText = ` |
| | | è®¡åæ é¢ï¼${plan.title} |
| | | 计åæè¿°ï¼${plan.description} |
| | | 计å级å«ï¼${getCurrentLevelText(plan.level)} |
| | | æ¶é´å¨æï¼${getCurrentPeriodText(plan.period)} |
| | | å¼å§æ¶é´ï¼${plan.startDate} |
| | | ç»ææ¶é´ï¼${plan.endDate} |
| | | è´è´£äººï¼${plan.assignee} |
| | | ä¼å
级ï¼${getPriorityText(plan.priority)} |
| | | æ ç¾ï¼${plan.tags.join(", ")} |
| | | ç¶æï¼${getStatusText(plan.status)} |
| | | è¿åº¦ï¼${plan.progress}% |
| | | `.trim(); |
| | | |
| | | // å¤å¶å°åªè´´æ¿ |
| | | navigator.clipboard.writeText(knowledgeText).then(() => { |
| | | ElMessage.success("ç¥è¯å
容已å¤å¶å°åªè´´æ¿"); |
| | | }).catch(() => { |
| | | ElMessage.error("å¤å¶å¤±è´¥ï¼è¯·æå¨å¤å¶"); |
| | | navigator.clipboard |
| | | .writeText(knowledgeText) |
| | | .then(() => { |
| | | ElMessage.success("ç¥è¯å
容已å¤å¶å°åªè´´æ¿"); |
| | | }) |
| | | .catch(() => { |
| | | ElMessage.error("å¤å¶å¤±è´¥ï¼è¯·æå¨å¤å¶"); |
| | | }); |
| | | // ElMessage.success('计åå·²å¤å¶') |
| | | break; |
| | | case "delete": |
| | | ElMessageBox.confirm("ç¡®å®è¦å é¤è¿ä¸ªè®¡ååï¼", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).then(() => { |
| | | delDutyPlan(ids).then(res => { |
| | | if (res.code === 200) { |
| | | ElMessage.success("计åå·²å é¤"); |
| | | ids.value = []; |
| | | getPlanList(); |
| | | } |
| | | }); |
| | | }); |
| | | // ElMessage.success('计åå·²å¤å¶') |
| | | break |
| | | case 'delete': |
| | | ElMessageBox.confirm('ç¡®å®è¦å é¤è¿ä¸ªè®¡ååï¼', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | }).then(() => { |
| | | |
| | | delDutyPlan(ids).then(res => { |
| | | break; |
| | | } |
| | | }; |
| | | // |
| | | const handleSavePlan = async () => { |
| | | try { |
| | | await planFormRef.value.validate(); |
| | | if (operationType.value === "add") { |
| | | addDutyPlan(planForm).then(res => { |
| | | if (res.code === 200) { |
| | | ElMessage.success('计åå·²å é¤') |
| | | ids.value = []; |
| | | getPlanList() |
| | | ElMessage.success("计åä¿åæå"); |
| | | planDialogVisible.value = false; |
| | | } |
| | | }) |
| | | }) |
| | | break |
| | | } |
| | | } |
| | | // |
| | | const handleSavePlan = async () => { |
| | | try { |
| | | await planFormRef.value.validate() |
| | | if (operationType.value === 'add') { |
| | | addDutyPlan(planForm).then(res => { |
| | | if (res.code === 200) { |
| | | ElMessage.success('计åä¿åæå') |
| | | planDialogVisible.value = false |
| | | } |
| | | getPlanList() |
| | | }) |
| | | } else { |
| | | |
| | | updateDutyPlan(planForm).then(res => { |
| | | if (res.code === 200) { |
| | | ElMessage.success('计åä¿åæå') |
| | | planDialogVisible.value = false |
| | | } |
| | | getPlanList() |
| | | }) |
| | | getPlanList(); |
| | | }); |
| | | } else { |
| | | updateDutyPlan(planForm).then(res => { |
| | | if (res.code === 200) { |
| | | ElMessage.success("计åä¿åæå"); |
| | | planDialogVisible.value = false; |
| | | } |
| | | getPlanList(); |
| | | }); |
| | | } |
| | | } catch (error) { |
| | | console.log("表åéªè¯å¤±è´¥:", error); |
| | | } |
| | | } catch (error) { |
| | | console.log('表åéªè¯å¤±è´¥:', error) |
| | | } |
| | | } |
| | | }; |
| | | |
| | | const handleDialogClose = () => { |
| | | planFormRef.value?.resetFields() |
| | | } |
| | | const handleDialogClose = () => { |
| | | planFormRef.value?.resetFields(); |
| | | }; |
| | | |
| | | const handleRefresh = () => { |
| | | getPlanList() |
| | | // ElMessage.success('æ°æ®å·²å·æ°') |
| | | } |
| | | const handleRefresh = () => { |
| | | getPlanList(); |
| | | // ElMessage.success('æ°æ®å·²å·æ°') |
| | | }; |
| | | |
| | | const handleFilter = () => { |
| | | ElMessage.info('æå¼çé颿¿') |
| | | } |
| | | const handleFilter = () => { |
| | | ElMessage.info("æå¼çé颿¿"); |
| | | }; |
| | | |
| | | const handleExport = () => { |
| | | ElMessageBox.confirm("æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | // exportDutyPlan().then(res => { |
| | | |
| | | // }) |
| | | proxy.download("/dutyPlan/export", {}, "计å管ç.xlsx"); |
| | | const handleExport = () => { |
| | | ElMessageBox.confirm("æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | const handleShare = () => { |
| | | ElMessage.success('计åå·²å
񄧮') |
| | | } |
| | | .then(() => { |
| | | // exportDutyPlan().then(res => { |
| | | |
| | | const getCurrentLevelText = () => { |
| | | const levelMap = { |
| | | personal: '个人计å', |
| | | group: 'å°ç»è®¡å', |
| | | department: 'é¨é¨è®¡å', |
| | | company: 'å
¬å¸è®¡å' |
| | | } |
| | | return levelMap[currentLevel.value] || '个人计å' |
| | | } |
| | | |
| | | const getCurrentPeriodText = () => { |
| | | const periodMap = { |
| | | week: 'å¨è®¡å', |
| | | month: 'æè®¡å', |
| | | year: '年计å' |
| | | } |
| | | return periodMap[currentPeriod.value] || 'å¨è®¡å' |
| | | } |
| | | |
| | | const getPriorityType = (priority) => { |
| | | const typeMap = { |
| | | high: 'danger', |
| | | medium: 'warning', |
| | | low: 'info' |
| | | } |
| | | return typeMap[priority] || 'info' |
| | | } |
| | | |
| | | const getPriorityText = (priority) => { |
| | | const textMap = { |
| | | high: 'é«', |
| | | medium: 'ä¸', |
| | | low: 'ä½' |
| | | } |
| | | return textMap[priority] || 'ä¸' |
| | | } |
| | | |
| | | const getStatusText = (status) => { |
| | | const statusMap = { |
| | | 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 getPlanList = async () => { |
| | | const params = { |
| | | level: currentLevel.value, |
| | | period: currentPeriod.value, |
| | | queryDate:currentDate.value |
| | | } |
| | | listDutyPlan(params).then(res => { |
| | | if (res.code === 200) { |
| | | planList.value = res.data.records |
| | | } |
| | | }).catch(err => { |
| | | console.log(err) |
| | | }) |
| | | } |
| | | //è·åæ°æ® |
| | | const getPlanNum = async () => { |
| | | 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 |
| | | // }) |
| | | proxy.download("/dutyPlan/export", {}, "计å管ç.xlsx"); |
| | | }) |
| | | |
| | | } |
| | | }).catch(err => { |
| | | console.log(err) |
| | | }) |
| | | } |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | const handleShare = () => { |
| | | ElMessage.success("计åå·²å
񄧮"); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getPlanList() |
| | | getPlanNum() |
| | | console.log('å¤çº§è®¡å模æ¿é¡µé¢å·²å è½½') |
| | | }) |
| | | const getCurrentLevelText = () => { |
| | | const levelMap = { |
| | | personal: "个人计å", |
| | | group: "å°ç»è®¡å", |
| | | department: "é¨é¨è®¡å", |
| | | company: "å
¬å¸è®¡å", |
| | | }; |
| | | return levelMap[currentLevel.value] || "个人计å"; |
| | | }; |
| | | |
| | | const getCurrentPeriodText = () => { |
| | | const periodMap = { |
| | | week: "å¨è®¡å", |
| | | month: "æè®¡å", |
| | | year: "年计å", |
| | | }; |
| | | return periodMap[currentPeriod.value] || "å¨è®¡å"; |
| | | }; |
| | | |
| | | const getPriorityType = priority => { |
| | | const typeMap = { |
| | | high: "danger", |
| | | medium: "warning", |
| | | low: "info", |
| | | }; |
| | | return typeMap[priority] || "info"; |
| | | }; |
| | | |
| | | const getPriorityText = priority => { |
| | | const textMap = { |
| | | high: "é«", |
| | | medium: "ä¸", |
| | | low: "ä½", |
| | | }; |
| | | return textMap[priority] || "ä¸"; |
| | | }; |
| | | |
| | | const getStatusText = status => { |
| | | const statusMap = { |
| | | 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 getPlanList = async () => { |
| | | const params = { |
| | | level: currentLevel.value, |
| | | period: currentPeriod.value, |
| | | queryDate: currentDate.value, |
| | | }; |
| | | listDutyPlan(params) |
| | | .then(res => { |
| | | if (res.code === 200) { |
| | | planList.value = res.data.records; |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | console.log(err); |
| | | }); |
| | | }; |
| | | //è·åæ°æ® |
| | | const getPlanNum = async () => { |
| | | 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; |
| | | }); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | console.log(err); |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getPlanList(); |
| | | getPlanNum(); |
| | | console.log("å¤çº§è®¡å模æ¿é¡µé¢å·²å è½½"); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .app-container { |
| | | padding: 20px; |
| | | background-color: #f5f5f5; |
| | | min-height: 100vh; |
| | | } |
| | | .app-container { |
| | | padding: 20px; |
| | | background-color: #f5f5f5; |
| | | min-height: 100vh; |
| | | } |
| | | |
| | | .header-actions { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 20px; |
| | | background: white; |
| | | padding: 20px; |
| | | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); |
| | | } |
| | | |
| | | .left-actions { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .right-actions { |
| | | display: flex; |
| | | gap: 10px; |
| | | } |
| | | |
| | | .overview-cards { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .overview-card { |
| | | height: 120px; |
| | | } |
| | | |
| | | .card-content { |
| | | display: flex; |
| | | align-items: center; |
| | | height: 100%; |
| | | } |
| | | |
| | | .card-icon { |
| | | width: 60px; |
| | | height: 60px; |
| | | border-radius: 50%; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | margin-right: 15px; |
| | | font-size: 24px; |
| | | color: white; |
| | | } |
| | | |
| | | .card-icon.personal { |
| | | background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
| | | } |
| | | |
| | | .card-icon.group { |
| | | background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); |
| | | } |
| | | |
| | | .card-icon.department { |
| | | background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%); |
| | | } |
| | | |
| | | .card-icon.company { |
| | | background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%); |
| | | } |
| | | |
| | | .card-info { |
| | | flex: 1; |
| | | } |
| | | |
| | | .card-title { |
| | | font-size: 14px; |
| | | color: #666; |
| | | margin-bottom: 5px; |
| | | } |
| | | |
| | | .card-number { |
| | | font-size: 24px; |
| | | font-weight: bold; |
| | | color: #333; |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .card-progress { |
| | | width: 100%; |
| | | } |
| | | |
| | | .plan-content { |
| | | background: white; |
| | | border-radius: 8px; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .card-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | font-weight: bold; |
| | | color: #333; |
| | | } |
| | | |
| | | .header-actions { |
| | | display: flex; |
| | | gap: 10px; |
| | | } |
| | | |
| | | .plan-list { |
| | | padding: 20px 0; |
| | | } |
| | | |
| | | .plan-item { |
| | | border: 1px solid #e4e7ed; |
| | | border-radius: 8px; |
| | | margin-bottom: 15px; |
| | | padding: 20px; |
| | | transition: all 0.3s ease; |
| | | } |
| | | |
| | | .plan-item:hover { |
| | | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); |
| | | transform: translateY(-2px); |
| | | } |
| | | |
| | | .plan-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 15px; |
| | | } |
| | | |
| | | .plan-title { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 10px; |
| | | } |
| | | |
| | | .title-text { |
| | | font-size: 16px; |
| | | font-weight: bold; |
| | | color: #333; |
| | | } |
| | | |
| | | .plan-actions { |
| | | display: flex; |
| | | gap: 10px; |
| | | } |
| | | |
| | | .plan-content { |
| | | margin-bottom: 15px; |
| | | } |
| | | |
| | | .plan-description { |
| | | color: #666; |
| | | margin-bottom: 15px; |
| | | line-height: 1.6; |
| | | } |
| | | |
| | | .plan-meta { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 20px; |
| | | margin-bottom: 15px; |
| | | } |
| | | |
| | | .meta-item { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 5px; |
| | | color: #666; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .plan-progress { |
| | | margin-bottom: 15px; |
| | | } |
| | | |
| | | .plan-tags { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 5px; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | gap: 10px; |
| | | } |
| | | |
| | | /* ååºå¼è®¾è®¡ */ |
| | | @media (max-width: 768px) { |
| | | .header-actions { |
| | | flex-direction: column; |
| | | gap: 15px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 20px; |
| | | background: white; |
| | | padding: 20px; |
| | | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); |
| | | } |
| | | |
| | | |
| | | .left-actions { |
| | | flex-wrap: wrap; |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .right-actions { |
| | | display: flex; |
| | | gap: 10px; |
| | | } |
| | | |
| | | .plan-meta { |
| | | flex-direction: column; |
| | | |
| | | .overview-cards { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .overview-card { |
| | | height: 120px; |
| | | } |
| | | |
| | | .card-content { |
| | | display: flex; |
| | | align-items: center; |
| | | height: 100%; |
| | | } |
| | | |
| | | .card-icon { |
| | | width: 60px; |
| | | height: 60px; |
| | | border-radius: 50%; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | margin-right: 15px; |
| | | font-size: 24px; |
| | | color: white; |
| | | } |
| | | |
| | | .card-icon.personal { |
| | | background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
| | | } |
| | | |
| | | .card-icon.group { |
| | | background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); |
| | | } |
| | | |
| | | .card-icon.department { |
| | | background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%); |
| | | } |
| | | |
| | | .card-icon.company { |
| | | background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%); |
| | | } |
| | | |
| | | .card-info { |
| | | flex: 1; |
| | | } |
| | | |
| | | .card-title { |
| | | font-size: 14px; |
| | | color: #666; |
| | | margin-bottom: 5px; |
| | | } |
| | | |
| | | .card-number { |
| | | font-size: 24px; |
| | | font-weight: bold; |
| | | color: #333; |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .card-progress { |
| | | width: 100%; |
| | | } |
| | | |
| | | .plan-content { |
| | | background: white; |
| | | border-radius: 8px; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .card-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | font-weight: bold; |
| | | color: #333; |
| | | } |
| | | |
| | | .header-actions { |
| | | display: flex; |
| | | gap: 10px; |
| | | } |
| | | |
| | | |
| | | .plan-list { |
| | | padding: 20px 0; |
| | | } |
| | | |
| | | .plan-item { |
| | | border: 1px solid #e4e7ed; |
| | | border-radius: 8px; |
| | | margin-bottom: 15px; |
| | | padding: 20px; |
| | | transition: all 0.3s ease; |
| | | } |
| | | |
| | | .plan-item:hover { |
| | | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); |
| | | transform: translateY(-2px); |
| | | } |
| | | |
| | | .plan-header { |
| | | flex-direction: column; |
| | | align-items: flex-start; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 15px; |
| | | } |
| | | |
| | | .plan-title { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 10px; |
| | | } |
| | | } |
| | | |
| | | .title-text { |
| | | font-size: 16px; |
| | | font-weight: bold; |
| | | color: #333; |
| | | } |
| | | |
| | | .plan-actions { |
| | | display: flex; |
| | | gap: 10px; |
| | | } |
| | | |
| | | .plan-content { |
| | | margin-bottom: 15px; |
| | | } |
| | | |
| | | .plan-description { |
| | | color: #666; |
| | | margin-bottom: 15px; |
| | | line-height: 1.6; |
| | | } |
| | | |
| | | .plan-meta { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 20px; |
| | | margin-bottom: 15px; |
| | | } |
| | | |
| | | .meta-item { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 5px; |
| | | color: #666; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .plan-progress { |
| | | margin-bottom: 15px; |
| | | } |
| | | |
| | | .plan-tags { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 5px; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | gap: 10px; |
| | | } |
| | | |
| | | /* ååºå¼è®¾è®¡ */ |
| | | @media (max-width: 768px) { |
| | | .header-actions { |
| | | flex-direction: column; |
| | | gap: 15px; |
| | | } |
| | | |
| | | .left-actions { |
| | | flex-wrap: wrap; |
| | | gap: 10px; |
| | | } |
| | | |
| | | .plan-meta { |
| | | flex-direction: column; |
| | | gap: 10px; |
| | | } |
| | | |
| | | .plan-header { |
| | | flex-direction: column; |
| | | align-items: flex-start; |
| | | gap: 10px; |
| | | } |
| | | } |
| | | </style> |
| | |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title">ç¨åºåï¼</span> |
| | | <el-input |
| | | v-model="searchForm.programName" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥ç¨åºåæç´¢" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | /> |
| | | <el-input v-model="searchForm.programName" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥ç¨åºåæç´¢" |
| | | @change="handleQuery" |
| | | clearable |
| | | :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" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | :total="page.total" |
| | | ></PIMTable> |
| | | <PIMTable rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | :total="page.total"></PIMTable> |
| | | </div> |
| | | |
| | | <!-- RPA表åå¼¹çª --> |
| | | <el-dialog |
| | | v-model="dialogVisible" |
| | | :title="dialogTitle" |
| | | width="500px" |
| | | :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" |
| | | placeholder="请è¾å
¥ç¨åºå" |
| | | clearable |
| | | /> |
| | | <el-dialog v-model="dialogVisible" |
| | | :title="dialogTitle" |
| | | width="500px" |
| | | :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" |
| | | placeholder="请è¾å
¥ç¨åºå" |
| | | 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" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥RPAç¨åºæè¿°" |
| | | clearable |
| | | /> |
| | | <el-form-item label="æè¿°" |
| | | prop="description"> |
| | | <el-input v-model="form.description" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥RPAç¨åºæè¿°" |
| | | 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> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | 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"; |
| | | // ååºå¼æ°æ® |
| | | const data = reactive({ |
| | | searchForm: { |
| | | programName: "", |
| | | status: "", |
| | | }, |
| | | form: { |
| | | programName: "", |
| | | status: "", |
| | | description: "" |
| | | }, |
| | | dialogVisible: false, |
| | | dialogTitle: "", |
| | | dialogType: "add", |
| | | tableLoading: false, |
| | | page: { |
| | | current: 1, |
| | | size: 20, |
| | | total: 0, |
| | | }, |
| | | tableData: [], |
| | | }); |
| | | |
| | | const { searchForm, form, dialogVisible, dialogTitle, dialogType, selectedIds, tableLoading, page, tableData } = toRefs(data); |
| | | |
| | | // 表åå¼ç¨ |
| | | const formRef = ref(); |
| | | // éæ©çè¡æ°æ® |
| | | const selectedRows = ref([]); |
| | | |
| | | // 表åéªè¯è§å |
| | | const rules = { |
| | | programName: [ |
| | | { required: true, message: "请è¾å
¥ç¨åºå", trigger: "blur" } |
| | | ], |
| | | status: [ |
| | | { required: true, message: "è¯·éæ©æ§è¡ç¶æ", trigger: "change" } |
| | | ] |
| | | }; |
| | | |
| | | // è¡¨æ ¼åé
ç½® |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "ç¨åºå", |
| | | prop: "programName", |
| | | // width: 200, |
| | | }, |
| | | { |
| | | label: "æ§è¡ç¶æ", |
| | | prop: "status", |
| | | dataType: "tag", |
| | | // width: 120, |
| | | formatData: (params) => { |
| | | const statusMap = { |
| | | running: "è¿è¡ä¸", |
| | | stopped: "已忢", |
| | | error: "å¼å¸¸" |
| | | }; |
| | | return statusMap[params] || params; |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | 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"; |
| | | // ååºå¼æ°æ® |
| | | const data = reactive({ |
| | | searchForm: { |
| | | programName: "", |
| | | status: "", |
| | | }, |
| | | formatType: (params) => { |
| | | const typeMap = { |
| | | running: "success", |
| | | stopped: "info", |
| | | error: "danger" |
| | | }; |
| | | return typeMap[params] || "info"; |
| | | } |
| | | }, |
| | | { |
| | | label: "æè¿°", |
| | | prop: "description", |
| | | // width: 300, |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "å建æ¶é´", |
| | | prop: "createTime", |
| | | // width: 180, |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 150, |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openForm("edit", row); |
| | | } |
| | | form: { |
| | | programName: "", |
| | | status: "", |
| | | description: "", |
| | | }, |
| | | dialogVisible: false, |
| | | dialogTitle: "", |
| | | dialogType: "add", |
| | | tableLoading: false, |
| | | page: { |
| | | current: 1, |
| | | size: 20, |
| | | total: 0, |
| | | }, |
| | | tableData: [], |
| | | }); |
| | | |
| | | const { |
| | | searchForm, |
| | | form, |
| | | dialogVisible, |
| | | dialogTitle, |
| | | dialogType, |
| | | selectedIds, |
| | | tableLoading, |
| | | page, |
| | | tableData, |
| | | } = toRefs(data); |
| | | |
| | | // 表åå¼ç¨ |
| | | const formRef = ref(); |
| | | // éæ©çè¡æ°æ® |
| | | const selectedRows = ref([]); |
| | | |
| | | // 表åéªè¯è§å |
| | | const rules = { |
| | | programName: [{ required: true, message: "请è¾å
¥ç¨åºå", trigger: "blur" }], |
| | | status: [{ required: true, message: "è¯·éæ©æ§è¡ç¶æ", trigger: "change" }], |
| | | }; |
| | | |
| | | // è¡¨æ ¼åé
ç½® |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "ç¨åºå", |
| | | prop: "programName", |
| | | // width: 200, |
| | | }, |
| | | { |
| | | label: "æ§è¡ç¶æ", |
| | | prop: "status", |
| | | dataType: "tag", |
| | | // width: 120, |
| | | formatData: params => { |
| | | const statusMap = { |
| | | running: "è¿è¡ä¸", |
| | | stopped: "已忢", |
| | | error: "å¼å¸¸", |
| | | }; |
| | | return statusMap[params] || params; |
| | | }, |
| | | // { |
| | | // name: "å¼å§", |
| | | // type: "text", |
| | | // clickFun: (row) => { |
| | | // handleStart(row); |
| | | // }, |
| | | // disabled: (row) => row.status !== 'stopped' |
| | | // }, |
| | | // { |
| | | // name: "忢", |
| | | // type: "text", |
| | | // clickFun: (row) => { |
| | | // handleStop(row); |
| | | // }, |
| | | // disabled: (row) => row.status === 'stopped' |
| | | // } |
| | | ] |
| | | } |
| | | ]); |
| | | |
| | | |
| | | // çå½å¨æ |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | |
| | | // æ¥è¯¢æ°æ® |
| | | const handleQuery = () => { |
| | | // page.value.current = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | listRpa({...page.value, ...searchForm.value}) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records |
| | | page.total = res.data.total; |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | | }) |
| | | }; |
| | | |
| | | // å页å¤ç |
| | | const pagination = (obj) => { |
| | | page.value.current = obj.page; |
| | | page.value.size = obj.limit; |
| | | handleQuery(); |
| | | }; |
| | | |
| | | // éæ©ååå¤ç |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | |
| | | // æå¼è¡¨å |
| | | const openForm = (type, row) => { |
| | | dialogType.value = type; |
| | | dialogVisible.value = true; |
| | | |
| | | if (type === "add") { |
| | | dialogTitle.value = "æ·»å RPA"; |
| | | } else { |
| | | dialogTitle.value = "ç¼è¾RPA"; |
| | | form.value = { ...row }; |
| | | } |
| | | }; |
| | | |
| | | // æäº¤è¡¨å |
| | | const submitForm = async () => { |
| | | if (!formRef.value) return; |
| | | |
| | | try { |
| | | await formRef.value.validate(); |
| | | |
| | | if (dialogType.value === "add") { |
| | | // æ·»å æ°RPA |
| | | addRpa({...form.value}).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("æ·»å æå"); |
| | | form.value = { |
| | | programName: "", |
| | | status: "", |
| | | description: "" |
| | | formatType: params => { |
| | | const typeMap = { |
| | | running: "success", |
| | | stopped: "info", |
| | | error: "danger", |
| | | }; |
| | | return typeMap[params] || "info"; |
| | | }, |
| | | }, |
| | | { |
| | | label: "æè¿°", |
| | | prop: "description", |
| | | // width: 300, |
| | | showOverflowTooltip: true, |
| | | }, |
| | | { |
| | | label: "å建æ¶é´", |
| | | prop: "createTime", |
| | | // width: 180, |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 150, |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: row => { |
| | | openForm("edit", row); |
| | | }, |
| | | dialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }, |
| | | // { |
| | | // name: "å¼å§", |
| | | // type: "text", |
| | | // clickFun: (row) => { |
| | | // handleStart(row); |
| | | // }, |
| | | // disabled: (row) => row.status !== 'stopped' |
| | | // }, |
| | | // { |
| | | // name: "忢", |
| | | // type: "text", |
| | | // clickFun: (row) => { |
| | | // handleStop(row); |
| | | // }, |
| | | // disabled: (row) => row.status === 'stopped' |
| | | // } |
| | | ], |
| | | }, |
| | | ]); |
| | | |
| | | // çå½å¨æ |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | |
| | | // æ¥è¯¢æ°æ® |
| | | const handleQuery = () => { |
| | | // page.value.current = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | listRpa({ ...page.value, ...searchForm.value }) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }) |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | // å页å¤ç |
| | | const pagination = obj => { |
| | | page.value.current = obj.page; |
| | | page.value.size = obj.limit; |
| | | handleQuery(); |
| | | }; |
| | | |
| | | // éæ©ååå¤ç |
| | | const handleSelectionChange = selection => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | |
| | | // æå¼è¡¨å |
| | | const openForm = (type, row) => { |
| | | dialogType.value = type; |
| | | dialogVisible.value = true; |
| | | |
| | | if (type === "add") { |
| | | dialogTitle.value = "æ·»å RPA"; |
| | | } else { |
| | | // ç¼è¾RPA |
| | | updateRpa({...form.value}).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("æ´æ°æå"); |
| | | dialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | dialogTitle.value = "ç¼è¾RPA"; |
| | | form.value = { ...row }; |
| | | } |
| | | } catch (error) { |
| | | console.error("表åéªè¯å¤±è´¥:", error); |
| | | } |
| | | }; |
| | | }; |
| | | |
| | | // å¼å§RPA |
| | | const handleStart = (row) => { |
| | | ElMessageBox.confirm(`ç¡®å®è¦å¯å¨RPAç¨åº"${row.programName}"åï¼`, "æç¤º", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).then(() => { |
| | | row.status = "running"; |
| | | ElMessage.success("RPAå¯å¨æå"); |
| | | getList(); |
| | | }).catch(() => { |
| | | // ç¨æ·åæ¶ |
| | | }); |
| | | }; |
| | | // æäº¤è¡¨å |
| | | const submitForm = async () => { |
| | | if (!formRef.value) return; |
| | | |
| | | // 忢RPA |
| | | const handleStop = (row) => { |
| | | ElMessageBox.confirm(`ç¡®å®è¦åæ¢RPAç¨åº"${row.programName}"åï¼`, "æç¤º", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).then(() => { |
| | | row.status = "stopped"; |
| | | ElMessage.success("RPA忢æå"); |
| | | getList(); |
| | | }).catch(() => { |
| | | // ç¨æ·åæ¶ |
| | | }); |
| | | }; |
| | | try { |
| | | await formRef.value.validate(); |
| | | |
| | | // å é¤RPA |
| | | const handleDelete = () => { |
| | | let ids = []; |
| | | if (selectedRows.value.length > 0) { |
| | | ids = selectedRows.value.map((item) => item.id); |
| | | } else { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | | } |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "å é¤æç¤º", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | delRpa(ids).then((res) => { |
| | | if(res.code == 200){ |
| | | ElMessage.success("å 餿å"); |
| | | getList(); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }) |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | if (dialogType.value === "add") { |
| | | // æ·»å æ°RPA |
| | | addRpa({ ...form.value }) |
| | | .then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("æ·»å æå"); |
| | | (form.value = { |
| | | programName: "", |
| | | status: "", |
| | | description: "", |
| | | }), |
| | | (dialogVisible.value = false); |
| | | getList(); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | } else { |
| | | // ç¼è¾RPA |
| | | updateRpa({ ...form.value }) |
| | | .then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("æ´æ°æå"); |
| | | dialogVisible.value = false; |
| | | getList(); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | } |
| | | } catch (error) { |
| | | console.error("表åéªè¯å¤±è´¥:", error); |
| | | } |
| | | }; |
| | | |
| | | // 导åºåè½ |
| | | const { proxy } = getCurrentInstance() |
| | | const handleExport = () => { |
| | | proxy.download('/rpaProcessAutomation/export', { ...searchForm.value }, 'RPA管ç.xlsx') |
| | | } |
| | | // å¼å§RPA |
| | | const handleStart = row => { |
| | | ElMessageBox.confirm(`ç¡®å®è¦å¯å¨RPAç¨åº"${row.programName}"åï¼`, "æç¤º", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | row.status = "running"; |
| | | ElMessage.success("RPAå¯å¨æå"); |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | // ç¨æ·åæ¶ |
| | | }); |
| | | }; |
| | | |
| | | // 忢RPA |
| | | const handleStop = row => { |
| | | ElMessageBox.confirm(`ç¡®å®è¦åæ¢RPAç¨åº"${row.programName}"åï¼`, "æç¤º", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | row.status = "stopped"; |
| | | ElMessage.success("RPA忢æå"); |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | // ç¨æ·åæ¶ |
| | | }); |
| | | }; |
| | | |
| | | // å é¤RPA |
| | | const handleDelete = () => { |
| | | let ids = []; |
| | | if (selectedRows.value.length > 0) { |
| | | ids = selectedRows.value.map(item => item.id); |
| | | } else { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | | } |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "å é¤æç¤º", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | delRpa(ids) |
| | | .then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("å 餿å"); |
| | | getList(); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | |
| | | // 导åºåè½ |
| | | const { proxy } = getCurrentInstance(); |
| | | const handleExport = () => { |
| | | 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 class="card-header"> |
| | | <span>è§ç« å¶åº¦åå¸</span> |
| | | </div> |
| | | <!-- è§ç« å¶åº¦ç®¡ç--> |
| | | <el-card class="box-card"> |
| | | <template #header> |
| | | <div class="card-header"> |
| | | <span>è§ç« å¶åº¦åå¸</span> |
| | | </div> |
| | | </template> |
| | | <div class="tab-content"> |
| | | <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-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> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <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> |
| | | </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"> |
| | | <template #default="scope"> |
| | | <el-tag>{{ getCategoryText(scope.row.category) }}</el-tag> |
| | | </template> |
| | | <div class="tab-content"> |
| | | <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-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> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <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> |
| | | </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"> |
| | | <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"> |
| | | <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"> |
| | | <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> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </el-card> |
| | | |
| | | </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"> |
| | | <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"> |
| | | <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> |
| | | </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 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' |
| | | }) |
| | | // ååºå¼æ°æ® |
| | | 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 sealForm = reactive({ |
| | | 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' }] |
| | | } |
| | | 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" }], |
| | | }; |
| | | |
| | | const sealSearchForm = reactive({ |
| | | title: '', |
| | | status: '' |
| | | }) |
| | | // å页忰 |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 10, |
| | | total: 0 |
| | | }) |
| | | // è§ç« å¶åº¦ç¸å
³ |
| | | const showRegulationDialog = ref(false) |
| | | const showRegulationDetailDialog = ref(false) |
| | | const showVersionHistoryDialog = ref(false) |
| | | const showReadStatusDialog = ref(false) |
| | | const currentRegulationDetail = ref(null) |
| | | const regulationFormRef = ref() |
| | | const regulationForm = reactive({ |
| | | id: '', |
| | | regulationNum: '', |
| | | title: '', |
| | | category: '', |
| | | content: '', |
| | | version: '', |
| | | status: 'active', |
| | | readCount: 0, |
| | | effectiveTime: '', |
| | | scope: [], |
| | | requireConfirm: false |
| | | }) |
| | | const sealSearchForm = reactive({ |
| | | title: "", |
| | | status: "", |
| | | }); |
| | | // å页忰 |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 10, |
| | | total: 0, |
| | | }); |
| | | // è§ç« å¶åº¦ç¸å
³ |
| | | const showRegulationDialog = ref(false); |
| | | const showRegulationDetailDialog = ref(false); |
| | | const showVersionHistoryDialog = ref(false); |
| | | const showReadStatusDialog = ref(false); |
| | | const currentRegulationDetail = ref(null); |
| | | const regulationFormRef = ref(); |
| | | const regulationForm = reactive({ |
| | | id: "", |
| | | regulationNum: "", |
| | | title: "", |
| | | category: "", |
| | | content: "", |
| | | version: "", |
| | | status: "active", |
| | | readCount: 0, |
| | | effectiveTime: "", |
| | | scope: [], |
| | | requireConfirm: false, |
| | | }); |
| | | |
| | | const readStatus = ref({ |
| | | id: '', |
| | | ruleId: '', |
| | | employee: '', |
| | | department: '', |
| | | createTime: '', |
| | | confirmTime: '', |
| | | status: 'unconfirmed' |
| | | }) |
| | | const readStatus = ref({ |
| | | id: "", |
| | | ruleId: "", |
| | | employee: "", |
| | | department: "", |
| | | createTime: "", |
| | | confirmTime: "", |
| | | status: "unconfirmed", |
| | | }); |
| | | |
| | | const regulationRules = { |
| | | title: [{ required: true, message: '请è¾å
¥å¶åº¦æ é¢', trigger: 'blur' }], |
| | | category: [{ required: true, message: 'è¯·éæ©å¶åº¦åç±»', trigger: 'change' }], |
| | | content: [{ required: true, message: '请è¾å
¥å¶åº¦å
容', trigger: 'blur' }], |
| | | effectiveTime: [{ required: true, message: 'è¯·éæ©çææ¶é´', trigger: 'change' }], |
| | | scope: [{ required: true, message: 'è¯·éæ©éç¨èå´', trigger: 'change' }] |
| | | } |
| | | const regulationRules = { |
| | | title: [{ required: true, message: "请è¾å
¥å¶åº¦æ é¢", trigger: "blur" }], |
| | | category: [{ required: true, message: "è¯·éæ©å¶åº¦åç±»", trigger: "change" }], |
| | | content: [{ required: true, message: "请è¾å
¥å¶åº¦å
容", trigger: "blur" }], |
| | | effectiveTime: [ |
| | | { required: true, message: "è¯·éæ©çææ¶é´", trigger: "change" }, |
| | | ], |
| | | scope: [{ required: true, message: "è¯·éæ©éç¨èå´", trigger: "change" }], |
| | | }; |
| | | |
| | | const regulationSearchForm = reactive({ |
| | | title: '', |
| | | category: '' |
| | | }) |
| | | const regulationSearchForm = reactive({ |
| | | 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 statusMap = { |
| | | pending: 'warning', |
| | | approved: 'success', |
| | | rejected: 'danger' |
| | | } |
| | | return statusMap[status] || 'info' |
| | | } |
| | | // å¶åº¦ç¶æ |
| | | const getStatusText = (status) => { |
| | | const statusMap = { |
| | | pending: 'å¾
审æ¹', |
| | | approved: 'å·²éè¿', |
| | | rejected: 'å·²æç»' |
| | | } |
| | | return statusMap[status] || 'æªç¥' |
| | | } |
| | | // ç¨å°ç±»å |
| | | const getSealTypeText = (sealType) => { |
| | | const sealTypeMap = { |
| | | official: 'å
¬ç« ', |
| | | contract: 'ååä¸ç¨ç« ', |
| | | finance: 'è´¢å¡ä¸ç¨ç« ', |
| | | tegal: 'ææ¯ä¸ç¨ç« ' |
| | | } |
| | | return sealTypeMap[sealType] || 'æªç¥' |
| | | } |
| | | // å¶åº¦åç±» |
| | | const getCategoryText = (category) => { |
| | | const categoryMap = { |
| | | hr: '人äºå¶åº¦', |
| | | finance: 'è´¢å¡å¶åº¦', |
| | | safety: 'å®å
¨å¶åº¦', |
| | | tech: 'ææ¯å¶åº¦' |
| | | } |
| | | return categoryMap[category] || 'æªç¥' |
| | | } |
| | | // æç´¢å°ç« ç³è¯· |
| | | const searchSealApplications = () => { |
| | | page.current=1 |
| | | getSealApplicationList() |
| | | // ç¨å°ç³è¯·ç¶æ |
| | | const getStatusType = status => { |
| | | const statusMap = { |
| | | pending: "warning", |
| | | approved: "success", |
| | | rejected: "danger", |
| | | }; |
| | | return statusMap[status] || "info"; |
| | | }; |
| | | // å¶åº¦ç¶æ |
| | | const getStatusText = status => { |
| | | const statusMap = { |
| | | pending: "å¾
审æ¹", |
| | | approved: "å·²éè¿", |
| | | rejected: "å·²æç»", |
| | | }; |
| | | return statusMap[status] || "æªç¥"; |
| | | }; |
| | | // ç¨å°ç±»å |
| | | const getSealTypeText = sealType => { |
| | | const sealTypeMap = { |
| | | official: "å
¬ç« ", |
| | | contract: "ååä¸ç¨ç« ", |
| | | finance: "è´¢å¡ä¸ç¨ç« ", |
| | | tegal: "ææ¯ä¸ç¨ç« ", |
| | | }; |
| | | return sealTypeMap[sealType] || "æªç¥"; |
| | | }; |
| | | // å¶åº¦åç±» |
| | | const getCategoryText = category => { |
| | | const categoryMap = { |
| | | hr: "人äºå¶åº¦", |
| | | finance: "è´¢å¡å¶åº¦", |
| | | safety: "å®å
¨å¶åº¦", |
| | | tech: "ææ¯å¶åº¦", |
| | | }; |
| | | return categoryMap[category] || "æªç¥"; |
| | | }; |
| | | // æç´¢å°ç« ç³è¯· |
| | | const searchSealApplications = () => { |
| | | page.current = 1; |
| | | getSealApplicationList(); |
| | | |
| | | // ElMessage.success('æç´¢å®æ') |
| | | } |
| | | // éç½®å°ç« ç³è¯·æç´¢ |
| | | const resetSealSearch = () => { |
| | | sealSearchForm.title = '' |
| | | sealSearchForm.status = '' |
| | | searchSealApplications() |
| | | } |
| | | // æç´¢å¶åº¦ |
| | | const searchRegulations = () => { |
| | | page.current=1 |
| | | getRegulationList() |
| | | } |
| | | // éç½®å¶åº¦æç´¢ |
| | | const resetRegulationSearch = () => { |
| | | regulationSearchForm.title = '' |
| | | regulationSearchForm.category = '' |
| | | searchRegulations() |
| | | } |
| | | // æäº¤ç¨å°ç³è¯· |
| | | const submitSealApplication = async () => { |
| | | try { |
| | | await sealFormRef.value.validate() |
| | | addSealApplication(sealForm).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('ç³è¯·æäº¤æå') |
| | | showSealApplyDialog.value = false |
| | | getSealApplicationList() |
| | | Object.assign(sealForm, { |
| | | applicationNum: '', |
| | | title: '', |
| | | sealType: '', |
| | | reason: '', |
| | | urgency: 'normal', |
| | | status: 'pending' |
| | | // ElMessage.success('æç´¢å®æ') |
| | | }; |
| | | // éç½®å°ç« ç³è¯·æç´¢ |
| | | const resetSealSearch = () => { |
| | | sealSearchForm.title = ""; |
| | | sealSearchForm.status = ""; |
| | | searchSealApplications(); |
| | | }; |
| | | // æç´¢å¶åº¦ |
| | | const searchRegulations = () => { |
| | | page.current = 1; |
| | | getRegulationList(); |
| | | }; |
| | | // éç½®å¶åº¦æç´¢ |
| | | const resetRegulationSearch = () => { |
| | | regulationSearchForm.title = ""; |
| | | regulationSearchForm.category = ""; |
| | | searchRegulations(); |
| | | }; |
| | | // æäº¤ç¨å°ç³è¯· |
| | | const submitSealApplication = async () => { |
| | | try { |
| | | await sealFormRef.value.validate(); |
| | | addSealApplication(sealForm) |
| | | .then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("ç³è¯·æäº¤æå"); |
| | | showSealApplyDialog.value = false; |
| | | getSealApplicationList(); |
| | | Object.assign(sealForm, { |
| | | applicationNum: "", |
| | | title: "", |
| | | sealType: "", |
| | | reason: "", |
| | | urgency: "normal", |
| | | status: "pending", |
| | | }); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | } catch (error) { |
| | | ElMessage.error("请å®åç³è¯·ä¿¡æ¯"); |
| | | } |
| | | }; |
| | | // æ°å¢ |
| | | const handleAdd = () => { |
| | | operationType.value = "add"; |
| | | resetRegulationForm(); |
| | | showRegulationDialog.value = true; |
| | | }; |
| | | |
| | | // ç¼è¾ |
| | | const handleEdit = row => { |
| | | operationType.value = "edit"; |
| | | Object.assign(regulationForm, row); |
| | | showRegulationDialog.value = true; |
| | | }; |
| | | // åºå¼ |
| | | const repealEdit = row => { |
| | | operationType.value = "edit"; |
| | | Object.assign(regulationForm, row); |
| | | regulationForm.status = "repealed"; |
| | | ElMessageBox.confirm("确认åºå¼è¯¥å¶åº¦ï¼", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | updateRuleManagement(regulationForm).then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("å¶åº¦åºå¼æå"); |
| | | // showRegulationDialog.value = false |
| | | getRegulationList(); |
| | | resetRegulationForm(); |
| | | } |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | ElMessage({ |
| | | type: "info", |
| | | message: "已忶åºå¼", |
| | | }); |
| | | }); |
| | | }; |
| | | // åå¸å¶åº¦ |
| | | const submitRegulation = async () => { |
| | | try { |
| | | await regulationFormRef.value.validate(); |
| | | if (operationType.value == "add") { |
| | | addRuleManagement(regulationForm).then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("å¶åº¦å叿å"); |
| | | showRegulationDialog.value = false; |
| | | getRegulationList(); |
| | | resetRegulationForm(); |
| | | } |
| | | }); |
| | | } else { |
| | | updateRuleManagement(regulationForm).then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("å¶åº¦ç¼è¾æå"); |
| | | showRegulationDialog.value = false; |
| | | resetRegulationForm(); |
| | | getRegulationList(); |
| | | } |
| | | }); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg) |
| | | }) |
| | | |
| | | } catch (error) { |
| | | ElMessage.error('请å®åç³è¯·ä¿¡æ¯') |
| | | } |
| | | } |
| | | // æ°å¢ |
| | | const handleAdd = () => { |
| | | operationType.value = 'add' |
| | | resetRegulationForm() |
| | | showRegulationDialog.value = true |
| | | } |
| | | } catch (err) { |
| | | ElMessage.error(err.msg); |
| | | } |
| | | }; |
| | | //éç½®å¶åº¦è¡¨å |
| | | const resetRegulationForm = () => { |
| | | Object.assign(regulationForm, { |
| | | id: "", |
| | | regulationNum: "", |
| | | title: "", |
| | | category: "", |
| | | content: "", |
| | | version: "", |
| | | status: "active", |
| | | readCount: 0, |
| | | effectiveTime: "", |
| | | scope: [], |
| | | requireConfirm: false, |
| | | }); |
| | | }; |
| | | |
| | | // ç¼è¾ |
| | | const handleEdit = (row) => { |
| | | operationType.value = 'edit' |
| | | Object.assign(regulationForm, row) |
| | | showRegulationDialog.value = true |
| | | } |
| | | // åºå¼ |
| | | const repealEdit = (row) => { |
| | | operationType.value = 'edit' |
| | | Object.assign(regulationForm, row) |
| | | regulationForm.status = 'repealed' |
| | | ElMessageBox.confirm('确认åºå¼è¯¥å¶åº¦ï¼', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | }).then(() => { |
| | | updateRuleManagement(regulationForm).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('å¶åº¦åºå¼æå') |
| | | // showRegulationDialog.value = false |
| | | getRegulationList() |
| | | resetRegulationForm() |
| | | // æ¥çç¨å°ç³è¯·è¯¦æ
|
| | | const viewSealDetail = row => { |
| | | currentSealDetail.value = row; |
| | | showSealDetailDialog.value = true; |
| | | }; |
| | | // 审æ¹ç¨å°ç³è¯· |
| | | const approveSeal = row => { |
| | | console.log(row); |
| | | ElMessageBox.confirm("确认éè¿è¯¥ç¨å°ç³è¯·ï¼", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).then(() => { |
| | | row.status = "approved"; |
| | | updateSealApplication(row).then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("审æ¹éè¿"); |
| | | } |
| | | }); |
| | | }); |
| | | }; |
| | | // æç»ç¨å°ç³è¯· |
| | | const rejectSeal = row => { |
| | | ElMessageBox.prompt("请è¾å
¥æç»åå ", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | inputPattern: /\S+/, |
| | | inputErrorMessage: "æç»åå ä¸è½ä¸ºç©º", |
| | | }).then(({ value }) => { |
| | | row.status = "rejected"; |
| | | updateSealApplication(row).then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("å®¡æ¹æç»"); |
| | | } |
| | | }); |
| | | ElMessage.success("å·²æç»ç³è¯·"); |
| | | }); |
| | | }; |
| | | // è·åå¨èåå·¥å表 |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | //è·åå½åç»å½ç¨æ·ä¿¡æ¯ |
| | | getUserProfile().then(res => { |
| | | if (res.code == 200) { |
| | | console.log(res.data.userName); |
| | | currentUser.value = res.data.userName; |
| | | } |
| | | }) |
| | | }).catch(() => { |
| | | ElMessage({ |
| | | type: 'info', |
| | | message: '已忶åºå¼' |
| | | }) |
| | | }) |
| | | } |
| | | // åå¸å¶åº¦ |
| | | const submitRegulation = async () => { |
| | | try { |
| | | await regulationFormRef.value.validate() |
| | | if(operationType.value == 'add'){ |
| | | addRuleManagement(regulationForm).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('å¶åº¦å叿å') |
| | | showRegulationDialog.value = false |
| | | getRegulationList() |
| | | resetRegulationForm() |
| | | }); |
| | | 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); |
| | | page.total = res.data.total; |
| | | |
| | | if (tableData.value.length == 0) { |
| | | ElMessage.error("å½åç¨æ·æªå å
¥ä»»ä½é¨é¨"); |
| | | } |
| | | }) |
| | | }else{ |
| | | updateRuleManagement(regulationForm).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('å¶åº¦ç¼è¾æå') |
| | | showRegulationDialog.value = false |
| | | resetRegulationForm() |
| | | getRegulationList() |
| | | }})} |
| | | }catch(err){ |
| | | ElMessage.error(err.msg) |
| | | } |
| | | } |
| | | //éç½®å¶åº¦è¡¨å |
| | | const resetRegulationForm = () => { |
| | | Object.assign(regulationForm, { |
| | | id: '', |
| | | regulationNum: '', |
| | | title: '', |
| | | category: '', |
| | | content: '', |
| | | version: '', |
| | | status: 'active', |
| | | readCount: 0, |
| | | effectiveTime: '', |
| | | scope: [], |
| | | requireConfirm: false |
| | | }) |
| | | } |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | |
| | | // æ¥çç¨å°ç³è¯·è¯¦æ
|
| | | const viewSealDetail = (row) => { |
| | | currentSealDetail.value = row |
| | | showSealDetailDialog.value = true |
| | | } |
| | | // 审æ¹ç¨å°ç³è¯· |
| | | const approveSeal = (row) => { |
| | | console.log(row) |
| | | ElMessageBox.confirm('确认éè¿è¯¥ç¨å°ç³è¯·ï¼', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | }).then(() => { |
| | | row.status = 'approved' |
| | | updateSealApplication(row).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('审æ¹éè¿') |
| | | // æ¥çå¶åº¦çæ¬åå² |
| | | const viewVersionHistory = row => { |
| | | showVersionHistoryDialog.value = true; |
| | | const params = { |
| | | category: row.category, |
| | | }; |
| | | listRuleManagement(page, params).then(res => { |
| | | if (res.code == 200) { |
| | | versionHistory.value = res.data.records; |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | // æç»ç¨å°ç³è¯· |
| | | const rejectSeal = (row) => { |
| | | ElMessageBox.prompt('请è¾å
¥æç»åå ', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | inputPattern: /\S+/, |
| | | inputErrorMessage: 'æç»åå ä¸è½ä¸ºç©º' |
| | | }).then(({ value }) => { |
| | | row.status = 'rejected' |
| | | updateSealApplication(row).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('å®¡æ¹æç»') |
| | | } |
| | | }) |
| | | ElMessage.success('å·²æç»ç³è¯·') |
| | | }) |
| | | } |
| | | // è·åå¨èåå·¥å表 |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | //è·åå½åç»å½ç¨æ·ä¿¡æ¯ |
| | | getUserProfile().then(res => { |
| | | if(res.code == 200){ |
| | | console.log(res.data.userName) |
| | | currentUser.value = res.data.userName |
| | | } |
| | | }) |
| | | 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) |
| | | page.total = res.data.total; |
| | | |
| | | if(tableData.value.length == 0){ |
| | | ElMessage.error('å½åç¨æ·æªå å
¥ä»»ä½é¨é¨') |
| | | } |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | | }) |
| | | |
| | | |
| | | }; |
| | | |
| | | // æ¥çå¶åº¦çæ¬åå² |
| | | const viewVersionHistory = (row) => { |
| | | showVersionHistoryDialog.value = true |
| | | const params = { |
| | | |
| | | category: row.category |
| | | } |
| | | listRuleManagement(page,params).then(res => { |
| | | if(res.code == 200){ |
| | | versionHistory.value = res.data.records |
| | | } |
| | | }) |
| | | } |
| | | // æ¥çå¶åº¦è¯¦æ
|
| | | const viewRegulation = (row) => { |
| | | getList() |
| | | currentRegulationDetail.value = row |
| | | showRegulationDetailDialog.value = true |
| | | getReadingStatusByRuleId(row.id).then(res => { |
| | | if(res.code == 200){ |
| | | readStatusList.value = res.data |
| | | if(readStatusList.value.length==0 && tableData.value.length>0){ |
| | | }); |
| | | }; |
| | | // æ¥çå¶åº¦è¯¦æ
|
| | | const viewRegulation = row => { |
| | | getList(); |
| | | currentRegulationDetail.value = row; |
| | | showRegulationDetailDialog.value = true; |
| | | getReadingStatusByRuleId(row.id).then(res => { |
| | | if (res.code == 200) { |
| | | readStatusList.value = res.data; |
| | | if (readStatusList.value.length == 0 && tableData.value.length > 0) { |
| | | const params = { |
| | | ruleId: row.id, |
| | | employee: tableData.value[0].staffName, |
| | | department: tableData.value[0].postJob, |
| | | status: 'unconfirmed' |
| | | ruleId: row.id, |
| | | employee: tableData.value[0].staffName, |
| | | department: tableData.value[0].postJob, |
| | | status: "unconfirmed", |
| | | }; |
| | | addReadingStatus(params).then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("å¶åº¦é
读æå"); |
| | | } |
| | | }); |
| | | } |
| | | addReadingStatus(params).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('å¶åº¦é
读æå') |
| | | } |
| | | }) |
| | | } |
| | | } |
| | | }) |
| | | |
| | | } |
| | | // æ¥çå¶åº¦é
è¯»ç¶æ |
| | | const viewReadStatus = (row) => { |
| | | showReadStatusDialog.value = true |
| | | //æ¥çé
è¯»ç¶æå表 |
| | | getReadingStatusByRuleId(row.id).then(res => { |
| | | if(res.code == 200){ |
| | | readStatusList.value = res.data |
| | | } |
| | | }) |
| | | } |
| | | |
| | | //确认æ¥ç |
| | | const resetForm = (row) => { |
| | | console.log("row",row) |
| | | row.readCount = row.readCount + 1 |
| | | |
| | | updateRuleManagement(row).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('æ¥çæ°éä¿®æ¹æå') |
| | | //ä¿®æ¹é
è¯»ç¶æ |
| | | //æ ¹æ®å¶åº¦idåå½åç»å½çåå·¥å¾å°é
è¯»ç¶æ |
| | | // let item = readStatusList.value.filter(item => item.employee == tableData.value[0].staffName ) |
| | | // if(item.length>0){ |
| | | // item[0].status = 'confirmed', |
| | | // item[0].confirmTime = new Date().toISOString().replace('T', ' ').split('.')[0]; |
| | | // } |
| | | // çéå½åå工对åºè¯¥å¶åº¦çé
è¯»ç¶æè®°å½ |
| | | let statusItem = readStatusList.value.find(item => item.employee === tableData.value[0].staffName && item.ruleId === row.id); |
| | | |
| | | if (statusItem) { |
| | | // 妿æ¾å°è®°å½ï¼æ´æ°ç¶æå确认æ¶é´ |
| | | statusItem.status = 'confirmed'; |
| | | // æ ¼å¼åæ¶é´ä¸º"YYYY-MM-DD HH:mm:ss"æ ¼å¼ |
| | | const now = new Date(); |
| | | statusItem.confirmTime = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}:${String(now.getSeconds()).padStart(2, '0')}`; |
| | | // statusItem.confirmTime = new Date().toISOString().replace('T', ' ').split('.')[0]; |
| | | |
| | | updateReadingStatus(statusItem).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('å¶åº¦é
è¯»ç¶æä¿®æ¹æå') |
| | | } |
| | | }) |
| | | }); |
| | | }; |
| | | // æ¥çå¶åº¦é
è¯»ç¶æ |
| | | const viewReadStatus = row => { |
| | | showReadStatusDialog.value = true; |
| | | //æ¥çé
è¯»ç¶æå表 |
| | | getReadingStatusByRuleId(row.id).then(res => { |
| | | if (res.code == 200) { |
| | | readStatusList.value = res.data; |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | } |
| | | }) |
| | | } |
| | | //确认æ¥ç |
| | | const resetForm = row => { |
| | | console.log("row", row); |
| | | row.readCount = row.readCount + 1; |
| | | |
| | | // 导åºè§ç« å¶åº¦ |
| | | const { proxy } = getCurrentInstance() |
| | | const handleExport = () => { |
| | | proxy.download('/rulesRegulationsManagement/export', { ...regulationSearchForm }, 'è§ç« å¶åº¦.xlsx') |
| | | } |
| | | updateRuleManagement(row).then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("æ¥çæ°éä¿®æ¹æå"); |
| | | //ä¿®æ¹é
è¯»ç¶æ |
| | | //æ ¹æ®å¶åº¦idåå½åç»å½çåå·¥å¾å°é
è¯»ç¶æ |
| | | // let item = readStatusList.value.filter(item => item.employee == tableData.value[0].staffName ) |
| | | // if(item.length>0){ |
| | | // item[0].status = 'confirmed', |
| | | // item[0].confirmTime = new Date().toISOString().replace('T', ' ').split('.')[0]; |
| | | // } |
| | | // çéå½åå工对åºè¯¥å¶åº¦çé
è¯»ç¶æè®°å½ |
| | | let statusItem = readStatusList.value.find( |
| | | item => |
| | | item.employee === tableData.value[0].staffName && |
| | | item.ruleId === row.id |
| | | ); |
| | | |
| | | // è·åå°ç« ç³è¯·åè¡¨æ°æ® |
| | | const getSealApplicationList = async () => { |
| | | tableLoading.value = true |
| | | listSealApplication(page,sealSearchForm) |
| | | .then(res => { |
| | | //è·åå½åç»å½çé¨é¨ä¿¡æ¯ |
| | | // è·åå½åç»å½çé¨é¨ä¿¡æ¯å¹¶è¿æ»¤æ°æ® |
| | | const currentFactoryName = userStore.currentFactoryName |
| | | if (currentFactoryName) { |
| | | // æ ¹æ®currentFactoryNameè¿æ»¤åºdepartmentç¸åçæ°æ® |
| | | sealApplications.value = res.data.records.filter(item => item.department === currentFactoryName) |
| | | // æ´æ°è¿æ»¤åçæ»æ° |
| | | page.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; |
| | | tableLoading.value = false; |
| | | if (statusItem) { |
| | | // 妿æ¾å°è®°å½ï¼æ´æ°ç¶æå确认æ¶é´ |
| | | statusItem.status = "confirmed"; |
| | | // æ ¼å¼åæ¶é´ä¸º"YYYY-MM-DD HH:mm:ss"æ ¼å¼ |
| | | const now = new Date(); |
| | | statusItem.confirmTime = `${now.getFullYear()}-${String( |
| | | now.getMonth() + 1 |
| | | ).padStart(2, "0")}-${String(now.getDate()).padStart(2, "0")} ${String( |
| | | now.getHours() |
| | | ).padStart(2, "0")}:${String(now.getMinutes()).padStart( |
| | | 2, |
| | | "0" |
| | | )}:${String(now.getSeconds()).padStart(2, "0")}`; |
| | | // statusItem.confirmTime = new Date().toISOString().replace('T', ' ').split('.')[0]; |
| | | |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | | }) |
| | | } |
| | | // è·åè§ç« å¶åº¦åè¡¨æ°æ® |
| | | const getRegulationList = async () => { |
| | | tableLoading.value = true |
| | | listRuleManagement(page,regulationSearchForm) |
| | | .then(res => { |
| | | updateReadingStatus(statusItem).then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("å¶åº¦é
è¯»ç¶æä¿®æ¹æå"); |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | regulations.value = res.data.records |
| | | // è¿æ»¤æå·²åºå¼çå¶åº¦ |
| | | // regulations.value = res.data.records.filter(item => item.status !== 'repealed') |
| | | page.value.total = res.data.total; |
| | | tableLoading.value = false; |
| | | // 导åºè§ç« å¶åº¦ |
| | | const { proxy } = getCurrentInstance(); |
| | | const handleExport = () => { |
| | | proxy.download( |
| | | "/rulesRegulationsManagement/export", |
| | | { ...regulationSearchForm }, |
| | | "è§ç« å¶åº¦.xlsx" |
| | | ); |
| | | }; |
| | | |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | | }) |
| | | } |
| | | // è·åå°ç« ç³è¯·åè¡¨æ°æ® |
| | | const getSealApplicationList = async () => { |
| | | tableLoading.value = true; |
| | | listSealApplication(page, sealSearchForm) |
| | | .then(res => { |
| | | //è·åå½åç»å½çé¨é¨ä¿¡æ¯ |
| | | // è·åå½åç»å½çé¨é¨ä¿¡æ¯å¹¶è¿æ»¤æ°æ® |
| | | const currentFactoryName = userStore.currentFactoryName; |
| | | if (currentFactoryName) { |
| | | // æ ¹æ®currentFactoryNameè¿æ»¤åºdepartmentç¸åçæ°æ® |
| | | sealApplications.value = res.data.records.filter( |
| | | item => item.department === currentFactoryName |
| | | ); |
| | | // æ´æ°è¿æ»¤åçæ»æ° |
| | | page.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; |
| | | tableLoading.value = false; |
| | | }) |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | // è·åè§ç« å¶åº¦åè¡¨æ°æ® |
| | | const getRegulationList = async () => { |
| | | tableLoading.value = true; |
| | | listRuleManagement(page, regulationSearchForm) |
| | | .then(res => { |
| | | regulations.value = res.data.records; |
| | | // è¿æ»¤æå·²åºå¼çå¶åº¦ |
| | | // regulations.value = res.data.records.filter(item => item.status !== 'repealed') |
| | | page.value.total = res.data.total; |
| | | tableLoading.value = false; |
| | | }) |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | // åå§å |
| | | getSealApplicationList() |
| | | getRegulationList() |
| | | }) |
| | | onMounted(() => { |
| | | // åå§å |
| | | getSealApplicationList(); |
| | | getRegulationList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .app-container { |
| | | padding: 20px; |
| | | } |
| | | .app-container { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .card-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | .card-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | |
| | | .tab-content { |
| | | padding: 20px 0; |
| | | } |
| | | .tab-content { |
| | | padding: 20px 0; |
| | | } |
| | | |
| | | .mb-20 { |
| | | margin-bottom: 20px; |
| | | } |
| | | .mb-20 { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .mt-20 { |
| | | margin-top: 20px; |
| | | } |
| | | .mt-20 { |
| | | margin-top: 20px; |
| | | } |
| | | |
| | | .ml-10 { |
| | | margin-left: 10px; |
| | | } |
| | | .ml-10 { |
| | | margin-left: 10px; |
| | | } |
| | | |
| | | .regulation-content { |
| | | background-color: #f5f5f5; |
| | | padding: 15px; |
| | | border-radius: 4px; |
| | | line-height: 1.6; |
| | | white-space: pre-wrap; |
| | | height: 200px; |
| | | } |
| | | .regulation-content { |
| | | background-color: #f5f5f5; |
| | | padding: 15px; |
| | | border-radius: 4px; |
| | | line-height: 1.6; |
| | | white-space: pre-wrap; |
| | | height: 200px; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | gap: 10px; |
| | | } |
| | | .dialog-footer { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | gap: 10px; |
| | | } |
| | | </style> |
| | |
| | | <span>ç¨å°ç®¡çåå¸</span> |
| | | </div> |
| | | </template> |
| | | |
| | | |
| | | <!-- ç¨å°ç³è¯·ç®¡ç --> |
| | | <div class="tab-content"> |
| | | <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-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> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <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> |
| | | </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"> |
| | | <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"> |
| | | <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"> |
| | | <template #default="scope"> |
| | | <el-button link @click="viewSealDetail(scope.row)">æ¥ç</el-button> |
| | | <el-button |
| | | v-if="scope.row.status === 'pending'" |
| | | link |
| | | type="primary" |
| | | @click="approveSeal(scope.row)" |
| | | > |
| | | å®¡æ¹ |
| | | </el-button> |
| | | <el-button |
| | | v-if="scope.row.status === 'pending'" |
| | | link |
| | | type="danger" |
| | | @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" /> |
| | | </div> |
| | | <!-- ç¨å°ç³è¯·ç®¡ç --> |
| | | <div class="tab-content"> |
| | | <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-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> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <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> |
| | | </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"> |
| | | <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"> |
| | | <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"> |
| | | <template #default="scope"> |
| | | <el-button link |
| | | @click="viewSealDetail(scope.row)">æ¥ç</el-button> |
| | | <el-button v-if="scope.row.status === 'pending'" |
| | | link |
| | | type="primary" |
| | | @click="approveSeal(scope.row)"> |
| | | å®¡æ¹ |
| | | </el-button> |
| | | <el-button v-if="scope.row.status === 'pending'" |
| | | link |
| | | type="danger" |
| | | @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" /> |
| | | </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 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' |
| | | }) |
| | | // ååºå¼æ°æ® |
| | | 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 sealForm = reactive({ |
| | | 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' }] |
| | | } |
| | | 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" }], |
| | | }; |
| | | |
| | | const sealSearchForm = reactive({ |
| | | title: '', |
| | | status: '' |
| | | }) |
| | | // å页忰 |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0 |
| | | }) |
| | | // è§ç« å¶åº¦ç¸å
³ |
| | | const showRegulationDialog = ref(false) |
| | | const showRegulationDetailDialog = ref(false) |
| | | const showVersionHistoryDialog = ref(false) |
| | | const showReadStatusDialog = ref(false) |
| | | const currentRegulationDetail = ref(null) |
| | | const regulationFormRef = ref() |
| | | const regulationForm = reactive({ |
| | | id: '', |
| | | regulationNum: '', |
| | | title: '', |
| | | category: '', |
| | | content: '', |
| | | version: '', |
| | | status: 'active', |
| | | readCount: 0, |
| | | effectiveTime: '', |
| | | scope: [], |
| | | requireConfirm: false |
| | | }) |
| | | const sealSearchForm = reactive({ |
| | | title: "", |
| | | status: "", |
| | | }); |
| | | // å页忰 |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | // è§ç« å¶åº¦ç¸å
³ |
| | | const showRegulationDialog = ref(false); |
| | | const showRegulationDetailDialog = ref(false); |
| | | const showVersionHistoryDialog = ref(false); |
| | | const showReadStatusDialog = ref(false); |
| | | const currentRegulationDetail = ref(null); |
| | | const regulationFormRef = ref(); |
| | | const regulationForm = reactive({ |
| | | id: "", |
| | | regulationNum: "", |
| | | title: "", |
| | | category: "", |
| | | content: "", |
| | | version: "", |
| | | status: "active", |
| | | readCount: 0, |
| | | effectiveTime: "", |
| | | scope: [], |
| | | requireConfirm: false, |
| | | }); |
| | | |
| | | const readStatus = ref({ |
| | | id: '', |
| | | ruleId: '', |
| | | employee: '', |
| | | department: '', |
| | | createTime: '', |
| | | confirmTime: '', |
| | | status: 'unconfirmed' |
| | | }) |
| | | const readStatus = ref({ |
| | | id: "", |
| | | ruleId: "", |
| | | employee: "", |
| | | department: "", |
| | | createTime: "", |
| | | confirmTime: "", |
| | | status: "unconfirmed", |
| | | }); |
| | | |
| | | const regulationRules = { |
| | | title: [{ required: true, message: '请è¾å
¥å¶åº¦æ é¢', trigger: 'blur' }], |
| | | category: [{ required: true, message: 'è¯·éæ©å¶åº¦åç±»', trigger: 'change' }], |
| | | content: [{ required: true, message: '请è¾å
¥å¶åº¦å
容', trigger: 'blur' }], |
| | | effectiveTime: [{ required: true, message: 'è¯·éæ©çææ¶é´', trigger: 'change' }], |
| | | scope: [{ required: true, message: 'è¯·éæ©éç¨èå´', trigger: 'change' }] |
| | | } |
| | | const regulationRules = { |
| | | title: [{ required: true, message: "请è¾å
¥å¶åº¦æ é¢", trigger: "blur" }], |
| | | category: [{ required: true, message: "è¯·éæ©å¶åº¦åç±»", trigger: "change" }], |
| | | content: [{ required: true, message: "请è¾å
¥å¶åº¦å
容", trigger: "blur" }], |
| | | effectiveTime: [ |
| | | { required: true, message: "è¯·éæ©çææ¶é´", trigger: "change" }, |
| | | ], |
| | | scope: [{ required: true, message: "è¯·éæ©éç¨èå´", trigger: "change" }], |
| | | }; |
| | | |
| | | const regulationSearchForm = reactive({ |
| | | title: '', |
| | | category: '' |
| | | }) |
| | | const regulationSearchForm = reactive({ |
| | | 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 statusMap = { |
| | | pending: 'warning', |
| | | approved: 'success', |
| | | rejected: 'danger' |
| | | } |
| | | return statusMap[status] || 'info' |
| | | } |
| | | // å¶åº¦ç¶æ |
| | | const getStatusText = (status) => { |
| | | const statusMap = { |
| | | pending: 'å¾
审æ¹', |
| | | approved: 'å·²éè¿', |
| | | rejected: 'å·²æç»' |
| | | } |
| | | return statusMap[status] || 'æªç¥' |
| | | } |
| | | // ç¨å°ç±»å |
| | | const getSealTypeText = (sealType) => { |
| | | const sealTypeMap = { |
| | | official: 'å
¬ç« ', |
| | | contract: 'ååä¸ç¨ç« ', |
| | | finance: 'è´¢å¡ä¸ç¨ç« ', |
| | | tegal: 'ææ¯ä¸ç¨ç« ' |
| | | } |
| | | return sealTypeMap[sealType] || 'æªç¥' |
| | | } |
| | | // å¶åº¦åç±» |
| | | const getCategoryText = (category) => { |
| | | const categoryMap = { |
| | | hr: '人äºå¶åº¦', |
| | | finance: 'è´¢å¡å¶åº¦', |
| | | safety: 'å®å
¨å¶åº¦', |
| | | tech: 'ææ¯å¶åº¦' |
| | | } |
| | | return categoryMap[category] || 'æªç¥' |
| | | } |
| | | // æç´¢å°ç« ç³è¯· |
| | | const searchSealApplications = () => { |
| | | page.current=1 |
| | | getSealApplicationList() |
| | | // ç¨å°ç³è¯·ç¶æ |
| | | const getStatusType = status => { |
| | | const statusMap = { |
| | | pending: "warning", |
| | | approved: "success", |
| | | rejected: "danger", |
| | | }; |
| | | return statusMap[status] || "info"; |
| | | }; |
| | | // å¶åº¦ç¶æ |
| | | const getStatusText = status => { |
| | | const statusMap = { |
| | | pending: "å¾
审æ¹", |
| | | approved: "å·²éè¿", |
| | | rejected: "å·²æç»", |
| | | }; |
| | | return statusMap[status] || "æªç¥"; |
| | | }; |
| | | // ç¨å°ç±»å |
| | | const getSealTypeText = sealType => { |
| | | const sealTypeMap = { |
| | | official: "å
¬ç« ", |
| | | contract: "ååä¸ç¨ç« ", |
| | | finance: "è´¢å¡ä¸ç¨ç« ", |
| | | tegal: "ææ¯ä¸ç¨ç« ", |
| | | }; |
| | | return sealTypeMap[sealType] || "æªç¥"; |
| | | }; |
| | | // å¶åº¦åç±» |
| | | const getCategoryText = category => { |
| | | const categoryMap = { |
| | | hr: "人äºå¶åº¦", |
| | | finance: "è´¢å¡å¶åº¦", |
| | | safety: "å®å
¨å¶åº¦", |
| | | tech: "ææ¯å¶åº¦", |
| | | }; |
| | | return categoryMap[category] || "æªç¥"; |
| | | }; |
| | | // æç´¢å°ç« ç³è¯· |
| | | const searchSealApplications = () => { |
| | | page.current = 1; |
| | | getSealApplicationList(); |
| | | |
| | | // ElMessage.success('æç´¢å®æ') |
| | | } |
| | | // éç½®å°ç« ç³è¯·æç´¢ |
| | | const resetSealSearch = () => { |
| | | sealSearchForm.title = '' |
| | | sealSearchForm.status = '' |
| | | searchSealApplications() |
| | | } |
| | | // æç´¢å¶åº¦ |
| | | const searchRegulations = () => { |
| | | page.current=1 |
| | | getRegulationList() |
| | | } |
| | | // éç½®å¶åº¦æç´¢ |
| | | const resetRegulationSearch = () => { |
| | | regulationSearchForm.title = '' |
| | | regulationSearchForm.category = '' |
| | | searchRegulations() |
| | | } |
| | | // æäº¤ç¨å°ç³è¯· |
| | | const submitSealApplication = async () => { |
| | | try { |
| | | await sealFormRef.value.validate() |
| | | addSealApplication(sealForm).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('ç³è¯·æäº¤æå') |
| | | showSealApplyDialog.value = false |
| | | getSealApplicationList() |
| | | Object.assign(sealForm, { |
| | | applicationNum: '', |
| | | title: '', |
| | | sealType: '', |
| | | reason: '', |
| | | urgency: 'normal', |
| | | status: 'pending' |
| | | // ElMessage.success('æç´¢å®æ') |
| | | }; |
| | | // éç½®å°ç« ç³è¯·æç´¢ |
| | | const resetSealSearch = () => { |
| | | sealSearchForm.title = ""; |
| | | sealSearchForm.status = ""; |
| | | searchSealApplications(); |
| | | }; |
| | | // æç´¢å¶åº¦ |
| | | const searchRegulations = () => { |
| | | page.current = 1; |
| | | getRegulationList(); |
| | | }; |
| | | // éç½®å¶åº¦æç´¢ |
| | | const resetRegulationSearch = () => { |
| | | regulationSearchForm.title = ""; |
| | | regulationSearchForm.category = ""; |
| | | searchRegulations(); |
| | | }; |
| | | // æäº¤ç¨å°ç³è¯· |
| | | const submitSealApplication = async () => { |
| | | try { |
| | | await sealFormRef.value.validate(); |
| | | addSealApplication(sealForm) |
| | | .then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("ç³è¯·æäº¤æå"); |
| | | showSealApplyDialog.value = false; |
| | | getSealApplicationList(); |
| | | Object.assign(sealForm, { |
| | | applicationNum: "", |
| | | title: "", |
| | | sealType: "", |
| | | reason: "", |
| | | urgency: "normal", |
| | | status: "pending", |
| | | }); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | ElMessage.error(err.msg); |
| | | }); |
| | | } catch (error) { |
| | | ElMessage.error("请å®åç³è¯·ä¿¡æ¯"); |
| | | } |
| | | }; |
| | | // æ°å¢ |
| | | const handleAdd = () => { |
| | | operationType.value = "add"; |
| | | resetRegulationForm(); |
| | | showRegulationDialog.value = true; |
| | | }; |
| | | |
| | | // ç¼è¾ |
| | | const handleEdit = row => { |
| | | operationType.value = "edit"; |
| | | Object.assign(regulationForm, row); |
| | | showRegulationDialog.value = true; |
| | | }; |
| | | // åºå¼ |
| | | const repealEdit = row => { |
| | | operationType.value = "edit"; |
| | | Object.assign(regulationForm, row); |
| | | regulationForm.status = "repealed"; |
| | | ElMessageBox.confirm("确认åºå¼è¯¥å¶åº¦ï¼", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | updateRuleManagement(regulationForm).then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("å¶åº¦åºå¼æå"); |
| | | // showRegulationDialog.value = false |
| | | getRegulationList(); |
| | | resetRegulationForm(); |
| | | } |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | ElMessage({ |
| | | type: "info", |
| | | message: "已忶åºå¼", |
| | | }); |
| | | }); |
| | | }; |
| | | // åå¸å¶åº¦ |
| | | const submitRegulation = async () => { |
| | | try { |
| | | await regulationFormRef.value.validate(); |
| | | if (operationType.value == "add") { |
| | | addRuleManagement(regulationForm).then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("å¶åº¦å叿å"); |
| | | showRegulationDialog.value = false; |
| | | getRegulationList(); |
| | | resetRegulationForm(); |
| | | } |
| | | }); |
| | | } else { |
| | | updateRuleManagement(regulationForm).then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("å¶åº¦ç¼è¾æå"); |
| | | showRegulationDialog.value = false; |
| | | resetRegulationForm(); |
| | | getRegulationList(); |
| | | } |
| | | }); |
| | | } |
| | | }).catch(err => { |
| | | ElMessage.error(err.msg) |
| | | }) |
| | | |
| | | } catch (error) { |
| | | ElMessage.error('请å®åç³è¯·ä¿¡æ¯') |
| | | } |
| | | } |
| | | // æ°å¢ |
| | | const handleAdd = () => { |
| | | operationType.value = 'add' |
| | | resetRegulationForm() |
| | | showRegulationDialog.value = true |
| | | } |
| | | } catch (err) { |
| | | ElMessage.error(err.msg); |
| | | } |
| | | }; |
| | | //éç½®å¶åº¦è¡¨å |
| | | const resetRegulationForm = () => { |
| | | Object.assign(regulationForm, { |
| | | id: "", |
| | | regulationNum: "", |
| | | title: "", |
| | | category: "", |
| | | content: "", |
| | | version: "", |
| | | status: "active", |
| | | readCount: 0, |
| | | effectiveTime: "", |
| | | scope: [], |
| | | requireConfirm: false, |
| | | }); |
| | | }; |
| | | |
| | | // ç¼è¾ |
| | | const handleEdit = (row) => { |
| | | operationType.value = 'edit' |
| | | Object.assign(regulationForm, row) |
| | | showRegulationDialog.value = true |
| | | } |
| | | // åºå¼ |
| | | const repealEdit = (row) => { |
| | | operationType.value = 'edit' |
| | | Object.assign(regulationForm, row) |
| | | regulationForm.status = 'repealed' |
| | | ElMessageBox.confirm('确认åºå¼è¯¥å¶åº¦ï¼', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | }).then(() => { |
| | | updateRuleManagement(regulationForm).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('å¶åº¦åºå¼æå') |
| | | // showRegulationDialog.value = false |
| | | getRegulationList() |
| | | resetRegulationForm() |
| | | // æ¥çç¨å°ç³è¯·è¯¦æ
|
| | | const viewSealDetail = row => { |
| | | currentSealDetail.value = row; |
| | | showSealDetailDialog.value = true; |
| | | }; |
| | | // 审æ¹ç¨å°ç³è¯· |
| | | const approveSeal = row => { |
| | | console.log(row); |
| | | ElMessageBox.confirm("确认éè¿è¯¥ç¨å°ç³è¯·ï¼", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).then(() => { |
| | | row.status = "approved"; |
| | | updateSealApplication(row).then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("审æ¹éè¿"); |
| | | } |
| | | }); |
| | | }); |
| | | }; |
| | | // æç»ç¨å°ç³è¯· |
| | | const rejectSeal = row => { |
| | | ElMessageBox.prompt("请è¾å
¥æç»åå ", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | inputPattern: /\S+/, |
| | | inputErrorMessage: "æç»åå ä¸è½ä¸ºç©º", |
| | | }).then(({ value }) => { |
| | | row.status = "rejected"; |
| | | updateSealApplication(row).then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("å®¡æ¹æç»"); |
| | | } |
| | | }); |
| | | ElMessage.success("å·²æç»ç³è¯·"); |
| | | }); |
| | | }; |
| | | // è·åå¨èåå·¥å表 |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | //è·åå½åç»å½ç¨æ·ä¿¡æ¯ |
| | | getUserProfile().then(res => { |
| | | if (res.code == 200) { |
| | | console.log(res.data.userName); |
| | | currentUser.value = res.data.userName; |
| | | } |
| | | }) |
| | | }).catch(() => { |
| | | ElMessage({ |
| | | type: 'info', |
| | | message: '已忶åºå¼' |
| | | }) |
| | | }) |
| | | } |
| | | // åå¸å¶åº¦ |
| | | const submitRegulation = async () => { |
| | | try { |
| | | await regulationFormRef.value.validate() |
| | | if(operationType.value == 'add'){ |
| | | addRuleManagement(regulationForm).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('å¶åº¦å叿å') |
| | | showRegulationDialog.value = false |
| | | getRegulationList() |
| | | resetRegulationForm() |
| | | }); |
| | | 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 |
| | | ); |
| | | page.total = res.data.total; |
| | | |
| | | if (tableData.value.length == 0) { |
| | | ElMessage.error("å½åç¨æ·æªå å
¥ä»»ä½é¨é¨"); |
| | | } |
| | | }) |
| | | }else{ |
| | | updateRuleManagement(regulationForm).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('å¶åº¦ç¼è¾æå') |
| | | showRegulationDialog.value = false |
| | | resetRegulationForm() |
| | | getRegulationList() |
| | | }})} |
| | | }catch(err){ |
| | | ElMessage.error(err.msg) |
| | | } |
| | | } |
| | | //éç½®å¶åº¦è¡¨å |
| | | const resetRegulationForm = () => { |
| | | Object.assign(regulationForm, { |
| | | id: '', |
| | | regulationNum: '', |
| | | title: '', |
| | | category: '', |
| | | content: '', |
| | | version: '', |
| | | status: 'active', |
| | | readCount: 0, |
| | | effectiveTime: '', |
| | | scope: [], |
| | | requireConfirm: false |
| | | }) |
| | | } |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | |
| | | // æ¥çç¨å°ç³è¯·è¯¦æ
|
| | | const viewSealDetail = (row) => { |
| | | currentSealDetail.value = row |
| | | showSealDetailDialog.value = true |
| | | } |
| | | // 审æ¹ç¨å°ç³è¯· |
| | | const approveSeal = (row) => { |
| | | console.log(row) |
| | | ElMessageBox.confirm('确认éè¿è¯¥ç¨å°ç³è¯·ï¼', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | }).then(() => { |
| | | row.status = 'approved' |
| | | updateSealApplication(row).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('审æ¹éè¿') |
| | | // æ¥çå¶åº¦çæ¬åå² |
| | | const viewVersionHistory = row => { |
| | | showVersionHistoryDialog.value = true; |
| | | const params = { |
| | | category: row.category, |
| | | }; |
| | | listRuleManagement(page, params).then(res => { |
| | | if (res.code == 200) { |
| | | versionHistory.value = res.data.records; |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | // æç»ç¨å°ç³è¯· |
| | | const rejectSeal = (row) => { |
| | | ElMessageBox.prompt('请è¾å
¥æç»åå ', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | inputPattern: /\S+/, |
| | | inputErrorMessage: 'æç»åå ä¸è½ä¸ºç©º' |
| | | }).then(({ value }) => { |
| | | row.status = 'rejected' |
| | | updateSealApplication(row).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('å®¡æ¹æç»') |
| | | } |
| | | }) |
| | | ElMessage.success('å·²æç»ç³è¯·') |
| | | }) |
| | | } |
| | | // è·åå¨èåå·¥å表 |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | //è·åå½åç»å½ç¨æ·ä¿¡æ¯ |
| | | getUserProfile().then(res => { |
| | | if(res.code == 200){ |
| | | console.log(res.data.userName) |
| | | currentUser.value = res.data.userName |
| | | } |
| | | }) |
| | | 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) |
| | | page.total = res.data.total; |
| | | |
| | | if(tableData.value.length == 0){ |
| | | ElMessage.error('å½åç¨æ·æªå å
¥ä»»ä½é¨é¨') |
| | | } |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | | }) |
| | | |
| | | |
| | | }; |
| | | |
| | | // æ¥çå¶åº¦çæ¬åå² |
| | | const viewVersionHistory = (row) => { |
| | | showVersionHistoryDialog.value = true |
| | | const params = { |
| | | |
| | | category: row.category |
| | | } |
| | | listRuleManagement(page,params).then(res => { |
| | | if(res.code == 200){ |
| | | versionHistory.value = res.data.records |
| | | } |
| | | }) |
| | | } |
| | | // æ¥çå¶åº¦è¯¦æ
|
| | | const viewRegulation = (row) => { |
| | | getList() |
| | | currentRegulationDetail.value = row |
| | | showRegulationDetailDialog.value = true |
| | | getReadingStatusByRuleId(row.id).then(res => { |
| | | if(res.code == 200){ |
| | | readStatusList.value = res.data |
| | | if(readStatusList.value.length==0 && tableData.value.length>0){ |
| | | }); |
| | | }; |
| | | // æ¥çå¶åº¦è¯¦æ
|
| | | const viewRegulation = row => { |
| | | getList(); |
| | | currentRegulationDetail.value = row; |
| | | showRegulationDetailDialog.value = true; |
| | | getReadingStatusByRuleId(row.id).then(res => { |
| | | if (res.code == 200) { |
| | | readStatusList.value = res.data; |
| | | if (readStatusList.value.length == 0 && tableData.value.length > 0) { |
| | | const params = { |
| | | ruleId: row.id, |
| | | employee: tableData.value[0].staffName, |
| | | department: tableData.value[0].postJob, |
| | | status: 'unconfirmed' |
| | | ruleId: row.id, |
| | | employee: tableData.value[0].staffName, |
| | | department: tableData.value[0].postJob, |
| | | status: "unconfirmed", |
| | | }; |
| | | addReadingStatus(params).then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("å¶åº¦é
读æå"); |
| | | } |
| | | }); |
| | | } |
| | | addReadingStatus(params).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('å¶åº¦é
读æå') |
| | | } |
| | | }) |
| | | } |
| | | } |
| | | }) |
| | | |
| | | } |
| | | // æ¥çå¶åº¦é
è¯»ç¶æ |
| | | const viewReadStatus = (row) => { |
| | | showReadStatusDialog.value = true |
| | | //æ¥çé
è¯»ç¶æå表 |
| | | getReadingStatusByRuleId(row.id).then(res => { |
| | | if(res.code == 200){ |
| | | readStatusList.value = res.data |
| | | } |
| | | }) |
| | | } |
| | | |
| | | //确认æ¥ç |
| | | const resetForm = (row) => { |
| | | console.log("row",row) |
| | | row.readCount = row.readCount + 1 |
| | | |
| | | updateRuleManagement(row).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('æ¥çæ°éä¿®æ¹æå') |
| | | //ä¿®æ¹é
è¯»ç¶æ |
| | | //æ ¹æ®å¶åº¦idåå½åç»å½çåå·¥å¾å°é
è¯»ç¶æ |
| | | // let item = readStatusList.value.filter(item => item.employee == tableData.value[0].staffName ) |
| | | // if(item.length>0){ |
| | | // item[0].status = 'confirmed', |
| | | // item[0].confirmTime = new Date().toISOString().replace('T', ' ').split('.')[0]; |
| | | // } |
| | | // çéå½åå工对åºè¯¥å¶åº¦çé
è¯»ç¶æè®°å½ |
| | | let statusItem = readStatusList.value.find(item => item.employee === tableData.value[0].staffName && item.ruleId === row.id); |
| | | |
| | | if (statusItem) { |
| | | // 妿æ¾å°è®°å½ï¼æ´æ°ç¶æå确认æ¶é´ |
| | | statusItem.status = 'confirmed'; |
| | | // æ ¼å¼åæ¶é´ä¸º"YYYY-MM-DD HH:mm:ss"æ ¼å¼ |
| | | const now = new Date(); |
| | | statusItem.confirmTime = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}:${String(now.getSeconds()).padStart(2, '0')}`; |
| | | // statusItem.confirmTime = new Date().toISOString().replace('T', ' ').split('.')[0]; |
| | | |
| | | updateReadingStatus(statusItem).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('å¶åº¦é
è¯»ç¶æä¿®æ¹æå') |
| | | } |
| | | }) |
| | | }); |
| | | }; |
| | | // æ¥çå¶åº¦é
è¯»ç¶æ |
| | | const viewReadStatus = row => { |
| | | showReadStatusDialog.value = true; |
| | | //æ¥çé
è¯»ç¶æå表 |
| | | getReadingStatusByRuleId(row.id).then(res => { |
| | | if (res.code == 200) { |
| | | readStatusList.value = res.data; |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | } |
| | | }) |
| | | } |
| | | //确认æ¥ç |
| | | const resetForm = row => { |
| | | console.log("row", row); |
| | | row.readCount = row.readCount + 1; |
| | | |
| | | // 导åºç¨å°ç³è¯· |
| | | const { proxy } = getCurrentInstance() |
| | | const handleExport = () => { |
| | | proxy.download('/sealApplicationManagement/export', { ...sealSearchForm }, 'ç¨å°ç³è¯·.xlsx') |
| | | } |
| | | updateRuleManagement(row).then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("æ¥çæ°éä¿®æ¹æå"); |
| | | //ä¿®æ¹é
è¯»ç¶æ |
| | | //æ ¹æ®å¶åº¦idåå½åç»å½çåå·¥å¾å°é
è¯»ç¶æ |
| | | // let item = readStatusList.value.filter(item => item.employee == tableData.value[0].staffName ) |
| | | // if(item.length>0){ |
| | | // item[0].status = 'confirmed', |
| | | // item[0].confirmTime = new Date().toISOString().replace('T', ' ').split('.')[0]; |
| | | // } |
| | | // çéå½åå工对åºè¯¥å¶åº¦çé
è¯»ç¶æè®°å½ |
| | | let statusItem = readStatusList.value.find( |
| | | item => |
| | | item.employee === tableData.value[0].staffName && |
| | | item.ruleId === row.id |
| | | ); |
| | | |
| | | // è·åå°ç« ç³è¯·åè¡¨æ°æ® |
| | | const getSealApplicationList = async () => { |
| | | tableLoading.value = true |
| | | listSealApplication(page,sealSearchForm) |
| | | .then(res => { |
| | | //è·åå½åç»å½çé¨é¨ä¿¡æ¯ |
| | | // è·åå½åç»å½çé¨é¨ä¿¡æ¯å¹¶è¿æ»¤æ°æ® |
| | | const currentFactoryName = userStore.currentFactoryName |
| | | if (currentFactoryName) { |
| | | // æ ¹æ®currentFactoryNameè¿æ»¤åºdepartmentç¸åçæ°æ® |
| | | sealApplications.value = res.data.records.filter(item => item.department === currentFactoryName) |
| | | // æ´æ°è¿æ»¤åçæ»æ° |
| | | page.total = sealApplications.value.length |
| | | } else { |
| | | // å¦ææ²¡æcurrentFactoryNameï¼åæ¾ç¤ºæææ°æ® |
| | | sealApplications.value = res.data.records |
| | | page.total = res.data.total |
| | | } |
| | | // sealApplications.value = res.data.records |
| | | // page.value.total = res.data.total; |
| | | tableLoading.value = false; |
| | | if (statusItem) { |
| | | // 妿æ¾å°è®°å½ï¼æ´æ°ç¶æå确认æ¶é´ |
| | | statusItem.status = "confirmed"; |
| | | // æ ¼å¼åæ¶é´ä¸º"YYYY-MM-DD HH:mm:ss"æ ¼å¼ |
| | | const now = new Date(); |
| | | statusItem.confirmTime = `${now.getFullYear()}-${String( |
| | | now.getMonth() + 1 |
| | | ).padStart(2, "0")}-${String(now.getDate()).padStart(2, "0")} ${String( |
| | | now.getHours() |
| | | ).padStart(2, "0")}:${String(now.getMinutes()).padStart( |
| | | 2, |
| | | "0" |
| | | )}:${String(now.getSeconds()).padStart(2, "0")}`; |
| | | // statusItem.confirmTime = new Date().toISOString().replace('T', ' ').split('.')[0]; |
| | | |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | | }) |
| | | } |
| | | // è·åè§ç« å¶åº¦åè¡¨æ°æ® |
| | | const getRegulationList = async () => { |
| | | tableLoading.value = true |
| | | listRuleManagement(page,regulationSearchForm) |
| | | .then(res => { |
| | | updateReadingStatus(statusItem).then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("å¶åº¦é
è¯»ç¶æä¿®æ¹æå"); |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | regulations.value = res.data.records |
| | | // è¿æ»¤æå·²åºå¼çå¶åº¦ |
| | | // regulations.value = res.data.records.filter(item => item.status !== 'repealed') |
| | | page.total = res.data.total; |
| | | tableLoading.value = false; |
| | | // 导åºç¨å°ç³è¯· |
| | | const { proxy } = getCurrentInstance(); |
| | | const handleExport = () => { |
| | | proxy.download( |
| | | "/sealApplicationManagement/export", |
| | | { ...sealSearchForm }, |
| | | "ç¨å°ç³è¯·.xlsx" |
| | | ); |
| | | }; |
| | | |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | | }) |
| | | } |
| | | // è·åå°ç« ç³è¯·åè¡¨æ°æ® |
| | | const getSealApplicationList = async () => { |
| | | tableLoading.value = true; |
| | | listSealApplication(page, sealSearchForm) |
| | | .then(res => { |
| | | //è·åå½åç»å½çé¨é¨ä¿¡æ¯ |
| | | // è·åå½åç»å½çé¨é¨ä¿¡æ¯å¹¶è¿æ»¤æ°æ® |
| | | const currentFactoryName = userStore.currentFactoryName; |
| | | if (currentFactoryName) { |
| | | // æ ¹æ®currentFactoryNameè¿æ»¤åºdepartmentç¸åçæ°æ® |
| | | sealApplications.value = res.data.records.filter( |
| | | item => item.department === currentFactoryName |
| | | ); |
| | | // æ´æ°è¿æ»¤åçæ»æ° |
| | | page.total = sealApplications.value.length; |
| | | } else { |
| | | // å¦ææ²¡æcurrentFactoryNameï¼åæ¾ç¤ºæææ°æ® |
| | | sealApplications.value = res.data.records; |
| | | page.total = res.data.total; |
| | | } |
| | | // sealApplications.value = res.data.records |
| | | // page.value.total = res.data.total; |
| | | tableLoading.value = false; |
| | | }) |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | // è·åè§ç« å¶åº¦åè¡¨æ°æ® |
| | | const getRegulationList = async () => { |
| | | tableLoading.value = true; |
| | | listRuleManagement(page, regulationSearchForm) |
| | | .then(res => { |
| | | regulations.value = res.data.records; |
| | | // è¿æ»¤æå·²åºå¼çå¶åº¦ |
| | | // regulations.value = res.data.records.filter(item => item.status !== 'repealed') |
| | | page.total = res.data.total; |
| | | tableLoading.value = false; |
| | | }) |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | // åå§å |
| | | getSealApplicationList() |
| | | getRegulationList() |
| | | }) |
| | | onMounted(() => { |
| | | // åå§å |
| | | getSealApplicationList(); |
| | | getRegulationList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .app-container { |
| | | padding: 20px; |
| | | } |
| | | .app-container { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .card-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | .card-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | |
| | | .tab-content { |
| | | padding: 20px 0; |
| | | } |
| | | .tab-content { |
| | | padding: 20px 0; |
| | | } |
| | | |
| | | .mb-20 { |
| | | margin-bottom: 20px; |
| | | } |
| | | .mb-20 { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .mt-20 { |
| | | margin-top: 20px; |
| | | } |
| | | .mt-20 { |
| | | margin-top: 20px; |
| | | } |
| | | |
| | | .ml-10 { |
| | | margin-left: 10px; |
| | | } |
| | | .ml-10 { |
| | | margin-left: 10px; |
| | | } |
| | | |
| | | .regulation-content { |
| | | background-color: #f5f5f5; |
| | | padding: 15px; |
| | | border-radius: 4px; |
| | | line-height: 1.6; |
| | | white-space: pre-wrap; |
| | | height: 200px; |
| | | } |
| | | .regulation-content { |
| | | background-color: #f5f5f5; |
| | | padding: 15px; |
| | | border-radius: 4px; |
| | | line-height: 1.6; |
| | | white-space: pre-wrap; |
| | | height: 200px; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | gap: 10px; |
| | | } |
| | | .dialog-footer { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | gap: 10px; |
| | | } |
| | | </style> |
| | |
| | | <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 === 'ä¸è¬ç¼ºé·'" |
| | | type="text" |
| | | @click="eliminateDefect(row)" |
| | | > |
| | | <el-button v-if="row.status === '严é缺é·' || row.status === 'ä¸è¬ç¼ºé·'" |
| | | type="text" |
| | | @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" |
| | | :key="index" |
| | | :label="item.deviceName" |
| | | :value="item.id" |
| | | ></el-option> |
| | | <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> |
| | | </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 { getDeviceLedger } from "@/api/equipmentManagement/ledger"; |
| | | // åè®¾ä»¥ä¸æ¯å端æ¥å£ |
| | | import { |
| | | registerDefect, |
| | | getDefectList, |
| | | eliminateDefect as apiEliminateDefect, |
| | | getDefectLedger, |
| | | deleteDefect |
| | | } from '@/api/equipmentManagement/defectManagement'; |
| | | import { ref, reactive } from "vue"; |
| | | import { ElMessage } from "element-plus"; |
| | | import { getDeviceLedger } from "@/api/equipmentManagement/ledger"; |
| | | // åè®¾ä»¥ä¸æ¯å端æ¥å£ |
| | | import { |
| | | registerDefect, |
| | | getDefectList, |
| | | eliminateDefect as apiEliminateDefect, |
| | | getDefectLedger, |
| | | deleteDefect, |
| | | } from "@/api/equipmentManagement/defectManagement"; |
| | | |
| | | // 缺é·å表 |
| | | const defectList = ref([]); |
| | | // ç»è®°å¯¹è¯æ¡æ¾ç¤ºç¶æ |
| | | const showRegisterDialog = ref(false); |
| | | // å°è´¦å¯¹è¯æ¡æ¾ç¤ºç¶æ |
| | | const showLedgerDialog = ref(false); |
| | | // 缺é·è¡¨å |
| | | const defectForm = reactive({ |
| | | deviceLedgerId: '', |
| | | defectDescription: '', |
| | | status: '', |
| | | }); |
| | | const deviceOptions = ref([]); |
| | | // 表åéªè¯è§å |
| | | const defectRules = reactive({ |
| | | deviceLedgerId: [{ required: true, message: '请è¾å
¥è®¾å¤åç§°', trigger: 'blur' }], |
| | | defectDescription: [{ required: true, message: '请è¾å
¥ç¼ºé·æè¿°', trigger: 'blur' }] |
| | | }); |
| | | // 表åå¼ç¨ |
| | | const defectFormRef = ref(null); |
| | | // å°è´¦å表 |
| | | const ledgerList = ref([]); |
| | | // 缺é·å表 |
| | | const defectList = ref([]); |
| | | // ç»è®°å¯¹è¯æ¡æ¾ç¤ºç¶æ |
| | | const showRegisterDialog = ref(false); |
| | | // å°è´¦å¯¹è¯æ¡æ¾ç¤ºç¶æ |
| | | const showLedgerDialog = ref(false); |
| | | // 缺é·è¡¨å |
| | | const defectForm = reactive({ |
| | | deviceLedgerId: "", |
| | | defectDescription: "", |
| | | status: "", |
| | | }); |
| | | const deviceOptions = ref([]); |
| | | // 表åéªè¯è§å |
| | | const defectRules = reactive({ |
| | | deviceLedgerId: [ |
| | | { required: true, message: "请è¾å
¥è®¾å¤åç§°", trigger: "blur" }, |
| | | ], |
| | | defectDescription: [ |
| | | { required: true, message: "请è¾å
¥ç¼ºé·æè¿°", trigger: "blur" }, |
| | | ], |
| | | }); |
| | | // 表åå¼ç¨ |
| | | const defectFormRef = ref(null); |
| | | // å°è´¦å表 |
| | | const ledgerList = ref([]); |
| | | |
| | | const loadDeviceName = async () => { |
| | | const { data } = await getDeviceLedger(); |
| | | // console.log(data); |
| | | deviceOptions.value = data; |
| | | }; |
| | | const loadDeviceName = async () => { |
| | | const { data } = await getDeviceLedger(); |
| | | // console.log(data); |
| | | deviceOptions.value = data; |
| | | }; |
| | | |
| | | // è·å缺é·å表 |
| | | const fetchDefectList = async () => { |
| | | try { |
| | | const res = await getDefectList(); |
| | | if (res.code === 200) { |
| | | defectList.value = res.data.records; |
| | | } else { |
| | | ElMessage.error(res.message || 'è·å缺é·å表失败'); |
| | | // è·å缺é·å表 |
| | | const fetchDefectList = async () => { |
| | | try { |
| | | const res = await getDefectList(); |
| | | if (res.code === 200) { |
| | | defectList.value = res.data.records; |
| | | } else { |
| | | ElMessage.error(res.message || "è·å缺é·å表失败"); |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error("è·å缺é·å表失败"); |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error('è·å缺é·å表失败'); |
| | | } |
| | | }; |
| | | }; |
| | | |
| | | // æäº¤ç¼ºé·ç»è®°è¡¨å |
| | | const submitDefectForm = async () => { |
| | | if (!defectFormRef.value) return; |
| | | try { |
| | | await defectFormRef.value.validate(); |
| | | const res = await registerDefect(defectForm); |
| | | if (res.code === 200) { |
| | | ElMessage.success('缺é·ç»è®°æå'); |
| | | showRegisterDialog.value = false; |
| | | fetchDefectList(); |
| | | } else { |
| | | ElMessage.error(res.message || '缺é·ç»è®°å¤±è´¥'); |
| | | // æäº¤ç¼ºé·ç»è®°è¡¨å |
| | | const submitDefectForm = async () => { |
| | | if (!defectFormRef.value) return; |
| | | try { |
| | | await defectFormRef.value.validate(); |
| | | const res = await registerDefect(defectForm); |
| | | if (res.code === 200) { |
| | | ElMessage.success("缺é·ç»è®°æå"); |
| | | showRegisterDialog.value = false; |
| | | fetchDefectList(); |
| | | } else { |
| | | ElMessage.error(res.message || "缺é·ç»è®°å¤±è´¥"); |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error("请填å宿´è¡¨åä¿¡æ¯"); |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error('请填å宿´è¡¨åä¿¡æ¯'); |
| | | } |
| | | }; |
| | | }; |
| | | |
| | | // æ¶é¤ç¼ºé· |
| | | const eliminateDefect = async (row) => { |
| | | |
| | | try { |
| | | const res = await apiEliminateDefect(row); |
| | | if (res.code === 200) { |
| | | ElMessage.success('ç¼ºé·æ¶é¤æå'); |
| | | fetchDefectList(); |
| | | } else { |
| | | ElMessage.error(res.message || 'ç¼ºé·æ¶é¤å¤±è´¥'); |
| | | // æ¶é¤ç¼ºé· |
| | | const eliminateDefect = async row => { |
| | | try { |
| | | const res = await apiEliminateDefect(row); |
| | | if (res.code === 200) { |
| | | ElMessage.success("ç¼ºé·æ¶é¤æå"); |
| | | fetchDefectList(); |
| | | } else { |
| | | ElMessage.error(res.message || "ç¼ºé·æ¶é¤å¤±è´¥"); |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error("ç¼ºé·æ¶é¤å¤±è´¥"); |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error('ç¼ºé·æ¶é¤å¤±è´¥'); |
| | | } |
| | | }; |
| | | }; |
| | | |
| | | // // 转维修工å |
| | | // const transferToRepairOrder = async (id) => { |
| | | // try { |
| | | // const res = await transferToRepair(id); |
| | | // if (res.code === 200) { |
| | | // ElMessage.success('转维修工åæå'); |
| | | // } else { |
| | | // ElMessage.error(res.message || '转维修工å失败'); |
| | | // } |
| | | // } catch (error) { |
| | | // ElMessage.error('转维修工å失败'); |
| | | // } |
| | | // }; |
| | | // // 转维修工å |
| | | // const transferToRepairOrder = async (id) => { |
| | | // try { |
| | | // const res = await transferToRepair(id); |
| | | // if (res.code === 200) { |
| | | // ElMessage.success('转维修工åæå'); |
| | | // } else { |
| | | // ElMessage.error(res.message || '转维修工å失败'); |
| | | // } |
| | | // } catch (error) { |
| | | // ElMessage.error('转维修工å失败'); |
| | | // } |
| | | // }; |
| | | |
| | | // è·å缺é·è®¾å¤å°è´¦ |
| | | 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 || 'è·å缺é·è®¾å¤å°è´¦å¤±è´¥'); |
| | | // è·å缺é·è®¾å¤å°è´¦ |
| | | 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 || "è·å缺é·è®¾å¤å°è´¦å¤±è´¥"); |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error("è·å缺é·è®¾å¤å°è´¦å¤±è´¥"); |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error('è·å缺é·è®¾å¤å°è´¦å¤±è´¥'); |
| | | } |
| | | }; |
| | | }; |
| | | |
| | | // ç»ä»¶æè½½æ¶è·å缺é·å表 |
| | | const onMounted = () => { |
| | | fetchDefectList(); |
| | | loadDeviceName(); |
| | | }; |
| | | onMounted(); |
| | | // ç»ä»¶æè½½æ¶è·å缺é·å表 |
| | | const onMounted = () => { |
| | | fetchDefectList(); |
| | | loadDeviceName(); |
| | | }; |
| | | onMounted(); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .defect-management { |
| | | padding: 20px; |
| | | } |
| | | .defect-management { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .actions { |
| | | margin-bottom: 10px; |
| | | } |
| | | .actions { |
| | | margin-bottom: 10px; |
| | | } |
| | | </style> |
| | |
| | | <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"> |
| | | <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" |
| | | :key="index" |
| | | :label="item.deviceName" |
| | | :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 |
| | | 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"/> |
| | | </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> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <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%" |
| | | /> |
| | | </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-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" |
| | | 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-select> |
| | | <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" |
| | | type="datetime" |
| | | clearable |
| | | placeholder="éæ©å¼å§æ¥æ" |
| | | 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" |
| | | type="datetime" |
| | | clearable |
| | | placeholder="éæ©å¼å§æ¥æ" |
| | | 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 @click="cancel">åæ¶</el-button> |
| | | <el-button type="primary" @click="submitForm">ä¿å</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | <div> |
| | | <el-dialog :title="operationType === 'add' ? 'æ°å¢å·¡æ£ä»»å¡' : 'ç¼è¾å·¡æ£ä»»å¡'" |
| | | 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" |
| | | :key="index" |
| | | :label="item.deviceName" |
| | | :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 |
| | | 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" /> |
| | | </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> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <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%" /> |
| | | </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-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" |
| | | 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-select> |
| | | <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" |
| | | type="datetime" |
| | | clearable |
| | | placeholder="éæ©å¼å§æ¥æ" |
| | | 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" |
| | | type="datetime" |
| | | clearable |
| | | placeholder="éæ©å¼å§æ¥æ" |
| | | 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> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {reactive, ref} from "vue"; |
| | | 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"; |
| | | import { reactive, ref } from "vue"; |
| | | 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 dialogVisitable = ref(false); |
| | | const operationType = ref('add'); |
| | | const deviceOptions = ref([]); |
| | | const data = reactive({ |
| | | form: { |
| | | taskId: undefined, |
| | | taskName: undefined, |
| | | 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([]) |
| | | const { proxy } = getCurrentInstance(); |
| | | const emit = defineEmits(); |
| | | const userStore = useUserStore(); |
| | | const dialogVisitable = ref(false); |
| | | const operationType = ref("add"); |
| | | const deviceOptions = ref([]); |
| | | const data = reactive({ |
| | | form: { |
| | | taskId: undefined, |
| | | taskName: undefined, |
| | | 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([]); |
| | | |
| | | const loadDeviceName = async () => { |
| | | const { data } = await getDeviceLedger(); |
| | | deviceOptions.value = data; |
| | | }; |
| | | const loadDeviceName = async () => { |
| | | const { data } = await getDeviceLedger(); |
| | | deviceOptions.value = data; |
| | | }; |
| | | |
| | | const setDeviceModel = (id) => { |
| | | const option = deviceOptions.value.find((item) => item.id === id); |
| | | if (option) { |
| | | form.value.taskName = option.deviceName; |
| | | } |
| | | } |
| | | 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 |
| | | |
| | | // é置表å |
| | | resetForm(); |
| | | |
| | | // å è½½ç¨æ·å表 |
| | | 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) |
| | | |
| | | // 妿æè®¾å¤IDï¼èªå¨è®¾ç½®è®¾å¤ä¿¡æ¯ |
| | | if (form.value.taskId) { |
| | | setDeviceModel(form.value.taskId); |
| | | } |
| | | } |
| | | } |
| | | // æå¼å¼¹æ¡ |
| | | const openDialog = async (type, row) => { |
| | | dialogVisitable.value = true; |
| | | operationType.value = type; |
| | | |
| | | // å
³éå¯¹è¯æ¡ |
| | | const cancel = () => { |
| | | resetForm() |
| | | dialogVisitable.value = false |
| | | emit('closeDia') |
| | | } |
| | | // é置表å |
| | | resetForm(); |
| | | |
| | | // é置表å彿° |
| | | const resetForm = () => { |
| | | if (proxy.$refs.formRef) { |
| | | proxy.$refs.formRef.resetFields() |
| | | } |
| | | // éç½®è¡¨åæ°æ®ç¡®ä¿è®¾å¤ä¿¡æ¯æ£ç¡®éç½® |
| | | form.value = { |
| | | taskId: undefined, |
| | | taskName: undefined, |
| | | inspector: '', |
| | | inspectorIds: '', |
| | | remarks: '', |
| | | frequencyType: '', |
| | | frequencyDetail: '', |
| | | week: '', |
| | | time: '' |
| | | } |
| | | } |
| | | // å è½½ç¨æ·å表 |
| | | userListNoPageByTenantId().then(res => { |
| | | userList.value = res.data; |
| | | }); |
| | | |
| | | // æäº¤è¡¨å |
| | | const submitForm = () => { |
| | | proxy.$refs["formRef"].validate(async valid => { |
| | | if (valid) { |
| | | try { |
| | | 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 |
| | | } |
| | | |
| | | let res = await userStore.getInfo() |
| | | form.value.registrantId = res.user.userId |
| | | |
| | | await addOrEditTimingTask(form.value) |
| | | cancel() |
| | | proxy.$modal.msgSuccess('æäº¤æå') |
| | | } catch (error) { |
| | | proxy.$modal.msgError('æäº¤å¤±è´¥ï¼è¯·éè¯') |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | defineExpose({ openDialog }) |
| | | // å 载设å¤å表 |
| | | await loadDeviceName(); |
| | | |
| | | 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"); |
| | | }; |
| | | |
| | | // é置表å彿° |
| | | const resetForm = () => { |
| | | if (proxy.$refs.formRef) { |
| | | proxy.$refs.formRef.resetFields(); |
| | | } |
| | | // éç½®è¡¨åæ°æ®ç¡®ä¿è®¾å¤ä¿¡æ¯æ£ç¡®éç½® |
| | | form.value = { |
| | | taskId: undefined, |
| | | taskName: undefined, |
| | | 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; |
| | | |
| | | 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; |
| | | |
| | | await addOrEditTimingTask(form.value); |
| | | cancel(); |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | } catch (error) { |
| | | proxy.$modal.msgError("æäº¤å¤±è´¥ï¼è¯·éè¯"); |
| | | } |
| | | } |
| | | }); |
| | | }; |
| | | 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" |
| | | :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"> |
| | | <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"> |
| | | <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" |
| | | size="small" |
| | | @click="() => editCategory(row)" |
| | | :disabled="loading" |
| | | > |
| | | <el-button type="text" |
| | | size="small" |
| | | @click="() => editCategory(row)" |
| | | :disabled="loading"> |
| | | ç¼è¾ |
| | | </el-button> |
| | | <el-button |
| | | link |
| | | @click="() => deleteCategory(row.id)" |
| | | style="color: #f56c6c;" |
| | | :disabled="loading" |
| | | > |
| | | <el-button type="text" |
| | | size="small" |
| | | @click="() => deleteCategory(row.id)" |
| | | style="color: #f56c6c;" |
| | | :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 formLoading = ref(false); |
| | | // å¯¹è¯æ¡æ¾ç¤ºç¶æ |
| | | const dialogVisible = ref(false); |
| | | // ç¼è¾ ID |
| | | const editId = ref(null); |
| | | // è¡¨æ ¼æ°æ® |
| | | const categories = ref([]); |
| | | // 渲æç¨çè¡¨æ ¼æ°æ® |
| | | // const renderTableData = computed(() => buildTree(categories.value)); |
| | | const renderTableData = ref([]); |
| | | const operationType = ref('add') |
| | | // 表åå¼ç¨ |
| | | const formRef = ref(null); |
| | | // è¡¨åæ°æ® |
| | | const form = reactive({ |
| | | id:'', |
| | | name: '', |
| | | sparePartsNo: '', |
| | | status: '', |
| | | description: '', |
| | | parentId: null |
| | | }); |
| | | |
| | | // 表åéªè¯è§å |
| | | const rules = reactive({ |
| | | name: [ |
| | | { required: true, message: '请è¾å
¥åç±»åç§°', trigger: 'blur' } |
| | | ], |
| | | sparePartsNo: [ |
| | | { required: true, message: '请è¾å
¥åç±»ç¼å·', trigger: 'blur' } |
| | | ], |
| | | status: [ |
| | | { required: true, message: 'è¯·éæ©ç¶æ', trigger: 'change' } |
| | | ] |
| | | }); |
| | | // è·å缩è¿é |
| | | const getIndentation = (row) => { |
| | | // è¿éç®åè¿å 20ï¼å¯æ ¹æ®å®é
éæ±å®ç°å±çº§ç¼©è¿é»è¾ |
| | | return 20; |
| | | }; |
| | | // å®ä¹ buildTree 彿° |
| | | const buildTree = (flatData) => { |
| | | const map = {}; |
| | | const result = []; |
| | | if(flatData){ |
| | | return result; |
| | | } |
| | | flatData.forEach(item => { |
| | | map[item.id] = { ...item, children: [] }; |
| | | // å è½½ç¶æ |
| | | const loading = ref(false); |
| | | const formLoading = ref(false); |
| | | // å¯¹è¯æ¡æ¾ç¤ºç¶æ |
| | | const dialogVisible = ref(false); |
| | | // ç¼è¾ ID |
| | | const editId = ref(null); |
| | | // è¡¨æ ¼æ°æ® |
| | | const categories = ref([]); |
| | | // 渲æç¨çè¡¨æ ¼æ°æ® |
| | | // const renderTableData = computed(() => buildTree(categories.value)); |
| | | const renderTableData = ref([]); |
| | | const operationType = ref("add"); |
| | | // 表åå¼ç¨ |
| | | const formRef = ref(null); |
| | | // è¡¨åæ°æ® |
| | | const form = reactive({ |
| | | id: "", |
| | | name: "", |
| | | sparePartsNo: "", |
| | | status: "", |
| | | description: "", |
| | | parentId: null, |
| | | }); |
| | | flatData.forEach(item => { |
| | | if (item.parentId === null || !map[item.parentId]) { |
| | | result.push(map[item.id]); |
| | | } else { |
| | | map[item.parentId].children.push(map[item.id]); |
| | | } |
| | | |
| | | // 表åéªè¯è§å |
| | | const rules = reactive({ |
| | | name: [{ required: true, message: "请è¾å
¥åç±»åç§°", trigger: "blur" }], |
| | | sparePartsNo: [ |
| | | { required: true, message: "请è¾å
¥åç±»ç¼å·", trigger: "blur" }, |
| | | ], |
| | | status: [{ required: true, message: "è¯·éæ©ç¶æ", trigger: "change" }], |
| | | }); |
| | | return result; |
| | | }; |
| | | //è·åæ å½¢ç»æ |
| | | const fetchTreeData = async () => { |
| | | fetchCategories(); |
| | | try { |
| | | const res = await getSparePartsTree(); |
| | | if (res.code === 200) { |
| | | renderTableData.value = res.data; |
| | | } else { |
| | | ElMessage.error(res.message || 'è·ååç±»å表失败'); |
| | | // è·å缩è¿é |
| | | const getIndentation = row => { |
| | | // è¿éç®åè¿å 20ï¼å¯æ ¹æ®å®é
éæ±å®ç°å±çº§ç¼©è¿é»è¾ |
| | | return 20; |
| | | }; |
| | | // å®ä¹ buildTree 彿° |
| | | const buildTree = flatData => { |
| | | const map = {}; |
| | | const result = []; |
| | | if (flatData) { |
| | | return result; |
| | | } |
| | | }catch (error) { |
| | | ElMessage.error('è·ååç±»å表失败'); |
| | | } |
| | | } |
| | | |
| | | // è·ååç±»å表 |
| | | const fetchCategories = async () => { |
| | | loading.value = true; |
| | | try { |
| | | const res = await getSparePartsList(); |
| | | if (res.code === 200) { |
| | | categories.value = res.data.records; |
| | | } else { |
| | | ElMessage.error(res.message || 'è·ååç±»å表失败'); |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error('è·ååç±»å表失败'); |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | | }; |
| | | |
| | | // æ°å¢åç±» |
| | | const addCategory = () => { |
| | | form.id = ''; |
| | | form.name = ''; |
| | | form.sparePartsNo = ''; |
| | | form.status = ''; |
| | | form.description = ''; |
| | | form.parentId = null; |
| | | operationType.value = 'add' |
| | | dialogVisible.value = true; |
| | | console.log('dialogVisible æ´æ°ä¸º', dialogVisible.value); |
| | | }; |
| | | |
| | | // ç¼è¾åç±» |
| | | const editCategory = (row) => { |
| | | Object.assign(form, row); |
| | | operationType.value = 'edit' |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | // å é¤åç±» |
| | | const deleteCategory = async (id) => { |
| | | try { |
| | | await ElMessageBox.confirm('æ¤æä½å°æ°¸ä¹
å é¤è¯¥åç±»ï¼æ¯å¦ç»§ç»?', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | flatData.forEach(item => { |
| | | map[item.id] = { ...item, children: [] }; |
| | | }); |
| | | loading.value = true; |
| | | const res = await delSparePart(id); |
| | | if (res.code === 200) { |
| | | ElMessage.success('å 餿å'); |
| | | fetchTreeData(); |
| | | } else { |
| | | ElMessage.error(res.message || 'å é¤å¤±è´¥'); |
| | | } |
| | | } catch (error) { |
| | | if (error !== 'cancel') { |
| | | ElMessage.error('å é¤å¤±è´¥'); |
| | | } |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | | }; |
| | | |
| | | // æäº¤è¡¨å |
| | | const submitForm = async () => { |
| | | if (!formRef.value) return; |
| | | try { |
| | | await formRef.value.validate(); |
| | | formLoading.value = true; |
| | | if (operationType.value === 'edit') { |
| | | let res = await editSparePart(form); |
| | | if (res.code === 200) { |
| | | ElMessage.success('ç¼è¾æå'); |
| | | dialogVisible.value = false; |
| | | fetchTreeData(); |
| | | } |
| | | } else { |
| | | let res = await addSparePart(form); |
| | | if (res.code === 200) { |
| | | ElMessage.success('ç¼è¾æå'); |
| | | dialogVisible.value = false; |
| | | fetchTreeData(); |
| | | flatData.forEach(item => { |
| | | if (item.parentId === null || !map[item.parentId]) { |
| | | result.push(map[item.id]); |
| | | } else { |
| | | map[item.parentId].children.push(map[item.id]); |
| | | } |
| | | }); |
| | | return result; |
| | | }; |
| | | //è·åæ å½¢ç»æ |
| | | const fetchTreeData = async () => { |
| | | fetchCategories(); |
| | | try { |
| | | const res = await getSparePartsTree(); |
| | | if (res.code === 200) { |
| | | renderTableData.value = res.data; |
| | | } else { |
| | | ElMessage.error(res.message || "è·ååç±»å表失败"); |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error("è·ååç±»å表失败"); |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error('请填å宿´è¡¨åä¿¡æ¯'); |
| | | } finally { |
| | | formLoading.value = false; |
| | | } |
| | | }; |
| | | }; |
| | | |
| | | // ç»ä»¶æè½½æ¶è·ååç±»å表 |
| | | onMounted(() => { |
| | | fetchCategories(); |
| | | fetchTreeData(); |
| | | }); |
| | | // è·ååç±»å表 |
| | | const fetchCategories = async () => { |
| | | loading.value = true; |
| | | try { |
| | | const res = await getSparePartsList(); |
| | | if (res.code === 200) { |
| | | categories.value = res.data.records; |
| | | } else { |
| | | ElMessage.error(res.message || "è·ååç±»å表失败"); |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error("è·ååç±»å表失败"); |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | | }; |
| | | |
| | | // æ°å¢åç±» |
| | | const addCategory = () => { |
| | | form.id = ""; |
| | | form.name = ""; |
| | | form.sparePartsNo = ""; |
| | | form.status = ""; |
| | | form.description = ""; |
| | | form.parentId = null; |
| | | operationType.value = "add"; |
| | | dialogVisible.value = true; |
| | | console.log("dialogVisible æ´æ°ä¸º", dialogVisible.value); |
| | | }; |
| | | |
| | | // ç¼è¾åç±» |
| | | const editCategory = row => { |
| | | Object.assign(form, row); |
| | | operationType.value = "edit"; |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | // å é¤åç±» |
| | | const deleteCategory = async id => { |
| | | try { |
| | | await ElMessageBox.confirm("æ¤æä½å°æ°¸ä¹
å é¤è¯¥åç±»ï¼æ¯å¦ç»§ç»?", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }); |
| | | loading.value = true; |
| | | const res = await delSparePart(id); |
| | | if (res.code === 200) { |
| | | ElMessage.success("å 餿å"); |
| | | fetchTreeData(); |
| | | } else { |
| | | ElMessage.error(res.message || "å é¤å¤±è´¥"); |
| | | } |
| | | } catch (error) { |
| | | if (error !== "cancel") { |
| | | ElMessage.error("å é¤å¤±è´¥"); |
| | | } |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | | }; |
| | | |
| | | // æäº¤è¡¨å |
| | | const submitForm = async () => { |
| | | if (!formRef.value) return; |
| | | try { |
| | | await formRef.value.validate(); |
| | | formLoading.value = true; |
| | | if (operationType.value === "edit") { |
| | | let res = await editSparePart(form); |
| | | if (res.code === 200) { |
| | | ElMessage.success("ç¼è¾æå"); |
| | | dialogVisible.value = false; |
| | | fetchTreeData(); |
| | | } |
| | | } else { |
| | | let res = await addSparePart(form); |
| | | if (res.code === 200) { |
| | | ElMessage.success("ç¼è¾æå"); |
| | | dialogVisible.value = false; |
| | | fetchTreeData(); |
| | | } |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error("请填å宿´è¡¨åä¿¡æ¯"); |
| | | } finally { |
| | | formLoading.value = false; |
| | | } |
| | | }; |
| | | |
| | | // ç»ä»¶æè½½æ¶è·ååç±»å表 |
| | | onMounted(() => { |
| | | fetchCategories(); |
| | | fetchTreeData(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .spare-part-category { |
| | | padding: 20px; |
| | | } |
| | | .table_list { |
| | | margin-top: unset; |
| | | } |
| | | .actions { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | margin-bottom: 10px; |
| | | align-items: center; |
| | | } |
| | | .spare-part-category { |
| | | padding: 20px; |
| | | } |
| | | .table_list { |
| | | margin-top: unset; |
| | | } |
| | | .actions { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | margin-bottom: 10px; |
| | | align-items: center; |
| | | } |
| | | |
| | | /* åµå¥æ å½¢ç»ææ ·å¼ */ |
| | | .nested-tree-node { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | width: 100%; |
| | | padding: 0 4px; |
| | | height: 30px; |
| | | line-height: 30px; |
| | | } |
| | | /* åµå¥æ å½¢ç»ææ ·å¼ */ |
| | | .nested-tree-node { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | width: 100%; |
| | | padding: 0 4px; |
| | | height: 30px; |
| | | line-height: 30px; |
| | | } |
| | | |
| | | .category-code { |
| | | color: #606266; |
| | | font-size: 12px; |
| | | margin-left: 8px; |
| | | } |
| | | .category-code { |
| | | color: #606266; |
| | | font-size: 12px; |
| | | margin-left: 8px; |
| | | } |
| | | |
| | | .tree-actions { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | margin-left: auto; |
| | | } |
| | | .tree-actions { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | margin-left: auto; |
| | | } |
| | | |
| | | /* è¡¨æ ¼æ ·å¼è°æ´ */ |
| | | .el-table { |
| | | font-size: 14px; |
| | | } |
| | | /* è¡¨æ ¼æ ·å¼è°æ´ */ |
| | | .el-table { |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .el-table__header-wrapper th { |
| | | background-color: #f5f7fa; |
| | | font-weight: 600; |
| | | } |
| | | .el-table__header-wrapper th { |
| | | background-color: #f5f7fa; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | .el-table__row:hover > td { |
| | | background-color: #fafafa; |
| | | } |
| | | .el-table__row:hover > td { |
| | | background-color: #fafafa; |
| | | } |
| | | |
| | | /* åµå¥æ å½¢ç»æç¹å®æ ·å¼ */ |
| | | .nested-tree { |
| | | background-color: transparent; |
| | | } |
| | | /* åµå¥æ å½¢ç»æç¹å®æ ·å¼ */ |
| | | .nested-tree { |
| | | background-color: transparent; |
| | | } |
| | | |
| | | .nested-tree .el-tree-node__content { |
| | | height: auto; |
| | | background-color: transparent; |
| | | } |
| | | .nested-tree .el-tree-node__content { |
| | | height: auto; |
| | | background-color: transparent; |
| | | } |
| | | |
| | | /* æç´¢æ¡æ ·å¼è°æ´ */ |
| | | .actions .el-input { |
| | | margin-right: 10px; |
| | | width: 200px; |
| | | } |
| | | /* æç´¢æ¡æ ·å¼è°æ´ */ |
| | | .actions .el-input { |
| | | margin-right: 10px; |
| | | width: 200px; |
| | | } |
| | | |
| | | /* æé®ç»æ ·å¼ */ |
| | | .actions > div { |
| | | display: flex; |
| | | gap: 10px; |
| | | } |
| | | /* æé®ç»æ ·å¼ */ |
| | | .actions > div { |
| | | display: flex; |
| | | gap: 10px; |
| | | } |
| | | |
| | | /* ç¡®ä¿è¡¨æ ¼ä¸çæä½æé®ä¸ä¼è¢«æªæ */ |
| | | .el-table-column--fixed-right .el-button { |
| | | margin: 0 2px; |
| | | } |
| | | /* ç¡®ä¿è¡¨æ ¼ä¸çæä½æé®ä¸ä¼è¢«æªæ */ |
| | | .el-table-column--fixed-right .el-button { |
| | | margin: 0 2px; |
| | | } |
| | | |
| | | /* æ å½¢èç¹å
å®¹æ ·å¼ */ |
| | | .nested-tree .el-tree-node__expand-icon { |
| | | font-size: 12px; |
| | | margin-right: 4px; |
| | | } |
| | | /* æ å½¢èç¹å
å®¹æ ·å¼ */ |
| | | .nested-tree .el-tree-node__expand-icon { |
| | | font-size: 12px; |
| | | margin-right: 4px; |
| | | } |
| | | |
| | | /* ç©ºç¶ææ ·å¼ */ |
| | | .el-table .cell:empty::before { |
| | | content: '-'; |
| | | color: #c0c4cc; |
| | | } |
| | | /* ç©ºç¶ææ ·å¼ */ |
| | | .el-table .cell:empty::before { |
| | | content: "-"; |
| | | color: #c0c4cc; |
| | | } |
| | | |
| | | /* å±å¼/æå åè½æ ·å¼ */ |
| | | .expand-icon { |
| | | display: inline-block; |
| | | width: 20px; |
| | | height: 20px; |
| | | text-align: center; |
| | | line-height: 20px; |
| | | cursor: pointer; |
| | | font-size: 12px; |
| | | color: #909399; |
| | | } |
| | | /* å±å¼/æå åè½æ ·å¼ */ |
| | | .expand-icon { |
| | | display: inline-block; |
| | | width: 20px; |
| | | height: 20px; |
| | | text-align: center; |
| | | line-height: 20px; |
| | | cursor: pointer; |
| | | font-size: 12px; |
| | | color: #909399; |
| | | } |
| | | |
| | | .expand-icon.expanded { |
| | | color: #409eff; |
| | | } |
| | | .expand-icon.expanded { |
| | | color: #409eff; |
| | | } |
| | | |
| | | /* å±å¼å
å®¹æ ·å¼ */ |
| | | .expand-content { |
| | | padding: 10px 20px; |
| | | } |
| | | /* å±å¼å
å®¹æ ·å¼ */ |
| | | .expand-content { |
| | | padding: 10px 20px; |
| | | } |
| | | |
| | | /* å级å
å®¹æ ·å¼ */ |
| | | .child-content { |
| | | padding-left: 40px; |
| | | } |
| | | /* å级å
å®¹æ ·å¼ */ |
| | | .child-content { |
| | | padding-left: 40px; |
| | | } |
| | | |
| | | /* æ ååç±»æç¤ºæ ·å¼ */ |
| | | .no-children { |
| | | padding: 10px 20px; |
| | | color: #909399; |
| | | font-size: 14px; |
| | | } |
| | | /* æ ååç±»æç¤ºæ ·å¼ */ |
| | | .no-children { |
| | | padding: 10px 20px; |
| | | color: #909399; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | /* ç¡®ä¿å±å¼çè¡¨æ ¼æ ·å¼æ£ç¡® */ |
| | | .el-table .el-table__expanded-cell { |
| | | background-color: #fafafa; |
| | | } |
| | | /* ç¡®ä¿å±å¼çè¡¨æ ¼æ ·å¼æ£ç¡® */ |
| | | .el-table .el-table__expanded-cell { |
| | | background-color: #fafafa; |
| | | } |
| | | |
| | | /* å±å¼çåè¡¨æ ¼æ ·å¼ */ |
| | | .el-table .el-table { |
| | | border-top: none; |
| | | border-bottom: none; |
| | | } |
| | | /* å±å¼çåè¡¨æ ¼æ ·å¼ */ |
| | | .el-table .el-table { |
| | | border-top: none; |
| | | border-bottom: none; |
| | | } |
| | | |
| | | /* å±å¼çåè¡¨æ ¼åå
æ ¼æ ·å¼ */ |
| | | .expand-content .el-table__body-wrapper .el-table__row { |
| | | background-color: #ffffff; |
| | | } |
| | | /* å±å¼çåè¡¨æ ¼åå
æ ¼æ ·å¼ */ |
| | | .expand-content .el-table__body-wrapper .el-table__row { |
| | | background-color: #ffffff; |
| | | } |
| | | |
| | | .expand-content .el-table__body-wrapper .el-table__row:hover > td { |
| | | background-color: #fafafa; |
| | | } |
| | | .expand-content .el-table__body-wrapper .el-table__row:hover > td { |
| | | background-color: #fafafa; |
| | | } |
| | | </style> |
| | |
| | | <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" |
| | | placeholder="请è¾å
¥é¨é¨åç§°" |
| | | clearable |
| | | style="width: 200px" |
| | | /> |
| | | <el-input v-model="searchForm.department" |
| | | placeholder="请è¾å
¥é¨é¨åç§°" |
| | | clearable |
| | | style="width: 200px" /> |
| | | </el-form-item> |
| | | <el-form-item label="å§å"> |
| | | <el-input |
| | | v-model="searchForm.name" |
| | | placeholder="请è¾å
¥å§å" |
| | | clearable |
| | | style="width: 200px" |
| | | /> |
| | | <el-input v-model="searchForm.name" |
| | | placeholder="请è¾å
¥å§å" |
| | | clearable |
| | | 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" |
| | | :data="tableData" |
| | | :dict-types="dictTypes" |
| | | :loading="loading" |
| | | :show-selection="true" |
| | | :show-actions="true" |
| | | :show-pagination="true" |
| | | :pagination="pagination" |
| | | height="calc(100vh - 280px)" |
| | | @selection-change="handleSelectionChange" |
| | | @edit="handleEdit" |
| | | @delete="handleDelete" |
| | | @select-change="handleSelectChange" |
| | | @input-change="handleInputChange" |
| | | @size-change="handleSizeChange" |
| | | @current-change="handleCurrentChange" |
| | | /> |
| | | <DynamicTable ref="dynamicTableRef" |
| | | :data="tableData" |
| | | :dict-types="dictTypes" |
| | | :loading="loading" |
| | | :show-selection="true" |
| | | :show-actions="true" |
| | | :show-pagination="true" |
| | | :pagination="pagination" |
| | | height="calc(100vh - 280px)" |
| | | @selection-change="handleSelectionChange" |
| | | @edit="handleEdit" |
| | | @delete="handleDelete" |
| | | @select-change="handleSelectChange" |
| | | @input-change="handleInputChange" |
| | | @size-change="handleSizeChange" |
| | | @current-change="handleCurrentChange" /> |
| | | </div> |
| | | |
| | | <!-- æ°å¢/ç¼è¾å¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | v-model="dialogVisible" |
| | | :title="dialogTitle" |
| | | width="600px" |
| | | 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="请è¾å
¥é¨é¨" /> |
| | | <el-dialog v-model="dialogVisible" |
| | | :title="dialogTitle" |
| | | width="600px" |
| | | 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="请è¾å
¥é¨é¨" /> |
| | | </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" |
| | | :key="dictItem.value" |
| | | :label="dictItem.label" |
| | | :prop="dictItem.value" |
| | | > |
| | | <el-select |
| | | v-model="form[dictItem.value]" |
| | | placeholder="è¯·éæ©" |
| | | style="width: 100%" |
| | | > |
| | | <el-option |
| | | v-for="option in dictItem.options" |
| | | :key="option.value" |
| | | :label="option.label" |
| | | :value="option.value" |
| | | /> |
| | | <el-form-item v-for="dictItem in dynamicFormItems" |
| | | :key="dictItem.value" |
| | | :label="dictItem.label" |
| | | :prop="dictItem.value"> |
| | | <el-select v-model="form[dictItem.value]" |
| | | placeholder="è¯·éæ©" |
| | | style="width: 100%"> |
| | | <el-option v-for="option in dictItem.options" |
| | | :key="option.value" |
| | | :label="option.label" |
| | | :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: '' |
| | | }) |
| | | // æç´¢è¡¨å |
| | | const searchForm = reactive({ |
| | | department: "", |
| | | name: "", |
| | | }); |
| | | |
| | | // è¡¨æ ¼æ°æ® |
| | | const tableData = ref([ |
| | | { |
| | | id: 1, |
| | | department: 'ææ¯é¨', |
| | | name: 'å¼ ä¸', |
| | | employeeId: 'EMP001', |
| | | status: '1', |
| | | level: '2', |
| | | position: '1' |
| | | }, |
| | | { |
| | | id: 2, |
| | | department: '人äºé¨', |
| | | name: 'æå', |
| | | employeeId: 'EMP002', |
| | | status: '0', |
| | | level: '1', |
| | | position: '2' |
| | | }, |
| | | { |
| | | id: 3, |
| | | department: 'è´¢å¡é¨', |
| | | name: 'çäº', |
| | | employeeId: 'EMP003', |
| | | status: '1', |
| | | level: '3', |
| | | position: '1' |
| | | } |
| | | ]) |
| | | |
| | | // åå
¸ç±»åé
ç½® |
| | | const dictTypes = ref([ |
| | | 'sys_normal_disable', // ç¶æåå
¸ |
| | | 'sys_user_level', // 级å«åå
¸ |
| | | 'sys_user_position' // èä½åå
¸ |
| | | ]) |
| | | |
| | | // å页é
ç½® |
| | | const pagination = reactive({ |
| | | current: 1, |
| | | size: 10, |
| | | total: 0 |
| | | }) |
| | | |
| | | // è¡¨åæ°æ® |
| | | const form = reactive({ |
| | | 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' } |
| | | ] |
| | | } |
| | | |
| | | // å¨æè¡¨å项 |
| | | const dynamicFormItems = computed(() => { |
| | | // è¿éå¯ä»¥æ ¹æ®åå
¸æ°æ®å¨æçæè¡¨å项 |
| | | return [ |
| | | // è¡¨æ ¼æ°æ® |
| | | const tableData = ref([ |
| | | { |
| | | label: 'ç¶æ', |
| | | value: 'status', |
| | | options: [ |
| | | { label: 'å¯ç¨', value: '1' }, |
| | | { label: 'ç¦ç¨', value: '0' } |
| | | ] |
| | | id: 1, |
| | | department: "ææ¯é¨", |
| | | name: "å¼ ä¸", |
| | | employeeId: "EMP001", |
| | | status: "1", |
| | | level: "2", |
| | | position: "1", |
| | | }, |
| | | { |
| | | label: '级å«', |
| | | value: 'level', |
| | | options: [ |
| | | { label: 'å级', value: '1' }, |
| | | { label: 'ä¸çº§', value: '2' }, |
| | | { label: 'é«çº§', value: '3' } |
| | | ] |
| | | id: 2, |
| | | department: "人äºé¨", |
| | | name: "æå", |
| | | employeeId: "EMP002", |
| | | status: "0", |
| | | level: "1", |
| | | position: "2", |
| | | }, |
| | | { |
| | | label: 'èä½', |
| | | value: 'position', |
| | | options: [ |
| | | { label: 'åå·¥', value: '1' }, |
| | | { label: '主管', value: '2' }, |
| | | { label: 'ç»ç', value: '3' } |
| | | ] |
| | | id: 3, |
| | | department: "è´¢å¡é¨", |
| | | name: "çäº", |
| | | employeeId: "EMP003", |
| | | status: "1", |
| | | level: "3", |
| | | position: "1", |
| | | }, |
| | | ]); |
| | | |
| | | // åå
¸ç±»åé
ç½® |
| | | const dictTypes = ref([ |
| | | "sys_normal_disable", // ç¶æåå
¸ |
| | | "sys_user_level", // 级å«åå
¸ |
| | | "sys_user_position", // èä½åå
¸ |
| | | ]); |
| | | |
| | | // å页é
ç½® |
| | | const pagination = reactive({ |
| | | current: 1, |
| | | size: 10, |
| | | total: 0, |
| | | }); |
| | | |
| | | // è¡¨åæ°æ® |
| | | const form = reactive({ |
| | | 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" }], |
| | | }; |
| | | |
| | | // å¨æè¡¨å项 |
| | | const dynamicFormItems = computed(() => { |
| | | // è¿éå¯ä»¥æ ¹æ®åå
¸æ°æ®å¨æçæè¡¨å项 |
| | | return [ |
| | | { |
| | | label: "ç¶æ", |
| | | value: "status", |
| | | options: [ |
| | | { label: "å¯ç¨", value: "1" }, |
| | | { label: "ç¦ç¨", value: "0" }, |
| | | ], |
| | | }, |
| | | { |
| | | label: "级å«", |
| | | value: "level", |
| | | options: [ |
| | | { label: "å级", value: "1" }, |
| | | { label: "ä¸çº§", value: "2" }, |
| | | { label: "é«çº§", value: "3" }, |
| | | ], |
| | | }, |
| | | { |
| | | label: "èä½", |
| | | value: "position", |
| | | options: [ |
| | | { label: "åå·¥", value: "1" }, |
| | | { label: "主管", value: "2" }, |
| | | { label: "ç»ç", value: "3" }, |
| | | ], |
| | | }, |
| | | ]; |
| | | }); |
| | | |
| | | // ç»ä»¶å¼ç¨ |
| | | const dynamicTableRef = ref(null); |
| | | const formRef = ref(null); |
| | | |
| | | // äºä»¶å¤ç彿° |
| | | const handleSearch = () => { |
| | | // å®ç°æç´¢é»è¾ |
| | | console.log("æç´¢æ¡ä»¶:", searchForm); |
| | | ElMessage.success("æç´¢åè½å¾
å®ç°"); |
| | | }; |
| | | |
| | | const handleReset = () => { |
| | | searchForm.department = ""; |
| | | searchForm.name = ""; |
| | | }; |
| | | |
| | | const handleAdd = () => { |
| | | 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; |
| | | }; |
| | | |
| | | const handleDelete = async (row, index) => { |
| | | try { |
| | | await ElMessageBox.confirm("ç¡®å®è¦å é¤è¿æ¡è®°å½åï¼", "æç¤º", { |
| | | type: "warning", |
| | | }); |
| | | |
| | | tableData.value.splice(index, 1); |
| | | ElMessage.success("å 餿å"); |
| | | } catch (error) { |
| | | // ç¨æ·åæ¶å é¤ |
| | | } |
| | | ] |
| | | }) |
| | | }; |
| | | |
| | | // ç»ä»¶å¼ç¨ |
| | | const dynamicTableRef = ref(null) |
| | | const formRef = ref(null) |
| | | const handleSelectionChange = selection => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | |
| | | // äºä»¶å¤ç彿° |
| | | const handleSearch = () => { |
| | | // å®ç°æç´¢é»è¾ |
| | | console.log('æç´¢æ¡ä»¶:', searchForm) |
| | | ElMessage.success('æç´¢åè½å¾
å®ç°') |
| | | } |
| | | const handleSelectChange = (row, prop, value) => { |
| | | console.log("éæ©åå:", row, prop, value); |
| | | // å¯ä»¥å¨è¿éå¤çæ°æ®æ´æ°é»è¾ |
| | | }; |
| | | |
| | | const handleReset = () => { |
| | | searchForm.department = '' |
| | | searchForm.name = '' |
| | | } |
| | | const handleInputChange = (row, prop, value) => { |
| | | console.log("è¾å
¥åå:", row, prop, value); |
| | | // å¯ä»¥å¨è¿éå¤çæ°æ®æ´æ°é»è¾ |
| | | }; |
| | | |
| | | const handleAdd = () => { |
| | | dialogTitle.value = 'æ°å¢åå·¥' |
| | | editIndex.value = -1 |
| | | resetForm() |
| | | dialogVisible.value = true |
| | | } |
| | | const handleSizeChange = size => { |
| | | pagination.size = size; |
| | | // éæ°å è½½æ°æ® |
| | | }; |
| | | |
| | | const handleEdit = (row, index) => { |
| | | dialogTitle.value = 'ç¼è¾åå·¥' |
| | | editIndex.value = index |
| | | Object.assign(form, row) |
| | | dialogVisible.value = true |
| | | } |
| | | const handleCurrentChange = current => { |
| | | pagination.current = current; |
| | | // éæ°å è½½æ°æ® |
| | | }; |
| | | |
| | | const handleDelete = async (row, index) => { |
| | | try { |
| | | await ElMessageBox.confirm('ç¡®å®è¦å é¤è¿æ¡è®°å½åï¼', 'æç¤º', { |
| | | type: 'warning' |
| | | }) |
| | | |
| | | tableData.value.splice(index, 1) |
| | | ElMessage.success('å 餿å') |
| | | } catch (error) { |
| | | // ç¨æ·åæ¶å é¤ |
| | | } |
| | | } |
| | | const handleSubmit = async () => { |
| | | try { |
| | | await formRef.value.validate(); |
| | | |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection |
| | | } |
| | | |
| | | const handleSelectChange = (row, prop, value) => { |
| | | console.log('éæ©åå:', row, prop, value) |
| | | // å¯ä»¥å¨è¿éå¤çæ°æ®æ´æ°é»è¾ |
| | | } |
| | | |
| | | const handleInputChange = (row, prop, value) => { |
| | | console.log('è¾å
¥åå:', row, prop, value) |
| | | // å¯ä»¥å¨è¿éå¤çæ°æ®æ´æ°é»è¾ |
| | | } |
| | | |
| | | const handleSizeChange = (size) => { |
| | | pagination.size = size |
| | | // éæ°å è½½æ°æ® |
| | | } |
| | | |
| | | const handleCurrentChange = (current) => { |
| | | pagination.current = current |
| | | // éæ°å è½½æ°æ® |
| | | } |
| | | |
| | | const handleSubmit = async () => { |
| | | try { |
| | | await formRef.value.validate() |
| | | |
| | | if (editIndex.value === -1) { |
| | | // æ°å¢ |
| | | const newRow = { |
| | | id: Date.now(), |
| | | ...form |
| | | if (editIndex.value === -1) { |
| | | // æ°å¢ |
| | | const newRow = { |
| | | id: Date.now(), |
| | | ...form, |
| | | }; |
| | | tableData.value.push(newRow); |
| | | ElMessage.success("æ°å¢æå"); |
| | | } else { |
| | | // ç¼è¾ |
| | | Object.assign(tableData.value[editIndex.value], form); |
| | | ElMessage.success("ç¼è¾æå"); |
| | | } |
| | | tableData.value.push(newRow) |
| | | ElMessage.success('æ°å¢æå') |
| | | } else { |
| | | // ç¼è¾ |
| | | Object.assign(tableData.value[editIndex.value], form) |
| | | ElMessage.success('ç¼è¾æå') |
| | | |
| | | dialogVisible.value = false; |
| | | } catch (error) { |
| | | console.error("表åéªè¯å¤±è´¥:", error); |
| | | } |
| | | |
| | | dialogVisible.value = false |
| | | } catch (error) { |
| | | console.error('表åéªè¯å¤±è´¥:', error) |
| | | } |
| | | } |
| | | }; |
| | | |
| | | const resetForm = () => { |
| | | Object.assign(form, { |
| | | department: '', |
| | | name: '', |
| | | employeeId: '', |
| | | status: '', |
| | | level: '', |
| | | position: '' |
| | | }) |
| | | formRef.value?.resetFields() |
| | | } |
| | | const resetForm = () => { |
| | | Object.assign(form, { |
| | | department: "", |
| | | name: "", |
| | | employeeId: "", |
| | | status: "", |
| | | level: "", |
| | | position: "", |
| | | }); |
| | | formRef.value?.resetFields(); |
| | | }; |
| | | |
| | | // ç»ä»¶æè½½æ¶åå§åæ°æ® |
| | | onMounted(() => { |
| | | pagination.total = tableData.value.length |
| | | }) |
| | | // ç»ä»¶æè½½æ¶åå§åæ°æ® |
| | | onMounted(() => { |
| | | pagination.total = tableData.value.length; |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .app-container { |
| | | padding: 20px; |
| | | } |
| | | .app-container { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .search-form { |
| | | margin-bottom: 20px; |
| | | padding: 20px; |
| | | background-color: #f5f5f5; |
| | | border-radius: 4px; |
| | | } |
| | | .search-form { |
| | | margin-bottom: 20px; |
| | | padding: 20px; |
| | | background-color: #f5f5f5; |
| | | border-radius: 4px; |
| | | } |
| | | |
| | | .table-container { |
| | | background-color: #fff; |
| | | border-radius: 4px; |
| | | padding: 20px; |
| | | } |
| | | .table-container { |
| | | background-color: #fff; |
| | | border-radius: 4px; |
| | | padding: 20px; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | text-align: right; |
| | | } |
| | | .dialog-footer { |
| | | text-align: right; |
| | | } |
| | | </style> |
| | |
| | | <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-option> |
| | | </el-select> |
| | | </div> |
| | | </div> |
| | | <div class="search_thing"> |
| | | <div class="search_label">è´§æ¶ï¼</div> |
| | | <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.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> |
| | | <!-- <div class="search_thing"> |
| | | <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-option> |
| | | </el-select> |
| | | </div> |
| | | </div> |
| | | <!-- <div class="search_thing"> |
| | | <el-button size="small" @click="handleShelf(entity.shelfId,'')">éç½®</el-button> |
| | | <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" |
| | | :disabled="entity.warehouseId==null">æ·»å è´§æ¶</el-button> |
| | | <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" |
| | | placement="top" |
| | | v-for="(n,j) in m.documentationDtoList" |
| | | :key="j"> |
| | | <el-tooltip effect="dark" |
| | | placement="top" |
| | | v-for="(n,j) in m.documentationDtoList" |
| | | :key="j"> |
| | | <template #content><span>{{ n.docName }}</span> |
| | | <span> [{{ n.docNumber }}]</span></template> |
| | | <li class="green" |
| | | @click="handelDetail(n)"> |
| | | @click="handelDetail(n)"> |
| | | <i></i> |
| | | <span>{{ n.docName }}</span> |
| | | <span> [{{ n.docNumber }}] <span :style="{ color: getStatusColor(n.docStatus) }">ï¼{{ n.docStatus }}ï¼</span></span> |
| | |
| | | </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" |
| | | empty-text="ææ æ°æ®"> |
| | | <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 |
| | | }) |
| | | // ååºå¼æ°æ® |
| | | const entity = reactive({ |
| | | warehouseId: 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) => { |
| | | if (!newVal) { |
| | | Object.keys(shelves).forEach(key => delete shelves[key]) |
| | | } |
| | | }) |
| | | |
| | | // æ¹æ³ |
| | | |
| | | const selectList = async () => { |
| | | // è¿ééè¦æ¿æ¢ä¸ºå®é
çAPIè°ç¨ |
| | | const res = await getWarehouseList() |
| | | warehouse.value = res.data |
| | | |
| | | if (warehouse.value.length == 0) { |
| | | entity.warehouseId = '' |
| | | entity.shelfId = '' |
| | | tableList.value = [] |
| | | } |
| | | |
| | | |
| | | |
| | | if (!entity.warehouseId && warehouse.value.length > 0) { |
| | | entity.warehouseId = warehouse.value[0].id |
| | | warehouseChange(entity.warehouseId) |
| | | if (shelf.value.length > 0) { |
| | | entity.shelfId = shelf.value[0].id |
| | | handleShelf(entity.shelfId) |
| | | } else { |
| | | tableList.value = [] |
| | | // çå¬å¨ |
| | | watch(isEdit, newVal => { |
| | | if (!newVal) { |
| | | Object.keys(shelves).forEach(key => delete shelves[key]); |
| | | } |
| | | } else if (warehouse.value.length > 0) { |
| | | warehouseChange(entity.warehouseId) |
| | | if (shelf.value.length > 0) { |
| | | entity.shelfId = shelf.value[0].id |
| | | handleShelf(entity.shelfId) |
| | | } else { |
| | | tableList.value = [] |
| | | }); |
| | | |
| | | // æ¹æ³ |
| | | |
| | | const selectList = async () => { |
| | | // è¿ééè¦æ¿æ¢ä¸ºå®é
çAPIè°ç¨ |
| | | const res = await getWarehouseList(); |
| | | warehouse.value = res.data; |
| | | |
| | | if (warehouse.value.length == 0) { |
| | | entity.warehouseId = ""; |
| | | entity.shelfId = ""; |
| | | tableList.value = []; |
| | | } |
| | | } |
| | | } |
| | | |
| | | const confirmWarehouse = () => { |
| | | if (!name.value) { |
| | | ElMessage.error('请填åä»åºåç§°') |
| | | return |
| | | } |
| | | upLoadWarehouse.value = true |
| | | |
| | | if (currentEdit.value && currentEdit.value.id) { |
| | | // ä¿®æ¹ä»åº |
| | | // è¿ééè¦æ¿æ¢ä¸ºå®é
çAPIè°ç¨ |
| | | updateWarehouse({ |
| | | id: currentEdit.value.id, |
| | | warehouseName: name.value |
| | | }).then(res => { |
| | | upLoadWarehouse.value = false |
| | | warehouseVisible.value = false |
| | | currentEdit.value = null |
| | | ElMessage.success('ä¿®æ¹æå') |
| | | selectList() |
| | | name.value = '' |
| | | warehouseChange(entity.warehouseId) |
| | | }) |
| | | |
| | | } else { |
| | | // æ°å¢ä»åº |
| | | // è¿ééè¦æ¿æ¢ä¸ºå®é
çAPIè°ç¨ |
| | | addWarehouse({ |
| | | warehouseName: name.value |
| | | }).then(res => { |
| | | upLoadWarehouse.value = false |
| | | warehouseVisible.value = false |
| | | ElMessage.success('æ·»å æå') |
| | | selectList() |
| | | name.value = '' |
| | | warehouseChange(entity.warehouseId) |
| | | }) |
| | | } |
| | | } |
| | | if (!entity.warehouseId && warehouse.value.length > 0) { |
| | | entity.warehouseId = warehouse.value[0].id; |
| | | warehouseChange(entity.warehouseId); |
| | | if (shelf.value.length > 0) { |
| | | entity.shelfId = shelf.value[0].id; |
| | | handleShelf(entity.shelfId); |
| | | } else { |
| | | tableList.value = []; |
| | | } |
| | | } else if (warehouse.value.length > 0) { |
| | | warehouseChange(entity.warehouseId); |
| | | if (shelf.value.length > 0) { |
| | | entity.shelfId = shelf.value[0].id; |
| | | handleShelf(entity.shelfId); |
| | | } else { |
| | | tableList.value = []; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | const confirmShelves = () => { |
| | | if (!shelves.name) { |
| | | ElMessage.error('请填åè´§æ¶åç§°') |
| | | return |
| | | } |
| | | if (!shelves.row) { |
| | | ElMessage.error('请填åè´§æ¶å±æ°') |
| | | return |
| | | } |
| | | if (!shelves.col) { |
| | | ElMessage.error('请填åè´§æ¶åæ°') |
| | | return |
| | | } |
| | | upLoadShelves.value = true |
| | | |
| | | if (currentEdit.value && currentEdit.value.id) { |
| | | // ä¿®æ¹ |
| | | updateShelf({ |
| | | id: 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('ä¿®æ¹å¤±è´¥') |
| | | }) |
| | | |
| | | } else { |
| | | // æ°å¢ |
| | | // è¿ééè¦æ¿æ¢ä¸ºå®é
çAPIè°ç¨ |
| | | addShelf({ |
| | | 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('æ·»å 失败') |
| | | }) |
| | | } |
| | | warehouseChange(entity.warehouseId) |
| | | } |
| | | const confirmWarehouse = () => { |
| | | if (!name.value) { |
| | | ElMessage.error("请填åä»åºåç§°"); |
| | | return; |
| | | } |
| | | upLoadWarehouse.value = true; |
| | | |
| | | |
| | | |
| | | const handleDelete = (row, level) => { |
| | | ElMessageBox.confirm('æ¯å¦å é¤å½åæ°æ®?', "è¦å", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning" |
| | | }).then(() => { |
| | | if (level == 1) { |
| | | // å é¤ä»åº |
| | | deleteWarehouse([row.id]).then(res => { |
| | | ElMessage.success('å 餿å') |
| | | selectList() |
| | | }) |
| | | } else { |
| | | // å é¤è´§æ¶ |
| | | deleteShelf({ |
| | | id: row.id |
| | | if (currentEdit.value && currentEdit.value.id) { |
| | | // ä¿®æ¹ä»åº |
| | | // è¿ééè¦æ¿æ¢ä¸ºå®é
çAPIè°ç¨ |
| | | updateWarehouse({ |
| | | id: currentEdit.value.id, |
| | | warehouseName: name.value, |
| | | }).then(res => { |
| | | ElMessage.success('å 餿å') |
| | | selectList() |
| | | }) |
| | | upLoadWarehouse.value = false; |
| | | warehouseVisible.value = false; |
| | | currentEdit.value = null; |
| | | ElMessage.success("ä¿®æ¹æå"); |
| | | selectList(); |
| | | name.value = ""; |
| | | warehouseChange(entity.warehouseId); |
| | | }); |
| | | } else { |
| | | // æ°å¢ä»åº |
| | | // è¿ééè¦æ¿æ¢ä¸ºå®é
çAPIè°ç¨ |
| | | addWarehouse({ |
| | | warehouseName: name.value, |
| | | }).then(res => { |
| | | upLoadWarehouse.value = false; |
| | | warehouseVisible.value = false; |
| | | ElMessage.success("æ·»å æå"); |
| | | selectList(); |
| | | name.value = ""; |
| | | warehouseChange(entity.warehouseId); |
| | | }); |
| | | } |
| | | warehouseChange(entity.warehouseId) |
| | | }).catch(() => {}) |
| | | } |
| | | }; |
| | | |
| | | const handleEdit = (data, level) => { |
| | | isEdit.value = true |
| | | if (level == 1) { |
| | | warehouseVisible.value = true |
| | | currentEdit.value = data |
| | | name.value = data.label |
| | | } else { |
| | | shelvesVisible.value = true |
| | | currentEdit.value = data |
| | | Object.assign(shelves, { |
| | | name: data.label, |
| | | row: data.row, |
| | | col: data.col, |
| | | warehouseId: data.warehouseId |
| | | }) |
| | | } |
| | | } |
| | | |
| | | const handelDetail = (row) => { |
| | | current.value = row |
| | | isDetail.value = true |
| | | } |
| | | |
| | | // æ ¹æ®ææ¡£ç¶æè¿å对åºçé¢è² |
| | | const getStatusColor = (status) => { |
| | | if (status === 'æ£å¸¸') { |
| | | return '#34BD66' // ç»¿è² |
| | | } else if (status === 'ååº') { |
| | | return '#F56C6C' // çº¢è² |
| | | } |
| | | return '#606266' // é»è®¤é¢è² |
| | | } |
| | | |
| | | const warehouseChange = (val) => { |
| | | tableList.value = [] |
| | | let map = warehouse.value.find(a => { |
| | | return a && a.id === val ? a : null |
| | | }) |
| | | if (map && map.children) { |
| | | shelf.value = map.children |
| | | entity.shelfId = '' |
| | | } else { |
| | | shelf.value = [] |
| | | } |
| | | currentEdit.value = null |
| | | } |
| | | |
| | | const handleShelf = async(e) => { |
| | | if (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 |
| | | }) |
| | | }else{ |
| | | ElMessage.error(res.message) |
| | | const confirmShelves = () => { |
| | | if (!shelves.name) { |
| | | ElMessage.error("请填åè´§æ¶åç§°"); |
| | | return; |
| | | } |
| | | setTimeout(() => { |
| | | 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) |
| | | if (arr.length > 0) { |
| | | if (arr.find(n => n.row == m.row)) { |
| | | arr.push(m) |
| | | } else { |
| | | tableList.value.push(arr) |
| | | arr = [] |
| | | arr.push(m) |
| | | } |
| | | } else { |
| | | arr.push(m) |
| | | } |
| | | } |
| | | if (!shelves.row) { |
| | | ElMessage.error("请填åè´§æ¶å±æ°"); |
| | | return; |
| | | } |
| | | if (!shelves.col) { |
| | | ElMessage.error("请填åè´§æ¶åæ°"); |
| | | return; |
| | | } |
| | | upLoadShelves.value = true; |
| | | |
| | | if (currentEdit.value && currentEdit.value.id) { |
| | | // ä¿®æ¹ |
| | | updateShelf({ |
| | | id: 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 = {}; |
| | | }) |
| | | |
| | | if (arr.length > 0) { |
| | | tableList.value.push(arr) |
| | | .catch(err => { |
| | | upLoadShelves.value = false; |
| | | shelvesVisible.value = false; |
| | | ElMessage.error("ä¿®æ¹å¤±è´¥"); |
| | | }); |
| | | } else { |
| | | // æ°å¢ |
| | | // è¿ééè¦æ¿æ¢ä¸ºå®é
çAPIè°ç¨ |
| | | addShelf({ |
| | | 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("æ·»å 失败"); |
| | | }); |
| | | } |
| | | warehouseChange(entity.warehouseId); |
| | | }; |
| | | |
| | | const handleDelete = (row, level) => { |
| | | ElMessageBox.confirm("æ¯å¦å é¤å½åæ°æ®?", "è¦å", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | if (level == 1) { |
| | | // å é¤ä»åº |
| | | deleteWarehouse([row.id]).then(res => { |
| | | ElMessage.success("å 餿å"); |
| | | selectList(); |
| | | }); |
| | | } else { |
| | | // å é¤è´§æ¶ |
| | | deleteShelf({ |
| | | id: row.id, |
| | | }).then(res => { |
| | | ElMessage.success("å 餿å"); |
| | | selectList(); |
| | | }); |
| | | } |
| | | warehouseChange(entity.warehouseId); |
| | | }) |
| | | .catch(() => {}); |
| | | }; |
| | | |
| | | const handleEdit = (data, level) => { |
| | | isEdit.value = true; |
| | | if (level == 1) { |
| | | warehouseVisible.value = true; |
| | | currentEdit.value = data; |
| | | name.value = data.label; |
| | | } else { |
| | | shelvesVisible.value = true; |
| | | currentEdit.value = data; |
| | | Object.assign(shelves, { |
| | | name: data.label, |
| | | row: data.row, |
| | | col: data.col, |
| | | warehouseId: data.warehouseId, |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | const handelDetail = row => { |
| | | current.value = row; |
| | | isDetail.value = true; |
| | | }; |
| | | |
| | | // æ ¹æ®ææ¡£ç¶æè¿å对åºçé¢è² |
| | | const getStatusColor = status => { |
| | | if (status === "æ£å¸¸") { |
| | | return "#34BD66"; // ç»¿è² |
| | | } else if (status === "ååº") { |
| | | return "#F56C6C"; // çº¢è² |
| | | } |
| | | return "#606266"; // é»è®¤é¢è² |
| | | }; |
| | | |
| | | const warehouseChange = val => { |
| | | tableList.value = []; |
| | | let map = warehouse.value.find(a => { |
| | | return a && a.id === val ? a : null; |
| | | }); |
| | | if (map && map.children) { |
| | | shelf.value = map.children; |
| | | entity.shelfId = ""; |
| | | } else { |
| | | shelf.value = []; |
| | | } |
| | | currentEdit.value = null; |
| | | }; |
| | | |
| | | const handleShelf = async e => { |
| | | if (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; |
| | | }); |
| | | } else { |
| | | ElMessage.error(res.message); |
| | | } |
| | | |
| | | rowList.value = [] |
| | | for (let i = 0; i < set.size; i++) { |
| | | rowList.value.push(`${i + 1} å`) |
| | | } |
| | | console.log(6666, tableList.value,rowList.value,data) |
| | | }, 1000) |
| | | } |
| | | } |
| | | setTimeout(() => { |
| | | 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); |
| | | if (arr.length > 0) { |
| | | if (arr.find(n => n.row == m.row)) { |
| | | arr.push(m); |
| | | } else { |
| | | tableList.value.push(arr); |
| | | arr = []; |
| | | arr.push(m); |
| | | } |
| | | } else { |
| | | arr.push(m); |
| | | } |
| | | } |
| | | }); |
| | | |
| | | if (arr.length > 0) { |
| | | tableList.value.push(arr); |
| | | } |
| | | } |
| | | |
| | | // çå½å¨æ |
| | | onMounted(() => { |
| | | selectList() |
| | | }) |
| | | rowList.value = []; |
| | | for (let i = 0; i < set.size; i++) { |
| | | rowList.value.push(`${i + 1} å`); |
| | | } |
| | | console.log(6666, tableList.value, rowList.value, data); |
| | | }, 1000); |
| | | } |
| | | }; |
| | | |
| | | // çå½å¨æ |
| | | onMounted(() => { |
| | | 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(() => { |
| | |
| | | <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-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" |
| | | :key="milestone.phaseId" |
| | | :timestamp="milestone.endDate" |
| | | > |
| | | <el-timeline-item v-for="milestone in milestoneList" |
| | | :key="milestone.phaseId" |
| | | :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" |
| | | :title="'ç¼è¾éç¨ç¢: ' + (form.phaseName || '')" |
| | | width="600px" |
| | | :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="请è¾å
¥éç¨ç¢åç§°" /> |
| | | <el-dialog v-model="dialogVisible" |
| | | :title="'ç¼è¾éç¨ç¢: ' + (form.phaseName || '')" |
| | | width="600px" |
| | | :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="请è¾å
¥éç¨ç¢åç§°" /> |
| | | </el-form-item> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <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%" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <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%" |
| | | /> |
| | | </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-col :span="12"> |
| | | <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%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <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%" /> |
| | | </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-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 |
| | | } |
| | | }); |
| | | |
| | | 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 |
| | | }); |
| | | |
| | | // 表åéªè¯è§å |
| | | const rules = { |
| | | phaseName: [ |
| | | { required: true, message: '请è¾å
¥éç¨ç¢åç§°', trigger: 'blur' }, |
| | | { min: 2, max: 50, message: 'é¿åº¦å¨ 2 å° 50 个å符', trigger: 'blur' } |
| | | ], |
| | | status: [ |
| | | { required: true, message: 'è¯·éæ©ç¶æ', trigger: 'change' } |
| | | ] |
| | | }; |
| | | |
| | | // è·åéç¨ç¢å表 |
| | | const getMilestoneList = async () => { |
| | | try { |
| | | listProjectPhase(props.projectId).then(res => { |
| | | 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); |
| | | } |
| | | }; |
| | | |
| | | // ç¼è¾éç¨ç¢ |
| | | const handleEdit = (milestone) => { |
| | | // å¤å¶éç¨ç¢æ°æ®å°è¡¨å |
| | | Object.assign(form, { |
| | | phaseId: milestone.phaseId, |
| | | phaseName: milestone.phaseName, |
| | | description: milestone.description, |
| | | endDate: milestone.endDate, |
| | | status: milestone.status, |
| | | projectId: props.projectId |
| | | const props = defineProps({ |
| | | projectId: { |
| | | type: String, |
| | | required: true, |
| | | }, |
| | | }); |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | // æäº¤ç¼è¾è¡¨å |
| | | const submitEditForm = async () => { |
| | | try { |
| | | await formRef.value.validate(); |
| | | |
| | | // åéæ´æ°è¯·æ± |
| | | const res = await updateProjectPhase(form); |
| | | |
| | | if (res.code === 200) { |
| | | ElMessage.success('éç¨ç¢ç¼è¾æå'); |
| | | dialogVisible.value = false; |
| | | getMilestoneList(); // å·æ°å表 |
| | | emit('refresh'); // éç¥ç¶ç»ä»¶å·æ° |
| | | } else { |
| | | ElMessage.error(res.msg || 'éç¨ç¢ç¼è¾å¤±è´¥'); |
| | | } |
| | | } catch (error) { |
| | | if (error.name === 'ValidationError') { |
| | | // 表åéªè¯å¤±è´¥ï¼Element Plusä¼èªå¨æç¤º |
| | | return; |
| | | } |
| | | ElMessage.error('éç¨ç¢ç¼è¾å¤±è´¥'); |
| | | console.error('ç¼è¾éç¨ç¢å¤±è´¥:', error); |
| | | } |
| | | }; |
| | | const emit = defineEmits(["refresh"]); |
| | | |
| | | // å é¤éç¨ç¢ |
| | | const handleDelete = (milestone) => { |
| | | ElMessageBox.confirm( |
| | | `ç¡®å®è¦å é¤éç¨ç¢ "${milestone.phaseName}" åï¼å é¤åå°æ æ³æ¢å¤ã`, |
| | | 'å é¤ç¡®è®¤', |
| | | { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | const milestoneList = ref([]); |
| | | const dialogVisible = ref(false); |
| | | const formRef = ref(null); |
| | | const form = reactive({ |
| | | 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" }, |
| | | ], |
| | | status: [{ required: true, message: "è¯·éæ©ç¶æ", trigger: "change" }], |
| | | }; |
| | | |
| | | // è·åéç¨ç¢å表 |
| | | const getMilestoneList = async () => { |
| | | try { |
| | | listProjectPhase(props.projectId).then(res => { |
| | | 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); |
| | | } |
| | | ) |
| | | .then(async () => { |
| | | try { |
| | | // è°ç¨å é¤API |
| | | const res = await delProjectPhase(milestone.phaseId); |
| | | |
| | | if (res.code === 200) { |
| | | ElMessage.success('éç¨ç¢å 餿å'); |
| | | getMilestoneList(); // å·æ°å表 |
| | | emit('refresh'); // éç¥ç¶ç»ä»¶å·æ° |
| | | } else { |
| | | ElMessage.error(res.msg || 'éç¨ç¢å é¤å¤±è´¥'); |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error('éç¨ç¢å é¤å¤±è´¥'); |
| | | console.error('å é¤éç¨ç¢å¤±è´¥:', error); |
| | | } |
| | | }) |
| | | .catch(() => { |
| | | // ç¨æ·åæ¶å é¤ |
| | | ElMessage.info('已忶å é¤'); |
| | | }; |
| | | |
| | | // ç¼è¾éç¨ç¢ |
| | | const handleEdit = milestone => { |
| | | // å¤å¶éç¨ç¢æ°æ®å°è¡¨å |
| | | Object.assign(form, { |
| | | phaseId: milestone.phaseId, |
| | | phaseName: milestone.phaseName, |
| | | description: milestone.description, |
| | | endDate: milestone.endDate, |
| | | status: milestone.status, |
| | | projectId: props.projectId, |
| | | }); |
| | | }; |
| | | |
| | | // è·åç¶ææ ç¾ç±»å |
| | | const getStatusType = (status) => { |
| | | const statusTypeMap = { |
| | | notStarted: 'info', |
| | | completed: 'success', |
| | | delayed: 'danger' |
| | | dialogVisible.value = true; |
| | | }; |
| | | return statusTypeMap[status] || 'default'; |
| | | }; |
| | | |
| | | // è·åç¶æææ¬ |
| | | const getStatusText = (status) => { |
| | | const statusTextMap = { |
| | | notStarted: 'æªå¼å§', |
| | | completed: '已宿', |
| | | delayed: '已延è¿' |
| | | // æäº¤ç¼è¾è¡¨å |
| | | const submitEditForm = async () => { |
| | | try { |
| | | await formRef.value.validate(); |
| | | |
| | | // åéæ´æ°è¯·æ± |
| | | const res = await updateProjectPhase(form); |
| | | |
| | | if (res.code === 200) { |
| | | ElMessage.success("éç¨ç¢ç¼è¾æå"); |
| | | dialogVisible.value = false; |
| | | getMilestoneList(); // å·æ°å表 |
| | | emit("refresh"); // éç¥ç¶ç»ä»¶å·æ° |
| | | } else { |
| | | ElMessage.error(res.msg || "éç¨ç¢ç¼è¾å¤±è´¥"); |
| | | } |
| | | } catch (error) { |
| | | if (error.name === "ValidationError") { |
| | | // 表åéªè¯å¤±è´¥ï¼Element Plusä¼èªå¨æç¤º |
| | | return; |
| | | } |
| | | ElMessage.error("éç¨ç¢ç¼è¾å¤±è´¥"); |
| | | console.error("ç¼è¾éç¨ç¢å¤±è´¥:", error); |
| | | } |
| | | }; |
| | | return statusTextMap[status] || status; |
| | | }; |
| | | |
| | | // çå¬é¡¹ç®IDåå |
| | | watch(() => props.projectId, () => { |
| | | if (props.projectId) { |
| | | getMilestoneList(); |
| | | } |
| | | }); |
| | | // å é¤éç¨ç¢ |
| | | const handleDelete = milestone => { |
| | | ElMessageBox.confirm( |
| | | `ç¡®å®è¦å é¤éç¨ç¢ "${milestone.phaseName}" åï¼å é¤åå°æ æ³æ¢å¤ã`, |
| | | "å é¤ç¡®è®¤", |
| | | { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | } |
| | | ) |
| | | .then(async () => { |
| | | try { |
| | | // è°ç¨å é¤API |
| | | const res = await delProjectPhase(milestone.phaseId); |
| | | |
| | | // åå§å |
| | | onMounted(() => { |
| | | if (props.projectId) { |
| | | getMilestoneList(); |
| | | } |
| | | }); |
| | | if (res.code === 200) { |
| | | ElMessage.success("éç¨ç¢å 餿å"); |
| | | getMilestoneList(); // å·æ°å表 |
| | | emit("refresh"); // éç¥ç¶ç»ä»¶å·æ° |
| | | } else { |
| | | ElMessage.error(res.msg || "éç¨ç¢å é¤å¤±è´¥"); |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error("éç¨ç¢å é¤å¤±è´¥"); |
| | | console.error("å é¤éç¨ç¢å¤±è´¥:", error); |
| | | } |
| | | }) |
| | | .catch(() => { |
| | | // ç¨æ·åæ¶å é¤ |
| | | ElMessage.info("已忶å é¤"); |
| | | }); |
| | | }; |
| | | |
| | | // è·åç¶ææ ç¾ç±»å |
| | | const getStatusType = status => { |
| | | const statusTypeMap = { |
| | | notStarted: "info", |
| | | completed: "success", |
| | | delayed: "danger", |
| | | }; |
| | | return statusTypeMap[status] || "default"; |
| | | }; |
| | | |
| | | // è·åç¶æææ¬ |
| | | const getStatusText = status => { |
| | | const statusTextMap = { |
| | | notStarted: "æªå¼å§", |
| | | completed: "已宿", |
| | | delayed: "已延è¿", |
| | | }; |
| | | return statusTextMap[status] || status; |
| | | }; |
| | | |
| | | // çå¬é¡¹ç®IDåå |
| | | watch( |
| | | () => props.projectId, |
| | | () => { |
| | | if (props.projectId) { |
| | | getMilestoneList(); |
| | | } |
| | | } |
| | | ); |
| | | |
| | | // åå§å |
| | | onMounted(() => { |
| | | if (props.projectId) { |
| | | getMilestoneList(); |
| | | } |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .milestone-list-container { |
| | | padding: 10px 0; |
| | | } |
| | | .milestone-list-container { |
| | | padding: 10px 0; |
| | | } |
| | | |
| | | .card-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | .card-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | |
| | | .milestone-actions { |
| | | display: flex; |
| | | gap: 10px; |
| | | } |
| | | .milestone-actions { |
| | | display: flex; |
| | | gap: 10px; |
| | | } |
| | | |
| | | .milestone-content { |
| | | padding: 10px 0; |
| | | } |
| | | .milestone-content { |
| | | padding: 10px 0; |
| | | } |
| | | |
| | | .milestone-status { |
| | | margin-top: 10px; |
| | | } |
| | | .milestone-status { |
| | | margin-top: 10px; |
| | | } |
| | | |
| | | .empty-tip { |
| | | margin-top: 40px; |
| | | text-align: center; |
| | | } |
| | | .empty-tip { |
| | | margin-top: 40px; |
| | | text-align: center; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | gap: 10px; |
| | | } |
| | | .dialog-footer { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | gap: 10px; |
| | | } |
| | | </style> |
| src/views/oaSystem/projectManagement/components/taskTree.vue
src/views/oaSystem/projectManagement/index.vue
src/views/oaSystem/projectManagement/projectDetail.vue
src/views/procurementManagement/procurementPlan/index.vue
src/views/productManagement/productIdentifier/index.vue
src/views/productionManagement/processRoute/Edit.vue
src/views/productionManagement/processRoute/New.vue
src/views/productionManagement/productStructure/StructureEdit.vue
src/views/productionManagement/productionOrder/index.vue
src/views/productionManagement/productionProcess/index.vue
src/views/productionManagement/productionReporting/Output.vue
src/views/productionManagement/productionReporting/index.vue
src/views/productionManagement/workOrder/index.vue
src/views/qualityManagement/rawMaterialInspection/components/formDia.vue
src/views/salesManagement/customerManagement/index.vue
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 |