| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <el-dialog |
| | | :title="title" |
| | | :visible.sync="dialogVisible" |
| | | width="900px" |
| | | top="5vh" |
| | | class="exception-detail-dialog" |
| | | @close="handleClose" |
| | | > |
| | | <!-- åºæ¬ä¿¡æ¯ --> |
| | | <div class="info-section"> |
| | | <div class="section-title">åºæ¬ä¿¡æ¯</div> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="8"> |
| | | <div class="info-item"> |
| | | <span class="label">æ£è
å§åï¼</span> |
| | | <span class="value">{{ currentRecord.patientName }}</span> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <div class="info-item"> |
| | | <span class="label">æ§å«ï¼</span> |
| | | <span class="value">{{ currentRecord.gender === 1 ? 'ç·' : '女' }}</span> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <div class="info-item"> |
| | | <span class="label">å¹´é¾ï¼</span> |
| | | <span class="value">{{ currentRecord.age }}å²</span> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <div class="info-item"> |
| | | <span class="label">èç³»æ¹å¼ï¼</span> |
| | | <span class="value">{{ currentRecord.phone }}</span> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <div class="info-item"> |
| | | <span class="label">åºé¢ç§å®¤ï¼</span> |
| | | <span class="value">{{ currentRecord.dischargeDept }}</span> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <div class="info-item"> |
| | | <span class="label">åºé¢ç
åºï¼</span> |
| | | <span class="value">{{ currentRecord.dischargeWard }}</span> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <div class="info-item"> |
| | | <span class="label">å¡«åæ¶é´ï¼</span> |
| | | <span class="value">{{ currentRecord.fillTime }}</span> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <div class="info-item"> |
| | | <span class="label">è´è´£ç§å®¤ï¼</span> |
| | | <el-tag type="primary">{{ currentRecord.responsibilityDept }}</el-tag> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <div class="info-item"> |
| | | <span class="label">å¤çç¶æï¼</span> |
| | | <el-tag |
| | | :type="getStatusTagType(currentRecord.processStatus)" |
| | | effect="dark" |
| | | > |
| | | {{ getStatusText(currentRecord.processStatus) }} |
| | | </el-tag> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | |
| | | <!-- é®å·è¯¦æ
--> |
| | | <div class="questionnaire-section"> |
| | | <div class="section-title">é®å·å¡«å详æ
</div> |
| | | <div class="questionnaire-content"> |
| | | <div class="question-item" v-for="(question, index) in questionnaireData" :key="index"> |
| | | <div class="question-header"> |
| | | <span class="question-index">{{ index + 1 }}.</span> |
| | | <span class="question-text">{{ question.question }}</span> |
| | | <el-tag |
| | | size="mini" |
| | | :type="question.type === 1 ? 'primary' : 'success'" |
| | | class="question-type" |
| | | > |
| | | {{ question.type === 1 ? 'åéé¢' : 'å¤éé¢' }} |
| | | </el-tag> |
| | | </div> |
| | | <div class="question-options"> |
| | | <el-radio-group |
| | | v-model="question.answer" |
| | | v-if="question.type === 1" |
| | | disabled |
| | | > |
| | | <el-radio |
| | | v-for="option in question.options" |
| | | :key="option.value" |
| | | :label="option.value" |
| | | :class="{ 'unsatisfactory-option': isUnsatisfactoryOption(option.value) }" |
| | | > |
| | | {{ option.text }} |
| | | </el-radio> |
| | | </el-radio-group> |
| | | <el-checkbox-group |
| | | v-model="question.answer" |
| | | v-else |
| | | disabled |
| | | > |
| | | <el-checkbox |
| | | v-for="option in question.options" |
| | | :key="option.value" |
| | | :label="option.value" |
| | | :class="{ 'unsatisfactory-option': isUnsatisfactoryOption(option.value) }" |
| | | > |
| | | {{ option.text }} |
| | | </el-checkbox> |
| | | </el-checkbox-group> |
| | | </div> |
| | | <div v-if="question.additional" class="additional-remark"> |
| | | <div class="remark-label">è¡¥å
说æï¼</div> |
| | | <div class="remark-content">{{ question.additional }}</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- å¤çè®°å½ --> |
| | | <div class="process-section"> |
| | | <div class="section-title">å¤çè®°å½</div> |
| | | <div class="process-timeline" v-if="processRecords.length > 0"> |
| | | <el-timeline> |
| | | <el-timeline-item |
| | | v-for="(record, index) in processRecords" |
| | | :key="index" |
| | | :timestamp="record.time" |
| | | placement="top" |
| | | > |
| | | <el-card> |
| | | <div class="process-item"> |
| | | <div class="process-header"> |
| | | <span class="process-user">{{ record.user }}</span> |
| | | <el-tag |
| | | size="small" |
| | | :type="getStatusTagType(record.status)" |
| | | > |
| | | {{ getStatusText(record.status) }} |
| | | </el-tag> |
| | | </div> |
| | | <div class="process-content"> |
| | | <div v-if="record.reportDepts && record.reportDepts.length > 0" class="process-depts"> |
| | | <span class="label">æ¥å¤ç§å®¤ï¼</span> |
| | | <el-tag |
| | | v-for="dept in record.reportDepts" |
| | | :key="dept" |
| | | size="small" |
| | | type="info" |
| | | class="dept-tag" |
| | | > |
| | | {{ dept }} |
| | | </el-tag> |
| | | </div> |
| | | <div v-if="record.remark" class="process-remark"> |
| | | <span class="label">å¤ç夿³¨ï¼</span> |
| | | <span class="content">{{ record.remark }}</span> |
| | | </div> |
| | | <div v-if="record.attachments && record.attachments.length > 0" class="process-attachments"> |
| | | <span class="label">éä»¶ï¼</span> |
| | | <el-button |
| | | v-for="file in record.attachments" |
| | | :key="file.id" |
| | | type="text" |
| | | size="small" |
| | | icon="el-icon-document" |
| | | @click="handlePreviewFile(file)" |
| | | > |
| | | {{ file.name }} |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | </el-timeline-item> |
| | | </el-timeline> |
| | | </div> |
| | | <div v-else class="no-record"> |
| | | ææ å¤çè®°å½ |
| | | </div> |
| | | </div> |
| | | |
| | | <span slot="footer" class="dialog-footer"> |
| | | <el-button |
| | | type="primary" |
| | | icon="el-icon-edit" |
| | | @click="handleProcess" |
| | | v-if="currentRecord.processStatus !== 2" |
| | | > |
| | | å¤çå¼å¸¸ |
| | | </el-button> |
| | | <el-button @click="dialogVisible = false">å
³é</el-button> |
| | | </span> |
| | | |
| | | <!-- å¤çå¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | title="å¤çå¼å¸¸åé¦" |
| | | :visible.sync="processDialogVisible" |
| | | width="600px" |
| | | center |
| | | append-to-body |
| | | > |
| | | <el-form |
| | | :model="processForm" |
| | | :rules="processRules" |
| | | ref="processForm" |
| | | label-width="100px" |
| | | size="medium" |
| | | > |
| | | <el-form-item label="å¤çç¶æ" prop="status"> |
| | | <el-select |
| | | v-model="processForm.status" |
| | | placeholder="è¯·éæ©å¤çç¶æ" |
| | | style="width: 100%" |
| | | > |
| | | <el-option label="å¤çä¸" :value="1" /> |
| | | <el-option label="å·²å¤ç" :value="2" /> |
| | | <el-option label="已驳å" :value="3" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="æ¥å¤ç§å®¤" prop="reportDepts"> |
| | | <el-select |
| | | v-model="processForm.reportDepts" |
| | | placeholder="è¯·éæ©æ¥å¤ç§å®¤" |
| | | multiple |
| | | filterable |
| | | collapse-tags |
| | | style="width: 100%" |
| | | > |
| | | <el-option |
| | | v-for="dept in deptList" |
| | | :key="dept.id" |
| | | :label="dept.name" |
| | | :value="dept.id" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="å¤ç夿³¨" prop="remark"> |
| | | <el-input |
| | | v-model="processForm.remark" |
| | | type="textarea" |
| | | :rows="4" |
| | | placeholder="请è¾å
¥å¤ç夿³¨ï¼æå¤500åï¼" |
| | | maxlength="500" |
| | | show-word-limit |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="éä»¶ä¸ä¼ "> |
| | | <el-upload |
| | | class="upload-demo" |
| | | action="#" |
| | | :on-preview="handleFilePreview" |
| | | :on-remove="handleFileRemove" |
| | | :before-remove="beforeFileRemove" |
| | | :limit="3" |
| | | :on-exceed="handleFileExceed" |
| | | :file-list="fileList" |
| | | > |
| | | <el-button size="small" type="primary">ç¹å»ä¸ä¼ </el-button> |
| | | <div slot="tip" class="el-upload__tip">æ¯æä¸ä¼ å¾çãææ¡£çéä»¶ï¼å个æä»¶ä¸è¶
è¿10MB</div> |
| | | </el-upload> |
| | | </el-form-item> |
| | | </el-form> |
| | | <span slot="footer" class="dialog-footer"> |
| | | <el-button @click="processDialogVisible = false">åæ¶</el-button> |
| | | <el-button |
| | | type="primary" |
| | | @click="submitProcess" |
| | | :loading="processing" |
| | | > |
| | | æäº¤å¤ç |
| | | </el-button> |
| | | </span> |
| | | </el-dialog> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'ExceptionDetailDialog', |
| | | props: { |
| | | // æ¯å¦æ¾ç¤ºå¯¹è¯æ¡ |
| | | visible: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // è®°å½ID |
| | | recordId: { |
| | | type: [Number, String], |
| | | default: null |
| | | }, |
| | | // å¯¹è¯æ¡æ é¢ |
| | | title: { |
| | | type: String, |
| | | default: 'å¼å¸¸åé¦è¯¦æ
' |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | // å½åè®°å½ |
| | | currentRecord: {}, |
| | | |
| | | // é®å·æ°æ® |
| | | questionnaireData: [], |
| | | |
| | | // å¤çè®°å½ |
| | | processRecords: [], |
| | | |
| | | // ç§å®¤å表 |
| | | deptList: [ |
| | | { id: 1, name: 'å¿è¡ç®¡å
ç§' }, |
| | | { id: 2, name: 'ç¥ç»å
ç§' }, |
| | | { id: 3, name: 'æ®å¤ç§' }, |
| | | { id: 4, name: '骨ç§' }, |
| | | { id: 5, name: 'å¦äº§ç§' }, |
| | | { id: 6, name: 'å¿ç§' }, |
| | | { id: 7, name: 'æ¥è¯ç§' }, |
| | | { id: 8, name: 'å¼å¸å
ç§' } |
| | | ], |
| | | |
| | | // å¤çå¯¹è¯æ¡ |
| | | processDialogVisible: false, |
| | | processing: false, |
| | | processForm: { |
| | | status: '', |
| | | reportDepts: [], |
| | | remark: '' |
| | | }, |
| | | processRules: { |
| | | status: [ |
| | | { required: true, message: 'è¯·éæ©å¤çç¶æ', trigger: 'change' } |
| | | ], |
| | | remark: [ |
| | | { required: true, message: '请è¾å
¥å¤ç夿³¨', trigger: 'blur' }, |
| | | { min: 5, max: 500, message: '夿³¨é¿åº¦å¨ 5 å° 500 个å符', trigger: 'blur' } |
| | | ] |
| | | }, |
| | | fileList: [], |
| | | |
| | | // å è½½ç¶æ |
| | | loading: false |
| | | }; |
| | | }, |
| | | |
| | | computed: { |
| | | dialogVisible: { |
| | | get() { |
| | | return this.visible; |
| | | }, |
| | | set(val) { |
| | | this.$emit('update:visible', val); |
| | | } |
| | | } |
| | | }, |
| | | |
| | | watch: { |
| | | visible: { |
| | | immediate: true, |
| | | handler(val) { |
| | | if (val && this.recordId) { |
| | | this.loadData(); |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | |
| | | methods: { |
| | | // å è½½æ°æ® |
| | | async loadData() { |
| | | this.loading = true; |
| | | try { |
| | | await Promise.all([ |
| | | this.loadRecordDetail(), |
| | | this.loadQuestionnaireData(), |
| | | this.loadProcessRecords() |
| | | ]); |
| | | } finally { |
| | | this.loading = false; |
| | | } |
| | | }, |
| | | |
| | | // å 载记å½è¯¦æ
|
| | | async loadRecordDetail() { |
| | | return new Promise(resolve => { |
| | | setTimeout(() => { |
| | | // æ ¹æ®ä¸åçrecordIdè¿åä¸åçmockæ°æ® |
| | | const mockRecords = { |
| | | 1: { |
| | | id: 1, |
| | | patientName: 'å¼ å
ç', |
| | | gender: 1, |
| | | age: 45, |
| | | phone: '13800138000', |
| | | dischargeDept: 'å¿è¡ç®¡å
ç§', |
| | | dischargeWard: 'å
ç§ä¸ç
åº', |
| | | fillTime: '2024-01-15 10:30:25', |
| | | responsibilityDept: 'å¿è¡ç®¡å
ç§', |
| | | processStatus: 0 |
| | | }, |
| | | 2: { |
| | | id: 2, |
| | | patientName: 'æå¥³å£«', |
| | | gender: 0, |
| | | age: 38, |
| | | phone: '13900139000', |
| | | dischargeDept: 'ç¥ç»å
ç§', |
| | | dischargeWard: 'å
ç§äºç
åº', |
| | | fillTime: '2024-01-14 16:20:10', |
| | | responsibilityDept: 'ç¥ç»å
ç§', |
| | | processStatus: 0 |
| | | }, |
| | | 3: { |
| | | id: 3, |
| | | patientName: 'çå
ç', |
| | | gender: 1, |
| | | age: 52, |
| | | phone: '13700137000', |
| | | dischargeDept: 'æ®å¤ç§', |
| | | dischargeWard: 'å¤ç§ä¸ç
åº', |
| | | fillTime: '2024-01-13 09:15:45', |
| | | responsibilityDept: 'æ®å¤ç§', |
| | | processStatus: 1 |
| | | } |
| | | }; |
| | | |
| | | this.currentRecord = mockRecords[this.recordId] || { |
| | | id: 1, |
| | | patientName: 'å¼ å
ç', |
| | | gender: 1, |
| | | age: 45, |
| | | phone: '13800138000', |
| | | dischargeDept: 'å¿è¡ç®¡å
ç§', |
| | | dischargeWard: 'å
ç§ä¸ç
åº', |
| | | fillTime: '2024-01-15 10:30:25', |
| | | responsibilityDept: 'å¿è¡ç®¡å
ç§', |
| | | processStatus: 0 |
| | | }; |
| | | resolve(); |
| | | }, 300); |
| | | }); |
| | | }, |
| | | |
| | | // å è½½é®å·æ°æ® |
| | | async loadQuestionnaireData() { |
| | | return new Promise(resolve => { |
| | | setTimeout(() => { |
| | | this.questionnaireData = [ |
| | | { |
| | | question: 'æ¨å¯¹å»æ¤äººåçæå¡æåº¦æ¯å¦æ»¡æï¼', |
| | | type: 1, |
| | | options: [ |
| | | { value: 'é常满æ', text: 'é常满æ' }, |
| | | { value: '满æ', text: '满æ' }, |
| | | { value: 'ä¸è¬', text: 'ä¸è¬' }, |
| | | { value: '䏿»¡æ', text: '䏿»¡æ' }, |
| | | { value: 'é叏䏿»¡æ', text: 'é叏䏿»¡æ' } |
| | | ], |
| | | answer: '䏿»¡æ', |
| | | additional: 'å»çæ¥æ¿æ¶é´å¤ªçï¼æ²éä¸å¤å
åï¼å¯¹ç
æ
è§£éä¸å¤è¯¦ç»' |
| | | }, |
| | | { |
| | | question: 'æ¨å¯¹å»ççè¯çæ°´å¹³åææ¯è½åè¯ä»·å¦ä½ï¼', |
| | | type: 1, |
| | | options: [ |
| | | { value: 'é常ä¸ä¸', text: 'é常ä¸ä¸' }, |
| | | { value: 'æ¯è¾ä¸ä¸', text: 'æ¯è¾ä¸ä¸' }, |
| | | { value: 'ä¸è¬', text: 'ä¸è¬' }, |
| | | { value: 'ä¸å¤ä¸ä¸', text: 'ä¸å¤ä¸ä¸' }, |
| | | { value: 'é常ä¸ä¸ä¸', text: 'é常ä¸ä¸ä¸' } |
| | | ], |
| | | answer: 'æ¯è¾ä¸ä¸', |
| | | additional: '' |
| | | }, |
| | | { |
| | | question: 'æ¨å¯¹å»é¢çç¯å¢åå«çç¶åµæ¯å¦æ»¡æï¼', |
| | | type: 1, |
| | | options: [ |
| | | { value: 'é常满æ', text: 'é常满æ' }, |
| | | { value: '满æ', text: '满æ' }, |
| | | { value: 'ä¸è¬', text: 'ä¸è¬' }, |
| | | { value: '䏿»¡æ', text: '䏿»¡æ' }, |
| | | { value: 'é叏䏿»¡æ', text: 'é叏䏿»¡æ' } |
| | | ], |
| | | answer: 'ä¸è¬', |
| | | additional: '' |
| | | }, |
| | | { |
| | | question: 'æ¨è®¤ä¸ºå»æ¤äººå䏿¨çæ²éæ¯å¦å
åï¼', |
| | | type: 1, |
| | | options: [ |
| | | { value: 'é常å
å', text: 'é常å
å' }, |
| | | { value: 'æ¯è¾å
å', text: 'æ¯è¾å
å' }, |
| | | { value: 'ä¸è¬', text: 'ä¸è¬' }, |
| | | { value: 'ä¸å¤å
å', text: 'ä¸å¤å
å' }, |
| | | { value: 'é常ä¸å
å', text: 'é常ä¸å
å' } |
| | | ], |
| | | answer: 'ä¸å¤å
å', |
| | | additional: 'å»ç讲解ç
æ
æ¶è¯éå¤ªå¿«ï¼æ²¡æç»è¶³å¤çæ¶é´æé®' |
| | | }, |
| | | { |
| | | question: 'æ¨å¯¹çå¾
å°±è¯åæ²»ççæ¶é´æ¯å¦æ»¡æï¼', |
| | | type: 1, |
| | | options: [ |
| | | { value: 'é常满æ', text: 'é常满æ' }, |
| | | { value: '满æ', text: '满æ' }, |
| | | { value: 'ä¸è¬', text: 'ä¸è¬' }, |
| | | { value: '䏿»¡æ', text: '䏿»¡æ' }, |
| | | { value: 'é叏䏿»¡æ', text: 'é叏䏿»¡æ' } |
| | | ], |
| | | answer: '䏿»¡æ', |
| | | additional: 'é¢çº¦ç9ç¹ï¼å®é
10ç¹æè§å°å»ç' |
| | | } |
| | | ]; |
| | | resolve(); |
| | | }, 300); |
| | | }); |
| | | }, |
| | | |
| | | // å è½½å¤çè®°å½ |
| | | async loadProcessRecords() { |
| | | return new Promise(resolve => { |
| | | setTimeout(() => { |
| | | this.processRecords = [ |
| | | { |
| | | id: 1, |
| | | time: '2024-01-15 14:20:30', |
| | | user: 'å¼ å»ç', |
| | | status: 1, // å¤çä¸ |
| | | reportDepts: ['å»å¡ç§', 'æ¤çé¨'], |
| | | remark: 'å·²æ¶å°åé¦ï¼æ£å¨å®æç¸å
³äººåæ ¸æ¥æ
åµ', |
| | | attachments: [ |
| | | { id: 1, name: 'åæ¥è°æ¥è®°å½.docx' }, |
| | | { id: 2, name: 'æ£è
æ²éè®°å½.jpg' } |
| | | ] |
| | | }, |
| | | { |
| | | id: 2, |
| | | time: '2024-01-15 10:45:12', |
| | | user: 'ç³»ç»', |
| | | status: 0, // å¾
å¤ç |
| | | remark: 'ç³»ç»èªå¨è¯å«ä¸ºå¼å¸¸åé¦ï¼å·²åé
å°è´£ä»»ç§å®¤', |
| | | attachments: [] |
| | | } |
| | | ]; |
| | | resolve(); |
| | | }, 300); |
| | | }); |
| | | }, |
| | | |
| | | // 夿æ¯å¦ä¸ºä¸æ»¡æé项 |
| | | isUnsatisfactoryOption(value) { |
| | | const unsatisfactoryValues = [ |
| | | '䏿»¡æ', |
| | | 'é叏䏿»¡æ', |
| | | 'ä¸å¤ä¸ä¸', |
| | | 'é常ä¸ä¸ä¸', |
| | | 'ä¸å¤å
å', |
| | | 'é常ä¸å
å' |
| | | ]; |
| | | return unsatisfactoryValues.includes(value); |
| | | }, |
| | | |
| | | // è·åç¶ææ ç¾ç±»å |
| | | getStatusTagType(status) { |
| | | switch (status) { |
| | | case 0: return 'warning'; // å¾
å¤ç |
| | | case 1: return 'primary'; // å¤çä¸ |
| | | case 2: return 'success'; // å·²å¤ç |
| | | case 3: return 'danger'; // 已驳å |
| | | default: return 'info'; |
| | | } |
| | | }, |
| | | |
| | | // è·åç¶æææ¬ |
| | | getStatusText(status) { |
| | | switch (status) { |
| | | case 0: return 'å¾
å¤ç'; |
| | | case 1: return 'å¤çä¸'; |
| | | case 2: return 'å·²å¤ç'; |
| | | case 3: return '已驳å'; |
| | | default: return 'æªç¥'; |
| | | } |
| | | }, |
| | | |
| | | // å¤çå¼å¸¸ |
| | | handleProcess() { |
| | | this.processForm = { |
| | | status: this.currentRecord.processStatus === 0 ? 1 : this.currentRecord.processStatus, |
| | | reportDepts: [], |
| | | remark: '' |
| | | }; |
| | | this.processDialogVisible = true; |
| | | }, |
| | | |
| | | // æäº¤å¤ç |
| | | async submitProcess() { |
| | | this.$refs.processForm.validate(async (valid) => { |
| | | if (valid) { |
| | | this.processing = true; |
| | | try { |
| | | // Mock APIè°ç¨ |
| | | await new Promise(resolve => setTimeout(resolve, 1000)); |
| | | |
| | | this.$message.success('å¤çæäº¤æå'); |
| | | this.processDialogVisible = false; |
| | | |
| | | // éæ°å è½½æ°æ® |
| | | await this.loadData(); |
| | | |
| | | // 触åç¶ç»ä»¶å·æ° |
| | | this.$emit('processed'); |
| | | } finally { |
| | | this.processing = false; |
| | | } |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // é¢è§æä»¶ |
| | | handlePreviewFile(file) { |
| | | this.$message.info(`é¢è§æä»¶: ${file.name}`); |
| | | }, |
| | | |
| | | // å¤çå¯¹è¯æ¡å
³é |
| | | handleClose() { |
| | | this.$emit('close'); |
| | | }, |
| | | |
| | | // æä»¶ä¸ä¼ ç¸å
³æ¹æ³ |
| | | handleFilePreview(file) { |
| | | console.log('é¢è§æä»¶:', file); |
| | | }, |
| | | |
| | | handleFileRemove(file, fileList) { |
| | | console.log('ç§»é¤æä»¶:', file, fileList); |
| | | }, |
| | | |
| | | beforeFileRemove(file) { |
| | | return this.$confirm(`ç¡®å®ç§»é¤ ${file.name}ï¼`); |
| | | }, |
| | | |
| | | handleFileExceed(files, fileList) { |
| | | this.$message.warning(`å½åéå¶éæ© 3 个æä»¶ï¼æ¬æ¬¡éæ©äº ${files.length} 个æä»¶ï¼å
±éæ©äº ${files.length + fileList.length} 个æä»¶`); |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .exception-detail-dialog { |
| | | ::v-deep .el-dialog { |
| | | max-height: 85vh; |
| | | display: flex; |
| | | flex-direction: column; |
| | | |
| | | .el-dialog__body { |
| | | flex: 1; |
| | | overflow-y: auto; |
| | | padding: 20px; |
| | | } |
| | | } |
| | | |
| | | .info-section { |
| | | margin-bottom: 20px; |
| | | padding: 20px; |
| | | background: #f8f9fa; |
| | | border-radius: 8px; |
| | | border: 1px solid #ebeef5; |
| | | |
| | | .section-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | margin-bottom: 15px; |
| | | padding-bottom: 10px; |
| | | border-bottom: 2px solid #409EFF; |
| | | } |
| | | |
| | | .info-item { |
| | | margin-bottom: 12px; |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | .label { |
| | | font-size: 14px; |
| | | color: #606266; |
| | | min-width: 80px; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .value { |
| | | font-size: 14px; |
| | | color: #303133; |
| | | font-weight: 500; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .questionnaire-section { |
| | | margin-bottom: 20px; |
| | | padding: 20px; |
| | | background: #fff; |
| | | border-radius: 8px; |
| | | border: 1px solid #ebeef5; |
| | | |
| | | .section-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | margin-bottom: 15px; |
| | | padding-bottom: 10px; |
| | | border-bottom: 2px solid #409EFF; |
| | | } |
| | | |
| | | .questionnaire-content { |
| | | .question-item { |
| | | margin-bottom: 20px; |
| | | padding: 15px; |
| | | border-radius: 6px; |
| | | border: 1px solid #ebeef5; |
| | | transition: all 0.3s; |
| | | |
| | | &:hover { |
| | | border-color: #409EFF; |
| | | box-shadow: 0 2px 12px 0 rgba(64, 158, 255, 0.1); |
| | | } |
| | | |
| | | .question-header { |
| | | display: flex; |
| | | align-items: center; |
| | | margin-bottom: 15px; |
| | | padding-bottom: 10px; |
| | | border-bottom: 1px dashed #dcdfe6; |
| | | |
| | | .question-index { |
| | | font-weight: 600; |
| | | color: #409EFF; |
| | | margin-right: 8px; |
| | | font-size: 15px; |
| | | } |
| | | |
| | | .question-text { |
| | | flex: 1; |
| | | font-size: 15px; |
| | | color: #303133; |
| | | font-weight: 500; |
| | | line-height: 1.5; |
| | | } |
| | | |
| | | .question-type { |
| | | margin-left: 10px; |
| | | } |
| | | } |
| | | |
| | | .question-options { |
| | | ::v-deep .el-radio-group { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 10px; |
| | | } |
| | | |
| | | ::v-deep .el-checkbox-group { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 15px; |
| | | } |
| | | |
| | | ::v-deep .el-radio, |
| | | ::v-deep .el-checkbox { |
| | | margin: 0; |
| | | padding: 8px 12px; |
| | | border-radius: 4px; |
| | | border: 1px solid #ebeef5; |
| | | transition: all 0.3s; |
| | | |
| | | &:hover { |
| | | background: #f5f7fa; |
| | | } |
| | | |
| | | &.unsatisfactory-option { |
| | | border-color: #e6a23c; |
| | | background: #fdf6ec; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .additional-remark { |
| | | margin-top: 15px; |
| | | padding: 12px; |
| | | background: #f0f9ff; |
| | | border-radius: 6px; |
| | | border-left: 4px solid #409EFF; |
| | | |
| | | .remark-label { |
| | | font-size: 13px; |
| | | color: #606266; |
| | | font-weight: 500; |
| | | margin-bottom: 5px; |
| | | } |
| | | |
| | | .remark-content { |
| | | font-size: 14px; |
| | | color: #303133; |
| | | line-height: 1.6; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .process-section { |
| | | .section-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | margin-bottom: 15px; |
| | | padding-bottom: 10px; |
| | | border-bottom: 2px solid #409EFF; |
| | | } |
| | | |
| | | .process-timeline { |
| | | ::v-deep .el-timeline-item { |
| | | padding-bottom: 20px; |
| | | |
| | | .el-timeline-item__timestamp { |
| | | font-size: 13px; |
| | | color: #909399; |
| | | } |
| | | } |
| | | |
| | | .process-item { |
| | | .process-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 10px; |
| | | |
| | | .process-user { |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | color: #409EFF; |
| | | } |
| | | } |
| | | |
| | | .process-content { |
| | | .process-depts { |
| | | margin-bottom: 8px; |
| | | |
| | | .label { |
| | | font-size: 13px; |
| | | color: #606266; |
| | | margin-right: 5px; |
| | | } |
| | | |
| | | .dept-tag { |
| | | margin-right: 5px; |
| | | margin-bottom: 5px; |
| | | } |
| | | } |
| | | |
| | | .process-remark { |
| | | margin-bottom: 8px; |
| | | |
| | | .label { |
| | | font-size: 13px; |
| | | color: #606266; |
| | | margin-right: 5px; |
| | | } |
| | | |
| | | .content { |
| | | font-size: 13px; |
| | | color: #303133; |
| | | line-height: 1.5; |
| | | } |
| | | } |
| | | |
| | | .process-attachments { |
| | | .label { |
| | | font-size: 13px; |
| | | color: #606266; |
| | | margin-right: 5px; |
| | | } |
| | | |
| | | ::v-deep .el-button { |
| | | margin-right: 8px; |
| | | margin-bottom: 5px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .no-record { |
| | | text-align: center; |
| | | padding: 40px 0; |
| | | color: #909399; |
| | | font-style: italic; |
| | | background: #f8f9fa; |
| | | border-radius: 6px; |
| | | } |
| | | } |
| | | |
| | | .dialog-footer { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | align-items: center; |
| | | gap: 10px; |
| | | } |
| | | } |
| | | </style> |