已删除4个文件
已修改62个文件
已添加22个文件
| | |
| | | { |
| | | "name": "ruoyi", |
| | | "version": "3.8.5", |
| | | "description": "æ¯å®äººæ°å»é¢æºæ
§é访平å°", |
| | | "description": "丽水人æ°å»é¢æºæ
§é访平å°", |
| | | "author": "ææ°", |
| | | "license": "MIT", |
| | | "scripts": { |
| | |
| | | "dayjs": "^1.11.7", |
| | | "echarts": "^5.4.2", |
| | | "element-ui": "^2.15.4", |
| | | "exceljs": "^4.4.0", |
| | | "file-saver": "^2.0.5", |
| | | "fuse.js": "6.4.3", |
| | | "highlight.js": "9.18.5", |
| | |
| | | "vue-count-to": "1.0.13", |
| | | "vue-cropper": "0.5.5", |
| | | "vue-meta": "2.4.0", |
| | | "vue-print-nb": "^1.7.5", |
| | | "vue-quill-editor": "^3.0.6", |
| | | "vue-router": "3.4.9", |
| | | "vuedraggable": "^2.24.3", |
| | | "vuex": "3.6.0", |
| | | "xlsx": "^0.18.5" |
| | | "xlsx": "^0.18.5", |
| | | "xlsx-js-style": "^1.2.0" |
| | | }, |
| | | "devDependencies": { |
| | | "@vue/cli-plugin-babel": "4.4.6", |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <!DOCTYPE html> |
| | | <html> |
| | | <head> |
| | | <meta charset="utf-8" /> |
| | | <title>SIPçµè¯Demo</title> |
| | | <meta http-equiv="Pragma" content="no-cache"> |
| | | <meta http-equiv="Expires" content="-1"> |
| | | <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> |
| | | <meta http-equiv="cache-control" content="no-store"> |
| | | <meta http-equiv="X-UA-Compatible" content="IE=edge" /> |
| | | <script language="javascript" type="text/javascript" src="./jssip-3.10.0.js"></script> |
| | | </head> |
| | | <body style="background-color:darkgray;"> |
| | | |
| | | |
| | | |
| | | <table border="1" cellspacing="0" bordercolor="gray" style="width:auto;"> |
| | | <tr> |
| | | <td style="text-align:center;width:120px;"> |
| | | <span> æå¡å¨å°å:</span> |
| | | </td> |
| | | <td style="text-align: center; width: 250px;"> |
| | | <input id="tbServer" type="text" style="width:200px;text-align:left;" value="192.168.1.96" /> |
| | | </td> |
| | | </tr> |
| | | <tr> |
| | | <td style="text-align:center;width:120px;"> |
| | | <span> åæºå·:</span> |
| | | </td> |
| | | <td style="text-align: center; width: 250px;"> |
| | | <input id="tbExtension" type="text" style="width:200px;text-align:left;" value="8005" /> |
| | | </td> |
| | | </tr> |
| | | <tr> |
| | | <td style="text-align:center;width:120px;"> |
| | | <span> å¯ç :</span> |
| | | </td> |
| | | <td style="text-align: center; width: 250px;"> |
| | | <input id="tbPassword" type="text" style="width:200px;text-align:left;" value="8005" /> |
| | | </td> |
| | | </tr> |
| | | <tr> |
| | | <td style="text-align:center;width:120px;" colspan="2"> |
| | | <button onclick="f_register()">注å</button> |
| | | </td> |
| | | </tr> |
| | | <tr> |
| | | <td style="text-align:center;width:120px;"> |
| | | <span> å¼å«å·ç :</span> |
| | | </td> |
| | | <td style="text-align: center; width: 250px;"> |
| | | <input id="tbPhoneNo" type="text" style="width:200px;text-align:left;" value="013958077789" /> |
| | | </td> |
| | | </tr> |
| | | <tr> |
| | | <td style="text-align:center;width:120px;" colspan="2"> |
| | | <button onclick="f_makecall()">è½¯å¤æ¨</button> |
| | | <button onclick="f_hangup()">ææ</button> |
| | | </td> |
| | | </tr> |
| | | </table> |
| | | |
| | | |
| | | <script type="text/javascript"> |
| | | var cur_session = undefined; |
| | | var ua = null; |
| | | |
| | | String.prototype.Right = function (i) { |
| | | return this.slice(this.length - i, this.length); |
| | | }; |
| | | Date.prototype.Format = function (fmt) { //author: meizz |
| | | var o = { |
| | | "M+": this.getMonth() + 1, //æä»½ |
| | | "d+": this.getDate(), //æ¥ |
| | | "h+": this.getHours(), //å°æ¶ |
| | | "m+": this.getMinutes(), //å |
| | | "s+": this.getSeconds(), //ç§ |
| | | "q+": Math.floor((this.getMonth() + 3) / 3), //å£åº¦ |
| | | "S": ('00' + this.getMilliseconds()).Right(3) //æ¯«ç§ |
| | | }; |
| | | if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length)); |
| | | for (var k in o) |
| | | if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); |
| | | return fmt; |
| | | }; |
| | | |
| | | function logger_info(message, ...optionalParams) { |
| | | console.log("[" + new Date().Format("yyyy-MM-dd hh:mm:ss.S") + "]" + message, optionalParams); |
| | | } |
| | | |
| | | function f_register() { |
| | | |
| | | var server = document.getElementById('tbServer').value; |
| | | var username = document.getElementById('tbExtension').value; |
| | | var passwd = document.getElementById('tbPassword').value; |
| | | |
| | | var uristr = 'sip:' + username; |
| | | if (uristr.indexOf('@') < 1) |
| | | uristr = uristr + '@' + server; |
| | | // |
| | | logger_info(`å¼å§æ³¨åå°æå¡å¨:${server},åæºå·:${username}...`); |
| | | var socket = new JsSIP.WebSocketInterface('wss://' + server +':7443'); |
| | | var configuration = { |
| | | sockets: [socket], |
| | | uri: uristr, |
| | | password: passwd, |
| | | display_name: username, |
| | | iceServers: [ |
| | | { urls: '' } |
| | | ] |
| | | }; |
| | | |
| | | ua = new JsSIP.UA(configuration); |
| | | |
| | | ua.on('registered', function (e) { logger_info("注åæåã", e); }); |
| | | ua.on('unregistered', function (e) { logger_info('åæ¶æ³¨åã', e); }); |
| | | ua.on('registrationFailed', function (e) { logger_info('注å失败çã', e); }); |
| | | ua.on('newRTCSession', function (e) { |
| | | logger_info('newRTCSession', e); |
| | | // |
| | | cur_session = e.session; |
| | | cur_session.on("accepted", function (e) { logger_info("å¼å«å·²æ¥éã", e); }); |
| | | cur_session.on("ended", function (e) { logger_info("å¼å«ç»æã", e); }); |
| | | |
| | | cur_session.oniceconnectionstatechange = function () { |
| | | if (cur_session.connection.iceConnectionState === 'completed') { |
| | | // è·åæ¬å°SDP |
| | | const localSdp = cur_session.connection.localDescription; |
| | | |
| | | // ä¿®æ¹SDPï¼è¿é以修æ¹é³é¢ç¼è§£ç å¨ä¼å
级为ä¾ï¼ |
| | | const sdp = localSdp.sdp; |
| | | const modifiedSdp = sdp.replace(/m=audio (\d+) RTP\/AVP (\d+) (.*)/g, (match, port, payloadTypes, formats) => { |
| | | // å设æä»¬æ³å°PCMUç¼è§£ç å¨çä¼å
级æé« |
| | | const preferredPayloadType = '0'; // PCMUçpayload type |
| | | const preferredFormat = formats.split(' ').find(format => format.startsWith(preferredPayloadType)); |
| | | if (preferredFormat) { |
| | | const newFormats = formats.split(' ').filter(format => format !== preferredFormat).concat(preferredFormat); |
| | | return `m=audio ${port} RTP/AVP ${newFormats.join(' ')}`; |
| | | } |
| | | return match; |
| | | }); |
| | | |
| | | // å建æ°çRTCSessionDescription对象 |
| | | const newDescription = new RTCSessionDescription({ |
| | | type: localSdp.type, |
| | | sdp: modifiedSdp |
| | | }); |
| | | |
| | | // 设置修æ¹åçSDP |
| | | cur_session.connection.setLocalDescription(newDescription).catch(error => { |
| | | logger_info('Failed to set local description:', error); |
| | | }); |
| | | } |
| | | } |
| | | // |
| | | if (e.originator == "remote") |
| | | e.session.answer(); |
| | | }); |
| | | ua.start(); |
| | | } |
| | | |
| | | function f_hangup() { |
| | | if (cur_session != undefined) { |
| | | cur_session.terminate(); |
| | | cur_session = undefined; |
| | | } |
| | | } |
| | | |
| | | function f_makecall() { |
| | | if (ua == undefined) |
| | | return; |
| | | // |
| | | var eventHandlers = { |
| | | 'progress': function (e) { |
| | | logger_info('call is in progress', e); |
| | | }, |
| | | 'failed': function (e) { |
| | | logger_info('call failed with cause: ', e); |
| | | }, |
| | | 'ended': function (e) { |
| | | logger_info('å¼å«ç»æï¼ææºåå : ', e); |
| | | }, |
| | | 'confirmed': function (e) { |
| | | logger_info('call confirmed', e); |
| | | } |
| | | }; |
| | | |
| | | var options = { |
| | | 'eventHandlers': eventHandlers, |
| | | 'mediaConstraints': { 'audio': true, 'video': false }, |
| | | sessionTimersExpires: 1800 |
| | | }; |
| | | |
| | | var server = document.getElementById('tbServer').value; |
| | | var phone = document.getElementById('tbPhoneNo').value; |
| | | logger_info("å¼å§å¼å«å·ç ï¼", phone); |
| | | cur_session = ua.call('sip:' + phone + '@' + server, options); |
| | | |
| | | } |
| | | |
| | | </script> |
| | | </body> |
| | | </html> |
| | |
| | | <router-view /> |
| | | <theme-picker /> |
| | | <!-- <Assistant v-if="routertf" /> --> |
| | | <Assistant |
| | | v-if="Assvite" |
| | | :initial-position="{ x: 50, y: 200 }" |
| | | :auto-hide="false" |
| | | :hide-delay="3000" |
| | | primary-color="#1890ff" |
| | | /> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | name: "App", |
| | | components: { |
| | | ThemePicker, |
| | | Assistant: () => import("./components/Assistant"), //弿¥ç»ä»¶å è½½æ¹å¼ |
| | | Assistant: () => import("./components/Assistant"), |
| | | }, |
| | | data() { |
| | | return { |
| | | routers: window.location.href, |
| | | routertf: true, |
| | | Assvite: true, |
| | | }; |
| | | }, |
| | | created() { |
| | | var startIndex = this.routers.indexOf("param5=") + "param5=".length; // æ¾å°ç¬¬ä¸ä¸ªå符çä½ç½® |
| | | this.routertf = JSON.parse(this.routers.substring(startIndex)); // æªåä» 'param5=' ä¹åçå
容 |
| | | // åå§å夿 |
| | | this.checkAndUpdateAssvite(); |
| | | }, |
| | | watch: { |
| | | // çå¬è·¯ç±åå |
| | | '$route'(to, from) { |
| | | this.checkAndUpdateAssvite(); |
| | | } |
| | | }, |
| | | methods: { |
| | | checkAndUpdateAssvite() { |
| | | const isLoginPage = window.location.pathname.includes("/login"); |
| | | this.Assvite = !isLoginPage; |
| | | console.log('å½åè·¯ç±:', this.$route.path, 'æ¯å¦ç»å½é¡µ:', isLoginPage, 'æ¾ç¤ºæ¬æµ®ç:', this.Assvite); |
| | | } |
| | | }, |
| | | metaInfo() { |
| | | return { |
| | |
| | | import request from "@/utils/request"; |
| | | |
| | | |
| | | // æ¥è¯¢é¨è¯çç
人次åäººæ° |
| | | export function getEChartsPatMedOuthospCount(data) { |
| | | return request({ |
| | |
| | | return request({ |
| | | url: "/smartor/organization/list", |
| | | method: "get", |
| | | params: data, |
| | | }); |
| | | } |
| | | // åéçä¿¡ |
| | |
| | | return request({ |
| | | url: "/sms/send", |
| | | method: "post", |
| | | data: data |
| | | data: data, |
| | | }); |
| | | } |
| | | // åéçä¿¡ |
| | | export function getCurrentUserServiceSubtaskCount(data) { |
| | | return request({ |
| | | url: "/smartor/serviceSubtask/getCurrentUserServiceSubtaskCount", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | |
| | | // data: data, |
| | | }); |
| | | } |
| | | |
| | | export function getTaskFollowupList(data) { |
| | | return request({ |
| | | url: "/smartor/ivrTaskTemplate/list", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | // æ°å¢é访模æ¿åç±»æ |
| | | export function addFollowupclassify(data) { |
| | | return request({ |
| | |
| | | data: data, |
| | | }); |
| | | } |
| | | // æ¥è¯¢é®å·æ¨¡æ¿å表 |
| | | export function taskgetQtemplateobj(data) { |
| | | return request({ |
| | | url: "smartor/svytemplateTask/selectInfoByCondition", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | // é®å·æ¨¡æ¿å表 |
| | | export function getQtemplatelist(data) { |
| | | return request({ |
| | |
| | | data: data, |
| | | }); |
| | | } |
| | | // 廿¤ä¿åæ°æ® |
| | | export function savequestiondetail(data) { |
| | | return request({ |
| | | url: "/smartor/subtaskAnswer/savequestiondetail", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | |
| | | data: data, |
| | | }); |
| | | } |
| | | // è¯ææ¥è¯¢å岿å¡å表 |
| | | export function historservelist(data) { |
| | | return request({ |
| | | url: "/smartor/serviceSubtask/getSubtaskByDiagname", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | // å¿«æ·æ¥è¯¢ä»»å¡å表 |
| | | export function buidegetTasklist(data) { |
| | | return request({ |
| | |
| | | method: "get", |
| | | }); |
| | | } |
| | | // è·åè¯é³ä»»å¡æ¨¡æ¿è¯¦æ
|
| | | export function selectInfoByCondition(data) { |
| | | return request({ |
| | | url: "/smartor/ivrTaskTemplate/selectInfoByCondition", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | // 任塿¨¡æ¿æ°å¢ä¿®æ¹ |
| | | export function TaskTemplatecomit(data) { |
| | | return request({ |
| | |
| | | }, |
| | | }); |
| | | } |
| | | // æ¥è¯¢å¤é¨æ£è
表 |
| | | // æ´æ°åçº§å· |
| | | export function CallsetState(data) { |
| | | return request({ |
| | | url: "/smartor/ServiceTelInfo/setState", |
| | |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | // æ¥è¯¢é®é¢ç»è®¡ |
| | | export function compileissuestatistics(data) { |
| | | return request({ |
| | | url: "/smartor/svytemplatescript/countPatByScript", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | // æ°å¢é®å·é®é¢åç±» |
| | | export function addissueclassify(data) { |
| | |
| | | import request from "@/utils/request"; |
| | | |
| | | // ç»å½æ¹æ³ |
| | | export function login(username, password, code, orgid) { |
| | | export function login(username, password, code, orgid,campusid) { |
| | | const data = { |
| | | username, |
| | | password, |
| | | code, |
| | | orgid, |
| | | campusid, |
| | | }; |
| | | return request({ |
| | | url: "/login", |
| | |
| | | data: query |
| | | }) |
| | | } |
| | | // æ¥è¯¢å¾
å
¥é¢è®°å½å表 |
| | | export function listPatMedInhosp(query) { |
| | | return request({ |
| | | url: '/smartor/patinhosp/selectPatMedInhospList', |
| | | method: 'post', |
| | | data: query |
| | | }) |
| | | } |
| | | |
| | | // æ¥è¯¢æ£è
é¨è¯è®°å½è¯¦ç» |
| | | export function getPatouthosp(id) { |
| | |
| | | data: data, |
| | | }); |
| | | } |
| | | // 满æåº¦æç»æ¥è¯¢ |
| | | export function getSfStatisticsJoydetails(data) { |
| | | // 满æåº¦ç»è®¡ |
| | | export function getSfStatisticsJoy(data) { |
| | | return request({ |
| | | url: "/smartor/serviceSubtask/getSfStatisticsJoydetails", |
| | | url: "/smartor/serviceSubtask/getSfStatisticsCount", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | }// 满æåº¦ç»è®¡ |
| | | export function getSfStatisticsJoy(data) { |
| | | } |
| | | // 满æåº¦ç»è®¡è¯¦æ
|
| | | export function getSfStatisticsJoyInfo(data) { |
| | | return request({ |
| | | url: "/smartor/serviceSubtask/getSfStatisticsJoy", |
| | | url: "/smartor/serviceSubtask/getSfStatisticsCountDetails", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | |
| | | } |
| | | |
| | | // ä»»å¡é访çç»è®¡è¡¨çä¸é»æç» |
| | | // sendstate = 2 å¾
é访 5 å¾
é访失败 |
| | | // sendstate = 2 å¾
é访 5 å¾
é访失败 |
| | | // preachform = ä»»å¡å½¢å¼(1,人工 2,纸质 3,çµè¯ 4,çä¿¡ 5.微信å
¬ä¼å· 6.微信å°ç¨åº 7.æ¯ä»å®å°ç¨åº 8.æºè½æºå¨äºº 9.éé) |
| | | export function querySubtaskList(data) { |
| | | return request({ |
| | |
| | | data: data, |
| | | }); |
| | | } |
| | | // çç«å德满æåº¦ç»è®¡é¡µé¢ç®æç» |
| | | export function statistics(data) { |
| | | return request({ |
| | | url: "/smartor/satisfaction/statistics", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | // çç«å德满æåº¦ç»è®¡é¡µé¢ç®æç» |
| | | export function satisfactionGraph(data) { |
| | | return request({ |
| | | url: "/smartor/satisfaction/satisfactionGraph", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | |
| | | ></el-col> |
| | | <el-col :span="12" |
| | | ><el-form-item label="å¼å¸¸æé"> |
| | | <el-radio-group v-model="radio"> |
| | | <el-radio :label="3">æ¯</el-radio> |
| | | <el-radio :label="6">å¦</el-radio> |
| | | </el-radio-group> |
| | | <el-select v-model="item.isabnormal" placeholder="è¯·éæ©ç¶æ"> |
| | | <el-option :value="0" label="æ£å¸¸" :style="{ color: '#67C23A' }"> |
| | | <span style="color: #67c23a">â æ£å¸¸</span> |
| | | </el-option> |
| | | |
| | | <el-option :value="2" label="è¦å" :style="{ color: '#FFBA00' }"> |
| | | <span style="color: #ffba00">â è¦å</span> |
| | | </el-option> |
| | | <el-option :value="1" label="å¼å¸¸" :style="{ color: '#f75c5c' }"> |
| | | <span style="color: #f75c5c">â å¼å¸¸</span> |
| | | </el-option> |
| | | </el-select> |
| | | </el-form-item></el-col |
| | | > |
| | | <el-col :span="12" v-if="intent" |
| | |
| | | <template> |
| | | <div |
| | | ref="floatDrag" |
| | | class="float-position" |
| | | id="float-box" |
| | | :style="{ |
| | | left: left + 'px', |
| | | top: top + 'px', |
| | | right: right + 'px !important', |
| | | zIndex: zIndex, |
| | | ref="floatBall" |
| | | class="float-ball" |
| | | :class="{ |
| | | 'float-ball-hidden': isHidden && !isHovering, |
| | | 'float-ball-expanded': isExpanded, |
| | | }" |
| | | @touchmove.prevent |
| | | @mousemove.prevent |
| | | @mousedown="mouseDown" |
| | | @mouseup="mouseUp" |
| | | :style="{ |
| | | left: position.x + 'px', |
| | | top: position.y + 'px', |
| | | '--primary-color': primaryColor, |
| | | '--hover-color': hoverColor, |
| | | }" |
| | | @mouseenter="handleMouseEnter" |
| | | @mouseleave="handleMouseLeave" |
| | | > |
| | | <div class="drag"> |
| | | <svg |
| | | t="1682058484158" |
| | | class="icon" |
| | | viewBox="0 0 1024 1024" |
| | | version="1.1" |
| | | xmlns="http://www.w3.org/2000/svg" |
| | | p-id="2023" |
| | | width="32" |
| | | height="32" |
| | | > |
| | | <path |
| | | d="M556.297 172.715a42.407 42.407 0 0 1 42.426 42.398l0.837 267.69c-0.118 1.703 0.63 2.737 1.408 2.737 0.63 0 1.29-0.699 1.506-2.284l37.74-208.953c3.732-20.672 21.844-36.166 42.162-36.166a40.074 40.074 0 0 1 7.136 0.64c23.064 4.164 38.391 27.562 34.217 50.587l-33.656 244.529c0 2.559 0.483 4.478 1.32 4.478 0.58 0 1.328-0.935 2.175-3.218l50.144-134.063c6.27-17.65 23.034-29.403 40.793-29.403A39.798 39.798 0 0 1 797.892 374c22.08 7.875 33.626 33.41 25.78 55.47l-87.904 287.191c-0.453 1.585-0.984 3.16-1.437 4.725l-0.187 0.591v0.128a187.031 187.031 0 0 1-177.847 129.1c-53.156 0-108.42-18.752-150.472-51-45.419-27.336-190.968-183.783-190.968-183.783-22.09-22.07-18.792-55.882 3.297-77.962 11.537-11.537 25.919-17.6 40.173-17.6 13.033 0 25.967 5.05 36.51 15.592l63.138 63.157c8.603 8.594 18.132 12.699 26.922 12.699a26.952 26.952 0 0 0 20.88-9.893c7.658-9.037 4.635-36.914 2.49-54.594l-31.668-260.259c-2.825-23.26 13.781-45.724 37.003-48.549a40.497 40.497 0 0 1 4.853-0.295c21.282 0 39.749 16.98 42.387 38.597l34.926 204.425c0.905 2.54 2.342 4.036 3.602 4.036s2.353-1.496 2.58-4.922l11.88-265.741a42.417 42.417 0 0 1 42.467-42.398m0-70.875a113.36 113.36 0 0 0-104.344 69.153c-0.246 0.57-0.482 1.152-0.718 1.732a111.234 111.234 0 0 0-90.022 10.976 113.597 113.597 0 0 0-32.415 29.207 115.23 115.23 0 0 0-19.067 38.489 113.843 113.843 0 0 0-3.465 44.68l21.36 175.77a120.842 120.842 0 0 0-69.3-21.863c-33.468 0-65.549 13.614-90.286 38.332-23.212 23.202-36.993 53.363-38.863 84.952a120.92 120.92 0 0 0 34.502 92.216c5.532 5.906 39.64 42.407 79.203 82.412 74.586 75.422 105.328 99.648 122.702 110.771 53.973 40.36 123.254 63.414 190.674 63.414A257.906 257.906 0 0 0 801.14 745.1c0.247-0.709 0.483-1.417 0.7-2.136l0.117-0.374a178.56 178.56 0 0 0 1.723-5.64l87.413-285.578a113.203 113.203 0 0 0 5.729-42.86 115.585 115.585 0 0 0-35.772-77.135 111.431 111.431 0 0 0-67.45-30.19l0.148-0.985a113.676 113.676 0 0 0-1.201-43.155 115.408 115.408 0 0 0-16.872-39.523 113.774 113.774 0 0 0-30.703-30.968 111.077 111.077 0 0 0-84.981-17.06 113.203 113.203 0 0 0-103.694-67.656z" |
| | | fill="#ffffff" |
| | | p-id="2024" |
| | | ></path> |
| | | </svg> |
| | | </div> |
| | | <div class="content" id="content" @click="handelFlex"> |
| | | <!-- <img src="../../../../assets/image/alarm.png" alt="" /> --> |
| | | <div class="label"> |
| | | <div v-if="flag">å±å¼</div> |
| | | <div v-else>æ¶èµ·</div> |
| | | </div> |
| | | <div class="item-container"> |
| | | <div |
| | | v-for="(item, index) in powerList" |
| | | :key="index" |
| | | @click.stop="activeHandle(index,item.url)" |
| | | <!-- 主çä½ --> |
| | | <div |
| | | class="ball-main" |
| | | :class="{ 'ball-main-expanded': isExpanded }" |
| | | @click="toggleExpand" |
| | | @mousedown="startDrag" |
| | | @touchstart="startDrag" |
| | | > |
| | | <!-- æå ç¶æå¾æ --> |
| | | <div v-if="!isExpanded" class="ball-icon"> |
| | | <svg |
| | | class="fold-icon" |
| | | viewBox="0 0 24 24" |
| | | fill="none" |
| | | stroke="currentColor" |
| | | stroke-width="2" |
| | | > |
| | | <path d="M4 6h16M4 12h16M4 18h16" /> |
| | | </svg> |
| | | </div> |
| | | |
| | | <!-- å±å¼ç¶æå
³éæé® --> |
| | | <div v-else class="close-btn" @click.stop="toggleExpand"> |
| | | <svg |
| | | class="close-icon" |
| | | viewBox="0 0 24 24" |
| | | fill="none" |
| | | stroke="currentColor" |
| | | stroke-width="2" |
| | | > |
| | | <path d="M6 18L18 6M6 6l12 12" /> |
| | | </svg> |
| | | </div> |
| | | |
| | | <!-- è§æ æç¤ºï¼ææªè¯»æ°æ¶æ¾ç¤ºï¼ --> |
| | | <div v-if="totalUnread > 0" class="ball-badge"> |
| | | {{ totalUnread > 99 ? "99+" : totalUnread }} |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- å±å¼çå
容颿¿ --> |
| | | <transition name="ball-expand"> |
| | | <div v-if="isExpanded" class="ball-content"> |
| | | <div class="content-header"> |
| | | <h3>é访工ä½å°</h3> |
| | | <div class="update-time">æ´æ°äº {{ updateTime }}</div> |
| | | </div> |
| | | |
| | | <div class="stats-grid"> |
| | | <div |
| | | :class="activeIndex == index ? 'active power-item' : 'power-item'" |
| | | v-for="(item, index) in statsItems" |
| | | :key="index" |
| | | class="stat-item" |
| | | :class="{ 'stat-item-highlight': item.highlight }" |
| | | @click="handleItemClick(item)" |
| | | > |
| | | <img :src="item.path" alt="" style="width: 26px" /> |
| | | <div class="stat-icon"> |
| | | <svg |
| | | v-if="item.icon === 'IconUsers'" |
| | | viewBox="0 0 24 24" |
| | | fill="none" |
| | | stroke="currentColor" |
| | | stroke-width="2" |
| | | > |
| | | <path |
| | | d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197m13-7.157a4 4 0 11-8 0 4 4 0 018 0z" |
| | | /> |
| | | </svg> |
| | | <svg |
| | | v-else-if="item.icon === 'IconAlertCircle'" |
| | | viewBox="0 0 24 24" |
| | | fill="none" |
| | | stroke="currentColor" |
| | | stroke-width="2" |
| | | > |
| | | <path d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /> |
| | | </svg> |
| | | <svg |
| | | v-else-if="item.icon === 'IconTask'" |
| | | viewBox="0 0 24 24" |
| | | fill="none" |
| | | stroke="currentColor" |
| | | stroke-width="2" |
| | | > |
| | | <path |
| | | d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" |
| | | /> |
| | | </svg> |
| | | </div> |
| | | <div class="stat-info"> |
| | | <div class="stat-label">{{ item.label }}</div> |
| | | <div class="stat-value">{{ item.value }}</div> |
| | | <div |
| | | v-if="item.trend" |
| | | class="stat-trend" |
| | | :class="'trend-' + item.trend.type" |
| | | > |
| | | <span class="trend-arrow">{{ item.trend.arrow }}</span> |
| | | <span class="trend-value">{{ item.trend.value }}</span> |
| | | </div> |
| | | </div> |
| | | <div v-if="item.unread > 0" class="stat-badge"> |
| | | {{ item.unread > 99 ? "99+" : item.unread }} |
| | | </div> |
| | | </div> |
| | | <div :class="activeIndex == index ? 'active-des des' : 'des'"> |
| | | {{ item.label }} |
| | | </div> |
| | | |
| | | <div class="quick-actions"> |
| | | <div |
| | | v-for="(action, index) in quickActions" |
| | | :key="index" |
| | | class="action-item" |
| | | @click="handleActionClick(action)" |
| | | > |
| | | <div class="action-icon"> |
| | | <svg |
| | | v-if="action.icon === 'IconMessageCircle'" |
| | | viewBox="0 0 24 24" |
| | | fill="none" |
| | | stroke="currentColor" |
| | | stroke-width="2" |
| | | > |
| | | <path |
| | | d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" |
| | | /> |
| | | </svg> |
| | | <svg |
| | | v-else-if="action.icon === 'IconPhone'" |
| | | viewBox="0 0 24 24" |
| | | fill="none" |
| | | stroke="currentColor" |
| | | stroke-width="2" |
| | | > |
| | | <path |
| | | d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" |
| | | /> |
| | | </svg> |
| | | </div> |
| | | <div class="action-label">{{ action.label }}</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </transition> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { getCurrentUserServiceSubtaskCount } from "@/api/AiCentre/index"; |
| | | export default { |
| | | name: "DragBall", |
| | | name: "FloatBall", |
| | | |
| | | props: { |
| | | distanceRight: { |
| | | type: Number, |
| | | default: 36, |
| | | // åå§ä½ç½® |
| | | initialPosition: { |
| | | type: Object, |
| | | default: () => ({ x: 20, y: 100 }), |
| | | }, |
| | | distanceBottom: { |
| | | type: Number, |
| | | default: 600, |
| | | }, |
| | | isScrollHidden: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | isCanDraggable: { |
| | | // æ¯å¦èªå¨éè |
| | | autoHide: { |
| | | type: Boolean, |
| | | default: true, |
| | | }, |
| | | zIndex: { |
| | | // éèå»¶è¿ï¼æ¯«ç§ï¼ |
| | | hideDelay: { |
| | | type: Number, |
| | | default: 50, |
| | | default: 2000, |
| | | }, |
| | | value: { |
| | | // 主é¢é¢è² |
| | | primaryColor: { |
| | | type: String, |
| | | default: "æ¬æµ®çï¼", |
| | | default: "#4f46e5", |
| | | }, |
| | | // æ¬åé¢è² |
| | | hoverColor: { |
| | | type: String, |
| | | default: "#4338ca", |
| | | }, |
| | | // æ°æ®æºï¼å¯ä»å¤é¨ä¼ å
¥ï¼ |
| | | statsData: { |
| | | type: Object, |
| | | default: null, |
| | | }, |
| | | }, |
| | | |
| | | data() { |
| | | return { |
| | | clientWidth: null, |
| | | clientHeight: null, |
| | | left: null, |
| | | top: null, |
| | | right: null, |
| | | timer: null, |
| | | currentTop: 0, |
| | | mousedownX: 0, |
| | | mousedownY: 0, |
| | | isExpanded: false, |
| | | isHovering: false, |
| | | isHidden: false, |
| | | isDragging: false, |
| | | position: { ...this.initialPosition }, |
| | | dragStart: { x: 0, y: 0 }, |
| | | hideTimer: null, |
| | | updateTime: "", |
| | | roles: null, |
| | | // ç»è®¡æ°æ® |
| | | statsItems: [ |
| | | { |
| | | id: "pending", |
| | | label: "å¾
é访", |
| | | value: "0", |
| | | unread: 0, |
| | | urltype: 2, |
| | | icon: "IconUsers", |
| | | url: "/followvisit/discharge", |
| | | trend: { type: "up", arrow: "", value: "" }, |
| | | highlight: true, |
| | | }, |
| | | { |
| | | id: "failed", |
| | | label: "é访失败", |
| | | value: "0", |
| | | unread: 0, |
| | | urltype: 3, |
| | | icon: "IconAlertCircle", |
| | | url: "/followvisit/discharge", |
| | | trend: { type: "down", arrow: "", value: "" }, |
| | | }, |
| | | { |
| | | id: "abnormal", |
| | | label: "ä»»å¡å¼å¸¸", |
| | | value: "0", |
| | | unread: 0, |
| | | urltype: 4, |
| | | icon: "IconAlertCircle", |
| | | url: "/followvisit/discharge", |
| | | trend: { type: "up", arrow: "", value: "" }, |
| | | }, |
| | | { |
| | | id: "myTasks", |
| | | label: "æçä»»å¡", |
| | | value: "0", |
| | | unread: 0, |
| | | urltype: 5, |
| | | icon: "IconTask", |
| | | url: "/followvisit/discharge", |
| | | trend: { type: "stable", arrow: "", value: "" }, |
| | | }, |
| | | ], |
| | | |
| | | flag: true, // æ§å¶æ¬æµ®æ¡æ¯å¦å±å¼ |
| | | box: "", // æ¬æµ®ççdom |
| | | activeIndex: 0, //é«äº®æ¾ç¤º |
| | | powerList: [ |
| | | // å¿«æ·æä½ |
| | | quickActions: [ |
| | | { |
| | | path: require("@/assets/images/huanzheliebiao.png"), |
| | | url:'/patient/patient/', |
| | | label: "æ£è
", |
| | | id: "sms", |
| | | label: "å建é®å·ä»»å¡", |
| | | icon: "IconMessageCircle", |
| | | url: "/followvisit/QuestionnaireTask?type=2&serviceType=2", |
| | | }, |
| | | { |
| | | path: require("@/assets/images/fwwu.png"), |
| | | url:'/followvisit/tasklist/', |
| | | label: "ä»»å¡", |
| | | id: "call", |
| | | label: "å建è¯é³ä»»å¡", |
| | | icon: "IconPhone", |
| | | url: "/followvisit/particty?type=1&serviceType=2", |
| | | }, |
| | | { |
| | | path: require("@/assets/images/duanxinjilu.png"), |
| | | url:'', |
| | | label: "çä¿¡", |
| | | }, |
| | | { |
| | | path: require("@/assets/images/dianhua.png"), |
| | | url:'', |
| | | label: "çµè¯", |
| | | }, |
| | | { |
| | | path: require("@/assets/images/zxlt.png"), |
| | | url:'', |
| | | label: "å¨çº¿è天", |
| | | }, |
| | | // { |
| | | // id: 'chat', |
| | | // label: 'å¨çº¿è天', |
| | | // icon: 'IconMessageCircle', |
| | | // url: '/chat' |
| | | // } |
| | | ], |
| | | }; |
| | | }, |
| | | created() { |
| | | this.clientWidth = document.documentElement.clientWidth; |
| | | this.clientHeight = document.documentElement.clientHeight; |
| | | |
| | | computed: { |
| | | totalUnread() { |
| | | return this.statsItems.reduce((sum, item) => sum + item.unread, 0); |
| | | }, |
| | | }, |
| | | |
| | | mounted() { |
| | | this.isCanDraggable && |
| | | this.$nextTick(() => { |
| | | this.floatDrag = this.$refs.floatDrag; |
| | | // è·åå
ç´ ä½ç½®å±æ§ |
| | | this.floatDragDom = this.floatDrag.getBoundingClientRect(); |
| | | // 设置åå§ä½ç½® |
| | | this.left = this.clientWidth - this.floatDragDom.width - this.distanceRight; |
| | | // this.right = 0; |
| | | this.top = |
| | | this.clientHeight - this.floatDragDom.height - this.distanceBottom; |
| | | this.initDraggable(); |
| | | }); |
| | | // this.isScrollHidden && window.addEventListener('scroll', this.handleScroll); |
| | | this.roles = this.$store.state.user.roles; |
| | | this.loadPosition(); |
| | | |
| | | if (this.autoHide) { |
| | | this.startAutoHide(); |
| | | } |
| | | |
| | | // ç¹å»å¤é¨å
³é |
| | | document.addEventListener("click", this.handleClickOutside); |
| | | |
| | | // çªå£å¤§å°ååæ¶éæ°å®ä½ |
| | | window.addEventListener("resize", this.handleResize); |
| | | |
| | | this.box = document.getElementById("float-box"); |
| | | }, |
| | | beforeUnmount() { |
| | | window.removeEventListener("scroll", this.handleScroll); |
| | | |
| | | beforeDestroy() { |
| | | document.removeEventListener("click", this.handleClickOutside); |
| | | window.removeEventListener("resize", this.handleResize); |
| | | clearTimeout(this.hideTimer); |
| | | }, |
| | | methods: { |
| | | // ä¼¸ç¼©æ¬æµ®ç |
| | | handelFlex() { |
| | | if (this.flag) { |
| | | this.buffer(this.box, "height", 600); |
| | | } else { |
| | | this.buffer(this.box, "height", 70); |
| | | } |
| | | this.flag = !this.flag; |
| | | console.log("æ¯å¦å±å¼", this.flag); |
| | | }, |
| | | // ç¹å»åªä¸ªpower |
| | | activeHandle(index,url) { |
| | | //ææä»¬èªå®ä¹ç䏿 èµå¼ |
| | | this.activeIndex = index; |
| | | this.$router.push({ |
| | | path: url, |
| | | }) |
| | | console.log("HHHH", index); |
| | | }, |
| | | // è·åè¦æ¹å徿 ·å¼å±æ§ |
| | | getStyleAttr(obj, attr) { |
| | | if (obj.currentStyle) { |
| | | // IE å opera |
| | | return obj.currentStyle[attr]; |
| | | } else { |
| | | return window.getComputedStyle(obj, null)[attr]; |
| | | } |
| | | }, |
| | | // å¨ç»å½æ° |
| | | buffer(eleObj, attr, target) { |
| | | // setIntervalæ¹å¼å¼å¯å¨ç» |
| | | //å
æ¸
å设 |
| | | // clearInterval(eleObj.timer); |
| | | // let speed = 0 |
| | | // let begin = 0 |
| | | // //è®¾ç½®å®æ¶å¨ |
| | | // eleObj.timer = setInterval(() => { |
| | | // //è·åå¨ç»å±æ§çåå§å¼ |
| | | // begin = parseInt(this.getStyleAttr(eleObj, attr)); |
| | | // speed = (target - begin) * 0.2; |
| | | // speed = target > begin ? Math.ceil(speed) : Math.floor(speed); |
| | | // eleObj.style[attr] = begin + speed + "px"; |
| | | // if (begin === target) { |
| | | // clearInterval(eleObj.timer); |
| | | // } |
| | | // }, 20); |
| | | // cancelAnimationFrameå¼å¯å¨ç» |
| | | // å
æ¸
å设 |
| | | cancelAnimationFrame(eleObj.timer); |
| | | let speed = 0; |
| | | let begin = 0; |
| | | let _this = this; |
| | | eleObj.timer = requestAnimationFrame(function fn() { |
| | | begin = parseInt(_this.getStyleAttr(eleObj, attr)); |
| | | // å¨ç»é度 |
| | | speed = (target - begin) * 0.9; |
| | | speed = target > begin ? Math.ceil(speed) : Math.floor(speed); |
| | | eleObj.style[attr] = begin + speed + "px"; |
| | | eleObj.timer = requestAnimationFrame(fn); |
| | | if (begin === target) { |
| | | cancelAnimationFrame(eleObj.timer); |
| | | } |
| | | }); |
| | | }, |
| | | /** |
| | | * çªå£resizeçå¬ |
| | | */ |
| | | handleResize() { |
| | | // this.clientWidth = document.documentElement.clientWidth; |
| | | // this.clientHeight = document.documentElement.clientHeight; |
| | | // console.log(window.innerWidth); |
| | | // console.log(document.documentElement.clientWidth); |
| | | |
| | | this.checkDraggablePosition(); |
| | | }, |
| | | /** |
| | | * åå§ådraggable |
| | | */ |
| | | initDraggable() { |
| | | this.floatDrag.addEventListener("touchstart", this.toucheStart); |
| | | this.floatDrag.addEventListener("touchmove", (e) => this.touchMove(e)); |
| | | this.floatDrag.addEventListener("touchend", this.touchEnd); |
| | | }, |
| | | mouseDown(e) { |
| | | const event = e || window.event; |
| | | this.mousedownX = event.screenX; |
| | | this.mousedownY = event.screenY; |
| | | const that = this; |
| | | let floatDragWidth = this.floatDragDom.width / 2; |
| | | let floatDragHeight = this.floatDragDom.height / 2; |
| | | if (event.preventDefault) { |
| | | event.preventDefault(); |
| | | methods: { |
| | | toggleExpand() { |
| | | this.isExpanded = !this.isExpanded; |
| | | if (this.isExpanded) { |
| | | this.isHidden = false; |
| | | clearTimeout(this.hideTimer); |
| | | this.updateStats(); |
| | | } |
| | | this.canClick = false; |
| | | this.floatDrag.style.transition = "none"; |
| | | document.onmousemove = function (e) { |
| | | var event = e || window.event; |
| | | that.left = event.clientX - floatDragWidth; |
| | | that.top = event.clientY - floatDragHeight; |
| | | if (that.left < 0) that.left = 0; |
| | | if (that.top < 0) that.top = 0; |
| | | // é¼ æ ç§»åºå¯è§åºååç»æé®è¿å |
| | | if ( |
| | | event.clientY < 0 || |
| | | event.clientY > Number(this.clientHeight) || |
| | | event.clientX > Number(this.clientWidth) || |
| | | event.clientX < 0 |
| | | ) { |
| | | this.right = 0; |
| | | this.top = |
| | | this.clientHeight - this.floatDragDom.height - this.distanceBottom; |
| | | document.onmousemove = null; |
| | | this.floatDrag.style.transition = "all 0.3s"; |
| | | return; |
| | | }, |
| | | |
| | | handleMouseEnter() { |
| | | this.isHovering = true; |
| | | if (this.autoHide) { |
| | | clearTimeout(this.hideTimer); |
| | | this.isHidden = false; |
| | | } |
| | | }, |
| | | |
| | | handleMouseLeave() { |
| | | this.isHovering = false; |
| | | if (this.autoHide && !this.isExpanded) { |
| | | this.startAutoHide(); |
| | | } |
| | | }, |
| | | |
| | | startAutoHide() { |
| | | this.hideTimer = setTimeout(() => { |
| | | if (!this.isExpanded && !this.isHovering) { |
| | | this.isHidden = true; |
| | | } |
| | | if ( |
| | | that.left >= |
| | | document.documentElement.clientWidth - floatDragWidth * 2 |
| | | ) { |
| | | that.left = document.documentElement.clientWidth - floatDragWidth * 2; |
| | | }, this.hideDelay); |
| | | }, |
| | | |
| | | startDrag(e) { |
| | | e.preventDefault(); |
| | | e.stopPropagation(); |
| | | this.isDragging = true; |
| | | |
| | | const clientX = e.type.includes("touch") |
| | | ? e.touches[0].clientX |
| | | : e.clientX; |
| | | const clientY = e.type.includes("touch") |
| | | ? e.touches[0].clientY |
| | | : e.clientY; |
| | | |
| | | this.dragStart = { |
| | | x: clientX - this.position.x, |
| | | y: clientY - this.position.y, |
| | | }; |
| | | |
| | | const onMove = (moveEvent) => { |
| | | if (!this.isDragging) return; |
| | | |
| | | const moveX = moveEvent.type.includes("touch") |
| | | ? moveEvent.touches[0].clientX |
| | | : moveEvent.clientX; |
| | | const moveY = moveEvent.type.includes("touch") |
| | | ? moveEvent.touches[0].clientY |
| | | : moveEvent.clientY; |
| | | |
| | | const newX = moveX - this.dragStart.x; |
| | | const newY = moveY - this.dragStart.y; |
| | | |
| | | // è¾¹çæ£æ¥ |
| | | const maxX = window.innerWidth - 60; |
| | | const maxY = window.innerHeight - 60; |
| | | |
| | | this.position.x = Math.max(0, Math.min(newX, maxX)); |
| | | this.position.y = Math.max(0, Math.min(newY, maxY)); |
| | | }; |
| | | |
| | | const onEnd = () => { |
| | | this.isDragging = false; |
| | | document.removeEventListener("mousemove", onMove); |
| | | document.removeEventListener("mouseup", onEnd); |
| | | document.removeEventListener("touchmove", onMove); |
| | | document.removeEventListener("touchend", onEnd); |
| | | |
| | | // 妿é è¿è¾¹ç¼ï¼èªå¨å¸é |
| | | if (this.position.x < 20) { |
| | | this.position.x = 0; |
| | | } else if (this.position.x > window.innerWidth - 80) { |
| | | this.position.x = window.innerWidth - 60; |
| | | } |
| | | if (that.top >= that.clientHeight - floatDragHeight * 2) { |
| | | that.top = that.clientHeight - floatDragHeight * 2; |
| | | |
| | | // ä¿åä½ç½®å°æ¬å°åå¨ |
| | | try { |
| | | localStorage.setItem( |
| | | "floatBallPosition", |
| | | JSON.stringify(this.position) |
| | | ); |
| | | } catch (e) { |
| | | console.error("ä¿åä½ç½®å¤±è´¥:", e); |
| | | } |
| | | }; |
| | | |
| | | document.addEventListener("mousemove", onMove); |
| | | document.addEventListener("mouseup", onEnd); |
| | | document.addEventListener("touchmove", onMove, { passive: false }); |
| | | document.addEventListener("touchend", onEnd); |
| | | }, |
| | | mouseUp(e) { |
| | | const event = e || window.event; |
| | | //å¤æåªæ¯å纯çç¹å»ï¼æ²¡æææ½ |
| | | |
| | | handleItemClick(item) { |
| | | if (item.url) { |
| | | console.log(item.url, "item.url"); |
| | | |
| | | // this.$router.push(item.url); |
| | | this.$router.replace({ |
| | | path: item.url, |
| | | query: { |
| | | errtype: item.urltype, |
| | | }, |
| | | }); |
| | | this.toggleExpand(); |
| | | } |
| | | }, |
| | | |
| | | handleActionClick(action) { |
| | | console.log(this.roles, "this.roles"); |
| | | if ( |
| | | this.mousedownY == event.screenY && |
| | | this.mousedownX == event.screenX |
| | | action.url && |
| | | (this.roles.includes("admin") || this.roles.includes("sysadmin")) |
| | | ) { |
| | | this.$emit("handlepaly"); |
| | | } |
| | | document.onmousemove = null; |
| | | this.checkDraggablePosition(); |
| | | this.floatDrag.style.transition = "all 0.3s"; |
| | | }, |
| | | toucheStart() { |
| | | this.canClick = false; |
| | | this.floatDrag.style.transition = "none"; |
| | | }, |
| | | touchMove(e) { |
| | | this.canClick = true; |
| | | if (e.targetTouches.length === 1) { |
| | | // åææå¨ |
| | | let touch = event.targetTouches[0]; |
| | | this.left = touch.clientX - this.floatDragDom.width / 2; |
| | | this.top = touch.clientY - this.floatDragDom.height / 2; |
| | | } |
| | | }, |
| | | touchEnd() { |
| | | if (!this.canClick) return; // è§£å³ç¹å»äºä»¶åtouchäºä»¶å²çªçé®é¢ |
| | | this.floatDrag.style.transition = "all 0.3s"; |
| | | this.checkDraggablePosition(); |
| | | }, |
| | | /** |
| | | * 夿å
ç´ æ¾ç¤ºä½ç½® |
| | | * å¨çªå£æ¹ååmove endæ¶è°ç¨ |
| | | */ |
| | | checkDraggablePosition() { |
| | | this.clientWidth = document.documentElement.clientWidth; |
| | | this.clientHeight = document.documentElement.clientHeight; |
| | | if (this.left + this.floatDragDom.width / 2 >= this.clientWidth / 2) { |
| | | // 夿ä½ç½®æ¯å¾å·¦å¾å³æ»å¨ |
| | | this.left = this.clientWidth - this.floatDragDom.width; |
| | | this.$router.replace(action.url); |
| | | this.toggleExpand(); |
| | | } else { |
| | | this.left = 0; |
| | | this.$modal.msgError("é管çåç¨æ·ææ åå»ºä»»å¡æé"); |
| | | } |
| | | if (this.top < 0) { |
| | | // 夿æ¯å¦è¶
åºå±å¹ä¸æ²¿ |
| | | this.top = 0; |
| | | }, |
| | | |
| | | async updateStats() { |
| | | try { |
| | | // è¿éå¯ä»¥æ¿æ¢ä¸ºå®é
ç API è°ç¨ |
| | | // const response = await this.$api.getFollowupStats() |
| | | // this.statsItems = response.data |
| | | |
| | | // æ¨¡ææ°æ®æ´æ° |
| | | const mockData = { |
| | | pending: { |
| | | value: "128", |
| | | unread: null, |
| | | trend: { type: "up", arrow: "â", value: "5" }, |
| | | }, |
| | | failed: { |
| | | value: "24", |
| | | unread: null, |
| | | trend: { type: "down", arrow: "â", value: "2" }, |
| | | }, |
| | | abnormal: { |
| | | value: "8", |
| | | unread: null, |
| | | trend: { type: "up", arrow: "â", value: "3" }, |
| | | }, |
| | | myTasks: { |
| | | value: "156", |
| | | unread: null, |
| | | trend: { type: "stable", arrow: "â", value: "0" }, |
| | | }, |
| | | }; |
| | | const response = await getCurrentUserServiceSubtaskCount(); |
| | | mockData.pending.value = response.pendingVisitCount; |
| | | mockData.failed.value = response.failedVisitCount; |
| | | mockData.abnormal.value = response.abnormalVisitCount; |
| | | mockData.myTasks.value = response.allVisitCount; |
| | | this.statsItems = this.statsItems.map((item) => { |
| | | const data = mockData[item.id] || {}; |
| | | return { |
| | | ...item, |
| | | value: data.value || item.value, |
| | | unread: data.unread || item.unread, |
| | | trend: data.trend || item.trend, |
| | | }; |
| | | }); |
| | | |
| | | // æ´æ°æ¶é´ |
| | | const now = new Date(); |
| | | this.updateTime = `${now.getHours().toString().padStart(2, "0")}:${now |
| | | .getMinutes() |
| | | .toString() |
| | | .padStart(2, "0")}`; |
| | | } catch (error) { |
| | | console.error("æ´æ°ç»è®¡æ°æ®å¤±è´¥:", error); |
| | | } |
| | | if (this.top + this.floatDragDom.height >= this.clientHeight) { |
| | | // 夿æ¯å¦è¶
åºå±å¹ä¸æ²¿ |
| | | this.top = this.clientHeight - this.floatDragDom.height; |
| | | }, |
| | | |
| | | loadPosition() { |
| | | try { |
| | | const savedPosition = localStorage.getItem("floatBallPosition"); |
| | | if (savedPosition) { |
| | | const parsed = JSON.parse(savedPosition); |
| | | this.position = parsed; |
| | | } |
| | | } catch (e) { |
| | | console.error("å è½½ä½ç½®å¤±è´¥:", e); |
| | | } |
| | | }, |
| | | |
| | | handleClickOutside(e) { |
| | | if ( |
| | | this.isExpanded && |
| | | this.$refs.floatBall && |
| | | !this.$refs.floatBall.contains(e.target) |
| | | ) { |
| | | this.toggleExpand(); |
| | | } |
| | | }, |
| | | |
| | | handleResize() { |
| | | const maxX = window.innerWidth - 60; |
| | | const maxY = window.innerHeight - 60; |
| | | |
| | | this.position.x = Math.min(this.position.x, maxX); |
| | | this.position.y = Math.min(this.position.y, maxY); |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | <style> |
| | | html, |
| | | body { |
| | | overflow: hidden; |
| | | } |
| | | </style> |
| | | <style scoped lang="scss"> |
| | | .float-position { |
| | | |
| | | <style scoped> |
| | | .float-ball { |
| | | position: fixed; |
| | | z-index: 10003 !important; |
| | | left: 0; |
| | | top: 20%; |
| | | width: 70px; |
| | | height: 70px; |
| | | border-radius: 32px; |
| | | z-index: 9999; |
| | | transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); |
| | | pointer-events: auto; |
| | | } |
| | | |
| | | .float-ball-hidden { |
| | | opacity: 0.3; |
| | | transform: translateX(10px); |
| | | } |
| | | |
| | | .float-ball-hidden:hover { |
| | | opacity: 1; |
| | | transform: translateX(0); |
| | | } |
| | | |
| | | .ball-main { |
| | | width: 60px; |
| | | height: 60px; |
| | | border-radius: 50%; |
| | | background: linear-gradient(135deg, var(--primary-color), #7c3aed); |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | cursor: move; |
| | | box-shadow: 0 4px 20px rgba(79, 70, 229, 0.3); |
| | | transition: all 0.3s ease; |
| | | position: relative; |
| | | z-index: 10000; |
| | | } |
| | | |
| | | .ball-main:hover { |
| | | background: linear-gradient(135deg, var(--hover-color), #6d28d9); |
| | | box-shadow: 0 6px 25px rgba(79, 70, 229, 0.4); |
| | | transform: scale(1.05); |
| | | } |
| | | |
| | | .ball-main-expanded { |
| | | background: linear-gradient(135deg, #6366f1, #8b5cf6); |
| | | } |
| | | |
| | | .ball-icon { |
| | | width: 24px; |
| | | height: 24px; |
| | | color: white; |
| | | } |
| | | |
| | | .fold-icon { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | |
| | | .close-btn { |
| | | width: 24px; |
| | | height: 24px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | cursor: pointer; |
| | | overflow: hidden; |
| | | user-select: none; |
| | | color: white; |
| | | transition: transform 0.2s ease; |
| | | } |
| | | |
| | | display: block; |
| | | background: black; |
| | | background: -webkit-radial-gradient(100px 100px, circle, #5788FE, #292929); |
| | | // background: -moz-radial-gradient(100px 100px, circle, #35a1a1, #000);Firefox æµè§å¨çå®ç° |
| | | // background: radial-gradient(100px 100px, circle, #35a1a1, #000);æ å HTML5 屿§ |
| | | margin: 0; |
| | | .drag { |
| | | width: 70px; |
| | | height: 35px; |
| | | // background: #f2e96a; |
| | | text-align: center; |
| | | line-height: 35px; |
| | | border-bottom: 1px solid #fff; |
| | | .close-btn:hover { |
| | | transform: rotate(90deg); |
| | | } |
| | | |
| | | .close-icon { |
| | | width: 20px; |
| | | height: 20px; |
| | | } |
| | | |
| | | .ball-badge { |
| | | position: absolute; |
| | | top: -5px; |
| | | right: -5px; |
| | | min-width: 20px; |
| | | height: 20px; |
| | | padding: 0 6px; |
| | | background: #ef4444; |
| | | color: white; |
| | | font-size: 12px; |
| | | font-weight: 600; |
| | | border-radius: 10px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | border: 2px solid white; |
| | | animation: pulse 2s infinite; |
| | | } |
| | | |
| | | @keyframes pulse { |
| | | 0%, |
| | | 100% { |
| | | transform: scale(1); |
| | | } |
| | | .content { |
| | | width: 70px; |
| | | height: 35px; |
| | | // background: #716af2; |
| | | .label { |
| | | width: 70px; |
| | | height: 35px; |
| | | text-align: center; |
| | | line-height: 35px; |
| | | color: white; |
| | | } |
| | | .label:hover { |
| | | color: rgb(19, 217, 243); |
| | | transition: all 0.5; |
| | | } |
| | | |
| | | .item-container { |
| | | margin-top: 10px; |
| | | width: 70px; |
| | | height: 500px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | flex-direction: column; |
| | | |
| | | .power-item { |
| | | width: 40px; |
| | | height: 40px; |
| | | border-radius: 50%; |
| | | background-color: #f1f7ff; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | flex-direction: column; |
| | | } |
| | | .des { |
| | | width: 40px; |
| | | text-align: center; |
| | | margin-bottom: 5px; |
| | | font-size: 10px; |
| | | color: #fff; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .close { |
| | | width: 20px; |
| | | height: 20px; |
| | | border-radius: 50%; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | color: #fff; |
| | | background: rgba(0, 0, 0, 0.6); |
| | | position: absolute; |
| | | right: -10px; |
| | | top: -12px; |
| | | cursor: pointer; |
| | | 50% { |
| | | transform: scale(1.1); |
| | | } |
| | | } |
| | | |
| | | .cart { |
| | | border-radius: 50%; |
| | | width: 5em; |
| | | height: 5em; |
| | | .ball-content { |
| | | position: absolute; |
| | | top: 70px; |
| | | left: 0; |
| | | width: 320px; |
| | | background: white; |
| | | border-radius: 16px; |
| | | box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1); |
| | | overflow: hidden; |
| | | z-index: 9999; |
| | | } |
| | | |
| | | .ball-expand-enter-active, |
| | | .ball-expand-leave-active { |
| | | transition: all 0.3s ease; |
| | | } |
| | | |
| | | .ball-expand-enter, |
| | | .ball-expand-leave-to { |
| | | opacity: 0; |
| | | transform: translateY(-10px); |
| | | } |
| | | |
| | | .content-header { |
| | | padding: 20px 20px 16px; |
| | | background: linear-gradient(135deg, var(--primary-color), #7c3aed); |
| | | color: white; |
| | | } |
| | | |
| | | .content-header h3 { |
| | | margin: 0 0 8px 0; |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | .update-time { |
| | | font-size: 12px; |
| | | opacity: 0.9; |
| | | } |
| | | |
| | | .stats-grid { |
| | | padding: 16px; |
| | | display: grid; |
| | | grid-template-columns: 1fr 1fr; |
| | | gap: 12px; |
| | | } |
| | | |
| | | .stat-item { |
| | | padding: 16px; |
| | | background: #f8fafc; |
| | | border-radius: 12px; |
| | | cursor: pointer; |
| | | transition: all 0.2s ease; |
| | | position: relative; |
| | | border: 2px solid transparent; |
| | | } |
| | | |
| | | .stat-item:hover { |
| | | background: #f1f5f9; |
| | | border-color: #e2e8f0; |
| | | transform: translateY(-2px); |
| | | } |
| | | |
| | | .stat-item-highlight { |
| | | border-color: var(--primary-color); |
| | | background: linear-gradient(to bottom right, #f0f9ff, #f8fafc); |
| | | } |
| | | |
| | | .stat-icon { |
| | | width: 32px; |
| | | height: 32px; |
| | | background: white; |
| | | border-radius: 8px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | margin-bottom: 12px; |
| | | color: var(--primary-color); |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); |
| | | } |
| | | |
| | | .stat-icon svg { |
| | | width: 18px; |
| | | height: 18px; |
| | | } |
| | | |
| | | .stat-label { |
| | | font-size: 12px; |
| | | color: #64748b; |
| | | margin-bottom: 4px; |
| | | } |
| | | |
| | | .stat-value { |
| | | font-size: 20px; |
| | | font-weight: 700; |
| | | color: #1e293b; |
| | | margin-bottom: 4px; |
| | | } |
| | | |
| | | .stat-trend { |
| | | font-size: 11px; |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 2px; |
| | | } |
| | | |
| | | .trend-up { |
| | | color: #10b981; |
| | | } |
| | | |
| | | .trend-down { |
| | | color: #ef4444; |
| | | } |
| | | |
| | | .trend-stable { |
| | | color: #64748b; |
| | | } |
| | | |
| | | .trend-arrow { |
| | | font-size: 10px; |
| | | } |
| | | |
| | | .stat-badge { |
| | | position: absolute; |
| | | top: 12px; |
| | | right: 12px; |
| | | min-width: 18px; |
| | | height: 18px; |
| | | padding: 0 4px; |
| | | background: #ef4444; |
| | | color: white; |
| | | font-size: 10px; |
| | | font-weight: 600; |
| | | border-radius: 9px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .header-notice { |
| | | display: inline-block; |
| | | transition: all 0.3s; |
| | | |
| | | span { |
| | | vertical-align: initial; |
| | | } |
| | | |
| | | .notice-badge { |
| | | color: inherit; |
| | | |
| | | .header-notice-icon { |
| | | font-size: 16px; |
| | | padding: 4px; |
| | | } |
| | | } |
| | | .quick-actions { |
| | | padding: 12px 20px 20px; |
| | | border-top: 1px solid #f1f5f9; |
| | | display: flex; |
| | | gap: 12px; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .drag-ball .drag-content { |
| | | overflow-wrap: break-word; |
| | | font-size: 14px; |
| | | color: #fff; |
| | | letter-spacing: 2px; |
| | | .action-item { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | gap: 8px; |
| | | cursor: pointer; |
| | | padding: 12px; |
| | | border-radius: 8px; |
| | | transition: all 0.2s ease; |
| | | flex: 1; |
| | | } |
| | | |
| | | .active { |
| | | background-color: #f9f1db !important; |
| | | .action-item:hover { |
| | | background: #f8fafc; |
| | | } |
| | | .active-des { |
| | | color: #71dcfa !important; |
| | | font-size: 20px !important; |
| | | font-weight: 500 !important; |
| | | |
| | | .action-icon { |
| | | width: 24px; |
| | | height: 24px; |
| | | color: var(--primary-color); |
| | | } |
| | | |
| | | .action-icon svg { |
| | | width: 20px; |
| | | height: 20px; |
| | | } |
| | | |
| | | .action-label { |
| | | font-size: 12px; |
| | | color: #475569; |
| | | font-weight: 500; |
| | | } |
| | | </style> |
| | |
| | | |
| | | <!-- å¼å«æé® --> |
| | | <button |
| | | :class="['call-btn', { calling: isCalling }]" |
| | | :class="[ |
| | | 'call-btn', |
| | | { |
| | | calling: isCalling, |
| | | registering: isRegistering, |
| | | }, |
| | | ]" |
| | | @click="startCall" |
| | | :disabled="isCalling || sipStatus !== '已注å'" |
| | | :disabled="isButtonDisabled" |
| | | > |
| | | <i v-if="isRegistering" class="el-icon-loading"></i> |
| | | {{ callButtonText }} |
| | | </button> |
| | | |
| | |
| | | const randomNum = Math.floor(Math.random() * 20) + 1000; // å®ä¹éæºåæºå· |
| | | return { |
| | | isCalling: false, |
| | | isRegistering: true, // åå§ä¸ºæ³¨åä¸ç¶æ |
| | | randomNum: randomNum, |
| | | randomID: null, |
| | | callStatus: "idle", // idle, calling, connected, ended |
| | | sipStatus: "æªè¿æ¥", |
| | | sipStatusClass: "status-disconnected", |
| | | sipConfig: { |
| | | wsUrl: "wss://192.168.10.124:7443", |
| | | // ç§»é¤ç¡¬ç¼ç çwsUrlådomain |
| | | wsUrl: "", |
| | | sipUri: "", |
| | | password: "Smartor@2023", |
| | | password: "Smartor@2023",//丽水 |
| | | // password: "heskj@1234",//å¸ä¸ |
| | | displayName: "Web å°é¾", |
| | | // realm: "9.208.5.18:8090", |
| | | }, |
| | |
| | | } |
| | | return ""; |
| | | }, |
| | | callStatusClass() { |
| | | return `status-${this.callStatus}`; |
| | | isButtonDisabled() { |
| | | return ( |
| | | this.isCalling || this.sipStatus !== "已注å" || this.isRegistering |
| | | ); |
| | | }, |
| | | callButtonText() { |
| | | if (this.isRegistering) return "注åä¸..."; |
| | | return this.isCalling ? "éè¯ä¸..." : "ä¸é®å¼å«"; |
| | | }, |
| | | callStatusClass() { |
| | | return `status-${this.callStatus}`; |
| | | }, |
| | | }, |
| | | created() { |
| | |
| | | }, |
| | | |
| | | async mounted() { |
| | | const orgName = localStorage.getItem("orgname"); |
| | | if (orgName == "æ¯å®ç²æèªæ²»å¿äººæ°å»é¢") { |
| | | return; |
| | | } |
| | | await this.CallgetList(); |
| | | this.isRegistering = true; // å¼å§æ³¨å |
| | | sipService.init(this.sipConfig); |
| | | // è®¾ç½®ç¶æåè° |
| | | sipService.onStatusChange = (status) => { |
| | | this.sipStatus = status.text; |
| | | this.sipStatusClass = `status-${status.type}`; |
| | | |
| | | // 注åæåæå¤±è´¥æ¶åæ¶å è½½ç¶æ |
| | | if (status.type === "registered" || status.type === "failed") { |
| | | this.isRegistering = false; |
| | | } |
| | | // 注åæå |
| | | if (status.type === "registered") { |
| | | this.startCallsetState(); |
| | | } |
| | | // å¤ç注å失败åæå¼è¿æ¥æ
åµ |
| | | if (status.type === "failed" || status.type === "disconnected") { |
| | | this.overCallsetState(); // éæ¾åæºå· |
| | | this.isRegistering = false; |
| | | } |
| | | }; |
| | | |
| | |
| | | // éç¥ç¶ç»ä»¶éè¯ç¶æåå |
| | | this.$emit("call-status-change", status); |
| | | }; |
| | | // æ·»å æ³¨åè¶
æ¶å¤ç |
| | | setTimeout(() => { |
| | | if (this.isRegistering && this.sipStatus !== "已注å") { |
| | | this.isRegistering = false; |
| | | this.$message.warning("SIP注åè¶
æ¶ï¼è¯·æ£æ¥ç½ç»è¿æ¥"); |
| | | } |
| | | }, 10000); // 10ç§è¶
æ¶ |
| | | }, |
| | | methods: { |
| | | async startCall() { |
| | |
| | | const res = await CallgetList(); |
| | | this.randomNum = res.data[0].tel; |
| | | this.randomID = res.data[0].id; |
| | | // æ£ç¡®è®¾ç½® sipUri |
| | | this.sipConfig.sipUri = `${this.randomNum}@192.168.10.124`; |
| | | this.startCallsetState(); |
| | | // å¨æè®¾ç½®sipUriï¼ååé¨åä¼å¨sipServiceä¸å¨æå¤ç |
| | | const orgName = localStorage.getItem("orgname"); |
| | | if (orgName == "丽水å¸ä¸å»é¢") { |
| | | this.sipConfig.sipUri = `${this.randomNum}@192.168.10.124`; |
| | | } else if (orgName == "龿³å¸äººæ°å»é¢") { |
| | | this.sipConfig.sipUri = `${this.randomNum}@10.10.0.220`; |
| | | } else if (orgName == "第ä¸äººæ°å»é¢æ¹æ»¨é¢åº"||orgName == "第ä¸äººæ°å»é¢å´å±±é¢åº") { |
| | | this.sipConfig.sipUri = `${this.randomNum}@192.169.129.198`; |
| | | } |
| | | } catch (error) { |
| | | console.error("è·ååæºå·å¤±è´¥:", error); |
| | | // this.updateStatus("failed", "è·ååæºå·å¤±è´¥"); |
| | |
| | | </el-input> </el-form-item |
| | | ></el-col> |
| | | <el-col :span="12" |
| | | ><el-form-item label="å¼å¸¸æé"> |
| | | <el-radio-group v-model="item.isabnormal"> |
| | | <el-radio :label="1">æ¯</el-radio> |
| | | <el-radio :label="0">å¦</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item></el-col |
| | | > |
| | | ><el-form-item label="å¼å¸¸æé"> |
| | | <el-select v-model="item.isabnormal" placeholder="è¯·éæ©ç¶æ"> |
| | | <el-option :value="0" label="æ£å¸¸" :style="{ color: '#67C23A' }"> |
| | | <span style="color: #67c23a">â æ£å¸¸</span> |
| | | </el-option> |
| | | |
| | | <el-option :value="2" label="è¦å" :style="{ color: '#FFBA00' }"> |
| | | <span style="color: #ffba00">â è¦å</span> |
| | | </el-option> |
| | | <el-option :value="1" label="å¼å¸¸" :style="{ color: '#f75c5c' }"> |
| | | <span style="color: #f75c5c">â å¼å¸¸</span> |
| | | </el-option> |
| | | </el-select> |
| | | </el-form-item></el-col |
| | | > |
| | | <!-- <el-col :span="12" v-if="intent" |
| | | ><el-form-item label="é项èç¹"> |
| | | <el-input |
| | |
| | | name: "OrderedCheckboxGroup", |
| | | props: { |
| | | options: { |
| | | type: Array, |
| | | default: () => [], |
| | | type: Array, |
| | | default: () => [], |
| | | validator: (value) => { |
| | | return Array.isArray(value); |
| | | } |
| | | }, |
| | | value: { |
| | | type: Array, |
| | | default: () => [], |
| | | type: Array, |
| | | default: () => [], |
| | | validator: (value) => { |
| | | // å
许空æ°ç»ï¼ä½å¦ææ¯éæ°ç»å¼åååºè¦å |
| | | if (!Array.isArray(value) && value !== null && value !== undefined) { |
| | | console.warn('value prop should be an array, received:', typeof value); |
| | | return false; |
| | | } |
| | | return true; |
| | | } |
| | | }, |
| | | initialselectedOrder: { |
| | | type: Array, |
| | |
| | | value: { |
| | | immediate: true, |
| | | handler(newVal) { |
| | | if ( |
| | | Array.isArray(newVal) && |
| | | newVal.length > 0 && |
| | | typeof newVal[0] === "object" |
| | | ) { |
| | | console.log(this.selectedOrder, "111"); |
| | | // é¦å
ç¡®ä¿newValæ¯æ°ç»ï¼å¦æä¸æ¯å转æ¢ä¸ºç©ºæ°ç» |
| | | if (!Array.isArray(newVal)) { |
| | | console.warn( |
| | | "Expected array for value prop, received:", |
| | | typeof newVal |
| | | ); |
| | | this.checkedValues = []; |
| | | this.selectedOrder = []; |
| | | return; |
| | | } |
| | | |
| | | if (newVal.length > 0 && typeof newVal[0] === "object") { |
| | | // 1. ä¼ å
¥çæ¯å¯¹è±¡æ°ç» [{ sort, preachform, compensateTime }] |
| | | this.checkedValues = newVal.map((item) => item.preachform); // æå preachform ç»æéä¸å¼æ°ç» |
| | | // æå»º selectedOrderï¼ä¼å
使ç¨ä¼ å
¥ç compensateTimeï¼å¦åç¨é»è®¤å¼ |
| | | this.checkedValues = newVal.map((item) => item.preachform); |
| | | this.selectedOrder = newVal.map((item) => ({ |
| | | value: item.preachform, |
| | | compensateTime: item.hasOwnProperty("compensateTime") |
| | |
| | | : this.defaultCompensateTime, |
| | | })); |
| | | } else { |
| | | // 2. ä¼ å
¥çæ¯å符串æ°ç» (å¦ ["1", "3", "4"]ï¼å
¼å®¹ä¹åçç¨æ³) |
| | | // 2. ä¼ å
¥çæ¯å符串æ°ç» |
| | | if (JSON.stringify(newVal) !== JSON.stringify(this.checkedValues)) { |
| | | this.checkedValues = [...newVal]; |
| | | console.log(this.selectedOrder, "222"); |
| | | console.log(this.newVal, "22"); |
| | | // æå»ºææ´æ° selectedOrderï¼ä¿çå·²æç compensateTime |
| | | |
| | | const newOrder = []; |
| | | newVal.forEach((value) => { |
| | | const existingItem = this.selectedOrder.find( |
| | |
| | | if (existingItem) { |
| | | newOrder.push(existingItem); |
| | | } else { |
| | | // ä¿®å¤hasOwnPropertyæ¹æ³è°ç¨ |
| | | const existingCompensateTime = this.hasOwnProperty(value); |
| | | newOrder.push({ |
| | | value, |
| | | compensateTime: this.hasOwnProperty(value) |
| | | ? this.hasOwnProperty(value) |
| | | : this.defaultCompensateTime, |
| | | compensateTime: |
| | | existingCompensateTime !== false |
| | | ? existingCompensateTime |
| | | : this.defaultCompensateTime, |
| | | }); |
| | | } |
| | | }); |
| | |
| | | } |
| | | } |
| | | }, |
| | | deep: true, // 建议添å deep: true 以确ä¿å¯¹è±¡æ°ç»å
çååè½è¢«æè· |
| | | deep: true, |
| | | }, |
| | | checkedValues(newVal, oldVal) { |
| | | console.log(this.selectedOrder, "333"); |
| | |
| | | } |
| | | }, |
| | | hasOwnProperty(patfrom) { |
| | | console.log(patfrom); |
| | | console.log(this.initialselectedOrder); |
| | | // 使ç¨findæ¹æ³æ¥æ¾å¹é
ç对象 |
| | | const foundObject = this.initialselectedOrder.find( |
| | | (item) => item.preachform === patfrom |
| | | ); |
| | | if (!this.initialselectedOrder || !Array.isArray(this.initialselectedOrder)) { |
| | | return false; |
| | | } |
| | | |
| | | // 妿æ¾å°å¯¹è±¡ï¼è¿åå
¶compensateTimeï¼å¦åè¿åfalse |
| | | return foundObject ? foundObject.compensateTime : false; |
| | | // 使ç¨findæ¹æ³æ¥æ¾å¹é
ç对象 |
| | | const foundObject = this.initialselectedOrder.find( |
| | | (item) => item.preachform === patfrom |
| | | ); |
| | | |
| | | // 妿æ¾å°å¯¹è±¡ï¼è¿åå
¶compensateTimeï¼å¦åè¿åfalse |
| | | return foundObject ? foundObject.compensateTime : false; |
| | | }, |
| | | // åå°ååäºä»¶ |
| | | emitChangeEvent() { |
| | |
| | | <template> |
| | | <div class="navbar"> |
| | | <hamburger id="hamburger-container" :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" /> |
| | | <hamburger |
| | | id="hamburger-container" |
| | | :is-active="sidebar.opened" |
| | | class="hamburger-container" |
| | | @toggleClick="toggleSideBar" |
| | | /> |
| | | |
| | | <breadcrumb id="breadcrumb-container" class="breadcrumb-container" v-if="!topNav"/> |
| | | <top-nav id="topmenu-container" class="topmenu-container" v-if="topNav"/> |
| | | <breadcrumb |
| | | id="breadcrumb-container" |
| | | class="breadcrumb-container" |
| | | v-if="!topNav" |
| | | /> |
| | | <top-nav id="topmenu-container" class="topmenu-container" v-if="topNav" /> |
| | | |
| | | <div class="right-menu"> |
| | | <template v-if="device!=='mobile'"> |
| | | <template v-if="device !== 'mobile'"> |
| | | <search id="header-search" class="right-menu-item" /> |
| | | |
| | | <!-- <el-tooltip content="æºç å°å" effect="dark" placement="bottom"> |
| | |
| | | <!-- <el-tooltip content="å¸å±å¤§å°" effect="dark" placement="bottom"> |
| | | <size-select id="size-select" class="right-menu-item hover-effect" /> |
| | | </el-tooltip> --> |
| | | |
| | | <span class="username">{{ username }}</span> |
| | | </template> |
| | | |
| | | <el-dropdown class="avatar-container right-menu-item hover-effect" trigger="click"> |
| | | <el-dropdown |
| | | class="avatar-container right-menu-item hover-effect" |
| | | trigger="click" |
| | | > |
| | | <div class="avatar-wrapper"> |
| | | <img :src="avatar" class="user-avatar"> |
| | | <img :src="avatar" class="user-avatar" /> |
| | | <i class="el-icon-caret-bottom" /> |
| | | </div> |
| | | <el-dropdown-menu slot="dropdown"> |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import { mapGetters } from 'vuex' |
| | | import Breadcrumb from '@/components/Breadcrumb' |
| | | import TopNav from '@/components/TopNav' |
| | | import Hamburger from '@/components/Hamburger' |
| | | import Screenfull from '@/components/Screenfull' |
| | | import SizeSelect from '@/components/SizeSelect' |
| | | import Search from '@/components/HeaderSearch' |
| | | import RuoYiGit from '@/components/RuoYi/Git' |
| | | import RuoYiDoc from '@/components/RuoYi/Doc' |
| | | import { mapGetters } from "vuex"; |
| | | import Breadcrumb from "@/components/Breadcrumb"; |
| | | import TopNav from "@/components/TopNav"; |
| | | import Hamburger from "@/components/Hamburger"; |
| | | import Screenfull from "@/components/Screenfull"; |
| | | import SizeSelect from "@/components/SizeSelect"; |
| | | import Search from "@/components/HeaderSearch"; |
| | | import RuoYiGit from "@/components/RuoYi/Git"; |
| | | import RuoYiDoc from "@/components/RuoYi/Doc"; |
| | | |
| | | export default { |
| | | components: { |
| | |
| | | SizeSelect, |
| | | Search, |
| | | RuoYiGit, |
| | | RuoYiDoc |
| | | RuoYiDoc, |
| | | }, |
| | | computed: { |
| | | ...mapGetters([ |
| | | 'sidebar', |
| | | 'avatar', |
| | | 'device' |
| | | ]), |
| | | ...mapGetters(["sidebar", "avatar", "device"]), |
| | | setting: { |
| | | get() { |
| | | return this.$store.state.settings.showSettings |
| | | return this.$store.state.settings.showSettings; |
| | | }, |
| | | set(val) { |
| | | this.$store.dispatch('settings/changeSetting', { |
| | | key: 'showSettings', |
| | | value: val |
| | | }) |
| | | } |
| | | this.$store.dispatch("settings/changeSetting", { |
| | | key: "showSettings", |
| | | value: val, |
| | | }); |
| | | }, |
| | | }, |
| | | topNav: { |
| | | get() { |
| | | return this.$store.state.settings.topNav |
| | | } |
| | | } |
| | | return this.$store.state.settings.topNav; |
| | | }, |
| | | }, |
| | | username: { |
| | | get() { |
| | | return this.$store.state.user.name; |
| | | }, |
| | | }, |
| | | }, |
| | | methods: { |
| | | toggleSideBar() { |
| | | this.$store.dispatch('app/toggleSideBar') |
| | | this.$store.dispatch("app/toggleSideBar"); |
| | | }, |
| | | async logout() { |
| | | this.$confirm('ç¡®å®æ³¨éå¹¶éåºç³»ç»åï¼', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | }).then(() => { |
| | | this.$store.dispatch('LogOut').then(() => { |
| | | location.href = '/index'; |
| | | this.$confirm("ç¡®å®æ³¨éå¹¶éåºç³»ç»åï¼", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | this.$store.dispatch("LogOut").then(() => { |
| | | location.href = "/index"; |
| | | }); |
| | | }) |
| | | }).catch(() => {}); |
| | | } |
| | | } |
| | | } |
| | | .catch(() => {}); |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | |
| | | overflow: hidden; |
| | | position: relative; |
| | | background: #fff; |
| | | box-shadow: 0 1px 4px rgba(0,21,41,.08); |
| | | box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08); |
| | | |
| | | .hamburger-container { |
| | | line-height: 46px; |
| | | height: 100%; |
| | | float: left; |
| | | cursor: pointer; |
| | | transition: background .3s; |
| | | -webkit-tap-highlight-color:transparent; |
| | | transition: background 0.3s; |
| | | -webkit-tap-highlight-color: transparent; |
| | | |
| | | &:hover { |
| | | background: rgba(0, 0, 0, .025) |
| | | background: rgba(0, 0, 0, 0.025); |
| | | } |
| | | } |
| | | |
| | | .breadcrumb-container { |
| | | float: left; |
| | | } |
| | |
| | | float: right; |
| | | height: 100%; |
| | | line-height: 50px; |
| | | display: flex; // æ°å¢ |
| | | align-items: center; // æ°å¢ï¼åç´å±
ä¸ |
| | | justify-content: center; // å¯éï¼æ°´å¹³å±
ä¸ |
| | | |
| | | &:focus { |
| | | outline: none; |
| | | } |
| | | |
| | | .right-menu-item { |
| | | display: inline-block; |
| | | display: inline-flex; // ä¿®æ¹ä¸ºinline-flex |
| | | align-items: center; // ç¡®ä¿å
容åç´å±
ä¸ |
| | | padding: 0 8px; |
| | | height: 100%; |
| | | font-size: 18px; |
| | |
| | | |
| | | &.hover-effect { |
| | | cursor: pointer; |
| | | transition: background .3s; |
| | | transition: background 0.3s; |
| | | |
| | | &:hover { |
| | | background: rgba(0, 0, 0, .025) |
| | | background: rgba(0, 0, 0, 0.025); |
| | | } |
| | | } |
| | | } |
| | | |
| | | .username { |
| | | // å é¤åæ¥ç margin-bottom: 20px; |
| | | display: flex; |
| | | align-items: center; |
| | | color: #1789fa; |
| | | height: 100%; |
| | | padding: 0 12px; |
| | | white-space: nowrap; // 鲿¢æåæ¢è¡ |
| | | } |
| | | .avatar-container { |
| | | margin-right: 30px; |
| | | |
| | | margin-top: 10px; |
| | | .avatar-wrapper { |
| | | margin-top: 5px; |
| | | position: relative; |
| | |
| | | import router from "./router"; |
| | | import directive from "./directive"; // directive |
| | | import plugins from "./plugins"; // plugins |
| | | import Print from 'vue-print-nb' |
| | | import { download } from "@/utils/request"; |
| | | //å¼å
¥quill-editorç¼è¾å¨ |
| | | import VueQuillEditor from "vue-quill-editor"; |
| | |
| | | import "quill/dist/quill.snow.css"; |
| | | import "quill/dist/quill.bubble.css"; |
| | | Vue.use(VueQuillEditor); |
| | | Vue.use(Print) |
| | | |
| | | // å¼å
¥ |
| | | import { codemirror } from "vue-codemirror"; |
| | | import "@/utils/cm-setting.js"; |
| | |
| | | Vue.filter(key, filters[key]); |
| | | } |
| | | import moment from "moment" |
| | | // 1. å¨main.js䏿·»å é误çå¬ |
| | | window.addEventListener('unhandledrejection', (event) => { |
| | | if (event.reason && event.reason.message && |
| | | event.reason.message.includes('Loading chunk')) { |
| | | // éæ°å è½½é¡µé¢ |
| | | window.location.reload(); |
| | | } |
| | | }); |
| | | |
| | | Vue.prototype.$moment = moment; |
| | | |
| | |
| | | import store from '@/store' |
| | | import store from "@/store"; |
| | | |
| | | function authPermission(permission) { |
| | | const all_permission = "*:*:*"; |
| | | const permissions = store.getters && store.getters.permissions |
| | | const permissions = store.getters && store.getters.permissions; |
| | | if (permission && permission.length > 0) { |
| | | return permissions.some(v => { |
| | | return all_permission === v || v === permission |
| | | }) |
| | | return permissions.some((v) => { |
| | | return all_permission === v || v === permission; |
| | | }); |
| | | } else { |
| | | return false |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | function authRole(role) { |
| | | const super_admin = "admin"; |
| | | const roles = store.getters && store.getters.roles |
| | | const roles = store.getters && store.getters.roles; |
| | | if (role && role.length > 0) { |
| | | return roles.some((v) => { |
| | | return super_admin === v || v === role; |
| | | }); |
| | | } else { |
| | | return false; |
| | | } |
| | | } |
| | | function authRoles(role) { |
| | | const super_admin = "admin"; |
| | | const roles = store.getters && store.getters.roles; |
| | | if (role && role.length > 0) { |
| | | return roles.some(v => { |
| | | return super_admin === v || v === role |
| | |
| | | }, |
| | | // éªè¯ç¨æ·æ¯å¦å«ææå®æéï¼åªéå
å«å
¶ä¸ä¸ä¸ª |
| | | hasPermiOr(permissions) { |
| | | return permissions.some(item => { |
| | | return authPermission(item) |
| | | }) |
| | | return permissions.some((item) => { |
| | | return authPermission(item); |
| | | }); |
| | | }, |
| | | // éªè¯ç¨æ·æ¯å¦å«ææå®æéï¼å¿
é¡»å
¨é¨æ¥æ |
| | | hasPermiAnd(permissions) { |
| | | return permissions.every(item => { |
| | | return authPermission(item) |
| | | }) |
| | | return permissions.every((item) => { |
| | | return authPermission(item); |
| | | }); |
| | | }, |
| | | // éªè¯ç¨æ·æ¯å¦å
·å¤æè§è² |
| | | hasRole(role) { |
| | |
| | | }, |
| | | // éªè¯ç¨æ·æ¯å¦å«ææå®è§è²ï¼åªéå
å«å
¶ä¸ä¸ä¸ª |
| | | hasRoleOr(roles) { |
| | | return roles.some(item => { |
| | | return authRole(item) |
| | | }) |
| | | return roles.some((item) => { |
| | | return authRoles(item); |
| | | }); |
| | | }, |
| | | // éªè¯ç¨æ·æ¯å¦å«ææå®è§è²ï¼å¿
é¡»å
¨é¨æ¥æ |
| | | hasRoleAnd(roles) { |
| | | return roles.every(item => { |
| | | return authRole(item) |
| | | }) |
| | | } |
| | | } |
| | | return roles.every((item) => { |
| | | return authRole(item); |
| | | }); |
| | | }, |
| | | }; |
| | |
| | | import Vue from 'vue' |
| | | import Router from 'vue-router' |
| | | import Vue from "vue"; |
| | | import Router from "vue-router"; |
| | | |
| | | Vue.use(Router) |
| | | Vue.use(Router); |
| | | |
| | | /* Layout */ |
| | | import Layout from '@/layout' |
| | | import Layout from "@/layout"; |
| | | |
| | | /** |
| | | * Note: è·¯ç±é
置项 |
| | |
| | | // å
Œ
±è·¯ç± |
| | | export const constantRoutes = [ |
| | | { |
| | | path: '/redirect', |
| | | path: "/redirect", |
| | | component: Layout, |
| | | hidden: true, |
| | | children: [ |
| | | { |
| | | path: '/redirect/:path(.*)', |
| | | component: () => import('@/views/redirect') |
| | | } |
| | | ] |
| | | path: "/redirect/:path(.*)", |
| | | component: () => import("@/views/redirect"), |
| | | }, |
| | | ], |
| | | }, |
| | | { |
| | | path: '/login', |
| | | component: () => import('@/views/login'), |
| | | hidden: true |
| | | }, |
| | | { |
| | | path: '/loginSSO', |
| | | component: () => import('@/views/loginSSO'), |
| | | hidden: true |
| | | path: "/login", |
| | | component: () => import("@/views/login"), |
| | | hidden: true, |
| | | }, |
| | | { |
| | | path: '/sf', |
| | | component: () => import('@/views/outsideChainnew'), |
| | | hidden: true |
| | | path: "/loginSSO", |
| | | component: () => import("@/views/loginSSO"), |
| | | hidden: true, |
| | | }, |
| | | { |
| | | path: '/wt', |
| | | component: () => import('@/views/outsideChainwtnew'), |
| | | hidden: true |
| | | path: "/sf", |
| | | component: () => import("@/views/outsideChainnew"), |
| | | hidden: true, |
| | | }, |
| | | { |
| | | path: '/xj', |
| | | component: () => import('@/views/outsideChainxjnew'), |
| | | hidden: true |
| | | path: "/wt", |
| | | component: () => import("@/views/outsideChainwtnew"), |
| | | hidden: true, |
| | | }, |
| | | { |
| | | path: '/satisfaction', |
| | | component: () => import('@/views/satisfaction'), |
| | | hidden: true |
| | | path: "/xj", |
| | | component: () => import("@/views/outsideChainxjnew"), |
| | | hidden: true, |
| | | }, |
| | | { |
| | | path: '/outsideChain', |
| | | component: () => import('@/views/outsideChain'), |
| | | hidden: true |
| | | path: "/satisfaction", |
| | | component: () => import("@/views/satisfaction"), |
| | | hidden: true, |
| | | }, |
| | | { |
| | | path: '/outsideChainwt', |
| | | component: () => import('@/views/outsideChainwt'), |
| | | hidden: true |
| | | path: "/outsideChain", |
| | | component: () => import("@/views/outsideChain"), |
| | | hidden: true, |
| | | }, |
| | | { |
| | | path: '/outsideChainxj', |
| | | component: () => import('@/views/outsideChainxj'), |
| | | hidden: true |
| | | path: "/outsideChainwt", |
| | | component: () => import("@/views/outsideChainwt"), |
| | | hidden: true, |
| | | }, |
| | | { |
| | | path: '/previews', |
| | | component: () => import('@/views/previews'), |
| | | hidden: true |
| | | path: "/outsideChainxj", |
| | | component: () => import("@/views/outsideChainxj"), |
| | | hidden: true, |
| | | }, |
| | | { |
| | | path: '/register', |
| | | component: () => import('@/views/register'), |
| | | hidden: true |
| | | path: "/previews", |
| | | component: () => import("@/views/previews"), |
| | | hidden: true, |
| | | }, |
| | | { |
| | | path: '/404', |
| | | component: () => import('@/views/error/404'), |
| | | hidden: true |
| | | path: "/register", |
| | | component: () => import("@/views/register"), |
| | | hidden: true, |
| | | }, |
| | | { |
| | | path: '/401', |
| | | component: () => import('@/views/error/401'), |
| | | hidden: true |
| | | path: "/404", |
| | | component: () => import("@/views/error/404"), |
| | | hidden: true, |
| | | }, |
| | | { |
| | | path: '', |
| | | path: "/401", |
| | | component: () => import("@/views/error/401"), |
| | | hidden: true, |
| | | }, |
| | | { |
| | | path: "", |
| | | component: Layout, |
| | | redirect: 'index', |
| | | redirect: "index", |
| | | children: [ |
| | | { |
| | | path: 'index', |
| | | component: () => import('@/views/index'), |
| | | name: 'Index', |
| | | meta: { title: 'é¦é¡µ', icon: 'dashboard', affix: true } |
| | | } |
| | | ] |
| | | path: "index", |
| | | component: () => import("@/views/index"), |
| | | name: "Index", |
| | | meta: { |
| | | title: "é¦é¡µ", |
| | | icon: "dashboard", |
| | | affix: true, |
| | | roles: ["admin", "sysadmin"], |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | { |
| | | path: '/user', |
| | | path: "/user", |
| | | component: Layout, |
| | | hidden: true, |
| | | redirect: 'noredirect', |
| | | redirect: "noredirect", |
| | | children: [ |
| | | { |
| | | path: 'profile', |
| | | component: () => import('@/views/system/user/profile/index'), |
| | | name: 'Profile', |
| | | meta: { title: '个人ä¸å¿', icon: 'user' } |
| | | } |
| | | ] |
| | | } |
| | | ] |
| | | path: "profile", |
| | | component: () => import("@/views/system/user/profile/index"), |
| | | name: "Profile", |
| | | meta: { title: "个人ä¸å¿", icon: "user" }, |
| | | }, |
| | | ], |
| | | }, |
| | | ]; |
| | | |
| | | // å¨æè·¯ç±ï¼åºäºç¨æ·æé卿å»å è½½ |
| | | export const dynamicRoutes = [ |
| | | { |
| | | path: '/system/user-auth', |
| | | path: "/system/user-auth", |
| | | component: Layout, |
| | | hidden: true, |
| | | permissions: ['system:user:edit'], |
| | | permissions: ["system:user:edit"], |
| | | children: [ |
| | | { |
| | | path: 'role/:userId(\\d+)', |
| | | component: () => import('@/views/system/user/authRole'), |
| | | name: 'AuthRole', |
| | | meta: { title: 'åé
è§è²', activeMenu: '/system/user' } |
| | | } |
| | | ] |
| | | path: "role/:userId(\\d+)", |
| | | component: () => import("@/views/system/user/authRole"), |
| | | name: "AuthRole", |
| | | meta: { title: "åé
è§è²", activeMenu: "/system/user" }, |
| | | }, |
| | | ], |
| | | }, |
| | | { |
| | | path: '/system/role-auth', |
| | | path: "/system/role-auth", |
| | | component: Layout, |
| | | hidden: true, |
| | | permissions: ['system:role:edit'], |
| | | permissions: ["system:role:edit"], |
| | | children: [ |
| | | { |
| | | path: 'user/:roleId(\\d+)', |
| | | component: () => import('@/views/system/role/authUser'), |
| | | name: 'AuthUser', |
| | | meta: { title: 'åé
ç¨æ·', activeMenu: '/system/role' } |
| | | } |
| | | ] |
| | | path: "user/:roleId(\\d+)", |
| | | component: () => import("@/views/system/role/authUser"), |
| | | name: "AuthUser", |
| | | meta: { title: "åé
ç¨æ·", activeMenu: "/system/role" }, |
| | | }, |
| | | ], |
| | | }, |
| | | { |
| | | path: '/system/dict-data', |
| | | path: "/system/dict-data", |
| | | component: Layout, |
| | | hidden: true, |
| | | permissions: ['system:dict:list'], |
| | | permissions: ["system:dict:list"], |
| | | children: [ |
| | | { |
| | | path: 'index/:dictId(\\d+)', |
| | | component: () => import('@/views/system/dict/data'), |
| | | name: 'Data', |
| | | meta: { title: 'åå
¸æ°æ®', activeMenu: '/system/dict' } |
| | | } |
| | | ] |
| | | path: "index/:dictId(\\d+)", |
| | | component: () => import("@/views/system/dict/data"), |
| | | name: "Data", |
| | | meta: { title: "åå
¸æ°æ®", activeMenu: "/system/dict" }, |
| | | }, |
| | | ], |
| | | }, |
| | | { |
| | | path: '/monitor/job-log', |
| | | path: "/monitor/job-log", |
| | | component: Layout, |
| | | hidden: true, |
| | | permissions: ['monitor:job:list'], |
| | | permissions: ["monitor:job:list"], |
| | | children: [ |
| | | { |
| | | path: 'index/:jobId(\\d+)', |
| | | component: () => import('@/views/monitor/job/log'), |
| | | name: 'JobLog', |
| | | meta: { title: 'è°åº¦æ¥å¿', activeMenu: '/monitor/job' } |
| | | } |
| | | ] |
| | | path: "index/:jobId(\\d+)", |
| | | component: () => import("@/views/monitor/job/log"), |
| | | name: "JobLog", |
| | | meta: { title: "è°åº¦æ¥å¿", activeMenu: "/monitor/job" }, |
| | | }, |
| | | ], |
| | | }, |
| | | { |
| | | path: '/tool/gen-edit', |
| | | path: "/tool/gen-edit", |
| | | component: Layout, |
| | | hidden: true, |
| | | permissions: ['tool:gen:edit'], |
| | | permissions: ["tool:gen:edit"], |
| | | children: [ |
| | | { |
| | | path: 'index/:tableId(\\d+)', |
| | | component: () => import('@/views/tool/gen/editTable'), |
| | | name: 'GenEdit', |
| | | meta: { title: 'ä¿®æ¹çæé
ç½®', activeMenu: '/tool/gen' } |
| | | } |
| | | ] |
| | | }/*, |
| | | path: "index/:tableId(\\d+)", |
| | | component: () => import("@/views/tool/gen/editTable"), |
| | | name: "GenEdit", |
| | | meta: { title: "ä¿®æ¹çæé
ç½®", activeMenu: "/tool/gen" }, |
| | | }, |
| | | ], |
| | | } /*, |
| | | { |
| | | path: '/smartor/archive', |
| | | component: Layout, |
| | |
| | | meta: { title: 'æ£è
ç»´æ¤', activeMenu: '/archive/add' } |
| | | } |
| | | ] |
| | | }*/ |
| | | ] |
| | | }*/, |
| | | ]; |
| | | |
| | | // 鲿¢è¿ç»ç¹å»å¤æ¬¡è·¯ç±æ¥é |
| | | let routerPush = Router.prototype.push; |
| | | Router.prototype.push = function push(location) { |
| | | return routerPush.call(this, location).catch(err => err) |
| | | } |
| | | return routerPush.call(this, location).catch((err) => err); |
| | | }; |
| | | |
| | | export default new Router({ |
| | | mode: 'history', // 廿urlä¸ç# |
| | | mode: "history", // 廿urlä¸ç# |
| | | scrollBehavior: () => ({ y: 0 }), |
| | | routes: constantRoutes |
| | | }) |
| | | routes: constantRoutes, |
| | | }); |
| | |
| | | permissions: (state) => state.user.permissions, |
| | | belongWards: (state) => state.user.belongWards, |
| | | belongDepts: (state) => state.user.belongDepts, |
| | | satisfactionCategories: (state) => state.user.satisfactionCategories, |
| | | hisUserId: (state) => state.user.hisUserId, |
| | | permission_routes: (state) => state.permission.routes, |
| | | topbarRouters: (state) => state.permission.topbarRouters, |
| | |
| | | import auth from '@/plugins/auth' |
| | | import router, { constantRoutes, dynamicRoutes } from '@/router' |
| | | import { getRouters } from '@/api/menu' |
| | | import Layout from '@/layout/index' |
| | | import ParentView from '@/components/ParentView' |
| | | import InnerLink from '@/layout/components/InnerLink' |
| | | import auth from "@/plugins/auth"; |
| | | import router, { constantRoutes, dynamicRoutes } from "@/router"; |
| | | import { getRouters } from "@/api/menu"; |
| | | import Layout from "@/layout/index"; |
| | | import ParentView from "@/components/ParentView"; |
| | | import InnerLink from "@/layout/components/InnerLink"; |
| | | import store from "@/store"; |
| | | |
| | | |
| | | const permission = { |
| | | state: { |
| | |
| | | addRoutes: [], |
| | | defaultRoutes: [], |
| | | topbarRouters: [], |
| | | sidebarRouters: [] |
| | | sidebarRouters: [], |
| | | }, |
| | | mutations: { |
| | | SET_ROUTES: (state, routes) => { |
| | | state.addRoutes = routes |
| | | state.routes = constantRoutes.concat(routes) |
| | | state.addRoutes = routes; |
| | | state.routes = constantRoutes.concat(routes); |
| | | }, |
| | | SET_DEFAULT_ROUTES: (state, routes) => { |
| | | state.defaultRoutes = constantRoutes.concat(routes) |
| | | state.defaultRoutes = constantRoutes.concat(routes); |
| | | }, |
| | | SET_TOPBAR_ROUTES: (state, routes) => { |
| | | state.topbarRouters = routes |
| | | state.topbarRouters = routes; |
| | | }, |
| | | SET_SIDEBAR_ROUTERS: (state, routes) => { |
| | | state.sidebarRouters = routes |
| | | state.sidebarRouters = routes; |
| | | }, |
| | | }, |
| | | actions: { |
| | | // çæè·¯ç± |
| | | GenerateRoutes({ commit }) { |
| | | return new Promise(resolve => { |
| | | return new Promise((resolve) => { |
| | | // åå端请æ±è·¯ç±æ°æ® |
| | | getRouters().then(res => { |
| | | const sdata = JSON.parse(JSON.stringify(res.data)) |
| | | const rdata = JSON.parse(JSON.stringify(res.data)) |
| | | const sidebarRoutes = filterAsyncRouter(sdata) |
| | | const rewriteRoutes = filterAsyncRouter(rdata, false, true) |
| | | const asyncRoutes = filterDynamicRoutes(dynamicRoutes); |
| | | rewriteRoutes.push({ path: '*', redirect: '/404', hidden: true }) |
| | | router.addRoutes(asyncRoutes); |
| | | commit('SET_ROUTES', rewriteRoutes) |
| | | commit('SET_SIDEBAR_ROUTERS', constantRoutes.concat(sidebarRoutes)) |
| | | commit('SET_DEFAULT_ROUTES', sidebarRoutes) |
| | | commit('SET_TOPBAR_ROUTES', sidebarRoutes) |
| | | resolve(rewriteRoutes) |
| | | console.log(res.data,'è·¯ç±æ°æ®'); |
| | | const result = res.data.find(item => item.name == "Followvisit"); |
| | | Processrouting(result) |
| | | getRouters().then((res) => { |
| | | const sdata = JSON.parse(JSON.stringify(res.data)); |
| | | const rdata = JSON.parse(JSON.stringify(res.data)); |
| | | const sidebarRoutes = filterAsyncRouter(sdata); |
| | | const rewriteRoutes = filterAsyncRouter(rdata, false, true); |
| | | // å
³é®ä¿®æ¹ï¼å¯¹éæè·¯ç±ä¹è¿è¡æéè¿æ»¤ |
| | | // console.log(constantRoutes, "é"); |
| | | // console.log(dynamicRoutes, "å¨"); |
| | | |
| | | }) |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | function Processrouting(result){ |
| | | const arrf=[]; |
| | | const arr=store.getters.Serviceauthority; |
| | | console.log(result,'result'); |
| | | console.log(arr,'arr'); |
| | | result.children.forEach(objA => { |
| | | arr.forEach(objB => { |
| | | const filteredConstantRoutes = filterDynamicRoutes(constantRoutes); |
| | | const asyncRoutes = filterDynamicRoutes(dynamicRoutes); |
| | | |
| | | rewriteRoutes.push({ path: "*", redirect: "/404", hidden: true }); |
| | | |
| | | // æ·»å è¿æ»¤åçè·¯ç± |
| | | router.addRoutes(filteredConstantRoutes); |
| | | router.addRoutes(asyncRoutes); |
| | | |
| | | // æäº¤å°storeæ¶ä¹ä½¿ç¨è¿æ»¤åçè·¯ç± |
| | | commit("SET_ROUTES", rewriteRoutes); |
| | | commit( |
| | | "SET_SIDEBAR_ROUTERS", |
| | | filteredConstantRoutes.concat(sidebarRoutes) |
| | | ); |
| | | commit("SET_DEFAULT_ROUTES", sidebarRoutes); |
| | | commit("SET_TOPBAR_ROUTES", sidebarRoutes); |
| | | resolve(rewriteRoutes); |
| | | console.log(res.data, "è·¯ç±æ°æ®"); |
| | | const result = res.data.find((item) => item.name == "Followvisit"); |
| | | Processrouting(result); |
| | | }); |
| | | }); |
| | | }, |
| | | }, |
| | | }; |
| | | function Processrouting(result) { |
| | | const arrf = []; |
| | | const arr = store.getters.Serviceauthority; |
| | | console.log(result, "result"); |
| | | console.log(arr, "arr"); |
| | | result.children.forEach((objA) => { |
| | | arr.forEach((objB) => { |
| | | if (objA.meta.title === objB.label) { |
| | | arrf.push(objB); |
| | | } |
| | | }); |
| | | }); |
| | | console.log(arrf,'arrf'); |
| | | store.commit('SET_Serviceauthority', arrf); |
| | | |
| | | |
| | | console.log(arrf, "arrf"); |
| | | store.commit("SET_Serviceauthority", arrf); |
| | | } |
| | | |
| | | // éååå°ä¼ æ¥çè·¯ç±å符串ï¼è½¬æ¢ä¸ºç»ä»¶å¯¹è±¡ |
| | | function filterAsyncRouter(asyncRouterMap, lastRouter = false, type = false) { |
| | | return asyncRouterMap.filter(route => { |
| | | return asyncRouterMap.filter((route) => { |
| | | if (type && route.children) { |
| | | route.children = filterChildren(route.children) |
| | | route.children = filterChildren(route.children); |
| | | } |
| | | if (route.component) { |
| | | // Layout ParentView ç»ä»¶ç¹æ®å¤ç |
| | | if (route.component === 'Layout') { |
| | | route.component = Layout |
| | | } else if (route.component === 'ParentView') { |
| | | route.component = ParentView |
| | | } else if (route.component === 'InnerLink') { |
| | | route.component = InnerLink |
| | | if (route.component === "Layout") { |
| | | route.component = Layout; |
| | | } else if (route.component === "ParentView") { |
| | | route.component = ParentView; |
| | | } else if (route.component === "InnerLink") { |
| | | route.component = InnerLink; |
| | | } else { |
| | | route.component = loadView(route.component) |
| | | route.component = loadView(route.component); |
| | | } |
| | | } |
| | | if (route.children != null && route.children && route.children.length) { |
| | | route.children = filterAsyncRouter(route.children, route, type) |
| | | route.children = filterAsyncRouter(route.children, route, type); |
| | | } else { |
| | | delete route['children'] |
| | | delete route['redirect'] |
| | | delete route["children"]; |
| | | delete route["redirect"]; |
| | | } |
| | | return true |
| | | }) |
| | | return true; |
| | | }); |
| | | } |
| | | |
| | | function filterChildren(childrenMap, lastRouter = false) { |
| | | var children = [] |
| | | var children = []; |
| | | childrenMap.forEach((el, index) => { |
| | | if (el.children && el.children.length) { |
| | | if (el.component === 'ParentView' && !lastRouter) { |
| | | el.children.forEach(c => { |
| | | c.path = el.path + '/' + c.path |
| | | if (el.component === "ParentView" && !lastRouter) { |
| | | el.children.forEach((c) => { |
| | | c.path = el.path + "/" + c.path; |
| | | if (c.children && c.children.length) { |
| | | children = children.concat(filterChildren(c.children, c)) |
| | | return |
| | | children = children.concat(filterChildren(c.children, c)); |
| | | return; |
| | | } |
| | | children.push(c) |
| | | }) |
| | | return |
| | | children.push(c); |
| | | }); |
| | | return; |
| | | } |
| | | } |
| | | if (lastRouter) { |
| | | el.path = lastRouter.path + '/' + el.path |
| | | el.path = lastRouter.path + "/" + el.path; |
| | | } |
| | | children = children.concat(el) |
| | | }) |
| | | return children |
| | | children = children.concat(el); |
| | | }); |
| | | return children; |
| | | } |
| | | |
| | | // å¨æè·¯ç±éåï¼éªè¯æ¯å¦å
·å¤æé |
| | | export function filterDynamicRoutes(routes) { |
| | | const res = [] |
| | | routes.forEach(route => { |
| | | const res = []; |
| | | routes.forEach((route) => { |
| | | // é¦å
æ£æ¥æéå符串 (permissions) |
| | | if (route.permissions) { |
| | | if (auth.hasPermiOr(route.permissions)) { |
| | | res.push(route) |
| | | } |
| | | } else if (route.roles) { |
| | | if (auth.hasRoleOr(route.roles)) { |
| | | res.push(route) |
| | | res.push(route); |
| | | } |
| | | } |
| | | }) |
| | | return res |
| | | // ç¶åæ£æ¥è§è²æé (roles) - è¿æ¯æ¨éè¦éç¹å
³æ³¨çé¨å |
| | | else if (route.children) { |
| | | if ( |
| | | route.children[0]?.meta?.roles && |
| | | auth.hasRoleOr(route.children[0].meta.roles) |
| | | ) { |
| | | res.push(route); |
| | | } |
| | | } |
| | | // å¯¹äºæ²¡æè®¾ç½®æéçè·¯ç±ï¼é»è®¤å
è®¸è®¿é® |
| | | else { |
| | | res.push(route); |
| | | } |
| | | }); |
| | | return res; |
| | | } |
| | | |
| | | export const loadView = (view) => { |
| | | if (process.env.NODE_ENV === 'development') { |
| | | return (resolve) => require([`@/views/${view}`], resolve) |
| | | if (process.env.NODE_ENV === "development") { |
| | | return (resolve) => require([`@/views/${view}`], resolve); |
| | | } else { |
| | | // ä½¿ç¨ import å®ç°ç产ç¯å¢çè·¯ç±æå è½½ |
| | | return () => import(`@/views/${view}`) |
| | | return () => import(`@/views/${view}`); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | export default permission |
| | | export default permission; |
| | |
| | | belongDepts: [], |
| | | roles: [], |
| | | permissions: [], |
| | | satisfactionCategories:{}, |
| | | // æå¡ç±»å |
| | | Serviceauthority: [ |
| | | { |
| | |
| | | SET_hisUserId: (state, hisUserId) => { |
| | | state.hisUserId = hisUserId; |
| | | }, |
| | | SET_satisfactionCategories: (state, satisfactionCategories) => { |
| | | state.satisfactionCategories = satisfactionCategories; |
| | | }, |
| | | SET_leaveldeptcodes: (state, belongDepts) => { |
| | | state.belongDepts = belongDepts; |
| | | }, |
| | |
| | | const username = userInfo.username.trim(); |
| | | const password = userInfo.password; |
| | | const code = userInfo.code; |
| | | const campusid = userInfo.campusid; |
| | | |
| | | const orgid = userInfo.orgid; |
| | | console.log(orgid, campusid, "88"); |
| | | |
| | | return new Promise((resolve, reject) => { |
| | | login(username, password, code, orgid) |
| | | login(username, password, code, orgid, campusid) |
| | | .then((res) => { |
| | | setToken(res.token); |
| | | commit("SET_TOKEN", res.token); |
| | |
| | | localStorage.setItem("YongHuXM", "LQZYY"); |
| | | } else if (orgid == "47243006833112611A2101") { |
| | | localStorage.setItem("orgname", "åºå
å¿ä¸å»å»é¢"); |
| | | localStorage.setItem("ZuHuID", "1429338802177000004"); |
| | | localStorage.setItem("ZuHuID", "1429338802177000005"); |
| | | localStorage.setItem("deptCode", ""); |
| | | localStorage.setItem("YongHuID", "1462585966286868480"); |
| | | localStorage.setItem("YongHuXM", "QYZYY"); |
| | | } else if (orgid == "47234002X33112111A2101") { |
| | | localStorage.setItem("orgname", "éç°å¿ä¸å»å»é¢"); |
| | | localStorage.setItem("ZuHuID", "1429338802177000005"); |
| | | localStorage.setItem("ZuHuID", "1429338802177000004"); |
| | | localStorage.setItem("deptCode", ""); |
| | | localStorage.setItem("YongHuID", "1462614919332499458"); |
| | | localStorage.setItem("YongHuXM", "QTHCZYY"); |
| | |
| | | } else if (orgid == "20001001") { |
| | | localStorage.setItem("orgname", "çç«åå¾·ç¿ èé¢åº"); |
| | | localStorage.setItem("ZuHuID", ""); |
| | | localStorage.setItem("deptCode", ""); |
| | | localStorage.setItem("YongHuID", ""); |
| | | localStorage.setItem("YongHuXM", ""); |
| | | } else if (orgid == "47252003933112411A2101") { |
| | | localStorage.setItem("orgname", "æ¾é³å¿ä¸å»å»é¢"); |
| | | localStorage.setItem("ZuHuID", "1429338802177000008"); |
| | | localStorage.setItem("deptCode", ""); |
| | | localStorage.setItem("YongHuID", "1497875635748474880"); |
| | | localStorage.setItem("YongHuXM", "SYZYY"); |
| | | } else if (orgid == "47231077933110211A1101") { |
| | | localStorage.setItem("orgname", "è²é½åºäººæ°å»é¢"); |
| | | localStorage.setItem("ZuHuID", "1429338802177000011"); |
| | | localStorage.setItem("deptCode", "01020901"); |
| | | localStorage.setItem("YongHuID", "1512710152715767808"); |
| | | localStorage.setItem("YongHuXM", "LDRMYY"); |
| | | } else if (orgid == "1" && campusid == 1) { |
| | | localStorage.setItem("orgname", "第ä¸äººæ°å»é¢æ¹æ»¨é¢åº"); |
| | | localStorage.setItem("ZuHuID", ""); |
| | | localStorage.setItem("deptCode", ""); |
| | | localStorage.setItem("YongHuID", ""); |
| | | localStorage.setItem("YongHuXM", ""); |
| | | } else if (orgid == "1" && campusid == 2) { |
| | | localStorage.setItem("orgname", "第ä¸äººæ°å»é¢å´å±±é¢åº"); |
| | | localStorage.setItem("ZuHuID", ""); |
| | | localStorage.setItem("deptCode", ""); |
| | | localStorage.setItem("YongHuID", ""); |
| | | localStorage.setItem("YongHuXM", ""); |
| | | } else if (orgid == "47246116333112211A1001") { |
| | | localStorage.setItem("orgname", "ç¼äºå¿äººæ°å»é¢"); |
| | | localStorage.setItem("ZuHuID", "1429338802177000010"); |
| | | localStorage.setItem("deptCode", ""); |
| | | localStorage.setItem("YongHuID", ""); |
| | | localStorage.setItem("YongHuXM", ""); |
| | | } else if (orgid == "47226079133110211G1001") { |
| | | localStorage.setItem("orgname", "丽水å¸å¦å¹¼ä¿å¥é¢"); |
| | | localStorage.setItem("ZuHuID", "1429338802177000014"); |
| | | localStorage.setItem("deptCode", ""); |
| | | localStorage.setItem("YongHuID", ""); |
| | | localStorage.setItem("YongHuXM", ""); |
| | |
| | | commit("SET_nickNAME", user.nickName); |
| | | commit("SET_Id", user.userId); |
| | | commit("SET_hisUserId", user.hisUserId); |
| | | commit("SET_satisfactionCategories", user.satisfactionCategories); |
| | | |
| | | // if (user.userName == "admin") { |
| | | // commit("SET_leaveldeptcodes", []); |
| | | // commit("SET_leavehospitaldistrictcodes", []); |
| | | // } else { |
| | | // commit("SET_leavehospitaldistrictcodes", user.belongWards); |
| | | // commit("SET_leaveldeptcodes", user.belongDepts); |
| | | // } |
| | | commit("SET_leavehospitaldistrictcodes", user.belongWards); |
| | | commit("SET_leaveldeptcodes", user.belongDepts); |
| | | commit("SET_AVATAR", avatar); |
| | |
| | | } |
| | | ) |
| | | .then(() => { |
| | | this.$router.replace("/login"); |
| | | console.log('鿩鿰ç»å½'); |
| | | |
| | | this.$router.replace("/login"); |
| | | }) |
| | | .catch(() => { |
| | | isRelogin.show = false; |
| | |
| | | import JsSIP from "jssip"; |
| | | |
| | | import { Notification, MessageBox, Message, Loading } from "element-ui"; |
| | | // å»é¢æºæä¸SIPæå¡å¨æ å°é
ç½® |
| | | // å
¬å¸æå¡å¨192.168.100.6 |
| | | const HOSPITAL_CONFIG = { |
| | | 丽水å¸ä¸å»é¢: { |
| | | wsUrl: "wss://192.168.10.124:7443", |
| | | domain: "192.168.10.124", |
| | | }, |
| | | 龿³å¸äººæ°å»é¢: { |
| | | wsUrl: "wss://10.10.0.220:7443", |
| | | domain: "10.10.0.220", |
| | | }, |
| | | 第ä¸äººæ°å»é¢æ¹æ»¨é¢åº: { |
| | | wsUrl: "wss://192.169.129.198:7443", |
| | | domain: "192.169.129.198", |
| | | }, |
| | | 第ä¸äººæ°å»é¢å´å±±é¢åº: { |
| | | wsUrl: "wss://192.169.129.198:7443", |
| | | domain: "192.169.129.198", |
| | | }, |
| | | // å¯ä»¥ç»§ç»æ·»å å
¶ä»å»é¢é
ç½® |
| | | default: { |
| | | wsUrl: "wss://192.168.10.124:7443", |
| | | domain: "192.168.10.124", |
| | | }, |
| | | }; |
| | | class SipService { |
| | | constructor() { |
| | | this.ua = null; |
| | |
| | | this.onIncomingCall = null; |
| | | this.isRegistered = false; // æ°å¢æ³¨åç¶ææ å¿ |
| | | this.registrationTime = null; // æ°å¢æ³¨åæåæ¶é´æ³ |
| | | this.currentConfig = null; // åå¨å½åé
ç½® |
| | | } |
| | | |
| | | init(config) { |
| | | // è·åå»é¢é
ç½®æ¹æ³ |
| | | getHospitalConfig() { |
| | | const orgName = localStorage.getItem("orgname"); |
| | | return HOSPITAL_CONFIG[orgName] || HOSPITAL_CONFIG.default; |
| | | } |
| | | init(baseConfig) { |
| | | try { |
| | | this.updateStatus("connecting", "è¿æ¥ä¸;..."); |
| | | // è·åæºæåç§°ï¼å¦ææ²¡æä¼ å
¥åä»localStorage读å |
| | | const orgName = baseConfig.orgName || localStorage.getItem("orgname"); |
| | | |
| | | // æ ¹æ®æºæåç§°è·å对åºçæå¡å¨é
ç½® |
| | | const hospitalConfig = this.getHospitalConfig(orgName); |
| | | console.log(hospitalConfig, "88"); |
| | | |
| | | // åå¹¶é
ç½® |
| | | this.currentConfig = { |
| | | ...baseConfig, |
| | | ...hospitalConfig, |
| | | }; |
| | | |
| | | console.log( |
| | | `å½åæºæ: ${orgName}, ä½¿ç¨æå¡å¨: ${this.currentConfig.domain}` |
| | | ); |
| | | |
| | | this.updateStatus("connecting", "è¿æ¥ä¸..."); |
| | | console.log(baseConfig.sipUri, "baseConfig.sipUri"); |
| | | |
| | | this.ua = new JsSIP.UA({ |
| | | sockets: [new JsSIP.WebSocketInterface(config.wsUrl)], |
| | | uri: config.sipUri, |
| | | password: config.password, |
| | | display_name: config.displayName, |
| | | sockets: [new JsSIP.WebSocketInterface(this.currentConfig.wsUrl)], |
| | | uri: baseConfig.sipUri, // è¿é使ç¨åºç¡çsipUriï¼domainé¨åä¼è¢«å¨ææ¿æ¢ |
| | | password: baseConfig.password, |
| | | display_name: baseConfig.displayName, |
| | | iceServers: [], |
| | | register: true, |
| | | sessionExpires: 1800, |
| | |
| | | const remaining = minDelay - timeSinceRegistration; |
| | | return { |
| | | canCall: false, |
| | | reason: `注åæåï¼è¯·çå¾
${Math.ceil(remaining / 1000)} ç§ååå¼å«`, |
| | | reason: `注åæåï¼èµæºå è½½ä¸è¯·çå¾
${Math.ceil( |
| | | remaining / 1000 |
| | | )} ç§ååå¼å«`, |
| | | }; |
| | | } |
| | | |
| | |
| | | makeCall(targetNumber) { |
| | | const { canCall, reason } = this.canMakeCall(); |
| | | if (!canCall) { |
| | | Message.error(reason); |
| | | return Promise.reject(new Error(reason)); |
| | | } |
| | | return new Promise((resolve, reject) => { |
| | |
| | | if (!this.ua.isRegistered()) { |
| | | throw new Error("SIPæªæ³¨åï¼æ æ³å¼å«"); |
| | | } |
| | | |
| | | const targetUri = `sip:${targetNumber}@${this.currentConfig.domain}`; |
| | | console.log(`å¼å«ç®æ : ${targetUri}`); |
| | | const options = { |
| | | sessionTimers: true, // å¯ç¨ä¼è¯è®¡æ¶å¨ |
| | | sessionTimersExpires: 150, |
| | |
| | | }, |
| | | }; |
| | | |
| | | this.currentSession = this.ua.call( |
| | | `sip:${targetNumber}@192.168.10.124`, |
| | | options |
| | | ); |
| | | this.currentSession = this.ua.call(targetUri, options); |
| | | |
| | | this.setupPeerConnection(this.currentSession); |
| | | this.setupAudio(this.currentSession); |
| | |
| | | }); |
| | | } |
| | | |
| | | // normalizeSDP(offer) { |
| | | // let sdp = offer.sdp; |
| | | // console.log("åå§SDP:", sdp); // è°è¯ç¨ï¼æè·åå§SDP |
| | | // // æ ååSDP |
| | | // sdp = sdp.replace(/c=IN IP4.*\r\n/, "c=IN IP4 0.0.0.0\r\n"); |
| | | // sdp = sdp.replace( |
| | | // /m=audio \d+.*\r\n/, |
| | | // "m=audio 9 UDP/TLS/RTP/SAVPF 0 8\r\n" |
| | | // ); |
| | | |
| | | // // ç¡®ä¿å
å«åºæ¬ç¼è§£ç å¨ |
| | | // if (!sdp.includes("PCMU/8000")) sdp += "a=rtpmap:0 PCMU/8000\r\n"; |
| | | // if (!sdp.includes("PCMA/8000")) sdp += "a=rtpmap:8 PCMA/8000\r\n"; |
| | | |
| | | // // æ·»å å¿
è¦å±æ§ |
| | | // sdp += "a=rtcp-mux\r\n"; |
| | | // sdp += "a=sendrecv\r\n"; |
| | | |
| | | // console.log("æ åååçSDP:", sdp); |
| | | // return new RTCSessionDescription({ |
| | | // type: offer.type, |
| | | // sdp: sdp, |
| | | // }); |
| | | // } |
| | | // å¨ SipService ç±»ä¸æ°å¢æ¹æ³ï¼ç¨äºè·åé对ç¹å®æå¡å¨çSDPå¤ççç¥ |
| | | getSDPNormalizationStrategy(orgName) { |
| | | const strategies = { |
| | | 龿³å¸äººæ°å»é¢: "conservative", // ä¿å®çç¥ï¼æå°åä¿®æ¹ï¼ä¼å
å
¼å®¹ |
| | | 丽水å¸ä¸å»é¢: "aggressive", // æ¿è¿çç¥ï¼ä¿æåæå¼ºæ ååé»è¾ |
| | | // å¯ä»¥ä¸ºå
¶ä»æºææ·»å æ´å¤çç¥ |
| | | }; |
| | | return strategies[orgName] || "moderate"; // é»è®¤çç¥ |
| | | } |
| | | |
| | | /** |
| | | * æ ååSDP Offer - ä¿®å¤é¾æ³å¸äººæ°å»é¢488é误 |
| | | * æ ¸å¿æè·¯ï¼ä»â强å¶è¦çâæ¹ä¸ºâæºè½ä¿®è¡¥âï¼é对ä¸åæå¡å¨ä½¿ç¨å·®å¼åçç¥ |
| | | */ |
| | | normalizeSDP(offer) { |
| | | const orgName = localStorage.getItem("orgname"); |
| | | const strategy = this.getSDPNormalizationStrategy(orgName); |
| | | let sdp = offer.sdp; |
| | | |
| | | // æ ååSDP |
| | | sdp = sdp.replace(/c=IN IP4.*\r\n/, "c=IN IP4 0.0.0.0\r\n"); |
| | | sdp = sdp.replace( |
| | | /m=audio \d+.*\r\n/, |
| | | "m=audio 9 UDP/TLS/RTP/SAVPF 0 8\r\n" |
| | | ); |
| | | console.log(`[SDPæ åå] æºæ: ${orgName}, çç¥: ${strategy}`); |
| | | console.log("[SDPæ åå] åå§SDP:", sdp); |
| | | |
| | | // ç¡®ä¿å
å«åºæ¬ç¼è§£ç å¨ |
| | | if (!sdp.includes("PCMU/8000")) sdp += "a=rtpmap:0 PCMU/8000\r\n"; |
| | | if (!sdp.includes("PCMA/8000")) sdp += "a=rtpmap:8 PCMA/8000\r\n"; |
| | | if (strategy === "conservative") { |
| | | // ==================== ä¿å®çç¥ï¼é坹龿³å¸äººæ°å»é¢çä¸¥æ ¼æå¡å¨ ==================== |
| | | // ååï¼é¤éå¿
è¦ï¼å¦åä¸ä¿®æ¹åæSDPç»æï¼ä»
æ·»å 缺失çå
³é®å±æ§ |
| | | |
| | | // æ·»å å¿
è¦å±æ§ |
| | | sdp += "a=rtcp-mux\r\n"; |
| | | sdp += "a=sendrecv\r\n"; |
| | | // 1. è°¨æ
å¤çè¿æ¥å°åï¼ä»
å¨å°åæ¯ææ¾å
ç½å°åæ¶æä¿®æ¹ |
| | | const privateIPRegex = |
| | | /c=IN IP4 (192\.168|10\.|172\.(1[6-9]|2[0-9]|3[0-1]))/; |
| | | if (privateIPRegex.test(sdp)) { |
| | | sdp = sdp.replace(/c=IN IP4.*\r\n/, "c=IN IP4 0.0.0.0\r\n"); |
| | | console.log("[SDPæ åå] 已修æ¹è¿æ¥å°å为 0.0.0.0"); |
| | | } |
| | | |
| | | console.log("æ åååçSDP:", sdp); |
| | | // 2. ä¿æåªä½è¡åæ ·ï¼ä¸å¼ºå¶ä¿®æ¹ç«¯å£ååè®® |
| | | // sdp = sdp.replace(/m=audio \d+.*\r\n/, "m=audio 9 UDP/TLS/RTP/SAVPF 0 8\r\n"); |
| | | |
| | | // 3. æºè½æ·»å åºç¡ç¼è§£ç 卿 å°ï¼ä»
å¨ç¼ºå¤±æ¶æ·»å ï¼ |
| | | const codecMappings = [ |
| | | { pt: 0, name: "PCMU/8000" }, |
| | | { pt: 8, name: "PCMA/8000" }, |
| | | ]; |
| | | |
| | | codecMappings.forEach((codec) => { |
| | | const rtpmapPattern = `a=rtpmap:${codec.pt} ${codec.name}`; |
| | | const payloadPattern = ` ${codec.pt} `; |
| | | |
| | | // åªæå½SDPä¸å
å«è¯¥è´è½½ç±»åä½ç¼ºå°è¯¦ç»æ å°æ¶ææ·»å |
| | | if (sdp.includes(payloadPattern) && !sdp.includes(rtpmapPattern)) { |
| | | sdp += `${rtpmapPattern}\r\n`; |
| | | console.log(`[SDPæ åå] 已添å ç¼è§£ç 卿 å°: ${rtpmapPattern}`); |
| | | } |
| | | }); |
| | | |
| | | // 4. æ¡ä»¶æ§æ·»å å¿
è¦å±æ§ï¼é¿å
éå¤ï¼ |
| | | const essentialAttributes = [ |
| | | { attr: "a=rtcp-mux", desc: "RTCPå¤ç¨" }, |
| | | { attr: "a=sendrecv", desc: "åååªä½æµ" }, |
| | | ]; |
| | | |
| | | essentialAttributes.forEach((item) => { |
| | | if (!sdp.includes(item.attr)) { |
| | | sdp += `${item.attr}\r\n`; |
| | | console.log(`[SDPæ åå] 已添å 屿§: ${item.desc}`); |
| | | } |
| | | }); |
| | | } else if (strategy === "aggressive") { |
| | | // ==================== æ¿è¿çç¥ï¼ä¿æåæé»è¾ ==================== |
| | | sdp = sdp.replace(/c=IN IP4.*\r\n/, "c=IN IP4 0.0.0.0\r\n"); |
| | | sdp = sdp.replace( |
| | | /m=audio \d+.*\r\n/, |
| | | "m=audio 9 UDP/TLS/RTP/SAVPF 0 8\r\n" |
| | | ); |
| | | |
| | | // ç¡®ä¿å
å«åºç¡ç¼è§£ç å¨ |
| | | if (!sdp.includes("PCMU/8000")) sdp += "a=rtpmap:0 PCMU/8000\r\n"; |
| | | if (!sdp.includes("PCMA/8000")) sdp += "a=rtpmap:8 PCMA/8000\r\n"; |
| | | |
| | | // æ·»å éç¨å±æ§ |
| | | sdp += "a=rtcp-mux\r\n"; |
| | | sdp += "a=sendrecv\r\n"; |
| | | } else { |
| | | // ==================== é»è®¤çç¥ï¼å¹³è¡¡æ¹æ¡ ==================== |
| | | // é度修æ¹ï¼å
¼é¡¾å
¼å®¹æ§ååè½æ§ |
| | | sdp = sdp.replace(/c=IN IP4.*\r\n/, "c=IN IP4 0.0.0.0\r\n"); |
| | | |
| | | // ä»
å¨åªä½è¡æ ¼å¼ææ¾å¼å¸¸æ¶ä¿®æ¹ |
| | | if (!sdp.match(/m=audio \d+ RTP\/AVP/)) { |
| | | sdp = sdp.replace( |
| | | /m=audio \d+.*\r\n/, |
| | | "m=audio 9 UDP/TLS/RTP/SAVPF 0 8\r\n" |
| | | ); |
| | | } |
| | | |
| | | // æºè½æ·»å 缺失ç屿§ |
| | | if (!sdp.includes("a=rtcp-mux")) sdp += "a=rtcp-mux\r\n"; |
| | | if (!sdp.includes("a=sendrecv")) sdp += "a=sendrecv\r\n"; |
| | | } |
| | | |
| | | console.log("[SDPæ åå] æ åååSDP:", sdp); |
| | | return new RTCSessionDescription({ |
| | | type: offer.type, |
| | | sdp: sdp, |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * å¢å¼ºçSDPè°è¯æ¹æ³ - ç¨äºå¯¹æ¯åæ |
| | | */ |
| | | debugSDPComparison(originalOffer, normalizedOffer, context) { |
| | | console.group(`[SDPè°è¯] ${context}`); |
| | | console.log( |
| | | "åå§SDPåªä½è¡:", |
| | | originalOffer.sdp.match(/m=audio.*\r\n/)?.[0] || "æªæ¾å°" |
| | | ); |
| | | console.log( |
| | | "æ ååååªä½è¡:", |
| | | normalizedOffer.sdp.match(/m=audio.*\r\n/)?.[0] || "æªæ¾å°" |
| | | ); |
| | | console.log( |
| | | "åå§ç¼è§£ç å¨å表:", |
| | | originalOffer.sdp.match(/a=rtpmap:\d+.*\r\n/g) || [] |
| | | ); |
| | | console.log( |
| | | "æ åååç¼è§£ç å¨å表:", |
| | | normalizedOffer.sdp.match(/a=rtpmap:\d+.*\r\n/g) || [] |
| | | ); |
| | | console.groupEnd(); |
| | | } |
| | | |
| | | // å¨ setupPeerConnection æ¹æ³ä¸éæè°è¯åè½ |
| | | setupPeerConnection(session) { |
| | | session.on("peerconnection", (pc) => { |
| | | const originalCreateOffer = pc.createOffer.bind(pc); |
| | | |
| | | pc.createOffer = async (offerOptions) => { |
| | | try { |
| | | const offer = await originalCreateOffer(offerOptions); |
| | | const normalizedOffer = this.normalizeSDP(offer); |
| | | |
| | | // è°è¯ä¿¡æ¯è¾åº |
| | | this.debugSDPComparison(offer, normalizedOffer, "Offeråå»ºé¶æ®µ"); |
| | | |
| | | return normalizedOffer; |
| | | } catch (error) { |
| | | console.error("å建Offer失败:", error); |
| | | throw error; |
| | | } |
| | | }; |
| | | }); |
| | | } |
| | | handleCallFailure(e, reject) { |
| | | if (e.response?.status_code === 422) { |
| | | const serverMinSE = e.response.headers["Min-SE"]?.[0]?.raw || "æªç¥"; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="batch-process"> |
| | | <!-- 页颿 é¢ --> |
| | | <div class="page-header"> |
| | | <div class="header-content"> |
| | | <h2 class="page-title">å¼å¸¸æ¹éå¤ç</h2> |
| | | <p class="page-description">æ¹éå¤çéä¸çå¼å¸¸åé¦</p> |
| | | <div class="header-actions"> |
| | | <el-button |
| | | type="primary" |
| | | icon="el-icon-check" |
| | | @click="handleBatchSubmit" |
| | | :loading="batchProcessing" |
| | | > |
| | | æ¹éæäº¤å¤ç |
| | | </el-button> |
| | | <el-button type="warning" icon="el-icon-back" @click="handleGoBack"> |
| | | è¿åå¼å¸¸å表 |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- å¼å¸¸å表 --> |
| | | <div class="list-section"> |
| | | <el-card shadow="never"> |
| | | <div class="filter-section"> |
| | | <el-form |
| | | :model="filterParams" |
| | | :inline="true" |
| | | size="medium" |
| | | class="filter-form" |
| | | > |
| | | <el-form-item label="è´è´£ç§å®¤"> |
| | | <el-select |
| | | v-model="filterParams.deptId" |
| | | placeholder="è¯·éæ©ç§å®¤" |
| | | clearable |
| | | style="width: 200px" |
| | | > |
| | | <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="å¤çç¶æ"> |
| | | <el-select |
| | | v-model="filterParams.status" |
| | | placeholder="è¯·éæ©ç¶æ" |
| | | clearable |
| | | style="width: 200px" |
| | | > |
| | | <el-option label="å¾
å¤ç" :value="0" /> |
| | | <el-option label="å¤çä¸" :value="1" /> |
| | | <el-option label="å·²å¤ç" :value="2" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button |
| | | type="primary" |
| | | icon="el-icon-search" |
| | | @click="handleFilter" |
| | | > |
| | | çé |
| | | </el-button> |
| | | <el-button icon="el-icon-refresh" @click="handleResetFilter"> |
| | | éç½® |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | |
| | | <el-table |
| | | v-loading="loading" |
| | | :data="exceptionList" |
| | | :border="true" |
| | | style="width: 100%" |
| | | @selection-change="handleSelectionChange" |
| | | class="exception-table" |
| | | > |
| | | <el-table-column type="selection" width="55" align="center" /> |
| | | |
| | | <el-table-column |
| | | label="åºå·" |
| | | type="index" |
| | | width="60" |
| | | align="center" |
| | | /> |
| | | |
| | | <el-table-column |
| | | label="è´è´£ç§å®¤" |
| | | prop="responsibilityDept" |
| | | width="120" |
| | | align="center" |
| | | > |
| | | <template slot-scope="{ row }"> |
| | | <el-tag type="primary">{{ row.responsibilityDept }}</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="䏿»¡æè¯¦æ
" |
| | | prop="unsatisfactoryDetail" |
| | | min-width="200" |
| | | align="center" |
| | | > |
| | | <template slot-scope="{ row }"> |
| | | <div class="detail-content"> |
| | | {{ row.unsatisfactoryDetail }} |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column label="æ£è
ä¿¡æ¯" width="300" align="center"> |
| | | <template slot-scope="{ row }"> |
| | | <div class="patient-info"> |
| | | <div class="patient-item"> |
| | | <span class="label">å§åï¼</span> |
| | | <span class="value">{{ row.patientName }}</span> |
| | | </div> |
| | | <div class="patient-item"> |
| | | <span class="label">æ§å«ï¼</span> |
| | | <span class="value">{{ |
| | | row.gender === 1 ? "ç·" : "女" |
| | | }}</span> |
| | | </div> |
| | | <div class="patient-item"> |
| | | <span class="label">å¹´é¾ï¼</span> |
| | | <span class="value">{{ row.age }}å²</span> |
| | | </div> |
| | | <div class="patient-item"> |
| | | <span class="label">çµè¯ï¼</span> |
| | | <span class="value">{{ row.phone }}</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column label="åºé¢ä¿¡æ¯" width="250" align="center"> |
| | | <template slot-scope="{ row }"> |
| | | <div class="discharge-info"> |
| | | <div class="info-item"> |
| | | <span class="label">ç§å®¤ï¼</span> |
| | | <span class="value">{{ row.dischargeDept }}</span> |
| | | </div> |
| | | <div class="info-item"> |
| | | <span class="label">ç
åºï¼</span> |
| | | <span class="value">{{ row.dischargeWard }}</span> |
| | | </div> |
| | | <div class="info-item"> |
| | | <span class="label">å¡«åæ¶é´ï¼</span> |
| | | <span class="value time">{{ row.fillTime }}</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="å¤çç¶æ" |
| | | prop="processStatus" |
| | | width="100" |
| | | align="center" |
| | | > |
| | | <template slot-scope="{ row }"> |
| | | <el-tag :type="getStatusTagType(row.processStatus)" effect="dark"> |
| | | {{ getStatusText(row.processStatus) }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="æä½" |
| | | width="210" |
| | | align="center" |
| | | fixed="right" |
| | | > |
| | | <template slot-scope="{ row }"> |
| | | <el-button |
| | | type="primary" |
| | | size="small" |
| | | icon="el-icon-view" |
| | | @click="handleViewDetail(row)" |
| | | > |
| | | æ¥ç详æ
|
| | | </el-button> |
| | | <el-button |
| | | type="warning" |
| | | size="small" |
| | | icon="el-icon-edit" |
| | | @click="handleProcess(row)" |
| | | :disabled="row.processStatus === 2" |
| | | > |
| | | å¤ç |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <!-- å页 --> |
| | | <div class="pagination-section"> |
| | | <el-pagination |
| | | background |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | :current-page="filterParams.pageNum" |
| | | :page-size="filterParams.pageSize" |
| | | :page-sizes="[10, 20, 30, 50]" |
| | | :total="total" |
| | | @size-change="handleSizeChange" |
| | | @current-change="handlePageChange" |
| | | /> |
| | | </div> |
| | | </el-card> |
| | | </div> |
| | | |
| | | <!-- å¤çå¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | title="å¤çå¼å¸¸åé¦" |
| | | :visible.sync="processDialogVisible" |
| | | width="600px" |
| | | center |
| | | > |
| | | <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="handlePreview" |
| | | :on-remove="handleRemove" |
| | | :before-remove="beforeRemove" |
| | | :limit="3" |
| | | :on-exceed="handleExceed" |
| | | :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 |
| | | title="æ¹éå¤çå¼å¸¸åé¦" |
| | | :visible.sync="batchDialogVisible" |
| | | width="600px" |
| | | center |
| | | > |
| | | <el-form |
| | | :model="batchProcessForm" |
| | | :rules="processRules" |
| | | ref="batchProcessForm" |
| | | label-width="100px" |
| | | size="medium" |
| | | > |
| | | <el-form-item label="å¤çç¶æ" prop="status"> |
| | | <el-select |
| | | v-model="batchProcessForm.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="batchProcessForm.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="batchProcessForm.remark" |
| | | type="textarea" |
| | | :rows="4" |
| | | placeholder="请è¾å
¥å¤ç夿³¨ï¼æå¤500åï¼" |
| | | maxlength="500" |
| | | show-word-limit |
| | | /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <span slot="footer" class="dialog-footer"> |
| | | <el-button @click="batchDialogVisible = false">åæ¶</el-button> |
| | | <el-button |
| | | type="primary" |
| | | @click="submitBatchProcess" |
| | | :loading="batchProcessing" |
| | | > |
| | | æ¹éæäº¤ |
| | | </el-button> |
| | | </span> |
| | | </el-dialog> |
| | | <!-- å¼å¸¸è¯¦æ
å¼¹æ¡ --> |
| | | <Details-anomaly |
| | | :visible="detailDialogVisible" |
| | | :record-id="selectedRecordId" |
| | | :title="detailDialogTitle" |
| | | @update:visible="handleDetailDialogClose" |
| | | @processed="handleProcessed" |
| | | @close="handleDetailDialogClose" |
| | | /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import DetailsAnomaly from "./components/DetailsAnomaly.vue"; |
| | | export default { |
| | | name: "BatchProcess", |
| | | components: { |
| | | DetailsAnomaly, |
| | | }, |
| | | data() { |
| | | return { |
| | | // æ·»å 以䏿°æ® |
| | | detailDialogVisible: false, |
| | | selectedRecordId: null, |
| | | detailDialogTitle: "å¼å¸¸åé¦è¯¦æ
", |
| | | // å½åå¤ççå¼å¸¸ID |
| | | currentExceptionId: null, |
| | | |
| | | // æ¹ééä¸çå¼å¸¸ID |
| | | selectedExceptionIds: [], |
| | | |
| | | // è¿æ»¤åæ° |
| | | filterParams: { |
| | | deptId: "", |
| | | status: "", |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | }, |
| | | |
| | | // å è½½ç¶æ |
| | | loading: false, |
| | | processing: false, |
| | | batchProcessing: false, |
| | | |
| | | // ç§å®¤å表 |
| | | 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: "å¼å¸å
ç§" }, |
| | | { id: 9, name: "æ¶åå
ç§" }, |
| | | { id: 10, name: "å
åæ³ç§" }, |
| | | ], |
| | | |
| | | // å¼å¸¸åè¡¨æ°æ® |
| | | exceptionList: [], |
| | | total: 0, |
| | | |
| | | // å¤çå¯¹è¯æ¡ |
| | | processDialogVisible: 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: [], |
| | | |
| | | // æ¹éå¤çå¯¹è¯æ¡ |
| | | batchDialogVisible: false, |
| | | batchProcessForm: { |
| | | status: "", |
| | | reportDepts: [], |
| | | remark: "", |
| | | }, |
| | | }; |
| | | }, |
| | | |
| | | mounted() { |
| | | this.loadExceptionList(); |
| | | }, |
| | | |
| | | methods: { |
| | | // å è½½å¼å¸¸å表 |
| | | async loadExceptionList() { |
| | | this.loading = true; |
| | | try { |
| | | // Mock æ°æ® |
| | | await new Promise((resolve) => { |
| | | setTimeout(() => { |
| | | this.exceptionList = [ |
| | | { |
| | | id: 1, |
| | | responsibilityDept: "å¿è¡ç®¡å
ç§", |
| | | unsatisfactoryDetail: |
| | | "å»çæ¥æ¿æ¶é´å¤ªçï¼æ²éä¸å¤å
åï¼å¯¹ç
æ
è§£éä¸å¤è¯¦ç»", |
| | | patientName: "å¼ å
ç", |
| | | gender: 1, |
| | | age: 45, |
| | | phone: "138****1234", |
| | | dischargeDept: "å¿è¡ç®¡å
ç§", |
| | | dischargeWard: "å
ç§ä¸ç
åº", |
| | | fillTime: "2024-01-15 10:30:25", |
| | | processStatus: 0, |
| | | questionnaireId: 1001, |
| | | }, |
| | | { |
| | | id: 2, |
| | | responsibilityDept: "ç¥ç»å
ç§", |
| | | unsatisfactoryDetail: |
| | | "æ¤å£«æéææ¯ä¸ä½³ï¼æäºä¸æ¬¡ææåï¼ä¸æåº¦ä¸å¤èå¿", |
| | | patientName: "æå¥³å£«", |
| | | gender: 0, |
| | | age: 38, |
| | | phone: "139****5678", |
| | | dischargeDept: "ç¥ç»å
ç§", |
| | | dischargeWard: "å
ç§äºç
åº", |
| | | fillTime: "2024-01-14 16:20:10", |
| | | processStatus: 0, |
| | | questionnaireId: 1002, |
| | | }, |
| | | { |
| | | id: 3, |
| | | responsibilityDept: "æ®å¤ç§", |
| | | unsatisfactoryDetail: "æ¯åæ¢è¯ä¸åæ¶ï¼ä¼¤å£ç¼çæ¶æ²¡æåæ¶å¤ç", |
| | | patientName: "çå
ç", |
| | | gender: 1, |
| | | age: 52, |
| | | phone: "137****9012", |
| | | dischargeDept: "æ®å¤ç§", |
| | | dischargeWard: "å¤ç§ä¸ç
åº", |
| | | fillTime: "2024-01-13 09:15:45", |
| | | processStatus: 1, |
| | | questionnaireId: 1003, |
| | | }, |
| | | { |
| | | id: 4, |
| | | responsibilityDept: "骨ç§", |
| | | unsatisfactoryDetail: "åº·å¤æå¯¼ä¸å¤ä¸ä¸ï¼å¯¹æ¢å¤è¿ç¨æè¿°ä¸æ¸
æ¥", |
| | | patientName: "å女士", |
| | | gender: 0, |
| | | age: 65, |
| | | phone: "136****3456", |
| | | dischargeDept: "骨ç§", |
| | | dischargeWard: "å¤ç§äºç
åº", |
| | | fillTime: "2024-01-12 14:40:30", |
| | | processStatus: 0, |
| | | questionnaireId: 1004, |
| | | }, |
| | | { |
| | | id: 5, |
| | | responsibilityDept: "å¦äº§ç§", |
| | | unsatisfactoryDetail: |
| | | "äº§åæ£æ¥æéæ¶é´è¿é¿ï¼çå¾
æé´æ²¡æä¼æ¯åº§ä½", |
| | | patientName: "é女士", |
| | | gender: 0, |
| | | age: 28, |
| | | phone: "135****7890", |
| | | dischargeDept: "å¦äº§ç§", |
| | | dischargeWard: "å¦äº§ç§ç
åº", |
| | | fillTime: "2024-01-11 11:25:15", |
| | | processStatus: 2, |
| | | questionnaireId: 1005, |
| | | }, |
| | | { |
| | | id: 6, |
| | | responsibilityDept: "å¿ç§", |
| | | unsatisfactoryDetail: |
| | | "å¿ç«¥ç¨è¯åéäº¤ä»£ä¸æ¸
æ°ï¼ç¨è¯æ³¨æäºé¡¹æ²¡æè¯´æ", |
| | | patientName: "èµµå®å®", |
| | | gender: 1, |
| | | age: 5, |
| | | phone: "134****1234", |
| | | dischargeDept: "å¿ç§", |
| | | dischargeWard: "å¿ç§ç
åº", |
| | | fillTime: "2024-01-10 15:50:20", |
| | | processStatus: 0, |
| | | questionnaireId: 1006, |
| | | }, |
| | | { |
| | | id: 7, |
| | | responsibilityDept: "æ¥è¯ç§", |
| | | unsatisfactoryDetail: "æ¥è¯çå¾
æ¶é´è¿é¿ï¼ç
æ
没æå¾å°åæ¶è¯ä¼°", |
| | | patientName: "åå
ç", |
| | | gender: 1, |
| | | age: 40, |
| | | phone: "133****5678", |
| | | dischargeDept: "æ¥è¯ç§", |
| | | dischargeWard: "æ¥è¯ç
åº", |
| | | fillTime: "2024-01-09 10:15:40", |
| | | processStatus: 0, |
| | | questionnaireId: 1007, |
| | | }, |
| | | { |
| | | id: 8, |
| | | responsibilityDept: "å¼å¸å
ç§", |
| | | unsatisfactoryDetail: "å»çå¼è¯è¾å¤ï¼è´¹ç¨è¾é«ï¼æ²¡æè¯´æå¿
è¦æ§", |
| | | patientName: "å¨å¥³å£«", |
| | | gender: 0, |
| | | age: 55, |
| | | phone: "132****9012", |
| | | dischargeDept: "å¼å¸å
ç§", |
| | | dischargeWard: "å
ç§ä¸ç
åº", |
| | | fillTime: "2024-01-08 13:30:55", |
| | | processStatus: 1, |
| | | questionnaireId: 1008, |
| | | }, |
| | | ]; |
| | | this.total = this.exceptionList.length; |
| | | resolve(); |
| | | }, 500); |
| | | }); |
| | | } finally { |
| | | this.loading = false; |
| | | } |
| | | }, |
| | | |
| | | // è·åç¶ææ ç¾ç±»å |
| | | getStatusTagType(status) { |
| | | switch (status) { |
| | | case 0: |
| | | return "warning"; // å¾
å¤ç |
| | | case 1: |
| | | return "primary"; // å¤çä¸ |
| | | case 2: |
| | | return "success"; // å·²å¤ç |
| | | default: |
| | | return "info"; |
| | | } |
| | | }, |
| | | |
| | | // è·åç¶æææ¬ |
| | | getStatusText(status) { |
| | | switch (status) { |
| | | case 0: |
| | | return "å¾
å¤ç"; |
| | | case 1: |
| | | return "å¤çä¸"; |
| | | case 2: |
| | | return "å·²å¤ç"; |
| | | default: |
| | | return "æªç¥"; |
| | | } |
| | | }, |
| | | |
| | | // å¤ççé |
| | | handleFilter() { |
| | | this.filterParams.pageNum = 1; |
| | | this.loadExceptionList(); |
| | | }, |
| | | |
| | | // éç½®çé |
| | | handleResetFilter() { |
| | | this.filterParams = { |
| | | deptId: "", |
| | | status: "", |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | }; |
| | | this.loadExceptionList(); |
| | | }, |
| | | |
| | | // å¤çéæ©åå |
| | | handleSelectionChange(selection) { |
| | | this.selectedExceptionIds = selection.map((item) => item.id); |
| | | }, |
| | | |
| | | // å¤çæ¹éæäº¤ |
| | | handleBatchSubmit() { |
| | | if (this.selectedExceptionIds.length === 0) { |
| | | this.$message.warning("请å
éæ©è¦å¤ççå¼å¸¸åé¦"); |
| | | return; |
| | | } |
| | | this.batchDialogVisible = true; |
| | | }, |
| | | |
| | | // è¿åå¼å¸¸å表 |
| | | handleGoBack() { |
| | | this.$router.push("/satisfaction/exception/list"); |
| | | }, |
| | | |
| | | // æ¥ç详æ
|
| | | handleViewDetail(row) { |
| | | this.selectedRecordId = row.id; |
| | | this.detailDialogTitle = `${row.patientName} - å¼å¸¸åé¦è¯¦æ
`; |
| | | this.detailDialogVisible = true; |
| | | }, |
| | | // å¤ç详æ
å¼¹æ¡å
³é |
| | | handleDetailDialogClose() { |
| | | this.detailDialogVisible = false; |
| | | this.selectedRecordId = null; |
| | | }, // å¤ç宿åçåè° |
| | | handleProcessed() { |
| | | // éæ°å è½½æ°æ® |
| | | this.loadExceptionList(); |
| | | }, |
| | | // å¤çå个å¼å¸¸ |
| | | handleProcess(row) { |
| | | this.currentExceptionId = row.id; |
| | | this.processForm = { |
| | | status: row.processStatus === 0 ? 1 : row.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; |
| | | this.loadExceptionList(); |
| | | } finally { |
| | | this.processing = false; |
| | | } |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // æäº¤æ¹éå¤ç |
| | | async submitBatchProcess() { |
| | | this.$refs.batchProcessForm.validate(async (valid) => { |
| | | if (valid) { |
| | | this.batchProcessing = true; |
| | | try { |
| | | // Mock APIè°ç¨ |
| | | await new Promise((resolve) => setTimeout(resolve, 1500)); |
| | | |
| | | this.$message.success( |
| | | `å·²æ¹éå¤ç ${this.selectedExceptionIds.length} æ¡å¼å¸¸åé¦` |
| | | ); |
| | | this.batchDialogVisible = false; |
| | | this.selectedExceptionIds = []; |
| | | this.loadExceptionList(); |
| | | } finally { |
| | | this.batchProcessing = false; |
| | | } |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // å页大å°åå |
| | | handleSizeChange(size) { |
| | | this.filterParams.pageSize = size; |
| | | this.filterParams.pageNum = 1; |
| | | this.loadExceptionList(); |
| | | }, |
| | | |
| | | // 页ç åå |
| | | handlePageChange(page) { |
| | | this.filterParams.pageNum = page; |
| | | this.loadExceptionList(); |
| | | }, |
| | | |
| | | // æä»¶ä¸ä¼ ç¸å
³æ¹æ³ |
| | | handlePreview(file) { |
| | | console.log("é¢è§æä»¶:", file); |
| | | }, |
| | | |
| | | handleRemove(file, fileList) { |
| | | console.log("ç§»é¤æä»¶:", file, fileList); |
| | | }, |
| | | |
| | | beforeRemove(file) { |
| | | return this.$confirm(`ç¡®å®ç§»é¤ ${file.name}ï¼`); |
| | | }, |
| | | |
| | | handleExceed(files, fileList) { |
| | | this.$message.warning( |
| | | `å½åéå¶éæ© 3 个æä»¶ï¼æ¬æ¬¡éæ©äº ${files.length} 个æä»¶ï¼å
±éæ©äº ${ |
| | | files.length + fileList.length |
| | | } 个æä»¶` |
| | | ); |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .batch-process { |
| | | padding: 20px; |
| | | background-color: #f5f7fa; |
| | | min-height: 100vh; |
| | | |
| | | .page-header { |
| | | margin-bottom: 20px; |
| | | padding: 20px; |
| | | background: linear-gradient(135deg, #5788fe 0%, #66b1ff 100%); |
| | | border-radius: 8px; |
| | | color: white; |
| | | |
| | | .header-content { |
| | | .page-title { |
| | | margin: 0 0 8px 0; |
| | | font-size: 20px; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | .page-description { |
| | | margin: 0 0 20px 0; |
| | | opacity: 0.9; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .header-actions { |
| | | display: flex; |
| | | gap: 10px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .list-section { |
| | | .filter-section { |
| | | margin-bottom: 20px; |
| | | |
| | | .filter-form { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | align-items: center; |
| | | |
| | | ::v-deep .el-form-item { |
| | | margin-bottom: 0; |
| | | margin-right: 20px; |
| | | |
| | | &:last-child { |
| | | margin-right: 0; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .exception-table { |
| | | ::v-deep .el-table__header-wrapper { |
| | | th { |
| | | background-color: #f8f9fa; |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | } |
| | | |
| | | .detail-content { |
| | | font-size: 13px; |
| | | color: #606266; |
| | | line-height: 1.5; |
| | | text-align: left; |
| | | } |
| | | |
| | | .patient-info { |
| | | .patient-item { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 5px; |
| | | padding: 2px 0; |
| | | |
| | | .label { |
| | | font-size: 12px; |
| | | color: #606266; |
| | | min-width: 40px; |
| | | } |
| | | |
| | | .value { |
| | | font-size: 13px; |
| | | color: #333; |
| | | font-weight: 500; |
| | | text-align: right; |
| | | flex: 1; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .discharge-info { |
| | | .info-item { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 5px; |
| | | padding: 2px 0; |
| | | |
| | | .label { |
| | | font-size: 12px; |
| | | color: #606266; |
| | | min-width: 50px; |
| | | } |
| | | |
| | | .value { |
| | | font-size: 13px; |
| | | color: #333; |
| | | font-weight: 500; |
| | | text-align: right; |
| | | flex: 1; |
| | | |
| | | &.time { |
| | | font-size: 12px; |
| | | color: #909399; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .pagination-section { |
| | | display: flex; |
| | | justify-content: center; |
| | | padding: 20px 0 0 0; |
| | | } |
| | | } |
| | | } |
| | | |
| | | @media (max-width: 768px) { |
| | | .batch-process { |
| | | padding: 10px; |
| | | |
| | | .page-header { |
| | | .header-actions { |
| | | flex-direction: column; |
| | | align-items: stretch; |
| | | } |
| | | } |
| | | |
| | | .list-section { |
| | | .filter-section { |
| | | .filter-form { |
| | | ::v-deep .el-form-item { |
| | | width: 100%; |
| | | margin-right: 0; |
| | | margin-bottom: 10px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <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> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="exception-list"> |
| | | <!-- 页颿 é¢ --> |
| | | <div class="page-header"> |
| | | <div class="header-content"> |
| | | <h2 class="page-title">满æåº¦å¼å¸¸å¤ç</h2> |
| | | <p class="page-description">çæ§åå¤ç满æåº¦é®å·ä¸çå¼å¸¸åé¦</p> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- æ¥è¯¢æ¡ä»¶åºå --> |
| | | <div class="search-section"> |
| | | <el-card shadow="never"> |
| | | <el-form |
| | | :model="queryParams" |
| | | ref="queryForm" |
| | | size="medium" |
| | | :inline="true" |
| | | label-width="120px" |
| | | class="search-form" |
| | | > |
| | | <el-form-item label="满æåº¦æ¨¡æ¿" prop="templateId"> |
| | | <el-select |
| | | v-model="queryParams.templateId" |
| | | placeholder="è¯·éæ©æ¨¡æ¿" |
| | | clearable |
| | | style="width: 200px" |
| | | > |
| | | <el-option |
| | | v-for="template in templateList" |
| | | :key="template.id" |
| | | :label="template.name" |
| | | :value="template.id" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="责任ç§å®¤" prop="deptIds"> |
| | | <el-select |
| | | v-model="queryParams.deptIds" |
| | | placeholder="è¯·éæ©è´£ä»»ç§å®¤" |
| | | clearable |
| | | filterable |
| | | multiple |
| | | collapse-tags |
| | | style="width: 300px" |
| | | > |
| | | <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="dateRange"> |
| | | <el-date-picker |
| | | v-model="queryParams.dateRange" |
| | | type="daterange" |
| | | range-separator="è³" |
| | | start-placeholder="å¼å§æ¥æ" |
| | | end-placeholder="ç»ææ¥æ" |
| | | value-format="yyyy-MM-dd" |
| | | :picker-options="pickerOptions" |
| | | style="width: 380px" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item> |
| | | <el-button |
| | | type="primary" |
| | | icon="el-icon-search" |
| | | @click="handleSearch" |
| | | :loading="loading" |
| | | > |
| | | æ¥è¯¢ |
| | | </el-button> |
| | | <el-button icon="el-icon-refresh" @click="handleReset"> |
| | | éç½® |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </el-card> |
| | | </div> |
| | | |
| | | <!-- æ¹éæä½ --> |
| | | <div class="batch-section"> |
| | | <el-card shadow="never"> |
| | | <div class="batch-actions"> |
| | | <el-button |
| | | type="primary" |
| | | icon="el-icon-s-operation" |
| | | :disabled="selectedIds.length === 0" |
| | | @click="handleBatchProcess" |
| | | > |
| | | æ¹éå¤ç ({{ selectedIds.length }}) |
| | | </el-button> |
| | | <el-button |
| | | type="info" |
| | | icon="el-icon-download" |
| | | @click="handleExport" |
| | | > |
| | | 导åºå¼å¸¸æ°æ® |
| | | </el-button> |
| | | <el-button |
| | | type="warning" |
| | | icon="el-icon-refresh-right" |
| | | @click="refreshData" |
| | | > |
| | | å·æ°æ°æ® |
| | | </el-button> |
| | | </div> |
| | | </el-card> |
| | | </div> |
| | | |
| | | <!-- å¼å¸¸ç»è®¡æ¦è§ --> |
| | | <div class="overview-section"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="6"> |
| | | <el-card shadow="never" class="stat-card"> |
| | | <div class="stat-content"> |
| | | <div class="stat-icon" style="background: #f0f9ff;"> |
| | | <i class="el-icon-s-claim" style="color: #5788FE;"></i> |
| | | </div> |
| | | <div class="stat-info"> |
| | | <div class="stat-title">æ»å¼å¸¸æ°é</div> |
| | | <div class="stat-value">{{ overviewData.totalExceptionCount }}</div> |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | </el-col> |
| | | <el-col :span="6"> |
| | | <el-card shadow="never" class="stat-card"> |
| | | <div class="stat-content"> |
| | | <div class="stat-icon" style="background: #f0f9ff;"> |
| | | <i class="el-icon-s-flag" style="color: #E6A23C;"></i> |
| | | </div> |
| | | <div class="stat-info"> |
| | | <div class="stat-title">å¾
å¤çå¼å¸¸</div> |
| | | <div class="stat-value">{{ overviewData.pendingCount }}</div> |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | </el-col> |
| | | <el-col :span="6"> |
| | | <el-card shadow="never" class="stat-card"> |
| | | <div class="stat-content"> |
| | | <div class="stat-icon" style="background: #f0f9ff;"> |
| | | <i class="el-icon-check" style="color: #67C23A;"></i> |
| | | </div> |
| | | <div class="stat-info"> |
| | | <div class="stat-title">å·²å¤çå¼å¸¸</div> |
| | | <div class="stat-value">{{ overviewData.processedCount }}</div> |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | </el-col> |
| | | <el-col :span="6"> |
| | | <el-card shadow="never" class="stat-card"> |
| | | <div class="stat-content"> |
| | | <div class="stat-icon" style="background: #f0f9ff;"> |
| | | <i class="el-icon-s-order" style="color: #909399;"></i> |
| | | </div> |
| | | <div class="stat-info"> |
| | | <div class="stat-title">仿¥å¤çæ°</div> |
| | | <div class="stat-value">{{ overviewData.todayProcessedCount }}</div> |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | |
| | | <!-- å¼å¸¸å表 --> |
| | | <div class="list-section"> |
| | | <el-card shadow="never"> |
| | | <el-table |
| | | v-loading="loading" |
| | | :data="exceptionList" |
| | | :border="true" |
| | | style="width: 100%" |
| | | @selection-change="handleSelectionChange" |
| | | class="exception-table" |
| | | > |
| | | <el-table-column |
| | | type="selection" |
| | | width="55" |
| | | align="center" |
| | | /> |
| | | |
| | | <el-table-column |
| | | label="åºå·" |
| | | type="index" |
| | | width="60" |
| | | align="center" |
| | | /> |
| | | |
| | | <el-table-column |
| | | label="é¢ç®å
容" |
| | | prop="questionContent" |
| | | min-width="300" |
| | | align="center" |
| | | > |
| | | <template slot-scope="{ row }"> |
| | | <div class="question-content"> |
| | | <span class="question-text">{{ row.questionContent }}</span> |
| | | <div class="question-tags"> |
| | | <el-tag |
| | | size="mini" |
| | | :type="getQuestionTypeTag(row.questionType)" |
| | | > |
| | | {{ row.questionType === 1 ? 'åéé¢' : 'å¤éé¢' }} |
| | | </el-tag> |
| | | <el-tag |
| | | size="mini" |
| | | type="info" |
| | | > |
| | | {{ row.templateName }} |
| | | </el-tag> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="è´è´£ç§å®¤" |
| | | prop="responsibilityDepts" |
| | | width="180" |
| | | align="center" |
| | | > |
| | | <template slot-scope="{ row }"> |
| | | <div class="dept-list"> |
| | | <el-tag |
| | | v-for="dept in row.responsibilityDepts" |
| | | :key="dept.id" |
| | | size="small" |
| | | type="primary" |
| | | class="dept-tag" |
| | | > |
| | | {{ dept.name }} |
| | | </el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="å¡«åæ
åµ" |
| | | width="200" |
| | | align="center" |
| | | > |
| | | <template slot-scope="{ row }"> |
| | | <div class="fill-statistics"> |
| | | <div class="stat-item"> |
| | | <span class="stat-label">ææå¡«åï¼</span> |
| | | <span class="stat-value">{{ row.validFillCount }}</span> |
| | | </div> |
| | | <div class="stat-item"> |
| | | <span class="stat-label">å¼å¸¸å¡«åï¼</span> |
| | | <span class="stat-value exception-count">{{ row.exceptionFillCount }}</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="å¼å¸¸ä»»å¡" |
| | | width="280" |
| | | align="center" |
| | | > |
| | | <template slot-scope="{ row }"> |
| | | <div class="exception-tasks"> |
| | | <div class="task-category"> |
| | | <div class="task-title">å·²å¤ç</div> |
| | | <div class="task-count processed">{{ row.processedCount }}</div> |
| | | </div> |
| | | <div class="task-category"> |
| | | <div class="task-title">å¾
å¤ç</div> |
| | | <div class="task-count pending">{{ row.pendingCount }}</div> |
| | | </div> |
| | | <div class="task-category"> |
| | | <div class="task-title">å¼å¸¸æ»æ°</div> |
| | | <div class="task-count total">{{ row.totalExceptionCount }}</div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="æè¿å¤ç" |
| | | prop="lastProcessTime" |
| | | width="180" |
| | | align="center" |
| | | > |
| | | <template slot-scope="{ row }"> |
| | | <div v-if="row.lastProcessTime" class="last-process"> |
| | | <div class="process-time">{{ row.lastProcessTime }}</div> |
| | | <div class="process-user">{{ row.lastProcessUser }}</div> |
| | | </div> |
| | | <span v-else class="no-process">ææ å¤çè®°å½</span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="æä½" |
| | | width="180" |
| | | align="center" |
| | | fixed="right" |
| | | > |
| | | <template slot-scope="{ row }"> |
| | | <!-- <el-button |
| | | type="primary" |
| | | size="small" |
| | | icon="el-icon-view" |
| | | @click="handleViewDetail(row)" |
| | | > |
| | | 详æ
|
| | | </el-button> --> |
| | | <el-button |
| | | type="warning" |
| | | size="small" |
| | | icon="el-icon-s-operation" |
| | | @click="handleBatchQuestion(row)" |
| | | > |
| | | æ¹éå¤ç |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <!-- å页 --> |
| | | <div class="pagination-section"> |
| | | <el-pagination |
| | | background |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | :current-page="queryParams.pageNum" |
| | | :page-size="queryParams.pageSize" |
| | | :page-sizes="[10, 20, 30, 50]" |
| | | :total="total" |
| | | @size-change="handleSizeChange" |
| | | @current-change="handlePageChange" |
| | | /> |
| | | </div> |
| | | </el-card> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'ExceptionList', |
| | | data() { |
| | | return { |
| | | // æ¥è¯¢åæ° |
| | | queryParams: { |
| | | templateId: '', |
| | | deptIds: [], |
| | | dateRange: [], |
| | | pageNum: 1, |
| | | pageSize: 10 |
| | | }, |
| | | |
| | | // å è½½ç¶æ |
| | | loading: false, |
| | | |
| | | // éä¸çID |
| | | selectedIds: [], |
| | | |
| | | // 模æ¿å表 |
| | | templateList: [ |
| | | { id: 1, name: 'åºé¢æ»¡æåº¦é®å·' }, |
| | | { id: 2, name: 'ä½é¢æ»¡æåº¦é®å·' }, |
| | | { id: 3, name: 'é¨è¯æ»¡æåº¦é®å·' }, |
| | | { id: 4, name: 'å¸¸ç¨æ»¡æåº¦é®å·' } |
| | | ], |
| | | |
| | | // ç§å®¤å表 |
| | | 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: 'å¼å¸å
ç§' }, |
| | | { id: 9, name: 'æ¶åå
ç§' }, |
| | | { id: 10, name: 'å
åæ³ç§' }, |
| | | { id: 11, name: 'è¾å
ç§' }, |
| | | { id: 12, name: 'è¿ç¤ç§' } |
| | | ], |
| | | |
| | | // å¼å¸¸åè¡¨æ°æ® |
| | | exceptionList: [], |
| | | total: 0, |
| | | |
| | | // ç»è®¡æ¦è§æ°æ® |
| | | overviewData: { |
| | | totalExceptionCount: 0, |
| | | pendingCount: 0, |
| | | processedCount: 0, |
| | | todayProcessedCount: 0 |
| | | }, |
| | | |
| | | // æ¥æéæ©å¨é项 |
| | | pickerOptions: { |
| | | shortcuts: [ |
| | | { |
| | | text: 'æè¿ä¸å¨', |
| | | onClick(picker) { |
| | | const end = new Date(); |
| | | const start = new Date(); |
| | | start.setTime(start.getTime() - 3600 * 1000 * 24 * 7); |
| | | picker.$emit('pick', [start, end]); |
| | | } |
| | | }, |
| | | { |
| | | text: 'æè¿ä¸ä¸ªæ', |
| | | onClick(picker) { |
| | | const end = new Date(); |
| | | const start = new Date(); |
| | | start.setTime(start.getTime() - 3600 * 1000 * 24 * 30); |
| | | picker.$emit('pick', [start, end]); |
| | | } |
| | | }, |
| | | { |
| | | text: 'æè¿ä¸ä¸ªæ', |
| | | onClick(picker) { |
| | | const end = new Date(); |
| | | const start = new Date(); |
| | | start.setTime(start.getTime() - 3600 * 1000 * 24 * 90); |
| | | picker.$emit('pick', [start, end]); |
| | | } |
| | | } |
| | | ], |
| | | disabledDate(time) { |
| | | return time.getTime() > Date.now(); |
| | | } |
| | | } |
| | | }; |
| | | }, |
| | | |
| | | mounted() { |
| | | this.loadData(); |
| | | }, |
| | | |
| | | methods: { |
| | | // å è½½æ°æ® |
| | | async loadData() { |
| | | this.loading = true; |
| | | try { |
| | | await Promise.all([ |
| | | this.loadExceptionList(), |
| | | this.loadOverviewData() |
| | | ]); |
| | | } finally { |
| | | this.loading = false; |
| | | } |
| | | }, |
| | | |
| | | // å è½½å¼å¸¸å表 |
| | | async loadExceptionList() { |
| | | return new Promise((resolve) => { |
| | | setTimeout(() => { |
| | | // Mock æ°æ® |
| | | this.exceptionList = [ |
| | | { |
| | | id: 1, |
| | | questionId: 101, |
| | | questionContent: 'æ¨å¯¹å»æ¤äººåçæå¡æåº¦æ¯å¦æ»¡æï¼', |
| | | questionType: 1, // 1: åéé¢, 2: å¤éé¢ |
| | | templateName: 'åºé¢æ»¡æåº¦é®å·', |
| | | responsibilityDepts: [ |
| | | { id: 1, name: 'å¿è¡ç®¡å
ç§' }, |
| | | { id: 2, name: 'ç¥ç»å
ç§' } |
| | | ], |
| | | validFillCount: 145, |
| | | exceptionFillCount: 8, |
| | | processedCount: 5, |
| | | pendingCount: 3, |
| | | totalExceptionCount: 8, |
| | | lastProcessTime: '2024-01-15 10:30:25', |
| | | lastProcessUser: 'å¼ å»ç' |
| | | }, |
| | | { |
| | | id: 2, |
| | | questionId: 102, |
| | | questionContent: 'æ¨å¯¹å»ççè¯çæ°´å¹³åææ¯è½åè¯ä»·å¦ä½ï¼', |
| | | questionType: 1, |
| | | templateName: 'ä½é¢æ»¡æåº¦é®å·', |
| | | responsibilityDepts: [ |
| | | { id: 3, name: 'æ®å¤ç§' }, |
| | | { id: 4, name: '骨ç§' } |
| | | ], |
| | | validFillCount: 120, |
| | | exceptionFillCount: 12, |
| | | processedCount: 8, |
| | | pendingCount: 4, |
| | | totalExceptionCount: 12, |
| | | lastProcessTime: '2024-01-14 16:20:10', |
| | | lastProcessUser: 'ææ¤å£«é¿' |
| | | }, |
| | | { |
| | | id: 3, |
| | | questionId: 103, |
| | | questionContent: 'æ¨å¯¹å»é¢çç¯å¢åå«çç¶åµæ¯å¦æ»¡æï¼', |
| | | questionType: 1, |
| | | templateName: 'é¨è¯æ»¡æåº¦é®å·', |
| | | responsibilityDepts: [ |
| | | { id: 5, name: 'å¦äº§ç§' }, |
| | | { id: 6, name: 'å¿ç§' }, |
| | | { id: 7, name: 'æ¥è¯ç§' } |
| | | ], |
| | | validFillCount: 180, |
| | | exceptionFillCount: 15, |
| | | processedCount: 10, |
| | | pendingCount: 5, |
| | | totalExceptionCount: 15, |
| | | lastProcessTime: '2024-01-13 09:15:45', |
| | | lastProcessUser: 'ç主任' |
| | | }, |
| | | { |
| | | id: 4, |
| | | questionId: 104, |
| | | questionContent: 'æ¨è®¤ä¸ºå»æ¤äººå䏿¨çæ²éæ¯å¦å
åï¼', |
| | | questionType: 1, |
| | | templateName: 'å¸¸ç¨æ»¡æåº¦é®å·', |
| | | responsibilityDepts: [ |
| | | { id: 8, name: 'å¼å¸å
ç§' }, |
| | | { id: 9, name: 'æ¶åå
ç§' } |
| | | ], |
| | | validFillCount: 95, |
| | | exceptionFillCount: 6, |
| | | processedCount: 4, |
| | | pendingCount: 2, |
| | | totalExceptionCount: 6, |
| | | lastProcessTime: '2024-01-12 14:40:30', |
| | | lastProcessUser: 'èµµå»ç' |
| | | }, |
| | | { |
| | | id: 5, |
| | | questionId: 105, |
| | | questionContent: 'æ¨å¯¹çå¾
å°±è¯åæ²»ççæ¶é´æ¯å¦æ»¡æï¼', |
| | | questionType: 1, |
| | | templateName: 'ä½é¢æ»¡æåº¦é®å·', |
| | | responsibilityDepts: [ |
| | | { id: 10, name: 'å
åæ³ç§' }, |
| | | { id: 11, name: 'è¾å
ç§' } |
| | | ], |
| | | validFillCount: 200, |
| | | exceptionFillCount: 25, |
| | | processedCount: 15, |
| | | pendingCount: 10, |
| | | totalExceptionCount: 25, |
| | | lastProcessTime: '2024-01-11 11:25:15', |
| | | lastProcessUser: '忤士' |
| | | }, |
| | | { |
| | | id: 6, |
| | | questionId: 106, |
| | | questionContent: 'æ¨å¯¹å»é¢æ¶è´¹çéæåº¦ååçæ§è¯ä»·å¦ä½ï¼', |
| | | questionType: 1, |
| | | templateName: 'é¨è¯æ»¡æåº¦é®å·', |
| | | responsibilityDepts: [ |
| | | { id: 12, name: 'è¿ç¤ç§' } |
| | | ], |
| | | validFillCount: 160, |
| | | exceptionFillCount: 18, |
| | | processedCount: 12, |
| | | pendingCount: 6, |
| | | totalExceptionCount: 18, |
| | | lastProcessTime: '2024-01-10 15:50:20', |
| | | lastProcessUser: 'å¨å»ç' |
| | | }, |
| | | { |
| | | id: 7, |
| | | questionId: 107, |
| | | questionContent: 'æ¨ä¼åäº²åæ¨èæä»¬å»é¢åï¼', |
| | | questionType: 1, |
| | | templateName: 'åºé¢æ»¡æåº¦é®å·', |
| | | responsibilityDepts: [ |
| | | { id: 1, name: 'å¿è¡ç®¡å
ç§' }, |
| | | { id: 8, name: 'å¼å¸å
ç§' } |
| | | ], |
| | | validFillCount: 110, |
| | | exceptionFillCount: 7, |
| | | processedCount: 5, |
| | | pendingCount: 2, |
| | | totalExceptionCount: 7, |
| | | lastProcessTime: '2024-01-09 10:15:40', |
| | | lastProcessUser: 'å´ä¸»ä»»' |
| | | }, |
| | | { |
| | | id: 8, |
| | | questionId: 108, |
| | | questionContent: 'æ¨å¯¹ä»¥ä¸åªäºæ¹é¢æ¯è¾æ»¡æï¼å¤éï¼ï¼', |
| | | questionType: 2, |
| | | templateName: 'å¸¸ç¨æ»¡æåº¦é®å·', |
| | | responsibilityDepts: [ |
| | | { id: 2, name: 'ç¥ç»å
ç§' }, |
| | | { id: 3, name: 'æ®å¤ç§' }, |
| | | { id: 5, name: 'å¦äº§ç§' } |
| | | ], |
| | | validFillCount: 135, |
| | | exceptionFillCount: 9, |
| | | processedCount: 6, |
| | | pendingCount: 3, |
| | | totalExceptionCount: 9, |
| | | lastProcessTime: '2024-01-08 13:30:55', |
| | | lastProcessUser: 'éå»ç' |
| | | } |
| | | ]; |
| | | this.total = this.exceptionList.length; |
| | | resolve(); |
| | | }, 500); |
| | | }); |
| | | }, |
| | | |
| | | // å è½½æ¦è§æ°æ® |
| | | async loadOverviewData() { |
| | | return new Promise((resolve) => { |
| | | setTimeout(() => { |
| | | // 计ç®ç»è®¡æ°æ® |
| | | const totalExceptionCount = this.exceptionList.reduce((sum, item) => sum + item.totalExceptionCount, 0); |
| | | const pendingCount = this.exceptionList.reduce((sum, item) => sum + item.pendingCount, 0); |
| | | const processedCount = this.exceptionList.reduce((sum, item) => sum + item.processedCount, 0); |
| | | |
| | | this.overviewData = { |
| | | totalExceptionCount, |
| | | pendingCount, |
| | | processedCount, |
| | | todayProcessedCount: 8 // 仿¥å¤çæ° mock |
| | | }; |
| | | resolve(); |
| | | }, 300); |
| | | }); |
| | | }, |
| | | |
| | | // è·åé¢ç®ç±»åæ ç¾æ ·å¼ |
| | | getQuestionTypeTag(type) { |
| | | return type === 1 ? 'primary' : 'success'; |
| | | }, |
| | | |
| | | // å¤çæ¥è¯¢ |
| | | handleSearch() { |
| | | this.queryParams.pageNum = 1; |
| | | this.loadData(); |
| | | }, |
| | | |
| | | // å¤çéç½® |
| | | handleReset() { |
| | | this.$refs.queryForm.resetFields(); |
| | | this.queryParams.dateRange = []; |
| | | this.queryParams.pageNum = 1; |
| | | this.loadData(); |
| | | }, |
| | | |
| | | // å¤çæ¹éå¤ç |
| | | handleBatchProcess() { |
| | | if (this.selectedIds.length === 0) { |
| | | this.$message.warning('请å
éæ©è¦å¤ççå¼å¸¸é¢ç®'); |
| | | return; |
| | | } |
| | | |
| | | // è·³è½¬å°æ¹éå¤çé¡µé¢ |
| | | this.$router.push({ |
| | | path: '/satisfaction/exception/batch-process', |
| | | query: { |
| | | questionIds: this.selectedIds.join(',') |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // å¤çå¯¼åº |
| | | handleExport() { |
| | | this.$message.success('导åºåè½å¼åä¸...'); |
| | | }, |
| | | |
| | | // å·æ°æ°æ® |
| | | refreshData() { |
| | | this.loadData(); |
| | | this.$message.success('æ°æ®å·²å·æ°'); |
| | | }, |
| | | |
| | | // å¤çéæ©åå |
| | | handleSelectionChange(selection) { |
| | | this.selectedIds = selection.map(item => item.questionId); |
| | | }, |
| | | |
| | | // å¤çæ¥ç详æ
|
| | | handleViewDetail(row) { |
| | | this.$router.push({ |
| | | path: '/satisfaction/exception/detail', |
| | | query: { |
| | | id: row.questionId |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // å¤çå个é¢ç®æ¹éå¤ç |
| | | handleBatchQuestion(row) { |
| | | this.$router.push({ |
| | | path: '/Intelligentcenter/batch', |
| | | query: { |
| | | questionId: row.questionId |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // å¤çå页大å°åå |
| | | handleSizeChange(size) { |
| | | this.queryParams.pageSize = size; |
| | | this.queryParams.pageNum = 1; |
| | | this.loadExceptionList(); |
| | | }, |
| | | |
| | | // å¤ç页ç åå |
| | | handlePageChange(page) { |
| | | this.queryParams.pageNum = page; |
| | | this.loadExceptionList(); |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .exception-list { |
| | | padding: 20px; |
| | | background-color: #f5f7fa; |
| | | min-height: 100vh; |
| | | |
| | | .page-header { |
| | | margin-bottom: 20px; |
| | | padding: 20px; |
| | | background: linear-gradient(135deg, #5788FE 0%, #66b1ff 100%); |
| | | border-radius: 8px; |
| | | color: white; |
| | | |
| | | .header-content { |
| | | .page-title { |
| | | margin: 0 0 8px 0; |
| | | font-size: 20px; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | .page-description { |
| | | margin: 0; |
| | | opacity: 0.9; |
| | | font-size: 14px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .search-section { |
| | | margin-bottom: 20px; |
| | | |
| | | .search-form { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | align-items: center; |
| | | |
| | | ::v-deep .el-form-item { |
| | | margin-bottom: 0; |
| | | margin-right: 20px; |
| | | |
| | | &:last-child { |
| | | margin-right: 0; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .batch-section { |
| | | margin-bottom: 20px; |
| | | |
| | | .batch-actions { |
| | | display: flex; |
| | | gap: 10px; |
| | | align-items: center; |
| | | } |
| | | } |
| | | |
| | | .overview-section { |
| | | margin-bottom: 20px; |
| | | |
| | | .stat-card { |
| | | .stat-content { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 20px; |
| | | |
| | | .stat-icon { |
| | | width: 60px; |
| | | height: 60px; |
| | | border-radius: 12px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | |
| | | i { |
| | | font-size: 28px; |
| | | } |
| | | } |
| | | |
| | | .stat-info { |
| | | flex: 1; |
| | | |
| | | .stat-title { |
| | | font-size: 14px; |
| | | color: #606266; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .stat-value { |
| | | font-size: 24px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .list-section { |
| | | .exception-table { |
| | | ::v-deep .el-table__header-wrapper { |
| | | th { |
| | | background-color: #f8f9fa; |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | } |
| | | |
| | | .question-content { |
| | | .question-text { |
| | | display: block; |
| | | font-size: 14px; |
| | | color: #303133; |
| | | margin-bottom: 8px; |
| | | line-height: 1.5; |
| | | } |
| | | |
| | | .question-tags { |
| | | display: flex; |
| | | gap: 5px; |
| | | justify-content: center; |
| | | } |
| | | } |
| | | |
| | | .dept-list { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 5px; |
| | | align-items: center; |
| | | |
| | | .dept-tag { |
| | | margin: 2px 0; |
| | | } |
| | | } |
| | | |
| | | .fill-statistics { |
| | | .stat-item { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 5px; |
| | | padding: 2px 0; |
| | | |
| | | .stat-label { |
| | | font-size: 12px; |
| | | color: #606266; |
| | | } |
| | | |
| | | .stat-value { |
| | | font-size: 14px; |
| | | font-weight: 500; |
| | | color: #333; |
| | | } |
| | | |
| | | .exception-count { |
| | | color: #e6a23c; |
| | | font-weight: 600; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .exception-tasks { |
| | | display: flex; |
| | | justify-content: space-around; |
| | | align-items: center; |
| | | |
| | | .task-category { |
| | | text-align: center; |
| | | padding: 5px 8px; |
| | | border-radius: 6px; |
| | | min-width: 70px; |
| | | |
| | | .task-title { |
| | | font-size: 12px; |
| | | color: #606266; |
| | | margin-bottom: 5px; |
| | | } |
| | | |
| | | .task-count { |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | line-height: 1; |
| | | |
| | | &.processed { |
| | | color: #67c23a; |
| | | } |
| | | |
| | | &.pending { |
| | | color: #e6a23c; |
| | | } |
| | | |
| | | &.total { |
| | | color: #5788FE; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .last-process { |
| | | .process-time { |
| | | font-size: 12px; |
| | | color: #606266; |
| | | margin-bottom: 4px; |
| | | } |
| | | |
| | | .process-user { |
| | | font-size: 13px; |
| | | color: #5788FE; |
| | | font-weight: 500; |
| | | } |
| | | } |
| | | |
| | | .no-process { |
| | | color: #909399; |
| | | font-style: italic; |
| | | } |
| | | } |
| | | |
| | | .pagination-section { |
| | | display: flex; |
| | | justify-content: center; |
| | | padding: 20px 0 0 0; |
| | | } |
| | | } |
| | | } |
| | | |
| | | @media (max-width: 768px) { |
| | | .exception-list { |
| | | padding: 10px; |
| | | |
| | | .search-section { |
| | | .search-form { |
| | | ::v-deep .el-form-item { |
| | | width: 100%; |
| | | margin-right: 0; |
| | | margin-bottom: 10px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .overview-section { |
| | | .el-row { |
| | | margin-left: 0; |
| | | margin-right: 0; |
| | | |
| | | .el-col { |
| | | padding-left: 0; |
| | | padding-right: 0; |
| | | margin-bottom: 10px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="satisfaction-exception-config"> |
| | | <!-- 页颿 é¢ --> |
| | | <div class="page-header"> |
| | | <div class="header-content"> |
| | | <h2 class="page-title">满æåº¦é¢ç®å¼å¸¸å¤çé
ç½®</h2> |
| | | <p class="page-description"> |
| | | åºäºæ¨¡æ¿é
置满æåº¦é¢ç®ç责任ç§å®¤åæ¥å¤ç§å®¤ |
| | | </p> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 模æ¿éæ©åºå --> |
| | | <div class="template-section"> |
| | | <el-card shadow="never"> |
| | | <div class="template-header"> |
| | | <h3 class="template-title">模æ¿éæ©</h3> |
| | | <p class="template-tip">请å
éæ©æ¨¡æ¿ç±»ååå
·ä½æ¨¡æ¿</p> |
| | | </div> |
| | | |
| | | <el-form |
| | | :model="templateForm" |
| | | :rules="templateRules" |
| | | ref="templateForm" |
| | | label-width="120px" |
| | | size="medium" |
| | | > |
| | | <el-row :gutter="20"> |
| | | <el-col :span="8"> |
| | | <el-form-item label="模æ¿ç±»å" prop="templateType"> |
| | | <el-select |
| | | v-model="templateForm.templateType" |
| | | placeholder="è¯·éæ©æ¨¡æ¿ç±»å" |
| | | clearable |
| | | @change="handleTemplateTypeChange" |
| | | style="width: 100%" |
| | | > |
| | | <el-option label="é®å·æ¨¡æ¿" :value="1" /> |
| | | <el-option label="è¯é³æ¨¡æ¿" :value="2" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | |
| | | <el-col :span="8"> |
| | | <el-form-item |
| | | label="éæ©æ¨¡æ¿" |
| | | prop="templateId" |
| | | :rules=" |
| | | templateForm.templateType |
| | | ? [ |
| | | { |
| | | required: true, |
| | | message: 'è¯·éæ©æ¨¡æ¿', |
| | | trigger: 'change', |
| | | }, |
| | | ] |
| | | : [] |
| | | " |
| | | > |
| | | <el-select |
| | | v-model="templateForm.templateId" |
| | | placeholder="è¯·éæ©æ¨¡æ¿" |
| | | clearable |
| | | filterable |
| | | @change="handleTemplateChange" |
| | | style="width: 100%" |
| | | > |
| | | <el-option |
| | | v-for="template in filteredTemplateOptions" |
| | | :key="template.id" |
| | | :label="template.templateName" |
| | | :value="template.id" |
| | | /> |
| | | <div |
| | | v-if="templateOptionsLoading" |
| | | slot="empty" |
| | | class="select-loading" |
| | | > |
| | | <i class="el-icon-loading"></i> |
| | | <span>å è½½ä¸...</span> |
| | | </div> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | |
| | | <el-col :span="8"> |
| | | <el-form-item> |
| | | <el-button |
| | | type="primary" |
| | | icon="el-icon-search" |
| | | @click="handleLoadTemplate" |
| | | :loading="templateLoading" |
| | | :disabled="!templateForm.templateId" |
| | | > |
| | | å 载模æ¿é¢ç® |
| | | </el-button> |
| | | <el-button icon="el-icon-refresh" @click="handleResetTemplate"> |
| | | éç½® |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | </el-card> |
| | | </div> |
| | | |
| | | <!-- 模æ¿ä¿¡æ¯ --> |
| | | <div v-if="currentTemplateInfo" class="template-info-section"> |
| | | <el-card shadow="never"> |
| | | <div class="template-info"> |
| | | <div class="info-left"> |
| | | <h3 class="template-name"> |
| | | {{ currentTemplateInfo.templateName }} |
| | | </h3> |
| | | <div class="template-meta"> |
| | | <span class="meta-item"> |
| | | <i class="el-icon-s-order"></i> |
| | | 模æ¿ç±»åï¼{{ |
| | | templateForm.templateType === 1 ? "é®å·æ¨¡æ¿" : "è¯é³æ¨¡æ¿" |
| | | }} |
| | | </span> |
| | | <span class="meta-item"> |
| | | <i class="el-icon-s-management"></i> |
| | | é¢ç®æ»æ°ï¼{{ currentTemplateInfo.questionCount || 0 }} |
| | | </span> |
| | | <span class="meta-item"> |
| | | <i class="el-icon-star-on"></i> |
| | | 满æåº¦é¢ç®ï¼{{ satisfactionQuestionsCount }} |
| | | </span> |
| | | </div> |
| | | </div> |
| | | <div class="info-right"> |
| | | <el-tag |
| | | :type=" |
| | | currentTemplateInfo.templateStatus === 1 ? 'success' : 'info' |
| | | " |
| | | size="medium" |
| | | > |
| | | {{ currentTemplateInfo.templateStatus === 1 ? "å¯ç¨" : "åç¨" }} |
| | | </el-tag> |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | </div> |
| | | |
| | | <!-- æç´¢åºåï¼é¢ç®çéï¼ --> |
| | | <div v-if="questionList.length > 0" class="search-section"> |
| | | <el-card shadow="never" class="search-container"> |
| | | <el-form :model="queryParams" :inline="true" size="medium"> |
| | | <el-form-item label="é®é¢ä¸»é¢"> |
| | | <el-input |
| | | v-model="queryParams.scriptTopic" |
| | | placeholder="请è¾å
¥é®é¢ä¸»é¢" |
| | | clearable |
| | | @keyup.enter.native="handleQuery" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="é®é¢å
容"> |
| | | <el-input |
| | | v-model="queryParams.scriptContent" |
| | | placeholder="请è¾å
¥é®é¢å
容" |
| | | clearable |
| | | @keyup.enter.native="handleQuery" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button |
| | | type="primary" |
| | | icon="el-icon-search" |
| | | @click="handleQuery" |
| | | > |
| | | çéé¢ç® |
| | | </el-button> |
| | | <el-button icon="el-icon-refresh" @click="resetQuery"> |
| | | éç½®çé |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </el-card> |
| | | </div> |
| | | |
| | | <!-- é
ç½®å表 --> |
| | | <div class="config-content"> |
| | | <!-- æ¹éæä½æ --> |
| | | <div v-if="questionList.length > 0" class="batch-actions-card"> |
| | | <el-card shadow="never"> |
| | | <div class="batch-actions"> |
| | | <el-button |
| | | type="success" |
| | | icon="el-icon-check" |
| | | :loading="batchSaving" |
| | | :disabled="!hasChanges || batchSaving" |
| | | @click="handleBatchSave" |
| | | size="medium" |
| | | > |
| | | {{ batchSaving ? "æ¹éä¿åä¸..." : "æ¹éä¿åé
ç½®" }} |
| | | </el-button> |
| | | <span v-if="changedCount > 0" class="change-count"> |
| | | æ {{ changedCount }} 项é
ç½®éè¦ä¿å |
| | | </span> |
| | | <div class="total-count"> |
| | | å
± {{ filteredQuestionList.length }} æ¡è®°å½ |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | </div> |
| | | |
| | | <div v-if="loading" class="loading-wrapper"> |
| | | <div class="loading-spinner"> |
| | | <i class="el-icon-loading"></i> |
| | | <span>å è½½ä¸...</span> |
| | | </div> |
| | | </div> |
| | | |
| | | <div |
| | | v-else-if="questionList.length === 0 && templateForm.templateId" |
| | | class="empty-wrapper" |
| | | > |
| | | <el-empty description="该模æ¿ä¸ææ 满æåº¦é¢ç®"> |
| | | <p class="empty-tip"> |
| | | è¯·éæ©å
¶ä»æ¨¡æ¿ææ£æ¥æ¨¡æ¿ä¸æ¯å¦å
嫿»¡æåº¦ç±»åé¢ç®ï¼åç±»ID: |
| | | 404,405,406ï¼ |
| | | </p> |
| | | </el-empty> |
| | | </div> |
| | | |
| | | <!-- ä¸è¡ä¸è¡çå¡çå表 --> |
| | | <div v-else-if="filteredQuestionList.length > 0" class="question-list"> |
| | | <div |
| | | v-for="(question, index) in filteredQuestionList" |
| | | :key="question.id" |
| | | class="question-item" |
| | | > |
| | | <el-card |
| | | shadow="hover" |
| | | class="question-card" |
| | | :class="{ 'has-changes': question.hasChanges }" |
| | | > |
| | | <!-- å¡çå¤´é¨ --> |
| | | <div class="card-header"> |
| | | <div class="header-left"> |
| | | <div class="question-index"> |
| | | <span class="index-number">{{ index + 1 }}</span> |
| | | <div class="index-line"></div> |
| | | </div> |
| | | <div class="question-basic-info"> |
| | | <div class="question-title-section"> |
| | | <h3 class="question-topic" :title="question.scriptTopic"> |
| | | {{ question.scriptTopic || "æ 主é¢" }} |
| | | </h3> |
| | | <div class="question-tags"> |
| | | <dict-tag |
| | | :options="askvaluetype" |
| | | :value="question.scriptType" |
| | | size="small" |
| | | /> |
| | | <el-tag |
| | | v-if="question.targetname" |
| | | size="small" |
| | | type="info" |
| | | > |
| | | {{ question.targetname }} |
| | | </el-tag> |
| | | </div> |
| | | </div> |
| | | <div class="question-content-section"> |
| | | <span class="content-label">é¢ç®å
容ï¼</span> |
| | | <span class="content-text">{{ |
| | | question.scriptContent |
| | | }}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="header-right"> |
| | | <!-- å¼å¸¸éé¡¹ç¶æ --> |
| | | <div |
| | | class="option-status" |
| | | v-if=" |
| | | templateForm.templateType != 3 && |
| | | templateForm.templateType != 4 |
| | | " |
| | | > |
| | | <el-tooltip |
| | | :content=" |
| | | checkHasAbnormalOptions(question) |
| | | ? 'å·²æå¼å¸¸é项' |
| | | : 'ææ å¼å¸¸é项' |
| | | " |
| | | placement="top" |
| | | > |
| | | <el-tag |
| | | :type=" |
| | | checkHasAbnormalOptions(question) ? 'success' : 'danger' |
| | | " |
| | | size="small" |
| | | class="status-tag" |
| | | > |
| | | <i |
| | | :class=" |
| | | checkHasAbnormalOptions(question) |
| | | ? 'el-icon-success' |
| | | : 'el-icon-warning' |
| | | " |
| | | ></i> |
| | | {{ |
| | | checkHasAbnormalOptions(question) |
| | | ? "å¼å¸¸é项已é
ç½®" |
| | | : "æ å¼å¸¸é项" |
| | | }} |
| | | </el-tag> |
| | | </el-tooltip> |
| | | </div> |
| | | |
| | | <el-button |
| | | type="text" |
| | | icon="el-icon-view" |
| | | @click="previewQuestion(question)" |
| | | size="small" |
| | | > |
| | | é¢è§ |
| | | </el-button> |
| | | |
| | | <!-- æ·»å é
ç½®é项æé® --> |
| | | <el-button |
| | | v-if=" |
| | | templateForm.templateType != 3 && |
| | | templateForm.templateType != 4 |
| | | " |
| | | type="text" |
| | | icon="el-icon-setting" |
| | | @click="openOptionDialog(question)" |
| | | size="small" |
| | | > |
| | | é
ç½®é项 |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- å¼å¸¸å¤çé
ç½® --> |
| | | <div class="config-section"> |
| | | <div class="config-title"> |
| | | <i class="el-icon-setting"></i> |
| | | <span>å¼å¸¸å¤çé
ç½®</span> |
| | | </div> |
| | | |
| | | <el-form |
| | | :model="question.exceptionConfig" |
| | | :rules="configRules" |
| | | ref="configForm" |
| | | label-width="100px" |
| | | size="small" |
| | | class="config-form" |
| | | > |
| | | <div class="config-fields"> |
| | | <!-- 责任ç§å®¤ï¼å¤éï¼ --> |
| | | <div class="config-field"> |
| | | <el-form-item |
| | | label="责任ç§å®¤" |
| | | prop="responsibilityDept" |
| | | class="config-item" |
| | | > |
| | | <el-select |
| | | v-model="question.exceptionConfig.responsibilityDept" |
| | | placeholder="è¯·éæ©è´£ä»»ç§å®¤" |
| | | filterable |
| | | clearable |
| | | multiple |
| | | style="width: 100%" |
| | | @change="handleConfigChange(question)" |
| | | > |
| | | <el-option |
| | | v-for="dept in deptOptions" |
| | | :key="dept.id" |
| | | :label="dept.label" |
| | | :value="dept.deptCode" |
| | | /> |
| | | </el-select> |
| | | <div class="config-tip"> |
| | | è´è´£å¤ç该é¢ç®åé¦çç§å®¤ï¼å¯å¤é |
| | | </div> |
| | | </el-form-item> |
| | | </div> |
| | | |
| | | <!-- æ¥å¤ç§å®¤ï¼å¤éï¼ --> |
| | | <div class="config-field"> |
| | | <el-form-item |
| | | label="æ¥å¤ç§å®¤" |
| | | prop="reportDept" |
| | | class="config-item" |
| | | > |
| | | <el-select |
| | | v-model="question.exceptionConfig.reportDept" |
| | | placeholder="è¯·éæ©æ¥å¤ç§å®¤" |
| | | filterable |
| | | clearable |
| | | multiple |
| | | style="width: 100%" |
| | | @change="handleConfigChange(question)" |
| | | > |
| | | <el-option |
| | | v-for="dept in deptOptions" |
| | | :key="dept.id" |
| | | :label="dept.label" |
| | | :value="dept.deptCode" |
| | | /> |
| | | </el-select> |
| | | <div class="config-tip"> |
| | | éè¦æ¥æ¶å¼å¸¸åé¦çç§å®¤ï¼å¯å¤é |
| | | </div> |
| | | </el-form-item> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- å½åé
ç½®ä¿¡æ¯ --> |
| | | <div v-if="question.hasChanges" class="current-config"> |
| | | <div class="config-preview"> |
| | | <div class="preview-item"> |
| | | <span class="preview-label">责任ç§å®¤ï¼</span> |
| | | <span class="preview-value"> |
| | | {{ |
| | | getDeptNames( |
| | | question.exceptionConfig.responsibilityDept || [] |
| | | ).join(", ") |
| | | }} |
| | | </span> |
| | | </div> |
| | | <div class="preview-item"> |
| | | <span class="preview-label">æ¥å¤ç§å®¤ï¼</span> |
| | | <span class="preview-value"> |
| | | {{ |
| | | getDeptNames( |
| | | question.exceptionConfig.reportDept || [] |
| | | ).join(", ") |
| | | }} |
| | | </span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- é
ç½®ç¶æåæä½æé® --> |
| | | <div class="config-footer"> |
| | | <div v-if="question.saveStatus" class="save-status"> |
| | | <el-alert |
| | | :type="question.saveStatus.type" |
| | | :title="question.saveStatus.message" |
| | | :closable="false" |
| | | show-icon |
| | | :effect=" |
| | | question.saveStatus.type === 'success' |
| | | ? 'dark' |
| | | : 'light' |
| | | " |
| | | size="small" |
| | | /> |
| | | </div> |
| | | |
| | | <div class="config-actions"> |
| | | <el-button |
| | | type="primary" |
| | | :loading="question.saving" |
| | | :disabled="!question.hasChanges" |
| | | @click="saveSingleConfig(question)" |
| | | size="small" |
| | | icon="el-icon-check" |
| | | > |
| | | {{ question.saving ? "ä¿åä¸..." : "ä¿åé
ç½®" }} |
| | | </el-button> |
| | | <el-button |
| | | v-if="question.hasChanges" |
| | | type="text" |
| | | @click="resetSingleConfig(question)" |
| | | size="small" |
| | | > |
| | | éç½® |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | </el-form> |
| | | </div> |
| | | </el-card> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <!-- é项é
ç½®å¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | title="é项å¼å¸¸ç¶æé
ç½®" |
| | | :visible.sync="optionDialogVisible" |
| | | width="700px" |
| | | center |
| | | :close-on-click-modal="false" |
| | | > |
| | | <div v-if="editingQuestion" class="option-config-wrapper"> |
| | | <div class="dialog-header"> |
| | | <h4>{{ editingQuestion.scriptTopic || 'æ 主é¢' }}</h4> |
| | | <p class="dialog-subtitle">{{ editingQuestion.scriptContent }}</p> |
| | | </div> |
| | | |
| | | <div class="option-list"> |
| | | <el-alert |
| | | v-if="!currentOptions.some(opt => opt.isabnormal === 1)" |
| | | title="请è³å°è®¾ç½®ä¸ä¸ªå¼å¸¸éé¡¹ï¼æ 记为å¼å¸¸ï¼" |
| | | type="warning" |
| | | :closable="false" |
| | | show-icon |
| | | style="margin-bottom: 20px;" |
| | | /> |
| | | |
| | | <div v-for="(option, index) in currentOptions" :key="index" class="option-item"> |
| | | <el-form |
| | | :model="option" |
| | | :rules="optionRules" |
| | | ref="optionForm" |
| | | size="small" |
| | | class="option-form" |
| | | > |
| | | <el-row :gutter="12" align="middle"> |
| | | <el-col :span="2"> |
| | | <div class="option-index">#{{ index + 1 }}</div> |
| | | </el-col> |
| | | |
| | | <el-col :span="12"> |
| | | <el-form-item prop="targetvalue"> |
| | | <el-input |
| | | v-model="option.targetvalue" |
| | | placeholder="请è¾å
¥é项å
容" |
| | | clearable |
| | | maxlength="200" |
| | | show-word-limit |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | |
| | | <el-col :span="6"> |
| | | <el-form-item prop="isabnormal"> |
| | | <el-select |
| | | v-model="option.isabnormal" |
| | | placeholder="éæ©ç¶æ" |
| | | style="width: 100%" |
| | | > |
| | | <el-option |
| | | v-for="status in abnormalOptions" |
| | | :key="status.value" |
| | | :label="status.label" |
| | | :value="status.value" |
| | | > |
| | | <el-tag :type="status.type" size="small">{{ status.label }}</el-tag> |
| | | </el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | |
| | | <el-col :span="4"> |
| | | <el-button |
| | | type="danger" |
| | | icon="el-icon-delete" |
| | | @click="removeOption(index)" |
| | | size="small" |
| | | circle |
| | | plain |
| | | /> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | </div> |
| | | |
| | | <!-- <el-button |
| | | type="primary" |
| | | icon="el-icon-plus" |
| | | @click="addNewOption" |
| | | size="small" |
| | | plain |
| | | style="width: 100%; margin-top: 10px;" |
| | | > |
| | | æ·»å é项 |
| | | </el-button> --> |
| | | </div> |
| | | </div> |
| | | |
| | | <span slot="footer" class="dialog-footer"> |
| | | <el-button @click="optionDialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="saveOptions" :loading="savingOptions"> |
| | | ä¿åé
ç½® |
| | | </el-button> |
| | | </span> |
| | | </el-dialog> |
| | | <!-- é¢ç®é¢è§å¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | title="é¢ç®é¢è§" |
| | | :visible.sync="previewVisible" |
| | | width="600px" |
| | | center |
| | | > |
| | | <div v-if="currentPreview" class="preview-wrapper"> |
| | | <div class="preview-header"> |
| | | <h4>{{ currentPreview.scriptTopic || "æ 主é¢" }}</h4> |
| | | <div class="preview-tags"> |
| | | <dict-tag |
| | | :options="askvaluetype" |
| | | :value="currentPreview.scriptType" |
| | | size="small" |
| | | /> |
| | | <el-tag v-if="currentPreview.targetname" size="small" type="info"> |
| | | {{ currentPreview.targetname }} |
| | | </el-tag> |
| | | </div> |
| | | </div> |
| | | <!-- 模æ¿é¢ç®å±ç¤º --> |
| | | |
| | | <div class="preview-content" v-if="templateForm.templateType == 1"> |
| | | <p class="preview-question">{{ currentPreview.scriptContent }}</p> |
| | | |
| | | <div |
| | | v-if=" |
| | | currentPreview.scriptType != 3 && currentPreview.scriptType != 4 |
| | | " |
| | | class="preview-options" |
| | | > |
| | | <el-radio-group v-model="previewAnswer"> |
| | | <el-radio |
| | | v-for="( |
| | | option, idx |
| | | ) in currentPreview.svyLibTemplateTargetoptions || []" |
| | | :key="idx" |
| | | :label="option.optioncontent" |
| | | class="option-item" |
| | | > |
| | | {{ option.optioncontent }} |
| | | </el-radio> |
| | | </el-radio-group> |
| | | </div> |
| | | |
| | | <div v-else class="preview-textarea"> |
| | | <el-input |
| | | type="textarea" |
| | | placeholder="请è¾å
¥åç" |
| | | v-model="previewAnswer" |
| | | :rows="4" |
| | | /> |
| | | </div> |
| | | </div> |
| | | <!-- è¯é³é¢ç®å±ç¤º --> |
| | | <div class="preview-content" v-else> |
| | | <p class="preview-question">{{ currentPreview.scriptContent }}</p> |
| | | |
| | | <div |
| | | v-if=" |
| | | currentPreview.scriptType != 3 && currentPreview.scriptType != 4 |
| | | " |
| | | class="preview-options" |
| | | > |
| | | <el-radio-group v-model="previewAnswer"> |
| | | <el-radio |
| | | v-for="( |
| | | option, idx |
| | | ) in currentPreview.ivrLibaScriptTargetoptionList || []" |
| | | :key="idx" |
| | | :label="option.targetvalue" |
| | | class="option-item" |
| | | > |
| | | {{ option.targetvalue }} |
| | | </el-radio> |
| | | </el-radio-group> |
| | | </div> |
| | | |
| | | <div v-else class="preview-textarea"> |
| | | <el-input |
| | | type="textarea" |
| | | placeholder="请è¾å
¥åç" |
| | | v-model="previewAnswer" |
| | | :rows="4" |
| | | /> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <span slot="footer" class="dialog-footer"> |
| | | <el-button @click="previewVisible = false">å
³é</el-button> |
| | | </span> |
| | | </el-dialog> |
| | | |
| | | <!-- ä¿åæåæç¤º --> |
| | | <el-dialog |
| | | title="ä¿åæå" |
| | | :visible.sync="saveSuccessVisible" |
| | | width="400px" |
| | | center |
| | | > |
| | | <div class="success-content"> |
| | | <i class="el-icon-success success-icon"></i> |
| | | <p class="success-text">é
置已æåä¿åï¼</p> |
| | | </div> |
| | | <span slot="footer" class="dialog-footer"> |
| | | <el-button type="primary" @click="saveSuccessVisible = false" |
| | | >ç¡®å®</el-button |
| | | > |
| | | </span> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { |
| | | compileissue, |
| | | compileQtemplate, |
| | | compileFollowup, |
| | | getQtemplatelist, |
| | | getFollowuplist, |
| | | getvFollowup, |
| | | getQtemplateobj, |
| | | selectInfoByConditiony, |
| | | } from "@/api/AiCentre/index"; |
| | | import { deptTreeSelect } from "@/api/system/user"; |
| | | import store from "@/store"; |
| | | import Pagination from "@/components/Pagination"; |
| | | |
| | | export default { |
| | | name: "SatisfactionExceptionConfig", |
| | | components: { Pagination }, |
| | | data() { |
| | | return { |
| | | // 模æ¿è¡¨å |
| | | templateForm: { |
| | | templateType: "", |
| | | templateId: "", |
| | | }, |
| | | templateRules: { |
| | | templateType: [ |
| | | { required: true, message: "è¯·éæ©æ¨¡æ¿ç±»å", trigger: "change" }, |
| | | ], |
| | | }, |
| | | // é项管çç¸å
³ |
| | | optionDialogVisible: false, |
| | | currentOptions: [], |
| | | editingQuestion: null, |
| | | optionRules: { |
| | | targetvalue: [ |
| | | { required: true, message: "请è¾å
¥é项å
容", trigger: "blur" }, |
| | | ], |
| | | isabnormal: [ |
| | | { required: true, message: "è¯·éæ©å¼å¸¸ç¶æ", trigger: "change" }, |
| | | ], |
| | | }, |
| | | |
| | | // å¼å¸¸ç¶æé项 |
| | | abnormalOptions: [ |
| | | { label: "æ£å¸¸", value: 0, type: "success" }, |
| | | { label: "å¼å¸¸", value: 1, type: "danger" }, |
| | | { label: "è¦å", value: 2, type: "warning" }, |
| | | ], |
| | | // 模æ¿é项 |
| | | questionnaireTemplates: [], // é®å·æ¨¡æ¿å表 |
| | | followupTemplates: [], // è¯é³æ¨¡æ¿å表 |
| | | templateOptionsLoading: false, |
| | | |
| | | // å½å模æ¿ä¿¡æ¯ |
| | | currentTemplateInfo: null, |
| | | templateLoading: false, |
| | | |
| | | // æ¥è¯¢åæ° |
| | | queryParams: { |
| | | scriptTopic: "", |
| | | scriptContent: "", |
| | | }, |
| | | |
| | | // æ°æ®å表 |
| | | questionList: [], |
| | | loading: false, |
| | | batchSaving: false, |
| | | |
| | | // åå
¸æ°æ® |
| | | askvaluetype: store.getters.askvaluetype || [], |
| | | qyoptions: store.getters.usable || [], |
| | | |
| | | // ç§å®¤é项 |
| | | deptOptions: [], |
| | | |
| | | // é¢è§ç¸å
³ |
| | | previewVisible: false, |
| | | currentPreview: null, |
| | | previewAnswer: "", |
| | | |
| | | // ä¿åç¸å
³ |
| | | saveSuccessVisible: false, |
| | | hasChanges: false, |
| | | changedCount: 0, |
| | | |
| | | // 满æåº¦åç±»ID |
| | | satisfactionCategoryIds: ["404", "405", "406", "10039", "10041", "10042"], |
| | | questionnaireCategorys: [], |
| | | voiceCategories: [], |
| | | // 表åéªè¯è§å |
| | | configRules: { |
| | | responsibilityDept: [ |
| | | { |
| | | required: true, |
| | | message: "请è³å°éæ©ä¸ä¸ªè´£ä»»ç§å®¤", |
| | | trigger: "change", |
| | | }, |
| | | { |
| | | validator: (rule, value, callback) => { |
| | | if (!value || value.length === 0) { |
| | | callback(new Error("请è³å°éæ©ä¸ä¸ªè´£ä»»ç§å®¤")); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, |
| | | trigger: "change", |
| | | }, |
| | | ], |
| | | reportDept: [ |
| | | { |
| | | required: true, |
| | | message: "请è³å°éæ©ä¸ä¸ªæ¥å¤ç§å®¤", |
| | | trigger: "change", |
| | | }, |
| | | { |
| | | validator: (rule, value, callback) => { |
| | | if (!value || value.length === 0) { |
| | | callback(new Error("请è³å°éæ©ä¸ä¸ªæ¥å¤ç§å®¤")); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, |
| | | trigger: "change", |
| | | }, |
| | | ], |
| | | }, |
| | | }; |
| | | }, |
| | | computed: { |
| | | // æ ¹æ®æ¨¡æ¿ç±»åè¿æ»¤æ¨¡æ¿é项 |
| | | filteredTemplateOptions() { |
| | | if (this.templateForm.templateType === 1) { |
| | | return this.questionnaireTemplates; |
| | | } else if (this.templateForm.templateType === 2) { |
| | | return this.followupTemplates; |
| | | } |
| | | return []; |
| | | }, |
| | | |
| | | // 满æåº¦é¢ç®æ°é |
| | | satisfactionQuestionsCount() { |
| | | if (this.templateForm.templateType === 1) { |
| | | return this.questionList.filter((q) => |
| | | this.questionnaireCategorys.includes(q.categoryid) |
| | | ).length; |
| | | } else if (this.templateForm.templateType === 2) { |
| | | return this.questionList.filter((q) => |
| | | this.voiceCategories.includes(q.scriptAssortid) |
| | | ).length; |
| | | } |
| | | }, |
| | | // æ£æ¥é¢ç®æ¯å¦æå¼å¸¸é项 |
| | | hasAbnormalOption(question) { |
| | | return (question) => { |
| | | if (!question) return false; |
| | | |
| | | // é®å·æ¨¡æ¿ |
| | | if (this.templateForm.templateType === 1) { |
| | | const options = question.svyLibTemplateTargetoptions || []; |
| | | return options.some((opt) => opt.isabnormal === 1); |
| | | } |
| | | // è¯é³æ¨¡æ¿ |
| | | else if (this.templateForm.templateType === 2) { |
| | | const options = question.ivrLibaScriptTargetoptionList || []; |
| | | return options.some((opt) => opt.isabnormal === 1); |
| | | } |
| | | |
| | | return false; |
| | | }; |
| | | }, |
| | | // çéåçé¢ç®å表 |
| | | filteredQuestionList() { |
| | | let filtered = this.questionList; |
| | | console.log(this.questionnaireCategorys); |
| | | |
| | | // çéæ»¡æåº¦é¢ç® |
| | | if (this.templateForm.templateType === 1) { |
| | | filtered = filtered.filter((q) => |
| | | this.questionnaireCategorys.includes(q.categoryid) |
| | | ); |
| | | } else if (this.templateForm.templateType === 2) { |
| | | filtered = filtered.filter((q) => |
| | | this.voiceCategories.includes(q.scriptAssortid) |
| | | ); |
| | | } |
| | | |
| | | // åºç¨æç´¢æ¡ä»¶ |
| | | if (this.queryParams.scriptTopic) { |
| | | const keyword = this.queryParams.scriptTopic.toLowerCase(); |
| | | filtered = filtered.filter( |
| | | (q) => q.scriptTopic && q.scriptTopic.toLowerCase().includes(keyword) |
| | | ); |
| | | } |
| | | |
| | | if (this.queryParams.scriptContent) { |
| | | const keyword = this.queryParams.scriptContent.toLowerCase(); |
| | | filtered = filtered.filter( |
| | | (q) => |
| | | q.scriptContent && q.scriptContent.toLowerCase().includes(keyword) |
| | | ); |
| | | } |
| | | |
| | | return filtered; |
| | | }, |
| | | }, |
| | | created() { |
| | | if (store.getters.satisfactionCategories) { |
| | | this.questionnaireCategorys = |
| | | store.getters.satisfactionCategories.questionnaireCategorys.map( |
| | | (item) => item.categoryid |
| | | ); |
| | | this.voiceCategories = |
| | | store.getters.satisfactionCategories.voiceCategories.map( |
| | | (item) => item.categoryid |
| | | ); |
| | | } |
| | | this.getDeptOptions(); |
| | | this.loadAllTemplates(); |
| | | }, |
| | | methods: { |
| | | /** å è½½æææ¨¡æ¿å表 */ |
| | | loadAllTemplates() { |
| | | this.templateOptionsLoading = true; |
| | | |
| | | // å¹¶è¡å è½½é®å·æ¨¡æ¿åè¯é³æ¨¡æ¿ |
| | | Promise.all([ |
| | | this.loadQuestionnaireTemplates(), |
| | | this.loadFollowupTemplates(), |
| | | ]).finally(() => { |
| | | this.templateOptionsLoading = false; |
| | | }); |
| | | }, |
| | | |
| | | /** æ¥è¯¢ç§å®¤å表 */ |
| | | getDeptOptions() { |
| | | deptTreeSelect() |
| | | .then((res) => { |
| | | if (res.code == 200) { |
| | | this.deptOptions = this.flattenArray(res.data) || []; |
| | | } |
| | | }) |
| | | .catch((error) => { |
| | | console.error("è·åç§å®¤å表失败:", error); |
| | | this.$message.error("è·åç§å®¤å表失败"); |
| | | }); |
| | | }, |
| | | |
| | | flattenArray(multiArray) { |
| | | let result = []; |
| | | |
| | | function flatten(element) { |
| | | if (element.children && element.children.length > 0) { |
| | | element.children.forEach((child) => flatten(child)); |
| | | } else { |
| | | let item = JSON.parse(JSON.stringify(element)); |
| | | result.push(item); |
| | | } |
| | | } |
| | | |
| | | multiArray.forEach((element) => flatten(element)); |
| | | return result; |
| | | }, |
| | | |
| | | /** æ ¹æ®ç§å®¤ç¼ç è·åç§å®¤åç§° */ |
| | | getDeptName(deptCode) { |
| | | if (!deptCode) return ""; |
| | | const dept = this.deptOptions.find((d) => d.deptCode === deptCode); |
| | | return dept ? dept.label : deptCode; |
| | | }, |
| | | |
| | | /** æ ¹æ®ç§å®¤ç¼ç æ°ç»è·åç§å®¤åç§°æ°ç» */ |
| | | getDeptNames(deptCodes) { |
| | | if (!Array.isArray(deptCodes) || deptCodes.length === 0) return []; |
| | | return deptCodes |
| | | .map((code) => this.getDeptName(code)) |
| | | .filter((name) => name && name.trim()); |
| | | }, |
| | | |
| | | /** 模æ¿ç±»ååæ´ */ |
| | | handleTemplateTypeChange() { |
| | | this.templateForm.templateId = ""; |
| | | this.currentTemplateInfo = null; |
| | | this.questionList = []; |
| | | }, |
| | | |
| | | /** å è½½é®å·æ¨¡æ¿å表 */ |
| | | loadQuestionnaireTemplates() { |
| | | return new Promise((resolve) => { |
| | | getQtemplatelist({ pageSize: 1000 }) |
| | | .then((res) => { |
| | | if (res.code === 200) { |
| | | this.questionnaireTemplates = (res.rows || []).map((item) => ({ |
| | | id: item.svyid, |
| | | templateName: item.svyname, |
| | | isavailable: item.isavailable, |
| | | })); |
| | | } else { |
| | | this.$message.error(res.msg || "å è½½é®å·æ¨¡æ¿å¤±è´¥"); |
| | | } |
| | | resolve(); |
| | | }) |
| | | .catch((error) => { |
| | | console.error("å è½½é®å·æ¨¡æ¿å¤±è´¥:", error); |
| | | this.$message.error("å è½½é®å·æ¨¡æ¿å¤±è´¥"); |
| | | resolve(); |
| | | }); |
| | | }); |
| | | }, |
| | | |
| | | /** å è½½è¯é³æ¨¡æ¿å表 */ |
| | | loadFollowupTemplates() { |
| | | return new Promise((resolve) => { |
| | | getFollowuplist({ pageSize: 1000 }) |
| | | .then((res) => { |
| | | if (res.code === 200) { |
| | | this.followupTemplates = (res.rows || []).map((item) => ({ |
| | | id: item.id, |
| | | templateName: item.templateName, |
| | | isavailable: item.isavailable, |
| | | })); |
| | | } else { |
| | | this.$message.error(res.msg || "å è½½è¯é³æ¨¡æ¿å¤±è´¥"); |
| | | } |
| | | resolve(); |
| | | }) |
| | | .catch((error) => { |
| | | console.error("å è½½è¯é³æ¨¡æ¿å¤±è´¥:", error); |
| | | this.$message.error("å è½½è¯é³æ¨¡æ¿å¤±è´¥"); |
| | | resolve(); |
| | | }); |
| | | }); |
| | | }, |
| | | |
| | | /** 模æ¿éæ©åæ´ */ |
| | | handleTemplateChange(templateId) { |
| | | if (templateId) { |
| | | const selectedTemplate = this.filteredTemplateOptions.find( |
| | | (t) => t.id === templateId |
| | | ); |
| | | if (selectedTemplate) { |
| | | this.currentTemplateInfo = { |
| | | templateName: selectedTemplate.templateName, |
| | | templateStatus: selectedTemplate.isavailable, |
| | | questionCount: 0, |
| | | }; |
| | | } |
| | | // å 载模æ¿è¯¦æ
æ°æ® |
| | | this.templateLoading = true; |
| | | this.loading = true; |
| | | this.questionList = []; |
| | | |
| | | if (this.templateForm.templateType === 1) { |
| | | this.loadQuestionnaireTemplateDetail(); |
| | | } else if (this.templateForm.templateType === 2) { |
| | | this.loadFollowupTemplateDetail(); |
| | | } |
| | | } else { |
| | | this.currentTemplateInfo = null; |
| | | this.questionList = []; |
| | | } |
| | | }, |
| | | |
| | | /** å 载模æ¿è¯¦æ
åé¢ç® */ |
| | | handleLoadTemplate() { |
| | | this.$refs.templateForm.validate((valid) => { |
| | | if (!valid) { |
| | | this.$message.warning("请å
éæ©æ¨¡æ¿"); |
| | | return; |
| | | } |
| | | |
| | | this.templateLoading = true; |
| | | this.loading = true; |
| | | this.questionList = []; |
| | | |
| | | if (this.templateForm.templateType === 1) { |
| | | this.loadQuestionnaireTemplateDetail(); |
| | | } else if (this.templateForm.templateType === 2) { |
| | | this.loadFollowupTemplateDetail(); |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | /** å è½½é®å·æ¨¡æ¿è¯¦æ
*/ |
| | | loadQuestionnaireTemplateDetail() { |
| | | getQtemplateobj({ svyid: this.templateForm.templateId }) |
| | | .then((res) => { |
| | | this.templateLoading = false; |
| | | this.loading = false; |
| | | |
| | | if (res.code === 200 && res.rows && res.rows.length > 0) { |
| | | const templateDetail = res.rows[0]; |
| | | |
| | | // æ´æ°æ¨¡æ¿ä¿¡æ¯ |
| | | this.currentTemplateInfo = { |
| | | ...templateDetail, |
| | | templateName: templateDetail.svyname, |
| | | templateStatus: templateDetail.isavailable, |
| | | questionCount: templateDetail.svyTemplateLibScripts?.length || 0, |
| | | }; |
| | | |
| | | // æåé¢ç®å表 |
| | | const questions = templateDetail.svyTemplateLibScripts || []; |
| | | this.processQuestions(questions); |
| | | |
| | | this.$message.success(`æåå è½½ ${questions.length} 个é¢ç®`); |
| | | } else { |
| | | this.$message.error(res.msg || "å 载模æ¿è¯¦æ
失败"); |
| | | } |
| | | }) |
| | | .catch((error) => { |
| | | this.templateLoading = false; |
| | | this.loading = false; |
| | | console.error("å è½½é®å·æ¨¡æ¿è¯¦æ
失败:", error); |
| | | this.$message.error("å 载模æ¿è¯¦æ
失败"); |
| | | }); |
| | | }, |
| | | |
| | | /** å è½½è¯é³æ¨¡æ¿è¯¦æ
*/ |
| | | loadFollowupTemplateDetail() { |
| | | getvFollowup({ id: this.templateForm.templateId }) |
| | | .then((res) => { |
| | | this.templateLoading = false; |
| | | this.loading = false; |
| | | |
| | | if (res.code === 200) { |
| | | const templateDetail = res.data; |
| | | |
| | | // æ´æ°æ¨¡æ¿ä¿¡æ¯ |
| | | this.currentTemplateInfo = { |
| | | ...this.currentTemplateInfo, |
| | | templateName: templateDetail.templateName, |
| | | templateStatus: templateDetail.isavailable, |
| | | questionCount: |
| | | templateDetail.ivrLibaTemplateScriptVOList?.length || 0, |
| | | }; |
| | | |
| | | // æåé¢ç®å表 |
| | | const questions = templateDetail.ivrLibaTemplateScriptVOList || []; |
| | | this.processQuestions(questions); |
| | | |
| | | this.$message.success(`æåå è½½ ${questions.length} 个é¢ç®`); |
| | | } else { |
| | | this.$message.error(res.msg || "å 载模æ¿è¯¦æ
失败"); |
| | | } |
| | | }) |
| | | .catch((error) => { |
| | | this.templateLoading = false; |
| | | this.loading = false; |
| | | console.error("å è½½è¯é³æ¨¡æ¿è¯¦æ
失败:", error); |
| | | this.$message.error("å 载模æ¿è¯¦æ
失败"); |
| | | }); |
| | | }, |
| | | |
| | | /** å¤çé¢ç®æ°æ® */ |
| | | processQuestions(questions) { |
| | | this.questionList = questions.map((question) => { |
| | | // è§£æè´£ä»»ç§å®¤åæ¥å¤ç§å®¤ |
| | | let exceptionConfig = { |
| | | responsibilityDept: [], // 责任ç§å®¤ç¼ç æ°ç» |
| | | reportDept: [], // æ¥å¤ç§å®¤ç¼ç æ°ç» |
| | | }; |
| | | |
| | | // ä»é¢ç®é¡¶å±åæ®µè¯»åæ°æ® |
| | | if (question.dutyDeptCode) { |
| | | // ä»éå·åéçå符串转为æ°ç» |
| | | exceptionConfig.responsibilityDept = question.dutyDeptCode |
| | | .split(",") |
| | | .map((code) => code.trim()) |
| | | .filter((code) => code); |
| | | } |
| | | |
| | | if (question.reportDeptCode) { |
| | | exceptionConfig.reportDept = question.reportDeptCode |
| | | .split(",") |
| | | .map((code) => code.trim()) |
| | | .filter((code) => code); |
| | | } |
| | | |
| | | return { |
| | | ...question, |
| | | // ç»ä¸å段å |
| | | id: question.id || question.scriptId, |
| | | scriptTopic: question.scriptTopic || question.scriptTopic, |
| | | scriptContent: question.scriptContent || question.scriptContent, |
| | | scriptType: question.scriptType, |
| | | isavailable: question.isavailable, |
| | | targetname: question.targetname, |
| | | categoryid: question.categoryid || question.categoryid, |
| | | originalConfig: JSON.parse(JSON.stringify(exceptionConfig)), |
| | | exceptionConfig: exceptionConfig, |
| | | hasChanges: false, |
| | | saving: false, |
| | | saveStatus: null, |
| | | }; |
| | | }); |
| | | |
| | | this.updateChangedStatus(); |
| | | }, |
| | | |
| | | /** é置模æ¿éæ© */ |
| | | handleResetTemplate() { |
| | | this.templateForm = { |
| | | templateType: "", |
| | | templateId: "", |
| | | }; |
| | | this.currentTemplateInfo = null; |
| | | this.questionList = []; |
| | | this.resetQuery(); |
| | | this.$refs.templateForm?.clearValidate(); |
| | | }, |
| | | |
| | | /** é
ç½®åæ´å¤ç */ |
| | | handleConfigChange(question) { |
| | | this.$nextTick(() => { |
| | | const index = this.filteredQuestionList.findIndex( |
| | | (q) => q.id === question.id |
| | | ); |
| | | if (index !== -1) { |
| | | const formRef = this.$refs.configForm && this.$refs.configForm[index]; |
| | | if (formRef) { |
| | | formRef.validate((valid) => { |
| | | if (valid) { |
| | | question.hasChanges = !this.isConfigEqual( |
| | | question.exceptionConfig, |
| | | question.originalConfig |
| | | ); |
| | | this.updateChangedStatus(); |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | /** æ¯è¾é
ç½®æ¯å¦æ¹å */ |
| | | isConfigEqual(config1, config2) { |
| | | if (!config1 || !config2) return false; |
| | | |
| | | const responsibility1 = [...(config1.responsibilityDept || [])] |
| | | .sort() |
| | | .join(",") |
| | | .toLowerCase(); |
| | | const responsibility2 = [...(config2.responsibilityDept || [])] |
| | | .sort() |
| | | .join(",") |
| | | .toLowerCase(); |
| | | const report1 = [...(config1.reportDept || [])] |
| | | .sort() |
| | | .join(",") |
| | | .toLowerCase(); |
| | | const report2 = [...(config2.reportDept || [])] |
| | | .sort() |
| | | .join(",") |
| | | .toLowerCase(); |
| | | |
| | | return responsibility1 === responsibility2 && report1 === report2; |
| | | }, |
| | | |
| | | /** æ´æ°åæ´ç¶æ */ |
| | | updateChangedStatus() { |
| | | const changedItems = this.questionList.filter((q) => q.hasChanges); |
| | | this.changedCount = changedItems.length; |
| | | this.hasChanges = changedItems.length > 0; |
| | | }, |
| | | |
| | | /** ä¿åå个é¢ç®é
ç½® */ |
| | | async saveSingleConfig(question) { |
| | | if (!question.hasChanges) return; |
| | | |
| | | const index = this.filteredQuestionList.findIndex( |
| | | (q) => q.id === question.id |
| | | ); |
| | | console.log(index, "filteredQuestionList"); |
| | | |
| | | if (index === -1) return; |
| | | |
| | | const formRef = this.$refs.configForm && this.$refs.configForm[index]; |
| | | if (!formRef) return; |
| | | |
| | | const valid = await formRef.validate(); |
| | | if (!valid) { |
| | | this.$message.warning("请å
宿å¿
填项"); |
| | | return; |
| | | } |
| | | |
| | | question.saving = true; |
| | | question.saveStatus = null; |
| | | |
| | | try { |
| | | // è·åå½å模æ¿è¯¦æ
|
| | | let templateDetail; |
| | | if (this.templateForm.templateType === 1) { |
| | | // é®å·æ¨¡æ¿ |
| | | const res = await getQtemplateobj({ |
| | | svyid: this.templateForm.templateId, |
| | | }); |
| | | if (res.code !== 200 || !res.rows || res.rows.length === 0) { |
| | | throw new Error(res.msg || "è·å模æ¿è¯¦æ
失败"); |
| | | } |
| | | templateDetail = res.rows[0]; |
| | | } else if (this.templateForm.templateType === 2) { |
| | | // è¯é³æ¨¡æ¿ |
| | | const res = await getvFollowup({ id: this.templateForm.templateId }); |
| | | if (res.code !== 200) { |
| | | throw new Error(res.msg || "è·å模æ¿è¯¦æ
失败"); |
| | | } |
| | | templateDetail = res.data; |
| | | } |
| | | |
| | | // æ´æ°é¢ç®é
ç½® |
| | | let updatedTemplateDetail = { ...templateDetail }; |
| | | let questionsField = |
| | | this.templateForm.templateType === 1 |
| | | ? "svyTemplateLibScripts" |
| | | : "ivrLibaTemplateScriptVOList"; |
| | | |
| | | const questions = updatedTemplateDetail[questionsField] || []; |
| | | const questionIndex = questions.findIndex((q) => q.id === question.id); |
| | | |
| | | if (questionIndex === -1) { |
| | | throw new Error("æªæ¾å°é¢ç®"); |
| | | } |
| | | |
| | | // è·åç§å®¤åç§° |
| | | const responsibilityDeptNames = this.getDeptNames( |
| | | question.exceptionConfig.responsibilityDept |
| | | ); |
| | | const reportDeptNames = this.getDeptNames( |
| | | question.exceptionConfig.reportDept |
| | | ); |
| | | |
| | | // ç´æ¥æ´æ°é¢ç®é¡¶å±å段 |
| | | questions[questionIndex] = { |
| | | ...questions[questionIndex], |
| | | // 设置Excelè¦æ±çåæ®µ |
| | | dutyDeptCode: question.exceptionConfig.responsibilityDept.join(","), |
| | | dutyDeptName: responsibilityDeptNames.join(","), |
| | | reportDeptCode: question.exceptionConfig.reportDept.join(","), |
| | | reportDeptName: reportDeptNames.join(","), |
| | | }; |
| | | |
| | | // æ´æ°æ¨¡æ¿ |
| | | updatedTemplateDetail[questionsField] = questions; |
| | | |
| | | // ä¿åæ¨¡æ¿ |
| | | let response; |
| | | if (this.templateForm.templateType === 1) { |
| | | response = await compileQtemplate({ |
| | | ...updatedTemplateDetail, |
| | | id: this.templateForm.templateId, |
| | | isoperation: 2, |
| | | }); |
| | | } else { |
| | | response = await compileFollowup({ |
| | | ...updatedTemplateDetail, |
| | | id: this.templateForm.templateId, |
| | | isoperation: 2, |
| | | }); |
| | | } |
| | | |
| | | if (response.code === 200) { |
| | | this.handleSaveSuccess(question); |
| | | } else { |
| | | throw new Error(response.msg || "ä¿å失败"); |
| | | } |
| | | } catch (error) { |
| | | console.error("ä¿å失败:", error); |
| | | question.saveStatus = { |
| | | type: "error", |
| | | message: error.message || "ä¿å失败ï¼è¯·ç¨åéè¯", |
| | | }; |
| | | this.$message.error(error.message || "ä¿å失败ï¼è¯·ç¨åéè¯"); |
| | | } finally { |
| | | question.saving = false; |
| | | } |
| | | }, |
| | | |
| | | /** å¤çä¿åæå */ |
| | | /** å¤çä¿åæå */ |
| | | handleSaveSuccess(question) { |
| | | // åæ¶æ´æ°é¢ç®é¡¶å±å段 |
| | | const responsibilityDeptNames = this.getDeptNames( |
| | | question.exceptionConfig.responsibilityDept |
| | | ); |
| | | const reportDeptNames = this.getDeptNames( |
| | | question.exceptionConfig.reportDept |
| | | ); |
| | | |
| | | // æ´æ°é¢ç®æ¬èº«çåæ®µ |
| | | question.dutyDeptCode = |
| | | question.exceptionConfig.responsibilityDept.join(","); |
| | | question.dutyDeptName = responsibilityDeptNames.join(","); |
| | | question.reportDeptCode = question.exceptionConfig.reportDept.join(","); |
| | | question.reportDeptName = reportDeptNames.join(","); |
| | | |
| | | // æ´æ°åå§é
ç½® |
| | | question.originalConfig = JSON.parse( |
| | | JSON.stringify(question.exceptionConfig) |
| | | ); |
| | | question.hasChanges = false; |
| | | question.saveStatus = { |
| | | type: "success", |
| | | message: "é
ç½®ä¿åæå", |
| | | }; |
| | | |
| | | this.updateChangedStatus(); |
| | | this.$message.success("é
ç½®ä¿åæå"); |
| | | |
| | | // 5ç§åæ¸
餿åæç¤º |
| | | setTimeout(() => { |
| | | question.saveStatus = null; |
| | | }, 5000); |
| | | }, |
| | | |
| | | /** éç½®å个é¢ç®é
ç½® */ |
| | | resetSingleConfig(question) { |
| | | this.$confirm("ç¡®å®è¦éç½®å½åé¢ç®çé
ç½®åï¼", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | question.exceptionConfig = JSON.parse( |
| | | JSON.stringify(question.originalConfig) |
| | | ); |
| | | // åæ¶éç½®é¢ç®é¡¶å±å段 |
| | | const responsibilityDeptNames = this.getDeptNames( |
| | | question.exceptionConfig.responsibilityDept |
| | | ); |
| | | const reportDeptNames = this.getDeptNames( |
| | | question.exceptionConfig.reportDept |
| | | ); |
| | | |
| | | question.dutyDeptCode = |
| | | question.exceptionConfig.responsibilityDept.join(","); |
| | | question.dutyDeptName = responsibilityDeptNames.join(","); |
| | | question.reportDeptCode = |
| | | question.exceptionConfig.reportDept.join(","); |
| | | question.reportDeptName = reportDeptNames.join(","); |
| | | |
| | | question.hasChanges = false; |
| | | question.saveStatus = null; |
| | | this.updateChangedStatus(); |
| | | this.$message.success("é
置已éç½®"); |
| | | }) |
| | | .catch(() => {}); |
| | | }, |
| | | |
| | | /** æ¹éä¿åé
ç½® */ |
| | | async handleBatchSave() { |
| | | if (!this.hasChanges || this.batchSaving) return; |
| | | |
| | | this.$confirm("ç¡®å®è¦ä¿åææä¿®æ¹è¿çé
ç½®åï¼", "æ¹éä¿å", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(async () => { |
| | | this.batchSaving = true; |
| | | |
| | | const changedQuestions = this.questionList.filter( |
| | | (q) => q.hasChanges |
| | | ); |
| | | const results = []; |
| | | |
| | | for (const question of changedQuestions) { |
| | | try { |
| | | await this.saveSingleConfig(question); |
| | | results.push({ |
| | | id: question.id, |
| | | success: |
| | | !question.hasChanges && |
| | | question.saveStatus?.type === "success", |
| | | }); |
| | | } catch (error) { |
| | | results.push({ |
| | | id: question.id, |
| | | success: false, |
| | | }); |
| | | } |
| | | } |
| | | |
| | | this.batchSaving = false; |
| | | |
| | | const successCount = results.filter((r) => r.success).length; |
| | | const failCount = results.length - successCount; |
| | | |
| | | if (failCount === 0) { |
| | | this.saveSuccessVisible = true; |
| | | this.$message.success(`æåä¿å ${successCount} 个é
ç½®`); |
| | | } else { |
| | | this.$message.warning( |
| | | `æåä¿å ${successCount} 个ï¼å¤±è´¥ ${failCount} 个` |
| | | ); |
| | | } |
| | | }) |
| | | .catch(() => { |
| | | this.batchSaving = false; |
| | | }); |
| | | }, |
| | | |
| | | /** é¢è§é¢ç® */ |
| | | previewQuestion(question) { |
| | | this.currentPreview = { ...question }; |
| | | this.previewAnswer = ""; |
| | | this.previewVisible = true; |
| | | }, |
| | | /** æ£æ¥é¢ç®æ¯å¦æå¼å¸¸é项 */ |
| | | checkHasAbnormalOptions(question) { |
| | | if (this.templateForm.templateType === 1) { |
| | | return (question.svyLibTemplateTargetoptions || []).some( |
| | | (opt) => opt.isabnormal === 1 |
| | | ); |
| | | } else if (this.templateForm.templateType === 2) { |
| | | return (question.ivrLibaScriptTargetoptionList || []).some( |
| | | (opt) => opt.isabnormal === 1 |
| | | ); |
| | | } |
| | | return false; |
| | | }, |
| | | |
| | | /** æå¼é项管çå¯¹è¯æ¡ */ |
| | | openOptionDialog(question) { |
| | | this.editingQuestion = question; |
| | | |
| | | // å¤å¶éé¡¹æ°æ® |
| | | if (this.templateForm.templateType === 1) { |
| | | this.currentOptions = JSON.parse( |
| | | JSON.stringify(question.svyLibTemplateTargetoptions || []) |
| | | ).map((opt) => ({ |
| | | ...opt, |
| | | id: opt.id, |
| | | targetvalue: opt.optioncontent || "", |
| | | isabnormal: opt.isabnormal || 0, |
| | | })); |
| | | } else if (this.templateForm.templateType === 2) { |
| | | this.currentOptions = JSON.parse( |
| | | JSON.stringify(question.ivrLibaScriptTargetoptionList || []) |
| | | ).map((opt) => ({ |
| | | ...opt, |
| | | targetvalue: opt.targetvalue || "", |
| | | isabnormal: opt.isabnormal || 0, |
| | | })); |
| | | } |
| | | |
| | | this.optionDialogVisible = true; |
| | | }, |
| | | |
| | | /** æ·»å æ°é项 */ |
| | | addNewOption() { |
| | | this.currentOptions.push({ |
| | | id: Date.now(), // 临æ¶ID |
| | | targetvalue: "", |
| | | isabnormal: 0, |
| | | isNew: true, |
| | | }); |
| | | }, |
| | | |
| | | /** å é¤é项 */ |
| | | removeOption(index) { |
| | | this.currentOptions.splice(index, 1); |
| | | }, |
| | | |
| | | /** ä¿åé项é
ç½® */ |
| | | async saveOptions() { |
| | | try { |
| | | // éªè¯å¿
填项 |
| | | for (const option of this.currentOptions) { |
| | | if (!option.targetvalue || option.targetvalue.trim() === "") { |
| | | this.$message.warning("è¯·å¡«åææé项å
容"); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | // æ£æ¥æ¯å¦æå¼å¸¸é项 |
| | | const hasAbnormal = this.currentOptions.some( |
| | | (opt) => opt.isabnormal === 1 |
| | | ); |
| | | |
| | | if (!hasAbnormal) { |
| | | this.$message.warning("请è³å°è®¾ç½®ä¸ä¸ªå¼å¸¸é项ï¼isabnormal=1ï¼"); |
| | | return; |
| | | } |
| | | |
| | | // ä¿åé»è¾ - æ´æ°é¢ç®å¯¹è±¡çéé¡¹æ°æ® |
| | | if (this.templateForm.templateType === 1) { |
| | | this.editingQuestion.svyLibTemplateTargetoptions = |
| | | this.currentOptions.map((opt) => ({ |
| | | ...opt, |
| | | optioncontent: opt.targetvalue, |
| | | isabnormal: opt.isabnormal, |
| | | })); |
| | | } else if (this.templateForm.templateType === 2) { |
| | | this.editingQuestion.ivrLibaScriptTargetoptionList = |
| | | this.currentOptions; |
| | | } |
| | | |
| | | // 触åé
ç½®åæ´æ£æ¥ |
| | | this.handleConfigChange(this.editingQuestion); |
| | | |
| | | this.$message.success("é项é
ç½®ä¿åæå"); |
| | | this.optionDialogVisible = false; |
| | | } catch (error) { |
| | | console.error("ä¿åé项失败:", error); |
| | | this.$message.error("ä¿åé项失败"); |
| | | } |
| | | }, |
| | | |
| | | /** ä¿®æ¹ä¿åå个é¢ç®é
ç½®æ¹æ³ï¼æ·»å å¼å¸¸éé¡¹æ£æ¥ */ |
| | | async saveSingleConfig(question) { |
| | | // æ£æ¥æ¯å¦æå¼å¸¸é项 |
| | | if (!this.checkHasAbnormalOptions(question)) { |
| | | this.$confirm("该é¢ç®æ²¡æè®¾ç½®å¼å¸¸éé¡¹ï¼æ¯å¦å
é
ç½®é项ï¼", "æç¤º", { |
| | | confirmButtonText: "å»é
ç½®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | this.openOptionDialog(question); |
| | | }) |
| | | .catch(() => {}); |
| | | return; |
| | | } |
| | | |
| | | // åæçä¿åé»è¾... |
| | | if (!question.hasChanges) return; |
| | | |
| | | const index = this.filteredQuestionList.findIndex( |
| | | (q) => q.id === question.id |
| | | ); |
| | | |
| | | if (index === -1) return; |
| | | |
| | | const formRef = this.$refs.configForm && this.$refs.configForm[index]; |
| | | if (!formRef) return; |
| | | |
| | | const valid = await formRef.validate(); |
| | | if (!valid) { |
| | | this.$message.warning("请å
宿å¿
填项"); |
| | | return; |
| | | } |
| | | |
| | | // ç»§ç»åæçä¿åé»è¾... |
| | | question.saving = true; |
| | | question.saveStatus = null; |
| | | |
| | | try { |
| | | // ... åæçä¿åé»è¾ä¸å |
| | | } catch (error) { |
| | | // ... é误å¤çä¸å |
| | | } finally { |
| | | question.saving = false; |
| | | } |
| | | }, |
| | | |
| | | /** æ¹éä¿åæ¶ä¹è¦æ£æ¥ */ |
| | | async handleBatchSave() { |
| | | if (!this.hasChanges || this.batchSaving) return; |
| | | |
| | | // æ£æ¥æææåæ´çé¢ç®æ¯å¦é½æå¼å¸¸é项 |
| | | const changedQuestions = this.questionList.filter((q) => q.hasChanges); |
| | | const questionsWithoutAbnormal = changedQuestions.filter( |
| | | (q) => !this.checkHasAbnormalOptions(q) |
| | | ); |
| | | |
| | | if (questionsWithoutAbnormal.length > 0) { |
| | | this.$confirm( |
| | | `æ ${questionsWithoutAbnormal.length} 个é¢ç®æ²¡æè®¾ç½®å¼å¸¸é项ï¼è¯·å
é
ç½®éé¡¹ãæ¯å¦ç»§ç»ï¼`, |
| | | "æç¤º", |
| | | { |
| | | confirmButtonText: "ç»§ç»", |
| | | cancelButtonText: "å»é
ç½®", |
| | | type: "warning", |
| | | } |
| | | ) |
| | | .then(() => { |
| | | // ç»§ç»æ§è¡æ¹éä¿å |
| | | this.executeBatchSave(changedQuestions); |
| | | }) |
| | | .catch(() => { |
| | | // å¯ä»¥å¨è¿é跳转å°ç¬¬ä¸ä¸ªæ²¡æå¼å¸¸é项çé¢ç® |
| | | if (questionsWithoutAbnormal.length > 0) { |
| | | this.openOptionDialog(questionsWithoutAbnormal[0]); |
| | | } |
| | | }); |
| | | } else { |
| | | this.executeBatchSave(changedQuestions); |
| | | } |
| | | }, |
| | | |
| | | /** æ§è¡æ¹éä¿å */ |
| | | async executeBatchSave(changedQuestions) { |
| | | this.$confirm("ç¡®å®è¦ä¿åææä¿®æ¹è¿çé
ç½®åï¼", "æ¹éä¿å", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(async () => { |
| | | this.batchSaving = true; |
| | | |
| | | const results = []; |
| | | for (const question of changedQuestions) { |
| | | try { |
| | | // è¿éè°ç¨ä¿®æ¹åçsaveSingleConfigæ¹æ³ |
| | | await this.saveSingleConfig(question); |
| | | results.push({ |
| | | id: question.id, |
| | | success: |
| | | !question.hasChanges && |
| | | question.saveStatus?.type === "success", |
| | | }); |
| | | } catch (error) { |
| | | results.push({ |
| | | id: question.id, |
| | | success: false, |
| | | }); |
| | | } |
| | | } |
| | | |
| | | this.batchSaving = false; |
| | | // ... åç»å¤çä¸å |
| | | }) |
| | | .catch(() => { |
| | | this.batchSaving = false; |
| | | }); |
| | | }, |
| | | |
| | | /** è·åå¼å¸¸é项ç»è®¡ */ |
| | | getAbnormalStats(question) { |
| | | if (this.templateForm.templateType === 1) { |
| | | const options = question.svyLibTemplateTargetoptions || []; |
| | | return { |
| | | total: options.length, |
| | | abnormal: options.filter((opt) => opt.isabnormal === 1).length, |
| | | warning: options.filter((opt) => opt.isabnormal === 2).length, |
| | | normal: options.filter((opt) => opt.isabnormal === 0).length, |
| | | }; |
| | | } else if (this.templateForm.templateType === 2) { |
| | | const options = question.ivrLibaScriptTargetoptionList || []; |
| | | return { |
| | | total: options.length, |
| | | abnormal: options.filter((opt) => opt.isabnormal === 1).length, |
| | | warning: options.filter((opt) => opt.isabnormal === 2).length, |
| | | normal: options.filter((opt) => opt.isabnormal === 0).length, |
| | | }; |
| | | } |
| | | return { total: 0, abnormal: 0, warning: 0, normal: 0 }; |
| | | }, |
| | | /** æç´¢ */ |
| | | handleQuery() { |
| | | // ä»
çéæ¾ç¤ºï¼ä¸éè¦éæ°å è½½ |
| | | }, |
| | | |
| | | /** éç½®æç´¢ */ |
| | | resetQuery() { |
| | | this.queryParams = { |
| | | scriptTopic: "", |
| | | scriptContent: "", |
| | | }; |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .satisfaction-exception-config { |
| | | min-height: 100%; |
| | | background-color: #f5f7fa; |
| | | padding: 20px; |
| | | |
| | | .page-header { |
| | | margin-bottom: 20px; |
| | | padding: 20px; |
| | | background: linear-gradient(135deg, #409eff 0%, #66b1ff 100%); |
| | | border-radius: 8px; |
| | | color: white; |
| | | |
| | | .header-content { |
| | | .page-title { |
| | | margin: 0 0 8px 0; |
| | | font-size: 20px; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | .page-description { |
| | | margin: 0; |
| | | opacity: 0.9; |
| | | font-size: 14px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .template-section { |
| | | margin-bottom: 20px; |
| | | |
| | | .template-header { |
| | | margin-bottom: 20px; |
| | | |
| | | .template-title { |
| | | margin: 0 0 8px 0; |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | } |
| | | |
| | | .template-tip { |
| | | margin: 0; |
| | | color: #909399; |
| | | font-size: 13px; |
| | | } |
| | | } |
| | | |
| | | .select-loading { |
| | | text-align: center; |
| | | padding: 10px; |
| | | color: #909399; |
| | | |
| | | i { |
| | | margin-right: 8px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .template-info-section { |
| | | margin-bottom: 20px; |
| | | |
| | | .template-info { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 5px 0; |
| | | |
| | | .info-left { |
| | | .template-name { |
| | | margin: 0 0 10px 0; |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | } |
| | | |
| | | .template-meta { |
| | | display: flex; |
| | | gap: 20px; |
| | | flex-wrap: wrap; |
| | | |
| | | .meta-item { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 5px; |
| | | font-size: 13px; |
| | | color: #606266; |
| | | |
| | | i { |
| | | font-size: 14px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .search-section { |
| | | margin-bottom: 20px; |
| | | |
| | | .search-container { |
| | | border-radius: 8px; |
| | | |
| | | .el-form { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 16px; |
| | | align-items: center; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .config-content { |
| | | .batch-actions-card { |
| | | margin-bottom: 20px; |
| | | |
| | | .batch-actions { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 20px; |
| | | padding: 8px 0; |
| | | |
| | | .change-count { |
| | | color: #e6a23c; |
| | | font-size: 14px; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .total-count { |
| | | margin-left: auto; |
| | | color: #909399; |
| | | font-size: 14px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .loading-wrapper { |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | min-height: 400px; |
| | | |
| | | .loading-spinner { |
| | | text-align: center; |
| | | color: #409eff; |
| | | |
| | | i { |
| | | font-size: 24px; |
| | | margin-right: 8px; |
| | | } |
| | | |
| | | span { |
| | | font-size: 16px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .empty-wrapper { |
| | | min-height: 400px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | |
| | | .empty-tip { |
| | | margin-top: 10px; |
| | | color: #909399; |
| | | font-size: 13px; |
| | | text-align: center; |
| | | } |
| | | } |
| | | |
| | | .question-list { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 16px; |
| | | } |
| | | |
| | | .question-item { |
| | | .question-card { |
| | | border-radius: 8px; |
| | | border: 1px solid #ebeef5; |
| | | transition: all 0.3s ease; |
| | | |
| | | &.has-changes { |
| | | border-color: #409eff; |
| | | box-shadow: 0 2px 12px 0 rgba(64, 158, 255, 0.1); |
| | | } |
| | | |
| | | &:hover { |
| | | box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); |
| | | } |
| | | |
| | | .card-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: flex-start; |
| | | margin-bottom: 20px; |
| | | padding-bottom: 20px; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | |
| | | .header-left { |
| | | display: flex; |
| | | gap: 20px; |
| | | flex: 1; |
| | | |
| | | .question-index { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | min-width: 40px; |
| | | |
| | | .index-number { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | width: 32px; |
| | | height: 32px; |
| | | background: #409eff; |
| | | color: white; |
| | | border-radius: 50%; |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .index-line { |
| | | width: 2px; |
| | | height: 100%; |
| | | background: #e0e0e0; |
| | | border-radius: 1px; |
| | | } |
| | | } |
| | | |
| | | .question-basic-info { |
| | | flex: 1; |
| | | |
| | | .question-title-section { |
| | | margin-bottom: 12px; |
| | | |
| | | .question-topic { |
| | | margin: 0 0 8px 0; |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | line-height: 1.4; |
| | | } |
| | | |
| | | .question-tags { |
| | | display: flex; |
| | | gap: 8px; |
| | | flex-wrap: wrap; |
| | | } |
| | | } |
| | | |
| | | .question-content-section { |
| | | display: flex; |
| | | align-items: flex-start; |
| | | gap: 8px; |
| | | |
| | | .content-label { |
| | | color: #606266; |
| | | font-size: 13px; |
| | | font-weight: 500; |
| | | min-width: 80px; |
| | | } |
| | | |
| | | .content-text { |
| | | color: #303133; |
| | | font-size: 13px; |
| | | line-height: 1.6; |
| | | flex: 1; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .header-right { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: flex-end; |
| | | gap: 8px; |
| | | |
| | | .option-status { |
| | | .status-tag { |
| | | cursor: default; |
| | | |
| | | i { |
| | | margin-right: 4px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .config-section { |
| | | .config-title { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | margin-bottom: 20px; |
| | | padding: 8px 12px; |
| | | background: #f8f9fa; |
| | | border-radius: 4px; |
| | | |
| | | i { |
| | | color: #409eff; |
| | | font-size: 16px; |
| | | } |
| | | |
| | | span { |
| | | color: #303133; |
| | | font-weight: 600; |
| | | font-size: 14px; |
| | | } |
| | | } |
| | | |
| | | .config-form { |
| | | .config-fields { |
| | | display: grid; |
| | | grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); |
| | | gap: 20px; |
| | | margin-bottom: 20px; |
| | | |
| | | .config-field { |
| | | .config-item { |
| | | margin-bottom: 0; |
| | | |
| | | :deep(.el-form-item__label) { |
| | | font-weight: 500; |
| | | color: #606266; |
| | | padding-right: 12px; |
| | | } |
| | | |
| | | .config-tip { |
| | | font-size: 12px; |
| | | color: #909399; |
| | | margin-top: 4px; |
| | | line-height: 1.4; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .current-config { |
| | | margin-bottom: 20px; |
| | | padding: 15px; |
| | | background: #f0f9ff; |
| | | border-radius: 6px; |
| | | border: 1px solid #d0ebff; |
| | | |
| | | .config-preview { |
| | | .preview-item { |
| | | display: flex; |
| | | align-items: flex-start; |
| | | margin-bottom: 8px; |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .preview-label { |
| | | font-size: 13px; |
| | | color: #606266; |
| | | font-weight: 500; |
| | | min-width: 80px; |
| | | } |
| | | |
| | | .preview-value { |
| | | font-size: 13px; |
| | | color: #303133; |
| | | line-height: 1.5; |
| | | flex: 1; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .config-footer { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding-top: 20px; |
| | | border-top: 1px dashed #dcdfe6; |
| | | |
| | | .save-status { |
| | | flex: 1; |
| | | margin-right: 20px; |
| | | |
| | | .el-alert { |
| | | padding: 8px 16px; |
| | | border-radius: 4px; |
| | | } |
| | | } |
| | | |
| | | .config-actions { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 12px; |
| | | flex-shrink: 0; |
| | | |
| | | .el-button { |
| | | min-width: 100px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .preview-wrapper { |
| | | .preview-header { |
| | | margin-bottom: 20px; |
| | | |
| | | h4 { |
| | | margin: 0 0 12px 0; |
| | | color: #303133; |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | .preview-tags { |
| | | display: flex; |
| | | gap: 8px; |
| | | flex-wrap: wrap; |
| | | } |
| | | } |
| | | |
| | | .preview-content { |
| | | .preview-question { |
| | | margin-bottom: 20px; |
| | | padding: 16px; |
| | | background: #f8f9fa; |
| | | border-radius: 4px; |
| | | color: #606266; |
| | | line-height: 1.6; |
| | | } |
| | | |
| | | .preview-options { |
| | | .option-item { |
| | | display: block; |
| | | margin-bottom: 12px; |
| | | padding: 12px; |
| | | border-radius: 4px; |
| | | border: 1px solid #ebeef5; |
| | | transition: all 0.3s; |
| | | |
| | | &:hover { |
| | | background: #f5f7fa; |
| | | border-color: #409eff; |
| | | } |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .preview-textarea { |
| | | .el-textarea__inner { |
| | | resize: none; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .success-content { |
| | | text-align: center; |
| | | padding: 20px 0; |
| | | |
| | | .success-icon { |
| | | color: #67c23a; |
| | | font-size: 48px; |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .success-text { |
| | | font-size: 16px; |
| | | color: #606266; |
| | | margin: 0; |
| | | } |
| | | } |
| | | } |
| | | .option-config-wrapper { |
| | | .dialog-header { |
| | | margin-bottom: 20px; |
| | | padding-bottom: 15px; |
| | | border-bottom: 1px solid #ebeef5; |
| | | |
| | | h4 { |
| | | margin: 0 0 8px 0; |
| | | color: #303133; |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | .dialog-subtitle { |
| | | margin: 0; |
| | | color: #606266; |
| | | font-size: 13px; |
| | | line-height: 1.4; |
| | | } |
| | | } |
| | | |
| | | .option-list { |
| | | .option-item { |
| | | margin-bottom: 12px; |
| | | padding: 12px; |
| | | background: #f8f9fa; |
| | | border-radius: 4px; |
| | | border: 1px solid #ebeef5; |
| | | |
| | | &:hover { |
| | | border-color: #dcdfe6; |
| | | } |
| | | |
| | | .option-form { |
| | | .option-index { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | height: 100%; |
| | | color: #909399; |
| | | font-weight: 500; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | @media (max-width: 768px) { |
| | | .satisfaction-exception-config { |
| | | padding: 12px; |
| | | |
| | | .page-header { |
| | | padding: 16px; |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | .template-info { |
| | | flex-direction: column; |
| | | align-items: flex-start; |
| | | gap: 10px; |
| | | } |
| | | |
| | | .search-card { |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | .config-content { |
| | | .batch-actions-card { |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | .question-item { |
| | | .question-card { |
| | | .card-header { |
| | | flex-direction: column; |
| | | gap: 12px; |
| | | |
| | | .header-left { |
| | | flex-direction: column; |
| | | gap: 12px; |
| | | |
| | | .question-index { |
| | | flex-direction: row; |
| | | align-items: center; |
| | | min-width: auto; |
| | | |
| | | .index-number { |
| | | margin-bottom: 0; |
| | | margin-right: 12px; |
| | | } |
| | | |
| | | .index-line { |
| | | width: 100%; |
| | | height: 2px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .config-section { |
| | | .config-form { |
| | | .config-fields { |
| | | grid-template-columns: 1fr; |
| | | gap: 16px; |
| | | } |
| | | |
| | | .current-config { |
| | | padding: 12px; |
| | | } |
| | | |
| | | .config-footer { |
| | | flex-direction: column; |
| | | align-items: stretch; |
| | | gap: 12px; |
| | | |
| | | .save-status { |
| | | margin-right: 0; |
| | | margin-bottom: 8px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="Questionnairemanagement"> |
| | | <!-- ä¸ä¾§æ --> |
| | | <div class="sidecolumn"> |
| | | <div> |
| | | <el-steps simple :active="Editprogress"> |
| | | <el-step |
| | | icon="el-icon-edit" |
| | | title="åºç¡ä¿¡æ¯" |
| | | description="éæ©å®£ææ¨¡æ¿ãå½¢å¼çåºç¡ä¿¡æ¯" |
| | | ></el-step> |
| | | <el-step |
| | | icon="el-icon-user" |
| | | title="宣æå¯¹è±¡" |
| | | description="卿¬é¨éæ©å®£æç
人" |
| | | ></el-step> |
| | | </el-steps> |
| | | </div> |
| | | </div> |
| | | <!-- ä¸ä¾§æ°æ® --> |
| | | <div class="leftvlue" style="margin: 0 20px"> |
| | | <!-- åºæ¬ä¿¡æ¯ --> |
| | | <div v-if="Editprogress == 1"> |
| | | <el-alert |
| | | title="éæ©å®£ææ¨¡æ¿ãå½¢å¼çåºç¡ä¿¡æ¯" |
| | | type="success" |
| | | effect="dark" |
| | | > |
| | | </el-alert> |
| | | <div class="leftvlue-jbxx"> |
| | | <!-- åºç¡ä¿¡æ¯ --> |
| | | <div class="examine-jic"> |
| | | <div class="headline"> |
| | | <div>åºç¡ä¿¡æ¯</div> |
| | | </div> |
| | | <div class="jic-value"> |
| | | <el-form ref="form" :model="form" label-width="105px"> |
| | | <el-form-item label="åéæ¶é´ï¼" v-if="currenttype != 2"> |
| | | <el-date-picker |
| | | v-model="form.name" |
| | | type="date" |
| | | placeholder="éæ©æ¥æ" |
| | | > |
| | | </el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item label="åéæ¶é´æ®µï¼" v-if="currenttype != 2"> |
| | | <el-checkbox-group v-model="checkList"> |
| | | <el-checkbox label="ä¸åï¼8:30-11:30ï¼"></el-checkbox> |
| | | <el-checkbox label="ä¸åï¼14:30-16:30ï¼"></el-checkbox> |
| | | <el-checkbox label="å¤é´ï¼18:30-20:30ï¼"></el-checkbox> |
| | | </el-checkbox-group> |
| | | </el-form-item> |
| | | <el-form-item label="æå¡å½¢å¼"> |
| | | <el-checkbox-group v-model="checkList"> |
| | | <el-checkbox |
| | | v-for="(item, index) in checkboxlist" |
| | | :key="index" |
| | | :label="item" |
| | | ></el-checkbox> |
| | | </el-checkbox-group> |
| | | </el-form-item> |
| | | <el-form-item label="ç»ç»å½¢å¼"> |
| | | <el-radio-group v-model="form.radio"> |
| | | <el-radio :label="3">å人</el-radio> |
| | | <el-radio :label="6">å¤äºº</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | <el-form-item label="è¯é³æ¨¡æ¿" prop="region"> |
| | | <el-select v-model="form.region" placeholder="è¯·éæ©æ¨¡æ¿"> |
| | | <el-option label="ä¸å·æ¨¡æ¿" value="shanghai"></el-option> |
| | | <el-option label="äºå·æ¨¡æ¿" value="beijing"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | </div> |
| | | <div class="examine-jic"> |
| | | <div class="headline"> |
| | | <div>{{ title }}</div> |
| | | </div> |
| | | <div class="examine-jic"> |
| | | <div class="jic-value"> |
| | | <el-row :gutter="20"> |
| | | <!--ç¨æ·æ°æ®--> |
| | | |
| | | <el-form |
| | | :model="topqueryParams" |
| | | ref="queryForm" |
| | | size="small" |
| | | :inline="true" |
| | | v-show="showSearch" |
| | | label-width="98px" |
| | | > |
| | | <el-form-item label="æ§è¡ç¶æ" prop="status"> |
| | | <el-select |
| | | v-model="topqueryParams.topic" |
| | | placeholder="è¯·éæ©" |
| | | > |
| | | <el-option |
| | | v-for="item in taskoptions" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | > |
| | | </el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item |
| | | label="ç§å®¤åç§°" |
| | | v-if="currenttype == 1 || currenttype == 3" |
| | | > |
| | | <el-input |
| | | v-model="topqueryParams.name" |
| | | ></el-input> </el-form-item |
| | | ><el-form-item label="ç
åºåç§°" v-if="currenttype == 2"> |
| | | <el-input v-model="topqueryParams.name"></el-input> |
| | | </el-form-item> |
| | | <el-form-item |
| | | label="æ£è
å§å" |
| | | v-if="currenttype == 1 || currenttype == 2" |
| | | > |
| | | <el-input v-model="topqueryParams.name"></el-input> |
| | | </el-form-item> |
| | | <el-form-item |
| | | label="主治å»ç" |
| | | v-if="currenttype == 1 || currenttype == 2" |
| | | > |
| | | <el-input v-model="topqueryParams.name"></el-input> |
| | | </el-form-item> |
| | | <el-form-item |
| | | label="ç®¡åºæ¤å£«" |
| | | v-if="currenttype == 1 || currenttype == 2" |
| | | > |
| | | <el-input v-model="topqueryParams.name"></el-input> |
| | | </el-form-item> |
| | | |
| | | <el-form-item> |
| | | <el-button |
| | | type="primary" |
| | | icon="el-icon-search" |
| | | size="medium" |
| | | @click="handleQuery" |
| | | >æç´¢</el-button |
| | | > |
| | | <el-button |
| | | icon="el-icon-refresh" |
| | | size="medium" |
| | | @click="resetQuery" |
| | | >éç½®</el-button |
| | | > |
| | | </el-form-item> |
| | | </el-form> |
| | | <el-divider></el-divider> |
| | | <!-- 鿩任å¡å表 --> |
| | | <SFtable |
| | | @handleUpdate="handleUpdate" |
| | | @handleSelectionChange="handleSelectionChange" |
| | | :currentList="userList" |
| | | :tableLabel="tableLabelxj" |
| | | :controlsc="false" |
| | | :multiplechoice="false" |
| | | /> |
| | | <pagination |
| | | v-show="total > 0" |
| | | :total="total" |
| | | :page.sync="topqueryParams.pageNum" |
| | | :limit.sync="topqueryParams.pageSize" |
| | | @pagination="getList" |
| | | /> |
| | | </el-row> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <el-button type="success" @click="submitForm('ruleForm')">{{ |
| | | quote ? "ç«å³å建" : "ä»»å¡è¯¦æ
设置" |
| | | }}</el-button> |
| | | <el-button @click="resetForm('ruleForm')">éç½®</el-button> |
| | | </div> |
| | | |
| | | <!-- ä»»å¡è¯¦æ
--> |
| | | <div v-if="Editprogress == 2"> |
| | | <el-alert title="卿¬é¶æ®µéæ©ç
人" type="success" effect="dark"> |
| | | </el-alert> |
| | | <div class="leftvlue-jbxx"> |
| | | <div class="examine-jic"> |
| | | <div class="headline"> |
| | | <div>æ£è
å表</div> |
| | | </div> |
| | | <div class="examine-jic"> |
| | | <div class="jic-value"> |
| | | <el-row :gutter="20"> |
| | | <!--ç¨æ·æ°æ®--> |
| | | <el-form |
| | | :model="topqueryParams" |
| | | ref="queryForm" |
| | | size="small" |
| | | :inline="true" |
| | | v-show="showSearch" |
| | | label-width="98px" |
| | | > |
| | | <el-form-item label="æ£è
åç§°"> |
| | | <el-input v-model="topqueryParams.name"></el-input> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="æ£è
èå´" prop="status"> |
| | | <el-select |
| | | v-model="topqueryParams.searchscope" |
| | | placeholder="è¯·éæ©" |
| | | > |
| | | <el-option |
| | | v-for="item in source" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | > |
| | | </el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="æ£è
ç¶æ" prop="status"> |
| | | <el-select |
| | | v-model="topqueryParams.topic" |
| | | placeholder="è¯·éæ©" |
| | | > |
| | | <el-option |
| | | v-for="item in topicoptions" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | > |
| | | </el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="éè®¿ç»æ" prop="status"> |
| | | <el-select |
| | | v-model="topqueryParams.topic" |
| | | placeholder="è¯·éæ©" |
| | | > |
| | | <el-option |
| | | v-for="item in topicoptions" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | > |
| | | </el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="æ£è
çµè¯"> |
| | | <el-input v-model="topqueryParams.name"></el-input> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button |
| | | type="primary" |
| | | icon="el-icon-search" |
| | | size="medium" |
| | | @click="handleQuery" |
| | | >æç´¢</el-button |
| | | > |
| | | <el-button |
| | | icon="el-icon-refresh" |
| | | size="medium" |
| | | @click="resetQuery" |
| | | >éç½®</el-button |
| | | > |
| | | <el-button |
| | | icon="el-icon-upload2" |
| | | size="medium" |
| | | type="warning" |
| | | >å½åæ£è
ä¸é®åé</el-button |
| | | > |
| | | </el-form-item> |
| | | </el-form> |
| | | <el-divider></el-divider> |
| | | <el-row :gutter="10" class="mb8"> |
| | | <el-col :span="1.5"> |
| | | <el-select |
| | | v-model="tasktopic" |
| | | placeholder="è¯·éæ©æ°å¢ç±»å" |
| | | > |
| | | <el-option |
| | | v-for="item in taskoptions" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | > |
| | | </el-option> |
| | | </el-select> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <el-button |
| | | type="primary" |
| | | plain |
| | | icon="el-icon-plus" |
| | | size="medium" |
| | | :disabled="!tasktopic" |
| | | @click="handleAddpatient" |
| | | >æ°å¢</el-button |
| | | > |
| | | </el-col> |
| | | |
| | | <el-col :span="1.5"> |
| | | <el-button |
| | | type="danger" |
| | | plain |
| | | icon="el-icon-delete" |
| | | size="medium" |
| | | :disabled="multiple" |
| | | @click="handleDelete" |
| | | >å é¤</el-button |
| | | > |
| | | </el-col> |
| | | |
| | | <!-- <el-col :span="1.5"> </el-col> --> |
| | | </el-row> |
| | | <!-- é䏿£è
å表 --> |
| | | <SFtable |
| | | @handleUpdate="handleUpdate" |
| | | @handleSelectionChange="handleSelectionChange" |
| | | :currentList="sonuserList" |
| | | :tableLabel="tableLabelhz" |
| | | :controlxz="false" |
| | | /> |
| | | <pagination |
| | | v-show="total > 0" |
| | | :total="total" |
| | | :page.sync="topqueryParams.pageNum" |
| | | :limit.sync="topqueryParams.pageSize" |
| | | @pagination="getList" |
| | | /> |
| | | </el-row> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <el-button type="primary" @click="laststep()">ä¸ä¸æ¥</el-button> |
| | | <el-button type="success" @click="submitForm('ruleForm')" |
| | | >ç«å³å建</el-button |
| | | > |
| | | <el-button @click="resetForm('ruleForm')">éç½®</el-button> |
| | | </div> |
| | | </div> |
| | | <!-- æ·»å æ£è
--> |
| | | <el-dialog |
| | | title="éæ©æ£è
" |
| | | :visible.sync="dialogVisiblepatient" |
| | | width="70%" |
| | | :before-close="handleClosehz" |
| | | > |
| | | <div class="examine-jic"> |
| | | <div class="jic-value"> |
| | | <el-row :gutter="20"> |
| | | <!--ç¨æ·æ°æ®--> |
| | | <el-form |
| | | :model="patientqueryParams" |
| | | ref="queryForm" |
| | | size="small" |
| | | :inline="true" |
| | | v-show="showSearch" |
| | | label-width="98px" |
| | | > |
| | | <el-form-item label="æ£è
åç§°ï¼"> |
| | | <el-input v-model="patientqueryParams.name"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="æ£è
èå´" prop="status"> |
| | | <el-select |
| | | v-model="patientqueryParams.topic" |
| | | placeholder="è¯·éæ©" |
| | | > |
| | | <el-option |
| | | v-for="item in topicoptions" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | > |
| | | </el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="åºé¢ç§å®¤" prop="status"> |
| | | <el-select |
| | | v-model="patientqueryParams.topic" |
| | | placeholder="è¯·éæ©" |
| | | > |
| | | <el-option |
| | | v-for="item in topicoptions" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | > |
| | | </el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="åºé¢ç
åº" prop="status"> |
| | | <el-select |
| | | v-model="patientqueryParams.topic" |
| | | placeholder="è¯·éæ©" |
| | | > |
| | | <el-option |
| | | v-for="item in topicoptions" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | > |
| | | </el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button |
| | | type="primary" |
| | | icon="el-icon-search" |
| | | size="medium" |
| | | @click="handleQuery" |
| | | >æç´¢</el-button |
| | | > |
| | | <el-button |
| | | icon="el-icon-refresh" |
| | | size="medium" |
| | | @click="resetQuery" |
| | | >åæ¶å建</el-button |
| | | > |
| | | </el-form-item> |
| | | </el-form> |
| | | <!-- éæ©æ£è
å表 --> |
| | | <SFtable |
| | | @handleUpdate="handleUpdate" |
| | | @handleSelectionChange="handleSelectionChange" |
| | | :currentList="patientuserList" |
| | | :tableLabel="tableLabelhz" |
| | | :controlsc="false" |
| | | /> |
| | | </el-row> |
| | | <pagination |
| | | v-show="patienttotal > 0" |
| | | :total="patienttotal" |
| | | :page.sync="patientqueryParams.pageNum" |
| | | :limit.sync="patientqueryParams.pageSize" |
| | | @pagination="handleAddpatient" |
| | | /> |
| | | </div> |
| | | </div> |
| | | <span slot="footer" class="dialog-footer"> |
| | | <el-button @click="dialogVisiblepatient = false">å æ¶</el-button> |
| | | <el-button type="primary" @click="AddDispatchpatients" |
| | | >ç¡®å®æ·»å </el-button |
| | | > |
| | | </span> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { messagelistpatient } from "@/api/patient/homepage"; |
| | | import SFtable from "@/components/SFtable"; //è¡¨æ ¼ç»ä»¶ |
| | | |
| | | export default { |
| | | name: "ServiceDetails", |
| | | data() { |
| | | return { |
| | | title: "宣æå
容å表", |
| | | currenttype: 1, //1宣æ2é¨è¯3åºé¢4å¤è¯5使£6é®å· |
| | | Editprogress: 1, //ç¼è¾è¿åº¦ |
| | | loading: false, // é®ç½©å± |
| | | patientloading: false, // é®ç½©å± |
| | | dialogVisiblepatient: false, //æ·»å æ£è
å¼¹æ¡ |
| | | checkboxlist: [], |
| | | tableLabel: [], |
| | | // æ£è
表å |
| | | tableLabelhz: [ |
| | | { label: "æ£è
åç§°", width: "", prop: "name" }, |
| | | { label: "æ§å«", width: "", prop: "sex" }, |
| | | { label: "å¹´é¾", width: "", prop: "age" }, |
| | | { label: "å°±è¯ç§å®¤", width: "", prop: "impTemplate" }, |
| | | { label: "å
¥é¢æ¥æ", width: "", prop: "create_time" }, |
| | | { label: "å建人", width: "", prop: "update_by" }, |
| | | ], |
| | | tableLabelxj: [ |
| | | { label: "é¨è¯ç¼å·", width: "", prop: "name" }, |
| | | { label: "å§å", width: "", prop: "name" }, |
| | | { label: "å¹´é¾", width: "", prop: "age" }, |
| | | { label: "èç³»çµè¯", width: "", prop: "telcode" }, |
| | | { label: "å°±è¯ç§å®¤", width: "", prop: "impTemplate" }, |
| | | { label: "è¯æ", width: "", prop: "name" }, |
| | | { label: "åºé¢æ¶é´", width: "", prop: "name" }, |
| | | { label: "åèµ·æ¶é´", width: "", prop: "create_time" }, |
| | | { label: "ç¶æ", width: "", prop: "sex" }, |
| | | { label: "é夿¬¡æ°", width: "", prop: "update_by" }, |
| | | { label: "任塿¥æº", width: "", prop: "update_by" }, |
| | | { label: "å建人", width: "", prop: "update_by" }, |
| | | ], |
| | | tableLabelmz: [ |
| | | { label: "é¨è¯ç¼å·", width: "", prop: "name" }, |
| | | { label: "å§å", width: "", prop: "name" }, |
| | | { label: "å¹´é¾", width: "", prop: "age" }, |
| | | { label: "èç³»çµè¯", width: "", prop: "telcode" }, |
| | | { label: "å°±è¯ç§å®¤", width: "", prop: "impTemplate" }, |
| | | { label: "è¯æ", width: "", prop: "name" }, |
| | | { label: "åºé¢æ¶é´", width: "", prop: "name" }, |
| | | { label: "åèµ·æ¶é´", width: "", prop: "create_time" }, |
| | | { label: "ç¶æ", width: "", prop: "sex" }, |
| | | { label: "é夿¬¡æ°", width: "", prop: "update_by" }, |
| | | { label: "任塿¥æº", width: "", prop: "update_by" }, |
| | | { label: "å建人", width: "", prop: "update_by" }, |
| | | ], |
| | | tableLabelcy: [ |
| | | { label: "åå·¥ç¼å·", width: "", prop: "name" }, |
| | | { label: "å§å", width: "", prop: "name" }, |
| | | { label: "å¹´é¾", width: "", prop: "age" }, |
| | | { label: "èç³»çµè¯", width: "", prop: "telcode" }, |
| | | { label: "æå¨ç§å®¤", width: "", prop: "impTemplate" }, |
| | | { label: "宿æ¶é´", width: "", prop: "finishtime" }, |
| | | { label: "ç¶æ", width: "", prop: "sex" }, |
| | | { label: "é夿¬¡æ°", width: "", prop: "update_by" }, |
| | | { label: "任塿¥æº", width: "", prop: "update_by" }, |
| | | { label: "å建人", width: "", prop: "update_by" }, |
| | | ], |
| | | |
| | | topqueryParams: { |
| | | pageNum: 1, // |
| | | pageSize: 10, |
| | | searchscope:2, |
| | | }, |
| | | checkList: [], |
| | | deliverytopqueryParams: { |
| | | pageNum: 1, // |
| | | pageSize: 10, |
| | | }, |
| | | patientqueryParams: { |
| | | pageNum: 1, // |
| | | pageSize: 10, |
| | | }, |
| | | topicoptions: [], |
| | | showSearch: true, // |
| | | total: 0, // |
| | | sontotal: 0, // |
| | | patienttotal: 0, // |
| | | // é䏿°ç» |
| | | ids: [], |
| | | // éå个ç¦ç¨ |
| | | single: true, |
| | | // éå¤ä¸ªç¦ç¨ |
| | | multiple: true, |
| | | // ç¨æ·è¡¨æ ¼æ°æ® |
| | | userList: [], //模æ¿å表 |
| | | patientuserList: [], //éæ©æ£è
å表 |
| | | sonuserList: [], //é䏿£è
å表 |
| | | tasktopic: null, //æ°å¢ç±»å |
| | | form: { |
| | | name: "", |
| | | region: "", |
| | | date1: "", |
| | | date2: "", |
| | | delivery: false, |
| | | type: [], |
| | | resource: "", |
| | | desc: "", |
| | | }, |
| | | source: [ |
| | | { |
| | | value: 0, |
| | | label: "æå±æ£è
", |
| | | }, |
| | | { |
| | | value: 1, |
| | | label: "ç§å®¤æ£è
", |
| | | }, |
| | | { |
| | | value: 2, |
| | | label: "ç
åºæ£è
", |
| | | }, |
| | | ], |
| | | options: [ |
| | | { |
| | | value: "é项1", |
| | | label: "é»éç³", |
| | | }, |
| | | { |
| | | value: "é项2", |
| | | label: "åç®å¥¶", |
| | | }, |
| | | { |
| | | value: "é项5", |
| | | label: "å京ç¤é¸", |
| | | }, |
| | | ], |
| | | taskoptions: [ |
| | | { |
| | | value: "1", |
| | | label: "éç¥", |
| | | }, |
| | | { |
| | | value: "2", |
| | | label: "é访", |
| | | }, |
| | | { |
| | | value: "3", |
| | | label: "é®å·", |
| | | }, |
| | | { |
| | | value: "4", |
| | | label: "宣æ", |
| | | }, |
| | | ], |
| | | quote: false, |
| | | }; |
| | | }, |
| | | components: { SFtable }, |
| | | |
| | | created() { |
| | | this.Addsubtask(); |
| | | this.Getsubtask(); |
| | | this.Acquisitiontype(); |
| | | }, |
| | | |
| | | methods: { |
| | | // è·åå½åç±»å |
| | | Acquisitiontype() { |
| | | this.currenttype = this.$route.query.type; |
| | | console.log(this.currenttype); |
| | | if (this.currenttype == 1) { |
| | | this.title = "é¨è¯ç
人任å¡"; |
| | | this.tableLabel = this.tableLabelxj; |
| | | this.checkboxlist = [ |
| | | "å½é¢", |
| | | "å¤åªä½", |
| | | "纸质", |
| | | "çµè¯", |
| | | "çä¿¡", |
| | | "微信å
¬ä¼å·", |
| | | "微信å°ç¨åº", |
| | | "éé", |
| | | ]; |
| | | } else if (this.currenttype == 2) { |
| | | this.title = "åºé¢ç
人任å¡"; |
| | | this.tableLabel = this.tableLabelmz; |
| | | this.checkboxlist = ["å½é¢", "纸质", "çµè¯", "çä¿¡", "微信å
¬ä¼å·"]; |
| | | } else if (this.currenttype == 3) { |
| | | this.title = "å»å¡äººåä»»å¡"; |
| | | this.tableLabel = this.tableLabelcy; |
| | | this.checkboxlist = ["å½é¢", "纸质", "çµè¯", "çä¿¡", "微信å
¬ä¼å·"]; |
| | | } |
| | | }, |
| | | // ä¸ä¸æ¥ |
| | | submitForm(formName) { |
| | | if (this.Editprogress <= 3) { |
| | | return this.Editprogress++; |
| | | } |
| | | // æäº¤ |
| | | // this.$refs[formName].validate((valid, object) => { |
| | | // if (valid) { |
| | | // alert("submit!"); |
| | | // } else { |
| | | // console.log("error submit!!", object); |
| | | // return false; |
| | | // } |
| | | // }); |
| | | }, |
| | | // åä»»å¡äºçº§å¼¹æ¡ |
| | | handleAddpatient(row) { |
| | | console.log(row, "åç»ä»¶æ°æ®"); |
| | | messagelistpatient(this.patientqueryParams).then((response) => { |
| | | console.log(response); |
| | | this.patientuserList = response.rows; |
| | | this.patienttotal = response.total; |
| | | this.loading = false; |
| | | }); |
| | | this.dialogVisiblepatient = true; |
| | | }, |
| | | handleUpdate() {}, |
| | | handleDelete() {}, |
| | | handleExport() {}, |
| | | // å¤éæ¡é䏿°æ® |
| | | handleSelectionChange(selection) { |
| | | this.ids = null; |
| | | this.ids = selection.map((item) => item.patid).join(","); |
| | | // let result = this.ids.join(","); |
| | | this.multiple = !selection.length; |
| | | console.log(this.ids); |
| | | }, |
| | | getList() {}, |
| | | handleQuery() {}, |
| | | resetQuery() {}, |
| | | handleClosehz() { |
| | | this.dialogVisiblepatient = false; |
| | | }, |
| | | // ä¸ä¸æ¥ |
| | | laststep() { |
| | | this.Editprogress--; |
| | | }, |
| | | // æäº¤è¡¨å |
| | | resetForm(formName) { |
| | | this.$refs[formName].resetFields(); |
| | | }, |
| | | // é¢è§æ¨¡æ¿ |
| | | PreviewTemplate() {}, |
| | | Acknowledgereference() { |
| | | this.quote = true; |
| | | }, |
| | | // æ°å¢åä»»å¡ |
| | | Addsubtask() { |
| | | this.topqueryParams.pguid = 2; |
| | | // addsvr_prjtask(this.topqueryParams).then((res) => { |
| | | // console.log(res); |
| | | // }); |
| | | }, |
| | | // æ°å¢æ´¾éæ£è
|
| | | AddDispatchpatients() { |
| | | let objictpint = {}; |
| | | objictpint.patientes = this.ids; |
| | | objictpint.pguid = 2; |
| | | // Addpatienttask(objictpint).then((res) => { |
| | | // console.log(res); |
| | | // }); |
| | | this.dialogVisiblepatient = false; |
| | | }, |
| | | |
| | | // æ¥è¯¢åä»»å¡å表 |
| | | Getsubtask() { |
| | | this.topqueryParams.pguid = 2; |
| | | console.log(this.topqueryParams); |
| | | messagelistpatient(this.topqueryParams).then((res) => { |
| | | this.userList = res.rows; |
| | | this.total = res.total; |
| | | console.log(this.userList); |
| | | }); |
| | | }, |
| | | /** æ¥è¯¢æ£è
å表 */ |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .Questionnairemanagement { |
| | | } |
| | | .leftvlue-jbxx { |
| | | margin-top: 10px; |
| | | } |
| | | .sidecolumn { |
| | | width: 100%; |
| | | // min-height: 12vh; |
| | | margin: 20px; |
| | | margin-bottom: 0; |
| | | padding: 20px; |
| | | background: #edf1f7; |
| | | border: 1px solid #dcdfe6; |
| | | -webkit-box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12), |
| | | 0 0 6px 0 rgba(0, 0, 0, 0.04); |
| | | } |
| | | .leftvlue { |
| | | // display: flex; |
| | | // flex: 1; |
| | | width: 100%; |
| | | margin-top: 20px; |
| | | // margin: 20px; |
| | | padding: 30px; |
| | | background: #ffff; |
| | | border: 1px solid #dcdfe6; |
| | | -webkit-box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12), |
| | | 0 0 6px 0 rgba(0, 0, 0, 0.04); |
| | | } |
| | | .examine-jic { |
| | | .headline { |
| | | font-size: 24px; |
| | | border-left: 5px solid #41a1be; |
| | | padding-left: 5px; |
| | | margin-bottom: 10px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | .Add-details { |
| | | font-size: 18px; |
| | | color: #02a7f0; |
| | | cursor: pointer; |
| | | } |
| | | } |
| | | .jic-value { |
| | | font-size: 20px; |
| | | border-top: 1px solid #a7abac; |
| | | padding: 10px; |
| | | margin-bottom: 10px; |
| | | .details-jic { |
| | | padding: 10px 15px; |
| | | border: 1px solid #dcdfe6; |
| | | -webkit-box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12), |
| | | 0 0 6px 0 rgba(0, 0, 0, 0.04); |
| | | .details-title { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | margin-bottom: 10px; |
| | | div:nth-child(2) { |
| | | color: #02a7f0; |
| | | cursor: pointer; |
| | | } |
| | | } |
| | | .details-renw { |
| | | background: #e4ebfc; |
| | | padding: 15px 5px; |
| | | border-radius: 5px; |
| | | margin-bottom: 20px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | // .leftvlue-jbxx { |
| | | // margin-bottom: 50px; |
| | | // font-size: 20px; |
| | | // span { |
| | | // position: absolute; |
| | | // right: 80px; |
| | | // } |
| | | // .demo-cascader { |
| | | // margin-right: 20px; |
| | | // } |
| | | // .PreviewTemplate { |
| | | // color: #02a7f0; |
| | | // cursor: pointer; |
| | | // font-size: 20px; |
| | | // margin: 0 20px; |
| | | // } |
| | | // } |
| | | .jic-value { |
| | | font-size: 20px; |
| | | border-top: 1px solid #a7abac; |
| | | padding: 10px; |
| | | margin-bottom: 10px; |
| | | .details-jic { |
| | | padding: 10px 15px; |
| | | border: 1px solid #dcdfe6; |
| | | -webkit-box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12), |
| | | 0 0 6px 0 rgba(0, 0, 0, 0.04); |
| | | .details-title { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | margin-bottom: 10px; |
| | | div:nth-child(2) { |
| | | color: #02a7f0; |
| | | cursor: pointer; |
| | | } |
| | | } |
| | | .details-renw { |
| | | background: #e4ebfc; |
| | | padding: 15px 5px; |
| | | border-radius: 5px; |
| | | margin-bottom: 20px; |
| | | } |
| | | } |
| | | } |
| | | ::v-deep .addtopic-input { |
| | | input { |
| | | background: #02a7f0; |
| | | color: #edf1f7; |
| | | width: 150px; |
| | | } |
| | | } |
| | | ::v-deep.el-step.is-vertical .el-step__title { |
| | | font-size: 25px; |
| | | } |
| | | ::v-deep.el-row { |
| | | margin-bottom: 10px; |
| | | } |
| | | // ::v-deep.el-input--medium { |
| | | // font-size: 24px !important; |
| | | // } |
| | | ::v-deep.ruleFormaa.el-select { |
| | | display: inline-block; |
| | | position: relative; |
| | | width: 700px; |
| | | } |
| | | .el-select__tags { |
| | | font-size: 20px; |
| | | max-width: 888px !important; |
| | | } |
| | | ::v-deep.el-radio__inner { |
| | | width: 22px; |
| | | height: 22px; |
| | | } |
| | | // ::v-deep.topic-dev.el-radio__label { |
| | | // font-size: 24px; |
| | | // } |
| | | ::v-deep.el-radio-group { |
| | | span { |
| | | font-size: 24px; |
| | | } |
| | | } |
| | | ::v-deep.el-checkbox-group { |
| | | span { |
| | | font-size: 24px; |
| | | } |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <!-- StatisticsMain.vue --> |
| | | <template> |
| | | <div class="statistics-main"> |
| | | <el-tabs v-model="activeTab" @tab-click="handleTabChange"> |
| | | <el-tab-pane label="满æåº¦ç»è®¡" name="followup"> |
| | | <followup-statistics |
| | | v-if="activeTab === 'followup'" |
| | | ref="followupRef" |
| | | /> |
| | | </el-tab-pane> |
| | | <el-tab-pane label="å¤è¯éç¥ç»è®¡" name="visitStatistics"> |
| | | <visit-Statistics |
| | | v-if="activeTab === 'visitStatistics'" |
| | | ref="visitStatisticsRef" |
| | | /> |
| | | </el-tab-pane> |
| | | |
| | | </el-tabs> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import FollowupStatistics from "./components/FollowupStatistics.vue"; |
| | | import visitStatistics from "./components/visitStatistics.vue"; |
| | | import SatisfactionStatistics from "./components/SatisfactionStatistics.vue"; |
| | | |
| | | export default { |
| | | name: "StatisticsMain", |
| | | components: { |
| | | FollowupStatistics, |
| | | SatisfactionStatistics, |
| | | visitStatistics, |
| | | }, |
| | | data() { |
| | | return { |
| | | activeTab: "followup", |
| | | }; |
| | | }, |
| | | methods: { |
| | | handleTabChange(tab) { |
| | | console.log("忢å°:", tab.name); |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .statistics-main { |
| | | padding: 20px; |
| | | background: #fff; |
| | | min-height: calc(100vh - 84px); |
| | | |
| | | ::v-deep .el-tabs__header { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | ::v-deep .el-tabs__item { |
| | | font-size: 16px; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | ::v-deep .el-tabs__nav-wrap::after { |
| | | height: 1px; |
| | | } |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="followup-statistics"> |
| | | <div class="query-section"> |
| | | <el-form |
| | | :model="queryParams" |
| | | ref="queryForm" |
| | | size="medium" |
| | | :inline="true" |
| | | label-width="100px" |
| | | class="query-form" |
| | | > |
| | | <el-form-item label="ç»è®¡ç±»å" prop="statisticaltype"> |
| | | <el-select |
| | | v-model="queryParams.statisticaltype" |
| | | placeholder="è¯·éæ©ç»è®¡ç±»å" |
| | | clearable |
| | | @change="handleStatisticalTypeChange" |
| | | > |
| | | <el-option |
| | | v-for="item in Statisticallist" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <!-- ç
åºéæ© --> |
| | | <el-form-item |
| | | v-if="queryParams.statisticaltype == 1" |
| | | label="ç
åº" |
| | | prop="leavehospitaldistrictcodes" |
| | | > |
| | | <el-select |
| | | v-model="queryParams.leavehospitaldistrictcodes" |
| | | placeholder="è¯·éæ©ç
åº" |
| | | multiple |
| | | collapse-tags |
| | | filterable |
| | | clearable |
| | | style="width: 300px" |
| | | > |
| | | <el-option |
| | | v-for="item in flatArrayhospit" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <!-- ç§å®¤éæ© --> |
| | | <el-form-item |
| | | v-if="queryParams.statisticaltype == 2" |
| | | label="ç§å®¤" |
| | | prop="deptcodes" |
| | | > |
| | | <el-select |
| | | v-model="queryParams.deptcodes" |
| | | placeholder="è¯·éæ©ç§å®¤" |
| | | multiple |
| | | collapse-tags |
| | | filterable |
| | | clearable |
| | | style="width: 300px" |
| | | > |
| | | <el-option |
| | | v-for="item in flatArraydept" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="æå¡ç±»å" prop="serviceType"> |
| | | <el-select |
| | | v-model="queryParams.serviceType" |
| | | placeholder="è¯·éæ©æå¡ç±»å" |
| | | multiple |
| | | collapse-tags |
| | | clearable |
| | | style="width: 300px" |
| | | > |
| | | <el-option |
| | | v-for="item in options" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="é访æ¶é´" prop="dateRange"> |
| | | <el-date-picker |
| | | v-model="queryParams.dateRange" |
| | | type="daterange" |
| | | range-separator="è³" |
| | | start-placeholder="å¼å§æ¥æ" |
| | | end-placeholder="ç»ææ¥æ" |
| | | value-format="yyyy-MM-dd" |
| | | :picker-options="pickerOptions" |
| | | style="width: 380px" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item> |
| | | <el-button |
| | | type="primary" |
| | | icon="el-icon-search" |
| | | @click="handleQuery" |
| | | :loading="loading" |
| | | > |
| | | æç´¢ |
| | | </el-button> |
| | | <el-button icon="el-icon-refresh" @click="resetQuery"> |
| | | éç½® |
| | | </el-button> |
| | | <el-button |
| | | type="warning" |
| | | icon="el-icon-download" |
| | | @click="handleExport" |
| | | :disabled="!userList.length" |
| | | > |
| | | å¯¼åº |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | |
| | | <div class="table-section"> |
| | | <el-table |
| | | v-loading="loading" |
| | | :data="userList" |
| | | :border="true" |
| | | style="width: 100%" |
| | | @selection-change="handleSelectionChange" |
| | | :row-key="getRowKey" |
| | | > |
| | | <!-- ç
åºå --> |
| | | <el-table-column |
| | | v-if="queryParams.statisticaltype == 1" |
| | | label="åºé¢ç
åº" |
| | | align="center" |
| | | sortable |
| | | key="leavehospitaldistrictname" |
| | | prop="leavehospitaldistrictname" |
| | | :show-overflow-tooltip="true" |
| | | :sort-method="sortChineseNumber" |
| | | min-width="120" |
| | | /> |
| | | |
| | | <!-- ç§å®¤å --> |
| | | <el-table-column |
| | | v-if="queryParams.statisticaltype == 2" |
| | | label="ç§å®¤" |
| | | align="center" |
| | | key="deptname" |
| | | prop="deptname" |
| | | :show-overflow-tooltip="true" |
| | | min-width="120" |
| | | /> |
| | | |
| | | <el-table-column |
| | | label="åºé¢äººæ¬¡" |
| | | align="center" |
| | | key="dischargeCount" |
| | | prop="dischargeCount" |
| | | min-width="100" |
| | | /> |
| | | |
| | | <el-table-column |
| | | label="æ éé访人次" |
| | | align="center" |
| | | key="nonFollowUp" |
| | | prop="nonFollowUp" |
| | | min-width="120" |
| | | /> |
| | | |
| | | <el-table-column |
| | | label="åºé访人次" |
| | | align="center" |
| | | key="followUpNeeded" |
| | | prop="followUpNeeded" |
| | | min-width="120" |
| | | /> |
| | | |
| | | <el-table-column |
| | | label="é访ç" |
| | | align="center" |
| | | key="followUpRate" |
| | | prop="followUpRate" |
| | | min-width="100" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span |
| | | v-if=" |
| | | scope.row.followUpRate !== null && |
| | | scope.row.followUpRate !== undefined |
| | | " |
| | | > |
| | | {{ scope.row.followUpRate }} |
| | | </span> |
| | | <span v-else>-</span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="åæ¶ç" |
| | | align="center" |
| | | key="rate" |
| | | prop="rate" |
| | | min-width="100" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | v-if="scope.row.rate !== null && scope.row.rate !== undefined" |
| | | type="text" |
| | | @click="handleSeedetails(scope.row)" |
| | | > |
| | | {{ formatPercent(scope.row.rate) }} |
| | | </el-button> |
| | | <span v-else style="color: #909399">-</span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="满æåº¦é¢ç®æ»é" |
| | | align="center" |
| | | key="joyAllCount" |
| | | prop="joyAllCount" |
| | | min-width="140" |
| | | /> |
| | | |
| | | <el-table-column |
| | | label="满æåº¦å¡«æ¥é" |
| | | align="center" |
| | | key="joyCount" |
| | | prop="joyCount" |
| | | min-width="120" |
| | | /> |
| | | |
| | | <el-table-column |
| | | label="宿æ¯ç" |
| | | align="center" |
| | | key="joyTotal" |
| | | prop="joyTotal" |
| | | min-width="100" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span |
| | | v-if=" |
| | | scope.row.joyTotal !== null && scope.row.joyTotal !== undefined |
| | | " |
| | | > |
| | | {{ formatPercent(scope.row.joyTotal) }} |
| | | </span> |
| | | <span v-else>-</span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column label="æä½" align="center" fixed="right" width="120"> |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="getinfo(scope.row)"> |
| | | <i class="el-icon-s-order" style="margin-right: 4px"></i> |
| | | æ¥ç详æ
|
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | |
| | | <!-- å页 --> |
| | | <div class="pagination-section" v-if="total > 0"> |
| | | <el-pagination |
| | | background |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | :current-page="queryParams.pageNum" |
| | | :page-size="queryParams.pageSize" |
| | | :page-sizes="[10, 20, 30, 50]" |
| | | :total="total" |
| | | @size-change="handleSizeChange" |
| | | @current-change="handlePageChange" |
| | | /> |
| | | </div> |
| | | |
| | | <!-- æªåæ¶é访详æ
å¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | title="æªåæ¶é访æ£è
æå¡" |
| | | :visible.sync="SeedetailsVisible" |
| | | width="80%" |
| | | :close-on-click-modal="false" |
| | | > |
| | | <SeedetailsDialog |
| | | v-if="SeedetailsVisible" |
| | | :row-data="currentRow" |
| | | :query-params="queryParams" |
| | | @close="SeedetailsVisible = false" |
| | | /> |
| | | </el-dialog> |
| | | |
| | | <!-- 满æåº¦è¯¦æ
å¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | :visible.sync="topicVisible" |
| | | width="60%" |
| | | :close-on-click-modal="false" |
| | | > |
| | | <template #title> |
| | | <div style="display: flex; align-items: center"> |
| | | <i |
| | | class="el-icon-s-data" |
| | | style="margin-right: 8px; color: #409eff" |
| | | ></i> |
| | | <span>{{ topicvalue.name }}</span> |
| | | <span style="margin-left: 10px; color: #666; font-size: 14px" |
| | | >满æåº¦ææ 详æ
</span |
| | | > |
| | | </div> |
| | | </template> |
| | | <topic-dialog |
| | | v-if="topicVisible" |
| | | :row-data="currentRow" |
| | | :topicList="topiclist" |
| | | :query-params="queryParams" |
| | | @close="topicVisible = false" |
| | | /> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { |
| | | getSfStatisticsJoy, |
| | | getSfStatisticsJoyInfo, |
| | | selectTimelyRate, |
| | | } from "@/api/system/user"; |
| | | import ExcelJS from "exceljs"; |
| | | import { saveAs } from "file-saver"; |
| | | import SeedetailsDialog from "./components/SeedetailsDialog.vue"; |
| | | import TopicDialog from "./components/TopicDialog.vue"; |
| | | |
| | | export default { |
| | | name: "FollowupStatistics", |
| | | components: { |
| | | SeedetailsDialog, |
| | | TopicDialog, |
| | | }, |
| | | data() { |
| | | return { |
| | | // æ¥è¯¢åæ° |
| | | queryParams: { |
| | | statisticaltype: 1, |
| | | leavehospitaldistrictcodes: ["all"], |
| | | deptcodes: [], |
| | | serviceType: [2], |
| | | dateRange: [], |
| | | pageNum: 1, |
| | | pageSize: 20, |
| | | }, |
| | | |
| | | // ç»è®¡ç±»åå表 |
| | | Statisticallist: [ |
| | | { label: "ç
åºç»è®¡", value: 1 }, |
| | | { label: "ç§å®¤ç»è®¡", value: 2 }, |
| | | ], |
| | | |
| | | // ç
åºå表 |
| | | flatArrayhospit: [], |
| | | |
| | | // ç§å®¤å表 |
| | | flatArraydept: [], |
| | | |
| | | // æå¡ç±»åé项 |
| | | options: [], |
| | | |
| | | // è¡¨æ ¼æ°æ® |
| | | userList: [], |
| | | |
| | | // æ»æ¡æ° |
| | | total: 0, |
| | | |
| | | // å è½½ç¶æ |
| | | loading: false, |
| | | |
| | | // éä¸çè¡ |
| | | ids: [], |
| | | single: true, |
| | | multiple: true, |
| | | |
| | | // å½åæä½çè¡ |
| | | currentRow: null, |
| | | |
| | | // å¯¹è¯æ¡æ¾ç¤ºæ§å¶ |
| | | SeedetailsVisible: false, |
| | | topicVisible: false, |
| | | |
| | | // 满æåº¦è¯¦æ
æ°æ® |
| | | topiclist: [], |
| | | topicvalue: { |
| | | name: "", |
| | | }, |
| | | |
| | | // æ¥æéæ©å¨é项 |
| | | pickerOptions: { |
| | | shortcuts: [ |
| | | { |
| | | text: "æè¿ä¸å¨", |
| | | onClick(picker) { |
| | | const end = new Date(); |
| | | const start = new Date(); |
| | | start.setTime(start.getTime() - 3600 * 1000 * 24 * 7); |
| | | picker.$emit("pick", [start, end]); |
| | | }, |
| | | }, |
| | | { |
| | | text: "æè¿ä¸ä¸ªæ", |
| | | onClick(picker) { |
| | | const end = new Date(); |
| | | const start = new Date(); |
| | | start.setTime(start.getTime() - 3600 * 1000 * 24 * 30); |
| | | picker.$emit("pick", [start, end]); |
| | | }, |
| | | }, |
| | | { |
| | | text: "æè¿ä¸ä¸ªæ", |
| | | onClick(picker) { |
| | | const end = new Date(); |
| | | const start = new Date(); |
| | | start.setTime(start.getTime() - 3600 * 1000 * 24 * 90); |
| | | picker.$emit("pick", [start, end]); |
| | | }, |
| | | }, |
| | | ], |
| | | disabledDate(time) { |
| | | return time.getTime() > Date.now(); |
| | | }, |
| | | }, |
| | | }; |
| | | }, |
| | | |
| | | created() { |
| | | this.initData(); |
| | | }, |
| | | |
| | | methods: { |
| | | // åå§åæ°æ® |
| | | async initData() { |
| | | await this.getDeptTree(); |
| | | await this.getList(); |
| | | }, |
| | | |
| | | // è·åç§å®¤æ |
| | | getDeptTree() { |
| | | // è·åæå¡ç±»å |
| | | this.options = this.$store.getters.tasktypes || []; |
| | | |
| | | // è·åç§å®¤å表 |
| | | this.flatArraydept = (this.$store.getters.belongDepts || []).map( |
| | | (dept) => { |
| | | return { |
| | | label: dept.deptName, |
| | | value: dept.deptCode, |
| | | }; |
| | | } |
| | | ); |
| | | |
| | | // è·åç
åºå表 |
| | | this.flatArrayhospit = (this.$store.getters.belongWards || []).map( |
| | | (ward) => { |
| | | return { |
| | | label: ward.districtName, |
| | | value: ward.districtCode, |
| | | }; |
| | | } |
| | | ); |
| | | |
| | | // æ·»å å
¨é¨é项 |
| | | this.flatArraydept.push({ label: "å
¨é¨", value: "all" }); |
| | | this.flatArrayhospit.push({ label: "å
¨é¨", value: "all" }); |
| | | }, |
| | | |
| | | // è·åç»è®¡å表 |
| | | async getList() { |
| | | this.loading = true; |
| | | try { |
| | | // å¤çæ¥è¯¢åæ° |
| | | const params = { |
| | | configKey: "joyCount", |
| | | ...this.queryParams, |
| | | }; |
| | | |
| | | // å¤çæ¥æèå´ |
| | | if ( |
| | | this.queryParams.dateRange && |
| | | this.queryParams.dateRange.length === 2 |
| | | ) { |
| | | params.startTime = this.queryParams.dateRange[0]; |
| | | params.endTime = this.queryParams.dateRange[1]; |
| | | } |
| | | |
| | | // å¤çç
åº/ç§å®¤éæ© |
| | | if (params.statisticaltype == 1) { |
| | | // ç
åºç»è®¡ |
| | | if (params.leavehospitaldistrictcodes.includes("all")) { |
| | | // 妿鿩äº"å
¨é¨"ï¼åç§»é¤"all"å¼ |
| | | params.leavehospitaldistrictcodes = |
| | | params.leavehospitaldistrictcodes.filter( |
| | | (item) => item !== "all" |
| | | ); |
| | | // 妿éè¦ä¼ ææç
åºä»£ç ï¼å¯ä»¥ä»storeä¸è·å |
| | | params.leavehospitaldistrictcodes = ( |
| | | this.$store.getters.belongWards || [] |
| | | ).map((ward) => ward.districtCode); |
| | | } |
| | | } else if (params.statisticaltype == 2) { |
| | | // ç§å®¤ç»è®¡ |
| | | if (params.deptcodes.includes("all")) { |
| | | // 妿鿩äº"å
¨é¨"ï¼åç§»é¤"all"å¼ |
| | | params.deptcodes = params.deptcodes.filter( |
| | | (item) => item !== "all" |
| | | ); |
| | | // 妿éè¦ä¼ ææç§å®¤ä»£ç ï¼å¯ä»¥ä»storeä¸è·å |
| | | params.deptcodes = (this.$store.getters.belongDepts || []).map( |
| | | (dept) => dept.deptCode |
| | | ); |
| | | } |
| | | } |
| | | |
| | | const response = await getSfStatisticsJoy(params); |
| | | this.userList = this.customSort(response.data) || []; |
| | | this.total = response.total || 0; |
| | | } catch (error) { |
| | | console.error("è·åç»è®¡å表失败:", error); |
| | | this.$message.error("è·åæ°æ®å¤±è´¥"); |
| | | } finally { |
| | | this.loading = false; |
| | | } |
| | | }, |
| | | sortChineseNumber(aRow, bRow) { |
| | | const a = aRow.leavehospitaldistrictname; |
| | | const b = bRow.leavehospitaldistrictname; |
| | | |
| | | // 䏿æ°åå°é¿æä¼¯æ°åçæ å°ï¼æ©å±å°45ï¼ |
| | | const chineseNumMap = { |
| | | ä¸: 1, |
| | | äº: 2, |
| | | ä¸: 3, |
| | | å: 4, |
| | | äº: 5, |
| | | å
: 6, |
| | | ä¸: 7, |
| | | å
«: 8, |
| | | ä¹: 9, |
| | | å: 10, |
| | | åä¸: 11, |
| | | åäº: 12, |
| | | åä¸: 13, |
| | | åå: 14, |
| | | åäº: 15, |
| | | åå
: 16, |
| | | åä¸: 17, |
| | | åå
«: 18, |
| | | åä¹: 19, |
| | | äºå: 20, |
| | | äºåä¸: 21, |
| | | äºåäº: 22, |
| | | äºåä¸: 23, |
| | | äºåå: 24, |
| | | äºåäº: 25, |
| | | äºåå
: 26, |
| | | äºåä¸: 27, |
| | | äºåå
«: 28, |
| | | äºåä¹: 29, |
| | | ä¸å: 30, |
| | | ä¸åä¸: 31, |
| | | ä¸åäº: 32, |
| | | ä¸åä¸: 33, |
| | | ä¸åå: 34, |
| | | ä¸åäº: 35, |
| | | ä¸åå
: 36, |
| | | ä¸åä¸: 37, |
| | | ä¸åå
«: 38, |
| | | ä¸åä¹: 39, |
| | | åå: 40, |
| | | ååä¸: 41, |
| | | ååäº: 42, |
| | | ååä¸: 43, |
| | | ååå: 44, |
| | | ååäº: 45, |
| | | }; |
| | | |
| | | // æå䏿æ°å |
| | | const getNumberFromText = (text) => { |
| | | if (!text || typeof text !== "string") return -1; |
| | | |
| | | // å¹é
䏿æ°åï¼æ¯æä¸å°ååäº |
| | | const match = text.match(/^([ä¸äºä¸åäºå
ä¸å
«ä¹å]+)/); |
| | | |
| | | if (match && match[1]) { |
| | | const chineseNum = match[1]; |
| | | return chineseNumMap[chineseNum] !== undefined |
| | | ? chineseNumMap[chineseNum] |
| | | : -1; |
| | | } |
| | | |
| | | // å¦ææ²¡æå¹é
å°ä¸ææ°åï¼å°è¯å¹é
é¿æä¼¯æ°å |
| | | const arabicMatch = text.match(/^(\d+)/); |
| | | if (arabicMatch && arabicMatch[1]) { |
| | | const num = parseInt(arabicMatch[1], 10); |
| | | return num >= 1 && num <= 45 ? num : -1; |
| | | } |
| | | |
| | | return -1; |
| | | }; |
| | | |
| | | const numA = getNumberFromText(a); |
| | | const numB = getNumberFromText(b); |
| | | |
| | | // å¤çæ æ³è§£æçæ
åµ |
| | | if (numA === -1 && numB === -1) { |
| | | return (a || "").localeCompare(b || ""); |
| | | } |
| | | if (numA === -1) return 1; |
| | | if (numB === -1) return -1; |
| | | |
| | | return numA - numB; |
| | | }, |
| | | customSort(data) { |
| | | // å®ä¹æ¨ææçç
åºé¡ºåºï¼æ©å±å°ååäºï¼ |
| | | const order = [ |
| | | "ä¸", |
| | | "äº", |
| | | "ä¸", |
| | | "å", |
| | | "äº", |
| | | "å
", |
| | | "ä¸", |
| | | "å
«", |
| | | "ä¹", |
| | | "å", |
| | | "åä¸", |
| | | "åäº", |
| | | "åä¸", |
| | | "åå", |
| | | "åäº", |
| | | "åå
", |
| | | "åä¸", |
| | | "åå
«", |
| | | "åä¹", |
| | | "äºå", |
| | | "äºåä¸", |
| | | "äºåäº", |
| | | "äºåä¸", |
| | | "äºåå", |
| | | "äºåäº", |
| | | "äºåå
", |
| | | "äºåä¸", |
| | | "äºåå
«", |
| | | "äºåä¹", |
| | | "ä¸å", |
| | | "ä¸åä¸", |
| | | "ä¸åäº", |
| | | "ä¸åä¸", |
| | | "ä¸åå", |
| | | "ä¸åäº", |
| | | "ä¸åå
", |
| | | "ä¸åä¸", |
| | | "ä¸åå
«", |
| | | "ä¸åä¹", |
| | | "åå", |
| | | "ååä¸", |
| | | "ååäº", |
| | | "ååä¸", |
| | | "ååå", |
| | | "ååäº", |
| | | ]; |
| | | |
| | | return data.sort((a, b) => { |
| | | // æåç
åºåç§°ä¸ç䏿æ°åé¨å |
| | | const getIndex = (name) => { |
| | | if (!name || typeof name !== "string") return -1; |
| | | |
| | | // å¹é
䏿æ°å |
| | | const chineseMatch = name.match(/^([ä¸äºä¸åäºå
ä¸å
«ä¹å]+)/); |
| | | if (chineseMatch && chineseMatch[1]) { |
| | | return order.indexOf(chineseMatch[1]); |
| | | } |
| | | |
| | | // å¹é
é¿æä¼¯æ°å |
| | | const arabicMatch = name.match(/^(\d+)/); |
| | | if (arabicMatch && arabicMatch[1]) { |
| | | const num = parseInt(arabicMatch[1], 10); |
| | | if (num >= 1 && num <= 45) { |
| | | return num - 1; // å 为æ°ç»ç´¢å¼ä»0å¼å§ |
| | | } |
| | | } |
| | | |
| | | return -1; |
| | | }; |
| | | |
| | | const indexA = getIndex(a.leavehospitaldistrictname); |
| | | const indexB = getIndex(b.leavehospitaldistrictname); |
| | | |
| | | // æåºé»è¾ |
| | | if (indexA === -1 && indexB === -1) { |
| | | return (a.leavehospitaldistrictname || "").localeCompare( |
| | | b.leavehospitaldistrictname || "" |
| | | ); |
| | | } |
| | | if (indexA === -1) return 1; |
| | | if (indexB === -1) return -1; |
| | | return indexA - indexB; |
| | | }); |
| | | }, |
| | | // å¤çç»è®¡ç±»ååå |
| | | handleStatisticalTypeChange(value) { |
| | | if (value === 1) { |
| | | this.queryParams.deptcodes = []; |
| | | } else { |
| | | this.queryParams.leavehospitaldistrictcodes = []; |
| | | } |
| | | this.queryParams.pageNum = 1; |
| | | this.getList(); |
| | | }, |
| | | |
| | | // å¤çæ¥è¯¢ |
| | | handleQuery() { |
| | | this.queryParams.pageNum = 1; |
| | | this.getList(); |
| | | }, |
| | | |
| | | // éç½®æ¥è¯¢ |
| | | resetQuery() { |
| | | this.queryParams = { |
| | | statisticaltype: 1, |
| | | leavehospitaldistrictcodes: [], |
| | | deptcodes: [], |
| | | serviceType: [2], |
| | | dateRange: [], |
| | | pageNum: 1, |
| | | pageSize: 20, |
| | | }; |
| | | this.getList(); |
| | | }, |
| | | |
| | | // å¤çå页大å°åå |
| | | handleSizeChange(size) { |
| | | this.queryParams.pageSize = size; |
| | | this.queryParams.pageNum = 1; |
| | | this.getList(); |
| | | }, |
| | | |
| | | // å¤ç页ç åå |
| | | handlePageChange(page) { |
| | | this.queryParams.pageNum = page; |
| | | this.getList(); |
| | | }, |
| | | |
| | | // å¤çè¡éæ© |
| | | handleSelectionChange(selection) { |
| | | this.ids = selection.map((item) => item.id); |
| | | this.single = selection.length !== 1; |
| | | this.multiple = !selection.length; |
| | | }, |
| | | |
| | | // è·åè¡key |
| | | getRowKey(row) { |
| | | return row.statisticaltype === 1 |
| | | ? row.leavehospitaldistrictcode |
| | | : row.deptcode; |
| | | }, |
| | | |
| | | // æ ¼å¼åç¾åæ¯ |
| | | formatPercent(value) { |
| | | if (value === null || value === undefined) return "-"; |
| | | const num = parseFloat(value); |
| | | if (isNaN(num)) return "-"; |
| | | return `${(num * 100).toFixed(2)}%`; |
| | | }, |
| | | |
| | | // æ¥çæªåæ¶é访详æ
|
| | | handleSeedetails(row) { |
| | | this.currentRow = row; |
| | | this.SeedetailsVisible = true; |
| | | }, |
| | | |
| | | // æ¥ç满æåº¦è¯¦æ
|
| | | async getinfo(row) { |
| | | this.currentRow = row; |
| | | |
| | | try { |
| | | // å¤çæ¥è¯¢åæ° |
| | | const params = { |
| | | configKey: "joyCount", |
| | | ...this.queryParams, |
| | | }; |
| | | |
| | | // å¤çæ¥æèå´ |
| | | if ( |
| | | this.queryParams.dateRange && |
| | | this.queryParams.dateRange.length === 2 |
| | | ) { |
| | | params.startTime = this.queryParams.dateRange[0]; |
| | | params.endTime = this.queryParams.dateRange[1]; |
| | | } |
| | | |
| | | if (this.queryParams.statisticaltype == 1) { |
| | | this.topicvalue.name = row.leavehospitaldistrictname; |
| | | params.leavehospitaldistrictcodes = [row.leavehospitaldistrictcode]; |
| | | } else { |
| | | this.topicvalue.name = row.deptname; |
| | | params.deptcodes = [row.deptcode]; |
| | | } |
| | | |
| | | const response = await getSfStatisticsJoyInfo(params); |
| | | this.topiclist = response.data || []; |
| | | this.topicVisible = true; |
| | | |
| | | } catch (error) { |
| | | console.error("è·å满æåº¦è¯¦æ
失败:", error); |
| | | this.$message.error("è·å详æ
失败"); |
| | | } |
| | | }, |
| | | |
| | | // å¯¼åºæ°æ® |
| | | async handleExport() { |
| | | if (!this.userList.length) { |
| | | this.$message.warning("æ²¡ææ°æ®å¯å¯¼åº"); |
| | | return; |
| | | } |
| | | |
| | | try { |
| | | this.loading = true; |
| | | |
| | | // æå»ºæ¥æèå´å符串 |
| | | let dateRangeString = ""; |
| | | let sheetNameSuffix = ""; |
| | | |
| | | if ( |
| | | this.queryParams.dateRange && |
| | | this.queryParams.dateRange.length === 2 |
| | | ) { |
| | | const startDateFormatted = this.queryParams.dateRange[0]; |
| | | const endDateFormatted = this.queryParams.dateRange[1]; |
| | | dateRangeString = `${startDateFormatted}è³${endDateFormatted}`; |
| | | sheetNameSuffix = `${startDateFormatted}è³${endDateFormatted}`; |
| | | } else { |
| | | const now = new Date(); |
| | | const currentMonth = now.getMonth() + 1; |
| | | dateRangeString = `${currentMonth}æ`; |
| | | sheetNameSuffix = `${currentMonth}æ`; |
| | | } |
| | | |
| | | const excelName = `é访ç»è®¡è¡¨_${dateRangeString}.xlsx`; |
| | | const worksheetName = `é访ç»è®¡_${sheetNameSuffix}`; |
| | | |
| | | // å建Excelå·¥ä½ç°¿ |
| | | const workbook = new ExcelJS.Workbook(); |
| | | const worksheet = workbook.addWorksheet(worksheetName); |
| | | |
| | | // å®ä¹æ ·å¼ |
| | | const titleStyle = { |
| | | font: { name: "微软é
é»", size: 16, bold: true }, |
| | | fill: { |
| | | type: "pattern", |
| | | pattern: "solid", |
| | | fgColor: { argb: "FFE6F3FF" }, |
| | | }, |
| | | alignment: { vertical: "middle", horizontal: "center" }, |
| | | border: { |
| | | top: { style: "thin", color: { argb: "FFD0D0D0" } }, |
| | | left: { style: "thin", color: { argb: "FFD0D0D0" } }, |
| | | bottom: { style: "thin", color: { argb: "FFD0D0D0" } }, |
| | | right: { style: "thin", color: { argb: "FFD0D0D0" } }, |
| | | }, |
| | | }; |
| | | |
| | | const headerStyle = { |
| | | font: { name: "微软é
é»", size: 11, bold: true }, |
| | | fill: { |
| | | type: "pattern", |
| | | pattern: "solid", |
| | | fgColor: { argb: "FFF5F7FA" }, |
| | | }, |
| | | alignment: { vertical: "middle", horizontal: "center" }, |
| | | border: { |
| | | top: { style: "thin", color: { argb: "FFD0D0D0" } }, |
| | | left: { style: "thin", color: { argb: "FFD0D0D0" } }, |
| | | bottom: { style: "thin", color: { argb: "FFD0D0D0" } }, |
| | | right: { style: "thin", color: { argb: "FFD0D0D0" } }, |
| | | }, |
| | | }; |
| | | |
| | | const cellStyle = { |
| | | font: { name: "å®ä½", size: 10 }, |
| | | alignment: { vertical: "middle", horizontal: "center" }, |
| | | border: { |
| | | top: { style: "thin", color: { argb: "FFD0D0D0" } }, |
| | | left: { style: "thin", color: { argb: "FFD0D0D0" } }, |
| | | bottom: { style: "thin", color: { argb: "FFD0D0D0" } }, |
| | | right: { style: "thin", color: { argb: "FFD0D0D0" } }, |
| | | }, |
| | | }; |
| | | |
| | | // æ·»å æ»æ é¢ |
| | | worksheet.mergeCells(1, 1, 1, 10); |
| | | const titleCell = worksheet.getCell(1, 1); |
| | | titleCell.value = `é访ç»è®¡è¡¨ï¼${sheetNameSuffix}ï¼`; |
| | | titleCell.style = titleStyle; |
| | | worksheet.getRow(1).height = 35; |
| | | |
| | | // æ·»å 表头 |
| | | const headers = [ |
| | | this.queryParams.statisticaltype == 1 ? "åºé¢ç
åº" : "ç§å®¤", |
| | | "åºé¢äººæ¬¡", |
| | | "æ éé访人次", |
| | | "åºé访人次", |
| | | "é访ç", |
| | | "åæ¶ç", |
| | | "满æåº¦é¢ç®æ»é", |
| | | "满æåº¦å¡«æ¥é", |
| | | "宿æ¯ç", |
| | | ]; |
| | | |
| | | const headerRow = worksheet.addRow(headers); |
| | | headerRow.eachCell((cell) => { |
| | | cell.style = headerStyle; |
| | | }); |
| | | headerRow.height = 25; |
| | | |
| | | // æ·»å æ°æ®è¡ |
| | | this.userList.forEach((item) => { |
| | | const dataRow = worksheet.addRow([ |
| | | this.queryParams.statisticaltype == 1 |
| | | ? item.leavehospitaldistrictname |
| | | : item.deptname, |
| | | item.dischargeCount || 0, |
| | | item.nonFollowUp || 0, |
| | | item.followUpNeeded || 0, |
| | | item.followUpRate || "0%", |
| | | item.rate ? this.formatPercent(item.rate) : "0%", |
| | | item.joyAllCount || 0, |
| | | item.joyCount || 0, |
| | | item.joyTotal ? this.formatPercent(item.joyTotal) : "0%", |
| | | ]); |
| | | |
| | | dataRow.eachCell((cell) => { |
| | | cell.style = cellStyle; |
| | | }); |
| | | dataRow.height = 22; |
| | | }); |
| | | |
| | | // 设置å宽 |
| | | worksheet.columns = [ |
| | | { width: 20 }, |
| | | { width: 12 }, |
| | | { width: 12 }, |
| | | { width: 12 }, |
| | | { width: 12 }, |
| | | { width: 12 }, |
| | | { width: 15 }, |
| | | { width: 15 }, |
| | | { width: 12 }, |
| | | ]; |
| | | |
| | | // çæå¹¶ä¸è½½æä»¶ |
| | | const buffer = await workbook.xlsx.writeBuffer(); |
| | | const blob = new Blob([buffer], { |
| | | type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", |
| | | }); |
| | | |
| | | saveAs(blob, excelName); |
| | | this.$message.success("å¯¼åºæå"); |
| | | } catch (error) { |
| | | console.error("导åºå¤±è´¥:", error); |
| | | this.$message.error(`导åºå¤±è´¥: ${error.message}`); |
| | | } finally { |
| | | this.loading = false; |
| | | } |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .followup-statistics { |
| | | .query-section { |
| | | background: #fff; |
| | | padding: 20px; |
| | | border-radius: 4px; |
| | | margin-bottom: 20px; |
| | | |
| | | .query-form { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | |
| | | ::v-deep .el-form-item { |
| | | margin-bottom: 20px; |
| | | |
| | | &:not(:last-child) { |
| | | margin-right: 20px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .table-section { |
| | | background: #fff; |
| | | padding: 20px; |
| | | border-radius: 4px; |
| | | margin-bottom: 20px; |
| | | |
| | | ::v-deep .el-table { |
| | | th { |
| | | background-color: #f8f9fa; |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .pagination-section { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | background: #fff; |
| | | padding: 20px; |
| | | border-radius: 4px; |
| | | } |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="satisfaction-statistics"> |
| | | <!-- æ¥è¯¢æ¡ä»¶åºå --> |
| | | <div class="query-section"> |
| | | <el-card shadow="never"> |
| | | <el-form |
| | | :model="queryParams" |
| | | ref="queryForm" |
| | | size="medium" |
| | | :inline="true" |
| | | label-width="100px" |
| | | class="query-form" |
| | | > |
| | | <el-form-item label="ç»è®¡ç±»å" prop="patientSource"> |
| | | <el-select |
| | | v-model="queryParams.type" |
| | | placeholder="è¯·éæ©ç»è®¡ç±»å" |
| | | clearable |
| | | style="width: 100%" |
| | | > |
| | | <el-option label="é®å·ç±»å" :value="2" /> |
| | | <el-option label="è¯é³ç±»å" :value="1" /> |
| | | <el-option label="å
¨é¨" :value="null" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="ç§å®¤" prop="deptCode"> |
| | | <el-select |
| | | v-model="queryParams.deptCode" |
| | | placeholder="è¯·éæ©ç§å®¤" |
| | | clearable |
| | | filterable |
| | | style="width: 200px" |
| | | @change="handleDeptChange" |
| | | > |
| | | <el-option |
| | | v-for="dept in deptList" |
| | | :key="dept.value" |
| | | :label="dept.label" |
| | | :value="dept.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="ç
åº" prop="wardCode"> |
| | | <el-select |
| | | v-model="queryParams.wardCode" |
| | | placeholder="è¯·éæ©ç
åº" |
| | | clearable |
| | | filterable |
| | | style="width: 200px" |
| | | @change="handleWardChange" |
| | | > |
| | | <el-option |
| | | v-for="ward in wardList" |
| | | :key="ward.value" |
| | | :label="ward.label" |
| | | :value="ward.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="ç»è®¡æ¶é´" prop="dateRange"> |
| | | <el-date-picker |
| | | v-model="queryParams.dateRange" |
| | | type="daterange" |
| | | range-separator="è³" |
| | | start-placeholder="å¼å§æ¥æ" |
| | | end-placeholder="ç»ææ¥æ" |
| | | value-format="yyyy-MM-dd" |
| | | :picker-options="pickerOptions" |
| | | style="width: 380px" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item> |
| | | <el-button |
| | | type="primary" |
| | | icon="el-icon-search" |
| | | @click="handleSearch" |
| | | :loading="loading" |
| | | > |
| | | æ¥è¯¢ |
| | | </el-button> |
| | | <el-button icon="el-icon-refresh" @click="handleReset"> |
| | | éç½® |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </el-card> |
| | | </div> |
| | | |
| | | <!-- 满æåº¦ç±»åç»è®¡å¾è¡¨ --> |
| | | <div class="chart-section"> |
| | | <el-card shadow="never"> |
| | | <div class="chart-container"> |
| | | <div class="chart-header"> |
| | | <h3 class="chart-title">满æåº¦ç±»åå¡«æ¥æ¯ä¾ç»è®¡</h3> |
| | | <div class="statistic-info"> |
| | | <div class="statistic-item"> |
| | | <span class="statistic-label">åéé®å·æ»éï¼</span> |
| | | <span class="statistic-value">{{ |
| | | totalSendCount.toLocaleString() |
| | | }}</span> |
| | | </div> |
| | | <div class="statistic-item"> |
| | | <span class="statistic-label">åæ¶é®å·æ»éï¼</span> |
| | | <span class="statistic-value">{{ |
| | | totalReceiveCount.toLocaleString() |
| | | }}</span> |
| | | </div> |
| | | <div class="statistic-item"> |
| | | <span class="statistic-label">æ»ä½åæ¶çï¼</span> |
| | | <span class="statistic-value">{{ |
| | | formatPercent(overallRecoveryRate) |
| | | }}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div |
| | | id="satisfactionBarChart" |
| | | style="width: 100%; height: 400px" |
| | | ></div> |
| | | </div> |
| | | </el-card> |
| | | </div> |
| | | |
| | | <!-- Tabæ ç¾é¡µ --> |
| | | <div class="tab-section"> |
| | | <el-card shadow="never"> |
| | | <el-tabs v-model="activeTab" @tab-click="handleTabClick"> |
| | | <el-tab-pane label="é¢ç®æç»ç»è®¡" name="questionDetail"> |
| | | <!-- é¢ç®æç»è¡¨æ ¼ --> |
| | | <div class="detail-table-section"> |
| | | <el-table |
| | | v-loading="detailLoading" |
| | | :data="questionDetailData" |
| | | :border="true" |
| | | style="width: 100%" |
| | | row-class-name="question-row" |
| | | > |
| | | <el-table-column type="expand" width="60"> |
| | | <template slot-scope="{ row }"> |
| | | <div class="option-detail"> |
| | | <el-table |
| | | :data="row.options" |
| | | :border="true" |
| | | style="width: 100%" |
| | | class="inner-table" |
| | | > |
| | | <el-table-column |
| | | label="é项" |
| | | prop="optionText" |
| | | align="center" |
| | | min-width="200" |
| | | /> |
| | | <el-table-column |
| | | label="éæ©äººæ°" |
| | | prop="chosenQuantity" |
| | | align="center" |
| | | min-width="120" |
| | | /> |
| | | <el-table-column |
| | | label="éæ©æ¯ä¾" |
| | | prop="chosenPercentage" |
| | | align="center" |
| | | min-width="120" |
| | | > |
| | | <template slot-scope="{ row: option }"> |
| | | {{ formatPercent(option.chosenPercentage) }} |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="åºå·" |
| | | type="index" |
| | | align="center" |
| | | width="60" |
| | | /> |
| | | |
| | | <el-table-column |
| | | label="é¢ç®" |
| | | prop="scriptContent" |
| | | align="center" |
| | | min-width="300" |
| | | > |
| | | <template slot-scope="{ row }"> |
| | | <span>{{ row.scriptContent }}</span> |
| | | <el-tag |
| | | :type="row.scriptType === 1 ? 'primary' : 'success'" |
| | | size="mini" |
| | | style="margin-left: 5px" |
| | | > |
| | | {{ row.scriptType === 1 ? "åéé¢" : "å¤éé¢" }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="å¹³åå¾å" |
| | | prop="averageScore" |
| | | align="center" |
| | | width="120" |
| | | > |
| | | <template slot-scope="{ row }"> |
| | | <span class="score-text">{{ |
| | | row.averageScore.toFixed(1) |
| | | }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="æé«å¾å" |
| | | prop="maxScore" |
| | | align="center" |
| | | width="120" |
| | | > |
| | | <template slot-scope="{ row }"> |
| | | <span class="score-text">{{ |
| | | row.maxScore.toFixed(1) |
| | | }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="æä½å¾å" |
| | | prop="minScore" |
| | | align="center" |
| | | width="120" |
| | | > |
| | | <template slot-scope="{ row }"> |
| | | <span class="score-text">{{ |
| | | row.minScore.toFixed(1) |
| | | }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="çé¢äººæ°" |
| | | prop="answerCount" |
| | | align="center" |
| | | width="100" |
| | | /> |
| | | |
| | | <el-table-column |
| | | label="æªçé¢äººæ°" |
| | | prop="unanswerCount" |
| | | align="center" |
| | | width="100" |
| | | > |
| | | <template slot-scope="{ row }"> |
| | | {{ row.noAnswerPerson }} |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="çé¢ç" |
| | | prop="answerRate" |
| | | align="center" |
| | | width="100" |
| | | > |
| | | <template slot-scope="{ row }"> |
| | | {{ formatPercent(row.answerRate) }} |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <!-- 综åå¾åè¡ --> |
| | | <div class="summary-row"> |
| | | <div class="summary-content"> |
| | | <div class="summary-item"> |
| | | <span class="label">æ»çé¢äººæ°ï¼</span> |
| | | <span class="value">{{ totalAnswerCount }}</span> |
| | | </div> |
| | | <div class="summary-item"> |
| | | <span class="label">æ»çé¢çï¼</span> |
| | | <span class="value">{{ |
| | | formatPercent(totalAnswerRate) |
| | | }}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- å页 --> |
| | | <div |
| | | class="pagination-section" |
| | | v-if="questionDetailData.length > 0" |
| | | > |
| | | <el-pagination |
| | | background |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | :current-page="detailQueryParams.pageNum" |
| | | :page-size="detailQueryParams.pageSize" |
| | | :page-sizes="[10, 20, 30]" |
| | | :total="detailTotal" |
| | | @size-change="handleDetailSizeChange" |
| | | @current-change="handleDetailPageChange" |
| | | /> |
| | | </div> |
| | | </div> |
| | | </el-tab-pane> |
| | | |
| | | <el-tab-pane label="åç±»åç»è®¡æç»" name="typeDetail"> |
| | | <!-- åç±»åç»è®¡æç»è¡¨æ ¼ --> |
| | | <div class="type-detail-section"> |
| | | <el-table |
| | | v-loading="typeDetailLoading" |
| | | :data="typeDetailData" |
| | | :border="true" |
| | | style="width: 100%" |
| | | class="type-detail-table" |
| | | > |
| | | <el-table-column |
| | | label="åºå·" |
| | | type="index" |
| | | align="center" |
| | | width="60" |
| | | /> |
| | | |
| | | <el-table-column |
| | | label="满æåº¦ç±»å" |
| | | prop="typeName" |
| | | align="center" |
| | | min-width="150" |
| | | > |
| | | <template slot-scope="{ row }"> |
| | | <div class="type-name-cell"> |
| | | <span class="type-name">{{ row.typeName }}</span> |
| | | <el-tag |
| | | v-if="row.isSpecial" |
| | | type="warning" |
| | | size="mini" |
| | | style="margin-left: 5px" |
| | | > |
| | | ç¹æ® |
| | | </el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="åéé®å·æ°" |
| | | prop="sendCount" |
| | | align="center" |
| | | width="120" |
| | | > |
| | | <template slot-scope="{ row }"> |
| | | <span class="number-text">{{ |
| | | row.sendCount.toLocaleString() |
| | | }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="åæ¶é®å·æ°" |
| | | prop="receiveCount" |
| | | align="center" |
| | | width="120" |
| | | > |
| | | <template slot-scope="{ row }"> |
| | | <span class="number-text">{{ |
| | | row.receiveCount.toLocaleString() |
| | | }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="åæ¶ç" |
| | | prop="recoveryRate" |
| | | align="center" |
| | | width="120" |
| | | > |
| | | <template slot-scope="{ row }"> |
| | | <span |
| | | class="rate-text" |
| | | :class="getRateClass(row.recoveryRate)" |
| | | > |
| | | {{ formatPercent(row.recoveryRate) }} |
| | | </span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="å¹³åå" |
| | | prop="averageScore" |
| | | align="center" |
| | | width="120" |
| | | > |
| | | <template slot-scope="{ row }"> |
| | | <span class="score-text">{{ |
| | | row.averageScore.toFixed(1) |
| | | }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="满æåº¦ç级" |
| | | prop="satisfactionLevel" |
| | | align="center" |
| | | width="120" |
| | | > |
| | | <template slot-scope="{ row }"> |
| | | <el-tag |
| | | :type="getLevelTagType(row.satisfactionLevel)" |
| | | effect="dark" |
| | | size="small" |
| | | > |
| | | {{ row.satisfactionLevel }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="è¶å¿" |
| | | prop="trend" |
| | | align="center" |
| | | width="120" |
| | | > |
| | | <template slot-scope="{ row }"> |
| | | <div class="trend-cell"> |
| | | <i |
| | | v-if="row.trend === 'up'" |
| | | class="el-icon-top trend-up" |
| | | :style="{ color: '#67C23A' }" |
| | | /> |
| | | <i |
| | | v-else-if="row.trend === 'down'" |
| | | class="el-icon-bottom trend-down" |
| | | :style="{ color: '#F56C6C' }" |
| | | /> |
| | | <i |
| | | v-else |
| | | class="el-icon-minus trend-stable" |
| | | :style="{ color: '#909399' }" |
| | | /> |
| | | <span class="trend-text">{{ |
| | | row.trend === "up" |
| | | ? "ä¸å" |
| | | : row.trend === "down" |
| | | ? "ä¸é" |
| | | : "稳å®" |
| | | }}</span> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="æä½" |
| | | align="center" |
| | | width="120" |
| | | fixed="right" |
| | | > |
| | | <template slot-scope="{ row }"> |
| | | <el-button |
| | | type="text" |
| | | size="small" |
| | | @click="handleTypeDetail(row)" |
| | | > |
| | | 详æ
|
| | | </el-button> |
| | | <el-button |
| | | type="text" |
| | | size="small" |
| | | @click="handleExportData(row)" |
| | | > |
| | | å¯¼åº |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <!-- ç±»åç»è®¡æ±æ» --> |
| | | <div class="type-summary-row"> |
| | | <div class="type-summary-content"> |
| | | <div class="type-summary-item"> |
| | | <span class="label">ç±»åæ»æ°ï¼</span> |
| | | <span class="value">{{ typeDetailData.length }}</span> |
| | | </div> |
| | | <div class="type-summary-item"> |
| | | <span class="label">å¹³ååæ¶çï¼</span> |
| | | <span class="value">{{ |
| | | formatPercent(averageRecoveryRate) |
| | | }}</span> |
| | | </div> |
| | | <div class="type-summary-item"> |
| | | <span class="label">ç±»åå¹³ååï¼</span> |
| | | <span class="value">{{ averageTypeScore.toFixed(1) }}</span> |
| | | </div> |
| | | <div class="type-summary-item"> |
| | | <span class="label">髿»¡æåº¦ç±»åï¼</span> |
| | | <span class="value high-count" |
| | | >{{ highSatisfactionCount }} 个</span |
| | | > |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | | </el-card> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import * as echarts from "echarts"; |
| | | import { statistics, satisfactionGraph } from "@/api/system/user"; |
| | | import store from "@/store"; |
| | | |
| | | export default { |
| | | name: "SatisfactionStatistics", |
| | | data() { |
| | | return { |
| | | // æ¥è¯¢åæ° |
| | | queryParams: { |
| | | type: 2, |
| | | patientSource: "", |
| | | deptCode: "", |
| | | wardCode: "", |
| | | dateRange: [], |
| | | }, |
| | | |
| | | // å½åæ¿æ´»çtab |
| | | activeTab: "questionDetail", |
| | | |
| | | // æ£è
æ¥æºé项 |
| | | patientSourceList: [ |
| | | { value: "1", label: "é¨è¯" }, |
| | | { value: "2", label: "ä½é¢" }, |
| | | { value: "3", label: "æ¥è¯" }, |
| | | { value: "4", label: "åºé¢" }, |
| | | ], |
| | | |
| | | // ç§å®¤å表 |
| | | deptList: [], |
| | | |
| | | // ç
åºå表 |
| | | wardList: [], |
| | | |
| | | // å¾è¡¨å®ä¾ |
| | | barChart: null, |
| | | |
| | | // å è½½ç¶æ |
| | | loading: false, |
| | | detailLoading: false, |
| | | typeDetailLoading: false, |
| | | |
| | | // é¢ç®æç»æ°æ® |
| | | questionDetailData: [], |
| | | |
| | | // é¢ç®æç»æ¥è¯¢åæ° |
| | | detailQueryParams: { |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | }, |
| | | |
| | | // é¢ç®æç»æ»æ° |
| | | detailTotal: 0, |
| | | |
| | | // 综åå¾å |
| | | totalScore: 0, |
| | | totalAnswerCount: 0, |
| | | totalAnswerRate: 0, |
| | | |
| | | // åç±»åç»è®¡æç»æ°æ® |
| | | typeDetailData: [], |
| | | |
| | | // æ±ç¶å¾æ°æ® |
| | | chartData: [], |
| | | |
| | | // ç»è®¡ä¿¡æ¯ |
| | | totalSendCount: 0, |
| | | totalReceiveCount: 0, |
| | | overallRecoveryRate: 0, |
| | | |
| | | // ç±»åç»è®¡æ±æ» |
| | | averageRecoveryRate: 0, |
| | | averageTypeScore: 0, |
| | | highSatisfactionCount: 0, |
| | | |
| | | // æ¥æéæ©å¨é项 |
| | | pickerOptions: { |
| | | shortcuts: [ |
| | | { |
| | | text: "æè¿ä¸å¨", |
| | | onClick(picker) { |
| | | const end = new Date(); |
| | | const start = new Date(); |
| | | start.setTime(start.getTime() - 3600 * 1000 * 24 * 7); |
| | | picker.$emit("pick", [start, end]); |
| | | }, |
| | | }, |
| | | { |
| | | text: "æè¿ä¸ä¸ªæ", |
| | | onClick(picker) { |
| | | const end = new Date(); |
| | | const start = new Date(); |
| | | start.setTime(start.getTime() - 3600 * 1000 * 24 * 30); |
| | | picker.$emit("pick", [start, end]); |
| | | }, |
| | | }, |
| | | { |
| | | text: "æè¿ä¸ä¸ªæ", |
| | | onClick(picker) { |
| | | const end = new Date(); |
| | | const start = new Date(); |
| | | start.setTime(start.getTime() - 3600 * 1000 * 24 * 90); |
| | | picker.$emit("pick", [start, end]); |
| | | }, |
| | | }, |
| | | ], |
| | | disabledDate(time) { |
| | | return time.getTime() > Date.now(); |
| | | }, |
| | | }, |
| | | |
| | | // 满æåº¦ç±»åæ°æ® |
| | | satisfactionTypes: [ |
| | | { id: 401, name: "åºé¢æ»¡æåº¦", color: "#36B37E" }, |
| | | { id: 402, name: "ä½é¢æ»¡æåº¦", color: "#4CAF50" }, |
| | | { id: 403, name: "é¨è¯æ»¡æåº¦", color: "#409EFF" }, |
| | | { id: 404, name: "å¸¸ç¨æ»¡æåº¦", color: "#FF9D4D" }, |
| | | ], |
| | | |
| | | // æ°å¢ï¼é»è®¤æå¡ç±»åæ°ç» |
| | | defaultServiceTypes: ["6", "14", "15", "16"], |
| | | |
| | | // æ°å¢ï¼åºç¡æ¨¡æ¿é®é¢IDéå |
| | | scriptIds: [], |
| | | |
| | | // æ°å¢ï¼æ¨¡æ¿ID |
| | | templateId: null, |
| | | }; |
| | | }, |
| | | |
| | | computed: { |
| | | // è®¡ç®æ¥è¯¢å¼å§æ¶é´ |
| | | startTime() { |
| | | if (this.queryParams.dateRange && this.queryParams.dateRange[0]) { |
| | | return this.queryParams.dateRange[0]; |
| | | } |
| | | // é»è®¤æè¿7天 |
| | | const date = new Date(); |
| | | date.setDate(date.getDate() - 7); |
| | | return this.formatDate(date); |
| | | }, |
| | | |
| | | // è®¡ç®æ¥è¯¢ç»ææ¶é´ |
| | | endTime() { |
| | | if (this.queryParams.dateRange && this.queryParams.dateRange[1]) { |
| | | return this.queryParams.dateRange[1]; |
| | | } |
| | | // é»è®¤ä»å¤© |
| | | return this.formatDate(new Date()); |
| | | }, |
| | | |
| | | // 计ç®ç§å®¤ç¼ç æ°ç» |
| | | deptCodes() { |
| | | if (this.queryParams.deptCode) { |
| | | return [this.queryParams.deptCode]; |
| | | } |
| | | return this.deptList.map((dept) => dept.value); |
| | | }, |
| | | |
| | | // 计ç®ç
åºç¼ç æ°ç» |
| | | hospitalDistrictCodes() { |
| | | if (this.queryParams.wardCode) { |
| | | return [this.queryParams.wardCode]; |
| | | } |
| | | return this.wardList.map((ward) => ward.value); |
| | | }, |
| | | }, |
| | | |
| | | mounted() { |
| | | this.initData(); |
| | | }, |
| | | |
| | | beforeDestroy() { |
| | | if (this.barChart) { |
| | | this.barChart.dispose(); |
| | | this.barChart = null; |
| | | } |
| | | }, |
| | | |
| | | methods: { |
| | | // æ ¼å¼åæ¥æ |
| | | formatDate(date) { |
| | | const year = date.getFullYear(); |
| | | const month = String(date.getMonth() + 1).padStart(2, "0"); |
| | | const day = String(date.getDate()).padStart(2, "0"); |
| | | return `${year}-${month}-${day}`; |
| | | }, |
| | | |
| | | // åå§åæ°æ® |
| | | async initData() { |
| | | await this.getDeptList(); |
| | | await this.getWardList(); |
| | | this.initChart(); |
| | | await this.loadData(); |
| | | }, |
| | | |
| | | // è·åç§å®¤å表 |
| | | getDeptList() { |
| | | return new Promise((resolve) => { |
| | | this.deptList = (this.$store.getters.belongDepts || []).map((dept) => { |
| | | return { |
| | | label: dept.deptName, |
| | | value: dept.deptCode, |
| | | }; |
| | | }); |
| | | resolve(); |
| | | }); |
| | | }, |
| | | |
| | | // è·åç
åºå表 |
| | | getWardList() { |
| | | return new Promise((resolve) => { |
| | | this.wardList = (this.$store.getters.belongWards || []).map((ward) => { |
| | | return { |
| | | label: ward.districtName, |
| | | value: ward.districtCode, |
| | | }; |
| | | }); |
| | | resolve(); |
| | | }); |
| | | }, |
| | | |
| | | // å è½½æ°æ® |
| | | async loadData() { |
| | | await Promise.all([ |
| | | this.loadChartData(), |
| | | this.loadQuestionDetailData(), |
| | | this.loadTypeDetailData(), |
| | | ]); |
| | | }, |
| | | |
| | | // å è½½å¾è¡¨æ°æ® |
| | | async loadChartData() { |
| | | this.loading = true; |
| | | try { |
| | | const params = { |
| | | type: this.queryParams.type, |
| | | startTime: this.startTime, |
| | | endTime: this.endTime, |
| | | deptcodes: this.deptCodes, |
| | | hospitaldistrictcodes: this.hospitalDistrictCodes, |
| | | templateid: this.templateId, |
| | | }; |
| | | |
| | | const response = await satisfactionGraph(params); |
| | | |
| | | if (response.code === 200) { |
| | | this.processChartData(response); |
| | | } else { |
| | | this.$message.error(response.msg || "è·åå¾è¡¨æ°æ®å¤±è´¥"); |
| | | // 使ç¨mockæ°æ® |
| | | await this.generateMockChartData(); |
| | | } |
| | | } catch (error) { |
| | | console.error("è·åå¾è¡¨æ°æ®åºé:", error); |
| | | this.$message.error("è·åå¾è¡¨æ°æ®å¤±è´¥"); |
| | | // é误æ¶ä½¿ç¨mockæ°æ® |
| | | await this.generateMockChartData(); |
| | | } finally { |
| | | this.loading = false; |
| | | } |
| | | }, |
| | | |
| | | // å¤çå¾è¡¨æ°æ® |
| | | processChartData(apiData) { |
| | | if (!apiData || !apiData.rows || Object.keys(apiData.rows).length === 0) { |
| | | this.chartData = []; |
| | | this.totalSendCount = 0; |
| | | this.totalReceiveCount = 0; |
| | | this.overallRecoveryRate = 0; |
| | | this.renderChart([]); |
| | | return; |
| | | } |
| | | |
| | | const chartData = []; |
| | | let totalSend = 0; |
| | | let totalReceive = 0; |
| | | let index = 0; |
| | | |
| | | // å¤çæ¥å£è¿åçæ»¡æåº¦ç±»åç»è®¡ |
| | | Object.entries(apiData.rows).forEach(([typeName, typeStat]) => { |
| | | const sendCount = typeStat.subidAll || 0; |
| | | const receiveCount = typeStat.fillCountAll || 0; |
| | | const recoveryRate = typeStat.receiveRate || 0; |
| | | |
| | | chartData.push({ |
| | | name: typeName, |
| | | value: recoveryRate * 100, // 转æ¢ä¸ºç¾åæ¯ |
| | | sendCount: sendCount, |
| | | receiveCount: receiveCount, |
| | | averageScore: typeStat.averageScore || 0, |
| | | itemStyle: { color: this.getChartColor(index) }, |
| | | }); |
| | | |
| | | totalSend += sendCount; |
| | | totalReceive += receiveCount; |
| | | index++; |
| | | }); |
| | | |
| | | this.totalSendCount = totalSend; |
| | | this.totalReceiveCount = totalReceive; |
| | | this.overallRecoveryRate = totalSend > 0 ? totalReceive / totalSend : 0; |
| | | this.chartData = chartData; |
| | | |
| | | this.renderChart(chartData); |
| | | }, |
| | | |
| | | // å è½½é¢ç®æç»æ°æ® |
| | | async loadQuestionDetailData() { |
| | | this.detailLoading = true; |
| | | try { |
| | | const params = { |
| | | type: this.queryParams.type, |
| | | startTime: this.startTime, |
| | | endTime: this.endTime, |
| | | scriptids: this.scriptIds, |
| | | templateid: this.templateId, |
| | | }; |
| | | |
| | | const response = await statistics(params); |
| | | |
| | | if (response.code === 200) { |
| | | this.processQuestionDetailData(response.rows); |
| | | } else { |
| | | this.$message.error(response.msg || "è·åé¢ç®æç»æ°æ®å¤±è´¥"); |
| | | const mockData = await this.generateMockQuestionDetail(); |
| | | this.questionDetailData = mockData.list; |
| | | this.detailTotal = mockData.total; |
| | | this.calculateSummary(mockData); |
| | | } |
| | | } catch (error) { |
| | | console.error("è·åé¢ç®æç»æ°æ®åºé:", error); |
| | | this.$message.error("è·åé¢ç®æç»æ°æ®å¤±è´¥"); |
| | | const mockData = await this.generateMockQuestionDetail(); |
| | | this.questionDetailData = mockData.list; |
| | | this.detailTotal = mockData.total; |
| | | this.calculateSummary(mockData); |
| | | } finally { |
| | | this.detailLoading = false; |
| | | } |
| | | }, |
| | | |
| | | // å¤çæ¥å£è¿åçé¢ç®æç»æ°æ® |
| | | processQuestionDetailData(apiData) { |
| | | if (!apiData || !apiData.patSatisfactionDetailEntities) { |
| | | this.questionDetailData = []; |
| | | this.detailTotal = 0; |
| | | this.totalAnswerCount = 0; |
| | | this.totalAnswerRate = 0; |
| | | return; |
| | | } |
| | | |
| | | const detailData = apiData.patSatisfactionDetailEntities.map((item) => { |
| | | const options = []; |
| | | if (item.matchedtextStats) { |
| | | Object.keys(item.matchedtextStats).forEach((key) => { |
| | | const stat = item.matchedtextStats[key]; |
| | | options.push({ |
| | | optionText: key, |
| | | chosenQuantity: stat.count || 0, |
| | | chosenPercentage: (stat.ratio || 0) / 100, |
| | | }); |
| | | }); |
| | | } |
| | | |
| | | return { |
| | | scriptContent: item.scriptContent || "", |
| | | scriptType: 1, |
| | | answerPerson: item.answerPerson || 0, |
| | | noAnswerPerson: item.noAnswerPerson || 0, |
| | | answerCount: item.answerPerson || 0, |
| | | averageScore: item.averageScore || 0, |
| | | maxScore: item.maxScore || 0, |
| | | minScore: item.minScore || 0, |
| | | answerRate: item.answerRate || 0, |
| | | totalCount: (item.answerPerson || 0) + (item.noAnswerPerson || 0), |
| | | options: options, |
| | | }; |
| | | }); |
| | | |
| | | const startIndex = |
| | | (this.detailQueryParams.pageNum - 1) * this.detailQueryParams.pageSize; |
| | | const endIndex = startIndex + this.detailQueryParams.pageSize; |
| | | const paginatedData = detailData.slice(startIndex, endIndex); |
| | | |
| | | this.questionDetailData = paginatedData; |
| | | this.detailTotal = detailData.length; |
| | | this.totalAnswerCount = apiData.totalPerson || 0; |
| | | this.totalAnswerRate = apiData.totalAnswerRate || 0; |
| | | }, |
| | | |
| | | // å 载类åæç»æ°æ® |
| | | async loadTypeDetailData() { |
| | | this.typeDetailLoading = true; |
| | | try { |
| | | const params = { |
| | | type: this.queryParams.type, |
| | | startTime: this.startTime, |
| | | endTime: this.endTime, |
| | | deptcodes: this.deptCodes, |
| | | hospitaldistrictcodes: this.hospitalDistrictCodes, |
| | | templateid: this.templateId, |
| | | }; |
| | | |
| | | const response = await satisfactionGraph(params); |
| | | |
| | | if (response.code === 200) { |
| | | this.processTypeDetailData(response.data); |
| | | } else { |
| | | this.$message.error(response.msg || "è·åç±»åæç»æ°æ®å¤±è´¥"); |
| | | const mockData = await this.generateMockTypeDetail(); |
| | | this.typeDetailData = mockData; |
| | | this.calculateTypeSummary(mockData); |
| | | } |
| | | } catch (error) { |
| | | console.error("è·åç±»åæç»æ°æ®åºé:", error); |
| | | this.$message.error("è·åç±»åæç»æ°æ®å¤±è´¥"); |
| | | const mockData = await this.generateMockTypeDetail(); |
| | | this.typeDetailData = mockData; |
| | | this.calculateTypeSummary(mockData); |
| | | } finally { |
| | | this.typeDetailLoading = false; |
| | | } |
| | | }, |
| | | |
| | | // å¤çç±»åæç»æ°æ® |
| | | processTypeDetailData(apiData) { |
| | | if (!apiData || !apiData.rows || Object.keys(apiData.rows).length === 0) { |
| | | this.typeDetailData = []; |
| | | this.calculateTypeSummary([]); |
| | | return; |
| | | } |
| | | |
| | | const typeDetail = []; |
| | | Object.entries(apiData.rows).forEach(([typeName, typeStat], index) => { |
| | | const sendCount = typeStat.subidAll || 0; |
| | | const receiveCount = typeStat.fillCountAll || 0; |
| | | const recoveryRate = typeStat.receiveRate || 0; |
| | | const averageScore = typeStat.averageScore || 0; |
| | | |
| | | typeDetail.push({ |
| | | id: index + 1, |
| | | typeName: typeName, |
| | | isSpecial: false, // æ ¹æ®å®é
æ
åµå¤æ |
| | | sendCount: sendCount, |
| | | receiveCount: receiveCount, |
| | | recoveryRate: recoveryRate, |
| | | averageScore: averageScore, |
| | | maxScore: 5, // é»è®¤å¼ |
| | | minScore: 0, // é»è®¤å¼ |
| | | satisfactionLevel: this.getSatisfactionLevel(averageScore), |
| | | trend: "stable", // é»è®¤ç¨³å® |
| | | }); |
| | | }); |
| | | |
| | | this.typeDetailData = typeDetail; |
| | | this.calculateTypeSummary(typeDetail); |
| | | }, |
| | | |
| | | // æ ¹æ®å¹³ååè·å满æåº¦ç级 |
| | | getSatisfactionLevel(score) { |
| | | if (score >= 4.5) return "ä¼ç§"; |
| | | if (score >= 4.0) return "è¯å¥½"; |
| | | if (score >= 3.0) return "ä¸è¬"; |
| | | if (score >= 2.0) return "è¾å·®"; |
| | | return "å·®"; |
| | | }, |
| | | |
| | | // è·åè¶å¿ |
| | | getTrend(trend) { |
| | | if (trend > 0.1) return "up"; |
| | | if (trend < -0.1) return "down"; |
| | | return "stable"; |
| | | }, |
| | | |
| | | // 计ç®ç»¼åå¾å |
| | | calculateSummary(data) { |
| | | let totalScore = 0; |
| | | let totalAnswerCount = 0; |
| | | let totalCount = 0; |
| | | |
| | | data.list.forEach((item) => { |
| | | totalScore += item.averageScore; |
| | | totalAnswerCount += item.answerCount; |
| | | totalCount += item.totalCount; |
| | | }); |
| | | |
| | | this.totalScore = |
| | | data.list.length > 0 ? totalScore / data.list.length : 0; |
| | | this.totalAnswerCount = totalAnswerCount; |
| | | this.totalAnswerRate = totalCount > 0 ? totalAnswerCount / totalCount : 0; |
| | | }, |
| | | |
| | | // 计ç®ç±»åç»è®¡æ±æ» |
| | | calculateTypeSummary(data) { |
| | | if (data.length === 0) { |
| | | this.averageRecoveryRate = 0; |
| | | this.averageTypeScore = 0; |
| | | this.highSatisfactionCount = 0; |
| | | return; |
| | | } |
| | | |
| | | let totalRecoveryRate = 0; |
| | | let totalTypeScore = 0; |
| | | let highCount = 0; |
| | | |
| | | data.forEach((item) => { |
| | | totalRecoveryRate += item.recoveryRate; |
| | | totalTypeScore += item.averageScore; |
| | | if ( |
| | | item.satisfactionLevel === "ä¼ç§" || |
| | | item.satisfactionLevel === "è¯å¥½" |
| | | ) { |
| | | highCount++; |
| | | } |
| | | }); |
| | | |
| | | this.averageRecoveryRate = totalRecoveryRate / data.length; |
| | | this.averageTypeScore = totalTypeScore / data.length; |
| | | this.highSatisfactionCount = highCount; |
| | | }, |
| | | |
| | | // åå§åå¾è¡¨ |
| | | initChart() { |
| | | const chartDom = document.getElementById("satisfactionBarChart"); |
| | | if (!chartDom) return; |
| | | |
| | | this.barChart = echarts.init(chartDom); |
| | | window.addEventListener("resize", this.handleChartResize); |
| | | }, |
| | | |
| | | // 渲æå¾è¡¨ |
| | | renderChart(chartData) { |
| | | if (!this.barChart) return; |
| | | if (!chartData || chartData.length === 0) { |
| | | const emptyOption = { |
| | | title: { |
| | | text: "ææ æ°æ®", |
| | | left: "center", |
| | | top: "center", |
| | | textStyle: { |
| | | color: "#999", |
| | | fontSize: 16, |
| | | fontWeight: "normal" |
| | | } |
| | | }, |
| | | xAxis: { show: false }, |
| | | yAxis: { show: false } |
| | | }; |
| | | this.barChart.setOption(emptyOption); |
| | | return; |
| | | } |
| | | const option = { |
| | | title: { |
| | | text: "", |
| | | left: "center", |
| | | }, |
| | | tooltip: { |
| | | trigger: "axis", |
| | | axisPointer: { |
| | | type: "shadow", |
| | | }, |
| | | formatter: (params) => { |
| | | const data = params[0]; |
| | | return ` |
| | | <div style="margin-bottom: 5px; font-weight: bold; color: #333;"> |
| | | ${data.name} |
| | | </div> |
| | | <div style="margin: 2px 0;"> |
| | | <span style="display:inline-block;width:10px;height:10px;border-radius:2px;background:${ |
| | | data.color |
| | | };margin-right:5px;"></span> |
| | | å¡«æ¥æ¯ä¾: <strong>${data.value.toFixed(1)}%</strong> |
| | | </div> |
| | | <div style="margin: 2px 0;"> |
| | | <span style="display:inline-block;width:10px;height:10px;border-radius:2px;background:#eee;margin-right:5px;"></span> |
| | | åéé®å·: <strong>${data.data.sendCount.toLocaleString()}</strong> |
| | | </div> |
| | | <div style="margin: 2px 0;"> |
| | | <span style="display:inline-block;width:10px;height:10px;border-radius:2px;background:#eee;margin-right:5px;"></span> |
| | | åæ¶é®å·: <strong>${data.data.receiveCount.toLocaleString()}</strong> |
| | | </div> |
| | | `; |
| | | }, |
| | | }, |
| | | grid: { |
| | | left: "3%", |
| | | right: "4%", |
| | | bottom: "3%", |
| | | top: 60, |
| | | containLabel: true, |
| | | }, |
| | | xAxis: { |
| | | type: "category", |
| | | data: chartData.map((item) => item.name), |
| | | axisLabel: { |
| | | interval: 0, |
| | | rotate: 0, |
| | | fontSize: 12, |
| | | color: "#666", |
| | | }, |
| | | axisLine: { |
| | | lineStyle: { |
| | | color: "#DCDFE6", |
| | | }, |
| | | }, |
| | | axisTick: { |
| | | alignWithLabel: true, |
| | | }, |
| | | }, |
| | | yAxis: { |
| | | type: "value", |
| | | name: "å¡«æ¥æ¯ä¾ (%)", |
| | | min: 0, |
| | | max: 100, |
| | | axisLabel: { |
| | | formatter: "{value}%", |
| | | color: "#666", |
| | | }, |
| | | axisLine: { |
| | | lineStyle: { |
| | | color: "#DCDFE6", |
| | | }, |
| | | }, |
| | | splitLine: { |
| | | lineStyle: { |
| | | type: "dashed", |
| | | color: "#E4E7ED", |
| | | }, |
| | | }, |
| | | }, |
| | | series: [ |
| | | { |
| | | name: "å¡«æ¥æ¯ä¾", |
| | | type: "bar", |
| | | barWidth: 40, |
| | | data: chartData, |
| | | itemStyle: { |
| | | color: (params) => { |
| | | return params.data.itemStyle.color; |
| | | }, |
| | | }, |
| | | label: { |
| | | show: true, |
| | | position: "top", |
| | | formatter: "{c}%", |
| | | fontSize: 12, |
| | | color: "#333", |
| | | }, |
| | | }, |
| | | ], |
| | | }; |
| | | |
| | | this.barChart.setOption(option); |
| | | }, |
| | | |
| | | // çæMockå¾è¡¨æ°æ® |
| | | generateMockChartData() { |
| | | return new Promise((resolve) => { |
| | | setTimeout(() => { |
| | | const data = this.satisfactionTypes.map((type, index) => ({ |
| | | name: type.name, |
| | | recoveryRate: Math.random() * 0.3 + 0.6, |
| | | sendCount: Math.floor(Math.random() * 3000) + 1500, |
| | | receiveCount: 0, |
| | | color: type.color, |
| | | })); |
| | | |
| | | data.forEach((item) => { |
| | | item.receiveCount = Math.floor(item.sendCount * item.recoveryRate); |
| | | }); |
| | | |
| | | this.totalSendCount = data.reduce( |
| | | (sum, item) => sum + item.sendCount, |
| | | 0 |
| | | ); |
| | | this.totalReceiveCount = data.reduce( |
| | | (sum, item) => sum + item.receiveCount, |
| | | 0 |
| | | ); |
| | | this.overallRecoveryRate = |
| | | this.totalSendCount > 0 |
| | | ? this.totalReceiveCount / this.totalSendCount |
| | | : 0; |
| | | |
| | | const chartData = data.map((item) => ({ |
| | | name: item.name, |
| | | value: item.recoveryRate * 100, |
| | | sendCount: item.sendCount, |
| | | receiveCount: item.receiveCount, |
| | | itemStyle: { color: item.color }, |
| | | })); |
| | | |
| | | this.chartData = chartData; |
| | | this.renderChart(chartData); |
| | | resolve(); |
| | | }, 300); |
| | | }); |
| | | }, |
| | | |
| | | // çæMocké¢ç®è¯¦æ
æ°æ® |
| | | generateMockQuestionDetail() { |
| | | return new Promise((resolve) => { |
| | | setTimeout(() => { |
| | | const questions = [ |
| | | { |
| | | scriptContent: "æ¨å¯¹æ¬æ¬¡å°±å»çæ´ä½æ»¡æç¨åº¦ï¼", |
| | | scriptType: 1, |
| | | answerPerson: 120, |
| | | noAnswerPerson: 30, |
| | | answerCount: 120, |
| | | totalCount: 150, |
| | | averageScore: 4.2, |
| | | maxScore: 5.0, |
| | | minScore: 1.0, |
| | | answerRate: 0.8, |
| | | options: [ |
| | | { |
| | | optionText: "é常满æ", |
| | | chosenQuantity: 60, |
| | | chosenPercentage: 0.5, |
| | | }, |
| | | { |
| | | optionText: "满æ", |
| | | chosenQuantity: 36, |
| | | chosenPercentage: 0.3, |
| | | }, |
| | | { |
| | | optionText: "ä¸è¬", |
| | | chosenQuantity: 18, |
| | | chosenPercentage: 0.15, |
| | | }, |
| | | { |
| | | optionText: "䏿»¡æ", |
| | | chosenQuantity: 6, |
| | | chosenPercentage: 0.05, |
| | | }, |
| | | ], |
| | | }, |
| | | { |
| | | scriptContent: "æ¨å¯¹å»æ¤äººåçæå¡æåº¦æ¯å¦æ»¡æï¼", |
| | | scriptType: 1, |
| | | answerPerson: 145, |
| | | noAnswerPerson: 11, |
| | | answerCount: 145, |
| | | totalCount: 156, |
| | | averageScore: 4.5, |
| | | maxScore: 5, |
| | | minScore: 3, |
| | | answerRate: 0.93, |
| | | options: [ |
| | | { |
| | | optionText: "é常满æ", |
| | | chosenQuantity: 89, |
| | | chosenPercentage: 0.61, |
| | | }, |
| | | { |
| | | optionText: "满æ", |
| | | chosenQuantity: 45, |
| | | chosenPercentage: 0.31, |
| | | }, |
| | | { |
| | | optionText: "ä¸è¬", |
| | | chosenQuantity: 8, |
| | | chosenPercentage: 0.06, |
| | | }, |
| | | { |
| | | optionText: "䏿»¡æ", |
| | | chosenQuantity: 2, |
| | | chosenPercentage: 0.01, |
| | | }, |
| | | { |
| | | optionText: "é叏䏿»¡æ", |
| | | chosenQuantity: 1, |
| | | chosenPercentage: 0.01, |
| | | }, |
| | | ], |
| | | }, |
| | | ]; |
| | | |
| | | const startIndex = |
| | | (this.detailQueryParams.pageNum - 1) * |
| | | this.detailQueryParams.pageSize; |
| | | const endIndex = startIndex + this.detailQueryParams.pageSize; |
| | | const paginatedData = questions.slice(startIndex, endIndex); |
| | | |
| | | resolve({ |
| | | list: paginatedData, |
| | | total: questions.length, |
| | | }); |
| | | }, 300); |
| | | }); |
| | | }, |
| | | |
| | | // çæMockç±»åæç»æ°æ® |
| | | generateMockTypeDetail() { |
| | | return new Promise((resolve) => { |
| | | setTimeout(() => { |
| | | const types = [ |
| | | { |
| | | id: 401, |
| | | typeName: "åºé¢æ»¡æåº¦", |
| | | isSpecial: false, |
| | | sendCount: 2850, |
| | | receiveCount: 2680, |
| | | recoveryRate: 0.94, |
| | | averageScore: 4.8, |
| | | maxScore: 5, |
| | | minScore: 3.8, |
| | | satisfactionLevel: "ä¼ç§", |
| | | trend: "up", |
| | | }, |
| | | { |
| | | id: 402, |
| | | typeName: "ä½é¢æ»¡æåº¦", |
| | | isSpecial: false, |
| | | sendCount: 2620, |
| | | receiveCount: 2405, |
| | | recoveryRate: 0.918, |
| | | averageScore: 4.6, |
| | | maxScore: 5, |
| | | minScore: 3.5, |
| | | satisfactionLevel: "ä¼ç§", |
| | | trend: "stable", |
| | | }, |
| | | { |
| | | id: 403, |
| | | typeName: "é¨è¯æ»¡æåº¦", |
| | | isSpecial: false, |
| | | sendCount: 3780, |
| | | receiveCount: 3220, |
| | | recoveryRate: 0.852, |
| | | averageScore: 4.3, |
| | | maxScore: 5, |
| | | minScore: 2.5, |
| | | satisfactionLevel: "è¯å¥½", |
| | | trend: "up", |
| | | }, |
| | | { |
| | | id: 404, |
| | | typeName: "å¸¸ç¨æ»¡æåº¦", |
| | | isSpecial: true, |
| | | sendCount: 1950, |
| | | receiveCount: 1780, |
| | | recoveryRate: 0.913, |
| | | averageScore: 4.5, |
| | | maxScore: 5, |
| | | minScore: 3.2, |
| | | satisfactionLevel: "è¯å¥½", |
| | | trend: "stable", |
| | | }, |
| | | ]; |
| | | |
| | | resolve(types); |
| | | }, 300); |
| | | }); |
| | | }, |
| | | |
| | | // è·åå¾è¡¨é¢è² |
| | | getChartColor(index) { |
| | | const colors = [ |
| | | "#36B37E", |
| | | "#4CAF50", |
| | | "#409EFF", |
| | | "#FF9D4D", |
| | | "#9B8DFF", |
| | | "#FF6B6B", |
| | | ]; |
| | | return colors[index % colors.length]; |
| | | }, |
| | | |
| | | // å¤çå¾è¡¨ååºå¼ |
| | | handleChartResize() { |
| | | if (this.barChart) { |
| | | this.barChart.resize(); |
| | | } |
| | | }, |
| | | |
| | | // å¤çæ¥è¯¢ |
| | | handleSearch() { |
| | | this.detailQueryParams.pageNum = 1; |
| | | this.loadData(); |
| | | // 强å¶éæ°æ¸²æå¾è¡¨ |
| | | setTimeout(() => { |
| | | if (this.chartData.length === 0) { |
| | | this.renderChart([]); |
| | | } |
| | | }, 100); |
| | | }, |
| | | |
| | | // å¤çéç½® |
| | | handleReset() { |
| | | this.$refs.queryForm.resetFields(); |
| | | this.queryParams.dateRange = []; |
| | | this.detailQueryParams.pageNum = 1; |
| | | this.loadData(); |
| | | }, |
| | | |
| | | // å¤çTab忢 |
| | | handleTabClick(tab) { |
| | | if (tab.name === "typeDetail" && this.typeDetailData.length === 0) { |
| | | this.loadTypeDetailData(); |
| | | } |
| | | }, |
| | | |
| | | // å¤çæç»å页大å°åå |
| | | handleDetailSizeChange(size) { |
| | | this.detailQueryParams.pageSize = size; |
| | | this.detailQueryParams.pageNum = 1; |
| | | this.loadQuestionDetailData(); |
| | | }, |
| | | |
| | | // å¤çæç»é¡µç åå |
| | | handleDetailPageChange(page) { |
| | | this.detailQueryParams.pageNum = page; |
| | | this.loadQuestionDetailData(); |
| | | }, |
| | | |
| | | // å¤çç±»å详æ
|
| | | handleTypeDetail(row) { |
| | | this.$message.info(`æ¥çç±»å详æ
ï¼${row.typeName}`); |
| | | }, |
| | | |
| | | // å¤çå¯¼åºæ°æ® |
| | | handleExportData(row) { |
| | | this.$message.success(`æ£å¨å¯¼åº ${row.typeName} æ°æ®...`); |
| | | }, |
| | | |
| | | // æ ¼å¼åç¾åæ¯ |
| | | formatPercent(value) { |
| | | if (value === null || value === undefined) return "-"; |
| | | const num = parseFloat(value); |
| | | if (isNaN(num)) return "-"; |
| | | // 妿å¼å°äº1ï¼è®¤ä¸ºæ¯å°æ°æ¯ä¾ï¼éè¦ä¹ä»¥100 |
| | | const percentValue = num < 1 ? num * 100 : num; |
| | | return `${percentValue.toFixed(2)}%`; |
| | | }, |
| | | |
| | | // è·ååæ¶çæ ·å¼ç±» |
| | | getRateClass(rate) { |
| | | if (rate >= 0.9) return "rate-high"; |
| | | if (rate >= 0.8) return "rate-medium"; |
| | | return "rate-low"; |
| | | }, |
| | | |
| | | // è·å满æåº¦ç级æ ç¾ç±»å |
| | | getLevelTagType(level) { |
| | | const levelMap = { |
| | | ä¼ç§: "success", |
| | | è¯å¥½: "primary", |
| | | ä¸è¬: "warning", |
| | | è¾å·®: "danger", |
| | | å·®: "info", |
| | | }; |
| | | return levelMap[level] || "info"; |
| | | }, |
| | | |
| | | // å¤çç§å®¤éæ©åå |
| | | handleDeptChange() { |
| | | this.loadData(); |
| | | }, |
| | | |
| | | // å¤çç
åºéæ©åå |
| | | handleWardChange() { |
| | | this.loadData(); |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .satisfaction-statistics { |
| | | padding: 20px; |
| | | background-color: #f5f7fa; |
| | | min-height: 100vh; |
| | | |
| | | .query-section { |
| | | margin-bottom: 20px; |
| | | |
| | | .query-form { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | align-items: center; |
| | | |
| | | ::v-deep .el-form-item { |
| | | margin-bottom: 0; |
| | | margin-right: 20px; |
| | | |
| | | &:last-child { |
| | | margin-right: 0; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .chart-section { |
| | | margin-bottom: 20px; |
| | | |
| | | .chart-container { |
| | | .chart-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 20px; |
| | | padding-bottom: 15px; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | |
| | | .chart-title { |
| | | margin: 0; |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | } |
| | | |
| | | .statistic-info { |
| | | display: flex; |
| | | gap: 30px; |
| | | align-items: center; |
| | | |
| | | .statistic-item { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | |
| | | .statistic-label { |
| | | font-size: 14px; |
| | | color: #606266; |
| | | } |
| | | |
| | | .statistic-value { |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | color: #409eff; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .tab-section { |
| | | ::v-deep .el-tabs__header { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | ::v-deep .el-tabs__content { |
| | | padding: 20px 0 0 0; |
| | | } |
| | | } |
| | | |
| | | .detail-table-section { |
| | | .option-detail { |
| | | padding: 15px; |
| | | background: #f8f9fa; |
| | | border-radius: 4px; |
| | | margin: 10px 0; |
| | | } |
| | | |
| | | ::v-deep .el-table { |
| | | th { |
| | | background-color: #f8f9fa; |
| | | font-weight: 600; |
| | | color: #333; |
| | | padding: 12px 0; |
| | | } |
| | | |
| | | td { |
| | | padding: 12px 0; |
| | | } |
| | | |
| | | .question-row { |
| | | td { |
| | | background-color: #fff; |
| | | } |
| | | |
| | | &:hover { |
| | | td { |
| | | background-color: #f5f7fa; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .score-text { |
| | | font-weight: 600; |
| | | color: #1890ff; |
| | | font-size: 16px; |
| | | } |
| | | |
| | | .summary-row { |
| | | margin-top: 20px; |
| | | padding: 20px; |
| | | background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%); |
| | | border-radius: 8px; |
| | | border: 1px solid #dee2e6; |
| | | |
| | | .summary-content { |
| | | display: flex; |
| | | justify-content: space-around; |
| | | align-items: center; |
| | | |
| | | .summary-item { |
| | | text-align: center; |
| | | |
| | | .label { |
| | | font-size: 16px; |
| | | color: #606266; |
| | | margin-right: 8px; |
| | | } |
| | | |
| | | .value { |
| | | font-size: 24px; |
| | | font-weight: 600; |
| | | color: #409eff; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .pagination-section { |
| | | display: flex; |
| | | justify-content: center; |
| | | padding: 20px 0 0 0; |
| | | } |
| | | } |
| | | |
| | | .type-detail-section { |
| | | .type-detail-table { |
| | | ::v-deep .el-table__header-wrapper { |
| | | th { |
| | | background-color: #f0f7ff; |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | } |
| | | |
| | | .type-name-cell { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | |
| | | .type-name { |
| | | font-weight: 500; |
| | | } |
| | | } |
| | | |
| | | .number-text { |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | |
| | | .rate-text { |
| | | font-weight: 600; |
| | | font-size: 14px; |
| | | |
| | | &.rate-high { |
| | | color: #67c23a; |
| | | } |
| | | |
| | | &.rate-medium { |
| | | color: #e6a23c; |
| | | } |
| | | |
| | | &.rate-low { |
| | | color: #f56c6c; |
| | | } |
| | | } |
| | | |
| | | .score-text { |
| | | font-weight: 600; |
| | | color: #409eff; |
| | | font-size: 15px; |
| | | } |
| | | |
| | | .trend-cell { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | gap: 5px; |
| | | |
| | | .trend-up, |
| | | .trend-down, |
| | | .trend-stable { |
| | | font-size: 16px; |
| | | } |
| | | |
| | | .trend-text { |
| | | font-size: 13px; |
| | | color: #666; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .type-summary-row { |
| | | margin-top: 20px; |
| | | padding: 20px; |
| | | background: linear-gradient(135deg, #f0f9ff 0%, #e6f7ff 100%); |
| | | border-radius: 8px; |
| | | border: 1px solid #d0ebff; |
| | | |
| | | .type-summary-content { |
| | | display: flex; |
| | | justify-content: space-around; |
| | | align-items: center; |
| | | flex-wrap: wrap; |
| | | gap: 20px; |
| | | |
| | | .type-summary-item { |
| | | text-align: center; |
| | | min-width: 150px; |
| | | |
| | | .label { |
| | | font-size: 14px; |
| | | color: #606266; |
| | | margin-right: 8px; |
| | | } |
| | | |
| | | .value { |
| | | font-size: 20px; |
| | | font-weight: 600; |
| | | color: #409eff; |
| | | } |
| | | |
| | | .high-count { |
| | | color: #67c23a; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | // å
å±è¡¨æ ¼æ ·å¼ |
| | | .inner-table { |
| | | ::v-deep .el-table__header-wrapper { |
| | | th { |
| | | background-color: #f0f7ff !important; |
| | | color: #333; |
| | | font-weight: 600; |
| | | } |
| | | } |
| | | |
| | | ::v-deep .el-table__body-wrapper { |
| | | tr { |
| | | background-color: #fff; |
| | | |
| | | &:hover { |
| | | background-color: #f5f7fa; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | @media (max-width: 768px) { |
| | | .satisfaction-statistics { |
| | | padding: 10px; |
| | | |
| | | .query-section { |
| | | .query-form { |
| | | ::v-deep .el-form-item { |
| | | width: 100%; |
| | | margin-right: 0; |
| | | margin-bottom: 10px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .chart-section { |
| | | .chart-container { |
| | | .chart-header { |
| | | flex-direction: column; |
| | | align-items: flex-start; |
| | | gap: 15px; |
| | | |
| | | .statistic-info { |
| | | width: 100%; |
| | | justify-content: space-between; |
| | | flex-wrap: wrap; |
| | | gap: 10px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .detail-table-section { |
| | | .summary-content { |
| | | flex-direction: column; |
| | | gap: 15px; |
| | | } |
| | | } |
| | | |
| | | .type-detail-section { |
| | | .type-summary-content { |
| | | flex-direction: column; |
| | | gap: 15px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="seedetails-dialog"> |
| | | <div class="examine-jic"> |
| | | <div class="jic-value"> |
| | | <!-- æ¥è¯¢è¡¨å --> |
| | | <el-form |
| | | :model="patientqueryParams" |
| | | ref="patientQueryForm" |
| | | size="small" |
| | | :inline="true" |
| | | class="detail-query-form" |
| | | > |
| | | <el-form-item label="æ£è
ï¼" prop="name"> |
| | | <el-input |
| | | v-model="patientqueryParams.name" |
| | | placeholder="请è¾å
¥æ£è
å§å" |
| | | clearable |
| | | @keyup.enter.native="handleSearch" |
| | | style="width: 180px" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="æ£è
è¯æï¼" prop="leavediagname"> |
| | | <el-input |
| | | v-model="patientqueryParams.leavediagname" |
| | | placeholder="请è¾å
¥æ£è
è¯æ" |
| | | clearable |
| | | @keyup.enter.native="handleSearch" |
| | | style="width: 200px" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item> |
| | | <el-button |
| | | type="primary" |
| | | icon="el-icon-search" |
| | | @click="handleSearch" |
| | | :loading="loading" |
| | | > |
| | | æç´¢ |
| | | </el-button> |
| | | <el-button icon="el-icon-refresh" @click="handleReset"> |
| | | éç½® |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <!-- æ£è
åè¡¨è¡¨æ ¼ --> |
| | | <el-table |
| | | v-loading="loading" |
| | | :data="logsheetlist" |
| | | style="width: 100%" |
| | | :border="true" |
| | | class="patient-table" |
| | | > |
| | | <el-table-column |
| | | prop="sendname" |
| | | label="å§å" |
| | | align="center" |
| | | width="100" |
| | | /> |
| | | |
| | | <el-table-column |
| | | prop="taskName" |
| | | label="ä»»å¡åç§°" |
| | | align="center" |
| | | width="200" |
| | | show-overflow-tooltip |
| | | /> |
| | | |
| | | <el-table-column |
| | | prop="sendstate" |
| | | label="ä»»å¡ç¶æ" |
| | | align="center" |
| | | width="120" |
| | | > |
| | | <template slot-scope="{ row }"> |
| | | <div v-if="row.sendstate == 1"> |
| | | <el-tag type="primary" size="small">表åå·²é¢å</el-tag> |
| | | </div> |
| | | <div v-if="row.sendstate == 2"> |
| | | <el-tag type="primary" size="small">å¾
é访</el-tag> |
| | | </div> |
| | | <div v-if="row.sendstate == 3"> |
| | | <el-tag type="success" size="small">表åå·²åé</el-tag> |
| | | </div> |
| | | <div v-if="row.sendstate == 4"> |
| | | <el-tag type="info" size="small">䏿§è¡</el-tag> |
| | | </div> |
| | | <div v-if="row.sendstate == 5"> |
| | | <el-tag type="danger" size="small">åé失败</el-tag> |
| | | </div> |
| | | <div v-if="row.sendstate == 6"> |
| | | <el-tag type="success" size="small">已宿</el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | prop="visitTime" |
| | | label="åºé访æ¶é´" |
| | | align="center" |
| | | width="180" |
| | | show-overflow-tooltip |
| | | /> |
| | | |
| | | <el-table-column |
| | | prop="finishtime" |
| | | label="éè®¿å®ææ¶é´" |
| | | align="center" |
| | | width="180" |
| | | show-overflow-tooltip |
| | | > |
| | | <template slot-scope="{ row }"> |
| | | <span v-if="row.finishtime">{{ row.finishtime }}</span> |
| | | <span v-else style="color: #f56c6c">æªå®æ</span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="åºé¢æ¥æ" |
| | | width="120" |
| | | align="center" |
| | | key="endtime" |
| | | prop="endtime" |
| | | > |
| | | <template slot-scope="{ row }"> |
| | | <span v-if="row.endtime">{{ formatTime(row.endtime) }}</span> |
| | | <span v-else>-</span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="责任æ¤å£«" |
| | | width="120" |
| | | align="center" |
| | | key="nurseName" |
| | | prop="nurseName" |
| | | /> |
| | | |
| | | <el-table-column |
| | | label="主治å»ç" |
| | | width="120" |
| | | align="center" |
| | | key="drname" |
| | | prop="drname" |
| | | /> |
| | | |
| | | <el-table-column |
| | | label="ç»æç¶æ" |
| | | align="center" |
| | | key="excep" |
| | | prop="excep" |
| | | width="120" |
| | | > |
| | | <template slot-scope="{ row }"> |
| | | <dict-tag |
| | | :options="dict.type.sys_yujing" |
| | | :value="row.excep" |
| | | size="small" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="å¤çæè§" |
| | | align="center" |
| | | key="suggest" |
| | | prop="suggest" |
| | | width="120" |
| | | > |
| | | <template slot-scope="{ row }"> |
| | | <dict-tag |
| | | :options="dict.type.sys_suggest" |
| | | :value="row.suggest" |
| | | size="small" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | prop="templatename" |
| | | label="æå¡æ¨¡æ¿" |
| | | width="150" |
| | | align="center" |
| | | show-overflow-tooltip |
| | | /> |
| | | |
| | | <el-table-column |
| | | prop="remark" |
| | | label="æå¡è®°å½" |
| | | width="150" |
| | | align="center" |
| | | show-overflow-tooltip |
| | | /> |
| | | |
| | | <el-table-column |
| | | prop="bankcardno" |
| | | label="å¼å«ç¶æ" |
| | | width="120" |
| | | align="center" |
| | | /> |
| | | |
| | | <el-table-column |
| | | label="æä½" |
| | | fixed="right" |
| | | align="center" |
| | | width="100" |
| | | > |
| | | <template slot-scope="{ row }"> |
| | | <el-button |
| | | type="text" |
| | | size="small" |
| | | @click="handleViewDetail(row)" |
| | | > |
| | | <i class="el-icon-view"></i> æ¥ç |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <!-- å页 --> |
| | | <div class="pagination" v-if="patienttotal > 0"> |
| | | <el-pagination |
| | | background |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | :current-page="patientqueryParams.pn" |
| | | :page-size="patientqueryParams.ps" |
| | | :page-sizes="[10, 20, 30]" |
| | | :total="patienttotal" |
| | | @size-change="handleSizeChange" |
| | | @current-change="handlePageChange" |
| | | /> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { selectTimelyRate } from "@/api/system/user"; |
| | | |
| | | export default { |
| | | name: 'SeedetailsDialog', |
| | | dicts: ['sys_yujing', 'sys_suggest'], |
| | | props: { |
| | | rowData: { |
| | | type: Object, |
| | | default: () => ({}) |
| | | }, |
| | | queryParams: { |
| | | type: Object, |
| | | default: () => ({}) |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | // æ¥è¯¢åæ° |
| | | patientqueryParams: { |
| | | pn: 1, |
| | | ps: 10, |
| | | name: '', |
| | | leavediagname: '' |
| | | }, |
| | | |
| | | // å è½½ç¶æ |
| | | loading: false, |
| | | |
| | | // æ£è
å表 |
| | | logsheetlist: [], |
| | | |
| | | // æ»æ¡æ° |
| | | patienttotal: 0 |
| | | }; |
| | | }, |
| | | |
| | | mounted() { |
| | | this.loadData(); |
| | | }, |
| | | |
| | | methods: { |
| | | // å è½½æ°æ® |
| | | async loadData() { |
| | | this.loading = true; |
| | | try { |
| | | const params = { |
| | | ...this.patientqueryParams, |
| | | deptcode: this.rowData.deptcode || '', |
| | | starttime: this.queryParams.dateRange?.[0] ? this.parseTime(this.queryParams.dateRange[0]) : '', |
| | | endtime: this.queryParams.dateRange?.[1] ? this.parseTime(this.queryParams.dateRange[1]) : '' |
| | | }; |
| | | |
| | | const response = await selectTimelyRate(params); |
| | | this.logsheetlist = response.data?.detail || []; |
| | | this.patienttotal = response.data?.total || 0; |
| | | } catch (error) { |
| | | console.error('è·åæªåæ¶é访详æ
失败:', error); |
| | | this.$message.error('è·åæ°æ®å¤±è´¥'); |
| | | } finally { |
| | | this.loading = false; |
| | | } |
| | | }, |
| | | |
| | | // å¤çæç´¢ |
| | | handleSearch() { |
| | | this.patientqueryParams.pn = 1; |
| | | this.loadData(); |
| | | }, |
| | | |
| | | // å¤çéç½® |
| | | handleReset() { |
| | | this.patientqueryParams = { |
| | | pn: 1, |
| | | ps: 10, |
| | | name: '', |
| | | leavediagname: '' |
| | | }; |
| | | this.loadData(); |
| | | }, |
| | | |
| | | // å¤çå页大å°åå |
| | | handleSizeChange(size) { |
| | | this.patientqueryParams.ps = size; |
| | | this.patientqueryParams.pn = 1; |
| | | this.loadData(); |
| | | }, |
| | | |
| | | // å¤ç页ç åå |
| | | handlePageChange(page) { |
| | | this.patientqueryParams.pn = page; |
| | | this.loadData(); |
| | | }, |
| | | |
| | | // æ ¼å¼åæ¶é´ |
| | | formatTime(time) { |
| | | if (!time) return '-'; |
| | | return time; |
| | | }, |
| | | |
| | | // è§£ææ¶é´ |
| | | parseTime(time) { |
| | | if (!time) return ''; |
| | | return time; |
| | | }, |
| | | |
| | | // æ¥ç详æ
|
| | | handleViewDetail(row) { |
| | | this.$emit('close'); |
| | | |
| | | let type = ""; |
| | | if (row.preachformson && row.preachformson.includes("3")) { |
| | | type = 1; |
| | | } |
| | | |
| | | setTimeout(() => { |
| | | this.$router.push({ |
| | | path: "/followvisit/record/detailpage/", |
| | | query: { |
| | | taskid: row.taskid, |
| | | patid: row.patid, |
| | | id: row.id, |
| | | Voicetype: type |
| | | } |
| | | }); |
| | | }, 300); |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .seedetails-dialog { |
| | | .detail-query-form { |
| | | margin-bottom: 20px; |
| | | padding-bottom: 20px; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | |
| | | ::v-deep .el-form-item { |
| | | margin-bottom: 0; |
| | | margin-right: 20px; |
| | | } |
| | | } |
| | | |
| | | .patient-table { |
| | | margin-bottom: 20px; |
| | | |
| | | ::v-deep .el-table__header-wrapper th { |
| | | background-color: #f8f9fa; |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | } |
| | | |
| | | .pagination { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | padding-top: 20px; |
| | | border-top: 1px solid #f0f0f0; |
| | | } |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="topic-dialog"> |
| | | <div class="topicdia"> |
| | | <div style="overflow-x: hidden; overflow-y: auto; max-height: 65vh"> |
| | | <!-- ä¿®æ¹è¿éï¼ä½¿ç¨ processedTopicList è䏿¯ topicList --> |
| | | <div |
| | | v-for="(item, index) in processedTopicList" |
| | | :key="item.scriptid" |
| | | class="ttaabbcc" |
| | | > |
| | | <div class="describe"> |
| | | 第{{ index + 1 }}é¢ï¼ {{ item.scriptContent }} |
| | | <span>[{{ item.scriptType == 1 ? "åéé¢" : "å¤éé¢" }}]</span> |
| | | </div> |
| | | <div> |
| | | <el-table :data="item.details" style="width: 100%"> |
| | | <el-table-column |
| | | prop="optionText" |
| | | label="é®é¢é项" |
| | | align="center" |
| | | min-width="200" |
| | | /> |
| | | <el-table-column |
| | | prop="chosenQuantity" |
| | | label="éæ©äººæ°" |
| | | align="center" |
| | | min-width="120" |
| | | > |
| | | <template slot-scope="{ row }"> |
| | | {{ row.chosenQuantity || 0 }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | prop="chosenPercentage" |
| | | label="æ¯ä¾" |
| | | align="center" |
| | | min-width="120" |
| | | > |
| | | <template slot-scope="{ row }"> |
| | | <span |
| | | v-if=" |
| | | row.chosenPercentage !== null && |
| | | row.chosenPercentage !== undefined |
| | | " |
| | | > |
| | | {{ (Number(row.chosenPercentage) * 100).toFixed(2) }}% |
| | | </span> |
| | | <span v-else>-</span> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- å¦ææ²¡ææ°æ® --> |
| | | <div |
| | | v-if="!processedTopicList.length" |
| | | class="no-data" |
| | | style="text-align: center; padding: 50px 0" |
| | | > |
| | | <el-empty description="ææ æ°æ®"></el-empty> |
| | | </div> |
| | | |
| | | <div |
| | | slot="footer" |
| | | class="dialog-footer" |
| | | style="text-align: center; padding-top: 20px" |
| | | > |
| | | <el-button @click="handleClose">å
³ é</el-button> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: "TopicDialog", |
| | | props: { |
| | | rowData: { |
| | | type: Object, |
| | | default: () => ({}), |
| | | }, |
| | | queryParams: { |
| | | type: Object, |
| | | default: () => ({}), |
| | | }, |
| | | topicList: { |
| | | type: [Array, Object], |
| | | default: () => ({}), |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | processedTopicList: [], // å¤çåçæ°æ® |
| | | }; |
| | | }, |
| | | watch: { |
| | | // çå¬ç¶ç»ä»¶ä¼ éçæ°æ®åå |
| | | topicList: { |
| | | immediate: true, |
| | | handler(newVal) { |
| | | console.log("TopicDialogæ¥æ¶å°ç¶ç»ä»¶æ°æ®:", newVal); |
| | | this.processTopicList(newVal); |
| | | }, |
| | | }, |
| | | }, |
| | | mounted() { |
| | | console.log("TopicDialog mounted, props:", this.$props); |
| | | }, |
| | | methods: { |
| | | // å¤çtopicListæ°æ® |
| | | processTopicList(data) { |
| | | console.log("å¼å§å¤çæ°æ®:", data); |
| | | |
| | | if (!data || typeof data !== "object") { |
| | | this.processedTopicList = []; |
| | | return; |
| | | } |
| | | |
| | | // å°å¯¹è±¡è½¬æ¢ä¸ºæ°ç» |
| | | const result = []; |
| | | |
| | | Object.keys(data).forEach((key) => { |
| | | const item = data[key]; |
| | | if (item && item.scriptContent) { |
| | | // æ·±æ·è´itemï¼é¿å
ä¿®æ¹åæ°æ® |
| | | const processedItem = JSON.parse(JSON.stringify(item)); |
| | | |
| | | // è¿æ»¤detailsï¼åªä¿çæéé¡¹ææ¬ç |
| | | if (processedItem.details && Array.isArray(processedItem.details)) { |
| | | processedItem.details = processedItem.details.filter( |
| | | (detail) => detail && detail.optionText |
| | | ); |
| | | } |
| | | |
| | | result.push(processedItem); |
| | | } |
| | | }); |
| | | |
| | | console.log("å¤çåçæ°æ®:", result); |
| | | this.processedTopicList = result; |
| | | }, |
| | | |
| | | // æ ¼å¼åç¾åæ¯ |
| | | formatPercent(value) { |
| | | if (value === null || value === undefined) return "-"; |
| | | const num = parseFloat(value); |
| | | if (isNaN(num)) return "-"; |
| | | return `${num.toFixed(2)}%`; // 注æï¼ä½ çæ°æ®ä¸ç¾åæ¯å·²ç»æ¯0-100çå½¢å¼ |
| | | }, |
| | | |
| | | // å
³éå¯¹è¯æ¡ |
| | | handleClose() { |
| | | this.$emit("close"); |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .topic-dialog { |
| | | .topicdia { |
| | | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, |
| | | "Helvetica Neue", Arial, sans-serif; |
| | | color: #333; |
| | | } |
| | | |
| | | .ttaabbcc { |
| | | background: #fafafa; |
| | | border-radius: 6px; |
| | | padding: 16px; |
| | | margin-bottom: 20px; |
| | | border-left: 4px solid #4794c5; |
| | | } |
| | | |
| | | .describe { |
| | | font-size: 15px; |
| | | line-height: 1.6; |
| | | margin-bottom: 12px; |
| | | color: #1f2d3d; |
| | | } |
| | | |
| | | .describe span { |
| | | font-size: 13px; |
| | | color: #999; |
| | | font-style: italic; |
| | | margin-left: 8px; |
| | | } |
| | | |
| | | ::v-deep .el-table { |
| | | border-radius: 4px; |
| | | overflow: hidden; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | ::v-deep .el-table th { |
| | | background-color: #f1f5f9; |
| | | color: #333; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | ::v-deep .el-table td { |
| | | border-bottom: 1px solid #f0f0f0; |
| | | padding: 12px 0; |
| | | } |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="followup-statistics"> |
| | | <div class="query-section"> |
| | | <el-form |
| | | :model="queryParams" |
| | | ref="queryForm" |
| | | size="medium" |
| | | :inline="true" |
| | | label-width="100px" |
| | | class="query-form" |
| | | > |
| | | <el-form-item label="ç»è®¡ç±»å" prop="statisticaltype"> |
| | | <el-select |
| | | v-model="queryParams.statisticaltype" |
| | | placeholder="è¯·éæ©ç»è®¡ç±»å" |
| | | clearable |
| | | @change="handleStatisticalTypeChange" |
| | | > |
| | | <el-option |
| | | v-for="item in Statisticallist" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <!-- ç
åºéæ© --> |
| | | <el-form-item |
| | | v-if="queryParams.statisticaltype == 1" |
| | | label="ç
åº" |
| | | prop="leavehospitaldistrictcodes" |
| | | > |
| | | <el-select |
| | | v-model="queryParams.leavehospitaldistrictcodes" |
| | | placeholder="è¯·éæ©ç
åº" |
| | | multiple |
| | | collapse-tags |
| | | filterable |
| | | clearable |
| | | style="width: 300px" |
| | | > |
| | | <el-option |
| | | v-for="item in flatArrayhospit" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <!-- ç§å®¤éæ© --> |
| | | <el-form-item |
| | | v-if="queryParams.statisticaltype == 2" |
| | | label="ç§å®¤" |
| | | prop="deptcodes" |
| | | > |
| | | <el-select |
| | | v-model="queryParams.deptcodes" |
| | | placeholder="è¯·éæ©ç§å®¤" |
| | | multiple |
| | | collapse-tags |
| | | filterable |
| | | clearable |
| | | style="width: 300px" |
| | | > |
| | | <el-option |
| | | v-for="item in flatArraydept" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="æå¡ç±»å" prop="serviceType"> |
| | | <el-select |
| | | v-model="queryParams.serviceType" |
| | | placeholder="è¯·éæ©æå¡ç±»å" |
| | | multiple |
| | | collapse-tags |
| | | clearable |
| | | style="width: 300px" |
| | | > |
| | | <el-option |
| | | v-for="item in options" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="é访æ¶é´" prop="dateRange"> |
| | | <el-date-picker |
| | | v-model="queryParams.dateRange" |
| | | type="daterange" |
| | | range-separator="è³" |
| | | start-placeholder="å¼å§æ¥æ" |
| | | end-placeholder="ç»ææ¥æ" |
| | | value-format="yyyy-MM-dd" |
| | | :picker-options="pickerOptions" |
| | | style="width: 380px" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item> |
| | | <el-button |
| | | type="primary" |
| | | icon="el-icon-search" |
| | | @click="handleQuery" |
| | | :loading="loading" |
| | | > |
| | | æç´¢ |
| | | </el-button> |
| | | <el-button icon="el-icon-refresh" @click="resetQuery"> |
| | | éç½® |
| | | </el-button> |
| | | <el-button |
| | | type="warning" |
| | | icon="el-icon-download" |
| | | @click="handleExport" |
| | | :disabled="!userList.length" |
| | | > |
| | | å¯¼åº |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | |
| | | <div class="table-section"> |
| | | <el-table |
| | | v-loading="loading" |
| | | :data="userList" |
| | | :border="true" |
| | | style="width: 100%" |
| | | @selection-change="handleSelectionChange" |
| | | :row-key="getRowKey" |
| | | > |
| | | <!-- ç
åºå --> |
| | | <el-table-column |
| | | v-if="queryParams.statisticaltype == 1" |
| | | label="åºé¢ç
åº" |
| | | align="center" |
| | | sortable |
| | | key="leavehospitaldistrictname" |
| | | prop="leavehospitaldistrictname" |
| | | :show-overflow-tooltip="true" |
| | | :sort-method="sortChineseNumber" |
| | | min-width="120" |
| | | /> |
| | | |
| | | <!-- ç§å®¤å --> |
| | | <el-table-column |
| | | v-if="queryParams.statisticaltype == 2" |
| | | label="ç§å®¤" |
| | | align="center" |
| | | key="deptname" |
| | | prop="deptname" |
| | | :show-overflow-tooltip="true" |
| | | min-width="120" |
| | | /> |
| | | |
| | | <el-table-column |
| | | label="åºé¢äººæ¬¡" |
| | | align="center" |
| | | key="dischargeCount" |
| | | prop="dischargeCount" |
| | | min-width="100" |
| | | /> |
| | | |
| | | <el-table-column |
| | | label="æ éé访人次" |
| | | align="center" |
| | | key="nonFollowUp" |
| | | prop="nonFollowUp" |
| | | min-width="120" |
| | | /> |
| | | |
| | | <el-table-column |
| | | label="åºé访人次" |
| | | align="center" |
| | | key="followUpNeeded" |
| | | prop="followUpNeeded" |
| | | min-width="120" |
| | | /> |
| | | |
| | | <el-table-column |
| | | label="é访ç" |
| | | align="center" |
| | | key="followUpRate" |
| | | prop="followUpRate" |
| | | min-width="100" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span |
| | | v-if=" |
| | | scope.row.followUpRate !== null && |
| | | scope.row.followUpRate !== undefined |
| | | " |
| | | > |
| | | {{ scope.row.followUpRate }} |
| | | </span> |
| | | <span v-else>-</span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="åæ¶ç" |
| | | align="center" |
| | | key="rate" |
| | | prop="rate" |
| | | min-width="100" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | v-if="scope.row.rate !== null && scope.row.rate !== undefined" |
| | | type="text" |
| | | @click="handleSeedetails(scope.row)" |
| | | > |
| | | {{ formatPercent(scope.row.rate) }} |
| | | </el-button> |
| | | <span v-else style="color: #909399">-</span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="å¤è¯éç¥é¢ç®æ»é" |
| | | align="center" |
| | | key="joyAllCount" |
| | | prop="joyAllCount" |
| | | min-width="140" |
| | | /> |
| | | |
| | | <el-table-column |
| | | label="å¤è¯éç¥å¡«æ¥é" |
| | | align="center" |
| | | key="joyCount" |
| | | prop="joyCount" |
| | | min-width="120" |
| | | /> |
| | | |
| | | <el-table-column |
| | | label="宿æ¯ç" |
| | | align="center" |
| | | key="joyTotal" |
| | | prop="joyTotal" |
| | | min-width="100" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span |
| | | v-if=" |
| | | scope.row.joyTotal !== null && scope.row.joyTotal !== undefined |
| | | " |
| | | > |
| | | {{ formatPercent(scope.row.joyTotal) }} |
| | | </span> |
| | | <span v-else>-</span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column label="æä½" align="center" fixed="right" width="120"> |
| | | <template slot-scope="scope"> |
| | | <el-button type="text" @click="getinfo(scope.row)"> |
| | | <i class="el-icon-s-order" style="margin-right: 4px"></i> |
| | | æ¥ç详æ
|
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | |
| | | <!-- å页 --> |
| | | <div class="pagination-section" v-if="total > 0"> |
| | | <el-pagination |
| | | background |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | :current-page="queryParams.pageNum" |
| | | :page-size="queryParams.pageSize" |
| | | :page-sizes="[10, 20, 30, 50]" |
| | | :total="total" |
| | | @size-change="handleSizeChange" |
| | | @current-change="handlePageChange" |
| | | /> |
| | | </div> |
| | | |
| | | <!-- æªåæ¶é访详æ
å¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | title="æªåæ¶é访æ£è
æå¡" |
| | | :visible.sync="SeedetailsVisible" |
| | | width="80%" |
| | | :close-on-click-modal="false" |
| | | > |
| | | <SeedetailsDialog |
| | | v-if="SeedetailsVisible" |
| | | :row-data="currentRow" |
| | | :query-params="queryParams" |
| | | @close="SeedetailsVisible = false" |
| | | /> |
| | | </el-dialog> |
| | | |
| | | <!-- å¤è¯éç¥è¯¦æ
å¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | :visible.sync="topicVisible" |
| | | width="60%" |
| | | :close-on-click-modal="false" |
| | | > |
| | | <template #title> |
| | | <div style="display: flex; align-items: center"> |
| | | <i |
| | | class="el-icon-s-data" |
| | | style="margin-right: 8px; color: #409eff" |
| | | ></i> |
| | | <span>{{ topicvalue.name }}</span> |
| | | <span style="margin-left: 10px; color: #666; font-size: 14px" |
| | | >å¤è¯éç¥ææ 详æ
</span |
| | | > |
| | | </div> |
| | | </template> |
| | | <topic-dialog |
| | | v-if="topicVisible" |
| | | :row-data="currentRow" |
| | | :topicList="topiclist" |
| | | :query-params="queryParams" |
| | | @close="topicVisible = false" |
| | | /> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { |
| | | getSfStatisticsJoy, |
| | | getSfStatisticsJoyInfo, |
| | | selectTimelyRate, |
| | | } from "@/api/system/user"; |
| | | import ExcelJS from "exceljs"; |
| | | import { saveAs } from "file-saver"; |
| | | import SeedetailsDialog from "./components/SeedetailsDialog.vue"; |
| | | import TopicDialog from "./components/TopicDialog.vue"; |
| | | |
| | | export default { |
| | | name: "FollowupStatistics", |
| | | components: { |
| | | SeedetailsDialog, |
| | | TopicDialog, |
| | | }, |
| | | data() { |
| | | return { |
| | | // æ¥è¯¢åæ° |
| | | queryParams: { |
| | | statisticaltype: 1, |
| | | leavehospitaldistrictcodes: ["all"], |
| | | deptcodes: [], |
| | | serviceType: [2], |
| | | dateRange: [], |
| | | pageNum: 1, |
| | | pageSize: 20, |
| | | }, |
| | | |
| | | // ç»è®¡ç±»åå表 |
| | | Statisticallist: [ |
| | | { label: "ç
åºç»è®¡", value: 1 }, |
| | | { label: "ç§å®¤ç»è®¡", value: 2 }, |
| | | ], |
| | | |
| | | // ç
åºå表 |
| | | flatArrayhospit: [], |
| | | |
| | | // ç§å®¤å表 |
| | | flatArraydept: [], |
| | | |
| | | // æå¡ç±»åé项 |
| | | options: [], |
| | | |
| | | // è¡¨æ ¼æ°æ® |
| | | userList: [], |
| | | |
| | | // æ»æ¡æ° |
| | | total: 0, |
| | | |
| | | // å è½½ç¶æ |
| | | loading: false, |
| | | |
| | | // éä¸çè¡ |
| | | ids: [], |
| | | single: true, |
| | | multiple: true, |
| | | |
| | | // å½åæä½çè¡ |
| | | currentRow: null, |
| | | |
| | | // å¯¹è¯æ¡æ¾ç¤ºæ§å¶ |
| | | SeedetailsVisible: false, |
| | | topicVisible: false, |
| | | |
| | | // å¤è¯éç¥è¯¦æ
æ°æ® |
| | | topiclist: [], |
| | | topicvalue: { |
| | | name: "", |
| | | }, |
| | | |
| | | // æ¥æéæ©å¨é项 |
| | | pickerOptions: { |
| | | shortcuts: [ |
| | | { |
| | | text: "æè¿ä¸å¨", |
| | | onClick(picker) { |
| | | const end = new Date(); |
| | | const start = new Date(); |
| | | start.setTime(start.getTime() - 3600 * 1000 * 24 * 7); |
| | | picker.$emit("pick", [start, end]); |
| | | }, |
| | | }, |
| | | { |
| | | text: "æè¿ä¸ä¸ªæ", |
| | | onClick(picker) { |
| | | const end = new Date(); |
| | | const start = new Date(); |
| | | start.setTime(start.getTime() - 3600 * 1000 * 24 * 30); |
| | | picker.$emit("pick", [start, end]); |
| | | }, |
| | | }, |
| | | { |
| | | text: "æè¿ä¸ä¸ªæ", |
| | | onClick(picker) { |
| | | const end = new Date(); |
| | | const start = new Date(); |
| | | start.setTime(start.getTime() - 3600 * 1000 * 24 * 90); |
| | | picker.$emit("pick", [start, end]); |
| | | }, |
| | | }, |
| | | ], |
| | | disabledDate(time) { |
| | | return time.getTime() > Date.now(); |
| | | }, |
| | | }, |
| | | }; |
| | | }, |
| | | |
| | | created() { |
| | | this.initData(); |
| | | }, |
| | | |
| | | methods: { |
| | | // åå§åæ°æ® |
| | | async initData() { |
| | | await this.getDeptTree(); |
| | | await this.getList(); |
| | | }, |
| | | |
| | | // è·åç§å®¤æ |
| | | getDeptTree() { |
| | | // è·åæå¡ç±»å |
| | | this.options = this.$store.getters.tasktypes || []; |
| | | |
| | | // è·åç§å®¤å表 |
| | | this.flatArraydept = (this.$store.getters.belongDepts || []).map( |
| | | (dept) => { |
| | | return { |
| | | label: dept.deptName, |
| | | value: dept.deptCode, |
| | | }; |
| | | } |
| | | ); |
| | | |
| | | // è·åç
åºå表 |
| | | this.flatArrayhospit = (this.$store.getters.belongWards || []).map( |
| | | (ward) => { |
| | | return { |
| | | label: ward.districtName, |
| | | value: ward.districtCode, |
| | | }; |
| | | } |
| | | ); |
| | | |
| | | // æ·»å å
¨é¨é项 |
| | | this.flatArraydept.push({ label: "å
¨é¨", value: "all" }); |
| | | this.flatArrayhospit.push({ label: "å
¨é¨", value: "all" }); |
| | | }, |
| | | |
| | | // è·åç»è®¡å表 |
| | | async getList() { |
| | | this.loading = true; |
| | | try { |
| | | // å¤çæ¥è¯¢åæ° |
| | | const params = { |
| | | configKey: "returnVisitCount", |
| | | ...this.queryParams, |
| | | }; |
| | | |
| | | // å¤çæ¥æèå´ |
| | | if ( |
| | | this.queryParams.dateRange && |
| | | this.queryParams.dateRange.length === 2 |
| | | ) { |
| | | params.startTime = this.queryParams.dateRange[0]; |
| | | params.endTime = this.queryParams.dateRange[1]; |
| | | } |
| | | |
| | | // å¤çç
åº/ç§å®¤éæ© |
| | | if (params.statisticaltype == 1) { |
| | | // ç
åºç»è®¡ |
| | | if (params.leavehospitaldistrictcodes.includes("all")) { |
| | | // 妿鿩äº"å
¨é¨"ï¼åç§»é¤"all"å¼ |
| | | params.leavehospitaldistrictcodes = |
| | | params.leavehospitaldistrictcodes.filter( |
| | | (item) => item !== "all" |
| | | ); |
| | | // 妿éè¦ä¼ ææç
åºä»£ç ï¼å¯ä»¥ä»storeä¸è·å |
| | | params.leavehospitaldistrictcodes = ( |
| | | this.$store.getters.belongWards || [] |
| | | ).map((ward) => ward.districtCode); |
| | | } |
| | | } else if (params.statisticaltype == 2) { |
| | | // ç§å®¤ç»è®¡ |
| | | if (params.deptcodes.includes("all")) { |
| | | // 妿鿩äº"å
¨é¨"ï¼åç§»é¤"all"å¼ |
| | | params.deptcodes = params.deptcodes.filter( |
| | | (item) => item !== "all" |
| | | ); |
| | | // 妿éè¦ä¼ ææç§å®¤ä»£ç ï¼å¯ä»¥ä»storeä¸è·å |
| | | params.deptcodes = (this.$store.getters.belongDepts || []).map( |
| | | (dept) => dept.deptCode |
| | | ); |
| | | } |
| | | } |
| | | |
| | | const response = await getSfStatisticsJoy(params); |
| | | this.userList = this.customSort(response.data) || []; |
| | | this.total = response.total || 0; |
| | | } catch (error) { |
| | | console.error("è·åç»è®¡å表失败:", error); |
| | | this.$message.error("è·åæ°æ®å¤±è´¥"); |
| | | } finally { |
| | | this.loading = false; |
| | | } |
| | | }, |
| | | sortChineseNumber(aRow, bRow) { |
| | | const a = aRow.leavehospitaldistrictname; |
| | | const b = bRow.leavehospitaldistrictname; |
| | | |
| | | // 䏿æ°åå°é¿æä¼¯æ°åçæ å°ï¼æ©å±å°45ï¼ |
| | | const chineseNumMap = { |
| | | ä¸: 1, |
| | | äº: 2, |
| | | ä¸: 3, |
| | | å: 4, |
| | | äº: 5, |
| | | å
: 6, |
| | | ä¸: 7, |
| | | å
«: 8, |
| | | ä¹: 9, |
| | | å: 10, |
| | | åä¸: 11, |
| | | åäº: 12, |
| | | åä¸: 13, |
| | | åå: 14, |
| | | åäº: 15, |
| | | åå
: 16, |
| | | åä¸: 17, |
| | | åå
«: 18, |
| | | åä¹: 19, |
| | | äºå: 20, |
| | | äºåä¸: 21, |
| | | äºåäº: 22, |
| | | äºåä¸: 23, |
| | | äºåå: 24, |
| | | äºåäº: 25, |
| | | äºåå
: 26, |
| | | äºåä¸: 27, |
| | | äºåå
«: 28, |
| | | äºåä¹: 29, |
| | | ä¸å: 30, |
| | | ä¸åä¸: 31, |
| | | ä¸åäº: 32, |
| | | ä¸åä¸: 33, |
| | | ä¸åå: 34, |
| | | ä¸åäº: 35, |
| | | ä¸åå
: 36, |
| | | ä¸åä¸: 37, |
| | | ä¸åå
«: 38, |
| | | ä¸åä¹: 39, |
| | | åå: 40, |
| | | ååä¸: 41, |
| | | ååäº: 42, |
| | | ååä¸: 43, |
| | | ååå: 44, |
| | | ååäº: 45, |
| | | }; |
| | | |
| | | // æå䏿æ°å |
| | | const getNumberFromText = (text) => { |
| | | if (!text || typeof text !== "string") return -1; |
| | | |
| | | // å¹é
䏿æ°åï¼æ¯æä¸å°ååäº |
| | | const match = text.match(/^([ä¸äºä¸åäºå
ä¸å
«ä¹å]+)/); |
| | | |
| | | if (match && match[1]) { |
| | | const chineseNum = match[1]; |
| | | return chineseNumMap[chineseNum] !== undefined |
| | | ? chineseNumMap[chineseNum] |
| | | : -1; |
| | | } |
| | | |
| | | // å¦ææ²¡æå¹é
å°ä¸ææ°åï¼å°è¯å¹é
é¿æä¼¯æ°å |
| | | const arabicMatch = text.match(/^(\d+)/); |
| | | if (arabicMatch && arabicMatch[1]) { |
| | | const num = parseInt(arabicMatch[1], 10); |
| | | return num >= 1 && num <= 45 ? num : -1; |
| | | } |
| | | |
| | | return -1; |
| | | }; |
| | | |
| | | const numA = getNumberFromText(a); |
| | | const numB = getNumberFromText(b); |
| | | |
| | | // å¤çæ æ³è§£æçæ
åµ |
| | | if (numA === -1 && numB === -1) { |
| | | return (a || "").localeCompare(b || ""); |
| | | } |
| | | if (numA === -1) return 1; |
| | | if (numB === -1) return -1; |
| | | |
| | | return numA - numB; |
| | | }, |
| | | customSort(data) { |
| | | // å®ä¹æ¨ææçç
åºé¡ºåºï¼æ©å±å°ååäºï¼ |
| | | const order = [ |
| | | "ä¸", |
| | | "äº", |
| | | "ä¸", |
| | | "å", |
| | | "äº", |
| | | "å
", |
| | | "ä¸", |
| | | "å
«", |
| | | "ä¹", |
| | | "å", |
| | | "åä¸", |
| | | "åäº", |
| | | "åä¸", |
| | | "åå", |
| | | "åäº", |
| | | "åå
", |
| | | "åä¸", |
| | | "åå
«", |
| | | "åä¹", |
| | | "äºå", |
| | | "äºåä¸", |
| | | "äºåäº", |
| | | "äºåä¸", |
| | | "äºåå", |
| | | "äºåäº", |
| | | "äºåå
", |
| | | "äºåä¸", |
| | | "äºåå
«", |
| | | "äºåä¹", |
| | | "ä¸å", |
| | | "ä¸åä¸", |
| | | "ä¸åäº", |
| | | "ä¸åä¸", |
| | | "ä¸åå", |
| | | "ä¸åäº", |
| | | "ä¸åå
", |
| | | "ä¸åä¸", |
| | | "ä¸åå
«", |
| | | "ä¸åä¹", |
| | | "åå", |
| | | "ååä¸", |
| | | "ååäº", |
| | | "ååä¸", |
| | | "ååå", |
| | | "ååäº", |
| | | ]; |
| | | |
| | | return data.sort((a, b) => { |
| | | // æåç
åºåç§°ä¸ç䏿æ°åé¨å |
| | | const getIndex = (name) => { |
| | | if (!name || typeof name !== "string") return -1; |
| | | |
| | | // å¹é
䏿æ°å |
| | | const chineseMatch = name.match(/^([ä¸äºä¸åäºå
ä¸å
«ä¹å]+)/); |
| | | if (chineseMatch && chineseMatch[1]) { |
| | | return order.indexOf(chineseMatch[1]); |
| | | } |
| | | |
| | | // å¹é
é¿æä¼¯æ°å |
| | | const arabicMatch = name.match(/^(\d+)/); |
| | | if (arabicMatch && arabicMatch[1]) { |
| | | const num = parseInt(arabicMatch[1], 10); |
| | | if (num >= 1 && num <= 45) { |
| | | return num - 1; // å 为æ°ç»ç´¢å¼ä»0å¼å§ |
| | | } |
| | | } |
| | | |
| | | return -1; |
| | | }; |
| | | |
| | | const indexA = getIndex(a.leavehospitaldistrictname); |
| | | const indexB = getIndex(b.leavehospitaldistrictname); |
| | | |
| | | // æåºé»è¾ |
| | | if (indexA === -1 && indexB === -1) { |
| | | return (a.leavehospitaldistrictname || "").localeCompare( |
| | | b.leavehospitaldistrictname || "" |
| | | ); |
| | | } |
| | | if (indexA === -1) return 1; |
| | | if (indexB === -1) return -1; |
| | | return indexA - indexB; |
| | | }); |
| | | }, |
| | | // å¤çç»è®¡ç±»ååå |
| | | handleStatisticalTypeChange(value) { |
| | | if (value === 1) { |
| | | this.queryParams.deptcodes = []; |
| | | } else { |
| | | this.queryParams.leavehospitaldistrictcodes = []; |
| | | } |
| | | this.queryParams.pageNum = 1; |
| | | this.getList(); |
| | | }, |
| | | |
| | | // å¤çæ¥è¯¢ |
| | | handleQuery() { |
| | | this.queryParams.pageNum = 1; |
| | | this.getList(); |
| | | }, |
| | | |
| | | // éç½®æ¥è¯¢ |
| | | resetQuery() { |
| | | this.queryParams = { |
| | | statisticaltype: 1, |
| | | leavehospitaldistrictcodes: [], |
| | | deptcodes: [], |
| | | serviceType: [2], |
| | | dateRange: [], |
| | | pageNum: 1, |
| | | pageSize: 20, |
| | | }; |
| | | this.getList(); |
| | | }, |
| | | |
| | | // å¤çå页大å°åå |
| | | handleSizeChange(size) { |
| | | this.queryParams.pageSize = size; |
| | | this.queryParams.pageNum = 1; |
| | | this.getList(); |
| | | }, |
| | | |
| | | // å¤ç页ç åå |
| | | handlePageChange(page) { |
| | | this.queryParams.pageNum = page; |
| | | this.getList(); |
| | | }, |
| | | |
| | | // å¤çè¡éæ© |
| | | handleSelectionChange(selection) { |
| | | this.ids = selection.map((item) => item.id); |
| | | this.single = selection.length !== 1; |
| | | this.multiple = !selection.length; |
| | | }, |
| | | |
| | | // è·åè¡key |
| | | getRowKey(row) { |
| | | return row.statisticaltype === 1 |
| | | ? row.leavehospitaldistrictcode |
| | | : row.deptcode; |
| | | }, |
| | | |
| | | // æ ¼å¼åç¾åæ¯ |
| | | formatPercent(value) { |
| | | if (value === null || value === undefined) return "-"; |
| | | const num = parseFloat(value); |
| | | if (isNaN(num)) return "-"; |
| | | return `${(num * 100).toFixed(2)}%`; |
| | | }, |
| | | |
| | | // æ¥çæªåæ¶é访详æ
|
| | | handleSeedetails(row) { |
| | | this.currentRow = row; |
| | | this.SeedetailsVisible = true; |
| | | }, |
| | | |
| | | // æ¥çå¤è¯éç¥è¯¦æ
|
| | | async getinfo(row) { |
| | | this.currentRow = row; |
| | | |
| | | try { |
| | | // å¤çæ¥è¯¢åæ° |
| | | const params = { |
| | | configKey: "returnVisitCount", |
| | | ...this.queryParams, |
| | | }; |
| | | |
| | | // å¤çæ¥æèå´ |
| | | if ( |
| | | this.queryParams.dateRange && |
| | | this.queryParams.dateRange.length === 2 |
| | | ) { |
| | | params.startTime = this.queryParams.dateRange[0]; |
| | | params.endTime = this.queryParams.dateRange[1]; |
| | | } |
| | | |
| | | if (this.queryParams.statisticaltype == 1) { |
| | | this.topicvalue.name = row.leavehospitaldistrictname; |
| | | params.leavehospitaldistrictcodes = [row.leavehospitaldistrictcode]; |
| | | } else { |
| | | this.topicvalue.name = row.deptname; |
| | | params.deptcodes = [row.deptcode]; |
| | | } |
| | | |
| | | const response = await getSfStatisticsJoyInfo(params); |
| | | this.topiclist = response.data || []; |
| | | console.log(this.topiclist); |
| | | this.topicVisible = true; |
| | | } catch (error) { |
| | | console.error("è·åå¤è¯éç¥è¯¦æ
失败:", error); |
| | | this.$message.error("è·å详æ
失败"); |
| | | } |
| | | }, |
| | | |
| | | // å¯¼åºæ°æ® |
| | | async handleExport() { |
| | | if (!this.userList.length) { |
| | | this.$message.warning("æ²¡ææ°æ®å¯å¯¼åº"); |
| | | return; |
| | | } |
| | | |
| | | try { |
| | | this.loading = true; |
| | | |
| | | // æå»ºæ¥æèå´å符串 |
| | | let dateRangeString = ""; |
| | | let sheetNameSuffix = ""; |
| | | |
| | | if ( |
| | | this.queryParams.dateRange && |
| | | this.queryParams.dateRange.length === 2 |
| | | ) { |
| | | const startDateFormatted = this.queryParams.dateRange[0]; |
| | | const endDateFormatted = this.queryParams.dateRange[1]; |
| | | dateRangeString = `${startDateFormatted}è³${endDateFormatted}`; |
| | | sheetNameSuffix = `${startDateFormatted}è³${endDateFormatted}`; |
| | | } else { |
| | | const now = new Date(); |
| | | const currentMonth = now.getMonth() + 1; |
| | | dateRangeString = `${currentMonth}æ`; |
| | | sheetNameSuffix = `${currentMonth}æ`; |
| | | } |
| | | |
| | | const excelName = `é访ç»è®¡è¡¨_${dateRangeString}.xlsx`; |
| | | const worksheetName = `é访ç»è®¡_${sheetNameSuffix}`; |
| | | |
| | | // å建Excelå·¥ä½ç°¿ |
| | | const workbook = new ExcelJS.Workbook(); |
| | | const worksheet = workbook.addWorksheet(worksheetName); |
| | | |
| | | // å®ä¹æ ·å¼ |
| | | const titleStyle = { |
| | | font: { name: "微软é
é»", size: 16, bold: true }, |
| | | fill: { |
| | | type: "pattern", |
| | | pattern: "solid", |
| | | fgColor: { argb: "FFE6F3FF" }, |
| | | }, |
| | | alignment: { vertical: "middle", horizontal: "center" }, |
| | | border: { |
| | | top: { style: "thin", color: { argb: "FFD0D0D0" } }, |
| | | left: { style: "thin", color: { argb: "FFD0D0D0" } }, |
| | | bottom: { style: "thin", color: { argb: "FFD0D0D0" } }, |
| | | right: { style: "thin", color: { argb: "FFD0D0D0" } }, |
| | | }, |
| | | }; |
| | | |
| | | const headerStyle = { |
| | | font: { name: "微软é
é»", size: 11, bold: true }, |
| | | fill: { |
| | | type: "pattern", |
| | | pattern: "solid", |
| | | fgColor: { argb: "FFF5F7FA" }, |
| | | }, |
| | | alignment: { vertical: "middle", horizontal: "center" }, |
| | | border: { |
| | | top: { style: "thin", color: { argb: "FFD0D0D0" } }, |
| | | left: { style: "thin", color: { argb: "FFD0D0D0" } }, |
| | | bottom: { style: "thin", color: { argb: "FFD0D0D0" } }, |
| | | right: { style: "thin", color: { argb: "FFD0D0D0" } }, |
| | | }, |
| | | }; |
| | | |
| | | const cellStyle = { |
| | | font: { name: "å®ä½", size: 10 }, |
| | | alignment: { vertical: "middle", horizontal: "center" }, |
| | | border: { |
| | | top: { style: "thin", color: { argb: "FFD0D0D0" } }, |
| | | left: { style: "thin", color: { argb: "FFD0D0D0" } }, |
| | | bottom: { style: "thin", color: { argb: "FFD0D0D0" } }, |
| | | right: { style: "thin", color: { argb: "FFD0D0D0" } }, |
| | | }, |
| | | }; |
| | | |
| | | // æ·»å æ»æ é¢ |
| | | worksheet.mergeCells(1, 1, 1, 10); |
| | | const titleCell = worksheet.getCell(1, 1); |
| | | titleCell.value = `é访ç»è®¡è¡¨ï¼${sheetNameSuffix}ï¼`; |
| | | titleCell.style = titleStyle; |
| | | worksheet.getRow(1).height = 35; |
| | | |
| | | // æ·»å 表头 |
| | | const headers = [ |
| | | this.queryParams.statisticaltype == 1 ? "åºé¢ç
åº" : "ç§å®¤", |
| | | "åºé¢äººæ¬¡", |
| | | "æ éé访人次", |
| | | "åºé访人次", |
| | | "é访ç", |
| | | "åæ¶ç", |
| | | "å¤è¯éç¥é¢ç®æ»é", |
| | | "å¤è¯éç¥å¡«æ¥é", |
| | | "宿æ¯ç", |
| | | ]; |
| | | |
| | | const headerRow = worksheet.addRow(headers); |
| | | headerRow.eachCell((cell) => { |
| | | cell.style = headerStyle; |
| | | }); |
| | | headerRow.height = 25; |
| | | |
| | | // æ·»å æ°æ®è¡ |
| | | this.userList.forEach((item) => { |
| | | const dataRow = worksheet.addRow([ |
| | | this.queryParams.statisticaltype == 1 |
| | | ? item.leavehospitaldistrictname |
| | | : item.deptname, |
| | | item.dischargeCount || 0, |
| | | item.nonFollowUp || 0, |
| | | item.followUpNeeded || 0, |
| | | item.followUpRate || "0%", |
| | | item.rate ? this.formatPercent(item.rate) : "0%", |
| | | item.joyAllCount || 0, |
| | | item.joyCount || 0, |
| | | item.joyTotal ? this.formatPercent(item.joyTotal) : "0%", |
| | | ]); |
| | | |
| | | dataRow.eachCell((cell) => { |
| | | cell.style = cellStyle; |
| | | }); |
| | | dataRow.height = 22; |
| | | }); |
| | | |
| | | // 设置å宽 |
| | | worksheet.columns = [ |
| | | { width: 20 }, |
| | | { width: 12 }, |
| | | { width: 12 }, |
| | | { width: 12 }, |
| | | { width: 12 }, |
| | | { width: 12 }, |
| | | { width: 15 }, |
| | | { width: 15 }, |
| | | { width: 12 }, |
| | | ]; |
| | | |
| | | // çæå¹¶ä¸è½½æä»¶ |
| | | const buffer = await workbook.xlsx.writeBuffer(); |
| | | const blob = new Blob([buffer], { |
| | | type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", |
| | | }); |
| | | |
| | | saveAs(blob, excelName); |
| | | this.$message.success("å¯¼åºæå"); |
| | | } catch (error) { |
| | | console.error("导åºå¤±è´¥:", error); |
| | | this.$message.error(`导åºå¤±è´¥: ${error.message}`); |
| | | } finally { |
| | | this.loading = false; |
| | | } |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .followup-statistics { |
| | | .query-section { |
| | | background: #fff; |
| | | padding: 20px; |
| | | border-radius: 4px; |
| | | margin-bottom: 20px; |
| | | |
| | | .query-form { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | |
| | | ::v-deep .el-form-item { |
| | | margin-bottom: 20px; |
| | | |
| | | &:not(:last-child) { |
| | | margin-right: 20px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .table-section { |
| | | background: #fff; |
| | | padding: 20px; |
| | | border-radius: 4px; |
| | | margin-bottom: 20px; |
| | | |
| | | ::v-deep .el-table { |
| | | th { |
| | | background-color: #f8f9fa; |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .pagination-section { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | background: #fff; |
| | | padding: 20px; |
| | | border-radius: 4px; |
| | | } |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <!-- StatisticsMain.vue --> |
| | | <template> |
| | | <div class="statistics-main"> |
| | | <el-tabs v-model="activeTab" @tab-click="handleTabChange"> |
| | | <el-tab-pane label="é访ç»è®¡" name="followup"> |
| | | <followup-statistics |
| | | v-if="activeTab === 'followup'" |
| | | ref="followupRef" |
| | | /> |
| | | </el-tab-pane> |
| | | <el-tab-pane label="满æåº¦ç»è®¡" name="satisfaction"> |
| | | <satisfaction-statistics |
| | | v-if="activeTab === 'satisfaction'" |
| | | ref="satisfactionRef" |
| | | /> |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import FollowupStatistics from './components/FollowupStatistics.vue'; |
| | | import SatisfactionStatistics from './components/SatisfactionStatistics.vue'; |
| | | |
| | | export default { |
| | | name: 'StatisticsMain', |
| | | components: { |
| | | FollowupStatistics, |
| | | SatisfactionStatistics |
| | | }, |
| | | data() { |
| | | return { |
| | | activeTab: 'followup' |
| | | }; |
| | | }, |
| | | methods: { |
| | | handleTabChange(tab) { |
| | | console.log('忢å°:', tab.name); |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .statistics-main { |
| | | padding: 20px; |
| | | background: #fff; |
| | | min-height: calc(100vh - 84px); |
| | | |
| | | ::v-deep .el-tabs__header { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | ::v-deep .el-tabs__item { |
| | | font-size: 16px; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | ::v-deep .el-tabs__nav-wrap::after { |
| | | height: 1px; |
| | | } |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <!-- å»¶ç»æ¤çé¡µé¢ --> |
| | | <div class="ContinuityCarePage" id="app-container"> |
| | | <!-- 第ä¸é¨åï¼æ£è
åºç¡ä¿¡æ¯ --> |
| | | <div class="patient-info-section"> |
| | | <div class="headline"> |
| | | <div>æ£è
åºç¡ä¿¡æ¯</div> |
| | | </div> |
| | | <div class="patient-info-form"> |
| | | <el-form |
| | | ref="patientForm" |
| | | :model="patientForm" |
| | | :rules="patientRules" |
| | | label-width="120px" |
| | | > |
| | | <el-row :gutter="20"> |
| | | <el-col :span="8"> |
| | | <el-form-item label="æ£è
å§å" prop="name"> |
| | | <el-input |
| | | v-model="patientForm.name" |
| | | placeholder="请è¾å
¥æ£è
å§å" |
| | | maxlength="30" |
| | | clearable |
| | | ></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="æ§å«" prop="sex"> |
| | | <el-select |
| | | v-model="patientForm.sex" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | > |
| | | <el-option label="ç·" :value="1"></el-option> |
| | | <el-option label="女" :value="2"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="å¹´é¾" prop="age"> |
| | | <el-input |
| | | v-model="patientForm.age" |
| | | placeholder="请è¾å
¥å¹´é¾" |
| | | maxlength="3" |
| | | clearable |
| | | ></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="8"> |
| | | <el-form-item label="èç³»çµè¯" prop="telcode"> |
| | | <el-input |
| | | v-model="patientForm.telcode" |
| | | placeholder="请è¾å
¥èç³»çµè¯" |
| | | maxlength="20" |
| | | clearable |
| | | ></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="ä½é¢å·" prop="hospitalNumber"> |
| | | <el-input |
| | | v-model="patientForm.hospitalNumber" |
| | | placeholder="请è¾å
¥ä½é¢å·" |
| | | maxlength="50" |
| | | clearable |
| | | ></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="åºé¢æ¥æ" prop="dischargeDate"> |
| | | <el-date-picker |
| | | v-model="patientForm.dischargeDate" |
| | | type="date" |
| | | placeholder="éæ©åºé¢æ¥æ" |
| | | value-format="yyyy-MM-dd" |
| | | style="width: 100%" |
| | | > |
| | | </el-date-picker> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="è¯æåç§°" prop="diagnosis"> |
| | | <el-input |
| | | v-model="patientForm.diagnosis" |
| | | placeholder="请è¾å
¥è¯æåç§°" |
| | | maxlength="100" |
| | | clearable |
| | | ></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="责任æ¤å£«" prop="nurseName"> |
| | | <el-input |
| | | v-model="patientForm.nurseName" |
| | | placeholder="请è¾å
¥è´£ä»»æ¤å£«" |
| | | maxlength="50" |
| | | clearable |
| | | ></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="å±
ä½å°å" prop="address"> |
| | | <el-input |
| | | v-model="patientForm.address" |
| | | placeholder="请è¾å
¥è¯¦ç»å±
ä½å°å" |
| | | maxlength="200" |
| | | clearable |
| | | ></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="亲å±å§å" prop="relativeName"> |
| | | <el-input |
| | | v-model="patientForm.relativeName" |
| | | placeholder="请è¾å
¥äº²å±å§å" |
| | | maxlength="30" |
| | | clearable |
| | | ></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="亲å±çµè¯" prop="relativeTel"> |
| | | <el-input |
| | | v-model="patientForm.relativeTel" |
| | | placeholder="请è¾å
¥äº²å±çµè¯" |
| | | maxlength="20" |
| | | clearable |
| | | ></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <!-- å»¶ç»æ¤çæ±æ»ä¿¡æ¯ --> |
| | | <el-row :gutter="20" v-if="continuitySummary.continueCount > 0"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="å»¶ç»æ¤çæ±æ»"> |
| | | <div class="continuity-summary"> |
| | | <div class="summary-item"> |
| | | <span class="label">å»¶ç»æ¬¡æ°ï¼</span> |
| | | <span class="value" |
| | | >{{ continuitySummary.continueCount }} 次</span |
| | | > |
| | | </div> |
| | | <div class="summary-item"> |
| | | <span class="label">ææ°æå¡ï¼</span> |
| | | <span class="value">{{ |
| | | formatDisplayTime(continuitySummary.continueTimeNow) |
| | | }}</span> |
| | | </div> |
| | | <div class="summary-item"> |
| | | <span class="label">䏿¬¡æå¡ï¼</span> |
| | | <span class="value">{{ |
| | | formatDisplayTime(continuitySummary.continueTimeNext) |
| | | }}</span> |
| | | </div> |
| | | </div> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <!-- æä½æé® --> |
| | | <el-form-item> |
| | | <el-button |
| | | type="primary" |
| | | @click="savePatientInfo" |
| | | :loading="savingPatientInfo" |
| | | > |
| | | ä¿åæ£è
ä¿¡æ¯ |
| | | </el-button> |
| | | <el-button @click="resetPatientInfo">éç½®</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | </div> |
| | | <!-- 第äºé¨åï¼æå¡åºç¡ä¿¡æ¯ --> |
| | | <div class="basic-info-section"> |
| | | <div class="headline"> |
| | | <div>æå¡åºç¡ä¿¡æ¯</div> |
| | | </div> |
| | | <div class="basic-info-container"> |
| | | <!-- å·¦åé¨åï¼å½åæå¡é访å
容ï¼åªè¯»ï¼ --> |
| | | <div class="followup-content readonly-content"> |
| | | <div class="sub-headline"> |
| | | <i class="el-icon-document"></i> å½åæå¡é访å
容ï¼åªè¯»ï¼ |
| | | <el-button |
| | | type="text" |
| | | size="small" |
| | | @click="toggleQuestionSelection" |
| | | style="margin-left: 10px" |
| | | > |
| | | {{ showQuestionSelector ? "éèé®é¢éå" : "éåå»¶ç»é®é¢" }} |
| | | </el-button> |
| | | </div> |
| | | |
| | | <!-- é®é¢éå颿¿ --> |
| | | <div v-if="showQuestionSelector" class="question-selector-panel"> |
| | | <div class="selector-header"> |
| | | <span>è¯·éæ©å»¶ç»é®é¢ï¼å¯å¤éï¼ï¼</span> |
| | | <el-button |
| | | type="primary" |
| | | size="small" |
| | | @click="confirmQuestionSelection" |
| | | > |
| | | 确认éå |
| | | </el-button> |
| | | </div> |
| | | <div class="question-list"> |
| | | <el-checkbox-group v-model="selectedQuestionIds"> |
| | | <div |
| | | v-for="(question, index) in availableQuestions" |
| | | :key="question.id" |
| | | class="question-item" |
| | | > |
| | | <el-checkbox :label="question.id"> |
| | | <div class="question-content"> |
| | | <span class="question-index" |
| | | >{{ question.index + 1 }}.</span |
| | | > |
| | | <span class="question-text">{{ question.text }}</span> |
| | | </div> |
| | | </el-checkbox> |
| | | </div> |
| | | </el-checkbox-group> |
| | | </div> |
| | | </div> |
| | | <div class="content-container"> |
| | | <el-tabs v-model="activeName" type="border-card"> |
| | | <el-tab-pane name="wj"> |
| | | <span slot="label" |
| | | ><i class="el-icon-notebook-1"></i> é®å·éè®¿ç»æ</span |
| | | > |
| | | <div class="CONTENT"> |
| | | <div class="title">{{ taskname ? taskname : "é®å·" }}</div> |
| | | <div class="preview-left" v-if="!Voicetype"> |
| | | <div |
| | | class="topic-dev" |
| | | v-for="(item, index) in tableDatatop" |
| | | :key="item.id" |
| | | > |
| | | <!-- åé --> |
| | | <div |
| | | :class="getTopicClass(item)" |
| | | :key="index" |
| | | v-if="item.scriptType == 1 && !item.astrict" |
| | | > |
| | | <div class="dev-text"> |
| | | {{ index + 1 }}ã[åé]<span>{{ |
| | | item.scriptContent |
| | | }}</span> |
| | | </div> |
| | | <div class="dev-xx"> |
| | | <el-radio-group v-model="item.scriptResult" disabled> |
| | | <el-radio |
| | | v-for="( |
| | | items, indexs |
| | | ) in item.svyTaskTemplateTargetoptions" |
| | | :class="getOptionClass(items)" |
| | | :key="indexs" |
| | | :label="items.optioncontent" |
| | | >{{ items.optioncontent }}</el-radio |
| | | > |
| | | </el-radio-group> |
| | | </div> |
| | | <div |
| | | v-if="item.showAppendInput || item.answerps" |
| | | class="append-input-container" |
| | | > |
| | | <el-input |
| | | type="textarea" |
| | | :rows="2" |
| | | placeholder="请è¾å
¥å
·ä½ä¿¡æ¯" |
| | | v-model="item.answerps" |
| | | readonly |
| | | ></el-input> |
| | | </div> |
| | | <div v-show="item.prompt"> |
| | | <el-alert :title="item.prompt" type="warning"> |
| | | </el-alert> |
| | | </div> |
| | | </div> |
| | | <!-- å¤é --> |
| | | <div |
| | | :class=" |
| | | item.isabnormal |
| | | ? 'scriptTopic-isabnormal' |
| | | : 'scriptTopic-dev' |
| | | " |
| | | :key="index" |
| | | v-if="item.scriptType == 2 && !item.astrict" |
| | | > |
| | | <div class="dev-text"> |
| | | {{ index + 1 }}ã[å¤é]<span>{{ |
| | | item.scriptContent |
| | | }}</span> |
| | | </div> |
| | | <div class="dev-xx"> |
| | | <el-checkbox-group |
| | | v-model="item.scriptResult" |
| | | disabled |
| | | > |
| | | <el-checkbox |
| | | :class="items.isabnormal ? 'red-star' : ''" |
| | | v-for="( |
| | | items, indexs |
| | | ) in item.svyTaskTemplateTargetoptions" |
| | | :key="indexs" |
| | | :label="items.optioncontent" |
| | | > |
| | | {{ items.optioncontent }} |
| | | </el-checkbox> |
| | | </el-checkbox-group> |
| | | </div> |
| | | <div v-show="item.prompt && item.scriptResult[0]"> |
| | | <el-alert :title="item.prompt" type="warning"> |
| | | </el-alert> |
| | | </div> |
| | | </div> |
| | | <!-- 填空 --> |
| | | <div |
| | | class="scriptTopic-dev" |
| | | :key="index" |
| | | v-if="item.scriptType == 4 && !item.astrict" |
| | | > |
| | | <div class="dev-text"> |
| | | {{ index + 1 }}ã[é®ç]<span>{{ |
| | | item.scriptContent |
| | | }}</span> |
| | | <span v-if="item.valueType == 3">(åªè½è¾å
¥æ°å)</span> |
| | | </div> |
| | | <div class="dev-xx" v-if="item.valueType == 3"> |
| | | <el-input |
| | | type="text" |
| | | placeholder="请è¾å
¥çæ¡" |
| | | v-model="item.scriptResult" |
| | | readonly |
| | | > |
| | | </el-input> |
| | | </div> |
| | | <div class="dev-xx" v-else> |
| | | <el-input |
| | | type="textarea" |
| | | :rows="2" |
| | | placeholder="请è¾å
¥çæ¡" |
| | | v-model="item.scriptResult" |
| | | readonly |
| | | > |
| | | </el-input> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="preview-left" v-else> |
| | | <div |
| | | class="topic-dev" |
| | | v-for="(item, index) in tableDatatop" |
| | | :key="item.id" |
| | | > |
| | | <div v-if="item.targetvalue"> |
| | | <div class="dev-text"> |
| | | {{ index + 1 }}ã[åé]<span>{{ |
| | | item.questiontext |
| | | }}</span> |
| | | </div> |
| | | <div class="dev-xx"> |
| | | <el-radio-group v-model="item.matchedtext" disabled> |
| | | <el-radio |
| | | v-for="(items, index) in item.scriptResult" |
| | | :key="index" |
| | | :label="items" |
| | | :class="items.isabnormal ? 'red-star' : ''" |
| | | >{{ items }}</el-radio |
| | | > |
| | | </el-radio-group> |
| | | </div> |
| | | <div v-show="item.prompt"> |
| | | <el-alert :title="item.prompt" type="warning"> |
| | | </el-alert> |
| | | </div> |
| | | </div> |
| | | <div class="scriptTopic-dev" :key="index" v-else> |
| | | <div class="dev-text"> |
| | | {{ index + 1 }}ã[é®ç]<span>{{ |
| | | item.scriptContent |
| | | }}</span> |
| | | <span v-if="item.valueType == 3">(åªè½è¾å
¥æ°å)</span> |
| | | </div> |
| | | <div class="dev-xx" v-if="item.valueType == 3"> |
| | | <el-input |
| | | type="text" |
| | | placeholder="请è¾å
¥çæ¡" |
| | | v-model="item.scriptResult" |
| | | readonly |
| | | > |
| | | </el-input> |
| | | </div> |
| | | <div class="dev-xx" v-else> |
| | | <el-input |
| | | type="textarea" |
| | | :rows="2" |
| | | placeholder="请è¾å
¥çæ¡" |
| | | v-model="item.scriptResult" |
| | | readonly |
| | | > |
| | | </el-input> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-tab-pane> |
| | | <el-tab-pane name="yy"> |
| | | <span slot="label" |
| | | ><i class="el-icon-headset"></i> è¯é³é访详æ
</span |
| | | > |
| | | <div class="borderdiv"> |
| | | <div class="title">{{ taskname ? taskname : "é®å·" }}</div> |
| | | <div class="voice-audio"> |
| | | 宿´è¯é³ï¼ |
| | | <mini-audio |
| | | :audio-source=" |
| | | voice ? voice : '@assets/order/example.mp3' |
| | | " |
| | | ></mini-audio> |
| | | </div> |
| | | <div class="preview-left"> |
| | | <div v-for="item in voiceDatatop"> |
| | | <div class="leftside"> |
| | | <i class="el-icon-phone-outline"></i |
| | | ><span>{{ item.questiontext }}</span> |
| | | </div> |
| | | <div class="offside"> |
| | | <i class="el-icon-user"></i> |
| | | <div class="offside-value"> |
| | | <el-input |
| | | type="textarea" |
| | | :autosize="{ minRows: 1 }" |
| | | v-model="item.asrtext" |
| | | readonly |
| | | ></el-input> |
| | | <div> |
| | | <mini-audio |
| | | :audio-source=" |
| | | item.questionvoice |
| | | ? item.questionvoice |
| | | : '@assets/order/example.mp3' |
| | | " |
| | | ></mini-audio> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- å³åé¨åï¼åæ¬¡å»¶ç»æ¤çæå¡ --> |
| | | <!-- å³åé¨åï¼åæ¬¡å»¶ç»æ¤çæå¡ --> |
| | | <div class="continuity-history"> |
| | | <div class="sub-headline"> |
| | | <i class="el-icon-time"></i> 忬¡å»¶ç»æ¤çæå¡ |
| | | <el-button |
| | | type="primary" |
| | | size="small" |
| | | icon="el-icon-plus" |
| | | @click="addContinuityTab" |
| | | style="margin-left: 10px" |
| | | >æ°å¢å»¶ç»æ¤ç</el-button |
| | | > |
| | | </div> |
| | | <div class="history-content"> |
| | | <el-tabs |
| | | v-model="activeContinuityTab" |
| | | type="card" |
| | | closable |
| | | @tab-remove="removeContinuityTab" |
| | | @tab-click="handleTabClick" |
| | | > |
| | | <el-tab-pane |
| | | v-for="(item, index) in continuityTabs" |
| | | :key="item.name" |
| | | :label="item.title" |
| | | :name="item.name" |
| | | > |
| | | <div class="continuity-form"> |
| | | <el-form |
| | | :ref="'continuityForm' + index" |
| | | :model="item.form" |
| | | :rules="continuityRules" |
| | | label-width="120px" |
| | | > |
| | | <!-- å»¶ç»é®é¢è¡¨å --> |
| | | <el-form-item label="å»¶ç»é®é¢" prop="continuityProblems"> |
| | | <div class="continuity-problems-form"> |
| | | <div class="problems-header"> |
| | | <span>å·²éåçå»¶ç»é®é¢ï¼</span> |
| | | <el-button |
| | | type="text" |
| | | size="small" |
| | | icon="el-icon-plus" |
| | | @click="addContinuityProblem(index)" |
| | | > |
| | | æ°å¢é®é¢ |
| | | </el-button> |
| | | </div> |
| | | |
| | | <!-- å·²éåçé®é¢å表 --> |
| | | <div |
| | | v-if=" |
| | | item.form.continuityProblems && |
| | | item.form.continuityProblems.length > 0 |
| | | " |
| | | class="problems-list-container" |
| | | > |
| | | <div |
| | | v-for="(problem, problemIndex) in item.form |
| | | .continuityProblems" |
| | | :key="problemIndex" |
| | | class="problem-item" |
| | | > |
| | | <div class="problem-content"> |
| | | <div class="problem-meta"> |
| | | <span class="problem-index" |
| | | >é®é¢ {{ problemIndex + 1 }}</span |
| | | > |
| | | <el-select |
| | | v-model="problem.questionId" |
| | | placeholder="éæ©é®é¢" |
| | | size="small" |
| | | style="width: 300px; margin: 0 10px" |
| | | @change=" |
| | | handleProblemChange( |
| | | index, |
| | | problemIndex, |
| | | $event |
| | | ) |
| | | " |
| | | > |
| | | <el-option |
| | | v-for="q in availableQuestions" |
| | | :key="q.id" |
| | | :label="q.text" |
| | | :value="q.id" |
| | | > |
| | | <span |
| | | >{{ q.index + 1 }}. |
| | | {{ truncateText(q.text, 40) }}</span |
| | | > |
| | | </el-option> |
| | | </el-select> |
| | | <!-- ä¿®å¤ï¼ä¼ éæ£ç¡®çç´¢å¼ --> |
| | | <el-button |
| | | type="danger" |
| | | icon="el-icon-delete" |
| | | size="mini" |
| | | circle |
| | | @click=" |
| | | removeContinuityProblem(index, problemIndex) |
| | | " |
| | | > |
| | | </el-button> |
| | | </div> |
| | | |
| | | <!-- é®å·å¼é®é¢å±ç¤ºåºå --> |
| | | <div |
| | | v-if="problem.questionId" |
| | | class="question-display-area" |
| | | > |
| | | <!-- æ ¹æ®é®é¢ç±»åå¨ææ¸²æ --> |
| | | <div |
| | | v-if=" |
| | | getQuestionOriginalData(problem.questionId) |
| | | " |
| | | class="question-render" |
| | | > |
| | | <!-- åéç±»å --> |
| | | <div |
| | | v-if=" |
| | | getQuestionOriginalData( |
| | | problem.questionId |
| | | ).scriptType == 1 |
| | | " |
| | | class="question-item-render" |
| | | > |
| | | <div class="question-text"> |
| | | <strong>[åé]</strong> |
| | | <span>{{ |
| | | getQuestionOriginalData( |
| | | problem.questionId |
| | | ).scriptContent |
| | | }}</span> |
| | | </div> |
| | | <div class="question-options"> |
| | | <el-radio-group |
| | | v-model="problem.selectedOption" |
| | | > |
| | | <el-radio |
| | | v-for="option in getQuestionOriginalData( |
| | | problem.questionId |
| | | ).svyTaskTemplateTargetoptions" |
| | | :key="option.optioncontent" |
| | | :label="option.optioncontent" |
| | | :class="getOptionClass(option)" |
| | | > |
| | | {{ option.optioncontent }} |
| | | </el-radio> |
| | | </el-radio-group> |
| | | </div> |
| | | <!-- éå è¾å
¥æ¡ --> |
| | | <div |
| | | v-if="problem.showAppendInput" |
| | | class="append-input" |
| | | style="margin-top: 10px" |
| | | > |
| | | <el-input |
| | | type="textarea" |
| | | :rows="2" |
| | | placeholder="请è¾å
¥å
·ä½ä¿¡æ¯" |
| | | v-model="problem.appendInput" |
| | | ></el-input> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- å¤éç±»å --> |
| | | <div |
| | | v-else-if=" |
| | | getQuestionOriginalData( |
| | | problem.questionId |
| | | ).scriptType == 2 |
| | | " |
| | | class="question-item-render" |
| | | > |
| | | <div class="question-text"> |
| | | <strong>[å¤é]</strong> |
| | | <span>{{ |
| | | getQuestionOriginalData( |
| | | problem.questionId |
| | | ).scriptContent |
| | | }}</span> |
| | | </div> |
| | | <div class="question-options"> |
| | | <el-checkbox-group |
| | | v-model="problem.selectedOptions" |
| | | > |
| | | <el-checkbox |
| | | v-for="option in getQuestionOriginalData( |
| | | problem.questionId |
| | | ).svyTaskTemplateTargetoptions" |
| | | :key="option.optioncontent" |
| | | :label="option.optioncontent" |
| | | :class=" |
| | | option.isabnormal ? 'red-star' : '' |
| | | " |
| | | > |
| | | {{ option.optioncontent }} |
| | | </el-checkbox> |
| | | </el-checkbox-group> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 填空/é®çç±»å --> |
| | | <div |
| | | v-else-if=" |
| | | getQuestionOriginalData( |
| | | problem.questionId |
| | | ).scriptType == 4 |
| | | " |
| | | class="question-item-render" |
| | | > |
| | | <div class="question-text"> |
| | | <strong>[é®ç]</strong> |
| | | <span>{{ |
| | | getQuestionOriginalData( |
| | | problem.questionId |
| | | ).scriptContent |
| | | }}</span> |
| | | <span |
| | | v-if=" |
| | | getQuestionOriginalData( |
| | | problem.questionId |
| | | ).valueType == 3 |
| | | " |
| | | >(åªè½è¾å
¥æ°å)</span |
| | | > |
| | | </div> |
| | | <div class="question-options"> |
| | | <el-input |
| | | v-if=" |
| | | getQuestionOriginalData( |
| | | problem.questionId |
| | | ).valueType == 3 |
| | | " |
| | | type="text" |
| | | placeholder="请è¾å
¥çæ¡" |
| | | v-model="problem.answer" |
| | | style="width: 200px" |
| | | ></el-input> |
| | | <el-input |
| | | v-else |
| | | type="textarea" |
| | | :rows="2" |
| | | placeholder="请è¾å
¥çæ¡" |
| | | v-model="problem.answer" |
| | | style="width: 100%" |
| | | ></el-input> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div v-else class="no-question-data"> |
| | | é®é¢æ°æ®å è½½ä¸... |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- åæçé®é¢æè¿°çåæ®µ --> |
| | | <div class="problem-detail"> |
| | | <div class="detail-row"> |
| | | <span class="detail-label">å½åç¶æï¼</span> |
| | | <el-select |
| | | v-model="problem.status" |
| | | placeholder="éæ©ç¶æ" |
| | | size="small" |
| | | style="width: 120px; margin-right: 20px" |
| | | > |
| | | <el-option |
| | | label="æªå¤ç" |
| | | value="pending" |
| | | ></el-option> |
| | | <el-option |
| | | label="å¤çä¸" |
| | | value="processing" |
| | | ></el-option> |
| | | <el-option |
| | | label="已解å³" |
| | | value="resolved" |
| | | ></el-option> |
| | | <el-option |
| | | label="æç»å
³æ³¨" |
| | | value="watching" |
| | | ></el-option> |
| | | </el-select> |
| | | |
| | | <span |
| | | class="detail-label" |
| | | v-if="problem.status === 'resolved'" |
| | | style="margin-left: 20px" |
| | | > |
| | | è§£å³æ¥æï¼ |
| | | </span> |
| | | <el-date-picker |
| | | v-if="problem.status === 'resolved'" |
| | | v-model="problem.resolvedDate" |
| | | type="date" |
| | | placeholder="éæ©è§£å³æ¥æ" |
| | | value-format="yyyy-MM-dd" |
| | | size="small" |
| | | style="width: 150px; margin-left: 10px" |
| | | ></el-date-picker> |
| | | </div> |
| | | |
| | | <!-- <div class="detail-row"> |
| | | <span class="detail-label">é®é¢æè¿°ï¼</span> |
| | | <el-input |
| | | type="textarea" |
| | | :rows="2" |
| | | v-model="problem.description" |
| | | placeholder="è¯·è¯¦ç»æè¿°è¯¥å»¶ç»é®é¢ï¼å¯è®°å½è¯ä¼°ç»æãå¤ç建议çï¼" |
| | | size="small" |
| | | style="flex: 1" |
| | | ></el-input> |
| | | </div> --> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-form-item> |
| | | |
| | | <!-- å»¶ç»æ§æ¤çè®°å½ --> |
| | | <el-form-item label="æ¤çè®°å½" prop="careRecord"> |
| | | <el-input |
| | | type="textarea" |
| | | :rows="4" |
| | | v-model="item.form.careRecord" |
| | | placeholder="请è¾å
¥å»¶ç»æ§æ¤çè®°å½" |
| | | clearable |
| | | ></el-input> |
| | | </el-form-item> |
| | | |
| | | <!-- 责任æ¤å£«ãå访形å¼ãæå¡æ¶é´ --> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="责任æ¤å£«" prop="dutyNurse"> |
| | | <el-input |
| | | v-model="item.form.dutyNurse" |
| | | placeholder="请è¾å
¥è´£ä»»æ¤å£«" |
| | | clearable |
| | | ></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å访形å¼" prop="visitType"> |
| | | <el-select |
| | | v-model="item.form.visitType" |
| | | placeholder="è¯·éæ©å访形å¼" |
| | | style="width: 100%" |
| | | clearable |
| | | > |
| | | <el-option |
| | | label="çµè¯å访" |
| | | value="phone" |
| | | ></el-option> |
| | | <el-option |
| | | label="ä¸é¨å访" |
| | | value="home" |
| | | ></el-option> |
| | | <el-option |
| | | label="é¨è¯å访" |
| | | value="clinic" |
| | | ></el-option> |
| | | <el-option |
| | | label="微信å访" |
| | | value="wechat" |
| | | ></el-option> |
| | | <el-option label="å
¶ä»" value="other"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item |
| | | label="䏿¬¡æå¡æ¶é´" |
| | | prop="nextServiceTime" |
| | | > |
| | | <el-date-picker |
| | | v-model="item.form.nextServiceTime" |
| | | type="datetime" |
| | | placeholder="鿩䏿¬¡å»¶ç»æå¡æ¶é´" |
| | | value-format="yyyy-MM-dd HH:mm:ss" |
| | | style="width: 100%" |
| | | > |
| | | </el-date-picker> |
| | | <div |
| | | class="time-tip" |
| | | v-if="item.form.nextServiceTime" |
| | | > |
| | | è·ä¸æ¬¡æå¡è¿æ |
| | | {{ calculateDaysLeft(item.form.nextServiceTime) }} |
| | | 天 |
| | | </div> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æå¡æ¶é´" prop="serviceTime"> |
| | | <el-date-picker |
| | | v-model="item.form.serviceTime" |
| | | type="datetime" |
| | | placeholder="éæ©æå¡æ¶é´" |
| | | value-format="yyyy-MM-dd HH:mm:ss" |
| | | style="width: 100%" |
| | | > |
| | | </el-date-picker> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <!-- 䏿¬¡å»¶ç»æå¡æ¶é´ --> |
| | | |
| | | <!-- æä½æé® --> |
| | | <el-form-item> |
| | | <el-button |
| | | type="primary" |
| | | @click="saveContinuityTab(index)" |
| | | :loading="item.saving" |
| | | > |
| | | ä¿å |
| | | </el-button> |
| | | <el-button @click="resetContinuityTab(index)"> |
| | | éç½® |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | <script> |
| | | import { |
| | | getsearchrResults, |
| | | getPersonVoices, |
| | | getTaskservelist, |
| | | Editsingletaskson, |
| | | } from "@/api/AiCentre/index"; |
| | | import { |
| | | messagelistpatient, |
| | | alterpatient, |
| | | listcontactinformation, |
| | | } from "@/api/patient/homepage"; |
| | | |
| | | export default { |
| | | dicts: ["sys_yujing"], |
| | | data() { |
| | | return { |
| | | // è·¯ç±åæ° |
| | | taskid: "", |
| | | id: "", |
| | | sendname: "", |
| | | patid: "", |
| | | Voicetype: 0, |
| | | serviceType: "", |
| | | |
| | | // é访å
容ç¸å
³ |
| | | activeName: "wj", |
| | | taskname: "", |
| | | voice: "", |
| | | tableDatatop: [], |
| | | voiceDatatop: [], |
| | | form: {}, |
| | | userform: {}, |
| | | // æ°å¢ï¼é®é¢éæ©ç¸å
³ |
| | | showQuestionSelector: false, |
| | | selectedQuestionIds: [], |
| | | // æ£è
åºç¡ä¿¡æ¯è¡¨å |
| | | patientForm: { |
| | | name: "", |
| | | sex: "", |
| | | age: "", |
| | | telcode: "", |
| | | hospitalNumber: "", |
| | | dischargeDate: "", |
| | | diagnosis: "", |
| | | nurseName: "", |
| | | address: "", |
| | | relativeName: "", |
| | | relativeTel: "", |
| | | }, |
| | | patientRules: { |
| | | name: [{ required: true, message: "请è¾å
¥æ£è
å§å", trigger: "blur" }], |
| | | age: [ |
| | | { required: true, message: "请è¾å
¥å¹´é¾", trigger: "blur" }, |
| | | { pattern: /^\d+$/, message: "å¹´é¾å¿
须为æ°å", trigger: "blur" }, |
| | | ], |
| | | telcode: [ |
| | | { required: true, message: "请è¾å
¥èç³»çµè¯", trigger: "blur" }, |
| | | { |
| | | pattern: /^1[3-9]\d{9}$/, |
| | | message: "请è¾å
¥æ£ç¡®çææºå·ç ", |
| | | trigger: "blur", |
| | | }, |
| | | ], |
| | | }, |
| | | savingPatientInfo: false, |
| | | |
| | | // å»¶ç»æ¤çç¸å
³ |
| | | activeContinuityTab: "continuity-0", |
| | | continuityTabs: [], |
| | | continuityTabIndex: 0, |
| | | continuityRules: { |
| | | // ç§»é¤continuityProblemsçéªè¯è§å |
| | | careRecord: [ |
| | | { required: true, message: "请è¾å
¥æ¤çè®°å½", trigger: "blur" }, |
| | | ], |
| | | dutyNurse: [ |
| | | { required: true, message: "请è¾å
¥è´£ä»»æ¤å£«", trigger: "blur" }, |
| | | ], |
| | | visitType: [ |
| | | { required: true, message: "è¯·éæ©å访形å¼", trigger: "change" }, |
| | | ], |
| | | serviceTime: [ |
| | | { required: true, message: "è¯·éæ©æå¡æ¶é´", trigger: "change" }, |
| | | ], |
| | | nextServiceTime: [ |
| | | { required: true, message: "è¯·éæ©ä¸æ¬¡æå¡æ¶é´", trigger: "change" }, |
| | | ], |
| | | }, |
| | | |
| | | // å¯éçå»¶ç»é®é¢ï¼ä»å·¦ä¾§é®å·ä¸æåï¼ |
| | | availableQuestions: [], |
| | | |
| | | // å»¶ç»æ¤çæ±æ»ä¿¡æ¯ |
| | | continuitySummary: { |
| | | continueCount: 0, |
| | | continueTimeNow: "", |
| | | continueTimeNext: "", |
| | | continueContent: "", |
| | | }, |
| | | |
| | | // å
¶ä» |
| | | logsheetlist: [], |
| | | }; |
| | | }, |
| | | created() { |
| | | this.taskid = this.$route.query.taskid; |
| | | this.id = this.$route.query.id; |
| | | this.sendname = this.$route.query.sendname; |
| | | this.patid = this.$route.query.patid; |
| | | this.Voicetype = this.$route.query.Voicetype || 0; |
| | | this.serviceType = this.$route.query.serviceType; |
| | | |
| | | this.getTaskservelist(this.id); |
| | | }, |
| | | methods: { |
| | | // è·å䏻颿 ·å¼ç±» |
| | | getTopicClass(item) { |
| | | console.log(item.isabnormal, "getTopicClass"); |
| | | |
| | | if (item.isabnormal == 1) { |
| | | return "scriptTopic-isabnormal"; |
| | | } else if (item.isabnormal == 2) { |
| | | return "scriptTopic-warning"; |
| | | } else { |
| | | return "scriptTopic-dev"; |
| | | } |
| | | }, |
| | | |
| | | // è·åéé¡¹æ ·å¼ç±» |
| | | getOptionClass(items) { |
| | | if (items.isabnormal == 1) { |
| | | return "red-star"; |
| | | } else if (items.isabnormal == 2) { |
| | | return "yellow-star"; |
| | | } |
| | | return ""; |
| | | }, |
| | | |
| | | // è·åé®å·æ°æ® |
| | | getsearchrResults(id) { |
| | | getsearchrResults({ |
| | | taskid: this.taskid, |
| | | patid: this.patid, |
| | | subId: id ? id : this.id, |
| | | isFinish: false, |
| | | }).then((res) => { |
| | | if (res.code === 200) { |
| | | this.tableDatatop = res.data.scriptResult; |
| | | |
| | | this.tableDatatop.forEach((item) => { |
| | | if (item.scriptType == 2) item.scriptResult = []; |
| | | if (item.scriptResultId && item.scriptType != 2) { |
| | | item.isoption = 3; |
| | | item.scriptResult = item.scriptResult; |
| | | } else if (item.scriptResultId && item.scriptType == 2) { |
| | | item.scriptResult = item.scriptResult.split("&"); |
| | | item.isoption = 3; |
| | | } |
| | | }); |
| | | this.taskname = res.data.taskName; |
| | | this.overdata(); |
| | | // æåå¯éçå»¶ç»é®é¢ |
| | | this.extractAvailableQuestions(); |
| | | } |
| | | }); |
| | | }, |
| | | overdata() { |
| | | this.tableDatatop.forEach((item, index) => { |
| | | var obj = item.svyTaskTemplateTargetoptions.find( |
| | | (items) => items.optioncontent == item.scriptResult |
| | | ); |
| | | if (obj) { |
| | | console.log(obj, "obj"); |
| | | if (obj.isabnormal) { |
| | | this.tableDatatop[index].isabnormal = obj.isabnormal; |
| | | } |
| | | this.$forceUpdate(); |
| | | } |
| | | }); |
| | | }, |
| | | // æåå¯éçå»¶ç»é®é¢ |
| | | extractAvailableQuestions() { |
| | | this.availableQuestions = this.tableDatatop |
| | | .filter( |
| | | (item) => item.scriptContent && item.scriptContent.trim() !== "" |
| | | ) |
| | | .map((item, index) => ({ |
| | | id: `question-${index}`, |
| | | index: index, |
| | | text: item.scriptContent, |
| | | originalIndex: index, |
| | | })); |
| | | }, // 忢é®é¢éæ©é¢æ¿æ¾ç¤º |
| | | toggleQuestionSelection() { |
| | | this.showQuestionSelector = !this.showQuestionSelector; |
| | | if (this.showQuestionSelector) { |
| | | // éç½®éæ© |
| | | this.selectedQuestionIds = []; |
| | | } |
| | | }, |
| | | // æ·»å å»¶ç»é®é¢ |
| | | addContinuityProblem(tabIndex) { |
| | | this.continuityTabs[tabIndex].form.continuityProblems.push({ |
| | | questionId: "", |
| | | status: "pending", |
| | | description: "", |
| | | resolvedDate: "", |
| | | createTime: new Date().toISOString(), |
| | | // æ°å¢å段ï¼ç¨äºé®å·å¼äº¤äº |
| | | selectedOption: "", // åéçæ¡ |
| | | selectedOptions: [], // å¤éçæ¡ |
| | | answer: "", // å¡«ç©ºçæ¡ |
| | | showAppendInput: false, // æ¯å¦æ¾ç¤ºéå è¾å
¥æ¡ |
| | | appendInput: "", // éå è¾å
¥å
容 |
| | | }); |
| | | }, |
| | | // æ ¹æ®é®é¢IDè·ååå§é®é¢æ°æ® |
| | | getQuestionOriginalData(questionId) { |
| | | if (!questionId) return null; |
| | | const originalIndex = this.availableQuestions.find( |
| | | (q) => q.id === questionId |
| | | )?.originalIndex; |
| | | if (originalIndex !== undefined && this.tableDatatop[originalIndex]) { |
| | | return this.tableDatatop[originalIndex]; |
| | | } |
| | | return null; |
| | | }, |
| | | // ç§»é¤å»¶ç»é®é¢ |
| | | removeContinuityProblem(tabIndex, problemIndex) { |
| | | this.continuityTabs[tabIndex].form.continuityProblems.splice( |
| | | problemIndex, |
| | | 1 |
| | | ); |
| | | }, |
| | | |
| | | // å¤çé®é¢éæ©åæ´ |
| | | handleProblemChange(tabIndex, problemIndex, questionId) { |
| | | const problem = |
| | | this.continuityTabs[tabIndex].form.continuityProblems[problemIndex]; |
| | | |
| | | if (!questionId) { |
| | | problem.description = ""; |
| | | // æ¸
ç©ºçæ¡åæ®µ |
| | | problem.selectedOption = ""; |
| | | problem.selectedOptions = []; |
| | | problem.answer = ""; |
| | | problem.showAppendInput = false; |
| | | problem.appendInput = ""; |
| | | return; |
| | | } |
| | | |
| | | // èªå¨å¡«å
é®é¢æè¿° |
| | | const question = this.availableQuestions.find((q) => q.id === questionId); |
| | | if (question) { |
| | | problem.description = `é®é¢ï¼${question.text}`; |
| | | } |
| | | |
| | | // æ ¹æ®é®é¢ç±»ååå§åçæ¡åæ®µ |
| | | const originalData = this.getQuestionOriginalData(questionId); |
| | | if (originalData) { |
| | | // åå§ååéçæ¡ |
| | | if (originalData.scriptType === 1) { |
| | | problem.selectedOption = originalData.scriptResult || ""; |
| | | // æ£æ¥æ¯å¦éè¦æ¾ç¤ºéå è¾å
¥æ¡ |
| | | problem.showAppendInput = originalData.showAppendInput || false; |
| | | problem.appendInput = originalData.answerps || ""; |
| | | } |
| | | // åå§åå¤éçæ¡ |
| | | else if (originalData.scriptType === 2) { |
| | | problem.selectedOptions = Array.isArray(originalData.scriptResult) |
| | | ? [...originalData.scriptResult] |
| | | : originalData.scriptResult |
| | | ? originalData.scriptResult.split("&") |
| | | : []; |
| | | } |
| | | // åå§åå¡«ç©ºçæ¡ |
| | | else if (originalData.scriptType === 4) { |
| | | problem.answer = originalData.scriptResult || ""; |
| | | } |
| | | } |
| | | }, |
| | | |
| | | // æ ¹æ®é®é¢IDè·åé®é¢ææ¬ |
| | | getQuestionText(questionId) { |
| | | if (!questionId) return "æªéæ©é®é¢"; |
| | | const question = this.availableQuestions.find((q) => q.id === questionId); |
| | | return question |
| | | ? `${question.index + 1}. ${question.text}` |
| | | : "é®é¢å·²å é¤"; |
| | | }, |
| | | |
| | | // æªæææ¬ |
| | | truncateText(text, length) { |
| | | if (!text) return ""; |
| | | return text.length > length ? text.substring(0, length) + "..." : text; |
| | | }, |
| | | // 确认é®é¢éæ© |
| | | confirmQuestionSelection() { |
| | | if (this.selectedQuestionIds.length === 0) { |
| | | this.$modal.msgWarning("请è³å°éæ©ä¸ä¸ªå»¶ç»é®é¢"); |
| | | return; |
| | | } |
| | | |
| | | // è·åå½åæ¿æ´»çæ ç¾é¡µç´¢å¼ |
| | | const activeTabIndex = this.continuityTabs.findIndex( |
| | | (tab) => tab.name === this.activeContinuityTab |
| | | ); |
| | | |
| | | if (activeTabIndex === -1) { |
| | | this.$modal.msgError("æªæ¾å°æ¿æ´»çå»¶ç»æ¤çæ ç¾é¡µ"); |
| | | return; |
| | | } |
| | | |
| | | // æ·»å éä¸çé®é¢å°å½åæ ç¾é¡µ |
| | | this.selectedQuestionIds.forEach((questionId) => { |
| | | // æ£æ¥æ¯å¦å·²åå¨ç¸åé®é¢ |
| | | const exists = this.continuityTabs[ |
| | | activeTabIndex |
| | | ].form.continuityProblems.some( |
| | | (problem) => problem.questionId === questionId |
| | | ); |
| | | |
| | | if (!exists) { |
| | | this.continuityTabs[activeTabIndex].form.continuityProblems.push({ |
| | | questionId: questionId, |
| | | status: "pending", |
| | | description: "", |
| | | resolvedDate: "", |
| | | createTime: new Date().toISOString(), |
| | | }); |
| | | } |
| | | }); |
| | | |
| | | // å
³é鿩颿¿ |
| | | this.showQuestionSelector = false; |
| | | this.selectedQuestionIds = []; |
| | | |
| | | this.$modal.msgSuccess( |
| | | `已添å ${this.selectedQuestionIds.length} 个延ç»é®é¢` |
| | | ); |
| | | }, |
| | | |
| | | // ç§»é¤å»¶ç»é®é¢ |
| | | removeContinuityProblem(tabIndex, problemIndex) { |
| | | this.continuityTabs[tabIndex].form.continuityProblems.splice( |
| | | problemIndex, |
| | | 1 |
| | | ); |
| | | }, |
| | | |
| | | // è·åè¯é³æ°æ® |
| | | getPersonVoices(id) { |
| | | let obj = { |
| | | taskid: this.taskid, |
| | | patid: this.patid, |
| | | subId: id ? id : this.id, |
| | | }; |
| | | |
| | | getPersonVoices(obj).then((res) => { |
| | | if (res.code == 200) { |
| | | this.voiceDatatop = res.data.serviceSubtaskDetails; |
| | | this.voice = res.data.voice; |
| | | this.activeName = "yy"; |
| | | this.taskname = res.data.taskName; |
| | | this.tableDatatop = res.data.filteredDetails; |
| | | this.tableDatatop.forEach((item) => { |
| | | if (item.targetvalue) { |
| | | item.scriptResult = item.targetvalue.split("&"); |
| | | } else { |
| | | item.scriptResult = []; |
| | | } |
| | | }); |
| | | |
| | | // æåå¯éçå»¶ç»é®é¢ |
| | | this.extractAvailableQuestions(); |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // è·ååºç¡ä¿¡æ¯ |
| | | getuserinfo() { |
| | | const queryParams = { |
| | | pid: Number(this.patid), |
| | | allhosp: "0", |
| | | }; |
| | | |
| | | messagelistpatient(queryParams).then((response) => { |
| | | if (response.rows[0]) { |
| | | this.userform = response.rows[0]; |
| | | this.initPatientForm(); |
| | | } |
| | | }); |
| | | |
| | | listcontactinformation({ patid: this.patid }).then((response) => { |
| | | this.tableData = response.rows; |
| | | if (this.tableData.length) { |
| | | this.patientForm.relativeName = this.tableData[0].relation || ""; |
| | | this.patientForm.relativeTel = this.tableData[0].contactway || ""; |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // åå§åæ£è
表å |
| | | initPatientForm() { |
| | | if (this.userform) { |
| | | this.patientForm.name = this.userform.name || ""; |
| | | this.patientForm.sex = this.userform.sex || ""; |
| | | this.patientForm.age = this.userform.age || ""; |
| | | this.patientForm.telcode = this.userform.telcode || ""; |
| | | this.patientForm.address = this.userform.placeOfResidence || ""; |
| | | this.patientForm.hospitalNumber = this.userform.medicalRecordNo || ""; |
| | | } |
| | | |
| | | if (this.form) { |
| | | this.patientForm.dischargeDate = |
| | | this.formatTime(this.form.endtime) || ""; |
| | | this.patientForm.diagnosis = this.form.leavediagname || ""; |
| | | this.patientForm.nurseName = this.form.nurseName || ""; |
| | | } |
| | | }, |
| | | |
| | | // è·åæ£è
è®°å½ |
| | | getTaskservelist(id) { |
| | | getTaskservelist({ |
| | | patid: this.patid, |
| | | subId: id, |
| | | pageSize: 100, |
| | | }).then((res) => { |
| | | if (res.code == 200) { |
| | | this.form = res.rows[0].serviceSubtaskList.find( |
| | | (item) => item.id == this.id |
| | | ); |
| | | this.logsheetlist = res.rows[0].serviceSubtaskList; |
| | | |
| | | // åå§åæ£è
ä¿¡æ¯ |
| | | this.initPatientForm(); |
| | | |
| | | // å è½½åå²å»¶ç»æ¤çæ°æ® |
| | | this.loadContinuityHistory(); |
| | | this.getuserinfo(); |
| | | } |
| | | |
| | | if (this.Voicetype) { |
| | | this.getPersonVoices(); |
| | | } else { |
| | | this.getsearchrResults(); |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // å è½½åå²å»¶ç»æ¤çæ°æ® |
| | | loadContinuityHistory() { |
| | | if (this.form && this.form.continueContent) { |
| | | try { |
| | | const historyData = JSON.parse(this.form.continueContent); |
| | | this.continuityTabs = historyData.map((item, index) => ({ |
| | | name: `continuity-${index}`, |
| | | title: `å»¶ç»æ¤ç${index + 1}`, |
| | | form: { |
| | | continuityProblems: item.continuityProblems || [], |
| | | careRecord: item.careRecord || "", |
| | | dutyNurse: item.dutyNurse || "", |
| | | visitType: item.visitType || "", |
| | | serviceTime: item.serviceTime || "", |
| | | nextServiceTime: item.nextServiceTime || "", |
| | | }, |
| | | saving: false, |
| | | })); |
| | | |
| | | if (this.continuityTabs.length > 0) { |
| | | this.activeContinuityTab = this.continuityTabs[0].name; |
| | | } |
| | | |
| | | // æ´æ°æ±æ»ä¿¡æ¯ |
| | | this.updateContinuitySummary(); |
| | | } catch (error) { |
| | | console.error("è§£æå»¶ç»æ¤çå岿°æ®å¤±è´¥:", error); |
| | | } |
| | | } |
| | | }, |
| | | |
| | | // æ´æ°å»¶ç»æ¤çæ±æ»ä¿¡æ¯ |
| | | updateContinuitySummary() { |
| | | if (this.form) { |
| | | this.continuitySummary.continueCount = this.form.continueCount || 0; |
| | | this.continuitySummary.continueTimeNow = |
| | | this.form.continueTimeNow || ""; |
| | | this.continuitySummary.continueTimeNext = |
| | | this.form.continueTimeNext || ""; |
| | | this.continuitySummary.continueContent = |
| | | this.form.continueContent || ""; |
| | | } |
| | | }, |
| | | |
| | | // æ·»å å»¶ç»æ¤çæ ç¾é¡µ |
| | | addContinuityTab() { |
| | | console.log(this.continuityTabs.length); |
| | | if (this.continuityTabs.length) { |
| | | this.continuityTabIndex = this.continuityTabs.length; |
| | | } |
| | | const newIndex = this.continuityTabIndex + 1; |
| | | const newTab = { |
| | | name: `continuity-${newIndex}`, |
| | | title: `å»¶ç»æ¤ç${newIndex}`, |
| | | form: { |
| | | continuityProblems: [], |
| | | careRecord: "", |
| | | dutyNurse: "", |
| | | visitType: "", |
| | | serviceTime: "", |
| | | nextServiceTime: "", |
| | | }, |
| | | saving: false, |
| | | }; |
| | | |
| | | this.continuityTabs.push(newTab); |
| | | this.continuityTabIndex = newIndex; |
| | | this.activeContinuityTab = newTab.name; |
| | | }, |
| | | |
| | | // ç§»é¤å»¶ç»æ¤çæ ç¾é¡µ |
| | | removeContinuityTab(targetName) { |
| | | const tabs = this.continuityTabs; |
| | | let activeName = this.activeContinuityTab; |
| | | |
| | | if (activeName === targetName) { |
| | | tabs.forEach((tab, index) => { |
| | | if (tab.name === targetName) { |
| | | const nextTab = tabs[index + 1] || tabs[index - 1]; |
| | | if (nextTab) { |
| | | activeName = nextTab.name; |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | |
| | | this.activeContinuityTab = activeName; |
| | | this.continuityTabs = tabs.filter((tab) => tab.name !== targetName); |
| | | }, |
| | | |
| | | // å¤çæ ç¾é¡µç¹å» |
| | | handleTabClick(tab) { |
| | | this.activeContinuityTab = tab.name; |
| | | }, |
| | | |
| | | // 计ç®è·ç¦»ä¸æ¬¡æå¡è¿æå¤å°å¤© |
| | | calculateDaysLeft(nextServiceTime) { |
| | | if (!nextServiceTime) return 0; |
| | | |
| | | const nextTime = new Date(nextServiceTime); |
| | | const now = new Date(); |
| | | const diffTime = nextTime - now; |
| | | const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); |
| | | |
| | | return diffDays > 0 ? diffDays : 0; |
| | | }, |
| | | |
| | | // ä¿åå»¶ç»æ¤çæ ç¾é¡µ |
| | | saveContinuityTab(index) { |
| | | const formRef = this.$refs[`continuityForm${index}`]; |
| | | if (!formRef) return; |
| | | |
| | | // éªè¯åºæ¬è¡¨å |
| | | formRef[0].validate((valid) => { |
| | | if (valid) { |
| | | // éªè¯å»¶ç»é®é¢æ¯å¦å®æ´ |
| | | const problems = this.continuityTabs[index].form.continuityProblems; |
| | | let hasError = false; |
| | | |
| | | problems.forEach((problem, problemIndex) => { |
| | | if (!problem.questionId) { |
| | | hasError = true; |
| | | this.$modal.msgError(`第${problemIndex + 1}个延ç»é®é¢æªéæ©`); |
| | | } |
| | | }); |
| | | |
| | | if (hasError) { |
| | | return false; |
| | | } |
| | | |
| | | this.continuityTabs[index].saving = true; |
| | | |
| | | // æ´æ°æ±æ»ä¿¡æ¯ |
| | | this.updateContinuitySummaryFromTabs(); |
| | | |
| | | // è°ç¨ä¿åAPI |
| | | this.saveContinuityData(); |
| | | } else { |
| | | this.$modal.msgError("请填å宿´ä¿¡æ¯"); |
| | | return false; |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // æ´æ°å»¶ç»æ¤çæ±æ»ä¿¡æ¯ |
| | | updateContinuitySummaryFromTabs() { |
| | | if (this.continuityTabs.length === 0) return; |
| | | |
| | | // æ¾å°ææ°çæå¡æ¶é´ |
| | | let latestTime = ""; |
| | | let nextTime = ""; |
| | | let totalProblems = 0; |
| | | |
| | | this.continuityTabs.forEach((tab) => { |
| | | if (tab.form.serviceTime) { |
| | | if ( |
| | | !latestTime || |
| | | new Date(tab.form.serviceTime) > new Date(latestTime) |
| | | ) { |
| | | latestTime = tab.form.serviceTime; |
| | | } |
| | | } |
| | | if (tab.form.nextServiceTime) { |
| | | if ( |
| | | !nextTime || |
| | | new Date(tab.form.nextServiceTime) < new Date(nextTime) |
| | | ) { |
| | | nextTime = tab.form.nextServiceTime; |
| | | } |
| | | } |
| | | |
| | | // ç»è®¡é®é¢æ°é |
| | | totalProblems += tab.form.continuityProblems.length; |
| | | }); |
| | | |
| | | this.continuitySummary.continueCount = this.continuityTabs.length; |
| | | this.continuitySummary.continueTimeNow = latestTime; |
| | | this.continuitySummary.continueTimeNext = nextTime; |
| | | |
| | | // æå»ºå®æ´çå»¶ç»æ¤çæ°æ® |
| | | const continuityData = this.continuityTabs.map((tab) => ({ |
| | | ...tab.form, |
| | | tabTitle: tab.title, |
| | | tabName: tab.name, |
| | | })); |
| | | |
| | | this.continuitySummary.continueContent = JSON.stringify(continuityData); |
| | | this.continuitySummary.totalProblems = totalProblems; |
| | | }, |
| | | |
| | | // ä¿åå»¶ç»æ¤çæ°æ® |
| | | saveContinuityData() { |
| | | const vm = this; |
| | | |
| | | // éªè¯æ¯ä¸ªé®é¢çquestionIdæ¯å¦å·²éæ© |
| | | let hasEmptyQuestion = false; |
| | | this.continuityTabs.forEach((tab, tabIndex) => { |
| | | tab.form.continuityProblems.forEach((problem, problemIndex) => { |
| | | if (!problem.questionId) { |
| | | hasEmptyQuestion = true; |
| | | vm.$modal.msgError( |
| | | `第${tabIndex + 1}个æ ç¾é¡µç第${problemIndex + 1}个é®é¢æªéæ©` |
| | | ); |
| | | } |
| | | }); |
| | | }); |
| | | |
| | | if (hasEmptyQuestion) { |
| | | return; |
| | | } |
| | | |
| | | const formData = { |
| | | id: vm.id, |
| | | patid: vm.patid, |
| | | taskid: vm.taskid, |
| | | continueFlag: 2, |
| | | continueCount: vm.continuitySummary.continueCount, |
| | | continueTimeNow: vm.continuitySummary.continueTimeNow, |
| | | continueTimeNext: vm.continuitySummary.continueTimeNext, |
| | | continueContent: vm.continuitySummary.continueContent, |
| | | // å¯ä»¥æ·»å é®å·çæ¡çæ´å |
| | | // questionnaireAnswers: vm.continuityTabs.map((tab) => ({ |
| | | // tabName: tab.name, |
| | | // problems: tab.form.continuityProblems.map((problem) => ({ |
| | | // questionId: problem.questionId, |
| | | // answer: |
| | | // problem.selectedOption || |
| | | // problem.selectedOptions || |
| | | // problem.answer, |
| | | // status: problem.status, |
| | | // description: problem.description, |
| | | // })), |
| | | // })), |
| | | }; |
| | | |
| | | Editsingletaskson(formData) |
| | | .then((res) => { |
| | | if (res.code === 200) { |
| | | vm.$modal.msgSuccess("å»¶ç»æ¤çè®°å½ä¿åæå"); |
| | | // éç½®ä¿åç¶æ |
| | | vm.continuityTabs.forEach((tab) => { |
| | | tab.saving = false; |
| | | }); |
| | | } else { |
| | | vm.$modal.msgError("ä¿å失败"); |
| | | } |
| | | }) |
| | | .catch((error) => { |
| | | console.error("ä¿å失败:", error); |
| | | vm.$modal.msgError("ä¿å失败"); |
| | | vm.continuityTabs.forEach((tab) => { |
| | | tab.saving = false; |
| | | }); |
| | | }); |
| | | }, |
| | | |
| | | // éç½®å»¶ç»æ¤çæ ç¾é¡µ |
| | | resetContinuityTab(index) { |
| | | this.continuityTabs[index].form = { |
| | | continuityProblems: [], |
| | | careRecord: "", |
| | | dutyNurse: "", |
| | | visitType: "", |
| | | serviceTime: "", |
| | | nextServiceTime: "", |
| | | }; |
| | | this.$refs[`continuityForm${index}`][0].clearValidate(); |
| | | }, |
| | | |
| | | // ä¿åæ£è
ä¿¡æ¯ |
| | | savePatientInfo() { |
| | | this.$refs.patientForm.validate((valid) => { |
| | | if (valid) { |
| | | this.savingPatientInfo = true; |
| | | |
| | | // æ´æ°userformæ°æ® |
| | | const updatedUserform = { |
| | | ...this.userform, |
| | | name: this.patientForm.name, |
| | | sex: this.patientForm.sex, |
| | | age: this.patientForm.age, |
| | | telcode: this.patientForm.telcode, |
| | | placeOfResidence: this.patientForm.address, |
| | | medicalRecordNo: this.patientForm.hospitalNumber, |
| | | }; |
| | | |
| | | alterpatient(updatedUserform) |
| | | .then((res) => { |
| | | if (res.code == 200) { |
| | | this.$modal.msgSuccess("æ£è
ä¿¡æ¯ä¿åæå"); |
| | | this.userform = updatedUserform; |
| | | } else { |
| | | this.$modal.msgError("æ£è
ä¿¡æ¯ä¿®æ¹å¤±è´¥"); |
| | | } |
| | | this.savingPatientInfo = false; |
| | | }) |
| | | .catch((error) => { |
| | | console.error("ä¿å失败:", error); |
| | | this.$modal.msgError("ä¿å失败"); |
| | | this.savingPatientInfo = false; |
| | | }); |
| | | } else { |
| | | this.$modal.msgError("请填å宿´ä¿¡æ¯"); |
| | | return false; |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // éç½®æ£è
ä¿¡æ¯ |
| | | resetPatientInfo() { |
| | | this.initPatientForm(); |
| | | this.$refs.patientForm.clearValidate(); |
| | | }, |
| | | |
| | | // æ¶é´æ ¼å¼å |
| | | formatTime(time) { |
| | | if (!time) return ""; |
| | | return time.split(" ")[0]; |
| | | }, |
| | | |
| | | // æ ¼å¼åæ¾ç¤ºæ¶é´ |
| | | formatDisplayTime(time) { |
| | | if (!time) return "æªè®¾ç½®"; |
| | | return time.replace(" ", " "); |
| | | }, |
| | | |
| | | // å¼å¸¸å渲æ |
| | | tableRowClassName({ row }) { |
| | | if (row.id == this.id) { |
| | | return "warning-row"; |
| | | } |
| | | return ""; |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | <style lang="scss" scoped> |
| | | .ContinuityCarePage { |
| | | margin: 10px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 20px; |
| | | } |
| | | |
| | | .headline { |
| | | font-size: 20px; |
| | | height: 40px; |
| | | border-left: 5px solid #41a1be; |
| | | padding-left: 10px; |
| | | margin-bottom: 20px; |
| | | display: flex; |
| | | align-items: center; |
| | | color: #333; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | .sub-headline { |
| | | font-size: 16px; |
| | | height: 36px; |
| | | padding-left: 8px; |
| | | margin-bottom: 15px; |
| | | display: flex; |
| | | align-items: center; |
| | | color: #409eff; |
| | | font-weight: 500; |
| | | border-bottom: 2px solid #e4e7ed; |
| | | padding-bottom: 8px; |
| | | |
| | | i { |
| | | margin-right: 8px; |
| | | font-size: 18px; |
| | | } |
| | | } |
| | | |
| | | /* 第ä¸é¨åï¼æå¡åºç¡ä¿¡æ¯ */ |
| | | .basic-info-section { |
| | | margin: 0 10px; |
| | | padding: 20px; |
| | | background: #fff; |
| | | border: 1px solid #dcdfe6; |
| | | box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12), 0 0 6px 0 rgba(0, 0, 0, 0.04); |
| | | border-radius: 4px; |
| | | |
| | | .basic-info-container { |
| | | display: flex; |
| | | gap: 20px; |
| | | min-height: 1000px; |
| | | |
| | | @media screen and (max-width: 1200px) { |
| | | flex-direction: column; |
| | | } |
| | | } |
| | | |
| | | .followup-content { |
| | | flex: 1; |
| | | min-width: 0; |
| | | |
| | | &.readonly-content { |
| | | background: #f8f9fa; |
| | | border-radius: 8px; |
| | | padding: 15px; |
| | | border: 1px solid #e4e7ed; |
| | | } |
| | | |
| | | .content-container { |
| | | height: calc(1000px - 60px); |
| | | overflow: hidden; |
| | | display: flex; |
| | | flex-direction: column; |
| | | |
| | | ::v-deep .el-tabs { |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | |
| | | .el-tabs__content { |
| | | flex: 1; |
| | | overflow: hidden; |
| | | |
| | | .el-tab-pane { |
| | | height: 100%; |
| | | overflow: hidden; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .continuity-history { |
| | | flex: 1; |
| | | min-width: 0; |
| | | background: #fff; |
| | | border-radius: 8px; |
| | | padding: 15px; |
| | | border: 1px solid #e4e7ed; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); |
| | | |
| | | .history-content { |
| | | height: calc(1000px - 60px); |
| | | overflow: hidden; |
| | | display: flex; |
| | | flex-direction: column; |
| | | |
| | | ::v-deep .el-tabs { |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | |
| | | .el-tabs__content { |
| | | flex: 1; |
| | | overflow-y: auto; |
| | | padding: 15px 0; |
| | | |
| | | .continuity-form { |
| | | padding: 0 10px; |
| | | |
| | | .el-form { |
| | | .selected-problems { |
| | | margin-top: 10px; |
| | | padding: 10px; |
| | | background: #f5f7fa; |
| | | border-radius: 4px; |
| | | border: 1px solid #e4e7ed; |
| | | } |
| | | |
| | | .time-tip { |
| | | margin-top: 5px; |
| | | font-size: 12px; |
| | | color: #67c23a; |
| | | font-style: italic; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .patient-info-section { |
| | | margin: 0 10px 20px 10px; |
| | | padding: 20px; |
| | | background: #fff; |
| | | border: 1px solid #dcdfe6; |
| | | box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12), 0 0 6px 0 rgba(0, 0, 0, 0.04); |
| | | border-radius: 4px; |
| | | |
| | | .patient-info-form { |
| | | .continuity-summary { |
| | | padding: 15px; |
| | | background: #ddf0f8; |
| | | border-radius: 8px; |
| | | border: 1px solid #b3e0f2; |
| | | |
| | | .summary-item { |
| | | display: inline-block; |
| | | margin-right: 30px; |
| | | margin-bottom: 8px; |
| | | |
| | | .label { |
| | | font-weight: 500; |
| | | color: #333; |
| | | } |
| | | |
| | | .value { |
| | | color: #409eff; |
| | | font-weight: 500; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /* å
±äº«æ ·å¼ */ |
| | | .CONTENT { |
| | | padding: 10px; |
| | | height: 100%; |
| | | display: flex; |
| | | flex-direction: column; |
| | | |
| | | .title { |
| | | font-size: 18px; |
| | | font-weight: bold; |
| | | margin-bottom: 20px; |
| | | text-align: center; |
| | | color: #333; |
| | | } |
| | | } |
| | | |
| | | .preview-left { |
| | | margin: 10px; |
| | | padding: 20px; |
| | | border: 1px solid #dcdfe6; |
| | | border-radius: 4px; |
| | | max-height: 800px; |
| | | overflow-y: auto; |
| | | background: #fff; |
| | | flex: 1; |
| | | |
| | | .topic-dev { |
| | | margin-bottom: 20px; |
| | | font-size: 16px; |
| | | |
| | | .dev-text { |
| | | margin-bottom: 10px; |
| | | font-weight: 500; |
| | | color: #333; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .scriptTopic-dev { |
| | | padding: 15px; |
| | | border-radius: 4px; |
| | | background: #fafafa; |
| | | border: 1px solid #e4e7ed; |
| | | margin-bottom: 15px; |
| | | } |
| | | |
| | | .scriptTopic-isabnormal { |
| | | padding: 15px; |
| | | border-radius: 4px; |
| | | background: #fff5f5; |
| | | border: 1px solid #f56c6c; |
| | | color: #f56c6c; |
| | | margin-bottom: 15px; |
| | | } |
| | | |
| | | .scriptTopic-warning { |
| | | padding: 15px; |
| | | border-radius: 4px; |
| | | background: #fff9e6; |
| | | border: 1px solid #e6a23c; |
| | | color: #e6a23c; |
| | | margin-bottom: 15px; |
| | | } |
| | | |
| | | .red-star { |
| | | ::v-deep.el-radio__label { |
| | | position: relative; |
| | | padding-right: 10px; |
| | | } |
| | | |
| | | ::v-deep.el-radio__label::after { |
| | | content: "*"; |
| | | color: #f56c6c; |
| | | position: absolute; |
| | | right: -5px; |
| | | top: 0; |
| | | } |
| | | } |
| | | |
| | | .yellow-star { |
| | | ::v-deep.el-radio__label { |
| | | position: relative; |
| | | padding-right: 10px; |
| | | } |
| | | |
| | | ::v-deep.el-radio__label::after { |
| | | content: "*"; |
| | | color: #e6a23c; |
| | | position: absolute; |
| | | right: -5px; |
| | | top: 0; |
| | | font-weight: bold; |
| | | } |
| | | } |
| | | |
| | | .borderdiv { |
| | | height: 100%; |
| | | padding: 10px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | |
| | | .title { |
| | | font-size: 18px; |
| | | font-weight: bold; |
| | | margin-bottom: 20px; |
| | | text-align: center; |
| | | } |
| | | |
| | | .voice-audio { |
| | | display: flex; |
| | | align-items: center; |
| | | color: #59a0f0; |
| | | margin-bottom: 20px; |
| | | padding: 10px; |
| | | background: #f5f7fa; |
| | | border-radius: 4px; |
| | | } |
| | | |
| | | .preview-left { |
| | | flex: 1; |
| | | margin: 0; |
| | | |
| | | .leftside { |
| | | margin: 15px 0; |
| | | |
| | | span { |
| | | display: inline-block; |
| | | padding: 8px 12px; |
| | | background: #409eff; |
| | | color: #fff; |
| | | border-radius: 8px; |
| | | max-width: 80%; |
| | | margin-left: 10px; |
| | | } |
| | | } |
| | | |
| | | .offside { |
| | | display: flex; |
| | | flex-direction: row-reverse; |
| | | margin: 15px 0; |
| | | |
| | | .offside-value { |
| | | padding: 8px 12px; |
| | | background: #67c23a; |
| | | color: #fff; |
| | | border-radius: 8px; |
| | | max-width: 80%; |
| | | margin-right: 10px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /* ååºå¼è®¾è®¡ */ |
| | | @media (max-width: 768px) { |
| | | .ContinuityCarePage { |
| | | margin: 5px; |
| | | gap: 10px; |
| | | } |
| | | |
| | | .basic-info-section, |
| | | .patient-info-section { |
| | | margin: 0 5px; |
| | | padding: 10px; |
| | | } |
| | | |
| | | .basic-info-container { |
| | | gap: 10px !important; |
| | | } |
| | | |
| | | .patient-info-form { |
| | | .el-row { |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .el-col { |
| | | width: 100% !important; |
| | | margin-bottom: 10px; |
| | | } |
| | | } |
| | | |
| | | .preview-left { |
| | | margin: 5px; |
| | | padding: 10px; |
| | | } |
| | | } |
| | | /* é®é¢éæ©å¨é¢æ¿ */ |
| | | .question-selector-panel { |
| | | margin-bottom: 20px; |
| | | padding: 15px; |
| | | background: #f8f9fa; |
| | | border: 1px solid #e4e7ed; |
| | | border-radius: 8px; |
| | | |
| | | .selector-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 15px; |
| | | padding-bottom: 10px; |
| | | border-bottom: 1px solid #e4e7ed; |
| | | |
| | | span { |
| | | font-weight: 500; |
| | | color: #333; |
| | | } |
| | | } |
| | | |
| | | .question-list { |
| | | max-height: 200px; |
| | | overflow-y: auto; |
| | | padding-right: 10px; |
| | | |
| | | .question-item { |
| | | margin-bottom: 10px; |
| | | padding: 8px 12px; |
| | | background: #fff; |
| | | border-radius: 6px; |
| | | border: 1px solid #e4e7ed; |
| | | transition: all 0.3s; |
| | | |
| | | &:hover { |
| | | border-color: #409eff; |
| | | background: #f0f7ff; |
| | | } |
| | | |
| | | .question-content { |
| | | display: flex; |
| | | align-items: flex-start; |
| | | |
| | | .question-index { |
| | | font-weight: 600; |
| | | color: #409eff; |
| | | min-width: 30px; |
| | | } |
| | | |
| | | .question-text { |
| | | flex: 1; |
| | | line-height: 1.5; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /* å»¶ç»é®é¢è¡¨å */ |
| | | .continuity-problems-form { |
| | | .problems-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 15px; |
| | | padding-bottom: 10px; |
| | | border-bottom: 1px solid #e4e7ed; |
| | | |
| | | span { |
| | | font-weight: 500; |
| | | color: #333; |
| | | } |
| | | } |
| | | |
| | | .problems-list { |
| | | .problem-item { |
| | | margin-bottom: 20px; |
| | | padding: 15px; |
| | | background: #f8f9fa; |
| | | border-radius: 8px; |
| | | border: 1px solid #e4e7ed; |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .problem-content { |
| | | .problem-meta { |
| | | display: flex; |
| | | align-items: center; |
| | | margin-bottom: 15px; |
| | | padding-bottom: 10px; |
| | | border-bottom: 1px dashed #e4e7ed; |
| | | |
| | | .problem-index { |
| | | font-weight: 500; |
| | | color: #409eff; |
| | | min-width: 80px; |
| | | } |
| | | } |
| | | |
| | | .problem-detail { |
| | | .detail-row { |
| | | display: flex; |
| | | align-items: flex-start; |
| | | margin-bottom: 10px; |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .detail-label { |
| | | font-weight: 500; |
| | | color: #666; |
| | | min-width: 100px; |
| | | line-height: 32px; |
| | | } |
| | | |
| | | .detail-value { |
| | | flex: 1; |
| | | line-height: 1.5; |
| | | color: #333; |
| | | padding: 5px 0; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .empty-problems { |
| | | text-align: center; |
| | | padding: 30px 0; |
| | | background: #fafafa; |
| | | border-radius: 8px; |
| | | border: 1px dashed #e4e7ed; |
| | | } |
| | | } |
| | | /* å»¶ç»é®é¢åè¡¨å®¹å¨ - æ·»å æ»å¨ */ |
| | | .problems-list-container { |
| | | max-height: 400px; /* æ§å¶æå¤§é«åº¦ */ |
| | | overflow-y: auto; |
| | | padding-right: 10px; |
| | | margin-bottom: 15px; |
| | | |
| | | &::-webkit-scrollbar { |
| | | width: 6px; |
| | | } |
| | | |
| | | &::-webkit-scrollbar-track { |
| | | background: #f1f1f1; |
| | | border-radius: 3px; |
| | | } |
| | | |
| | | &::-webkit-scrollbar-thumb { |
| | | background: #c1c1c1; |
| | | border-radius: 3px; |
| | | |
| | | &:hover { |
| | | background: #a8a8a8; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /* é®å·å¼é®é¢å±ç¤º */ |
| | | .question-display-area { |
| | | margin: 15px 0; |
| | | padding: 15px; |
| | | background: #fff; |
| | | border-radius: 8px; |
| | | border: 1px solid #e4e7ed; |
| | | |
| | | .question-item-render { |
| | | .question-text { |
| | | margin-bottom: 15px; |
| | | font-size: 14px; |
| | | line-height: 1.5; |
| | | color: #333; |
| | | |
| | | strong { |
| | | color: #409eff; |
| | | margin-right: 5px; |
| | | } |
| | | |
| | | span { |
| | | color: #666; |
| | | } |
| | | } |
| | | |
| | | .question-options { |
| | | margin-left: 20px; |
| | | |
| | | .el-radio, |
| | | .el-checkbox { |
| | | display: block; |
| | | margin-bottom: 8px; |
| | | margin-right: 20px; |
| | | } |
| | | } |
| | | |
| | | .append-input { |
| | | margin-left: 20px; |
| | | margin-top: 10px; |
| | | } |
| | | } |
| | | |
| | | .no-question-data { |
| | | text-align: center; |
| | | color: #999; |
| | | padding: 20px; |
| | | font-style: italic; |
| | | } |
| | | } |
| | | |
| | | /* è°æ´é®é¢è¯¦æ
å¸å± */ |
| | | .problem-detail { |
| | | margin-top: 5px; |
| | | padding-top: 5px; |
| | | padding-bottom: 20px; |
| | | margin-bottom: 10px; |
| | | border-bottom: 1px dashed #6e9af4; |
| | | |
| | | .detail-row { |
| | | display: flex; |
| | | align-items: center; |
| | | margin-bottom: 15px; |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .detail-label { |
| | | font-weight: 500; |
| | | color: #666; |
| | | min-width: 80px; |
| | | white-space: nowrap; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /* ååºå¼è°æ´ */ |
| | | @media (max-width: 768px) { |
| | | .problems-list-container { |
| | | max-height: 300px; |
| | | } |
| | | |
| | | .problem-detail { |
| | | .detail-row { |
| | | flex-direction: column; |
| | | align-items: flex-start; |
| | | |
| | | .detail-label { |
| | | margin-bottom: 5px; |
| | | min-width: auto; |
| | | } |
| | | |
| | | .el-select, |
| | | .el-date-picker { |
| | | width: 100% !important; |
| | | margin: 5px 0 !important; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | /* ååºå¼è°æ´ */ |
| | | @media (max-width: 768px) { |
| | | .question-selector-panel { |
| | | padding: 10px; |
| | | |
| | | .question-list { |
| | | .question-item { |
| | | padding: 6px 8px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .continuity-problems-form { |
| | | .problems-list { |
| | | .problem-item { |
| | | padding: 10px; |
| | | |
| | | .problem-content { |
| | | .problem-meta { |
| | | flex-direction: column; |
| | | align-items: flex-start; |
| | | |
| | | .el-select { |
| | | width: 100% !important; |
| | | margin: 10px 0; |
| | | } |
| | | } |
| | | |
| | | .problem-detail { |
| | | .detail-row { |
| | | flex-direction: column; |
| | | align-items: flex-start; |
| | | |
| | | .detail-label { |
| | | margin-bottom: 5px; |
| | | min-width: auto; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | /* æ»å¨æ¡ç¾å */ |
| | | .preview-left, |
| | | .history-content .el-tabs__content, |
| | | .content-container .el-tabs__content { |
| | | &::-webkit-scrollbar { |
| | | width: 6px; |
| | | } |
| | | |
| | | &::-webkit-scrollbar-track { |
| | | background: #f1f1f1; |
| | | border-radius: 3px; |
| | | } |
| | | |
| | | &::-webkit-scrollbar-thumb { |
| | | background: #c1c1c1; |
| | | border-radius: 3px; |
| | | |
| | | &:hover { |
| | | background: #a8a8a8; |
| | | } |
| | | } |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <!-- <div class="leftvlue" style="margin-bottom: 20px"> |
| | | <el-row :gutter="10"> |
| | | <el-col :span="2.5" v-for="(item, index) in cardlist" :key="index"> |
| | | <el-card |
| | | shadow="hover" |
| | | :body-style="item.router ? ' cursor: pointer' : 'cursor: default'" |
| | | > |
| | | <div style="padding: 8px" @click="$router.push(item.router)"> |
| | | <span>{{ item.name }}</span> |
| | | <div |
| | | style=" |
| | | text-align: center; |
| | | font-size: 18px; |
| | | margin-top: 10px; |
| | | font-weight: 600; |
| | | " |
| | | > |
| | | {{ item.value ? item.value : 0 }} |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | </el-col> |
| | | <el-col :span="2.5"> |
| | | <div class="ysfleftvlue"> |
| | | <el-card shadow="hover"> |
| | | <div style="padding: 8px"> |
| | | <span>表åå·²åé</span> |
| | | <div |
| | | style=" |
| | | text-align: center; |
| | | font-size: 18px; |
| | | margin-top: 10px; |
| | | font-weight: 600; |
| | | " |
| | | > |
| | | {{ yfsvalue }} |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="2.5"> |
| | | <div class="errleftvlue"> |
| | | <el-card shadow="hover"> |
| | | <div style="padding: 8px"> |
| | | <span>å¼å¸¸</span> |
| | | <div |
| | | style=" |
| | | text-align: center; |
| | | font-size: 18px; |
| | | margin-top: 10px; |
| | | font-weight: 600; |
| | | " |
| | | > |
| | | {{ ycvalue }} |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="2.5" v-if="orgname == 'çç«åå¾·ç¿ èé¢åº'"> |
| | | <div class="jgleftvlue"> |
| | | <el-card shadow="hover "> |
| | | <div style="padding: 8px"> |
| | | <span>è¦å</span> |
| | | <div |
| | | style=" |
| | | text-align: center; |
| | | font-size: 18px; |
| | | margin-top: 10px; |
| | | font-weight: 600; |
| | | " |
| | | > |
| | | {{ jgvalue }} |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | </div> --> |
| | | <el-row :gutter="20"> |
| | | <!--ç¨æ·æ°æ®--> |
| | | <el-form |
| | | :model="topqueryParams" |
| | | ref="queryForm" |
| | | size="small" |
| | | :inline="true" |
| | | v-show="showSearch" |
| | | label-width="98px" |
| | | > |
| | | <el-form-item label="ä»»å¡åç§°"> |
| | | <el-input |
| | | v-model="topqueryParams.taskName" |
| | | placeholder="è¯·éæ©ä»»å¡åç§°" |
| | | ></el-input> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="åºé¢æ¶é´"> |
| | | <el-date-picker |
| | | v-model="dateRange" |
| | | style="width: 240px" |
| | | value-format="yyyy-MM-dd" |
| | | type="daterange" |
| | | range-separator="-" |
| | | start-placeholder="å¼å§æ¥æ" |
| | | end-placeholder="ç»ææ¥æ" |
| | | ></el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item label="åºé访æ¶é´"> |
| | | <el-date-picker |
| | | v-model="dateRangefs" |
| | | style="width: 240px" |
| | | value-format="yyyy-MM-dd" |
| | | type="daterange" |
| | | range-separator="-" |
| | | start-placeholder="å¼å§æ¥æ" |
| | | end-placeholder="ç»ææ¥æ" |
| | | ></el-date-picker> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="æ£è
å§å" prop="sendname"> |
| | | <el-input |
| | | v-model="topqueryParams.sendname" |
| | | placeholder="请è¾å
¥æ£è
å§å" |
| | | ></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="è¯æåç§°" prop="leavediagname"> |
| | | <el-input |
| | | v-model="topqueryParams.leavediagname" |
| | | placeholder="请è¾å
¥è¯æåç§°" |
| | | ></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="é访人å" prop="updateBy"> |
| | | <el-input |
| | | v-model="topqueryParams.updateBy" |
| | | placeholder="请è¾å
¥é访人å" |
| | | ></el-input> |
| | | </el-form-item> |
| | | <!-- <el-form-item label="主治å»ç" prop="drname"> |
| | | <el-input |
| | | v-model="topqueryParams.drname" |
| | | placeholder="请è¾å
¥ä¸»æ²»å»ç" |
| | | ></el-input> |
| | | </el-form-item> --> |
| | | <!-- <el-form-item label="ç»ç®¡å»ç" prop="managementDoctor"> |
| | | <el-input |
| | | v-model="topqueryParams.managementDoctor" |
| | | placeholder="请è¾å
¥ä¸»æ²»å»ç" |
| | | ></el-input> |
| | | </el-form-item> --> |
| | | <!-- <el-form-item label="æ¥æéå¶" prop="status"> |
| | | <el-select v-model="endOut" placeholder="è¯·éæ©"> |
| | | <el-option |
| | | v-for="item in endOuts" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | > |
| | | </el-option> |
| | | </el-select> |
| | | </el-form-item> --> |
| | | <el-form-item label="æ£è
èå´" prop="status"> |
| | | <el-cascader |
| | | v-model="topqueryParams.scopetype" |
| | | placeholder="é»è®¤å
¨é¨" |
| | | :options="sourcetype" |
| | | :props="{ expandTrigger: 'hover' }" |
| | | @change="handleChange" |
| | | ></el-cascader> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="ä»»å¡ç¶æ" prop="status"> |
| | | <el-select v-model="topqueryParams.sendstate" placeholder="è¯·éæ©"> |
| | | <el-option |
| | | v-for="item in topicoptions" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | > |
| | | </el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <!-- <el-form-item label="æåºæ¹å¼" prop="status"> |
| | | <el-select v-model="topqueryParams.sort" placeholder="è¯·éæ©"> |
| | | <el-option |
| | | v-for="item in topicoptionssort" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | > |
| | | </el-option> |
| | | </el-select> |
| | | </el-form-item> --> |
| | | |
| | | <el-form-item> |
| | | <el-button |
| | | type="primary" |
| | | icon="el-icon-search" |
| | | size="medium" |
| | | @click="handleQuery(1)" |
| | | >æç´¢</el-button |
| | | > |
| | | <el-button icon="el-icon-refresh" size="medium" @click="resetQuery" |
| | | >éç½®</el-button |
| | | > |
| | | </el-form-item> |
| | | </el-form> |
| | | <el-divider></el-divider> |
| | | <el-row :gutter="10" class="mb8"> |
| | | <el-col :span="1.5"> |
| | | <div class="documentf"> |
| | | <div class="document"> |
| | | <el-button |
| | | type="warning" |
| | | plain |
| | | icon="el-icon-warning-outline" |
| | | size="medium" |
| | | @click="toleadExport(1)" |
| | | >æ§è¡å¤±è´¥</el-button |
| | | > |
| | | </div> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="1.5"> |
| | | <div class="documentf"> |
| | | <div class="document"> |
| | | <el-button |
| | | type="danger" |
| | | plain |
| | | icon="el-icon-warning" |
| | | size="medium" |
| | | @click="toleadExport(2)" |
| | | >ç»æå¼å¸¸</el-button |
| | | > |
| | | </div> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | <el-table |
| | | v-loading="loading" |
| | | ref="userform" |
| | | :data="userList" |
| | | :row-class-name="tableRowClassName" |
| | | @selection-change="handleSelectionChange" |
| | | > |
| | | <el-table-column type="selection" width="50" align="center" /> |
| | | <el-table-column |
| | | label="ä»»å¡åç§°" |
| | | fixed |
| | | width="150" |
| | | show-overflow-tooltip |
| | | align="center" |
| | | key="taskName" |
| | | prop="taskName" |
| | | /> |
| | | <!-- <el-table-column label="åºå·" fixed align="center" key="id" prop="id" /> --> |
| | | <el-table-column |
| | | label="å§å" |
| | | width="100" |
| | | align="center" |
| | | key="sendname" |
| | | prop="sendname" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | size="medium" |
| | | type="text" |
| | | @click=" |
| | | gettoken360(scope.row.sfzh, scope.row.drcode, scope.row.drname) |
| | | " |
| | | ><span class="button-textsc">{{ |
| | | scope.row.sendname |
| | | }}</span></el-button |
| | | > |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="è¯æåç§°" |
| | | align="center" |
| | | key="leavediagname" |
| | | prop="leavediagname" |
| | | width="120" |
| | | :show-overflow-tooltip="true" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="å»¶ç»æ¤ç次æ°" |
| | | align="center" |
| | | key="continueCount" |
| | | prop="continueCount" |
| | | width="120" |
| | | :show-overflow-tooltip="true" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="ææ°å»¶ç»æ¤çæ¶é´" |
| | | sortable |
| | | align="center" |
| | | prop="finishtime" |
| | | width="160" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span>{{ parseTime(scope.row.continueTimeNext) }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="䏿¬¡å»¶ç»æ¤çæ¶é´" |
| | | sortable |
| | | align="center" |
| | | prop="finishtime" |
| | | width="160" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span>{{ parseTime(scope.row.continueTimeNow) }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="ä»»å¡ç¶æ" |
| | | align="center" |
| | | key="sendstate" |
| | | prop="sendstate" |
| | | width="120" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-tooltip |
| | | class="item" |
| | | effect="dark" |
| | | :content="scope.row.remark" |
| | | placement="top-start" |
| | | > |
| | | <div v-if="scope.row.sendstate == 1"> |
| | | <el-tag type="primary" :disable-transitions="false" |
| | | >表åå·²é¢å</el-tag |
| | | > |
| | | </div> |
| | | <div v-if="scope.row.sendstate == 2"> |
| | | <el-tag type="primary" :disable-transitions="false" |
| | | >å¾
é访</el-tag |
| | | > |
| | | </div> |
| | | <div v-if="scope.row.sendstate == 3"> |
| | | <el-tag type="success" :disable-transitions="false" |
| | | >表åå·²åé</el-tag |
| | | > |
| | | </div> |
| | | <div v-if="scope.row.sendstate == 4"> |
| | | <el-tag type="info" :disable-transitions="false">䏿§è¡</el-tag> |
| | | </div> |
| | | <div v-if="scope.row.sendstate == 5"> |
| | | <el-tag type="danger" :disable-transitions="false" |
| | | >åé失败</el-tag |
| | | > |
| | | </div> |
| | | <div v-if="scope.row.sendstate == 6"> |
| | | <el-tag type="success" :disable-transitions="false" |
| | | >已宿</el-tag |
| | | > |
| | | </div> |
| | | <div v-if="scope.row.sendstate == 7"> |
| | | <el-tag type="danger" :disable-transitions="false" |
| | | >è¶
æ¶</el-tag |
| | | > |
| | | </div> |
| | | </el-tooltip> |
| | | </template> |
| | | </el-table-column> |
| | | <!-- <el-table-column |
| | | label="ä»»å¡å¼å¸¸è¯´æ" |
| | | width="120" |
| | | align="center" |
| | | key="remark" |
| | | prop="remark" --> |
| | | /> |
| | | |
| | | <el-table-column |
| | | label="å¤çæè§" |
| | | align="center" |
| | | key="suggest" |
| | | prop="suggest" |
| | | width="120" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <dict-tag |
| | | :options="dict.type.sys_suggest" |
| | | :value="scope.row.suggest" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="馿¬¡éè®¿å®ææ¶é´" |
| | | sortable |
| | | align="center" |
| | | prop="finishtime" |
| | | width="160" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span>{{ parseTime(scope.row.finishtime) }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="åºé¢æ¥æ" |
| | | width="200" |
| | | align="center" |
| | | key="endtime" |
| | | prop="endtime" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span>{{ formatTime(scope.row.endtime) }}</span> |
| | | </template></el-table-column |
| | | > |
| | | <el-table-column |
| | | label="åºéè®¿æ¥æ" |
| | | width="200" |
| | | align="center" |
| | | key="visitTime" |
| | | prop="visitTime" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span>{{ formatTime(scope.row.visitTime) }}</span> |
| | | </template></el-table-column |
| | | > |
| | | <el-table-column |
| | | label="主治å»ç" |
| | | width="120" |
| | | align="center" |
| | | key="drname" |
| | | prop="drname" |
| | | /> |
| | | <el-table-column |
| | | v-if="orgname != '丽水å¸ä¸å»é¢'" |
| | | label="é访人å" |
| | | align="center" |
| | | key="updateBy" |
| | | prop="updateBy" |
| | | width="120" |
| | | /> |
| | | <el-table-column |
| | | v-if="orgname != '丽水å¸ä¸å»é¢'" |
| | | label="ç»ç®¡å»ç" |
| | | align="center" |
| | | key="managementDoctor" |
| | | prop="managementDoctor" |
| | | width="120" |
| | | /> |
| | | <el-table-column |
| | | label="åºé¢å¤©æ°" |
| | | width="120" |
| | | align="center" |
| | | key="endDay" |
| | | prop="endDay" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span>{{ scope.row.endDay ? scope.row.endDay + "天" : "" }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="身份è¯å·ç " |
| | | width="200" |
| | | align="center" |
| | | key="sfzh" |
| | | prop="sfzh" |
| | | /> |
| | | <el-table-column |
| | | label="èç³»çµè¯" |
| | | width="200" |
| | | align="center" |
| | | key="phone" |
| | | prop="phone" |
| | | /> |
| | | <el-table-column |
| | | label="责任æ¤å£«" |
| | | width="120" |
| | | align="center" |
| | | key="nurseName" |
| | | prop="nurseName" |
| | | /> |
| | | |
| | | <el-table-column |
| | | label="ç§å®¤" |
| | | align="center" |
| | | key="deptname" |
| | | prop="deptname" |
| | | width="120" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="ç
åº" |
| | | align="center" |
| | | key="leavehospitaldistrictname" |
| | | prop="leavehospitaldistrictname" |
| | | width="120" |
| | | > |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="åºé¢é访模æ¿åç§°" |
| | | align="center" |
| | | key="templatename" |
| | | prop="templatename" |
| | | width="200" |
| | | /> |
| | | <el-table-column |
| | | label="任塿§è¡æ¹å¼" |
| | | align="center" |
| | | key="preachform" |
| | | prop="preachform" |
| | | width="160" |
| | | :show-overflow-tooltip="true" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span v-for="item in scope.row.preachform">{{ item }}ã </span> |
| | | </template> |
| | | </el-table-column> |
| | | <!-- <el-table-column |
| | | label="ä»»å¡åéæµç¨" |
| | | align="center" |
| | | key="serviceSubtaskRecordList" |
| | | prop="serviceSubtaskRecordList" |
| | | width="160" |
| | | :show-overflow-tooltip="true" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span v-for="item in scope.row.serviceSubtaskRecordList" |
| | | >{{ item.remark }}ã |
| | | </span> |
| | | </template> |
| | | </el-table-column> --> |
| | | <el-table-column |
| | | label="ä»»å¡ç»æè¯´æ" |
| | | width="220" |
| | | align="center" |
| | | key="remark" |
| | | prop="remark" |
| | | > |
| | | <template slot-scope="scope" v-if="scope.row.remark"> |
| | | <el-tooltip |
| | | :content="scope.row.remark" |
| | | placement="top" |
| | | effect="dark" |
| | | > |
| | | <el-tag |
| | | type="warning" |
| | | v-if="scope.row.sendstate != 5 && scope.row.sendstate != 4" |
| | | >{{ scope.row.remark }}</el-tag |
| | | > |
| | | <el-tag type="warning" v-else>{{ scope.row.remark }}</el-tag> |
| | | </el-tooltip> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="æä½" |
| | | align="center" |
| | | fixed="right" |
| | | width="120" |
| | | class-name="small-padding fixed-width" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button size="medium" type="text" @click="Seedetails(scope.row)" |
| | | ><span class="button-zx" |
| | | ><i class="el-icon-s-order"></i>æ¥ç详æ
</span |
| | | ></el-button |
| | | > |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <pagination |
| | | v-show="total > 0" |
| | | :total="total" |
| | | :page.sync="topqueryParams.pageNum" |
| | | :limit.sync="topqueryParams.pageSize" |
| | | @pagination="getList" |
| | | /> |
| | | </el-row> |
| | | <!-- 满æåº¦å¼¹æ¡ --> |
| | | <el-dialog |
| | | title="é访满æåº¦è¯å" |
| | | :visible.sync="scoreDialogVisible" |
| | | width="80%" |
| | | :close-on-click-modal="false" |
| | | > |
| | | <el-table :data="selectedRows" border style="width: 100%"> |
| | | <el-table-column |
| | | label="å§å" |
| | | width="100" |
| | | align="center" |
| | | prop="sendname" |
| | | /> |
| | | <el-table-column |
| | | label="ä»»å¡åç§°" |
| | | width="180" |
| | | align="center" |
| | | prop="taskName" |
| | | /> |
| | | <!-- æ°å¢è¯åå --> |
| | | <el-table-column |
| | | label="ç宿§(20)" |
| | | align="center" |
| | | key="authenticity" |
| | | prop="authenticity" |
| | | width="150" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-input-number |
| | | v-model="scope.row.authenticity" |
| | | :min="0" |
| | | :max="20" |
| | | :step="1" |
| | | size="small" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="ä¸å¨å
宿(20)" |
| | | align="center" |
| | | key="weekFinish" |
| | | prop="weekFinish" |
| | | width="150" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-input-number |
| | | v-model="scope.row.weekFinish" |
| | | :min="0" |
| | | :max="20" |
| | | :step="1" |
| | | size="small" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="è§èæ§(10)" |
| | | align="center" |
| | | key="standard" |
| | | prop="standard" |
| | | width="150" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-input-number |
| | | v-model="scope.row.standard" |
| | | :min="0" |
| | | :max="10" |
| | | :step="1" |
| | | size="small" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="åæ¶æ§(10)" |
| | | align="center" |
| | | key="timeliness" |
| | | prop="timeliness" |
| | | width="150" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-input-number |
| | | v-model="scope.row.timeliness" |
| | | :min="0" |
| | | :max="10" |
| | | :step="1" |
| | | size="small" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="宣ææ
åµ(10)" |
| | | align="center" |
| | | key="library" |
| | | prop="library" |
| | | width="150" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-input-number |
| | | v-model="scope.row.library" |
| | | :min="0" |
| | | :max="10" |
| | | :step="1" |
| | | size="small" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="ç¯å¢æ»¡æåº¦(10)" |
| | | align="center" |
| | | key="environment" |
| | | prop="environment" |
| | | width="150" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-input-number |
| | | v-model="scope.row.environment" |
| | | :min="0" |
| | | :max="10" |
| | | :step="1" |
| | | size="small" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="å»ç满æåº¦(10)" |
| | | align="center" |
| | | key="doctorSatisfaction" |
| | | prop="doctorSatisfaction" |
| | | width="150" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-input-number |
| | | v-model="scope.row.doctorSatisfaction" |
| | | :min="0" |
| | | :max="10" |
| | | :step="1" |
| | | size="small" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="æ¤å£«æ»¡æåº¦(10)" |
| | | align="center" |
| | | key="nurseSatisfaction" |
| | | prop="nurseSatisfaction" |
| | | width="150" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-input-number |
| | | v-model="scope.row.nurseSatisfaction" |
| | | :min="0" |
| | | :max="10" |
| | | :step="1" |
| | | size="small" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="æ»å" |
| | | align="center" |
| | | key="total" |
| | | prop="total" |
| | | fixed="right" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span>{{ calculateTotal(scope.row) }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <div slot="footer" class="dialog-footer"> |
| | | <el-button @click="scoreDialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="saveScores">ä¿å</el-button> |
| | | </div> |
| | | </el-dialog> |
| | | <!-- æ·»å æä¿®æ¹å½±åéè®¿å¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | :title="amendtag ? 'ä¿®æ¹æ£è
ä¿¡æ¯' : 'æ°å¢æ£è
'" |
| | | :visible.sync="Labelchange" |
| | | width="900px" |
| | | > |
| | | <el-form ref="form" :model="form" :rules="rules" label-width="100px"> |
| | | <el-row> |
| | | <el-col :span="8"> |
| | | <el-form-item label="å§å" width="100" prop="name"> |
| | | <el-input |
| | | v-model="form.name" |
| | | placeholder="请è¾å
¥å§å" |
| | | maxlength="30" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="æ§å«" width="100" prop="sex"> |
| | | <el-select v-model="form.sex" placeholder="è¯·éæ©æ§å«"> |
| | | <el-option |
| | | v-for="dict in sextype" |
| | | :key="dict.value" |
| | | :label="dict.label" |
| | | :value="dict.value" |
| | | ></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="å¹´é¾" prop="age"> |
| | | <el-input |
| | | v-model="form.age" |
| | | placeholder="请è¾å
¥å¹´é¾" |
| | | maxlength="30" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="8"> |
| | | <el-form-item label="è¿æ»¤å»ç" width="100" prop="filterDrname"> |
| | | <el-input |
| | | v-model="form.filterDrname" |
| | | placeholder="请è¾å
¥å»çå§å" |
| | | maxlength="30" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="è¿æ»¤åå "> |
| | | <el-input |
| | | v-model="form.notrequiredreason" |
| | | type="textarea" |
| | | placeholder="请è¾å
¥è¿æ»¤åå " |
| | | ></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <div slot="footer" class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm">ç¡® å®</el-button> |
| | | <el-button @click="cancel">å æ¶</el-button> |
| | | </div> |
| | | </el-dialog> |
| | | <!-- ä¿®æ¹åéæ¶é´å¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | title="åéæ¶é´è®¾ç½®" |
| | | :visible.sync="modificationVisible" |
| | | width="45%" |
| | | > |
| | | <div style="margin-bottom: 20px; color: red"> |
| | | ç»ä¸ä¿®æ¹å½å¤©æªåéç任塿¶é´ |
| | | </div> |
| | | |
| | | <el-form |
| | | :model="ruleForm" |
| | | :rules="rules" |
| | | ref="ruleForm" |
| | | label-width="120px" |
| | | class="demo-ruleForm" |
| | | > |
| | | <el-form-item label="å鿥æ"> |
| | | <el-date-picker |
| | | v-model="ruleForm.value1" |
| | | type="date" |
| | | placeholder="éæ©æ¥æ" |
| | | > |
| | | </el-date-picker> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="æ¶é´æ®µ" prop="type"> |
| | | <el-checkbox-group v-model="ruleForm.type"> |
| | | <el-checkbox label="ä¸å" name="type"></el-checkbox> |
| | | <el-checkbox label="ä¸å" name="type"></el-checkbox> |
| | | <el-checkbox label="æä¸" name="type"></el-checkbox> |
| | | </el-checkbox-group> |
| | | </el-form-item> |
| | | <el-form-item label="ä¸åæ¶é´åºé´" required> |
| | | <el-time-picker |
| | | is-range |
| | | v-model="ruleForm.value2" |
| | | range-separator="è³" |
| | | start-placeholder="å¼å§æ¶é´" |
| | | end-placeholder="ç»ææ¶é´" |
| | | placeholder="éæ©æ¶é´èå´" |
| | | > |
| | | </el-time-picker> |
| | | </el-form-item> |
| | | <el-form-item label="ä¸åæ¶é´åºé´" required> |
| | | <el-time-picker |
| | | is-range |
| | | v-model="ruleForm.value3" |
| | | range-separator="è³" |
| | | start-placeholder="å¼å§æ¶é´" |
| | | end-placeholder="ç»ææ¶é´" |
| | | placeholder="éæ©æ¶é´èå´" |
| | | > |
| | | </el-time-picker> |
| | | </el-form-item> |
| | | <el-form-item label="æä¸æ¶é´åºé´" required> |
| | | <el-time-picker |
| | | is-range |
| | | v-model="ruleForm.value4" |
| | | range-separator="è³" |
| | | start-placeholder="å¼å§æ¶é´" |
| | | end-placeholder="ç»ææ¶é´" |
| | | placeholder="éæ©æ¶é´èå´" |
| | | > |
| | | </el-time-picker> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <span slot="footer" class="dialog-footer"> |
| | | <el-button @click="modificationVisible = false">å æ¶</el-button> |
| | | <el-button type="primary" @click="modificationVisible = false" |
| | | >ç¡® å®</el-button |
| | | > |
| | | </span> |
| | | </el-dialog> |
| | | <!-- 忬¡é访 --> |
| | | <el-dialog title="æ£è
忬¡é访" :visible.sync="dialogFormVisible"> |
| | | <el-form ref="zcform" :rules="zcrules" :model="zcform" label-width="80px"> |
| | | <el-form-item label="ä»»å¡åç§°"> |
| | | <el-input |
| | | style="width: 400px" |
| | | disabled |
| | | v-model="zcform.taskName" |
| | | ></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="æ£è
åç§°"> |
| | | <el-input |
| | | style="width: 400px" |
| | | disabled |
| | | v-model="zcform.sendname" |
| | | ></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="å¹´é¾"> |
| | | <el-input |
| | | style="width: 400px" |
| | | disabled |
| | | v-model="zcform.age" |
| | | ></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="ç§å®¤"> |
| | | <el-input |
| | | style="width: 400px" |
| | | disabled |
| | | v-model="zcform.deptname" |
| | | ></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="ç
åº"> |
| | | <el-input |
| | | style="width: 400px" |
| | | disabled |
| | | v-model="zcform.leavehospitaldistrictname" |
| | | ></el-input> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="é访æ¹å¼" prop="resource"> |
| | | <el-radio-group v-model="zcform.resource"> |
| | | <el-radio label="1">æ¬ç
åºé访</el-radio> |
| | | <el-radio label="2">é访ä¸å¿é访</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | <!-- <el-form-item label="å³å»åé"> |
| | | <el-switch v-model="zcform.delivery"></el-switch> |
| | | </el-form-item> --> |
| | | <el-form-item label="åºé¢æ¶é´"> |
| | | <el-input |
| | | style="width: 400px" |
| | | disabled |
| | | v-model="zcform.endtime" |
| | | ></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="éè®¿å®ææ¶é´" prop="date1"> |
| | | <el-date-picker |
| | | type="date" |
| | | placeholder="éæ©æ¥æ" |
| | | v-model="zcform.date1" |
| | | style="width: 100%" |
| | | ></el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item label="é访记å½"> |
| | | <el-input type="textarea" v-model="zcform.remark"></el-input> |
| | | </el-form-item> |
| | | </el-form> |
| | | <div slot="footer" class="dialog-footer"> |
| | | <el-button @click="dialogFormVisible = false">å æ¶</el-button> |
| | | <el-button type="primary" @click="setupsubtask">确认å建æå¡</el-button> |
| | | </div> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { |
| | | delUser, |
| | | addUser, |
| | | updateUser, |
| | | resetUserPwd, |
| | | changeUserStatus, |
| | | } from "@/api/system/user"; |
| | | import { |
| | | getTaskservelist, |
| | | buidegetTasklist, |
| | | addserviceSubtask, |
| | | query360PatInfo, |
| | | addsatisfaction, |
| | | } from "@/api/AiCentre/index"; |
| | | import { alterpatient, particularpatient } from "@/api/patient/homepage"; |
| | | import Treeselect from "@riophae/vue-treeselect"; |
| | | import store from "@/store"; |
| | | import "@riophae/vue-treeselect/dist/vue-treeselect.css"; |
| | | |
| | | export default { |
| | | name: "Discharge", |
| | | dicts: ["sys_normal_disable", "sys_user_sex", "sys_yujing", "sys_suggest"], |
| | | components: { Treeselect }, |
| | | data() { |
| | | return { |
| | | // é®ç½©å± |
| | | loading: true, |
| | | // é䏿°ç» |
| | | ids: [], |
| | | // éå个ç¦ç¨ |
| | | single: true, |
| | | // éå¤ä¸ªç¦ç¨ |
| | | multiple: true, |
| | | // æ¾ç¤ºæç´¢æ¡ä»¶ |
| | | showSearch: true, |
| | | dialogFormVisible: false, |
| | | // æ»æ¡æ° |
| | | total: 0, |
| | | // ç¨æ·è¡¨æ ¼æ°æ® |
| | | userList: null, |
| | | // å¼¹åºå±æ é¢ |
| | | title: "æ°å¢å½±åé访", |
| | | // æ¯å¦æ¾ç¤ºä¿®æ¹ãæ·»å å¼¹åºå± |
| | | addalteropen: false, |
| | | // ä¿®æ¹åéæ¶é´å¯¹è¯æ¡ |
| | | modificationVisible: false, |
| | | // é¨é¨åç§° |
| | | deptName: undefined, |
| | | // é»è®¤å¯ç |
| | | initPassword: undefined, |
| | | // æ¥æèå´ |
| | | dateRange: [], |
| | | dateRangefs: [], |
| | | // å²ä½é项 |
| | | postOptions: [], |
| | | ruleForm: { |
| | | type: [], |
| | | }, |
| | | zcform: {}, |
| | | dynamicTags: ["é项ä¸", "é项äº", "é项ä¸"], //é项 |
| | | inputVisible: false, |
| | | Labelchange: false, |
| | | ycvalue: "", |
| | | jgvalue: "", |
| | | yfsvalue: "", |
| | | inputValue: "", |
| | | preachform: "", |
| | | previewVisible: false, //å½±åé访é¢è§å¼¹æ¡ |
| | | radio: "", |
| | | radios: [], |
| | | previewtype: 2, //é¢è§å½±åé访类å |
| | | total: 0, // æ»æ¡æ° |
| | | // 满æåº¦è°æ¥æ°æ® |
| | | scoreDialogVisible: false, |
| | | selectedRows: [], |
| | | |
| | | value: [], |
| | | list: [], |
| | | |
| | | sourcetype: [ |
| | | { |
| | | value: 1, |
| | | label: "ç§å®¤", |
| | | children: [], |
| | | }, |
| | | { |
| | | value: 2, |
| | | label: "ç
åº", |
| | | children: [], |
| | | }, |
| | | { |
| | | value: 3, |
| | | label: "å
¨é¨", |
| | | }, |
| | | ], |
| | | loading: false, |
| | | cardlist: [ |
| | | { |
| | | name: "åºé¢æå¡æ»é", |
| | | value: 0, |
| | | }, |
| | | // { |
| | | // name: "æ£è
è¿æ»¤", |
| | | // value: 0, |
| | | // }, |
| | | { |
| | | name: "éé访", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "åé失败", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "å¾
é访", |
| | | value: 0, |
| | | }, |
| | | // { |
| | | // name: "å·²åé", |
| | | // value: 0, |
| | | // }, |
| | | |
| | | // { |
| | | // name: "表åå·²åé", |
| | | // value: 0, |
| | | // }, |
| | | ], |
| | | zcrules: { |
| | | date1: [ |
| | | { required: true, message: "è¯·éæ©é访æ¹å¼", trigger: "change" }, |
| | | ], |
| | | resource: [ |
| | | { required: true, message: "è¯·éæ©é访æ¶é´", trigger: "blur" }, |
| | | ], |
| | | }, |
| | | // 表ååæ° |
| | | form: { |
| | | phonenumber: "", |
| | | totagid: "", |
| | | types: "", |
| | | nickName: "", |
| | | qystatus: "", |
| | | btstatus: "", |
| | | }, |
| | | // endOut: 1, |
| | | endOut: localStorage.getItem("orgname") == "丽水å¸ä¸å»é¢" ? 0 : 1, //0 åºé¢æ¶é´(æ£åº) 1 åºé¢æ¶é´(ååº) 2 åéæ¶é´(æ£åº) 3 åéæ¶é´(ååº) 7åºéè®¿æ¥æ(ååº) åºéè®¿æ¥æ(æ£åº) |
| | | endOuts: [ |
| | | { |
| | | value: 0, |
| | | label: "æªæ¢è³å½æ¥æå¡", |
| | | }, |
| | | { |
| | | value: 1, |
| | | label: "å
¨é¨æå¡", |
| | | }, |
| | | ], |
| | | topicoptionssort: [ |
| | | { |
| | | value: 0, |
| | | label: "åºé¢æ¶é´(æ£åº)", |
| | | }, |
| | | { |
| | | value: 1, |
| | | label: "åºé¢æ¶é´(ååº)", |
| | | }, |
| | | { |
| | | value: 2, |
| | | label: "åéæ¶é´(æ£åº)", |
| | | }, |
| | | { |
| | | value: 3, |
| | | label: "åéæ¶é´(ååº)", |
| | | }, |
| | | { |
| | | value: 7, |
| | | label: "åºéè®¿æ¥æ(æ£åº)", |
| | | }, |
| | | { |
| | | value: 8, |
| | | label: "åºéè®¿æ¥æ(ååº)", |
| | | }, |
| | | ], |
| | | // æ¥è¯¢åæ° |
| | | topqueryParams: { |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | sort: localStorage.getItem("orgname") == "丽水å¸ä¸å»é¢" ? 8 : 2, //0 åºé¢æ¶é´(æ£åº) 1 åºé¢æ¶é´(ååº) 2 åéæ¶é´(æ£åº) 3 åéæ¶é´(ååº) 7åºéè®¿æ¥æ(ååº) åºéè®¿æ¥æ(æ£åº) |
| | | searchscope: 3, |
| | | continueFlag: 2, |
| | | visitCount: 1, |
| | | scopetype: [], |
| | | leaveldeptcodes: [], |
| | | leavehospitaldistrictcodes: [], |
| | | }, |
| | | orgname: "", |
| | | propss: { multiple: true }, |
| | | options: [], |
| | | |
| | | topicoptions: [ |
| | | { |
| | | value: null, |
| | | label: "å
¨é¨", |
| | | }, |
| | | { |
| | | value: 1, |
| | | label: "表åå·²é¢å", |
| | | }, |
| | | { |
| | | value: 2, |
| | | label: "å¾
é访", |
| | | }, |
| | | { |
| | | value: 3, |
| | | label: "表åå·²åé", |
| | | }, |
| | | { |
| | | value: 4, |
| | | label: "䏿§è¡", |
| | | }, |
| | | { |
| | | value: 5, |
| | | label: "åé失败", |
| | | }, |
| | | { |
| | | value: 6, |
| | | label: "已宿", |
| | | }, |
| | | { |
| | | value: 7, |
| | | label: "è¶
æ¶", |
| | | }, |
| | | ], |
| | | sextype: [ |
| | | { |
| | | value: 1, |
| | | label: "ç·", |
| | | }, |
| | | { |
| | | value: 2, |
| | | label: "女", |
| | | }, |
| | | ], |
| | | topicoptionsyj: [ |
| | | { |
| | | value: 1, |
| | | label: "å¼å¸¸", |
| | | }, |
| | | { |
| | | value: 2, |
| | | label: "è¦å", |
| | | }, |
| | | { |
| | | value: 0, |
| | | label: "æ£å¸¸", |
| | | }, |
| | | ], |
| | | url: "http://9.208.2.190:8090/smartor/serviceExternal/query360PatInfo", |
| | | postData: { |
| | | XiaoXiTou: { |
| | | FaSongFCSJC: "ZJHES", |
| | | FaSongJGID: localStorage.getItem("orgid"), |
| | | FaSongJGMC: localStorage.getItem("orgname"), |
| | | FaSongSJ: "2025-01-09Â 17:29:36", |
| | | FaSongXTJC: "SUIFANGXT", |
| | | FaSongXTMC: "é访系ç»", |
| | | XiaoXiID: "5FA92AFB-9833-4608-87C7-F56A654AC171", |
| | | XiaoXiLX: "SC_LC_360STCX", |
| | | XiaoXiMC: "360 è§å¾æ¥è¯¢", |
| | | ZuHuID: localStorage.getItem("ZuHuID"), |
| | | ZuHuMC: localStorage.getItem("orgname"), |
| | | }, |
| | | YeWuXX: { |
| | | BingRenXX: { |
| | | ZhengJianHM: "", |
| | | ZhengJianLXDM: "01", |
| | | ZhengJianLXMC: "å±
æ°èº«ä»½è¯", |
| | | ZuZhiJGID: localStorage.getItem("orgid"), |
| | | ZuZhiJGMC: localStorage.getItem("orgname"), |
| | | }, |
| | | YongHuXX: { |
| | | XiTongID: "SUIFANGXT", |
| | | XiTongMC: "é访系ç»", |
| | | YongHuID: localStorage.getItem("YongHuID"), |
| | | YongHuXM: localStorage.getItem("YongHuXM"), |
| | | ZuZhiJGID: localStorage.getItem("orgid"), |
| | | ZuZhiJGMC: localStorage.getItem("orgname"), |
| | | idp: "lyra", |
| | | }, |
| | | }, |
| | | }, |
| | | amendtag: false, |
| | | errtype: "", |
| | | leavehospitaldistrictcode: "", |
| | | serviceState: [], |
| | | checkboxlist: [], |
| | | // è¡¨åæ ¡éª |
| | | rules: {}, |
| | | }; |
| | | }, |
| | | watch: {}, |
| | | created() { |
| | | this.serviceState = store.getters.serviceState; |
| | | this.checkboxlist = store.getters.checkboxlist; |
| | | this.errtype = this.$route.query.errtype; |
| | | this.orgname = localStorage.getItem("orgname"); |
| | | this.leavehospitaldistrictcode = |
| | | this.$route.query.leavehospitaldistrictcode; |
| | | this.sourcetype[0].children = store.getters.belongDepts.map((dept) => { |
| | | return { |
| | | label: dept.deptName, |
| | | value: dept.deptCode, |
| | | }; |
| | | }); |
| | | this.sourcetype[1].children = store.getters.belongWards.map((dept) => { |
| | | return { |
| | | label: dept.districtName, |
| | | value: dept.districtCode, |
| | | }; |
| | | }); |
| | | if (this.errtype) { |
| | | this.toleadExport(2); |
| | | } else { |
| | | this.getList(1); |
| | | } |
| | | this.getConfigKey("sys.user.initPassword").then((response) => { |
| | | this.initPassword = response.msg; |
| | | }); |
| | | }, |
| | | activated() { |
| | | this.getList(1); |
| | | }, |
| | | methods: { |
| | | /** æ¥è¯¢é访æå¡å表 */ |
| | | getList(refresh) { |
| | | // é»è®¤å
¨é¨ |
| | | if (this.topqueryParams.searchscope == 3) { |
| | | this.topqueryParams.leaveldeptcodes = store.getters.belongDepts.map( |
| | | (obj) => obj.deptCode |
| | | ); |
| | | this.topqueryParams.leavehospitaldistrictcodes = |
| | | store.getters.belongWards.map((obj) => obj.districtCode); |
| | | } |
| | | if (this.endOut == 0) { |
| | | this.topqueryParams.endSendDateTime = this.formatDateToYYYYMMDDHHMMSS( |
| | | this.getEndOfDay() |
| | | ); |
| | | } else { |
| | | // this.topqueryParams.endSendDateTime = null; |
| | | } |
| | | // æ¥åå¼å¸¸è·³è½¬ |
| | | if (this.errtype) { |
| | | this.topqueryParams.leavehospitaldistrictcodes.push( |
| | | this.leavehospitaldistrictcode |
| | | ); |
| | | console.log(this.topqueryParams.leavehospitaldistrictcodes, "11"); |
| | | } |
| | | this.loading = true; |
| | | if ( |
| | | this.topqueryParams.leavehospitaldistrictcodes[0] && |
| | | this.topqueryParams.leaveldeptcodes[0] |
| | | ) { |
| | | this.topqueryParams.deptOrDistrict = 2; |
| | | } else { |
| | | this.topqueryParams.deptOrDistrict = 1; |
| | | } |
| | | getTaskservelist(this.topqueryParams).then((response) => { |
| | | this.userList = response.rows[0].serviceSubtaskList; |
| | | this.total = response.total; |
| | | if (refresh) { |
| | | this.cardlist[0].value = |
| | | Number(response.rows[0].wzx) + Number(response.rows[0].ysf); |
| | | // this.cardlist[1].value = response.rows[0].wzx; |
| | | this.cardlist[1].value = response.rows[0].ysf; |
| | | this.ycvalue = response.rows[0].yc; |
| | | this.jgvalue = response.rows[0].jg; |
| | | this.cardlist[2].value = response.rows[0].fssb; |
| | | this.cardlist[3].value = response.rows[0].dsf; |
| | | // this.cardlist[4].value = response.rows[0].yfs2; |
| | | this.yfsvalue = response.rows[0].yfs; |
| | | } |
| | | this.loading = false; |
| | | this.userList.forEach((item) => { |
| | | let idArray = null; |
| | | if (item.endtime) { |
| | | item.endDay = this.daysBetween(item.endtime); |
| | | } |
| | | |
| | | if (item.preachform) { |
| | | if (item.endtime) { |
| | | item.preachformson = item.preachform; |
| | | idArray = item.preachform.split(","); |
| | | } |
| | | |
| | | item.preachform = idArray.map((value) => { |
| | | // æ¥æ¾id对åºç对象 |
| | | const item = this.checkboxlist.find( |
| | | (item) => item.value == value |
| | | ); |
| | | // 妿æ¾å°å¯¹åºçidï¼è¿ålabelå¼ï¼å¦åè¿ånull |
| | | return item ? item.label : null; |
| | | }); |
| | | } |
| | | }); |
| | | this.total = response.total; |
| | | }); |
| | | }, |
| | | // æ¶é´ |
| | | getEndOfDay() { |
| | | const date = new Date(); // å建ä¸ä¸ªè¡¨ç¤ºå½åæ¶é´çDate对象 |
| | | date.setHours(23, 59, 59, 0); // å°æ¶é´è®¾ç½®ä¸º23:59:59.000 |
| | | return date; |
| | | }, |
| | | formatDateToYYYYMMDDHHMMSS(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 seconds = String(date.getSeconds()).padStart(2, "0"); |
| | | |
| | | return `${year}-${month}-${day}`; |
| | | }, |
| | | affiliation() { |
| | | this.topqueryParams.managementDoctorCode = store.getters.hisUserId; |
| | | this.getList(1); |
| | | }, |
| | | onthatday() { |
| | | this.topqueryParams.startSendDateTime = this.getCurrentDate(); |
| | | this.topqueryParams.endSendDateTime = this.getCurrentDate(); |
| | | this.getList(1); |
| | | }, |
| | | getCurrentDate() { |
| | | const now = new Date(); |
| | | return now.toISOString().slice(0, 10); // æªåå10个å符ï¼å³ YYYY-MM-DD |
| | | }, |
| | | buidegetTasklist(type) { |
| | | if (this.topqueryParams.searchscope == 3) { |
| | | this.topqueryParams.leaveldeptcodes = store.getters.belongDepts.map( |
| | | (obj) => obj.deptCode |
| | | ); |
| | | this.topqueryParams.leavehospitaldistrictcodes = |
| | | store.getters.belongWards.map((obj) => obj.districtCode); |
| | | } |
| | | // æ¥åå¼å¸¸è·³è½¬ |
| | | if (this.errtype) { |
| | | this.topqueryParams.leavehospitaldistrictcodes.push( |
| | | this.leavehospitaldistrictcode |
| | | ); |
| | | } |
| | | let obj = { |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | leavehospitaldistrictcodes: |
| | | this.topqueryParams.leavehospitaldistrictcodes, |
| | | sendstates: [2, 3], |
| | | leaveldeptcodes: this.topqueryParams.leaveldeptcodes, |
| | | }; |
| | | buidegetTasklist(obj).then((response) => { |
| | | this.userList = response.rows[0].serviceSubtaskList; |
| | | this.total = response.total; |
| | | if (refresh) { |
| | | this.cardlist[0].value = |
| | | Number(response.rows[0].wzx) + Number(response.rows[0].ysf); |
| | | this.cardlist[1].value = response.rows[0].wzx; |
| | | this.cardlist[2].value = response.rows[0].ysf; |
| | | this.ycvalue = response.rows[0].yc; |
| | | this.jgvalue = response.rows[0].jg; |
| | | this.cardlist[3].value = response.rows[0].fssb; |
| | | this.cardlist[4].value = response.rows[0].dsf; |
| | | // this.cardlist[5].value = response.rows[0].yfs2; |
| | | this.yfsvalue = response.rows[0].yfs; |
| | | } |
| | | this.loading = false; |
| | | this.userList.forEach((item) => { |
| | | let idArray = null; |
| | | if (item.endtime) { |
| | | item.endDay = this.daysBetween(item.endtime); |
| | | } |
| | | |
| | | if (item.preachform) { |
| | | if (item.endtime) { |
| | | item.preachformson = item.preachform; |
| | | idArray = item.preachform.split(","); |
| | | } |
| | | |
| | | item.preachform = idArray.map((value) => { |
| | | // æ¥æ¾id对åºç对象 |
| | | const item = this.checkboxlist.find( |
| | | (item) => item.value == value |
| | | ); |
| | | // 妿æ¾å°å¯¹åºçidï¼è¿ålabelå¼ï¼å¦åè¿ånull |
| | | return item ? item.label : null; |
| | | }); |
| | | } |
| | | }); |
| | | this.total = response.total; |
| | | }); |
| | | }, |
| | | // æ¥çé¨è¯é访详æ
|
| | | Referencequestion(row) { |
| | | this.previewVisible = true; |
| | | }, |
| | | // æ·»å å¼¹æ¡æç´¢ |
| | | remoteMethod(query) { |
| | | if (query !== "") { |
| | | this.loading = true; |
| | | setTimeout(() => { |
| | | this.loading = false; |
| | | this.options = this.list.filter((item) => { |
| | | return item.label.toLowerCase().indexOf(query.toLowerCase()) > -1; |
| | | }); |
| | | }, 200); |
| | | } else { |
| | | this.options = []; |
| | | } |
| | | }, |
| | | // å½±åéè®¿ç¶æä¿®æ¹ |
| | | handleStatusChange(row) { |
| | | let text = row.status === "0" ? "å¯ç¨" : "åç¨"; |
| | | this.$modal |
| | | .confirm('确认è¦"' + text + '""' + row.userName + '"ç¨æ·åï¼') |
| | | .then(function () { |
| | | return changeUserStatus(row.userId, row.status); |
| | | }) |
| | | .then(() => { |
| | | this.$modal.msgSuccess(text + "æå"); |
| | | }) |
| | | .catch(function () { |
| | | row.status = row.status === "0" ? "1" : "0"; |
| | | }); |
| | | }, |
| | | |
| | | // 表åéç½® |
| | | reset() { |
| | | this.form = { |
| | | userId: undefined, |
| | | deptId: undefined, |
| | | userName: undefined, |
| | | nickName: undefined, |
| | | password: undefined, |
| | | phonenumber: undefined, |
| | | email: undefined, |
| | | sex: undefined, |
| | | status: "0", |
| | | remark: undefined, |
| | | postIds: [], |
| | | roleIds: [], |
| | | }; |
| | | this.resetForm("form"); |
| | | }, |
| | | /** æç´¢æé®æä½ */ |
| | | handleQuery(refresh) { |
| | | if (this.topqueryParams.searchscope == 3) { |
| | | this.topqueryParams.leaveldeptcodes = store.getters.belongDepts.map( |
| | | (obj) => obj.deptCode |
| | | ); |
| | | this.topqueryParams.leavehospitaldistrictcodes = |
| | | store.getters.belongWards.map((obj) => obj.districtCode); |
| | | } |
| | | this.topqueryParams.pageNum = 1; |
| | | this.topqueryParams.startOutHospTime = this.dateRange[0]; |
| | | this.topqueryParams.endOutHospTime = this.dateRange[1]; |
| | | this.topqueryParams.startSendDateTime = this.dateRangefs[0]; |
| | | this.topqueryParams.endSendDateTime = this.dateRangefs[1]; |
| | | this.getList(refresh); |
| | | }, |
| | | // æ£è
èå´å¤ç |
| | | handleChange(value) { |
| | | let type = value[0]; |
| | | let code = value.slice(-1)[0]; |
| | | this.topqueryParams.leavehospitaldistrictcodes = []; |
| | | this.topqueryParams.leaveldeptcodes = []; |
| | | if (type == 1) { |
| | | this.topqueryParams.leaveldeptcodes.push(code); |
| | | this.topqueryParams.leavehospitaldistrictcodes = []; |
| | | this.topqueryParams.searchscope = 1; |
| | | } else if (type == 2) { |
| | | this.topqueryParams.leavehospitaldistrictcodes.push(code); |
| | | this.topqueryParams.leaveldeptcodes = []; |
| | | this.topqueryParams.searchscope = 2; |
| | | } else { |
| | | this.topqueryParams.searchscope = 3; |
| | | } |
| | | }, |
| | | /** éç½®æé®æä½ */ |
| | | resetQuery() { |
| | | this.dateRange = []; |
| | | this.dateRangefs = []; |
| | | this.topqueryParams = { |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | sort: 2, //0 åºé¢æ¶é´(æ£åº) 1 åºé¢æ¶é´(ååº) 2 åéæ¶é´(æ£åº) 3 åéæ¶é´(ååº) |
| | | searchscope: 3, |
| | | continueFlag: 2, |
| | | visitCount: 1, |
| | | scopetype: [], |
| | | leaveldeptcodes: [], |
| | | leavehospitaldistrictcodes: [], |
| | | }; |
| | | this.handleQuery(1); |
| | | }, |
| | | handleSelectionChange(rows) { |
| | | this.selectedRows = rows.map((row) => { |
| | | // åå§åè¯ååæ®µ |
| | | return { |
| | | ...row, |
| | | authenticity: row.authenticity || 0, |
| | | weekFinish: row.weekFinish || 0, |
| | | standard: row.standard || 0, |
| | | timeliness: row.timeliness || 0, |
| | | library: row.library || 0, |
| | | environment: row.environment || 0, |
| | | doctorSatisfaction: row.doctorSatisfaction || 0, |
| | | nurseSatisfaction: row.nurseSatisfaction || 0, |
| | | }; |
| | | }); |
| | | |
| | | if (this.selectedRows.length > 0) { |
| | | this.multiple = false; |
| | | } else { |
| | | this.multiple = true; |
| | | } |
| | | }, |
| | | |
| | | // è®¡ç®æ»å |
| | | calculateTotal(row) { |
| | | return ( |
| | | (row.authenticity || 0) + |
| | | (row.weekFinish || 0) + |
| | | (row.standard || 0) + |
| | | (row.timeliness || 0) + |
| | | (row.library || 0) + |
| | | (row.environment || 0) + |
| | | (row.doctorSatisfaction || 0) + |
| | | (row.nurseSatisfaction || 0) |
| | | ); |
| | | }, |
| | | |
| | | // ä¿åè¯å |
| | | saveScores() { |
| | | this.selectedRows.forEach((item) => { |
| | | item.createBy = null; |
| | | item.patName = item.sendname; |
| | | item.hospitaldistrictname = item.leavehospitaldistrictname; |
| | | }); |
| | | addsatisfaction(this.selectedRows).then((res) => { |
| | | if (res.code == 200) { |
| | | this.$message.success("è¯åä¿åæå"); |
| | | this.scoreDialogVisible = false; |
| | | this.selectedRows = []; |
| | | this.$refs.userform.clearSelection(); |
| | | } else { |
| | | this.$modal.msgWarning("è¯åä¿å失败"); |
| | | this.scoreDialogVisible = false; |
| | | this.selectedRows = []; |
| | | this.$refs.userform.clearSelection(); |
| | | } |
| | | }); |
| | | // è¿éå¯ä»¥æ·»å ä¿åé»è¾ï¼å¦è°ç¨APIä¿åè¯å |
| | | }, |
| | | //å é¤é项 |
| | | handleClose(tag) { |
| | | this.dynamicTags.splice(this.dynamicTags.indexOf(tag), 1); |
| | | }, |
| | | //è§¦åæ°å¢è¾å
¥ |
| | | showInput() { |
| | | this.inputVisible = true; |
| | | this.$nextTick((_) => { |
| | | this.$refs.saveTagInput.$refs.input.focus(); |
| | | }); |
| | | }, |
| | | //è·å失å»ç¦ç¹è§¦å |
| | | handleInputConfirm() { |
| | | let inputValue = this.inputValue; |
| | | if (inputValue) { |
| | | this.dynamicTags.push(inputValue); |
| | | } |
| | | this.inputVisible = false; |
| | | this.inputValue = ""; |
| | | }, |
| | | /** æ°å¢æé®æä½ */ |
| | | handleAdd() { |
| | | this.$router.push({ |
| | | path: "/followvisit/QuestionnaireTask", |
| | | query: { |
| | | type: 2, |
| | | serviceType: 2, |
| | | }, |
| | | }); |
| | | }, |
| | | //æ£è
360跳转 |
| | | gettoken360(sfzh, drcode, drname) { |
| | | // this.$modal.msgWarning("360åè½ææªå¼é"); |
| | | |
| | | this.postData.YeWuXX.BingRenXX.ZhengJianHM = sfzh; |
| | | |
| | | query360PatInfo(this.postData).then((res) => { |
| | | if (res.data.url) { |
| | | window.open(res.data.url, "_blank"); |
| | | // this.linkUrl = res.data.url; |
| | | } else { |
| | | this.$modal.msgWarning("360æ¥è¯¢æ ç»æ"); |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | /** éç½®å¯ç æé®æä½ */ |
| | | handleResetPwd(row) { |
| | | this.$prompt('请è¾å
¥"' + row.userName + '"çæ°å¯ç ', "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | closeOnClickModal: false, |
| | | inputPattern: /^.{5,20}$/, |
| | | inputErrorMessage: "ç¨æ·å¯ç é¿åº¦å¿
é¡»ä»äº 5 å 20 ä¹é´", |
| | | }) |
| | | .then(({ value }) => { |
| | | resetUserPwd(row.userId, value).then((response) => { |
| | | this.$modal.msgSuccess("ä¿®æ¹æåï¼æ°å¯ç æ¯ï¼" + value); |
| | | }); |
| | | }) |
| | | .catch(() => {}); |
| | | }, |
| | | // åæ¶æé® |
| | | cancel() { |
| | | this.Labelchange = false; |
| | | this.reset(); |
| | | }, |
| | | /** æäº¤æé® */ |
| | | submitForm: function () { |
| | | this.$refs["form"].validate((valid) => { |
| | | if (valid) { |
| | | this.form.isoperation = 2; |
| | | this.form.notrequiredFlag = 1; |
| | | alterpatient(this.form) |
| | | .then((response) => { |
| | | console.log(response); |
| | | }) |
| | | .then(() => { |
| | | this.getList(1); |
| | | this.$modal.msgSuccess("æ£è
è¿æ»¤æå"); |
| | | }); |
| | | |
| | | this.reset(); |
| | | this.Labelchange = false; |
| | | } |
| | | }); |
| | | }, |
| | | /** å é¤æé®æä½ */ |
| | | handleDelete(row) { |
| | | const userIds = row.userId || this.ids; |
| | | this.$modal |
| | | .confirm('æ¯å¦ç¡®è®¤å é¤ç¨æ·ç¼å·ä¸º"' + userIds + '"çæ°æ®é¡¹ï¼') |
| | | .then(function () { |
| | | return delUser(userIds); |
| | | }) |
| | | .then(() => { |
| | | this.getList(1); |
| | | this.$modal.msgSuccess("å 餿å"); |
| | | }) |
| | | .catch(() => {}); |
| | | }, |
| | | // å
¨é¨åæ¢ |
| | | AllStop() { |
| | | this.$modal |
| | | .confirm("æ¯å¦åæ¢å
¨é¨ä»»å¡ï¼") |
| | | .then(function () { |
| | | return console.log("忢æå"); |
| | | }) |
| | | .then(() => { |
| | | this.getList(1); |
| | | this.$modal.msgWarning("忢æå"); |
| | | }) |
| | | .catch(() => {}); |
| | | }, |
| | | // å
¨é¨å¼å§ |
| | | AllStarted() { |
| | | this.$modal |
| | | .confirm("æ¯å¦å¼å¯å
¨é¨ä»»å¡ï¼") |
| | | .then(function () { |
| | | return console.log("å¼å¯æå"); |
| | | }) |
| | | .then(() => { |
| | | this.getList(1); |
| | | this.$modal.msgSuccess("å¼å¯æå"); |
| | | }) |
| | | .catch(() => {}); |
| | | }, |
| | | // ä»»å¡éç½® |
| | | TaskReset() { |
| | | this.$modal |
| | | .confirm("æ¯å¦éç½®éä¸çä»»å¡é¡¹ï¼") |
| | | .then(function () { |
| | | return console.log("é䏿å"); |
| | | }) |
| | | .then(() => { |
| | | this.getList(1); |
| | | this.$modal.msgSuccess("éç½®æå"); |
| | | }) |
| | | .catch(() => {}); |
| | | }, |
| | | // 设置åéæ¶é´ |
| | | Sendtimesetting() { |
| | | this.modificationVisible = true; |
| | | }, |
| | | // 跳转详æ
页 |
| | | Seedetails(row) { |
| | | let type = ""; |
| | | console.log(row, "rwo"); |
| | | if (row.type == 1) { |
| | | type = 1; |
| | | } |
| | | this.$router.push({ |
| | | path: "/followvisit/ContinueFordetails/", |
| | | query: { |
| | | taskid: row.taskid, |
| | | patid: row.patid, |
| | | id: row.id, |
| | | Voicetype: type, |
| | | visitCount: this.topqueryParams.visitCount, |
| | | }, |
| | | }); |
| | | }, |
| | | // 忬¡é访 |
| | | followupvisit(row) { |
| | | this.zcform = row; |
| | | this.zcform.endtime = this.formatTime(this.zcform.endtime); |
| | | this.dialogFormVisible = true; |
| | | }, |
| | | onSubmit() {}, |
| | | // æåæå¡ |
| | | handlestop(row) { |
| | | let objson = row; |
| | | this.$modal |
| | | .confirm( |
| | | 'æ¯å¦ç¡®è®¤æåä»»å¡å称为"' + |
| | | row.taskName + |
| | | 'æ£è
å称为"' + |
| | | row.sendname + |
| | | '"çæ°æ®é¡¹ï¼' |
| | | ) |
| | | .then(() => { |
| | | getTaskservelist({ |
| | | patid: row.patid, |
| | | taskid: row.taskid, |
| | | }).then((res) => { |
| | | if (res.code == 200) { |
| | | objson.sendstate = 4; |
| | | objson.remark = "æå¡æå"; |
| | | Editsingletaskson(objson).then((res) => { |
| | | if (res.code) { |
| | | this.$modal.msgSuccess("è®°å½æå"); |
| | | this.getList(1); |
| | | } |
| | | }); |
| | | } |
| | | }); |
| | | }) |
| | | .catch(() => {}); |
| | | }, |
| | | // æ£è
è¿æ»¤è§¦å |
| | | handleUpdate(row) { |
| | | particularpatient(row.patid).then((response) => { |
| | | this.form = response.data; |
| | | this.form.filterDrname = store.getters.nickName; |
| | | }); |
| | | this.amendtag = true; |
| | | this.Labelchange = true; |
| | | }, |
| | | // ä¾¿æ·æé® |
| | | toleadExport(too) { |
| | | if (too == 1) { |
| | | this.topqueryParams.sendstate = 4; |
| | | this.topqueryParams.excep = null; |
| | | } else if (too == 2) { |
| | | this.topqueryParams.excep = 1; |
| | | } |
| | | this.handleQuery(); |
| | | }, |
| | | /** å¯¼åºæé®æä½ */ |
| | | handleExport() { |
| | | this.topqueryParams.pageNum = null; |
| | | this.topqueryParams.pageSize = null; |
| | | this.download( |
| | | "smartor/serviceSubtask/patItemExport", |
| | | { |
| | | ...this.topqueryParams, |
| | | }, |
| | | `user_${new Date().getTime()}.xlsx` |
| | | ); |
| | | }, |
| | | // å¼å¸¸å渲æ |
| | | tableRowClassName({ row, rowIndex }) { |
| | | if (row.excep == 1) { |
| | | return "warning-row"; |
| | | } else if (row.excep == 2) { |
| | | return "remind-row"; |
| | | } |
| | | return ""; |
| | | }, |
| | | // åå»ºåæ¬¡é访æå¡ |
| | | setupsubtask() { |
| | | this.$refs["zcform"].validate((valid) => { |
| | | if (valid) { |
| | | this.zcform.remark = |
| | | this.zcform.remark + "ã" + this.getCurrentTime() + "ã"; |
| | | let form = structuredClone(this.zcform); |
| | | form.visitTime = this.formatTime(form.date1); |
| | | form.finishtime = ""; |
| | | if (form.resource) { |
| | | if (form.resource == 2) { |
| | | form.serviceType = 13; |
| | | } |
| | | } else { |
| | | this.$modal.msgError("æªéæ©é访æ¹å¼"); |
| | | } |
| | | form.id = null; |
| | | form.sendstate = 2; |
| | | form.preachform = form.preachformson; |
| | | form.longTask = 0; |
| | | addserviceSubtask(form).then((res) => { |
| | | if (res.code == 200) { |
| | | this.$modal.msgSuccess("å建æå"); |
| | | } else { |
| | | this.$modal.msgError("å建失败"); |
| | | } |
| | | this.dialogFormVisible = false; |
| | | }); |
| | | } |
| | | }); |
| | | }, |
| | | getCurrentTime() { |
| | | const now = new Date(); |
| | | const year = now.getFullYear(); |
| | | const month = String(now.getMonth() + 1).padStart(2, "0"); |
| | | const day = String(now.getDate()).padStart(2, "0"); |
| | | const hours = String(now.getHours()).padStart(2, "0"); |
| | | const minutes = String(now.getMinutes()).padStart(2, "0"); |
| | | const seconds = String(now.getSeconds()).padStart(2, "0"); |
| | | |
| | | return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .el-button--primary.is-plain { |
| | | color: #ffffff; |
| | | background: #409eff; |
| | | border-color: #4fabe9; |
| | | } |
| | | |
| | | .document { |
| | | // width: 100px; |
| | | height: 50px; |
| | | } |
| | | ::v-deep.el-table .warning-row { |
| | | background: #eec4c4; |
| | | } |
| | | ::v-deep.el-table .remind-row { |
| | | background: #fcf5aa; |
| | | } |
| | | |
| | | .documentf { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | } |
| | | |
| | | .download { |
| | | text-align: center; |
| | | |
| | | .el-upload__tip { |
| | | font-size: 23px; |
| | | } |
| | | |
| | | .el-upload__text { |
| | | font-size: 23px; |
| | | } |
| | | } |
| | | |
| | | .uploading { |
| | | margin-top: 20px; |
| | | margin: 20px; |
| | | padding: 30px; |
| | | background: #ffffff; |
| | | border: 1px solid #dcdfe6; |
| | | -webkit-box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12), |
| | | 0 0 6px 0 rgba(0, 0, 0, 0.04); |
| | | } |
| | | |
| | | .el-tag + .el-tag { |
| | | margin-left: 10px; |
| | | } |
| | | |
| | | .button-new-tag { |
| | | margin-left: 10px; |
| | | height: 32px; |
| | | line-height: 30px; |
| | | padding-top: 0; |
| | | padding-bottom: 0; |
| | | } |
| | | |
| | | .input-new-tag { |
| | | width: 90px; |
| | | margin-left: 10px; |
| | | vertical-align: bottom; |
| | | } |
| | | |
| | | .drexamine { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | padding: 30px; |
| | | background: #daeaf5; |
| | | |
| | | img { |
| | | width: 100px; |
| | | height: 100px; |
| | | } |
| | | } |
| | | |
| | | .qrcode-dialo { |
| | | // text-align: center; |
| | | // display: flex; |
| | | margin: 20px; |
| | | padding: 30px; |
| | | background: #edf1f7; |
| | | border: 1px solid #dcdfe6; |
| | | -webkit-box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12), |
| | | 0 0 6px 0 rgba(0, 0, 0, 0.04); |
| | | |
| | | .topic-dev { |
| | | margin-bottom: 25px; |
| | | font-size: 20px !important; |
| | | |
| | | .dev-text { |
| | | margin-bottom: 10px; |
| | | } |
| | | } |
| | | } |
| | | ::v-deep.leftvlue .el-card__body { |
| | | background: #f2f8ff; |
| | | color: #324a9b; |
| | | } |
| | | ::v-deep.leftvlue .el-card__body:hover { |
| | | background: #3664d9; |
| | | color: #fff; |
| | | cursor: pointer; /* é¼ æ æ¬æµ®æ¶å为æå½¢ */ |
| | | } |
| | | ::v-deep.errleftvlue .el-card__body { |
| | | background: #fdd0d7; |
| | | } |
| | | ::v-deep.errleftvlue .el-card__body:hover { |
| | | background: #f88d96; |
| | | cursor: pointer; /* é¼ æ æ¬æµ®æ¶å为æå½¢ */ |
| | | } |
| | | ::v-deep.jgleftvlue .el-card__body:hover { |
| | | background: #f7f075; |
| | | cursor: pointer; /* é¼ æ æ¬æµ®æ¶å为æå½¢ */ |
| | | } |
| | | |
| | | ::v-deep.ysfleftvlue .el-card__body { |
| | | background: #d0fdd8; |
| | | } |
| | | ::v-deep.ysfleftvlue .el-card__body:hover { |
| | | background: #0abc54; |
| | | cursor: pointer; /* é¼ æ æ¬æµ®æ¶å为æå½¢ */ |
| | | } |
| | | .button-bb { |
| | | font-weight: 500; |
| | | background-color: #2ba05c; |
| | | padding: 5px; |
| | | border-radius: 1px; |
| | | color: #ffffff; |
| | | } |
| | | .button-xq { |
| | | font-weight: 500; |
| | | background-color: #409eff; |
| | | padding: 5px; |
| | | border-radius: 1px; |
| | | color: #ffffff; |
| | | } |
| | | .button-sc { |
| | | font-weight: 500; |
| | | background-color: #b3a21f; |
| | | padding: 5px; |
| | | border-radius: 1px; |
| | | color: #ffffff; |
| | | } |
| | | .button-zx { |
| | | background: #324a9b; |
| | | padding: 5px; |
| | | border-radius: 1px; |
| | | color: #ffffff; |
| | | } |
| | | |
| | | ::v-deep.el-radio-group { |
| | | span { |
| | | font-size: 24px; |
| | | } |
| | | } |
| | | .purple-button { |
| | | background-color: #7e22ce; |
| | | border-color: #7e22ce; |
| | | color: #fff; |
| | | } |
| | | |
| | | .purple-button:hover, |
| | | .purple-button:focus { |
| | | background-color: #9333ea; |
| | | border-color: #9333ea; |
| | | } |
| | | |
| | | .purple-button:active { |
| | | background-color: #6b21a8; |
| | | border-color: #6b21a8; |
| | | } |
| | | .button-textxga { |
| | | color: #de7897; |
| | | } |
| | | .purple-button.is-disabled { |
| | | background-color: #d8b4fe; |
| | | border-color: #d8b4fe; |
| | | opacity: 1; /* ä¿æç¦ç¨ç¶æéæåº¦ */ |
| | | } |
| | | // é项å使¾å¤§ |
| | | // ::v-deep.el-checkbox-group { |
| | | // span { |
| | | // font-size: 24px; |
| | | // } |
| | | // } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <!-- åå²éè®¿è®°å½ --> |
| | | <div class="app-container"> |
| | | <div class="leftvlue" style="margin-bottom: 20px"></div> |
| | | <el-row :gutter="20"> |
| | | <!--ç¨æ·æ°æ®--> |
| | | <el-form |
| | | :model="topqueryParams" |
| | | ref="queryForm" |
| | | size="small" |
| | | :inline="true" |
| | | v-show="showSearch" |
| | | label-width="98px" |
| | | > |
| | | <el-form-item label="ä»»å¡åç§°"> |
| | | <el-input |
| | | v-model="topqueryParams.taskName" |
| | | placeholder="è¯·éæ©ä»»å¡åç§°" |
| | | ></el-input> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="æ£è
å§å" prop="sendname"> |
| | | <el-input |
| | | v-model="topqueryParams.sendname" |
| | | placeholder="请è¾å
¥æ£è
å§å" |
| | | ></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="è¯æåç§°" prop="leavediagname"> |
| | | <el-input |
| | | v-model="topqueryParams.leavediagname" |
| | | placeholder="请è¾å
¥è¯æåç§°" |
| | | ></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="ä»»å¡ç¶æ" prop="status"> |
| | | <el-select v-model="topqueryParams.sendstate" placeholder="è¯·éæ©"> |
| | | <el-option |
| | | v-for="item in topicoptions" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | > |
| | | </el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item> |
| | | <el-button |
| | | type="primary" |
| | | icon="el-icon-search" |
| | | size="medium" |
| | | @click="handleQuery(1)" |
| | | >æç´¢</el-button |
| | | > |
| | | <el-button icon="el-icon-refresh" size="medium" @click="resetQuery" |
| | | >éç½®</el-button |
| | | > |
| | | </el-form-item> |
| | | </el-form> |
| | | <el-divider></el-divider> |
| | | <el-row :gutter="10" class="mb8"> |
| | | <el-col :span="1.5"> |
| | | <div class="documentf"> |
| | | <div class="document"> |
| | | <el-button |
| | | type="warning" |
| | | plain |
| | | icon="el-icon-upload2" |
| | | size="medium" |
| | | @click="handleExport" |
| | | >导åº</el-button |
| | | > |
| | | </div> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | <el-table |
| | | v-loading="loading" |
| | | :data="userList" |
| | | :row-class-name="tableRowClassName" |
| | | @selection-change="handleSelectionChange" |
| | | > |
| | | <el-table-column type="selection" width="50" align="center" /> |
| | | <el-table-column |
| | | label="ä»»å¡åç§°" |
| | | fixed |
| | | align="center" |
| | | key="taskName" |
| | | prop="taskName" |
| | | width="180" |
| | | /> |
| | | <!-- <el-table-column label="åºå·" fixed align="center" key="id" prop="id" /> --> |
| | | <el-table-column |
| | | label="å§å" |
| | | width="100" |
| | | align="center" |
| | | key="sendname" |
| | | prop="sendname" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | size="medium" |
| | | type="text" |
| | | @click=" |
| | | gettoken360(scope.row.sfzh, scope.row.drcode, scope.row.drname) |
| | | " |
| | | ><span class="button-textsc">{{ |
| | | scope.row.sendname |
| | | }}</span></el-button |
| | | > |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="ä»»å¡ç¶æ" |
| | | align="center" |
| | | key="sendstate" |
| | | prop="sendstate" |
| | | width="120" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-tooltip |
| | | class="item" |
| | | effect="dark" |
| | | :content="scope.row.remark" |
| | | placement="top-start" |
| | | > |
| | | <div v-if="scope.row.sendstate == 1"> |
| | | <el-tag type="primary" :disable-transitions="false" |
| | | >表åå·²é¢å</el-tag |
| | | > |
| | | </div> |
| | | <div v-if="scope.row.sendstate == 2"> |
| | | <el-tag type="primary" :disable-transitions="false" |
| | | >å¾
é访</el-tag |
| | | > |
| | | </div> |
| | | <div v-if="scope.row.sendstate == 3"> |
| | | <el-tag type="success" :disable-transitions="false" |
| | | >表åå·²åé</el-tag |
| | | > |
| | | </div> |
| | | <div v-if="scope.row.sendstate == 4"> |
| | | <el-tag type="info" :disable-transitions="false">䏿§è¡</el-tag> |
| | | </div> |
| | | <div v-if="scope.row.sendstate == 5"> |
| | | <el-tag type="danger" :disable-transitions="false" |
| | | >åé失败</el-tag |
| | | > |
| | | </div> |
| | | <div v-if="scope.row.sendstate == 6"> |
| | | <el-tag type="danger" :disable-transitions="false" |
| | | >已宿</el-tag |
| | | > |
| | | </div> |
| | | </el-tooltip> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="è¯æåç§°" |
| | | align="center" |
| | | key="leavediagname" |
| | | prop="leavediagname" |
| | | width="120" |
| | | :show-overflow-tooltip="true" |
| | | > |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="å¤çæè§" |
| | | align="center" |
| | | key="suggest" |
| | | prop="suggest" |
| | | width="120" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <dict-tag |
| | | :options="dict.type.sys_suggest" |
| | | :value="scope.row.suggest" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="é访人å" |
| | | align="center" |
| | | key="updateBy" |
| | | prop="updateBy" |
| | | width="120" |
| | | /> |
| | | <el-table-column |
| | | label="éè®¿å®ææ¶é´" |
| | | sortable |
| | | align="center" |
| | | prop="finishtime" |
| | | width="160" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span>{{ parseTime(scope.row.finishtime) }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | label="åºéè®¿æ¥æ" |
| | | width="200" |
| | | align="center" |
| | | key="visitTime" |
| | | prop="visitTime" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span>{{ formatTime(scope.row.visitTime) }}</span> |
| | | </template></el-table-column |
| | | > |
| | | <el-table-column |
| | | label="åºé¢æ¥æ" |
| | | width="200" |
| | | align="center" |
| | | key="endtime" |
| | | prop="endtime" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span>{{ formatTime(scope.row.endtime) }}</span> |
| | | </template></el-table-column |
| | | > |
| | | <el-table-column |
| | | label="åºé¢å¤©æ°" |
| | | width="120" |
| | | align="center" |
| | | key="endDay" |
| | | prop="endDay" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span>{{ scope.row.endDay ? scope.row.endDay + "天" : "" }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="身份è¯å·ç " |
| | | width="200" |
| | | align="center" |
| | | key="sfzh" |
| | | prop="sfzh" |
| | | /> |
| | | <el-table-column |
| | | label="èç³»çµè¯" |
| | | width="200" |
| | | align="center" |
| | | key="phone" |
| | | prop="phone" |
| | | /> |
| | | <el-table-column |
| | | label="责任æ¤å£«" |
| | | width="120" |
| | | align="center" |
| | | key="nurseName" |
| | | prop="nurseName" |
| | | /> |
| | | <el-table-column |
| | | label="主治å»ç" |
| | | width="120" |
| | | align="center" |
| | | key="drname" |
| | | prop="drname" |
| | | /> |
| | | |
| | | <!-- <el-table-column |
| | | label="ç
åå·" |
| | | align="center" |
| | | sortable |
| | | key="medicalRecordNo" |
| | | prop="medicalRecordNo" |
| | | width="120" |
| | | /> --> |
| | | |
| | | <!-- <el-table-column label="å¹´é¾" align="center" key="age" prop="age" /> --> |
| | | <!-- <el-table-column label="æ§å«"width="100" align="center" key="sex" prop="sex" /> --> |
| | | <!-- <el-table-column label="åºå·" align="center" key="badNo" prop="badNo" /> --> |
| | | <el-table-column |
| | | label="ç§å®¤" |
| | | align="center" |
| | | key="deptname" |
| | | prop="deptname" |
| | | width="120" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="ç
åº" |
| | | align="center" |
| | | key="leavehospitaldistrictname" |
| | | prop="leavehospitaldistrictname" |
| | | width="120" |
| | | > |
| | | </el-table-column> |
| | | |
| | | <!-- <el-table-column |
| | | label="ç¾ç
åç§°" |
| | | align="center" |
| | | key="icdName" |
| | | prop="icdName" |
| | | width="120" |
| | | :show-overflow-tooltip="true" |
| | | > |
| | | </el-table-column> --> |
| | | |
| | | <el-table-column |
| | | label="åºé¢é访模æ¿åç§°" |
| | | align="center" |
| | | key="templatename" |
| | | prop="templatename" |
| | | width="200" |
| | | /> |
| | | <el-table-column |
| | | label="任塿§è¡æ¹å¼" |
| | | align="center" |
| | | key="preachform" |
| | | prop="preachform" |
| | | width="160" |
| | | :show-overflow-tooltip="true" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span v-for="item in scope.row.preachform">{{ item }}ã </span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="ä»»å¡ç»æè¯´æ" |
| | | width="200" |
| | | align="center" |
| | | key="remark" |
| | | prop="remark" |
| | | > |
| | | <template slot-scope="scope" v-if="scope.row.remark"> |
| | | <el-tag |
| | | type="warning" |
| | | v-if="scope.row.sendstate != 5 && scope.row.sendstate != 4" |
| | | >{{ scope.row.remark }}</el-tag |
| | | > |
| | | <el-tag type="warning" v-else>{{ scope.row.remark }}</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="æä½" |
| | | align="center" |
| | | fixed="right" |
| | | width="200" |
| | | class-name="small-padding fixed-width" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <el-button size="medium" type="text" @click="Seedetails(scope.row)" |
| | | ><span class="button-zx" |
| | | ><i class="el-icon-s-order"></i>æ¥ç详æ
</span |
| | | ></el-button |
| | | > |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <pagination |
| | | v-show="total > 0" |
| | | :total="total" |
| | | :page.sync="topqueryParams.pageNum" |
| | | :limit.sync="topqueryParams.pageSize" |
| | | @pagination="getList" |
| | | /> |
| | | </el-row> |
| | | <!-- æ·»å æä¿®æ¹å½±åéè®¿å¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | :title="title" |
| | | :visible.sync="addalteropen" |
| | | width="700px" |
| | | append-to-body |
| | | > |
| | | <el-form ref="form" :model="form" label-width="100px"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12" |
| | | ><el-form-item label="ä»»å¡åç§°"> |
| | | <el-input v-model="form.name"></el-input> </el-form-item |
| | | ></el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="24" |
| | | ><el-form-item label="æå±ç§å®¤"> |
| | | <el-select v-model="form.region" placeholder="è¯·éæ©ç§å®¤"> |
| | | <el-option label="åºåä¸" value="shanghai"></el-option> |
| | | <el-option label="åºåäº" value="beijing"></el-option> |
| | | </el-select> </el-form-item></el-col |
| | | ></el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="24" |
| | | ><el-form-item label="é访类å"> |
| | | <el-select v-model="form.region" placeholder="è¯·éæ©é访类å"> |
| | | <el-option label="åºåä¸" value="shanghai"></el-option> |
| | | <el-option label="åºåäº" value="beijing"></el-option> |
| | | </el-select> </el-form-item |
| | | ></el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="æå¡æ¨¡å"> |
| | | <el-select v-model="form.region" placeholder="è¯·éæ©æ¨¡å"> |
| | | <el-option label="åºåä¸" value="shanghai"></el-option> |
| | | <el-option label="åºåäº" value="beijing"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="å½±åéè®¿è¦æ±"> |
| | | <el-input type="textarea" v-model="form.desc"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <div slot="footer" class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm">æ 交</el-button> |
| | | <el-button @click="cancel">è¿ å</el-button> |
| | | </div> |
| | | </el-dialog> |
| | | <!-- ä¿®æ¹åéæ¶é´å¯¹è¯æ¡ --> |
| | | <!-- 忬¡é访 --> |
| | | <el-dialog title="æ£è
忬¡é访" :visible.sync="dialogFormVisible"> |
| | | <el-form ref="form" :model="zcform" label-width="80px"> |
| | | <el-form-item label="æ£è
åç§°"> |
| | | <el-input style="width: 400px" v-model="zcform.name"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="ä»»å¡åç§°"> |
| | | <el-input style="width: 400px" v-model="zcform.name"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="é访æ¹å¼"> |
| | | <el-radio-group v-model="zcform.resource"> |
| | | <el-radio label="1">æ¬ç
åºé访</el-radio> |
| | | <el-radio label="2">é访ä¸å¿é访</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | <el-form-item label="å³å»åé"> |
| | | <el-switch v-model="zcform.delivery"></el-switch> |
| | | </el-form-item> |
| | | <el-form-item label="é访æ¶é´" v-if="!zcform.delivery"> |
| | | <el-col :span="11"> |
| | | <el-date-picker |
| | | type="date" |
| | | placeholder="éæ©æ¥æ" |
| | | v-model="zcform.date1" |
| | | style="width: 100%" |
| | | ></el-date-picker> |
| | | </el-col> |
| | | <el-col class="line" :span="2">-</el-col> |
| | | <el-col :span="11"> |
| | | <el-time-picker |
| | | placeholder="éæ©æ¶é´" |
| | | v-model="zcform.date2" |
| | | style="width: 100%" |
| | | ></el-time-picker> |
| | | </el-col> |
| | | </el-form-item> |
| | | </el-form> |
| | | <div slot="footer" class="dialog-footer"> |
| | | <el-button @click="dialogFormVisible = false">å æ¶</el-button> |
| | | <el-button type="primary" @click="dialogFormVisible = false" |
| | | >ç¡® å®</el-button |
| | | > |
| | | </div> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { |
| | | listUser, |
| | | getUser, |
| | | delUser, |
| | | addUser, |
| | | updateUser, |
| | | resetUserPwd, |
| | | changeUserStatus, |
| | | } from "@/api/system/user"; |
| | | import { |
| | | historservelist, |
| | | buidegetTasklist, |
| | | query360PatInfo, |
| | | } from "@/api/AiCentre/index"; |
| | | import Treeselect from "@riophae/vue-treeselect"; |
| | | import store from "@/store"; |
| | | import "@riophae/vue-treeselect/dist/vue-treeselect.css"; |
| | | |
| | | export default { |
| | | name: "Discharge", |
| | | dicts: ["sys_normal_disable", "sys_user_sex", "sys_yujing", "sys_suggest"], |
| | | components: { Treeselect }, |
| | | data() { |
| | | return { |
| | | // é®ç½©å± |
| | | loading: true, |
| | | // é䏿°ç» |
| | | ids: [], |
| | | // éå个ç¦ç¨ |
| | | single: true, |
| | | // éå¤ä¸ªç¦ç¨ |
| | | multiple: true, |
| | | // æ¾ç¤ºæç´¢æ¡ä»¶ |
| | | showSearch: true, |
| | | dialogFormVisible: false, |
| | | // æ»æ¡æ° |
| | | total: 0, |
| | | // ç¨æ·è¡¨æ ¼æ°æ® |
| | | userList: null, |
| | | // å¼¹åºå±æ é¢ |
| | | title: "æ°å¢å½±åé访", |
| | | // æ¯å¦æ¾ç¤ºä¿®æ¹ãæ·»å å¼¹åºå± |
| | | addalteropen: false, |
| | | // ä¿®æ¹åéæ¶é´å¯¹è¯æ¡ |
| | | modificationVisible: false, |
| | | // é¨é¨åç§° |
| | | deptName: undefined, |
| | | // é»è®¤å¯ç |
| | | initPassword: undefined, |
| | | // æ¥æèå´ |
| | | dateRange: [], |
| | | // å²ä½é项 |
| | | postOptions: [], |
| | | ruleForm: { |
| | | type: [], |
| | | }, |
| | | postData: { |
| | | XiaoXiTou: { |
| | | FaSongFCSJC: "ZJHES", |
| | | FaSongJGID: localStorage.getItem("orgid"), |
| | | FaSongJGMC: localStorage.getItem("orgname"), |
| | | FaSongSJ: "2025-01-09Â 17:29:36", |
| | | FaSongXTJC: "SUIFANGXT", |
| | | FaSongXTMC: "é访系ç»", |
| | | XiaoXiID: "5FA92AFB-9833-4608-87C7-F56A654AC171", |
| | | XiaoXiLX: "SC_LC_360STCX", |
| | | XiaoXiMC: "360 è§å¾æ¥è¯¢", |
| | | ZuHuID: localStorage.getItem("ZuHuID"), |
| | | ZuHuMC: localStorage.getItem("orgname"), |
| | | }, |
| | | YeWuXX: { |
| | | BingRenXX: { |
| | | ZhengJianHM: "", |
| | | ZhengJianLXDM: "01", |
| | | ZhengJianLXMC: "å±
æ°èº«ä»½è¯", |
| | | ZuZhiJGID: localStorage.getItem("orgid"), |
| | | ZuZhiJGMC: localStorage.getItem("orgname"), |
| | | }, |
| | | YongHuXX: { |
| | | XiTongID: "SUIFANGXT", |
| | | XiTongMC: "é访系ç»", |
| | | YongHuID: localStorage.getItem("YongHuID"), |
| | | YongHuXM: localStorage.getItem("YongHuXM"), |
| | | ZuZhiJGID: localStorage.getItem("orgid"), |
| | | ZuZhiJGMC: localStorage.getItem("orgname"), |
| | | idp: "lyra", |
| | | }, |
| | | }, |
| | | }, |
| | | zcform: {}, |
| | | dynamicTags: ["é项ä¸", "é项äº", "é项ä¸"], //é项 |
| | | inputVisible: false, |
| | | ycvalue: "", |
| | | yfsvalue: "", |
| | | inputValue: "", |
| | | preachform: "", |
| | | previewVisible: false, //å½±åé访é¢è§å¼¹æ¡ |
| | | radio: "", |
| | | radios: [], |
| | | previewtype: 2, //é¢è§å½±åé访类å |
| | | total: 0, // æ»æ¡æ° |
| | | ImportQuantity: 999, //导影åé访æ°é |
| | | //é¢è§å½±åéè®¿ä¿¡æ¯ |
| | | previewvalue: { |
| | | username: "è¿ä¸ªå»çå¯¹ä½ æä¹æ ·", |
| | | }, |
| | | value: [], |
| | | list: [], |
| | | |
| | | sourcetype: [ |
| | | { |
| | | value: 1, |
| | | label: "ç§å®¤", |
| | | children: [], |
| | | }, |
| | | { |
| | | value: 2, |
| | | label: "ç
åº", |
| | | children: [], |
| | | }, |
| | | { |
| | | value: 3, |
| | | label: "å
¨é¨", |
| | | }, |
| | | ], |
| | | loading: false, |
| | | cardlist: [ |
| | | { |
| | | name: "åºé¢æå¡æ»é", |
| | | value: 0, |
| | | }, |
| | | // { |
| | | // name: "æ£è
è¿æ»¤", |
| | | // value: 0, |
| | | // }, |
| | | { |
| | | name: "éé访", |
| | | value: 0, |
| | | }, |
| | | |
| | | // { |
| | | // name: "å¼å¸¸", |
| | | // value: 0, |
| | | // }, |
| | | { |
| | | name: "åé失败", |
| | | value: 0, |
| | | }, |
| | | { |
| | | name: "å¾
é访", |
| | | value: 0, |
| | | }, |
| | | // { |
| | | // name: "å·²åé", |
| | | // value: 0, |
| | | // }, |
| | | |
| | | // { |
| | | // name: "表åå·²åé", |
| | | // value: 0, |
| | | // }, |
| | | ], |
| | | |
| | | // 表ååæ° |
| | | form: { |
| | | phonenumber: "", |
| | | totagid: "", |
| | | types: "", |
| | | nickName: "", |
| | | qystatus: "", |
| | | btstatus: "", |
| | | }, |
| | | // æ¥è¯¢åæ° |
| | | topqueryParams: { |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | }, |
| | | propss: { multiple: true }, |
| | | options: [], |
| | | |
| | | topicoptions: [ |
| | | { |
| | | value: null, |
| | | label: "å
¨é¨", |
| | | }, |
| | | { |
| | | value: 1, |
| | | label: "表åå·²é¢å", |
| | | }, |
| | | { |
| | | value: 2, |
| | | label: "å¾
é访", |
| | | }, |
| | | { |
| | | value: 3, |
| | | label: "表åå·²åé", |
| | | }, |
| | | { |
| | | value: 4, |
| | | label: "䏿§è¡", |
| | | }, |
| | | { |
| | | value: 5, |
| | | label: "åé失败", |
| | | }, |
| | | { |
| | | value: 6, |
| | | label: "已宿", |
| | | }, |
| | | { |
| | | value: 7, |
| | | label: "è¶
æ¶", |
| | | }, |
| | | ], |
| | | topicoptionsyj: [ |
| | | { |
| | | value: 1, |
| | | label: "å¼å¸¸", |
| | | }, |
| | | { |
| | | value: 0, |
| | | label: "æ£å¸¸", |
| | | }, |
| | | ], |
| | | topicoptionssort: [ |
| | | { |
| | | value: 0, |
| | | label: "åºé¢æ¶é´(æ£åº)", |
| | | }, |
| | | { |
| | | value: 1, |
| | | label: "åºé¢æ¶é´(ååº)", |
| | | }, |
| | | { |
| | | value: 2, |
| | | label: "åéæ¶é´(æ£åº)", |
| | | }, |
| | | { |
| | | value: 3, |
| | | label: "åéæ¶é´(ååº)", |
| | | }, |
| | | { |
| | | value: 7, |
| | | label: "åºéè®¿æ¥æ(æ£åº)", |
| | | }, |
| | | { |
| | | value: 8, |
| | | label: "åºéè®¿æ¥æ(ååº)", |
| | | }, |
| | | ], |
| | | errtype: "", |
| | | leavehospitaldistrictcode: "", |
| | | serviceState: [], |
| | | checkboxlist: [], |
| | | // è¡¨åæ ¡éª |
| | | rules: {}, |
| | | }; |
| | | }, |
| | | watch: {}, |
| | | created() { |
| | | this.serviceState = store.getters.serviceState; |
| | | this.checkboxlist = store.getters.checkboxlist; |
| | | this.errtype = this.$route.query.errtype; |
| | | this.leavehospitaldistrictcode = |
| | | this.$route.query.leavehospitaldistrictcode; |
| | | this.sourcetype[0].children = store.getters.belongDepts.map((dept) => { |
| | | return { |
| | | label: dept.deptName, |
| | | value: dept.deptCode, |
| | | }; |
| | | }); |
| | | this.sourcetype[1].children = store.getters.belongWards.map((dept) => { |
| | | return { |
| | | label: dept.districtName, |
| | | value: dept.districtCode, |
| | | }; |
| | | }); |
| | | if (this.errtype) { |
| | | this.toleadExport(2); |
| | | } else { |
| | | this.getList(1); |
| | | } |
| | | this.getConfigKey("sys.user.initPassword").then((response) => { |
| | | this.initPassword = response.msg; |
| | | }); |
| | | }, |
| | | activated() { |
| | | this.getList(1); |
| | | }, |
| | | methods: { |
| | | /** æ¥è¯¢å½±åé访æå¡å表 */ |
| | | getList(refresh) { |
| | | // é»è®¤å
¨é¨ |
| | | |
| | | this.loading = true; |
| | | |
| | | historservelist(this.topqueryParams).then((response) => { |
| | | // this.userList = response.rows[0].serviceSubtaskList; |
| | | this.userList = response?.rows ?? []; |
| | | this.total = response.total; |
| | | this.loading = false; |
| | | this.userList.forEach((item) => { |
| | | let idArray = null; |
| | | if (item.endtime) { |
| | | item.endDay = this.daysBetween(item.endtime); |
| | | } |
| | | |
| | | if (item.preachform) { |
| | | if (item.endtime) { |
| | | item.preachformson = item.preachform; |
| | | idArray = item.preachform.split(","); |
| | | } |
| | | |
| | | item.preachform = idArray.map((value) => { |
| | | // æ¥æ¾id对åºç对象 |
| | | const item = this.checkboxlist.find( |
| | | (item) => item.value == value |
| | | ); |
| | | // 妿æ¾å°å¯¹åºçidï¼è¿ålabelå¼ï¼å¦åè¿ånull |
| | | return item ? item.label : null; |
| | | }); |
| | | } |
| | | }); |
| | | this.total = response.total; |
| | | }); |
| | | }, |
| | | //æ£è
360跳转 |
| | | gettoken360(sfzh, drcode, drname) { |
| | | // this.$modal.msgWarning('360åè½ææªå¼é'); |
| | | |
| | | this.postData.YeWuXX.BingRenXX.ZhengJianHM = sfzh; |
| | | |
| | | query360PatInfo(this.postData).then((res) => { |
| | | if (res.data.url) { |
| | | window.open(res.data.url, "_blank"); |
| | | // this.linkUrl = res.data.url; |
| | | } else { |
| | | this.$modal.msgWarning("360æ¥è¯¢æ ç»æ"); |
| | | } |
| | | }); |
| | | }, |
| | | buidegetTasklist(type) { |
| | | if (this.topqueryParams.searchscope == 3) { |
| | | this.topqueryParams.leaveldeptcodes = store.getters.belongDepts.map( |
| | | (obj) => obj.deptCode |
| | | ); |
| | | this.topqueryParams.leavehospitaldistrictcodes = |
| | | store.getters.belongWards.map((obj) => obj.districtCode); |
| | | } |
| | | // æ¥åå¼å¸¸è·³è½¬ |
| | | if (this.errtype) { |
| | | this.topqueryParams.leavehospitaldistrictcodes.push( |
| | | this.leavehospitaldistrictcode |
| | | ); |
| | | } |
| | | let obj = { |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | leavehospitaldistrictcodes: |
| | | this.topqueryParams.leavehospitaldistrictcodes, |
| | | sendstates: [2, 3], |
| | | leaveldeptcodes: this.topqueryParams.leaveldeptcodes, |
| | | }; |
| | | buidegetTasklist(obj).then((response) => { |
| | | this.userList = response.rows[0].serviceSubtaskList; |
| | | this.total = response.total; |
| | | if (refresh) { |
| | | this.cardlist[0].value = |
| | | Number(response.rows[0].wzx) + Number(response.rows[0].ysf); |
| | | this.cardlist[1].value = response.rows[0].wzx; |
| | | this.cardlist[2].value = response.rows[0].ysf; |
| | | this.ycvalue = response.rows[0].yc; |
| | | this.cardlist[3].value = response.rows[0].fssb; |
| | | this.cardlist[4].value = response.rows[0].dsf; |
| | | // this.cardlist[5].value = response.rows[0].yfs2; |
| | | this.yfsvalue = response.rows[0].yfs; |
| | | } |
| | | this.loading = false; |
| | | this.userList.forEach((item) => { |
| | | let idArray = null; |
| | | if (item.endtime) { |
| | | item.endDay = this.daysBetween(item.endtime); |
| | | } |
| | | |
| | | if (item.preachform) { |
| | | if (item.endtime) { |
| | | item.preachformson = item.preachform; |
| | | idArray = item.preachform.split(","); |
| | | } |
| | | |
| | | item.preachform = idArray.map((value) => { |
| | | // æ¥æ¾id对åºç对象 |
| | | const item = this.checkboxlist.find( |
| | | (item) => item.value == value |
| | | ); |
| | | // 妿æ¾å°å¯¹åºçidï¼è¿ålabelå¼ï¼å¦åè¿ånull |
| | | return item ? item.label : null; |
| | | }); |
| | | } |
| | | }); |
| | | this.total = response.total; |
| | | }); |
| | | }, |
| | | // æ¥çé¨è¯é访详æ
|
| | | Referencequestion(row) { |
| | | this.previewVisible = true; |
| | | }, |
| | | // æ·»å å¼¹æ¡æç´¢ |
| | | remoteMethod(query) { |
| | | if (query !== "") { |
| | | this.loading = true; |
| | | setTimeout(() => { |
| | | this.loading = false; |
| | | this.options = this.list.filter((item) => { |
| | | return item.label.toLowerCase().indexOf(query.toLowerCase()) > -1; |
| | | }); |
| | | }, 200); |
| | | } else { |
| | | this.options = []; |
| | | } |
| | | }, |
| | | // å½±åéè®¿ç¶æä¿®æ¹ |
| | | handleStatusChange(row) { |
| | | let text = row.status === "0" ? "å¯ç¨" : "åç¨"; |
| | | this.$modal |
| | | .confirm('确认è¦"' + text + '""' + row.userName + '"ç¨æ·åï¼') |
| | | .then(function () { |
| | | return changeUserStatus(row.userId, row.status); |
| | | }) |
| | | .then(() => { |
| | | this.$modal.msgSuccess(text + "æå"); |
| | | }) |
| | | .catch(function () { |
| | | row.status = row.status === "0" ? "1" : "0"; |
| | | }); |
| | | }, |
| | | // åæ¶æé® |
| | | cancel() { |
| | | this.addalteropen = false; |
| | | this.reset(); |
| | | }, |
| | | // 表åéç½® |
| | | reset() { |
| | | this.form = { |
| | | userId: undefined, |
| | | deptId: undefined, |
| | | userName: undefined, |
| | | nickName: undefined, |
| | | password: undefined, |
| | | phonenumber: undefined, |
| | | email: undefined, |
| | | sex: undefined, |
| | | status: "0", |
| | | remark: undefined, |
| | | postIds: [], |
| | | roleIds: [], |
| | | }; |
| | | this.resetForm("form"); |
| | | }, |
| | | /** æç´¢æé®æä½ */ |
| | | handleQuery(refresh) { |
| | | if (this.topqueryParams.searchscope == 3) { |
| | | this.topqueryParams.leaveldeptcodes = store.getters.belongDepts.map( |
| | | (obj) => obj.deptCode |
| | | ); |
| | | this.topqueryParams.leavehospitaldistrictcodes = |
| | | store.getters.belongWards.map((obj) => obj.districtCode); |
| | | } |
| | | this.topqueryParams.pageNum = 1; |
| | | this.topqueryParams.startOutHospTime = this.dateRange[0]; |
| | | this.topqueryParams.endOutHospTime = this.dateRange[1]; |
| | | |
| | | this.getList(refresh); |
| | | }, |
| | | // æ£è
èå´å¤ç |
| | | handleChange(value) { |
| | | let type = value[0]; |
| | | let code = value.slice(-1)[0]; |
| | | this.topqueryParams.leavehospitaldistrictcodes = []; |
| | | this.topqueryParams.leaveldeptcodes = []; |
| | | |
| | | if (type == 1) { |
| | | this.topqueryParams.leaveldeptcodes.push(code); |
| | | this.topqueryParams.leavehospitaldistrictcodes = []; |
| | | this.topqueryParams.searchscope = 1; |
| | | } else if (type == 2) { |
| | | this.topqueryParams.leavehospitaldistrictcodes.push(code); |
| | | this.topqueryParams.leaveldeptcodes = []; |
| | | this.topqueryParams.searchscope = 2; |
| | | } else { |
| | | this.topqueryParams.searchscope = 3; |
| | | } |
| | | }, |
| | | /** éç½®æé®æä½ */ |
| | | resetQuery() { |
| | | this.dateRange = []; |
| | | this.topqueryParams = { |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | serviceType: 13, |
| | | sort: 2, |
| | | searchscope: 2, |
| | | sendstate: 2, |
| | | scopetype: [], |
| | | leaveldeptcodes: [], |
| | | leavehospitaldistrictcodes: [], |
| | | }; |
| | | this.handleQuery(1); |
| | | }, |
| | | // å¤éæ¡é䏿°æ® |
| | | handleSelectionChange(selection) { |
| | | this.ids = selection.map((item) => item.userId); |
| | | this.single = selection.length != 1; |
| | | this.multiple = !selection.length; |
| | | }, |
| | | //å é¤é项 |
| | | handleClose(tag) { |
| | | this.dynamicTags.splice(this.dynamicTags.indexOf(tag), 1); |
| | | }, |
| | | //è§¦åæ°å¢è¾å
¥ |
| | | showInput() { |
| | | this.inputVisible = true; |
| | | this.$nextTick((_) => { |
| | | this.$refs.saveTagInput.$refs.input.focus(); |
| | | }); |
| | | }, |
| | | onthatday() { |
| | | this.topqueryParams.startSendDateTime = this.getCurrentDate(); |
| | | this.topqueryParams.endSendDateTime = this.getCurrentDate(); |
| | | this.getList(1); |
| | | }, |
| | | getCurrentDate() { |
| | | const now = new Date(); |
| | | return now.toISOString().slice(0, 10); // æªåå10个å符ï¼å³ YYYY-MM-DD |
| | | }, |
| | | //è·å失å»ç¦ç¹è§¦å |
| | | handleInputConfirm() { |
| | | let inputValue = this.inputValue; |
| | | if (inputValue) { |
| | | this.dynamicTags.push(inputValue); |
| | | } |
| | | this.inputVisible = false; |
| | | this.inputValue = ""; |
| | | }, |
| | | /** æ°å¢æé®æä½ */ |
| | | handleAdd() { |
| | | this.$router.push({ |
| | | path: "/followvisit/QuestionnaireTask", |
| | | query: { |
| | | type: 2, |
| | | serviceType: 13, |
| | | }, |
| | | }); |
| | | }, |
| | | |
| | | /** éç½®å¯ç æé®æä½ */ |
| | | handleResetPwd(row) { |
| | | this.$prompt('请è¾å
¥"' + row.userName + '"çæ°å¯ç ', "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | closeOnClickModal: false, |
| | | inputPattern: /^.{5,20}$/, |
| | | inputErrorMessage: "ç¨æ·å¯ç é¿åº¦å¿
é¡»ä»äº 5 å 20 ä¹é´", |
| | | }) |
| | | .then(({ value }) => { |
| | | resetUserPwd(row.userId, value).then((response) => { |
| | | this.$modal.msgSuccess("ä¿®æ¹æåï¼æ°å¯ç æ¯ï¼" + value); |
| | | }); |
| | | }) |
| | | .catch(() => {}); |
| | | }, |
| | | |
| | | /** æäº¤æé® */ |
| | | submitForm: function () { |
| | | this.$refs["form"].validate((valid) => { |
| | | if (valid) { |
| | | if (this.form.userId != undefined) { |
| | | updateUser(this.form).then((response) => { |
| | | this.$modal.msgSuccess("ä¿®æ¹æå"); |
| | | this.open = false; |
| | | this.getList(1); |
| | | }); |
| | | } else { |
| | | addUser(this.form).then((response) => { |
| | | this.$modal.msgSuccess("æ°å¢æå"); |
| | | this.open = false; |
| | | this.getList(1); |
| | | }); |
| | | } |
| | | } |
| | | }); |
| | | }, |
| | | /** å é¤æé®æä½ */ |
| | | handleDelete(row) { |
| | | const userIds = row.userId || this.ids; |
| | | this.$modal |
| | | .confirm('æ¯å¦ç¡®è®¤å é¤ç¨æ·ç¼å·ä¸º"' + userIds + '"çæ°æ®é¡¹ï¼') |
| | | .then(function () { |
| | | return delUser(userIds); |
| | | }) |
| | | .then(() => { |
| | | this.getList(1); |
| | | this.$modal.msgSuccess("å 餿å"); |
| | | }) |
| | | .catch(() => {}); |
| | | }, |
| | | // å
¨é¨åæ¢ |
| | | AllStop() { |
| | | this.$modal |
| | | .confirm("æ¯å¦åæ¢å
¨é¨ä»»å¡ï¼") |
| | | .then(function () { |
| | | return console.log("忢æå"); |
| | | }) |
| | | .then(() => { |
| | | this.getList(1); |
| | | this.$modal.msgWarning("忢æå"); |
| | | }) |
| | | .catch(() => {}); |
| | | }, |
| | | // å
¨é¨å¼å§ |
| | | AllStarted() { |
| | | this.$modal |
| | | .confirm("æ¯å¦å¼å¯å
¨é¨ä»»å¡ï¼") |
| | | .then(function () { |
| | | return console.log("å¼å¯æå"); |
| | | }) |
| | | .then(() => { |
| | | this.getList(1); |
| | | this.$modal.msgSuccess("å¼å¯æå"); |
| | | }) |
| | | .catch(() => {}); |
| | | }, |
| | | // ä»»å¡éç½® |
| | | TaskReset() { |
| | | this.$modal |
| | | .confirm("æ¯å¦éç½®éä¸çä»»å¡é¡¹ï¼") |
| | | .then(function () { |
| | | return console.log("é䏿å"); |
| | | }) |
| | | .then(() => { |
| | | this.getList(1); |
| | | this.$modal.msgSuccess("éç½®æå"); |
| | | }) |
| | | .catch(() => {}); |
| | | }, |
| | | // 设置åéæ¶é´ |
| | | Sendtimesetting() { |
| | | this.modificationVisible = true; |
| | | }, |
| | | // 跳转详æ
页 |
| | | Seedetails(row) { |
| | | let type = ""; |
| | | console.log(row, "rwo"); |
| | | if (row.type == 1) { |
| | | type = 1; |
| | | } |
| | | this.$router.push({ |
| | | path: "/followvisit/record/detailpage/", |
| | | query: { |
| | | taskid: row.taskid, |
| | | patid: row.patid, |
| | | id: row.id, |
| | | Voicetype: type, |
| | | again: 1, |
| | | }, |
| | | }); |
| | | }, |
| | | // 忬¡é访 |
| | | followupvisit() { |
| | | this.dialogFormVisible = true; |
| | | }, |
| | | onSubmit() {}, |
| | | |
| | | // ä¾¿æ·æé® |
| | | toleadExport(too) { |
| | | if (too == 1) { |
| | | this.topqueryParams.sendstate = 4; |
| | | this.topqueryParams.excep = null; |
| | | } else if (too == 2) { |
| | | this.topqueryParams.excep = 1; |
| | | } |
| | | this.handleQuery(); |
| | | }, |
| | | /** å¯¼åºæé®æä½ */ |
| | | handleExport() { |
| | | console.log(this.topqueryParams); |
| | | |
| | | this.download( |
| | | // "smartor/serviceSubtask/export", |
| | | "smartor/serviceSubtask/getSubtaskByDiagnameExport", |
| | | { |
| | | ...this.topqueryParams, |
| | | }, |
| | | `user_${new Date().getTime()}.xlsx` |
| | | ); |
| | | }, |
| | | // å¼å¸¸å渲æ |
| | | tableRowClassName({ row, rowIndex }) { |
| | | if (row.excep == 1) { |
| | | return "warning-row"; |
| | | } |
| | | return ""; |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .el-button--primary.is-plain { |
| | | color: #ffffff; |
| | | background: #409eff; |
| | | border-color: #4fabe9; |
| | | } |
| | | |
| | | .document { |
| | | // width: 100px; |
| | | height: 50px; |
| | | } |
| | | ::v-deep.el-table .warning-row { |
| | | background: #eec4c4; |
| | | } |
| | | |
| | | .documentf { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | } |
| | | |
| | | .download { |
| | | text-align: center; |
| | | |
| | | .el-upload__tip { |
| | | font-size: 23px; |
| | | } |
| | | |
| | | .el-upload__text { |
| | | font-size: 23px; |
| | | } |
| | | } |
| | | |
| | | .uploading { |
| | | margin-top: 20px; |
| | | margin: 20px; |
| | | padding: 30px; |
| | | background: #ffffff; |
| | | border: 1px solid #dcdfe6; |
| | | -webkit-box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12), |
| | | 0 0 6px 0 rgba(0, 0, 0, 0.04); |
| | | } |
| | | |
| | | .el-tag + .el-tag { |
| | | margin-left: 10px; |
| | | } |
| | | |
| | | .button-new-tag { |
| | | margin-left: 10px; |
| | | height: 32px; |
| | | line-height: 30px; |
| | | padding-top: 0; |
| | | padding-bottom: 0; |
| | | } |
| | | |
| | | .input-new-tag { |
| | | width: 90px; |
| | | margin-left: 10px; |
| | | vertical-align: bottom; |
| | | } |
| | | |
| | | .drexamine { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | padding: 30px; |
| | | background: #daeaf5; |
| | | |
| | | img { |
| | | width: 100px; |
| | | height: 100px; |
| | | } |
| | | } |
| | | |
| | | .qrcode-dialo { |
| | | // text-align: center; |
| | | // display: flex; |
| | | margin: 20px; |
| | | padding: 30px; |
| | | background: #edf1f7; |
| | | border: 1px solid #dcdfe6; |
| | | -webkit-box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12), |
| | | 0 0 6px 0 rgba(0, 0, 0, 0.04); |
| | | |
| | | .topic-dev { |
| | | margin-bottom: 25px; |
| | | font-size: 20px !important; |
| | | |
| | | .dev-text { |
| | | margin-bottom: 10px; |
| | | } |
| | | } |
| | | } |
| | | ::v-deep.leftvlue .el-card__body { |
| | | background: #f2f8ff; |
| | | color: #324a9b; |
| | | } |
| | | ::v-deep.leftvlue .el-card__body:hover { |
| | | background: #3664d9; |
| | | color: #fff; |
| | | cursor: pointer; /* é¼ æ æ¬æµ®æ¶å为æå½¢ */ |
| | | } |
| | | ::v-deep.errleftvlue .el-card__body { |
| | | background: #fdd0d7; |
| | | } |
| | | ::v-deep.errleftvlue .el-card__body:hover { |
| | | background: #f88d96; |
| | | cursor: pointer; /* é¼ æ æ¬æµ®æ¶å为æå½¢ */ |
| | | } |
| | | |
| | | ::v-deep.ysfleftvlue .el-card__body { |
| | | background: #d0fdd8; |
| | | } |
| | | ::v-deep.ysfleftvlue .el-card__body:hover { |
| | | background: #8df8a4; |
| | | cursor: pointer; /* é¼ æ æ¬æµ®æ¶å为æå½¢ */ |
| | | } |
| | | .button-bb { |
| | | font-weight: 500; |
| | | background-color: #2ba05c; |
| | | padding: 5px; |
| | | border-radius: 1px; |
| | | color: #ffffff; |
| | | } |
| | | .button-xq { |
| | | font-weight: 500; |
| | | background-color: #409eff; |
| | | padding: 5px; |
| | | border-radius: 1px; |
| | | color: #ffffff; |
| | | } |
| | | .button-sc { |
| | | font-weight: 500; |
| | | background-color: #b3a21f; |
| | | padding: 5px; |
| | | border-radius: 1px; |
| | | color: #ffffff; |
| | | } |
| | | .button-zx { |
| | | background: #4fabe9; |
| | | padding: 5px; |
| | | border-radius: 1px; |
| | | color: #ffffff; |
| | | } |
| | | |
| | | ::v-deep.el-radio-group { |
| | | span { |
| | | font-size: 24px; |
| | | } |
| | | } |
| | | |
| | | // é项å使¾å¤§ |
| | | // ::v-deep.el-checkbox-group { |
| | | // span { |
| | | // font-size: 24px; |
| | | // } |
| | | // } |
| | | </style> |
| | |
| | | ></el-input> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="é¨è¯æ¶é´"> |
| | | <el-form-item label="æå¡æ¶é´"> |
| | | <el-date-picker |
| | | v-model="dateRange" |
| | | style="width: 240px" |
| | |
| | | <el-col :span="1.5"> |
| | | <el-button |
| | | type="primary" |
| | | icon="el-icon-plus" |
| | | icon="el-icon-plus" |
| | | size="medium" |
| | | @click="handleAdd" |
| | | >æ°å¢</el-button |
| | |
| | | >åé失败</el-tag |
| | | > |
| | | </div> |
| | | <div v-if="scope.row.sendstate == 6"> |
| | | <div v-if="scope.row.sendstate == 6"> |
| | | <el-tag type="success" :disable-transitions="false" |
| | | >已宿</el-tag |
| | | > |
| | | </div> |
| | | <div v-if="scope.row.sendstate == 7"> |
| | | <el-tag type="danger" :disable-transitions="false" |
| | | >è¶
æ¶</el-tag |
| | | > |
| | | </div> |
| | | </el-tooltip> |
| | |
| | | label="åºéè®¿æ¥æ" |
| | | width="200" |
| | | align="center" |
| | | key="longSendTime" |
| | | prop="longSendTime" |
| | | key="visitTime" |
| | | prop="visitTime" |
| | | > |
| | | <template slot-scope="scope"> |
| | | <span>{{ formatTime(scope.row.longSendTime) }}</span> |
| | | <span>{{ formatTime(scope.row.visitTime) }}</span> |
| | | </template></el-table-column |
| | | > |
| | | <el-table-column |
| | |
| | | /> |
| | | |
| | | <!-- <el-table-column |
| | | label="é¨è¯å¤©æ°" |
| | | label="æå¡å¤©æ°" |
| | | width="120" |
| | | align="center" |
| | | key="endDay" |
| | |
| | | /> |
| | | |
| | | <el-table-column |
| | | label="é¨è¯é访模æ¿åç§°" |
| | | label="æå¡é访模æ¿åç§°" |
| | | align="center" |
| | | key="templatename" |
| | | prop="templatename" |
| | |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row > |
| | | <el-row> |
| | | <el-col :span="8"> |
| | | <el-form-item label="è¿æ»¤å»ç" width="100" prop="filterDrname"> |
| | | <el-input |
| | |
| | | <!-- <el-form-item label="å³å»åé"> |
| | | <el-switch v-model="zcform.delivery"></el-switch> |
| | | </el-form-item> --> |
| | | <el-form-item label="é¨è¯æ¶é´"> |
| | | <el-form-item label="æå¡æ¶é´"> |
| | | <el-input |
| | | style="width: 400px" |
| | | disabled |
| | |
| | | loading: false, |
| | | cardlist: [ |
| | | { |
| | | name: "é¨è¯æå¡æ»é", |
| | | name: "æå¡è·è¸ªæ»é", |
| | | value: 0, |
| | | }, |
| | | // { |
| | |
| | | topicoptionssort: [ |
| | | { |
| | | value: 0, |
| | | label: "é¨è¯æ¶é´(æ£åº)", |
| | | label: "æå¡æ¶é´(æ£åº)", |
| | | }, |
| | | { |
| | | value: 1, |
| | | label: "é¨è¯æ¶é´(ååº)", |
| | | label: "æå¡æ¶é´(ååº)", |
| | | }, |
| | | { |
| | | value: 2, |
| | |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | sendstate: 2, |
| | | sort: localStorage.getItem("orgname") == "丽水å¸ä¸å»é¢" ? 8 : 2, //0 é¨è¯æ¶é´(æ£åº) 1 é¨è¯æ¶é´(ååº) 2 åéæ¶é´(æ£åº) 3 åéæ¶é´(ååº) 7åºéè®¿æ¥æ(ååº) åºéè®¿æ¥æ(æ£åº) |
| | | sort: localStorage.getItem("orgname") == "丽水å¸ä¸å»é¢" ? 8 : 2, //0 æå¡æ¶é´(æ£åº) 1 æå¡æ¶é´(ååº) 2 åéæ¶é´(æ£åº) 3 åéæ¶é´(ååº) 7åºéè®¿æ¥æ(ååº) åºéè®¿æ¥æ(æ£åº) |
| | | serviceType: 3, |
| | | searchscope: 3, |
| | | visitCount: 2, |
| | | scopetype: [], |
| | | visitDeptCodes: [], |
| | | leaveldeptcodes:[], |
| | | // leaveldeptcodes:[], |
| | | leavehospitaldistrictcodes: [], |
| | | }, |
| | | propss: { multiple: true }, |
| | |
| | | value: 4, |
| | | label: "䏿§è¡", |
| | | }, |
| | | { |
| | | { |
| | | value: 5, |
| | | label: "åé失败", |
| | | }, |
| | | { |
| | | value: 6, |
| | | label: "已宿", |
| | | }, |
| | | { |
| | | value: 7, |
| | | label: "è¶
æ¶", |
| | | }, |
| | | ], |
| | | sextype: [ |
| | |
| | | this.topqueryParams.visitDeptCodes = store.getters.belongDepts.map( |
| | | (obj) => obj.deptCode |
| | | ); |
| | | this.topqueryParams.leaveldeptcodes = store.getters.belongDepts.map( |
| | | (obj) => obj.deptCode |
| | | ); |
| | | // this.topqueryParams.leaveldeptcodes = store.getters.belongDepts.map( |
| | | // (obj) => obj.deptCode |
| | | // ); |
| | | this.topqueryParams.leavehospitaldistrictcodes = |
| | | store.getters.belongWards.map((obj) => obj.districtCode); |
| | | } |
| | |
| | | this.loading = true; |
| | | if ( |
| | | this.topqueryParams.leavehospitaldistrictcodes[0] && |
| | | this.topqueryParams.visitDeptCodes[0]&&this.topqueryParams.leaveldeptcodes[0] |
| | | this.topqueryParams.visitDeptCodes[0] |
| | | ) { |
| | | this.topqueryParams.deptOrDistrict = 2; |
| | | this.topqueryParams.deptOrDistrict = 4; |
| | | } else { |
| | | this.topqueryParams.deptOrDistrict = 1; |
| | | } |
| | |
| | | }); |
| | | }, |
| | | affiliation() { |
| | | this.topqueryParams.managementDoctorCode= store.getters.hisUserId; |
| | | this.topqueryParams.managementDoctorCode = store.getters.hisUserId; |
| | | |
| | | this.getList(1); |
| | | }, |
| | |
| | | this.topqueryParams.visitDeptCodes = store.getters.belongDepts.map( |
| | | (obj) => obj.deptCode |
| | | ); |
| | | this.topqueryParams.leaveldeptcodes = store.getters.belongDepts.map( |
| | | (obj) => obj.deptCode |
| | | ); |
| | | // this.topqueryParams.leaveldeptcodes = store.getters.belongDepts.map( |
| | | // (obj) => obj.deptCode |
| | | // ); |
| | | this.topqueryParams.leavehospitaldistrictcodes = |
| | | store.getters.belongWards.map((obj) => obj.districtCode); |
| | | } |
| | |
| | | this.topqueryParams.leavehospitaldistrictcodes, |
| | | sendstates: [2, 3], |
| | | visitDeptCodes: this.topqueryParams.visitDeptCodes, |
| | | leaveldeptcodes: this.topqueryParams.leaveldeptcodes, |
| | | // leaveldeptcodes: this.topqueryParams.leaveldeptcodes, |
| | | }; |
| | | buidegetTasklist(obj).then((response) => { |
| | | this.userList = response.rows[0].serviceSubtaskList; |
| | |
| | | this.total = response.total; |
| | | }); |
| | | }, |
| | | // æ¥çé¨è¯é访详æ
|
| | | // æ¥çæå¡é访详æ
|
| | | Referencequestion(row) { |
| | | this.previewVisible = true; |
| | | }, |
| | |
| | | this.topqueryParams.visitDeptCodes = store.getters.belongDepts.map( |
| | | (obj) => obj.deptCode |
| | | ); |
| | | this.topqueryParams.leaveldeptcodes = store.getters.belongDepts.map( |
| | | (obj) => obj.deptCode |
| | | ); |
| | | // this.topqueryParams.leaveldeptcodes = store.getters.belongDepts.map( |
| | | // (obj) => obj.deptCode |
| | | // ); |
| | | this.topqueryParams.leavehospitaldistrictcodes = |
| | | store.getters.belongWards.map((obj) => obj.districtCode); |
| | | } |
| | |
| | | let code = value.slice(-1)[0]; |
| | | this.topqueryParams.leavehospitaldistrictcodes = []; |
| | | this.topqueryParams.visitDeptCodes = []; |
| | | this.topqueryParams.leaveldeptcodes = []; |
| | | // this.topqueryParams.leaveldeptcodes = []; |
| | | if (type == 1) { |
| | | this.topqueryParams.visitDeptCodes.push(code); |
| | | this.topqueryParams.leaveldeptcodes.push(code); |
| | | // this.topqueryParams.leaveldeptcodes.push(code); |
| | | this.topqueryParams.leavehospitaldistrictcodes = []; |
| | | this.topqueryParams.searchscope = 1; |
| | | } else if (type == 2) { |
| | | this.topqueryParams.leavehospitaldistrictcodes.push(code); |
| | | this.topqueryParams.visitDeptCodes = []; |
| | | this.topqueryParams.leaveldeptcodes = []; |
| | | // this.topqueryParams.leaveldeptcodes = []; |
| | | this.topqueryParams.searchscope = 2; |
| | | } else { |
| | | this.topqueryParams.searchscope = 3; |
| | |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | sendstate: 2, |
| | | sort: 2, //0 é¨è¯æ¶é´(æ£åº) 1 é¨è¯æ¶é´(ååº) 2 åéæ¶é´(æ£åº) 3 åéæ¶é´(ååº) |
| | | sort: 2, //0 æå¡æ¶é´(æ£åº) 1 æå¡æ¶é´(ååº) 2 åéæ¶é´(æ£åº) 3 åéæ¶é´(ååº) |
| | | serviceType: 3, |
| | | searchscope: 3, |
| | | visitCount: 2, |
| | | scopetype: [], |
| | | visitDeptCodes: [], |
| | | leaveldeptcodes:[], |
| | | // leaveldeptcodes:[], |
| | | leavehospitaldistrictcodes: [], |
| | | }; |
| | | this.handleQuery(1); |
| | |
| | | .then((response) => { |
| | | console.log(response); |
| | | }) |
| | | .then(() => { |
| | | .then(() => { |
| | | this.getList(1); |
| | | this.$modal.msgSuccess("æ£è
è¿æ»¤æå"); |
| | | }); |
| | |
| | | }, |
| | | // 跳转详æ
页 |
| | | Seedetails(row) { |
| | | let type = ""; |
| | | let type = ""; |
| | | console.log(row, "rwo"); |
| | | if (row.type == 1) { |
| | | type = 1; |
| | | } |
| | | if (row.type == 1) { |
| | | type = 1; |
| | | } |
| | | this.$router.push({ |
| | | path: "/followvisit/record/detailpage/", |
| | | query: { |
| | |
| | | this.zcform.remark = |
| | | this.zcform.remark + "ã" + this.getCurrentTime() + "ã"; |
| | | let form = structuredClone(this.zcform); |
| | | form.longSendTime = this.formatTime(form.date1); |
| | | form.visitTime = this.formatTime(form.date1); |
| | | form.finishtime = ""; |
| | | if (form.resource) { |
| | | if (form.resource == 2) { |
| | |
| | | } |
| | | } |
| | | ::v-deep.leftvlue .el-card__body { |
| | | background: #F2F8FF; |
| | | color: #324A9B; |
| | | background: #f2f8ff; |
| | | color: #324a9b; |
| | | } |
| | | ::v-deep.leftvlue .el-card__body:hover { |
| | | background: #3664D9; |
| | | background: #3664d9; |
| | | color: #fff; |
| | | cursor: pointer; /* é¼ æ æ¬æµ®æ¶å为æå½¢ */ |
| | | } |
| src/views/followvisit/SpecificDisease/index.vue
src/views/followvisit/Tracking/index.vue
src/views/followvisit/again/index.vue
src/views/followvisit/complaint/index.vue
src/views/followvisit/discharge/index.vue
src/views/followvisit/discharge/js/prototype.js
src/views/followvisit/discharge/outpatientService.vue
src/views/followvisit/mzsatisfaction/index.vue
src/views/followvisit/outpatient/index.vue
src/views/followvisit/record/TracingInfo/index.vue
src/views/followvisit/record/detailpage/index copy.vue
src/views/followvisit/record/detailpage/index.vue
src/views/followvisit/record/index.vue
src/views/followvisit/record/physical/index.vue
src/views/followvisit/satisfaction/index.vue
src/views/followvisit/technology/index.vue
src/views/followvisit/zbAgain/index.vue
src/views/followvisit/zysatisfaction/index.vue
src/views/index.vue
src/views/knowledge/questionbank/particulars/index.vue
src/views/login-sy.vue
src/views/login.vue
src/views/outsideChainwtnew.vue
src/views/patient/patient/AwaitingAdmission.vue
src/views/patient/patient/behospitalized.vue
src/views/patient/patient/hospital.vue
src/views/patient/patient/indexls.vue
src/views/patient/physical/index.vue
src/views/patient/propaganda/Missioncreation.vue
src/views/patient/propaganda/QuestionnaireTask.vue
src/views/patient/propaganda/index.vue
src/views/patient/propaganda/particty.vue
src/views/patient/questionnaire/index.vue
src/views/patient/shadow/index.vue
src/views/patient/subsequent/index.vue
src/views/repositoryai/templateku/configurat/index.vue
src/views/sfstatistics/ProblemStatistics/index.vue
src/views/sfstatistics/percentage/index.vue
src/views/sfstatistics/percentage/satisfaction.vue
src/views/system/user/index.vue
vue.config.js
xinhua.zip (已删除) |