|
|
@@ -0,0 +1,1301 @@
|
|
|
+<template>
|
|
|
+ <div>
|
|
|
+ <el-dialog
|
|
|
+ class="process-dialog"
|
|
|
+ :close-on-click-modal="false"
|
|
|
+ :show-close="false"
|
|
|
+ top="5vh"
|
|
|
+ :visible="visible"
|
|
|
+ width="900px"
|
|
|
+ @close="handleClose">
|
|
|
+ <!-- 头部标题区域 -->
|
|
|
+ <div slot="title" class="dialog-header">
|
|
|
+ <div class="header-left">
|
|
|
+ <div class="header-icon">{{ data.eventNo ? data.eventNo.charAt(0) : 'E' }}</div>
|
|
|
+ <span class="header-title">{{ data.eventNo }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="header-actions">
|
|
|
+ <template v-if="readOnly">
|
|
|
+ <el-button size="small" @click="handleClose">关闭</el-button>
|
|
|
+ </template>
|
|
|
+ <template v-else-if="isReceiveMode">
|
|
|
+ <el-button size="small" @click="handleClose">取消</el-button>
|
|
|
+ <el-button :loading="submitLoading" size="small" type="primary" @click="handleReceive">确认接收</el-button>
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <el-button v-if="data.eventStatus === '10'" size="small" type="primary" @click="handleReceive">
|
|
|
+ 接收
|
|
|
+ </el-button>
|
|
|
+ <template v-else-if="data.eventStatus === '20' || data.eventStatus === '30'">
|
|
|
+ <el-button size="small" type="danger" @click="handleComplete">关闭</el-button>
|
|
|
+ <el-button size="small" type="warning" @click="handleSuspend">挂起</el-button>
|
|
|
+ <el-button size="small" type="info" @click="handleTransferDev">转开发</el-button>
|
|
|
+ </template>
|
|
|
+ <template v-else-if="data.eventStatus === '40'">
|
|
|
+ <el-button size="small" type="danger" @click="handleComplete">关闭</el-button>
|
|
|
+ <el-button size="small" type="warning" @click="handleSuspend">挂起</el-button>
|
|
|
+ </template>
|
|
|
+ <template v-else-if="data.eventStatus === '70'">
|
|
|
+ <el-button size="small" type="success" @click="handleResume">转处理</el-button>
|
|
|
+ </template>
|
|
|
+ <el-button size="small" @click="handleClose">取消</el-button>
|
|
|
+ </template>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 事件标题 -->
|
|
|
+ <div class="event-main-title">{{ data.eventTitle }}</div>
|
|
|
+
|
|
|
+ <!-- 信息卡片区域 -->
|
|
|
+ <div class="info-cards">
|
|
|
+ <div class="info-card">
|
|
|
+ <div class="card-icon blue">
|
|
|
+ <i class="el-icon-user" />
|
|
|
+ </div>
|
|
|
+ <div class="card-content">
|
|
|
+ <div class="card-value">{{ data.opsUserName || '-' }}</div>
|
|
|
+ <div class="card-label">运维人员</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="info-card">
|
|
|
+ <div class="card-icon orange">
|
|
|
+ <i class="el-icon-s-promotion" />
|
|
|
+ </div>
|
|
|
+ <div class="card-content">
|
|
|
+ <div class="card-value">{{ getStatusLabel(data.eventStatus) }}</div>
|
|
|
+ <div class="card-label">当前状态</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="info-card">
|
|
|
+ <div class="card-icon red">
|
|
|
+ <i class="el-icon-warning" />
|
|
|
+ </div>
|
|
|
+ <div class="card-content">
|
|
|
+ <div class="card-value">{{ data.priorityLevel }}</div>
|
|
|
+ <div class="card-label">优先级</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="info-card info-card-large">
|
|
|
+ <div class="card-icon green">
|
|
|
+ <i class="el-icon-office-building" />
|
|
|
+ </div>
|
|
|
+ <div class="card-content">
|
|
|
+ <div class="card-value">{{ data.custName }}</div>
|
|
|
+ <div class="card-label">客户名称</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 主内容区 -->
|
|
|
+ <div class="dialog-body">
|
|
|
+ <!-- 左侧描述区域 -->
|
|
|
+ <div class="left-panel">
|
|
|
+ <div class="section-title">描述</div>
|
|
|
+
|
|
|
+ <!-- 只读模式显示事件描述 -->
|
|
|
+ <div class="event-desc-wrapper">
|
|
|
+ <div class="event-desc" v-html="data.eventDesc || '暂无描述'"></div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 属性区域 - 平铺显示 -->
|
|
|
+ <div class="property-section">
|
|
|
+ <div class="section-title">属性信息</div>
|
|
|
+ <div class="property-grid">
|
|
|
+ <div class="property-item">
|
|
|
+ <span class="property-label">负责人</span>
|
|
|
+ <span class="property-value">{{ data.opsUserName || '-' }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="property-item">
|
|
|
+ <span class="property-label">事件类型</span>
|
|
|
+ <span class="property-value">{{ getEventTypeLabel(data.eventType) }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="property-item">
|
|
|
+ <span class="property-label">优先级</span>
|
|
|
+ <span class="property-value">{{ data.priorityLevel }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="property-item">
|
|
|
+ <span class="property-label">合同编号</span>
|
|
|
+ <span class="property-value">{{ data.eventNo }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="property-item">
|
|
|
+ <span class="property-label">反馈人</span>
|
|
|
+ <span class="property-value">{{ data.feedbackReporter || '-' }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="property-item">
|
|
|
+ <span class="property-label">反馈时间</span>
|
|
|
+ <span class="property-value">{{ formatTime(data.feedbackDate) }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 右侧动态区域 -->
|
|
|
+ <div class="right-panel">
|
|
|
+ <div class="panel-header">
|
|
|
+ <span class="panel-title">动态</span>
|
|
|
+ </div>
|
|
|
+ <el-tabs v-model="activeTab">
|
|
|
+ <el-tab-pane label="过程记录" name="record">
|
|
|
+ <div class="record-container">
|
|
|
+ <div class="record-list">
|
|
|
+ <div v-if="recordList.length === 0" class="empty-record">暂无过程记录</div>
|
|
|
+ <div v-for="(record, index) in recordList" :key="index" class="record-item">
|
|
|
+ <div class="record-avatar">{{ getFirstChar(record.handleUserName) }}</div>
|
|
|
+ <div class="record-user">{{ record.handleUserName }}</div>
|
|
|
+ <div class="record-content-box">
|
|
|
+ <div class="record-content" v-html="record.handleContent"></div>
|
|
|
+ </div>
|
|
|
+ <div class="record-time">{{ formatTime(record.handleDate) }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 快速登记功能 -->
|
|
|
+ <div v-if="!readOnly" class="quick-record-section">
|
|
|
+ <div v-if="!showQuickInput" class="quick-record-trigger" @click="showQuickInput = true">
|
|
|
+ <span class="placeholder">记录一下...</span>
|
|
|
+ <i class="el-icon-paperclip" @click.stop="openFileUpload" />
|
|
|
+ </div>
|
|
|
+ <div v-else class="quick-record-editor">
|
|
|
+ <div style="border: 1px solid #dcdfe6; border-radius: 4px">
|
|
|
+ <Toolbar
|
|
|
+ :default-config="quickToolbarConfig"
|
|
|
+ :editor="quickEditor"
|
|
|
+ :mode="mode"
|
|
|
+ style="border-bottom: 1px solid #dcdfe6" />
|
|
|
+ <Editor
|
|
|
+ v-model="quickRecordContent"
|
|
|
+ :default-config="quickEditorConfig"
|
|
|
+ :mode="mode"
|
|
|
+ style="height: 120px; overflow-y: auto"
|
|
|
+ @onCreated="onQuickEditorCreated" />
|
|
|
+ </div>
|
|
|
+ <div class="quick-record-actions">
|
|
|
+ <el-button size="small" @click="cancelQuickRecord">取消</el-button>
|
|
|
+ <el-button :loading="submitLoading" size="small" type="primary" @click="submitQuickRecord">
|
|
|
+ 发送
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-tab-pane>
|
|
|
+ <el-tab-pane label="文件" name="file">
|
|
|
+ <div class="file-list">
|
|
|
+ <div v-if="attachmentList.length === 0" class="empty-file">暂无文件</div>
|
|
|
+ <div v-for="(file, index) in attachmentList" :key="index" class="file-item">
|
|
|
+ <i class="el-icon-document" />
|
|
|
+ <span class="file-name">{{ file.fileName }}</span>
|
|
|
+ <el-button size="mini" type="text" @click="downloadFile(file)">下载</el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-tab-pane>
|
|
|
+ </el-tabs>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <el-dialog
|
|
|
+ append-to-body
|
|
|
+ :close-on-click-modal="false"
|
|
|
+ title="关闭事件"
|
|
|
+ :visible.sync="closeDialogVisible"
|
|
|
+ width="450px">
|
|
|
+ <el-form label-width="80px">
|
|
|
+ <el-form-item label="解决状态">
|
|
|
+ <el-select v-model="closeForm.handleResult" style="width: 100%">
|
|
|
+ <el-option v-for="item in handleResultOptions" :key="item.value" :label="item.label" :value="item.value" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="关闭原因">
|
|
|
+ <el-input
|
|
|
+ v-model="closeForm.handleContent"
|
|
|
+ maxlength="500"
|
|
|
+ placeholder="请输入关闭原因"
|
|
|
+ :rows="4"
|
|
|
+ type="textarea" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <div slot="footer">
|
|
|
+ <el-button @click="closeDialogVisible = false">取消</el-button>
|
|
|
+ <el-button :loading="submitLoading" type="primary" @click="submitClose">确定</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+ import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
|
|
|
+ import operationEventApi from '@/api/operation/operationEvent'
|
|
|
+ import { parseTime } from '@/utils'
|
|
|
+
|
|
|
+ export default {
|
|
|
+ name: 'OperationDetail',
|
|
|
+ components: { Editor, Toolbar },
|
|
|
+ props: {
|
|
|
+ visible: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false,
|
|
|
+ },
|
|
|
+ data: {
|
|
|
+ type: Object,
|
|
|
+ default: () => ({}),
|
|
|
+ },
|
|
|
+ mode: {
|
|
|
+ type: String,
|
|
|
+ default: 'view',
|
|
|
+ },
|
|
|
+ action: {
|
|
|
+ type: String,
|
|
|
+ default: '',
|
|
|
+ },
|
|
|
+ readOnly: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ editor: null,
|
|
|
+ toolbarConfig: {
|
|
|
+ toolbarKeys: [
|
|
|
+ 'bold',
|
|
|
+ 'italic',
|
|
|
+ 'underline',
|
|
|
+ 'through',
|
|
|
+ '|',
|
|
|
+ 'color',
|
|
|
+ 'bgColor',
|
|
|
+ '|',
|
|
|
+ 'bulletedList',
|
|
|
+ 'numberedList',
|
|
|
+ '|',
|
|
|
+ 'uploadImage',
|
|
|
+ '|',
|
|
|
+ 'undo',
|
|
|
+ 'redo',
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ editorConfig: {
|
|
|
+ placeholder: '请输入处理描述...',
|
|
|
+ MENU_CONF: {
|
|
|
+ uploadImage: {
|
|
|
+ customUpload: this.handleImageUpload,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ isEditing: false,
|
|
|
+ isReceiveMode: false,
|
|
|
+ isProcessMode: false,
|
|
|
+ showProperty: false,
|
|
|
+ activeTab: 'record',
|
|
|
+ submitLoading: false,
|
|
|
+ recordList: [],
|
|
|
+ attachmentList: [],
|
|
|
+ editForm: {
|
|
|
+ handleContent: '',
|
|
|
+ handleResult: '10',
|
|
|
+ },
|
|
|
+ // 快速登记相关数据
|
|
|
+ showQuickInput: false,
|
|
|
+ quickEditor: null,
|
|
|
+ quickRecordContent: '',
|
|
|
+ quickToolbarConfig: {
|
|
|
+ toolbarKeys: ['uploadImage', '|', 'bold', 'italic', 'underline', '|', 'bulletedList', 'numberedList'],
|
|
|
+ },
|
|
|
+ quickEditorConfig: {
|
|
|
+ placeholder: '记录一下...',
|
|
|
+ MENU_CONF: {
|
|
|
+ uploadImage: {
|
|
|
+ customUpload: this.handleQuickImageUpload,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ closeDialogVisible: false,
|
|
|
+ closeForm: {
|
|
|
+ handleResult: '10',
|
|
|
+ handleContent: '',
|
|
|
+ },
|
|
|
+ handleResultOptions: [
|
|
|
+ { value: '10', label: '已解决' },
|
|
|
+ { value: '20', label: '部分解决' },
|
|
|
+ { value: '30', label: '未解决' },
|
|
|
+ ],
|
|
|
+ detailAction: '',
|
|
|
+ }
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ visible(val) {
|
|
|
+ if (val) {
|
|
|
+ this.initDialog()
|
|
|
+ this.fetchRecordList()
|
|
|
+ this.fetchAttachmentList()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ mode: {
|
|
|
+ immediate: true,
|
|
|
+ handler(val) {
|
|
|
+ if (val === 'receive') {
|
|
|
+ this.isReceiveMode = true
|
|
|
+ this.isProcessMode = false
|
|
|
+ this.isEditing = false
|
|
|
+ } else if (val === 'process') {
|
|
|
+ this.isReceiveMode = false
|
|
|
+ this.isProcessMode = true
|
|
|
+ this.isEditing = true
|
|
|
+ this.editForm.handleContent = ''
|
|
|
+ } else {
|
|
|
+ this.isReceiveMode = false
|
|
|
+ this.isProcessMode = false
|
|
|
+ this.isEditing = false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ beforeDestroy() {
|
|
|
+ if (this.editor) {
|
|
|
+ this.editor.destroy()
|
|
|
+ this.editor = null
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ onEditorCreated(editor) {
|
|
|
+ this.editor = editor
|
|
|
+ },
|
|
|
+ handleImageUpload(file, insertFn) {
|
|
|
+ const reader = new FileReader()
|
|
|
+ reader.readAsDataURL(file)
|
|
|
+ reader.onload = () => {
|
|
|
+ insertFn(reader.result, file.name, reader.result)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ initDialog() {
|
|
|
+ this.showProperty = false
|
|
|
+ this.activeTab = 'record'
|
|
|
+ this.detailAction = this.action || ''
|
|
|
+ if (this.mode === 'receive') {
|
|
|
+ this.isReceiveMode = true
|
|
|
+ this.isProcessMode = false
|
|
|
+ this.isEditing = false
|
|
|
+ } else if (this.mode === 'process') {
|
|
|
+ this.isReceiveMode = false
|
|
|
+ this.isProcessMode = true
|
|
|
+ this.isEditing = true
|
|
|
+ this.editForm.handleContent = ''
|
|
|
+ } else {
|
|
|
+ this.isReceiveMode = false
|
|
|
+ this.isProcessMode = false
|
|
|
+ this.isEditing = false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ startReceive() {
|
|
|
+ this.isReceiveMode = true
|
|
|
+ this.isProcessMode = false
|
|
|
+ this.isEditing = false
|
|
|
+ },
|
|
|
+ startAction(action) {
|
|
|
+ this.isReceiveMode = false
|
|
|
+ this.isProcessMode = true
|
|
|
+ this.isEditing = true
|
|
|
+ this.editForm.handleContent = ''
|
|
|
+ this.detailAction = action
|
|
|
+ },
|
|
|
+ startProcess() {
|
|
|
+ this.isReceiveMode = false
|
|
|
+ this.isProcessMode = true
|
|
|
+ this.isEditing = true
|
|
|
+ this.editForm.handleContent = ''
|
|
|
+ },
|
|
|
+ async fetchRecordList() {
|
|
|
+ if (!this.data.id) return
|
|
|
+ try {
|
|
|
+ const res = await operationEventApi.getRecordList({ eventId: this.data.id })
|
|
|
+ if (res.code === 200) {
|
|
|
+ this.recordList = res.data.list || []
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('获取过程记录失败:', error)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async fetchAttachmentList() {
|
|
|
+ if (!this.data.id) return
|
|
|
+ try {
|
|
|
+ const res = await operationEventApi.getAttachmentList({ eventId: this.data.id })
|
|
|
+ if (res.code === 200) {
|
|
|
+ this.attachmentList = res.data || []
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('获取附件列表失败:', error)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async handleReceive() {
|
|
|
+ this.submitLoading = true
|
|
|
+ try {
|
|
|
+ const res = await operationEventApi.assignOpsUser({
|
|
|
+ id: this.data.id,
|
|
|
+ })
|
|
|
+ if (res.code === 200) {
|
|
|
+ this.$message.success('接收成功')
|
|
|
+ this.$emit('refresh')
|
|
|
+ this.handleClose()
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('接收失败:', error)
|
|
|
+ } finally {
|
|
|
+ this.submitLoading = false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async handleSaveProcess() {
|
|
|
+ if (!this.editForm.handleContent.trim()) {
|
|
|
+ this.$message.warning('请输入处理描述')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ this.submitLoading = true
|
|
|
+ try {
|
|
|
+ const res = await operationEventApi.addRecord({
|
|
|
+ eventId: this.data.id,
|
|
|
+ handleContent: this.editForm.handleContent,
|
|
|
+ handleResult: this.editForm.handleResult,
|
|
|
+ })
|
|
|
+
|
|
|
+ if (res.code === 200) {
|
|
|
+ this.$message.success('处理记录保存成功')
|
|
|
+ this.fetchRecordList()
|
|
|
+ this.isProcessMode = false
|
|
|
+ this.isEditing = false
|
|
|
+ this.$emit('refresh')
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('保存处理记录失败:', error)
|
|
|
+ } finally {
|
|
|
+ this.submitLoading = false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ downloadFile(file) {
|
|
|
+ window.open(file.fileUrl, '_blank')
|
|
|
+ },
|
|
|
+ handleClose() {
|
|
|
+ this.isReceiveMode = false
|
|
|
+ this.isProcessMode = false
|
|
|
+ this.isEditing = false
|
|
|
+ this.editForm.handleContent = ''
|
|
|
+ if (this.editor) {
|
|
|
+ this.editor.clear()
|
|
|
+ }
|
|
|
+ this.$emit('update:visible', false)
|
|
|
+ },
|
|
|
+ getStatusLabel(status) {
|
|
|
+ const map = {
|
|
|
+ 10: '待处理',
|
|
|
+ 20: '处理中(重点)',
|
|
|
+ 30: '处理中(普通)',
|
|
|
+ 40: '转研发',
|
|
|
+ 70: '挂起',
|
|
|
+ 80: '已关闭',
|
|
|
+ }
|
|
|
+ return map[status] || status
|
|
|
+ },
|
|
|
+ getEventTypeLabel(type) {
|
|
|
+ const map = {
|
|
|
+ 10: '操作咨询',
|
|
|
+ 20: '数据处理',
|
|
|
+ 30: '系统BUG',
|
|
|
+ 40: '功能调整',
|
|
|
+ 50: '二开需求',
|
|
|
+ 90: '其他问题',
|
|
|
+ }
|
|
|
+ return map[type] || type
|
|
|
+ },
|
|
|
+ formatTime(time) {
|
|
|
+ return time ? parseTime(time, '{y}-{m}-{d} {h}:{i}') : '-'
|
|
|
+ },
|
|
|
+ // 状态变更处理方法
|
|
|
+ async handleComplete() {
|
|
|
+ this.closeForm.handleResult = '10'
|
|
|
+ this.closeForm.handleContent = ''
|
|
|
+ this.closeDialogVisible = true
|
|
|
+ },
|
|
|
+ async submitClose() {
|
|
|
+ if (!this.closeForm.handleContent.trim()) {
|
|
|
+ this.$message.warning('请输入关闭原因')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.submitLoading = true
|
|
|
+ try {
|
|
|
+ const res = await operationEventApi.updateStatus({
|
|
|
+ id: this.data.id,
|
|
|
+ eventStatus: '80',
|
|
|
+ handleContent: this.closeForm.handleContent.trim(),
|
|
|
+ handleResult: this.closeForm.handleResult,
|
|
|
+ })
|
|
|
+ if (res.code === 200) {
|
|
|
+ this.$message.success('事件已关闭')
|
|
|
+ this.closeDialogVisible = false
|
|
|
+ this.isProcessMode = false
|
|
|
+ this.isEditing = false
|
|
|
+ this.$emit('refresh')
|
|
|
+ this.handleClose()
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('关闭事件失败:', error)
|
|
|
+ } finally {
|
|
|
+ this.submitLoading = false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async handleSuspend() {
|
|
|
+ this.$prompt('请填写挂起原因', '挂起事件', {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ inputType: 'textarea',
|
|
|
+ inputPlaceholder: '请输入挂起原因',
|
|
|
+ inputValidator: (value) => {
|
|
|
+ if (!value || !value.trim()) {
|
|
|
+ return '挂起原因不能为空'
|
|
|
+ }
|
|
|
+ return true
|
|
|
+ },
|
|
|
+ })
|
|
|
+ .then(async ({ value }) => {
|
|
|
+ this.submitLoading = true
|
|
|
+ try {
|
|
|
+ const res = await operationEventApi.updateStatus({
|
|
|
+ id: this.data.id,
|
|
|
+ eventStatus: '70',
|
|
|
+ handleContent: value.trim(),
|
|
|
+ })
|
|
|
+ if (res.code === 200) {
|
|
|
+ this.$message.success('事件已挂起')
|
|
|
+ this.isProcessMode = false
|
|
|
+ this.isEditing = false
|
|
|
+ this.$emit('refresh')
|
|
|
+ this.handleClose()
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('挂起事件失败:', error)
|
|
|
+ } finally {
|
|
|
+ this.submitLoading = false
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .catch(() => {})
|
|
|
+ },
|
|
|
+ async handleTransferDev() {
|
|
|
+ this.$prompt('请填写转研发原因', '转研发处理', {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ inputType: 'textarea',
|
|
|
+ inputPlaceholder: '请输入转研发原因',
|
|
|
+ inputValidator: (value) => {
|
|
|
+ if (!value || !value.trim()) {
|
|
|
+ return '转研发原因不能为空'
|
|
|
+ }
|
|
|
+ return true
|
|
|
+ },
|
|
|
+ })
|
|
|
+ .then(async ({ value }) => {
|
|
|
+ this.submitLoading = true
|
|
|
+ try {
|
|
|
+ const res = await operationEventApi.updateStatus({
|
|
|
+ id: this.data.id,
|
|
|
+ eventStatus: '40',
|
|
|
+ handleContent: value.trim(),
|
|
|
+ })
|
|
|
+ if (res.code === 200) {
|
|
|
+ this.$message.success('事件已转研发')
|
|
|
+ this.isProcessMode = false
|
|
|
+ this.isEditing = false
|
|
|
+ this.$emit('refresh')
|
|
|
+ this.handleClose()
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('转研发失败:', error)
|
|
|
+ } finally {
|
|
|
+ this.submitLoading = false
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .catch(() => {})
|
|
|
+ },
|
|
|
+ async handleResume() {
|
|
|
+ this.$prompt('请填写转处理说明', '转处理', {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ inputType: 'textarea',
|
|
|
+ inputPlaceholder: '请输入转处理说明',
|
|
|
+ inputValidator: (value) => {
|
|
|
+ if (!value || !value.trim()) return '请填写转处理说明'
|
|
|
+ return true
|
|
|
+ },
|
|
|
+ })
|
|
|
+ .then(async ({ value }) => {
|
|
|
+ this.submitLoading = true
|
|
|
+ try {
|
|
|
+ const res = await operationEventApi.updateStatus({
|
|
|
+ id: this.data.id,
|
|
|
+ operateType: '25',
|
|
|
+ handleContent: value,
|
|
|
+ })
|
|
|
+ if (res.code === 200) {
|
|
|
+ this.$message.success('事件已转回处理中')
|
|
|
+ this.isProcessMode = false
|
|
|
+ this.isEditing = false
|
|
|
+ this.$emit('refresh')
|
|
|
+ this.handleClose()
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('转处理失败:', error)
|
|
|
+ } finally {
|
|
|
+ this.submitLoading = false
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .catch(() => {})
|
|
|
+ },
|
|
|
+ // 快速登记相关方法
|
|
|
+ onQuickEditorCreated(editor) {
|
|
|
+ this.quickEditor = editor
|
|
|
+ },
|
|
|
+ handleQuickImageUpload(file, insertFn) {
|
|
|
+ const reader = new FileReader()
|
|
|
+ reader.readAsDataURL(file)
|
|
|
+ reader.onload = () => {
|
|
|
+ insertFn(reader.result, file.name, reader.result)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ openFileUpload() {
|
|
|
+ this.$message.info('文件上传功能开发中...')
|
|
|
+ },
|
|
|
+ cancelQuickRecord() {
|
|
|
+ this.showQuickInput = false
|
|
|
+ this.quickRecordContent = ''
|
|
|
+ if (this.quickEditor) {
|
|
|
+ this.quickEditor.clear()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async submitQuickRecord() {
|
|
|
+ if (!this.quickRecordContent.trim()) {
|
|
|
+ this.$message.warning('请输入记录内容')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ this.submitLoading = true
|
|
|
+ try {
|
|
|
+ const res = await operationEventApi.addRecord({
|
|
|
+ eventId: this.data.id,
|
|
|
+ handleContent: this.quickRecordContent,
|
|
|
+ handleResult: '30',
|
|
|
+ })
|
|
|
+
|
|
|
+ if (res.code === 200) {
|
|
|
+ this.$message.success('记录提交成功')
|
|
|
+ this.fetchRecordList()
|
|
|
+ this.showQuickInput = false
|
|
|
+ this.quickRecordContent = ''
|
|
|
+ if (this.quickEditor) {
|
|
|
+ this.quickEditor.clear()
|
|
|
+ }
|
|
|
+ this.$emit('refresh')
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('提交记录失败:', error)
|
|
|
+ } finally {
|
|
|
+ this.submitLoading = false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ getFirstChar(name) {
|
|
|
+ if (!name) return '?'
|
|
|
+ return name.charAt(0)
|
|
|
+ },
|
|
|
+ },
|
|
|
+ }
|
|
|
+</script>
|
|
|
+
|
|
|
+<style src="@wangeditor/editor/dist/css/style.css"></style>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+ .process-dialog {
|
|
|
+ ::v-deep .el-dialog {
|
|
|
+ margin-top: 5vh !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ ::v-deep .el-dialog__body {
|
|
|
+ padding: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ ::v-deep .el-dialog__header {
|
|
|
+ padding: 20px 20px 10px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .dialog-header {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ width: 100%;
|
|
|
+
|
|
|
+ .header-left {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .header-icon {
|
|
|
+ width: 24px;
|
|
|
+ height: 24px;
|
|
|
+ border-radius: 50%;
|
|
|
+ background: #409eff;
|
|
|
+ color: #fff;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ font-size: 12px;
|
|
|
+ font-weight: bold;
|
|
|
+ }
|
|
|
+
|
|
|
+ .header-title {
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #303133;
|
|
|
+ }
|
|
|
+
|
|
|
+ .header-actions {
|
|
|
+ display: flex;
|
|
|
+ gap: 8px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .event-main-title {
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #303133;
|
|
|
+ padding: 8px 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .info-cards {
|
|
|
+ display: flex;
|
|
|
+ gap: 16px;
|
|
|
+ padding: 16px 20px;
|
|
|
+ border-bottom: 1px solid #ebeef5;
|
|
|
+
|
|
|
+ .info-card {
|
|
|
+ flex: 1;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 10px;
|
|
|
+
|
|
|
+ &.info-card-large {
|
|
|
+ flex: 2;
|
|
|
+
|
|
|
+ .card-value {
|
|
|
+ max-width: none !important;
|
|
|
+ white-space: normal !important;
|
|
|
+ word-break: break-all !important;
|
|
|
+ overflow: visible !important;
|
|
|
+ text-overflow: clip !important;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .card-icon {
|
|
|
+ width: 40px;
|
|
|
+ height: 40px;
|
|
|
+ border-radius: 50%;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ color: #fff;
|
|
|
+ font-size: 18px;
|
|
|
+
|
|
|
+ &.blue {
|
|
|
+ background: #409eff;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.orange {
|
|
|
+ background: #e6a23c;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.red {
|
|
|
+ background: #f56c6c;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.green {
|
|
|
+ background: #67c23a;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .card-content {
|
|
|
+ .card-value {
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #303133;
|
|
|
+ max-width: 120px;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ white-space: nowrap;
|
|
|
+ }
|
|
|
+
|
|
|
+ .card-label {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #909399;
|
|
|
+ margin-top: 2px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .dialog-body {
|
|
|
+ display: flex;
|
|
|
+ height: calc(90vh - 200px);
|
|
|
+ max-height: calc(90vh - 200px);
|
|
|
+
|
|
|
+ .left-panel {
|
|
|
+ flex: 1;
|
|
|
+ padding: 16px 20px;
|
|
|
+ overflow-y: auto;
|
|
|
+ border-right: 1px solid #ebeef5;
|
|
|
+
|
|
|
+ .section-title {
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #606266;
|
|
|
+ margin-bottom: 12px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .event-desc-wrapper {
|
|
|
+ height: 240px;
|
|
|
+ background: #f5f7fa;
|
|
|
+ border-radius: 4px;
|
|
|
+ margin-bottom: 12px;
|
|
|
+ overflow-y: auto;
|
|
|
+ padding: 12px;
|
|
|
+
|
|
|
+ /* 自定义滚动条样式 */
|
|
|
+ &::-webkit-scrollbar {
|
|
|
+ width: 6px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &::-webkit-scrollbar-track {
|
|
|
+ background: transparent;
|
|
|
+ }
|
|
|
+
|
|
|
+ &::-webkit-scrollbar-thumb {
|
|
|
+ background: #c0c4cc;
|
|
|
+ border-radius: 3px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &::-webkit-scrollbar-thumb:hover {
|
|
|
+ background: #909399;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .event-desc {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #606266;
|
|
|
+ line-height: 1.8;
|
|
|
+ word-wrap: break-word;
|
|
|
+ word-break: break-all;
|
|
|
+
|
|
|
+ ::v-deep img {
|
|
|
+ max-width: 100%;
|
|
|
+ height: auto;
|
|
|
+ border-radius: 4px;
|
|
|
+ margin: 12px 0;
|
|
|
+ display: block;
|
|
|
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
|
+ }
|
|
|
+
|
|
|
+ ::v-deep p {
|
|
|
+ margin: 8px 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ ::v-deep ul,
|
|
|
+ ::v-deep ol {
|
|
|
+ margin: 8px 0;
|
|
|
+ padding-left: 24px;
|
|
|
+ }
|
|
|
+
|
|
|
+ ::v-deep li {
|
|
|
+ margin: 4px 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .property-section {
|
|
|
+ margin-top: 16px;
|
|
|
+
|
|
|
+ .section-title {
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #606266;
|
|
|
+ margin-bottom: 12px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .property-grid {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: repeat(2, 1fr);
|
|
|
+ gap: 12px 20px;
|
|
|
+
|
|
|
+ .property-item {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+
|
|
|
+ .property-label {
|
|
|
+ width: 70px;
|
|
|
+ font-size: 13px;
|
|
|
+ color: #909399;
|
|
|
+ flex-shrink: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .property-value {
|
|
|
+ flex: 1;
|
|
|
+ font-size: 13px;
|
|
|
+ color: #303133;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ white-space: nowrap;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .right-panel {
|
|
|
+ width: 300px;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ overflow: hidden;
|
|
|
+
|
|
|
+ .panel-header {
|
|
|
+ padding: 12px 16px;
|
|
|
+ border-bottom: 1px solid #ebeef5;
|
|
|
+ flex-shrink: 0;
|
|
|
+
|
|
|
+ .panel-title {
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #303133;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ::v-deep .el-tabs {
|
|
|
+ flex: 1;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ overflow: hidden;
|
|
|
+ min-height: 0;
|
|
|
+
|
|
|
+ .el-tabs__header {
|
|
|
+ margin: 0;
|
|
|
+ padding: 0 16px;
|
|
|
+ flex-shrink: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-tabs__content {
|
|
|
+ flex: 1;
|
|
|
+ overflow: hidden;
|
|
|
+ overflow: hidden;
|
|
|
+ min-height: 0;
|
|
|
+ padding: 12px 16px 4px;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ min-height: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-tab-pane {
|
|
|
+ flex: 1;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ overflow: hidden;
|
|
|
+ min-height: 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .record-container {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ flex: 1;
|
|
|
+ overflow: hidden;
|
|
|
+ min-height: 0;
|
|
|
+
|
|
|
+ .record-list {
|
|
|
+ flex: 1;
|
|
|
+ overflow-y: auto;
|
|
|
+ min-height: 0;
|
|
|
+ position: relative;
|
|
|
+ padding-left: 40px;
|
|
|
+
|
|
|
+ &::before {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ left: 15px;
|
|
|
+ top: 0;
|
|
|
+ bottom: 0;
|
|
|
+ width: 2px;
|
|
|
+ border-left: 2px dashed #dcdfe6;
|
|
|
+ }
|
|
|
+
|
|
|
+ .empty-record {
|
|
|
+ text-align: center;
|
|
|
+ color: #909399;
|
|
|
+ font-size: 13px;
|
|
|
+ padding: 20px 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .record-item {
|
|
|
+ position: relative;
|
|
|
+ padding: 12px 0;
|
|
|
+
|
|
|
+ &:first-child {
|
|
|
+ padding-top: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .record-avatar {
|
|
|
+ position: absolute;
|
|
|
+ left: -33px;
|
|
|
+ top: 0;
|
|
|
+ width: 28px;
|
|
|
+ height: 28px;
|
|
|
+ border-radius: 50%;
|
|
|
+ background: #67c23a;
|
|
|
+ color: #fff;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ font-size: 12px;
|
|
|
+ font-weight: 500;
|
|
|
+ z-index: 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ .record-user {
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #303133;
|
|
|
+ margin-bottom: 8px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .record-content-box {
|
|
|
+ background: #f5f7fa;
|
|
|
+ border-radius: 8px;
|
|
|
+ padding: 12px;
|
|
|
+ border: 1px solid #e4e7ed;
|
|
|
+
|
|
|
+ .record-content {
|
|
|
+ font-size: 13px;
|
|
|
+ color: #606266;
|
|
|
+ line-height: 1.6;
|
|
|
+
|
|
|
+ ::v-deep img {
|
|
|
+ max-width: 100%;
|
|
|
+ height: auto;
|
|
|
+ border-radius: 4px;
|
|
|
+ margin: 4px 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .file-attachment {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8px;
|
|
|
+ margin-top: 8px;
|
|
|
+ padding: 8px;
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 4px;
|
|
|
+
|
|
|
+ i {
|
|
|
+ font-size: 20px;
|
|
|
+ color: #909399;
|
|
|
+ }
|
|
|
+
|
|
|
+ .file-name {
|
|
|
+ flex: 1;
|
|
|
+ font-size: 13px;
|
|
|
+ color: #606266;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ white-space: nowrap;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .record-time {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #909399;
|
|
|
+ margin-top: 8px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .empty-record {
|
|
|
+ text-align: center;
|
|
|
+ color: #909399;
|
|
|
+ font-size: 13px;
|
|
|
+ padding: 20px 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .record-item {
|
|
|
+ position: relative;
|
|
|
+ padding: 12px 0;
|
|
|
+
|
|
|
+ &:first-child {
|
|
|
+ padding-top: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .record-avatar {
|
|
|
+ position: absolute;
|
|
|
+ left: -33px;
|
|
|
+ top: 0;
|
|
|
+ width: 28px;
|
|
|
+ height: 28px;
|
|
|
+ border-radius: 50%;
|
|
|
+ background: #67c23a;
|
|
|
+ color: #fff;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ font-size: 12px;
|
|
|
+ font-weight: 500;
|
|
|
+ z-index: 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ .record-user {
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #303133;
|
|
|
+ margin-bottom: 8px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .record-content-box {
|
|
|
+ background: #f5f7fa;
|
|
|
+ border-radius: 8px;
|
|
|
+ padding: 12px;
|
|
|
+ border: 1px solid #e4e7ed;
|
|
|
+
|
|
|
+ .record-content {
|
|
|
+ font-size: 13px;
|
|
|
+ color: #606266;
|
|
|
+ line-height: 1.6;
|
|
|
+
|
|
|
+ ::v-deep img {
|
|
|
+ max-width: 100%;
|
|
|
+ height: auto;
|
|
|
+ border-radius: 4px;
|
|
|
+ margin: 4px 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .file-attachment {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8px;
|
|
|
+ margin-top: 8px;
|
|
|
+ padding: 8px;
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 4px;
|
|
|
+
|
|
|
+ i {
|
|
|
+ font-size: 20px;
|
|
|
+ color: #909399;
|
|
|
+ }
|
|
|
+
|
|
|
+ .file-name {
|
|
|
+ flex: 1;
|
|
|
+ font-size: 13px;
|
|
|
+ color: #606266;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ white-space: nowrap;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .record-time {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #909399;
|
|
|
+ margin-top: 8px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 快速登记样式
|
|
|
+ .quick-record-section {
|
|
|
+ margin-top: 8px;
|
|
|
+ padding-top: 8px;
|
|
|
+ border-top: 1px solid #ebeef5;
|
|
|
+ flex-shrink: 0;
|
|
|
+ background: #fff;
|
|
|
+ position: relative;
|
|
|
+ z-index: 1;
|
|
|
+
|
|
|
+ .quick-record-trigger {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ padding: 10px 12px;
|
|
|
+ background: #f5f7fa;
|
|
|
+ border-radius: 4px;
|
|
|
+ cursor: pointer;
|
|
|
+ transition: all 0.3s;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ background: #e4e7ed;
|
|
|
+ }
|
|
|
+
|
|
|
+ .placeholder {
|
|
|
+ font-size: 13px;
|
|
|
+ color: #909399;
|
|
|
+ }
|
|
|
+
|
|
|
+ i {
|
|
|
+ font-size: 16px;
|
|
|
+ color: #606266;
|
|
|
+ cursor: pointer;
|
|
|
+ padding: 4px;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ color: #409eff;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .quick-record-editor {
|
|
|
+ .quick-record-actions {
|
|
|
+ display: flex;
|
|
|
+ justify-content: flex-end;
|
|
|
+ gap: 8px;
|
|
|
+ margin-top: 8px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .file-list {
|
|
|
+ .empty-file {
|
|
|
+ text-align: center;
|
|
|
+ color: #909399;
|
|
|
+ font-size: 13px;
|
|
|
+ padding: 20px 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .file-item {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8px;
|
|
|
+ padding: 10px 0;
|
|
|
+ border-bottom: 1px solid #f0f0f0;
|
|
|
+
|
|
|
+ &:last-child {
|
|
|
+ border-bottom: none;
|
|
|
+ }
|
|
|
+
|
|
|
+ i {
|
|
|
+ font-size: 18px;
|
|
|
+ color: #909399;
|
|
|
+ }
|
|
|
+
|
|
|
+ .file-name {
|
|
|
+ flex: 1;
|
|
|
+ font-size: 13px;
|
|
|
+ color: #606266;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ white-space: nowrap;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+</style>
|