| | |
| | | <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> |