Merge remote-tracking branch 'origin/dev_ai' into ywx
| | |
| | | "jsencrypt": "3.3.2", |
| | | "nprogress": "0.2.0", |
| | | "pinia": "2.1.7", |
| | | "qrcode": "^1.5.4", |
| | | "sortablejs": "^1.15.6", |
| | | "splitpanes": "3.1.5", |
| | | "vue": "3.4.31", |
| | | "vue-cropper": "1.1.1", |
| | | "vue-esign": "^1.1.4", |
| | | "vue-router": "4.4.0", |
| | | "vuedraggable": "4.1.0" |
| | | }, |
¶Ô±ÈÐÂÎļþ |
| | |
| | | // ç¨æ°´ç®¡ç |
| | | import request from "@/utils/request"; |
| | | |
| | | // ç¨æ°´è®¾å¤-å页æ¥è¯¢ |
| | | export function waterEquipmentListPage(query) { |
| | | return request({ |
| | | url: '/waterRecord/listPage', |
| | | method: 'get', |
| | | params: query, |
| | | }) |
| | | } |
| | | |
| | | // ç¨æ°´è¶å¿-å页æ¥è¯¢ |
| | | export function listPageByWaterTrend(query) { |
| | | return request({ |
| | | url: '/waterRecord/listPageByTrend', |
| | | method: 'get', |
| | | params: query, |
| | | }) |
| | | } |
| | | |
| | | // ç¨æ°´è®¾å¤-å é¤ |
| | | export function waterEquipmentDelete(query) { |
| | | return request({ |
| | | url: '/waterRecord/delete', |
| | | method: 'delete', |
| | | data: query, |
| | | }) |
| | | } |
| | | |
| | | // ç¨æ°´è®¾å¤-æ°å¢ |
| | | export function waterEquipmentAdd(query) { |
| | | return request({ |
| | | url: '/waterRecord/add', |
| | | method: 'post', |
| | | data: query, |
| | | }) |
| | | } |
| | | |
| | | // ç¨æ°´è®¾å¤-ä¿®æ¹ |
| | | export function waterEquipmentUpdate(query) { |
| | | return request({ |
| | | url: '/waterRecord/update', |
| | | method: 'post', |
| | | data: query, |
| | | }) |
| | | } |
| | | |
| | | // ç¨æ°´è®¾å¤ä¸ææ¡æ¥è¯¢ |
| | | export function waterDeviceList(query) { |
| | | return request({ |
| | | url: '/device/ledger/page', |
| | | method: 'get', |
| | | params: query, |
| | | }) |
| | | } |
| | | |
| | | // 水费管ç-å页æ¥è¯¢ |
| | | export function waterBillListPage(query) { |
| | | return request({ |
| | | url: '/waterBill/listPage', |
| | | method: 'get', |
| | | params: query, |
| | | }) |
| | | } |
| | | |
| | | // 水费管ç-æ°å¢ |
| | | export function waterBillAdd(query) { |
| | | return request({ |
| | | url: '/waterBill/add', |
| | | method: 'post', |
| | | data: query, |
| | | }) |
| | | } |
| | | |
| | | // 水费管ç-ä¿®æ¹ |
| | | export function waterBillUpdate(query) { |
| | | return request({ |
| | | url: '/waterBill/update', |
| | | method: 'post', |
| | | data: query, |
| | | }) |
| | | } |
| | | |
| | | // 水费管ç-å é¤ |
| | | export function waterBillDelete(query) { |
| | | return request({ |
| | | url: '/waterBill/delete', |
| | | method: 'delete', |
| | | data: query, |
| | | }) |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | import request from "@/utils/request"; |
| | | |
| | | // æ¥è¯¢å¨æ°ç½é¢è¦å表 |
| | | export const getStockWarningPage = (params) => { |
| | | return request({ |
| | | url: "/gasTankWarning/listPage", |
| | | method: "get", |
| | | params, |
| | | }); |
| | | }; |
| | | |
| | | // æ°å¢å¨æ°ç½é¢è¦è§å |
| | | export const addStockWarning = (data) => { |
| | | return request({ |
| | | url: "/gasTankWarning/add", |
| | | method: "post", |
| | | data, |
| | | }); |
| | | }; |
| | | |
| | | // ä¿®æ¹å¨æ°ç½é¢è¦è§å |
| | | export const updateStockWarning = (data) => { |
| | | return request({ |
| | | url: "/gasTankWarning/update", |
| | | method: "put", |
| | | data, |
| | | }); |
| | | }; |
| | | |
| | | // å é¤å¨æ°ç½é¢è¦è§å |
| | | export const deleteStockWarning = (ids) => { |
| | | return request({ |
| | | url: "/gasTankWarning/delete", |
| | | method: "delete", |
| | | data: { ids }, |
| | | }); |
| | | }; |
| | | |
| | | // æ¹éå¤ç卿°ç½é¢è¦ |
| | | export const batchProcessStockWarning = (data) => { |
| | | return request({ |
| | | url: "/gasTankWarning/batchProcess", |
| | | method: "post", |
| | | data, |
| | | }); |
| | | }; |
| | | |
| | | // 导åºå¨æ°ç½é¢è¦æ°æ® |
| | | export const exportStockWarning = (params) => { |
| | | return request({ |
| | | url: "/gasTankWarning/export", |
| | | method: "get", |
| | | params, |
| | | responseType: "blob", |
| | | }); |
| | | }; |
| | | |
| | | // æ ¹æ®IDè·å卿°ç½é¢è¦è¯¦æ
|
| | | export const getStockWarningById = (id) => { |
| | | return request({ |
| | | url: `/gasTankWarning/${id}`, |
| | | method: "get", |
| | | }); |
| | | }; |
| | | |
| | | // å¯ç¨/ç¦ç¨é¢è¦è§å |
| | | export const toggleStockWarningStatus = (data) => { |
| | | return request({ |
| | | url: "/gasTankWarning/toggleStatus", |
| | | method: "put", |
| | | data, |
| | | }); |
| | | }; |
| | | |
| | | // è·åé¢è¦ç»è®¡ä¿¡æ¯ |
| | | export const getStockWarningStatistics = () => { |
| | | return request({ |
| | | url: "/gasTankWarning/statistics", |
| | | method: "get", |
| | | }); |
| | | }; |
¶Ô±ÈÐÂÎļþ |
| | |
| | | // èªé
¬ç®¡ç |
| | | import request from "@/utils/request"; |
| | | |
| | | // æ¥è¯¢å表 |
| | | export function compensationListPage(query) { |
| | | return request({ |
| | | url: "/compensationPerformance/listPage", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | // æ°å¢ |
| | | export function compensationAdd(query) { |
| | | return request({ |
| | | url: "/compensationPerformance/add", |
| | | method: "post", |
| | | data: query, |
| | | }); |
| | | } |
| | | // ä¿®æ¹ |
| | | export function compensationUpdate(query) { |
| | | return request({ |
| | | url: "/compensationPerformance/update", |
| | | method: "post", |
| | | data: query, |
| | | }); |
| | | } |
| | | // å é¤ |
| | | export function compensationDelete(query) { |
| | | return request({ |
| | | url: "/compensationPerformance/delete", |
| | | method: "delete", |
| | | data: query, |
| | | }); |
| | | } |
| | |
| | | params: query, |
| | | }) |
| | | } |
| | | |
| | | // æ°å¢ææ å表 |
| | | export function qualityTestStandardAdd(query) { |
| | | return request({ |
| | |
| | | data: query, |
| | | }) |
| | | } |
| | | |
| | | // ä¿®æ¹ææ å表 |
| | | export function qualityTestStandardUpdate(query) { |
| | | return request({ |
| | |
| | | data: query, |
| | | }) |
| | | } |
| | | |
| | | // å 餿æ å表 |
| | | export function qualityTestStandardDel(query) { |
| | | return request({ |
| | |
| | | method: 'delete', |
| | | data: query, |
| | | }) |
| | | } |
| | | |
| | | // å 餿æ å表 |
| | | export function qualityInspectDetailByProductId(productId) { |
| | | return request({ |
| | | url: '/quality/qualityTestStandard/product/' + productId, |
| | | method: 'get', |
| | | }) |
| | | } |
| | |
| | | params: query, |
| | | }) |
| | | } |
| | | |
| | | // æ°å¢åæææ£éª |
| | | export function qualityInspectAdd(query) { |
| | | return request({ |
| | |
| | | data: query, |
| | | }) |
| | | } |
| | | |
| | | // ä¿®æ¹åæææ£éª |
| | | export function qualityInspectUpdate(query) { |
| | | return request({ |
| | |
| | | data: query, |
| | | }) |
| | | } |
| | | |
| | | // å é¤åæææ£éª |
| | | export function qualityInspectDel(query) { |
| | | return request({ |
| | |
| | | data: query, |
| | | }) |
| | | } |
| | | |
| | | // æäº¤åæææ£éª |
| | | export function submitQualityInspect(data) { |
| | | return request({ |
| | | url: '/quality/qualityInspect/submit', |
| | | method: 'post', |
| | | data: data, |
| | | }) |
| | | } |
| | | |
| | | // æäº¤åæææ£éª |
| | | export function downloadQualityInspect(data) { |
| | | return request({ |
| | | url: '/quality/qualityInspect/down', |
| | | method: 'post', |
| | | data: data, |
| | | responseType: "blob", |
| | | }) |
| | | } |
| | | |
| | |
| | | }
|
| | | .el-dialog__body {
|
| | | padding: 16px 40px 0 40px;
|
| | | max-height: 90vh;
|
| | | max-height: 74vh;
|
| | | overflow-y: auto;
|
| | | }
|
| | | .el-dialog__footer {
|
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="file-card"> |
| | | <img src="@/assets/img/fileImg/unknowfile.png" alt="" v-if="fileType == 0"/> |
| | | <img src="@/assets/img/fileImg/word.png" alt="" v-else-if="fileType == 1"/> |
| | | <img src="@/assets/img/fileImg/excel.png" alt="" v-else-if="fileType == 2"/> |
| | | <img src="@/assets/img/fileImg/ppt.png" alt="" v-else-if="fileType == 3"/> |
| | | <img src="@/assets/img/fileImg/pdf.png" alt="" v-else-if="fileType == 4"/> |
| | | <img src="@/assets/img/fileImg/zpi.png" alt="" v-else-if="fileType == 5"/> |
| | | <img src="@/assets/img/fileImg/txt.png" alt="" v-else/> |
| | | <div class="word"> |
| | | <span |
| | | >{{file.name || 'æªç¥'}}</span |
| | | > |
| | | <span>154kb</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | // props: ["fileType", "file"], |
| | | props: { |
| | | fileType: Number, |
| | | file: File, |
| | | default() { |
| | | return {}; |
| | | }, |
| | | }, |
| | | watch: { |
| | | file() { |
| | | console.log(this.file); |
| | | }, |
| | | }, |
| | | mounted() { |
| | | console.log(this.file); |
| | | console.log(this.fileType); |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .file-card { |
| | | width: 250px; |
| | | height: 100px; |
| | | background-color: rgb(45, 48, 63); |
| | | border-radius: 20px; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | padding: 10px; |
| | | box-sizing: border-box; |
| | | cursor: pointer; |
| | | &:hover { |
| | | background-color: rgb(33, 36, 54); |
| | | } |
| | | img { |
| | | width: 60px; |
| | | height: 60px; |
| | | } |
| | | .word { |
| | | width: 60%; |
| | | margin-left: 10px; |
| | | overflow: hidden; |
| | | span { |
| | | width: 90%; |
| | | display: inline-block; |
| | | color: #fff; |
| | | } |
| | | span:first-child { |
| | | font-size: 14px; |
| | | overflow: hidden; |
| | | white-space: nowrap; |
| | | text-overflow: ellipsis; |
| | | } |
| | | span:last-child { |
| | | font-size: 12px; |
| | | color: rgb(180, 180, 180); |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | |
| | | component: () => import('@/views/error/401'),
|
| | | hidden: true
|
| | | },
|
| | |
|
| | | {
|
| | | path: '',
|
| | | component: Layout,
|
| | |
| | | ]
|
| | | },
|
| | | {
|
| | | path: '/main/MobileChat',
|
| | | component: Layout,
|
| | | redirect: '',
|
| | | hidden: true,
|
| | | children: [
|
| | | {
|
| | | path: '',
|
| | | component: () => import('@/views/chatHome/chatHomeIndex/MobileChat'),
|
| | | name: 'MobileChat',
|
| | | meta: { title: 'AI对è¯', icon: 'dashboard', affix: true}
|
| | | }
|
| | | ]
|
| | | },
|
| | | {
|
| | | path: '/user',
|
| | | component: Layout,
|
| | | hidden: true,
|
¶Ô±ÈÐÂÎļþ |
| | |
| | | //鲿 |
| | | export function debounce(fn) { |
| | | console.log(1) |
| | | let t = null //åªä¼æ§è¡ä¸æ¬¡ |
| | | debugger |
| | | |
| | | return function (){ |
| | | if(t){ |
| | | clearTimeout(t) |
| | | } |
| | | t = setTimeout(()=>{ |
| | | console.log(temp); //å¯ä»¥è·å |
| | | // console.log(arguments[0]) //undefined |
| | | fn.apply(this,arguments) |
| | | //å¨è¿ä¸ªåè°å½æ°éé¢çargumentæ¯è¿ä¸ªåè°å½æ°çåæ°ï¼å 为没æåæ°æä»¥undefinedï¼å¯ä»¥éè¿å¤é¢ç彿°èµå¼æ¥è¿è¡è®¿é® |
| | | //ä¹å¯ä»¥æ¹åæç®å¤´å½æ°,ç®å¤´å½æ°çthisæ¯æåå®ä¹å½æ°çé£ä¸å±çï¼æä»¥è®¿é®å°çargumentsæ¯ä¸ä¸å±å½æ°çarguments |
| | | },1000) |
| | | |
| | | } |
| | | } |
| | | //èæµ |
| | | export function throttle(fn, delay = 200) { |
| | | let timer = null |
| | | console.log(fn); |
| | | debugger |
| | | return function () { |
| | | if(timer) return |
| | | timer = setTimeout(() => { |
| | | debugger |
| | | fn.apply(this,arguments) |
| | | timer = null |
| | | }) |
| | | } |
| | | } |
| | | //䏿å¨ç» |
| | | export function animation(obj, target, fn1) { |
| | | // console.log(fn1); |
| | | // fnæ¯ä¸ä¸ªåè°å½æ°ï¼å¨å®æ¶å¨ç»æçæ¶åæ·»å |
| | | // æ¯æ¬¡å¼å®æ¶å¨ä¹åå
æ¸
餿宿¶å¨ |
| | | clearInterval(obj.timer); |
| | | obj.timer = setInterval(function () { |
| | | // æ¥é¿è®¡ç®å
¬å¼ è¶æ¥è¶å° |
| | | // æ¥é¿åæ´ |
| | | var step = (target - obj.scrollTop) / 10; |
| | | step = step > 0 ? Math.ceil(step) : Math.floor(step); |
| | | if (obj.scrollTop >= target) { |
| | | clearInterval(obj.timer); |
| | | // 妿fn1åå¨ï¼è°ç¨fn |
| | | if (fn1) { |
| | | fn1(); |
| | | } |
| | | } else { |
| | | // æ¯30毫ç§å°±å°æ°çå¼ç»obj.left |
| | | obj.scrollTop = obj.scrollTop + step; |
| | | } |
| | | }, 10); |
| | | } |
| | | |
| | | //夿æä»¶ç±»å |
| | | export function judgeFileType(file) { |
| | | if (file == null||file == ""){ |
| | | alert("è¯·éæ©è¦ä¸ä¼ çå¾ç!"); |
| | | return false; |
| | | } |
| | | if (file.lastIndexOf('.')==-1){ //妿ä¸åå¨"." |
| | | alert("è·¯å¾ä¸æ£ç¡®!"); |
| | | return false; |
| | | } |
| | | var AllImgExt=".jpg|.jpeg|.gif|.bmp|.png|"; |
| | | var extName = file.substring(file.lastIndexOf(".")).toLowerCase();//ï¼æè·¯å¾ä¸çææåæ¯å
¨é¨è½¬æ¢ä¸ºå°åï¼ |
| | | if(AllImgExt.indexOf(extName+"|")==-1) |
| | | { |
| | | ErrMsg="该æä»¶ç±»åä¸å
许ä¸ä¼ ã请ä¸ä¼ "+AllImgExt+" ç±»åçæä»¶ï¼å½åæä»¶ç±»å为"+extName; |
| | | alert(ErrMsg); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | //æä»¶ç±»å |
| | | export function fileType() { |
| | | return { |
| | | 'application/msword': 'word', |
| | | 'application/pdf': 'pdf', |
| | | 'application/vnd.ms-powerpoint': 'ppt', |
| | | 'application/vnd.ms-excel': 'excel', |
| | | 'aplication/zip': 'zpi', |
| | | } |
| | | } |
| | | |
| | | export function filterArr(arr) { |
| | | return arr.filter(item => item.flag !== false); |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="mobile-chat-wrapper" style="height: 91vh;"> |
| | | <div class="chat-history"> |
| | | <div class="chat-content" ref="chatContent"> |
| | | <div class="chat-wrapper" v-for="(item, index) in chatList" :key="index"> |
| | | <div class="chat-friend" v-if="item.uid !== '1001'"> |
| | | <div class="info-time"> |
| | | <img :src="item.headImg" alt="" /> |
| | | <span>{{ item.name }}</span> |
| | | <span>{{ item.time }}</span> |
| | | </div> |
| | | <div class="chat-text" v-if="item.chatType == 0"> |
| | | <template v-if="isSend && index === chatList.length - 1"> |
| | | <span class="flash_cursor"></span> |
| | | </template> |
| | | <template v-else> |
| | | <pre>{{ item.msg }}</pre> |
| | | </template> |
| | | </div> |
| | | <div class="chat-img" v-if="item.chatType == 1"> |
| | | <img :src="item.msg" alt="表æ
" v-if="item.extend.imgType == 1" style="width: 100px; height: 100px" /> |
| | | <el-image :src="item.msg" :preview-src-list="srcImgList" v-else> </el-image> |
| | | </div> |
| | | <div class="chat-img" v-if="item.chatType == 2"> |
| | | <div class="word-file"> |
| | | <FileCard :fileType="item.extend.fileType" :file="item.msg"></FileCard> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="chat-me" v-else> |
| | | <div class="info-time"> |
| | | <span>{{ item.name }}</span> |
| | | <span>{{ item.time }}</span> |
| | | <img :src="item.headImg" alt="" /> |
| | | </div> |
| | | <div class="chat-text" v-if="item.chatType == 0"> |
| | | {{ item.msg }} |
| | | </div> |
| | | <div class="chat-img" v-if="item.chatType == 1"> |
| | | <img :src="item.msg" alt="表æ
" v-if="item.extend.imgType == 1" style="width: 100px; height: 100px" /> |
| | | <el-image style="max-width: 300px; border-radius: 10px" :src="item.msg" :preview-src-list="srcImgList" v-else> </el-image> |
| | | </div> |
| | | <div class="chat-img" v-if="item.chatType == 2"> |
| | | <div class="word-file"> |
| | | <FileCard :fileType="item.extend.fileType" :file="item.msg"></FileCard> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="chat-input-wrapper"> |
| | | <div style="display: flex; align-items: center"> |
| | | <input v-model="inputMsg" @change="sendText" :disabled="loading" class="input-text" autofocus placeholder="ç»å°æºåéæ¶æ¯" /> |
| | | <img class="send-icon" src="@/assets/img/emoji/rocket.png" alt="" @click="sendText" /> |
| | | |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted, nextTick,onActivated } from 'vue' |
| | | import { useRoute } from 'vue-router' |
| | | import { animation } from '@/utils/util' |
| | | import chatGPTHeadImg from '@/assets/img/head_portrait1.png' |
| | | import headPortrait from '@/assets/img/head_portrait.jpg' |
| | | import FileCard from '@/components/FileCard.vue' |
| | | import { ElMessage } from "element-plus" |
| | | import {checking} from './ai-wd.js' |
| | | |
| | | // å®ä¹ååºå¼æ°æ® |
| | | const route = useRoute() |
| | | const chatContent = ref(null) |
| | | const ws = ref(null) |
| | | const chatList = ref([ |
| | | { |
| | | headImg: chatGPTHeadImg, |
| | | name: 'å°æº', |
| | | time: new Date().toLocaleTimeString(), |
| | | msg: ' å°æºä¸ºæ¨æå¡', |
| | | chatType: 0, |
| | | uid: '1002' |
| | | } |
| | | ]) |
| | | const inputMsg = ref('') |
| | | const isSend = ref(false) |
| | | const fileList = ref([]) |
| | | const isProcessing = ref(false) |
| | | const loading = ref(true) |
| | | const srcImgList = ref([]) |
| | | |
| | | // å é¤å¾ç |
| | | const deleteImg = (index) => { |
| | | if (index >= 0 && index < fileList.value.length) { |
| | | fileList.value.splice(index, 1) |
| | | } |
| | | } |
| | | |
| | | // WebSocketæ¶æ¯æ¥æ¶ |
| | | const websocketonmessage = (e) => { |
| | | const redata = JSON.parse(e.data) |
| | | //æ°æ®æ¥æ¶ |
| | | let chatGPT = { |
| | | headImg: headPortrait, |
| | | name: 'DeepSeek', |
| | | time: new Date().toLocaleTimeString(), |
| | | msg: redata[0].text, |
| | | chatType: 0, //ä¿¡æ¯ç±»åï¼0æåï¼1å¾ç |
| | | uid: '1002' //uid |
| | | } |
| | | sendMsg(chatGPT) |
| | | isSend.value = false |
| | | } |
| | | |
| | | // WebSocketåéæ¶æ¯ |
| | | const websocketsend = (Data) => { |
| | | console.log("å³å°åéæ¶æ¯", Data) |
| | | if (ws.value && ws.value.readyState === WebSocket.OPEN) { |
| | | console.log("åéæ¶æ¯", ws.value) |
| | | console.log("åéæ¶æ¯", Data) |
| | | let fileUrls = fileList.value.map(item => item.file.fileUrl) |
| | | //æ°æ®åé |
| | | ws.value.send(Data + ":" + fileUrls.join(",")) |
| | | fileList.value = [] |
| | | inputMsg.value = '' |
| | | } |
| | | } |
| | | |
| | | // åéææ¬æ¶æ¯ |
| | | const sendText = () => { |
| | | if (inputMsg.value) { |
| | | let chatMsg = { |
| | | headImg: headPortrait, |
| | | name: 'å§é¾', |
| | | time: new Date().toLocaleTimeString(), |
| | | msg: inputMsg.value, |
| | | chatType: 0, //ä¿¡æ¯ç±»åï¼0æåï¼1å¾ç |
| | | uid: '1001' //uid |
| | | } |
| | | chatList.value.push(chatMsg) |
| | | let chatGPT = { |
| | | headImg: headPortrait, |
| | | name: 'å°æº', |
| | | time: new Date().toLocaleTimeString(), |
| | | msg: "", |
| | | chatType: 0, //ä¿¡æ¯ç±»åï¼0æåï¼1å¾ç |
| | | uid: '1002' //uid |
| | | } |
| | | chatList.value.push(chatGPT) // å°æ¥æ¶å°çæ¶æ¯åå¨å° messages æ°ç» |
| | | simulateStreamingOutput(chatGPT, inputMsg.value) |
| | | inputMsg.value = '' |
| | | |
| | | } else { |
| | | ElMessage({ |
| | | message: 'æ¶æ¯ä¸è½ä¸ºç©ºå¦~', |
| | | type: 'warning' |
| | | }) |
| | | } |
| | | } |
| | | |
| | | // åéä¿¡æ¯ |
| | | const sendMsg = (msgList) => { |
| | | chatList.value.push(msgList) |
| | | scrollBottom() |
| | | } |
| | | |
| | | // è·åçªå£é«åº¦å¹¶æ»å¨è³æåºå± |
| | | const scrollBottom = () => { |
| | | nextTick(() => { |
| | | const scrollDom = chatContent.value |
| | | animation(scrollDom, scrollDom.scrollHeight - scrollDom.offsetHeight) |
| | | }) |
| | | } |
| | | |
| | | // ç»ä»¶æè½½æ¶æ§è¡ |
| | | onActivated(() => { |
| | | chatList.value = [] |
| | | chatList.value.push({ |
| | | headImg: chatGPTHeadImg, |
| | | name: 'å°æº', |
| | | time: new Date().toLocaleTimeString(), |
| | | msg: 'å°æºä¸ºæ¨æå¡', |
| | | chatType: 0, |
| | | uid: '1002' |
| | | }) |
| | | chatList.value.push({ |
| | | headImg: chatGPTHeadImg, |
| | | name: 'å§é¾', |
| | | time: new Date().toLocaleTimeString(), |
| | | msg: route.query.keyWord, |
| | | chatType: 0, |
| | | uid: '1001' |
| | | }) |
| | | // æ·»å ä¸ä¸ªç©ºçå夿¶æ¯å ä½ |
| | | const replyMsg = { |
| | | headImg: chatGPTHeadImg, |
| | | name: 'å°æº', |
| | | time: new Date().toLocaleTimeString(), |
| | | msg: '', |
| | | chatType: 0, |
| | | uid: '1002' |
| | | } |
| | | chatList.value.push(replyMsg) |
| | | scrollBottom() |
| | | |
| | | // å¦æææ¥è¯¢å
³é®åï¼åæ¨¡ææµå¼è¾åº |
| | | if (route.query.keyWord) { |
| | | simulateStreamingOutput(replyMsg, route.query.keyWord) |
| | | } |
| | | }) |
| | | // æ¨¡ææµå¼è¾åº |
| | | const simulateStreamingOutput = async (msgObj, keyWord) => { |
| | | loading.value = true |
| | | // çæ0.8-1.3ç§ä¹é´çéæºå»¶è¿ |
| | | const delay = Math.random() * 500 + 800 |
| | | |
| | | // 模æåå¤å
容ï¼å®é
åºç¨ä¸åºä»APIè·åï¼ |
| | | const responseText = `å
³äº"${keyWord}"çé®é¢ï¼ææ¥ä¸ºæ¨è§£çï¼\n` + checking(keyWord) |
| | | |
| | | isSend.value = true |
| | | |
| | | let index = 0 |
| | | setTimeout(() => { |
| | | const interval = setInterval(() => { |
| | | isSend.value = true |
| | | if (index < responseText.length) { |
| | | msgObj.msg += responseText.charAt(index) |
| | | index++ |
| | | isSend.value = false |
| | | scrollBottom() |
| | | } else { |
| | | clearInterval(interval) |
| | | isSend.value = false |
| | | loading.value = false |
| | | } |
| | | }, 50) // æ¯50msè¾åºä¸ä¸ªåç¬¦ï¼æ¨¡ææµå¼ææ |
| | | }, delay) |
| | | |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .mobile-chat-wrapper { |
| | | display: flex; |
| | | flex-direction: column; |
| | | overflow: hidden; |
| | | height: 91vh; |
| | | position: relative; |
| | | background-color: white; |
| | | |
| | | .chat-history { |
| | | flex: 1 1 0; |
| | | overflow-y: auto; |
| | | } |
| | | |
| | | .chat-input-wrapper { |
| | | padding: 8px 16px 8px 8px; |
| | | position: absolute; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | .file-tt{ |
| | | flex-direction: column; |
| | | width: 200px; |
| | | display: flex; |
| | | padding: 5px; |
| | | border-radius: 5px; |
| | | margin-right: 5px; |
| | | background: #cacaca; |
| | | .file-item{ |
| | | width: 200px; |
| | | overflow:hidden; |
| | | word-wrap: break-word; |
| | | text-overflow:ellipsis; |
| | | display:-webkit-box; |
| | | -webkit-box-orient:vertical; |
| | | -webkit-line-clamp:2; |
| | | } |
| | | } |
| | | |
| | | .send-icon { |
| | | height: 40px; |
| | | margin-left: 16px; |
| | | } |
| | | .input-text{ |
| | | font-size: 18px; |
| | | width: 100%; |
| | | border-radius: 20px; |
| | | height: 80px; |
| | | padding-left: 10px; |
| | | //padding-top: 10px; |
| | | border: none; |
| | | color: black; /* ä¿®æ¹ææ¬é¢è²ä¸ºç½è² */ |
| | | background-color: #f5f4f4; /* ä¿®æ¹èæ¯é¢è²ä¸ºæ·±ç°è² */ |
| | | } |
| | | } |
| | | |
| | | .chat-content { |
| | | width: 100%; |
| | | height: 80%; |
| | | overflow-y: scroll; |
| | | padding: 20px; |
| | | box-sizing: border-box; |
| | | |
| | | &::-webkit-scrollbar { |
| | | width: 0; |
| | | /* Safari,Chrome éèæ»å¨æ¡ */ |
| | | height: 0; |
| | | /* Safari,Chrome éèæ»å¨æ¡ */ |
| | | display: none; |
| | | /* ç§»å¨ç«¯ãpad ä¸Safariï¼Chromeï¼éèæ»å¨æ¡ */ |
| | | } |
| | | |
| | | .chat-wrapper { |
| | | position: relative; |
| | | word-break: break-all; |
| | | |
| | | .chat-friend { |
| | | width: 100%; |
| | | float: left; |
| | | margin-bottom: 20px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: flex-start; |
| | | align-items: flex-start; |
| | | |
| | | .chat-text { |
| | | max-width: 90%; |
| | | padding: 20px; |
| | | border-radius: 20px 20px 20px 5px; |
| | | background-color: rgb(245, 248, 248); |
| | | color: black; |
| | | |
| | | &:hover { |
| | | background-color: rgb(232, 232, 232); |
| | | } |
| | | |
| | | pre { |
| | | white-space: break-spaces; |
| | | } |
| | | } |
| | | |
| | | .chat-img { |
| | | img { |
| | | width: 100px; |
| | | height: 100px; |
| | | } |
| | | } |
| | | |
| | | .info-time { |
| | | margin: 10px 0; |
| | | color: black; |
| | | font-size: 14px; |
| | | |
| | | img { |
| | | width: 30px; |
| | | height: 30px; |
| | | border-radius: 50%; |
| | | vertical-align: middle; |
| | | margin-right: 10px; |
| | | } |
| | | |
| | | span:last-child { |
| | | color: rgb(101, 104, 115); |
| | | margin-left: 10px; |
| | | vertical-align: middle; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .chat-me { |
| | | width: 100%; |
| | | float: right; |
| | | margin-bottom: 20px; |
| | | position: relative; |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: flex-end; |
| | | align-items: flex-end; |
| | | |
| | | .chat-text { |
| | | float: right; |
| | | max-width: 90%; |
| | | padding: 20px; |
| | | border-radius: 20px 20px 5px 20px; |
| | | background-color: rgb(29, 144, 245); |
| | | color: #fff; |
| | | |
| | | &:hover { |
| | | background-color: rgb(26, 129, 219); |
| | | } |
| | | } |
| | | |
| | | .chat-img { |
| | | img { |
| | | max-width: 300px; |
| | | max-height: 200px; |
| | | border-radius: 10px; |
| | | } |
| | | } |
| | | |
| | | .info-time { |
| | | margin: 10px 0; |
| | | color: black; |
| | | font-size: 14px; |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | |
| | | img { |
| | | width: 30px; |
| | | height: 30px; |
| | | border-radius: 50%; |
| | | vertical-align: middle; |
| | | margin-left: 10px; |
| | | } |
| | | |
| | | span { |
| | | line-height: 30px; |
| | | } |
| | | |
| | | span:first-child { |
| | | color: rgb(101, 104, 115); |
| | | margin-right: 10px; |
| | | vertical-align: middle; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .flash_cursor { |
| | | width: 20px; |
| | | height: 30px; |
| | | display: inline-block; |
| | | background: #d6e3f5; |
| | | opacity: 1; |
| | | animation: glow 800ms ease-out infinite alternate; |
| | | } |
| | | @keyframes glow { |
| | | 0% { |
| | | opacity: 1; |
| | | } |
| | | |
| | | 25% { |
| | | opacity: 0.5; |
| | | } |
| | | |
| | | 50% { |
| | | opacity: 0; |
| | | } |
| | | |
| | | 75% { |
| | | opacity: 0.5; |
| | | } |
| | | |
| | | 100% { |
| | | opacity: 1; |
| | | } |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | export function jam() { |
| | | return "" |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | export function gasLeaks() { |
| | | return "1. 设计ä¸è®¾å¤éæ©\n" + |
| | | "éç¨é«è´¨éææï¼ç®¡éãéé¨ãå¨ç½ç设å¤åºéç¨èè
èãèé«åçææï¼å¹¶ç¬¦åå®å
¨æ åï¼å¦ASMEãAPIçï¼ã\n" + |
| | | "\n" + |
| | | "å®å
¨è®¾è®¡ï¼\n" + |
| | | "\n" + |
| | | "å®è£
åä½çå®å
¨è£
ç½®ï¼å¦åééé¨ãçç ´çãå®å
¨éçï¼ã\n" + |
| | | "\n" + |
| | | "设置æ°ä½æ³æ¼æ£æµç³»ç»ï¼å¦å¯çæ°ä½æ¥è¦å¨ãææ¯æ°ä½ä¼ æå¨ï¼ã\n" + |
| | | "\n" + |
| | | "éç¨å°éå¼ç³»ç»è®¾è®¡ï¼åå°å¼æ¾æ¥å£ã\n" + |
| | | "\n" + |
| | | "éé£ç³»ç»ï¼å¨å¯è½æ³æ¼çåºåå®è£
强å¶éé£è®¾å¤ï¼é²æ¢æ°ä½èéã\n" + |
| | | "\n" + |
| | | "2. å®è£
ä¸ç»´æ¤\n" + |
| | | "è§èå®è£
ï¼ç±ä¸ä¸äººåè¿è¡è®¾å¤å®è£
ï¼ç¡®ä¿ç®¡éçæ¥ãå¯å°çç¯èæ 缺é·ã\n" + |
| | | "\n" + |
| | | "å®ææ£æ¥ï¼\n" + |
| | | "\n" + |
| | | "对管éãéé¨ãè¿æ¥å¤è¿è¡æ³æ¼æ£æµï¼å¦ååæµè¯ãè¶
å£°æ³¢æ£æµãè¥çæ°´æ£æ¼ï¼ã\n" + |
| | | "\n" + |
| | | "æ´æ¢èåæè
èçé¨ä»¶ã\n" + |
| | | "\n" + |
| | | "é¢é²æ§ç»´æ¤ï¼å¶å®ç»´æ¤è®¡åï¼å®ææ¶¦æ»éé¨ãæ´æ¢å¯å°ä»¶çã\n" + |
| | | "\n" + |
| | | "3. æä½ç®¡ç\n" + |
| | | "ä¸¥æ ¼æä½è§ç¨ï¼\n" + |
| | | "\n" + |
| | | "æä½äººåéå¹è®ä¸å²ï¼çææ°ä½ç¹æ§ååºæ¥æµç¨ã\n" + |
| | | "\n" + |
| | | "é¿å
è¶
åãè¶
温æé误æä½ã\n" + |
| | | "\n" + |
| | | "çæ§ç³»ç»ï¼\n" + |
| | | "\n" + |
| | | "宿¶çæµååãæ¸©åº¦ãæµéçåæ°ï¼è®¾ç½®èªå¨æ¥è¦åèéåæºè£
ç½®ã\n" + |
| | | "\n" + |
| | | "ä½¿ç¨æ°ä½æ£æµä»ªï¼å¦çº¢å¤ãçµåå¦ä¼ æå¨ï¼çæµç¯å¢æµåº¦ã\n" + |
| | | "\n" + |
| | | "æç¡®æ è¯ï¼å¨å±é©åºåæ ææ°ä½ç±»åãé£é©ç级å鲿¤è¦æ±ã\n" + |
| | | "\n" + |
| | | "4. æ³æ¼åºæ¥æªæ½\n" + |
| | | "åºæ¥è®¾å¤ï¼\n" + |
| | | "\n" + |
| | | "é
å¤é²æ¯é¢å
·ãå¼å¸å¨ã鲿¤æçä¸ªäººé²æ¤è£
å¤ï¼PPEï¼ã\n" + |
| | | "\n" + |
| | | "å°±è¿æ¾ç½®æ³æ¼åºæ¥å
ï¼å¦å µæ¼è¶ãå¯å°å¸¦ï¼ã\n" + |
| | | "\n" + |
| | | "ç´§æ¥ååºï¼\n" + |
| | | "\n" + |
| | | "ç«å³åææ°æºï¼å
³é䏿¸¸é鍿å¯å¨ç´§æ¥åæç³»ç»ï¼ã\n" + |
| | | "\n" + |
| | | "å¯å¨éé£è®¾å¤ç¨éæ°ä½æµåº¦ã\n" + |
| | | "\n" + |
| | | "çæ£äººå并䏿¥ä¸ä¸é¨é¨ï¼å¦æ¶é²ãç¯ä¿ï¼ã\n" + |
| | | "\n" + |
| | | "åºæ¥é¢æ¡ï¼å®ææ¼ç»æ³æ¼å¤ç½®æµç¨ï¼ç¡®ä¿äººåçæåå·¥ã\n" + |
| | | "\n" + |
| | | "5. å¨åä¸è¿è¾å®å
¨\n" + |
| | | "å¨åè¦æ±ï¼\n" + |
| | | "\n" + |
| | | "å¨ç½è¿ç¦»ç«æºã髿¸©åºï¼å¹¶è®¾ç½®å´å °é²æ¢æ©æ£ã\n" + |
| | | "\n" + |
| | | "æ¶²åæ°ä½å¨ç½éé
夿³åè£
ç½®ã\n" + |
| | | "\n" + |
| | | "è¿è¾å®å
¨ï¼\n" + |
| | | "\n" + |
| | | "使ç¨åè§çè¿è¾è½¦è¾ï¼åºå®æ°ç¶é²æ¢ç¢°æã\n" + |
| | | "\n" + |
| | | "è¿è¾éä¸çæ§è½¦è¾ç¶æï¼å¦GPSãæ¸©åº¦ä¼ æå¨ï¼ã\n" + |
| | | "\n" + |
| | | "6. 人åå¹è®ä¸æå\n" + |
| | | "å®å
¨å¹è®ï¼å®æå¼å±æ°ä½å±å®³ã鲿¤æªæ½ååºæ¥å¤ççå¹è®ã\n" + |
| | | "\n" + |
| | | "å®å
¨æåï¼é¼å±åå·¥æ¥åæ½å¨é£é©ï¼å»ºç«âé¶æ³æ¼â管çç®æ ã\n" + |
| | | "\n" + |
| | | "7. æ³è§ä¸æ å\n" + |
| | | "éµå®ç¸å
³æ³è§ï¼å¦OSHAãGB 50493ãç³æ²¹åå·¥å¯çæ°ä½åææ¯æ°ä½æ£æµæ¥è¦è®¾è®¡è§èãï¼ã\n" + |
| | | "\n" + |
| | | "宿è¿è¡å®å
¨å®¡è®¡ï¼ç¡®ä¿ç¬¦åè¡ä¸æ åã\n" + |
| | | "\n" + |
| | | "常è§å±é©æ°ä½æ³æ¼çéå¯¹æ§æªæ½\n" + |
| | | "å¯çæ°ä½ï¼å¦ç²ç·ãæ°¢æ°ï¼ï¼é²ççµå¨ãæ¶é¤éçµã\n" + |
| | | "\n" + |
| | | "ææ¯æ°ä½ï¼å¦æ°¯æ°ãç¡«åæ°¢ï¼ï¼é
å¤ä¸ç¨è¿æ»¤å¼æä¾æ°§å¼å¼å¸å¨ã\n" + |
| | | "\n" + |
| | | "çªæ¯æ§æ°ä½ï¼å¦æ°®æ°ãäºæ°§å碳ï¼ï¼çæµæ°§æ°æµåº¦ï¼é¿å
å¯é空é´ä½ä¸ã\n" + |
| | | "\n" + |
| | | "éè¿ä»¥ä¸æªæ½ç综ååºç¨ï¼å¯å¤§å¹
é使°ä½æ³æ¼é£é©ï¼ä¿é人åå®å
¨åç¯å¢å¥åº·ãè¥åçæ³æ¼ï¼éä¼å
ç¡®ä¿äººåæ¤ç¦»ï¼åç±ä¸ä¸äººåå¤ç½®ã\n" + |
| | | "\n" + |
| | | "æ¬åçç± AI çæï¼å
容ä»
ä¾åèï¼è¯·ä»ç»çå«ã" |
| | | } |
| | | |
| | | export function shipping() { |
| | | return "ä¸ãç«å³åºæ¥ååº\n" + |
| | | "1. åç°æ³æ¼æ¶çç´§æ¥è¡å¨\n" + |
| | | "å车并é离ç°åºï¼\n" + |
| | | "\n" + |
| | | "è¿è¾è½¦è¾ç«å³åé å¨ç©ºæ·ãè¿ç¦»äººç¾¤åç«æºçä½ç½®ã\n" + |
| | | "\n" + |
| | | "è®¾ç½®è¦æçº¿ï¼è³å°50~100ç±³åå¾ï¼æ ¹æ®æ°ä½æ§è´¨è°æ´ï¼ï¼ç¦æ¢æ å
³äººåè¿å
¥ã\n" + |
| | | "\n" + |
| | | "åææ³æ¼æºï¼\n" + |
| | | "\n" + |
| | | "å
³é容å¨é鍿å°å µç ´æå¤ï¼å¦ä½¿ç¨åºæ¥å µæ¼å·¥å
·ï¼ã\n" + |
| | | "\n" + |
| | | "è¥é鍿åï¼å°è¯è½¬ç§»å©ä½æ°ä½è³å¤ç¨å®¹å¨ï¼éä¸ä¸äººåæä½ï¼ã\n" + |
| | | "\n" + |
| | | "æ¥è¦ä¸ä¸æ¥ï¼\n" + |
| | | "\n" + |
| | | "æ¨æåºæ¥çµè¯ï¼å¦æ¶é²119ãç¯ä¿é¨é¨ï¼ï¼è¯´ææ°ä½ç±»åãæ³æ¼éãä½ç½®çä¿¡æ¯ã\n" + |
| | | "\n" + |
| | | "èç³»è¿è¾å
¬å¸å货主ï¼è·åææ¯æ¯æ´ï¼å¦MSDSå®å
¨æ°æ®è¡¨ï¼ã\n" + |
| | | "\n" + |
| | | "2. 人å鲿¤ä¸çæ£\n" + |
| | | "ç©¿æ´é²æ¤è£
å¤ï¼\n" + |
| | | "\n" + |
| | | "å¯çæ°ä½ï¼é²çå·¥å
·+é²éçµæï¼ææ¯æ°ä½ï¼æ£åå¼å¼å¸å¨+é²åæã\n" + |
| | | "\n" + |
| | | "æ 鲿¤è£
夿¶ï¼ç«å³æ¤ç¦»è³ä¸é£æ¹åã\n" + |
| | | "\n" + |
| | | "çæ£å¨è¾¹åºåï¼\n" + |
| | | "\n" + |
| | | "æ ¹æ®æ°ä½æ©æ£èå´ï¼åèåºæ¥ååºæåERGï¼çæ£å±
æ°æä½ä¸äººåã\n" + |
| | | "\n" + |
| | | "é¿å
使´¼å¤æ»çï¼æäºæ°ä½æ¯ç©ºæ°éï¼å¦ç¡«åæ°¢ï¼ã\n" + |
| | | "\n" + |
| | | "3. æ§å¶æ³æ¼æ©æ£\n" + |
| | | "ç©çæ¹æ³ï¼\n" + |
| | | "\n" + |
| | | "è¦çæ³æ¼å£ï¼å¦ç¨æµ¸æ°´æ£è¢«åå°æ¥åï¼ä½ç¦ç¨äºéæ°´ååºæ°ä½å¦æ°¯æ°ï¼ã\n" + |
| | | "\n" + |
| | | "çå ¤å´å µæ¶²ä½æ³æ¼ç©ï¼é²æ¢æµå
¥ä¸æ°´éææ²³æµã\n" + |
| | | "\n" + |
| | | "å妿¹æ³ï¼\n" + |
| | | "\n" + |
| | | "ä¸åå¤çï¼å¦æ°¨æ°æ³æ¼å·æ´ç¨çé
¸ï¼éä¸ä¸äººåæä½ï¼ã\n" + |
| | | "\n" + |
| | | "使ç¨å¸éææï¼å¦æ´»æ§çãæ²åå¸éææºæ°ä½ï¼ã" |
| | | } |
| | | |
| | | export function operate(){ |
| | | return "ä¸ãæä½ä¸å½åçåçåºæ¥å¤ç\n" + |
| | | "1. ç«å³æ§å¶äºæ
\n" + |
| | | "忢æä½ï¼\n" + |
| | | "\n" + |
| | | "æä¸ç´§æ¥åæºæé®ï¼å
³éæè¿ç䏿¸¸éé¨ã\n" + |
| | | "\n" + |
| | | "å¯å¨åºæ¥é¢æ¡ï¼\n" + |
| | | "\n" + |
| | | "å°åæ³æ¼ï¼ä½¿ç¨åºæ¥å µæ¼å·¥å
·ï¼å¦å¯å°è¶ã夹å
·ï¼ã\n" + |
| | | "\n" + |
| | | "大忳æ¼ï¼çæ£äººåï¼æ¥è¦æ±å©ï¼119/ç¯ä¿é¨é¨ï¼ã\n" + |
| | | "\n" + |
| | | "2. 人åå®å
¨\n" + |
| | | "æ¤ç¦»ä¸é离ï¼\n" + |
| | | "\n" + |
| | | "é飿¤ç¦»è³ä¸é£åå®å
¨åºï¼é¿å
使´¼å¤ï¼éæ°ä½ç§¯èï¼ã\n" + |
| | | "\n" + |
| | | "æ¥ææªæ½ï¼\n" + |
| | | "\n" + |
| | | "å¸å
¥ææ¯æ°ä½ï¼ç§»è³ç©ºæ°æ°é²å¤ï¼å¿
è¦æ¶äººå·¥å¼å¸ã\n" + |
| | | "\n" + |
| | | "ç®è¤æ¥è§¦ï¼ç«å³ç¨æ¸
æ°´å²æ´15åéï¼è
èæ§æ°ä½ï¼ã\n" + |
| | | "\n" + |
| | | "3. äºæ
è°æ¥ä¸æ´æ¹\n" + |
| | | "æ ¹æ¬åå åæï¼RCAï¼ï¼\n" + |
| | | "\n" + |
| | | "æ¯æä½å¤±è¯¯ãå¹è®ä¸è¶³ï¼è¿æ¯è®¾å¤ç¼ºé·ï¼\n" + |
| | | "\n" + |
| | | "æ¹è¿æªæ½ï¼\n" + |
| | | "\n" + |
| | | "修订æä½è§ç¨ï¼å¢å è¦ç¤ºæ è¯ã\n" + |
| | | "\n" + |
| | | "对责任人åå¹è®ï¼å¿
è¦æ¶è°å²ã" |
| | | } |
| | | |
| | | export function emergency(){ |
| | | return "ä¸ãä¼ååºæ¥ååºçå
³é®æªæ½\n" + |
| | | "1. å®ååºæ¥é¢æ¡\n" + |
| | | "é对æ§è®¾è®¡ï¼\n" + |
| | | "\n" + |
| | | "åºäºHAZOPï¼å±é©ä¸å¯æä½æ§åæï¼è¯å«æææ½å¨é£é©åºæ¯ã\n" + |
| | | "\n" + |
| | | "å¶å®å级ååºæºå¶ï¼å°æ³æ¼ç°åºå¤ç½®ãå¤§æ³æ¼å
¨åçæ£ï¼ã\n" + |
| | | "\n" + |
| | | "æç¡®èè´£ï¼\n" + |
| | | "\n" + |
| | | "设ç«åºæ¥ææ¥é¨ï¼æå®æ»ææ¥ãé讯ç»ãæ¢é©ç»ãå»çç»çã\n" + |
| | | "\n" + |
| | | "ç¡®ä¿24å°æ¶å¼çå¶åº¦ï¼èç³»æ¹å¼å®æ¶æ´æ°ã\n" + |
| | | "\n" + |
| | | "èå¨å¤é¨èµæºï¼\n" + |
| | | "\n" + |
| | | "䏿¶é²ãç¯ä¿ãå»é¢æåç¾è®¢ææ´åè®®ï¼æç¡®å使µç¨ã\n" + |
| | | "\n" + |
| | | "2. 强ååºæ¥èµæºä¿é\n" + |
| | | "è£
å¤ä¸ç©èµï¼\n" + |
| | | "\n" + |
| | | "é
å¤è¶³é䏿æçåºæ¥è®¾å¤ï¼å
æ¬ï¼\n" + |
| | | "\n" + |
| | | "ä¸ªäººé²æ¤è£
å¤ï¼PPEï¼ï¼é²æ¯é¢å
·ãåå¦é²æ¤æã\n" + |
| | | "\n" + |
| | | "å µæ¼å·¥å
·ï¼å¯å°è¶ã夹å
·ãå¿«éå°å µå¨ã\n" + |
| | | "\n" + |
| | | "å¸é/ä¸åææï¼æ´»æ§çãæ²åãç¨ç¢±æ¶²ï¼ç¨äºé
¸æ§æ°ä½ï¼ã\n" + |
| | | "\n" + |
| | | "å®ææ£æ¥ãç»´æ¤åæ´æ¢ï¼å¦æ°ç¶ååãä¼ æå¨çµæ± ï¼ã\n" + |
| | | "\n" + |
| | | "åºæ¥è½¦è¾ä¸ééï¼\n" + |
| | | "\n" + |
| | | "ç¡®ä¿ææ´è½¦è¾å¯å¿«éæµè¾¾æ³æ¼ç¹ï¼æ¸
é¤è·¯éï¼æ è¯åºæ¥è·¯çº¿ï¼ã\n" + |
| | | "\n" + |
| | | "å
³é®åºåè®¾ç½®åºæ¥æ´ç¼å¨ãå·æ·ç³»ç»ã\n" + |
| | | "\n" + |
| | | "3. å 强人åå¹è®ä¸è½å建设\n" + |
| | | "åå±å¹è®ï¼\n" + |
| | | "\n" + |
| | | "åºå±äººåï¼ææ¡åºæ¬åºæ¥å¤ç½®ï¼å¦å
³ééé¨ã使ç¨çç«å¨ï¼ã\n" + |
| | | "\n" + |
| | | "åºæ¥å°ç»ï¼ä¸ä¸å µæ¼ã伤忥æãæ°ä½æ£æµæè½ã\n" + |
| | | "\n" + |
| | | "管çå±ï¼ææ¥å³çãåªä½æ²éãæ³å¾åè§ã\n" + |
| | | "\n" + |
| | | "宿åèæ ¸ï¼\n" + |
| | | "\n" + |
| | | "éè¿æ¨¡æçªåæ³æ¼ï¼å¦ç²æ¼ï¼æ£éªååºé度ã\n" + |
| | | "\n" + |
| | | "ä¸åæ ¼è
ééæ°å¹è®ã\n" + |
| | | "\n" + |
| | | "4. 宿æ¼ç»ä¸æç»æ¹è¿\n" + |
| | | "æ¼ç»é¢çï¼\n" + |
| | | "\n" + |
| | | "æ¯å£åº¦è³å°1次æ¡é¢æ¨æ¼ï¼æ¯å¹´2次综å宿æ¼ç»ã\n" + |
| | | "\n" + |
| | | "åºæ¯è®¾è®¡ï¼\n" + |
| | | "\n" + |
| | | "模æå¤ææ
åµï¼å¦å¤é´åçµãå¤äººå伤ï¼ã\n" + |
| | | "\n" + |
| | | "å¼å
¥âçªååéâï¼å¦é£åçªåãäºæ¬¡æ³æ¼ï¼ã\n" + |
| | | "\n" + |
| | | "å¤çä¸ä¼åï¼\n" + |
| | | "\n" + |
| | | "è®°å½æ¼ç»ä¸çé®é¢ï¼å¦é讯延è¿ãè£
å¤ç¼ºå¤±ï¼ã\n" + |
| | | "\n" + |
| | | "æ´æ°é¢æ¡å¹¶ä¸åå¦ä¹ ã\n" + |
| | | "\n" + |
| | | "5. ææ¯åçº§ä¸æºè½åæ¯æ\n" + |
| | | "宿¶çæµä¸é¢è¦ï¼\n" + |
| | | "\n" + |
| | | "é¨ç½²ç©èç½ï¼IoTï¼ä¼ æå¨ï¼çæµæ°ä½æµåº¦ã设å¤ç¶æã\n" + |
| | | "\n" + |
| | | "设置èªå¨èéæ§å¶ï¼å¦æ³æ¼æ¶èå¨å
³ééé¨å¹¶å¯å¨éé£ï¼ã\n" + |
| | | "\n" + |
| | | "åºæ¥é讯系ç»ï¼\n" + |
| | | "\n" + |
| | | "使ç¨é²ç对讲æºã嫿çµè¯ï¼ä¿éä¿¡å·è¦çï¼ã\n" + |
| | | "\n" + |
| | | "建ç«åºæ¥å¹¿æç³»ç»ï¼å¦ååºè¦æ¥ãç信群åï¼ã\n" + |
| | | "\n" + |
| | | "æ°åå颿¡ï¼\n" + |
| | | "\n" + |
| | | "å°åºæ¥é¢æ¡å½å
¥ç§»å¨ç»ç«¯ï¼å®ç°ä¸é®è°é
ãæ¥éª¤æå¼ã" |
| | | } |
| | | |
| | | export function compliance(){ |
| | | return "ä¸ã常è§çåè§æ§é®é¢\n" + |
| | | "1. 许å¯ä¸èµè´¨ç¼ºå¤±\n" + |
| | | "é®é¢ï¼\n" + |
| | | "\n" + |
| | | "æªåå¾å±é©åå¦åç»è¥è®¸å¯è¯æå®å
¨ç产许å¯è¯ã\n" + |
| | | "\n" + |
| | | "ç¹ç§ä½ä¸äººåï¼å¦åå容卿ä½å·¥ï¼æ è¯ä¸å²ã\n" + |
| | | "\n" + |
| | | "é£é©ï¼\n" + |
| | | "\n" + |
| | | "ç管é¨é¨å¤ç½ï¼å¦ç½æ¬¾ã责令å产ï¼ã\n" + |
| | | "\n" + |
| | | "ä¿é©æèµï¼äºæ
åçæ¶ï¼ã\n" + |
| | | "\n" + |
| | | "2. å®å
¨è®¾è®¡ä¸è¾¾æ \n" + |
| | | "é®é¢ï¼\n" + |
| | | "\n" + |
| | | "å¨ç½ãç®¡éæªæGB/T 150ï¼åå容卿 åï¼è®¾è®¡ã\n" + |
| | | "\n" + |
| | | "æªå®è£
å¯ç/ææ¯æ°ä½æ¥è¦å¨ï¼è¿åGB 50493ï¼ã\n" + |
| | | "\n" + |
| | | "é£é©ï¼\n" + |
| | | "\n" + |
| | | "设å¤å¤±æå¯¼è´æ³æ¼æçç¸ã\n" + |
| | | "\n" + |
| | | "ä¸ç¬¦ååºæ¥ç®¡ç鍿OSHAæ£æ¥è¦æ±ã\n" + |
| | | "\n" + |
| | | "3. æä½ä¸ç»´æ¤è¿è§\n" + |
| | | "é®é¢ï¼\n" + |
| | | "\n" + |
| | | "æªæ§è¡ä½ä¸ç¥¨å¶åº¦ï¼å¦å¨ç«ä½ä¸æªå®¡æ¹ï¼ã\n" + |
| | | "\n" + |
| | | "æªå®ææ£éªåå容å¨ï¼è¿åTSG 21-2016ï¼ã\n" + |
| | | "\n" + |
| | | "é£é©ï¼\n" + |
| | | "\n" + |
| | | "è¿è§æä½å¼åäºæ
ï¼å¦çæ¥å¼åå¯çæ°ä½çç¸ï¼ã\n" + |
| | | "\n" + |
| | | "设å¤èå导è´çªåæ³æ¼ã\n" + |
| | | "\n" + |
| | | "4. åºæ¥ç®¡çä¸åè§\n" + |
| | | "é®é¢ï¼\n" + |
| | | "\n" + |
| | | "æªå¶å®åºæ¥é¢æ¡ææªå¤æ¡ï¼è¿åãç产å®å
¨äºæ
åºæ¥æ¡ä¾ãï¼ã\n" + |
| | | "\n" + |
| | | "æªé
å¤åºæ¥ç©èµï¼å¦é²æ¯é¢å
·ãå µæ¼å·¥å
·ï¼ã\n" + |
| | | "\n" + |
| | | "é£é©ï¼\n" + |
| | | "\n" + |
| | | "äºæ
åçæ¶æ æ³æææ§å¶ï¼å¯¼è´æå¤±æ©å¤§ã\n" + |
| | | "\n" + |
| | | "é¢ä¸´çæç¯å¢é¨è¿½è´£ï¼å¦åå¦å污æå壤/æ°´ä½ï¼ã\n" + |
| | | "\n" + |
| | | "5. è®°å½ä¸æ¥å缺失\n" + |
| | | "é®é¢ï¼\n" + |
| | | "\n" + |
| | | "æªä¿åå®å
¨æ£æ¥è®°å½æå¹è®æ¡£æ¡ã\n" + |
| | | "\n" + |
| | | "æªæè§å®ä¸æ¥æ³æ¼äºæ
ï¼å¦çæ¥ãè¿æ¥ï¼ã\n" + |
| | | "\n" + |
| | | "é£é©ï¼\n" + |
| | | "\n" + |
| | | "äºæ
è°æ¥æ¶æ æ³èªè¯åè§ï¼æ¿æ
å
¨è´£ã\n" + |
| | | "\n" + |
| | | "被åå
¥å®å
¨ç产é»ååï¼å½±åä¼ä¸ä¿¡èªã" |
| | | } |
| | | |
| | | export function monitoring(){ |
| | | return "ä¸ãåºå®å¼çæµææ¯\n" + |
| | | "1. å¬åçç§å¼ä¼ æå¨\n" + |
| | | "åçï¼å¯çæ°ä½å¨éä¸è¡¨é¢çç§å¯¼è´çµé»åå\n" + |
| | | "\n" + |
| | | "ä¼å¿ï¼ææ¬ä½ï¼ï¿¥500-2000/个ï¼ãååºå¿«ï¼<10sï¼\n" + |
| | | "\n" + |
| | | "å±éï¼æä¸æ¯ï¼ç¡
/ç¡«ååç©ï¼ã寿å½çï¼2-3å¹´ï¼\n" + |
| | | "\n" + |
| | | "éç¨ï¼ç³ååå¯çæ°çæµï¼ç²ç·ãæ°¢æ°çï¼\n" + |
| | | "\n" + |
| | | "2. çµåå¦ä¼ æå¨\n" + |
| | | "åçï¼æ°ä½ä¸çµè§£æ¶²åçæ°§åè¿åååºäº§ççµæµ\n" + |
| | | "\n" + |
| | | "ä¼å¿ï¼ppbçº§æ£æµï¼å¦H2Sæ£æµä¸é0.1ppmï¼\n" + |
| | | "\n" + |
| | | "å±éï¼å温湿度影åï¼éå®ææ ¡åï¼\n" + |
| | | "\n" + |
| | | "éç¨ï¼ææ¯æ°ä½ï¼ClâãNHâãCOçï¼\n" + |
| | | "\n" + |
| | | "3. 红å¤å¸æ¶å¼ï¼NDIRï¼\n" + |
| | | "åçï¼æ°ä½å¯¹ç¹å®çº¢å¤æ³¢æ®µç叿¶çæ£æµ\n" + |
| | | "\n" + |
| | | "ä¼å¿ï¼å
æ ¡åï¼å¯¿å½5-10å¹´ï¼ãæä¸æ¯\n" + |
| | | "\n" + |
| | | "å±éï¼é«ææ¬ï¼ï¿¥5000+/个ï¼\n" + |
| | | "\n" + |
| | | "éç¨ï¼COâãCHâçæ¸©å®¤æ°ä½çæµ\n" + |
| | | "\n" + |
| | | "4. æ¿å
å
è°±ï¼TDLASï¼\n" + |
| | | "åçï¼å¯è°è°æ¿å
äºæç®¡æ«ææ°ä½å¸æ¶çº¿\n" + |
| | | "\n" + |
| | | "ä¼å¿ï¼ppm级精度ãååºms级\n" + |
| | | "\n" + |
| | | "å±éï¼éå
å¦å¯¹åï¼å®è£
夿ï¼\n" + |
| | | "\n" + |
| | | "éç¨ï¼ç®¡éå¾®æ³æ¼æ£æµï¼å¤©ç¶æ°é¿è¾ç®¡çº¿ï¼" |
| | | } |
| | | |
| | | export function checking(keyWord){ |
| | | if(keyWord.includes("æ°ä½æ³æ¼")){ |
| | | return gasLeaks(); |
| | | } |
| | | if(keyWord.includes("容å¨å¤±æ")){ |
| | | return shipping(); |
| | | } |
| | | if(keyWord.includes("æä½ä¸å½")){ |
| | | return operate(); |
| | | } |
| | | if(keyWord.includes("ååºä¸è¶³")){ |
| | | return emergency(); |
| | | } |
| | | if(keyWord.includes("åè§æ§")){ |
| | | return compliance(); |
| | | } |
| | | if(keyWord.includes("çæµææ¯")){ |
| | | return monitoring(); |
| | | } |
| | | return "ä¸å¥½ææï¼å°æºè¿å¨æé¿è¿ç¨ä¸ï¼æ¨çé®é¢å·²ç»è¶
è¿å°æºçå¤çèå´äºã"; |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="home"> |
| | | <div style="background: white;color: black;font-size: 30px;" class="logo"> |
| | | <div class="logo-one" style="font-weight: bold"> |
| | | <!-- <img src="/src/assets/img/logo.png" style="width: 50px;height: 50px;margin: 0 10px" />--> |
| | | <div><i>大模åAIå°æºæ£å¨ä¸ºæ¨æå¡</i></div> |
| | | </div> |
| | | <div class="input"> |
| | | <input type="text" v-model="keyWord" class="input-text" placeholder="ç»å°æºåéæ¶æ¯" @keyup.enter="sendMsg" /> |
| | | <div style="font-size: 13px;color: #808080;display: flex;justify-content: space-between;padding: 10px;"> |
| | | <div style="display: flex;justify-content: center;align-items: center;"> |
| | | <!-- <div style="display: flex;justify-content: center;align-items: center;">--> |
| | | <!-- <img src="/src/assets/img/logo.png" style="width: 15px;height: 15px;margin: 0 5px" />--> |
| | | <!-- <span>深度æè(R1)</span>--> |
| | | <!-- </div>--> |
| | | <!-- <div style="display: flex;justify-content: center;align-items: center;">--> |
| | | <!-- <img src="/src/assets/img/logo.png" style="width: 15px;height: 15px;margin: 0 5px" />--> |
| | | <!-- <span>èç½æç´¢</span>--> |
| | | <!-- </div>--> |
| | | </div> |
| | | <div style="display: flex;justify-content: center;align-items: center;margin-right: 5px;"> |
| | | <!-- <img src="/src/assets/img/logo.png" style="width: 25px;height: 25px;margin: 0 5px" />--> |
| | | <img src="@/assets/img/emoji/rocket.png" style="width: 25px;height: 25px;margin: 0 5px" @click="sendMsg"/> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div style="width: 780px;"> |
| | | <div style="font-weight: bold;margin: 30px 0;">ç鍿¨è</div> |
| | | <div class="keywords"> |
| | | <div class="keywordss" @click="sendMsgDefault(keyWordOne)"> |
| | | <p class="fontSize aaa">{{keyWordOne}}</p> |
| | | <p class="fontSize">éé¨ã管éæå®¹å¨å¯å°å¤±æå¯¼è´æ°ä½æ³æ¼ï¼å¦æ°¯æ°ãæ°¨æ°ï¼ã</p> |
| | | <p class="fontSize">åæï¼ä¸æ¯ãçç¸ãç¯å¢æ±¡æã</p> |
| | | </div> |
| | | <div class="keywordss" @click="sendMsgDefault(keyWordTwo)"> |
| | | <p class="fontSize aaa">{{keyWordTwo}}</p> |
| | | <p class="fontSize">é¢ç¶æç½ä½å ææç²å³ãè
èæè¶
åç ´è£</p> |
| | | <p class="fontSize">åå ï¼æªå®ææ£æµãè¿è§å
è£
æå¤é¨æå»ãã</p> |
| | | </div> |
| | | </div> |
| | | <div class="keywords"> |
| | | <div class="keywordss" @click="sendMsgDefault(keyWordFive)"> |
| | | <p class="fontSize aaa">{{keyWordFive}}</p> |
| | | <p class="fontSize">è£
å¸è¿ç¨ä¸è¿è§æä½ï¼å¦éè®æ¬è¿ãæ··è£
ç¦å¿ç©è´¨ï¼ã</p> |
| | | <p class="fontSize">è¿è¾é䏿ªåºå®å®¹å¨ï¼å¯¼è´ç¢°ææå¾åã</p> |
| | | </div> |
| | | <div class="keywordss" @click="sendMsgDefault(keyWordSix)"> |
| | | <p class="fontSize aaa">{{keyWordSix}}</p> |
| | | <p class="fontSize">ç¼ºä¹æ³æ¼åºæ¥é¢æ¡ï¼äººåå¹è®ä¸è¶³ã</p> |
| | | <p class="fontSize">ææ´è®¾å¤ï¼å¦é²æ¯é¢å
·ãå µæ¼å·¥å
·ï¼ç¼ºå¤±æå¤±æã</p> |
| | | </div> |
| | | </div> |
| | | <div class="keywords"> |
| | | <div class="keywordss" @click="sendMsgDefault(keyWordServen)"> |
| | | <p class="fontSize aaa">{{keyWordServen}}</p> |
| | | <p class="fontSize">æªåå¾è¿è¾èµè´¨ï¼å¦ADR/RIDçå½é
è§èï¼ã</p> |
| | | <p class="fontSize">路线è§åä¸åè§ï¼å¦ç©¿è¶äººå£å¯éåºï¼ã</p> |
| | | </div> |
| | | <div class="keywordss" @click="sendMsgDefault(keyWordEight)"> |
| | | <p class="fontSize aaa">{{keyWordEight}}</p> |
| | | <p class="fontSize">ä¼ æå¨é¨ç½²ï¼å¦çº¢å¤æ°ä½æ¢æµå¨ãçµåå¦ä¼ æå¨ï¼ã</p> |
| | | <p class="fontSize">宿¶æ°æ®ä¼ è¾è³çæ§å¹³å°ï¼è§¦åæ¥è¦ã</p> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div></div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref,onMounted } from "vue"; |
| | | import {useRoute,useRouter} from "vue-router" |
| | | const route = useRoute(); |
| | | const router = useRouter(); |
| | | const keyWord = ref(''); |
| | | const keyWordOne = ref('å±é©æ°ä½æ³æ¼æä¹å'); |
| | | const keyWordTwo = ref('è¿è¾å®¹å¨å¤±ææä¹å'); |
| | | const keyWordFive = ref('æä½ä¸å½æä¹å'); |
| | | const keyWordSix = ref('åºæ¥ååºä¸è¶³æä¹å'); |
| | | const keyWordServen = ref('åè§æ§é®é¢'); |
| | | const keyWordEight = ref('æ³æ¼çæµææ¯æåªäº'); |
| | | |
| | | const sendMsg = () => { |
| | | router.push({ path: '/main/MobileChat',query:{ keyWord: keyWord.value} }) |
| | | } |
| | | |
| | | const sendMsgDefault = (value) => { |
| | | router.push({ path: '/main/MobileChat',query:{ keyWord: value} }) |
| | | } |
| | | |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .home { |
| | | width: 100%; |
| | | height: 91vh; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | |
| | | .logo { |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | flex-direction: column; |
| | | z-index: 99; |
| | | width: 100%; |
| | | height: 100%; |
| | | color: #fff; |
| | | cursor: pointer; |
| | | overflow: hidden; |
| | | background-color: #F0F6F9; |
| | | |
| | | .keywords { |
| | | display: flex; |
| | | width: 100%; |
| | | height: 90px; |
| | | line-height: 80px; |
| | | justify-content: space-between; |
| | | margin: 10px 0; |
| | | |
| | | .keywordss { |
| | | box-shadow: 0px 2px 5px #b8b8b8; |
| | | width: 48%; |
| | | background: #e0edfc; |
| | | border-radius: 10px; |
| | | |
| | | .aaa { |
| | | font-weight: bold; |
| | | font-size: 15px !important; |
| | | } |
| | | |
| | | .fontSize { |
| | | font-size: 13px; |
| | | height: 20px; |
| | | line-height: 20px; |
| | | margin: 6px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .logo-one { |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .input { |
| | | width: 780px; |
| | | height: 150px; |
| | | background: #f5f4f4; |
| | | border-radius: 20px; |
| | | |
| | | .input-text { |
| | | font-size: 18px; |
| | | width: 568px; |
| | | border-radius: 20px 20px 0 0; |
| | | height: 90px; |
| | | padding-left: 10px; |
| | | border: none; |
| | | color: black; |
| | | background-color: #f5f4f4; |
| | | } |
| | | |
| | | .input-text:focus { |
| | | outline: none; |
| | | border: none; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | |
| | | <div v-if="!activity.isShen" class="node-reason"> |
| | | <span>å®¡æ¹æè§ï¼</span>{{ activity.approveNodeReason }} |
| | | </div> |
| | | <div v-if="!activity.isShen" class="node-reason"> |
| | | <span>ç¾åï¼</span> |
| | | <img :src="activity.urlTem" class="signImg" alt="" v-if="activity.urlTem"/> |
| | | </div> |
| | | <div v-else-if="activity.isShen"> |
| | | <el-form-item |
| | | :prop="'activities.' + index + '.approveNodeReason'" |
| | |
| | | <template #footer v-if="operationType === 'approval'"> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm(2)">ä¸éè¿</el-button> |
| | | <el-button type="primary" @click="submitForm(1)">éè¿</el-button> |
| | | <el-button type="primary" @click="openSignatureDialog(1)">éè¿</el-button> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | <!-- çµåç¾åå¼¹çªï¼vue3-signature-padï¼ --> |
| | | <el-dialog v-model="signatureDialogVisible" title="çµåç¾å" width="600px" append-to-body> |
| | | <vueEsign |
| | | ref="esign" |
| | | class="mySign" |
| | | :width="800" |
| | | :height="300" |
| | | :isCrop="isCrop" |
| | | :lineWidth="lineWidth" |
| | | :lineColor="lineColor" |
| | | /> |
| | | <div style="margin-top:10px;"> |
| | | <el-button @click="clearSignature">æ¸
é¤</el-button> |
| | | <el-button type="primary" @click="confirmSignature">ç¡®å®</el-button> |
| | | </div> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {getCurrentInstance, reactive, ref, toRefs} from "vue"; |
| | | import { getCurrentInstance, reactive, ref, toRefs } from "vue"; |
| | | import vueEsign from "vue-esign"; |
| | | import { |
| | | approveProcessDetails, |
| | | getDept, |
| | |
| | | import useUserStore from "@/store/modules/user.js"; |
| | | import {userListNoPageByTenantId} from "@/api/system/user.js"; |
| | | import { WarningFilled, Edit, Check, MoreFilled } from '@element-plus/icons-vue' |
| | | import { getToken } from "@/utils/auth"; |
| | | const emit = defineEmits(['close']) |
| | | const { proxy } = getCurrentInstance() |
| | | |
| | |
| | | }, |
| | | }); |
| | | const { form } = toRefs(data); |
| | | const signatureDialogVisible = ref(false); |
| | | const signatureImg = ref(''); |
| | | let submitStatus = null; // 临æ¶åå¨éè¿/ä¸éè¿ç¶æ |
| | | const isCrop = ref(""); |
| | | const esign = ref(null); |
| | | const lineWidth = ref(0); |
| | | const lineColor = ref("#000000"); |
| | | |
| | | // ä¸ä¼ é
ç½® |
| | | const upload = reactive({ |
| | | // ä¸ä¼ çå°å |
| | | url: import.meta.env.VITE_APP_BASE_API + "/file/upload", |
| | | // 设置ä¸ä¼ ç请æ±å¤´é¨ |
| | | headers: { Authorization: "Bearer " + getToken() }, |
| | | }); |
| | | |
| | | // èç¹æ é¢ |
| | | const getNodeTitle = (index, len) => { |
| | | if (index === len - 1) return 'ç»æ'; |
| | |
| | | activities.value = res.data |
| | | // å¢å isApprovalåæ®µ |
| | | activities.value.forEach(item => { |
| | | if (item.url && item.url.includes('word')) { |
| | | item.urlTem = item.url.replaceAll('word', 'img') |
| | | } else { |
| | | item.urlTem = item.url |
| | | } |
| | | if (item.approveNodeStatus === 2) { |
| | | item.isApproval = '已驳å'; |
| | | } else if (item.approveNodeStatus === 1) { |
| | |
| | | productOptions.value = res.data; |
| | | }); |
| | | }; |
| | | // æå¼ç¾åå¼¹çª |
| | | const openSignatureDialog = (status) => { |
| | | submitStatus = status; |
| | | signatureDialogVisible.value = true; |
| | | }; |
| | | // æ¸
é¤ç¾å |
| | | const clearSignature = () => { |
| | | esign.value.reset(); |
| | | }; |
| | | // 确认ç¾å |
| | | const confirmSignature = () => { |
| | | esign.value.generate().then((res) => { |
| | | console.log(res); |
| | | // å°base64转æ¢ä¸ºäºè¿å¶ |
| | | const base64Data = res.split(',')[1]; // ç§»é¤data:image/png;base64,åç¼ |
| | | const binaryString = atob(base64Data); |
| | | const bytes = new Uint8Array(binaryString.length); |
| | | for (let i = 0; i < binaryString.length; i++) { |
| | | bytes[i] = binaryString.charCodeAt(i); |
| | | } |
| | | signatureImg.value = bytes; |
| | | |
| | | // å建æä»¶å¯¹è±¡ç¨äºä¸ä¼ |
| | | const blob = new Blob([bytes], { type: 'image/png' }); |
| | | const file = new File([blob], 'signature.png', { type: 'image/png' }); |
| | | |
| | | // å建FormData |
| | | const formData = new FormData(); |
| | | formData.append('file', file); |
| | | |
| | | // ä¸ä¼ ç¾åå¾ç |
| | | fetch(upload.url, { |
| | | method: 'POST', |
| | | headers: upload.headers, |
| | | body: formData |
| | | }) |
| | | .then(response => response.json()) |
| | | .then(data => { |
| | | if (data.code === 200) { |
| | | console.log('data---', data) |
| | | let tempFileIds = []; |
| | | tempFileIds.push(data.data.tempId); |
| | | signatureDialogVisible.value = false; |
| | | clearSignature(); |
| | | // åªæéè¿æ¶æä¼ éç¾åæä»¶ID |
| | | if (submitStatus === 1) { |
| | | submitForm(submitStatus, tempFileIds); |
| | | } else { |
| | | submitForm(submitStatus); |
| | | } |
| | | } else { |
| | | proxy.$modal.msgError("ç¾åå¾çä¸ä¼ 失败ï¼" + data.msg); |
| | | } |
| | | }) |
| | | .catch(error => { |
| | | console.error('ä¸ä¼ 失败:', error); |
| | | proxy.$modal.msgError("ç¾åå¾çä¸ä¼ 失败"); |
| | | }); |
| | | }).catch((err) => { |
| | | console.log(err); |
| | | proxy.$modal.msgWarning("请å
ç¾åï¼"); |
| | | }) |
| | | }; |
| | | // æäº¤å®¡æ¹ |
| | | const submitForm = (status) => { |
| | | const submitForm = (status, tempFileIds) => { |
| | | const filteredActivities = activities.value.filter(activity => activity.isShen); |
| | | filteredActivities[0].approveNodeStatus = status |
| | | filteredActivities[0].approveNodeStatus = status; |
| | | // åªæéè¿æ¶æéè¦ç¾å |
| | | if (status === 1 && tempFileIds) { |
| | | filteredActivities[0].tempFileIds = tempFileIds; |
| | | } |
| | | // 夿æ¯å¦ä¸ºæå䏿¥ |
| | | const isLast = activities.value.findIndex(a => a.isShen) === activities.value.length-1; |
| | | updateApproveNode({ ...filteredActivities[0], isLast }).then(() => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | }) |
| | | } |
| | | }); |
| | | }; |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | |
| | | height: 30px; |
| | | border-radius: 50px; |
| | | } |
| | | .signImg { |
| | | cursor: pointer; |
| | | width: 200px; |
| | | height: 60px; |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div> |
| | | <el-dialog |
| | | v-model="dialogFormVisible" |
| | | title="ç¨æ°´è®¾å¤" |
| | | width="70%" |
| | | @close="closeDia" |
| | | > |
| | | <el-form |
| | | :model="form" |
| | | label-width="140px" |
| | | label-position="top" |
| | | :rules="rules" |
| | | ref="formRef" |
| | | > |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="设å¤ï¼" prop="deviceModel"> |
| | | <el-select |
| | | v-model="form.deviceModel" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | @change="setName" |
| | | :disabled="operationType !== 'add'" |
| | | > |
| | | <el-option |
| | | v-for="item in codeList" |
| | | :key="item.deviceModel" |
| | | :label="item.deviceName" |
| | | :value="item.deviceModel" |
| | | > |
| | | {{item.deviceName + '--' + item.deviceModel}} |
| | | </el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ¯æ¥éå¶æ°´éï¼" prop="waterDayLimit"> |
| | | <el-input |
| | | v-model="form.waterDayLimit" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="é¢å®æµéï¼" prop="ratedRate"> |
| | | <el-input |
| | | v-model="form.ratedRate" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å®é
æµéï¼" prop="actualTraffic"> |
| | | <el-input |
| | | v-model="form.actualTraffic" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="è¿è¡æ¶é´ï¼" prop="runTime"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="form.runTime" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="彿¥ç¨æ°´éï¼" prop="waterDay"> |
| | | <el-input |
| | | v-model="form.waterDay" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ°´è´¹åä»·ï¼" prop="waterPrice"> |
| | | <el-input |
| | | v-model="form.waterPrice" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç¨æ°´ç±»åï¼" prop="type"> |
| | | <el-select |
| | | v-model="form.type" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | > |
| | | <el-option label="å·¥ä¸ç¨æ°´" value="industrial" /> |
| | | <el-option label="çæ´»ç¨æ°´" value="domestic" /> |
| | | <el-option label="æ¶é²ç¨æ°´" value="fire" /> |
| | | <el-option label="绿åç¨æ°´" value="greening" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm">确认</el-button> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref, reactive, nextTick} from "vue"; |
| | | import useUserStore from "@/store/modules/user.js"; |
| | | import {waterDeviceList, waterEquipmentAdd, waterEquipmentUpdate} from "@/api/energyManagement/waterManagement.js"; |
| | | const { proxy } = getCurrentInstance() |
| | | const emit = defineEmits(['close']) |
| | | const dialogFormVisible = ref(false); |
| | | const operationType = ref('') |
| | | const userStore = useUserStore(); |
| | | |
| | | const data = reactive({ |
| | | form: { |
| | | deviceName: "", |
| | | deviceModel: "", |
| | | waterDayLimit: "", |
| | | ratedRate: "", |
| | | actualTraffic: "", |
| | | runTime: "", |
| | | waterDay: "", |
| | | waterPrice: "", |
| | | type: "", |
| | | }, |
| | | rules: { |
| | | deviceModel: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | runTime: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | waterDayLimit: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | ratedRate: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | actualTraffic: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | waterDay: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | waterPrice: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | type: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | }, |
| | | }) |
| | | const { form, rules } = toRefs(data); |
| | | const codeList = ref([]) |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openDialog = (type, row) => { |
| | | operationType.value = type; |
| | | dialogFormVisible.value = true; |
| | | form.value = {} |
| | | proxy.resetForm("formRef"); |
| | | waterDeviceList({size: -1}).then((res) => { |
| | | codeList.value = res.data.records; |
| | | }); |
| | | if (type === "edit") { |
| | | form.value = {...row} |
| | | } |
| | | } |
| | | const setName = (code) => { |
| | | const index = codeList.value.findIndex(item => item.deviceModel === code); |
| | | if (index > -1) { |
| | | console.log(codeList) |
| | | form.value.name = codeList.value[index].deviceName; |
| | | } |
| | | } |
| | | const submitForm = () => { |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | if (valid) { |
| | | if (operationType.value === "add") { |
| | | waterEquipmentAdd(form.value).then(response => { |
| | | proxy.$modal.msgSuccess("æ°å¢æå") |
| | | closeDia() |
| | | }) |
| | | } else { |
| | | waterEquipmentUpdate(form.value).then(response => { |
| | | proxy.$modal.msgSuccess("ä¿®æ¹æå") |
| | | closeDia() |
| | | }) |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | dialogFormVisible.value = false; |
| | | emit('close') |
| | | }; |
| | | // è·åå½åæ¥æå¹¶æ ¼å¼å为 YYYY-MM-DD |
| | | function getCurrentDate() { |
| | | const today = new Date(); |
| | | const year = today.getFullYear(); |
| | | const month = String(today.getMonth() + 1).padStart(2, "0"); // æä»½ä»0å¼å§ |
| | | const day = String(today.getDate()).padStart(2, "0"); |
| | | return `${year}-${month}-${day}`; |
| | | } |
| | | defineExpose({ |
| | | openDialog, |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div> |
| | | <el-dialog |
| | | v-model="dialogFormVisible" |
| | | title="水费管ç" |
| | | width="70%" |
| | | @close="closeDia" |
| | | > |
| | | <el-form |
| | | :model="form" |
| | | label-width="140px" |
| | | label-position="top" |
| | | :rules="rules" |
| | | ref="formRef" |
| | | > |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="设å¤ï¼" prop="code"> |
| | | <el-select |
| | | v-model="form.code" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | @change="setName" |
| | | :disabled="operationType !== 'add'" |
| | | > |
| | | <el-option |
| | | v-for="item in codeList" |
| | | :key="item.deviceModel" |
| | | :label="item.deviceName" |
| | | :value="item.deviceModel" |
| | | > |
| | | {{item.deviceName + '--' + item.deviceModel}} |
| | | </el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç¨æ°´éï¼" prop="waterConsumption"> |
| | | <el-input |
| | | v-model="form.waterConsumption" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ°´è´¹åä»·ï¼" prop="waterPrice"> |
| | | <el-input |
| | | v-model="form.waterPrice" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ°´è´¹éé¢ï¼" prop="waterBill"> |
| | | <el-input |
| | | v-model="form.waterBill" |
| | | placeholder="èªå¨è®¡ç®" |
| | | clearable |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="è®¡è´¹æ¥æï¼" prop="billDate"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="form.billDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç¨æ°´ç±»åï¼" prop="waterType"> |
| | | <el-select |
| | | v-model="form.waterType" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | > |
| | | <el-option label="å·¥ä¸ç¨æ°´" value="industrial" /> |
| | | <el-option label="çæ´»ç¨æ°´" value="domestic" /> |
| | | <el-option label="æ¶é²ç¨æ°´" value="fire" /> |
| | | <el-option label="绿åç¨æ°´" value="greening" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm">确认</el-button> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref, reactive, nextTick, watch} from "vue"; |
| | | import useUserStore from "@/store/modules/user.js"; |
| | | import {waterDeviceList, waterBillAdd, waterBillUpdate} from "@/api/energyManagement/waterManagement.js"; |
| | | const { proxy } = getCurrentInstance() |
| | | const emit = defineEmits(['close']) |
| | | const dialogFormVisible = ref(false); |
| | | const operationType = ref('') |
| | | const userStore = useUserStore(); |
| | | |
| | | const data = reactive({ |
| | | form: { |
| | | name: "", |
| | | code: "", |
| | | waterConsumption: "", |
| | | waterPrice: "", |
| | | waterBill: "", |
| | | billDate: "", |
| | | waterType: "", |
| | | }, |
| | | rules: { |
| | | code: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | waterConsumption: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | waterPrice: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | billDate: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | waterType: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | }, |
| | | }) |
| | | const { form, rules } = toRefs(data); |
| | | const codeList = ref([]) |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openDialog = (type, row) => { |
| | | operationType.value = type; |
| | | dialogFormVisible.value = true; |
| | | form.value = {} |
| | | proxy.resetForm("formRef"); |
| | | waterDeviceList().then((res) => { |
| | | codeList.value = res.data; |
| | | }); |
| | | if (type === "edit") { |
| | | form.value = {...row} |
| | | } |
| | | } |
| | | const setName = (code) => { |
| | | const index = codeList.value.findIndex(item => item.deviceModel === code); |
| | | if (index > -1) { |
| | | console.log(codeList) |
| | | form.value.name = codeList.value[index].deviceName; |
| | | } |
| | | } |
| | | |
| | | // è®¡ç®æ°´è´¹éé¢ |
| | | const calculateWaterBill = () => { |
| | | if (form.value.waterConsumption && form.value.waterPrice) { |
| | | form.value.waterBill = (parseFloat(form.value.waterConsumption) * parseFloat(form.value.waterPrice)).toFixed(2); |
| | | } |
| | | } |
| | | |
| | | // çå¬ç¨æ°´éåæ°´è´¹åä»·åå |
| | | watch([() => form.value.waterConsumption, () => form.value.waterPrice], () => { |
| | | calculateWaterBill(); |
| | | }); |
| | | |
| | | const submitForm = () => { |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | if (valid) { |
| | | if (operationType.value === "add") { |
| | | waterBillAdd(form.value).then(response => { |
| | | proxy.$modal.msgSuccess("æ°å¢æå") |
| | | closeDia() |
| | | }) |
| | | } else { |
| | | waterBillUpdate(form.value).then(response => { |
| | | proxy.$modal.msgSuccess("ä¿®æ¹æå") |
| | | closeDia() |
| | | }) |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | dialogFormVisible.value = false; |
| | | emit('close') |
| | | }; |
| | | // è·åå½åæ¥æå¹¶æ ¼å¼å为 YYYY-MM-DD |
| | | function getCurrentDate() { |
| | | const today = new Date(); |
| | | const year = today.getFullYear(); |
| | | const month = String(today.getMonth() + 1).padStart(2, "0"); // æä»½ä»0å¼å§ |
| | | const day = String(today.getDate()).padStart(2, "0"); |
| | | return `${year}-${month}-${day}`; |
| | | } |
| | | defineExpose({ |
| | | openDialog, |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title">设å¤åç§°ï¼</span> |
| | | <el-input |
| | | v-model="searchForm.deviceName" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | /> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px" |
| | | >æç´¢</el-button |
| | | > |
| | | </div> |
| | | <div> |
| | | <el-button type="primary" @click="openForm('add')">æ°å¢</el-button> |
| | | <el-button type="info" plain icon="Upload" @click="handleImport">导å
¥</el-button> |
| | | <el-button type="danger" plain @click="handleDelete">å é¤</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | ></PIMTable> |
| | | </div> |
| | | <form-dia ref="formDia" @close="handleQuery"></form-dia> |
| | | <el-dialog |
| | | :title="upload.title" |
| | | v-model="upload.open" |
| | | width="400px" |
| | | append-to-body |
| | | @close="handleDialogClose" |
| | | > |
| | | <el-upload |
| | | ref="uploadRef" |
| | | :limit="1" |
| | | accept=".xlsx, .xls" |
| | | :headers="upload.headers" |
| | | :action="upload.url" |
| | | :disabled="upload.isUploading" |
| | | :before-upload="upload.beforeUpload" |
| | | :on-progress="upload.onProgress" |
| | | :on-success="upload.onSuccess" |
| | | :on-error="upload.onError" |
| | | :on-change="upload.onChange" |
| | | :auto-upload="false" |
| | | drag |
| | | > |
| | | <el-icon class="el-icon--upload"><upload-filled /></el-icon> |
| | | <div class="el-upload__text">å°æä»¶æå°æ¤å¤ï¼æ<em>ç¹å»ä¸ä¼ </em></div> |
| | | <template #tip> |
| | | <div class="el-upload__tip text-center"> |
| | | <span>ä»
å
许导å
¥xlsãxlsxæ ¼å¼æä»¶ã</span> |
| | | <el-link |
| | | type="primary" |
| | | :underline="false" |
| | | style="font-size: 12px; vertical-align: baseline" |
| | | @click="importTemplate" |
| | | >ä¸è½½æ¨¡æ¿</el-link |
| | | > |
| | | </div> |
| | | </template> |
| | | </el-upload> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitFileForm">ç¡® å®</el-button> |
| | | <el-button @click="upload.open = false">å æ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {Search} from "@element-plus/icons-vue"; |
| | | import {onMounted, ref, reactive, nextTick} from "vue"; |
| | | import FormDia from "@/views/energyManagement/waterManagement/components/formDia.vue"; |
| | | import {ElMessageBox} from "element-plus"; |
| | | import {getToken} from "@/utils/auth.js"; |
| | | import {waterEquipmentDelete, waterEquipmentListPage} from "@/api/energyManagement/waterManagement.js"; |
| | | const { proxy } = getCurrentInstance(); |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | name: "", |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | |
| | | const selectedRows = ref([]); |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "设å¤åç§°", |
| | | prop: "deviceName", |
| | | width: 200, |
| | | }, |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | prop: "deviceModel", |
| | | width: 200, |
| | | }, |
| | | { |
| | | label: "é¢å®æµé", |
| | | prop: "ratedRate", |
| | | }, |
| | | { |
| | | label: "å®é
æµé", |
| | | prop: "actualTraffic", |
| | | }, |
| | | { |
| | | label: "è¿è¡æ¶é´", |
| | | prop: "runTime", |
| | | width:150 |
| | | }, |
| | | { |
| | | label: "彿¥ç¨æ°´é", |
| | | prop: "waterDay", |
| | | width: 150, |
| | | }, |
| | | { |
| | | label: "æ¯æ¥éå¶æ°´é", |
| | | prop: "waterDayLimit", |
| | | width:220 |
| | | }, |
| | | { |
| | | label: "æ°´è´¹åä»·", |
| | | prop: "waterPrice", |
| | | width: 120, |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: 'right', |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openForm("edit", row); |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | const formDia = ref() |
| | | const upload = reactive({ |
| | | // æ¯å¦æ¾ç¤ºå¼¹åºå±ï¼å®¢æ·å¯¼å
¥ï¼ |
| | | open: false, |
| | | // å¼¹åºå±æ é¢ï¼å®¢æ·å¯¼å
¥ï¼ |
| | | title: "", |
| | | // æ¯å¦ç¦ç¨ä¸ä¼ |
| | | isUploading: false, |
| | | // 设置ä¸ä¼ ç请æ±å¤´é¨ |
| | | headers: { Authorization: "Bearer " + getToken() }, |
| | | // ä¸ä¼ çå°å |
| | | url: import.meta.env.VITE_APP_BASE_API + "/waterRecord/importData", |
| | | // æä»¶ä¸ä¼ åçåè° |
| | | beforeUpload: (file) => { |
| | | console.log('æä»¶å³å°ä¸ä¼ ', file); |
| | | // å¯ä»¥å¨æ¤å¤åæä»¶ç±»åæå¤§å°æ ¡éª |
| | | const isValid = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' || file.name.endsWith('.xlsx') || file.name.endsWith('.xls'); |
| | | if (!isValid) { |
| | | proxy.$modal.msgError("åªè½ä¸ä¼ Excel æä»¶"); |
| | | } |
| | | return isValid; |
| | | }, |
| | | // æä»¶ç¶ææ¹åæ¶çåè° |
| | | onChange: (file, fileList) => { |
| | | console.log('æä»¶ç¶ææ¹å', file, fileList); |
| | | }, |
| | | // æä»¶ä¸ä¼ æåæ¶çåè° |
| | | onSuccess: (response, file, fileList) => { |
| | | console.log('ä¸ä¼ æå', response, file, fileList); |
| | | if(response.code === 200){ |
| | | proxy.$modal.msgSuccess("æä»¶ä¸ä¼ æå"); |
| | | }else if(response.code === 500){ |
| | | proxy.$modal.msgError(response.msg); |
| | | }else{ |
| | | proxy.$modal.msgError("æä»¶ä¸ä¼ 失败"); |
| | | } |
| | | upload.open = false; |
| | | getList(); |
| | | }, |
| | | // æä»¶ä¸ä¼ 失败æ¶çåè° |
| | | onError: (error, file, fileList) => { |
| | | console.log('ä¸ä¼ 失败', error, file, fileList); |
| | | proxy.$modal.msgError("æä»¶ä¸ä¼ 失败"); |
| | | upload.open = false; |
| | | }, |
| | | // æä»¶ä¸ä¼ è¿åº¦æ¹åæ¶çåè° |
| | | onProgress: (event, file, fileList) => { |
| | | console.log('ä¸ä¼ è¿åº¦', event, file, fileList); |
| | | upload.isUploading = true; |
| | | }, |
| | | }); |
| | | |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const pagination = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | waterEquipmentListPage({ ...searchForm.value, ...page }).then((res) => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }).catch(() => { |
| | | tableLoading.value = false; |
| | | }) |
| | | }; |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openForm = (type, row) => { |
| | | nextTick(() => { |
| | | formDia.value?.openDialog(type, row) |
| | | }) |
| | | }; |
| | | |
| | | /** 导å
¥æé®æä½ */ |
| | | function handleImport() { |
| | | upload.title = "ç¨æ°´è®¾å¤"; |
| | | upload.open = true; |
| | | // æ¸
ç©ºä¸æ¬¡ä¸ä¼ çæä»¶å表 |
| | | nextTick(() => { |
| | | proxy.$refs["uploadRef"]?.clearFiles(); |
| | | }); |
| | | } |
| | | function importTemplate() { |
| | | proxy.download( |
| | | "/waterRecord/export", |
| | | {}, |
| | | 'ç¨æ°´è®¾å¤å¯¼å
¥æ¨¡ç.xlsx' |
| | | ); |
| | | } |
| | | /** æäº¤ä¸ä¼ æä»¶ */ |
| | | function submitFileForm() { |
| | | proxy.$refs["uploadRef"].submit(); |
| | | } |
| | | |
| | | /** å¼¹æ¡å
³éæ¶æ¸
空æä»¶å表 */ |
| | | function handleDialogClose() { |
| | | nextTick(() => { |
| | | proxy.$refs["uploadRef"]?.clearFiles(); |
| | | }); |
| | | } |
| | | |
| | | const handleDelete = () => { |
| | | let ids = []; |
| | | if (selectedRows.value.length > 0) { |
| | | ids = selectedRows.value.map((item) => item.id); |
| | | } else { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | | } |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "å é¤æç¤º", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | tableLoading.value = true; |
| | | waterEquipmentDelete(ids) |
| | | .then((res) => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }) |
| | | .finally(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title">设å¤åç§°ï¼</span> |
| | | <el-input |
| | | v-model="searchForm.name" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | /> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px" |
| | | >æç´¢</el-button |
| | | > |
| | | </div> |
| | | <div> |
| | | <el-button type="primary" @click="openForm('add')">æ°å¢</el-button> |
| | | <el-button type="danger" plain @click="handleDelete">å é¤</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | ></PIMTable> |
| | | </div> |
| | | <form-dia ref="formDia" @close="handleQuery"></form-dia> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {Search} from "@element-plus/icons-vue"; |
| | | import {onMounted, ref, reactive, nextTick} from "vue"; |
| | | import FormDia from "@/views/energyManagement/waterManagement/components/waterBillForm.vue"; |
| | | import {ElMessageBox} from "element-plus"; |
| | | import {waterBillDelete, waterBillListPage} from "@/api/energyManagement/waterManagement.js"; |
| | | const { proxy } = getCurrentInstance(); |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | name: "", |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | |
| | | const selectedRows = ref([]); |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "设å¤åç§°", |
| | | prop: "name", |
| | | width: 200, |
| | | }, |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | prop: "code", |
| | | width: 200, |
| | | }, |
| | | { |
| | | label: "ç¨æ°´é", |
| | | prop: "waterConsumption", |
| | | }, |
| | | { |
| | | label: "æ°´è´¹åä»·", |
| | | prop: "waterPrice", |
| | | }, |
| | | { |
| | | label: "æ°´è´¹éé¢", |
| | | prop: "waterBill", |
| | | width:150 |
| | | }, |
| | | { |
| | | label: "è®¡è´¹æ¥æ", |
| | | prop: "billDate", |
| | | width: 150, |
| | | }, |
| | | { |
| | | label: "ç¨æ°´ç±»å", |
| | | prop: "waterType", |
| | | width:120 |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: 'right', |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openForm("edit", row); |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | const formDia = ref() |
| | | |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const pagination = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | waterBillListPage({ ...searchForm.value, ...page }).then((res) => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }); |
| | | }; |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openForm = (type, row) => { |
| | | nextTick(() => { |
| | | formDia.value?.openDialog(type, row) |
| | | }) |
| | | }; |
| | | |
| | | const handleDelete = () => { |
| | | let ids = []; |
| | | if (selectedRows.value.length > 0) { |
| | | ids = selectedRows.value.map((item) => item.id); |
| | | } else { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | | } |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "å é¤æç¤º", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | tableLoading.value = true; |
| | | waterBillDelete(ids) |
| | | .then((res) => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }) |
| | | .finally(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title">设å¤åç§°ï¼</span> |
| | | <el-input |
| | | v-model="searchForm.name" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | /> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px" |
| | | >æç´¢</el-button |
| | | > |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | ></PIMTable> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {Search} from "@element-plus/icons-vue"; |
| | | import {onMounted, ref, reactive} from "vue"; |
| | | import {listPageByWaterTrend} from "@/api/energyManagement/waterManagement.js"; |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | name: "", |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | |
| | | const selectedRows = ref([]); |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "设å¤åç§°", |
| | | prop: "name", |
| | | width: 220, |
| | | }, |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | prop: "code", |
| | | width: 220, |
| | | }, |
| | | { |
| | | label: "è¿è¡æ¶é´", |
| | | prop: "runDate", |
| | | width: 250, |
| | | }, |
| | | { |
| | | label: "æ¨æ¥ç¨æ°´é", |
| | | prop: "toDayNum", |
| | | }, |
| | | { |
| | | label: "æ¬æå¹³åæ°´é", |
| | | prop: "avgNum", |
| | | width:150 |
| | | }, |
| | | { |
| | | label: "è¶å¿", |
| | | prop: "trend", |
| | | width: 220, |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const pagination = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | listPageByWaterTrend({ ...searchForm.value, ...page }).then((res) => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <!-- 页颿 é¢ --> |
| | | <div class="page-header"> |
| | | <h2>éåç½å¼è´§è½¦çæ§</h2> |
| | | <div class="header-actions"> |
| | | <!-- <el-button type="primary" @click="addTank">æ°å¢å¨ç½</el-button>--> |
| | | <!-- <el-button @click="exportData">å¯¼åºæ°æ®</el-button>--> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- åä¸ªä¸»è¦æ¨¡å --> |
| | | <div class="modules-container"> |
| | | <!-- 1. åºæ¬ä¿¡æ¯æ¨¡å --> |
| | | <el-card class="module-card"> |
| | | <template #header> |
| | | <div class="card-header"> |
| | | <span>1. åºæ¬ä¿¡æ¯</span> |
| | | <el-button type="text" @click="handleEditBasicInfo">ç¼è¾</el-button> |
| | | </div> |
| | | </template> |
| | | <div class="info-grid"> |
| | | <div class="info-item"> |
| | | <label>å¨ç½ç¼å·ï¼</label> |
| | | <span>{{ basicInfo.tankCode }}</span> |
| | | </div> |
| | | <div class="info-item"> |
| | | <label>å¨ç½åç§°ï¼</label> |
| | | <span>{{ basicInfo.tankName }}</span> |
| | | </div> |
| | | <div class="info-item"> |
| | | <label>å¨ç½ç±»åï¼</label> |
| | | <span>{{ basicInfo.tankType }}</span> |
| | | </div> |
| | | <div class="info-item"> |
| | | <label>设计ååï¼</label> |
| | | <span>{{ basicInfo.designPressure }} MPa</span> |
| | | </div> |
| | | <div class="info-item"> |
| | | <label>å·¥ä½ååï¼</label> |
| | | <span>{{ basicInfo.workingPressure }} MPa</span> |
| | | </div> |
| | | <div class="info-item"> |
| | | <label>容积ï¼</label> |
| | | <span>{{ basicInfo.volume }} m³</span> |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | |
| | | <!-- 2. çæµåæ°æ¨¡å --> |
| | | <el-card class="module-card"> |
| | | <template #header> |
| | | <div class="card-header"> |
| | | <span>2. çæµåæ°</span> |
| | | <el-button type="text" @click="refreshMonitoring">å·æ°</el-button> |
| | | </div> |
| | | </template> |
| | | <div class="monitoring-grid"> |
| | | <div class="monitor-item"> |
| | | <div class="monitor-label">åå</div> |
| | | <div class="monitor-value" :class="getStatusClass(monitoringData.pressureStatus)"> |
| | | {{ monitoringData.pressure }} MPa |
| | | </div> |
| | | <div class="monitor-status">{{ monitoringData.pressureStatus === 'normal' ? 'æ£å¸¸' : 'å¼å¸¸' }}</div> |
| | | </div> |
| | | <div class="monitor-item"> |
| | | <div class="monitor-label">温度</div> |
| | | <div class="monitor-value" :class="getStatusClass(monitoringData.temperatureStatus)"> |
| | | {{ monitoringData.temperature }} â |
| | | </div> |
| | | <div class="monitor-status">{{ monitoringData.temperatureStatus === 'normal' ? 'æ£å¸¸' : 'å¼å¸¸' }}</div> |
| | | </div> |
| | | <div class="monitor-item"> |
| | | <div class="monitor-label">æ°ä½æµåº¦</div> |
| | | <div class="monitor-value" :class="getStatusClass(monitoringData.gasStatus)"> |
| | | {{ monitoringData.gasConcentration }} ppm |
| | | </div> |
| | | <div class="monitor-status">{{ monitoringData.gasStatus === 'normal' ? 'æ£å¸¸' : 'å¼å¸¸' }}</div> |
| | | </div> |
| | | <div class="monitor-item"> |
| | | <div class="monitor-label">æµé</div> |
| | | <div class="monitor-value" :class="getStatusClass(monitoringData.flowStatus)"> |
| | | {{ monitoringData.flow }} m³/h |
| | | </div> |
| | | <div class="monitor-status">{{ monitoringData.flowStatus === 'normal' ? 'æ£å¸¸' : 'å¼å¸¸' }}</div> |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | |
| | | <!-- 3. å®å
¨è£
置模å --> |
| | | <el-card class="module-card"> |
| | | <template #header> |
| | | <div class="card-header"> |
| | | <span>3. å®å
¨è£
ç½®</span> |
| | | <el-button type="text" @click="checkSafetyDevices">æ£æ¥</el-button> |
| | | </div> |
| | | </template> |
| | | <div class="safety-grid"> |
| | | <div class="safety-item" v-for="device in safetyDevices" :key="device.name"> |
| | | |
| | | <div class="device-info"> |
| | | <div class="device-name">{{ device.name }}</div> |
| | | <div class="device-status" :class="device.status"> |
| | | {{ device.status === 'normal' ? 'æ£å¸¸' : 'å¼å¸¸' }} |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | |
| | | <!-- 4. ç»´æ¤è®°å½æ¨¡å --> |
| | | <el-card class="module-card"> |
| | | <template #header> |
| | | <div class="card-header"> |
| | | <span>4. ç»´æ¤è®°å½</span> |
| | | <el-button type="text" @click="addMaintenanceRecord">æ·»å è®°å½</el-button> |
| | | </div> |
| | | </template> |
| | | <div class="maintenance-list"> |
| | | <div class="maintenance-item" v-for="record in maintenanceRecords" :key="record.id"> |
| | | <div class="record-header"> |
| | | <span class="record-date">{{ record.date }}</span> |
| | | <el-tag :type="record.type === 'inspection' ? 'primary' : 'success'" size="small"> |
| | | {{ record.type === 'inspection' ? 'æ£éª' : 'ç»´æ¤' }} |
| | | </el-tag> |
| | | </div> |
| | | <div class="record-content"> |
| | | <div class="record-title">{{ record.title }}</div> |
| | | <div class="record-desc">{{ record.description }}</div> |
| | | <div class="record-operator">æä½äººï¼{{ record.operator }}</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | </div> |
| | | |
| | | <!-- ç¼è¾åºæ¬ä¿¡æ¯å¼¹çª --> |
| | | <el-dialog v-model="basicInfoDialogVisible" title="ç¼è¾åºæ¬ä¿¡æ¯" width="600px"> |
| | | <el-form :model="editBasicInfo" label-width="120px"> |
| | | <el-form-item label="å¨ç½ç¼å·"> |
| | | <el-input v-model="editBasicInfo.tankCode" /> |
| | | </el-form-item> |
| | | <el-form-item label="å¨ç½åç§°"> |
| | | <el-input v-model="editBasicInfo.tankName" /> |
| | | </el-form-item> |
| | | <el-form-item label="å¨ç½ç±»å"> |
| | | <el-select v-model="editBasicInfo.tankType" style="width: 100%"> |
| | | <el-option label="æ¶²åæ°ä½å¨ç½" value="æ¶²åæ°ä½å¨ç½" /> |
| | | <el-option label="åå容å¨" value="åå容å¨" /> |
| | | <el-option label="常åå¨ç½" value="常åå¨ç½" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="设计åå"> |
| | | <el-input-number v-model="editBasicInfo.designPressure" :precision="2" style="width: 100%" /> |
| | | </el-form-item> |
| | | <el-form-item label="å·¥ä½åå"> |
| | | <el-input-number v-model="editBasicInfo.workingPressure" :precision="2" style="width: 100%" /> |
| | | </el-form-item> |
| | | <el-form-item label="容积"> |
| | | <el-input-number v-model="editBasicInfo.volume" :precision="2" style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button @click="basicInfoDialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="saveBasicInfo">ä¿å</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- æ·»å ç»´æ¤è®°å½å¼¹çª --> |
| | | <el-dialog v-model="maintenanceDialogVisible" title="æ·»å ç»´æ¤è®°å½" width="600px"> |
| | | <el-form :model="newMaintenanceRecord" label-width="120px"> |
| | | <el-form-item label="è®°å½ç±»å"> |
| | | <el-select v-model="newMaintenanceRecord.type" style="width: 100%"> |
| | | <el-option label="æ£éª" value="inspection" /> |
| | | <el-option label="ç»´æ¤" value="maintenance" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="æ é¢"> |
| | | <el-input v-model="newMaintenanceRecord.title" /> |
| | | </el-form-item> |
| | | <el-form-item label="æè¿°"> |
| | | <el-input type="textarea" v-model="newMaintenanceRecord.description" :rows="3" /> |
| | | </el-form-item> |
| | | <el-form-item label="æä½äºº"> |
| | | <el-input v-model="newMaintenanceRecord.operator" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button @click="maintenanceDialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="saveMaintenanceRecord">ä¿å</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted } from 'vue' |
| | | import { ElMessage } from 'element-plus' |
| | | |
| | | // åºæ¬ä¿¡æ¯ |
| | | const basicInfo = reactive({ |
| | | tankCode: 'GT001', |
| | | tankName: 'æ¶²åæ°å¨ç½A', |
| | | tankType: 'æ¶²åæ°ä½å¨ç½', |
| | | designPressure: 1.6, |
| | | workingPressure: 0.8, |
| | | volume: 100.5 |
| | | }) |
| | | |
| | | // çæµåæ° |
| | | const monitoringData = reactive({ |
| | | pressure: 0.8, |
| | | pressureStatus: 'normal', |
| | | temperature: 25.5, |
| | | temperatureStatus: 'normal', |
| | | gasConcentration: 0.1, |
| | | gasStatus: 'normal', |
| | | flow: 15.2, |
| | | flowStatus: 'normal' |
| | | }) |
| | | |
| | | // å®å
¨è£
ç½® |
| | | const safetyDevices = ref([ |
| | | { name: 'å®å
¨é', status: 'normal' }, |
| | | { name: 'ååä¼ æå¨', status: 'normal' }, |
| | | { name: 'æ¸©åº¦ä¼ æå¨', status: 'normal' }, |
| | | { name: 'æ°ä½æ£æµå¨', status: 'normal' }, |
| | | { name: 'çç ´ç', status: 'normal' }, |
| | | { name: 'æ³åè£
ç½®', status: 'normal' } |
| | | ]) |
| | | |
| | | // ç»´æ¤è®°å½ |
| | | const maintenanceRecords = ref([ |
| | | { |
| | | id: 1, |
| | | date: '2024-01-15', |
| | | type: 'inspection', |
| | | title: '年度æ£éª', |
| | | description: 'æç
§TSG 21-2016æ åè¿è¡å¹´åº¦æ£éªï¼è®¾å¤ç¶æè¯å¥½', |
| | | operator: 'å¼ å·¥ç¨å¸' |
| | | }, |
| | | { |
| | | id: 2, |
| | | date: '2024-02-20', |
| | | type: 'maintenance', |
| | | title: 'å®å
¨éç»´æ¤', |
| | | description: 'æ´æ¢å®å
¨éå¯å°åï¼æ ¡ååå设å®å¼', |
| | | operator: 'ææå¸' |
| | | }, |
| | | { |
| | | id: 3, |
| | | date: '2024-03-10', |
| | | type: 'inspection', |
| | | title: 'ååæµè¯', |
| | | description: 'è¿è¡åå容卿°´åè¯éªï¼ç¬¦åè®¾è®¡è¦æ±', |
| | | operator: 'çæ£éªå' |
| | | } |
| | | ]) |
| | | |
| | | // å¼¹çªæ§å¶ |
| | | const basicInfoDialogVisible = ref(false) |
| | | const maintenanceDialogVisible = ref(false) |
| | | |
| | | // ç¼è¾è¡¨åæ°æ® |
| | | const editBasicInfo = reactive({ ...basicInfo }) |
| | | const newMaintenanceRecord = reactive({ |
| | | type: 'inspection', |
| | | title: '', |
| | | description: '', |
| | | operator: '' |
| | | }) |
| | | |
| | | // è·åç¶ææ ·å¼ç±» |
| | | const getStatusClass = (status) => { |
| | | return status === 'normal' ? 'status-normal' : 'status-warning' |
| | | } |
| | | |
| | | // æ°å¢å¨ç½ |
| | | const addTank = () => { |
| | | ElMessage.success('æ°å¢å¨ç½åè½') |
| | | } |
| | | |
| | | // å¯¼åºæ°æ® |
| | | const exportData = () => { |
| | | ElMessage.success('å¯¼åºæå') |
| | | } |
| | | |
| | | // ç¼è¾åºæ¬ä¿¡æ¯ |
| | | const handleEditBasicInfo = () => { |
| | | Object.assign(editBasicInfo, basicInfo) |
| | | basicInfoDialogVisible.value = true |
| | | } |
| | | |
| | | // ä¿ååºæ¬ä¿¡æ¯ |
| | | const saveBasicInfo = () => { |
| | | Object.assign(basicInfo, editBasicInfo) |
| | | basicInfoDialogVisible.value = false |
| | | ElMessage.success('ä¿åæå') |
| | | } |
| | | |
| | | // å·æ°çæµæ°æ® |
| | | const refreshMonitoring = () => { |
| | | // æ¨¡ææ°æ®æ´æ° |
| | | monitoringData.pressure = (Math.random() * 0.5 + 0.6).toFixed(2) |
| | | monitoringData.temperature = (Math.random() * 10 + 20).toFixed(1) |
| | | monitoringData.gasConcentration = (Math.random() * 0.2).toFixed(2) |
| | | monitoringData.flow = (Math.random() * 10 + 10).toFixed(1) |
| | | ElMessage.success('æ°æ®å·²å·æ°') |
| | | } |
| | | |
| | | // æ£æ¥å®å
¨è£
ç½® |
| | | const checkSafetyDevices = () => { |
| | | // æ¨¡ææ£æ¥è¿ç¨ |
| | | safetyDevices.value.forEach(device => { |
| | | device.status = Math.random() > 0.1 ? 'normal' : 'warning' |
| | | }) |
| | | ElMessage.success('å®å
¨è£
ç½®æ£æ¥å®æ') |
| | | } |
| | | |
| | | // æ·»å ç»´æ¤è®°å½ |
| | | const addMaintenanceRecord = () => { |
| | | newMaintenanceRecord.type = 'inspection' |
| | | newMaintenanceRecord.title = '' |
| | | newMaintenanceRecord.description = '' |
| | | newMaintenanceRecord.operator = '' |
| | | maintenanceDialogVisible.value = true |
| | | } |
| | | |
| | | // ä¿åç»´æ¤è®°å½ |
| | | const saveMaintenanceRecord = () => { |
| | | const record = { |
| | | id: Date.now(), |
| | | date: new Date().toISOString().split('T')[0], |
| | | ...newMaintenanceRecord |
| | | } |
| | | maintenanceRecords.value.unshift(record) |
| | | maintenanceDialogVisible.value = false |
| | | ElMessage.success('è®°å½æ·»å æå') |
| | | } |
| | | |
| | | // 模æå®æ¶æ°æ®æ´æ° |
| | | onMounted(() => { |
| | | setInterval(() => { |
| | | monitoringData.pressure = (Math.random() * 0.5 + 0.6).toFixed(2) |
| | | monitoringData.temperature = (Math.random() * 10 + 20).toFixed(1) |
| | | monitoringData.gasConcentration = (Math.random() * 0.2).toFixed(2) |
| | | monitoringData.flow = (Math.random() * 10 + 10).toFixed(1) |
| | | }, 5000) |
| | | }) |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .app-container { |
| | | padding: 20px; |
| | | background: #f5f5f5; |
| | | min-height: 100vh; |
| | | } |
| | | |
| | | .page-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 20px; |
| | | padding: 20px; |
| | | background: white; |
| | | border-radius: 8px; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); |
| | | |
| | | h2 { |
| | | margin: 0; |
| | | color: #303133; |
| | | } |
| | | |
| | | .header-actions { |
| | | display: flex; |
| | | gap: 10px; |
| | | } |
| | | } |
| | | |
| | | .modules-container { |
| | | display: grid; |
| | | grid-template-columns: repeat(2, 1fr); |
| | | gap: 20px; |
| | | } |
| | | |
| | | .module-card { |
| | | .card-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | font-weight: bold; |
| | | color: #303133; |
| | | } |
| | | } |
| | | |
| | | .info-grid { |
| | | display: grid; |
| | | grid-template-columns: repeat(2, 1fr); |
| | | gap: 15px; |
| | | |
| | | .info-item { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | padding: 10px; |
| | | background: #f8f9fa; |
| | | border-radius: 4px; |
| | | |
| | | label { |
| | | font-weight: bold; |
| | | color: #606266; |
| | | } |
| | | |
| | | span { |
| | | color: #303133; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .monitoring-grid { |
| | | display: grid; |
| | | grid-template-columns: repeat(2, 1fr); |
| | | gap: 15px; |
| | | |
| | | .monitor-item { |
| | | text-align: center; |
| | | padding: 15px; |
| | | background: #f8f9fa; |
| | | border-radius: 8px; |
| | | border: 2px solid transparent; |
| | | |
| | | .monitor-label { |
| | | font-size: 14px; |
| | | color: #606266; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .monitor-value { |
| | | font-size: 20px; |
| | | font-weight: bold; |
| | | margin-bottom: 5px; |
| | | |
| | | &.status-normal { |
| | | color: #67c23a; |
| | | } |
| | | |
| | | &.status-warning { |
| | | color: #e6a23c; |
| | | } |
| | | } |
| | | |
| | | .monitor-status { |
| | | font-size: 12px; |
| | | color: #909399; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .safety-grid { |
| | | display: grid; |
| | | grid-template-columns: repeat(2, 1fr); |
| | | gap: 15px; |
| | | |
| | | .safety-item { |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 15px; |
| | | background: #f8f9fa; |
| | | border-radius: 8px; |
| | | border: 2px solid transparent; |
| | | |
| | | .device-icon { |
| | | margin-right: 15px; |
| | | } |
| | | |
| | | .device-info { |
| | | flex: 1; |
| | | |
| | | .device-name { |
| | | font-weight: bold; |
| | | color: #303133; |
| | | margin-bottom: 5px; |
| | | } |
| | | |
| | | .device-status { |
| | | font-size: 12px; |
| | | padding: 2px 8px; |
| | | border-radius: 10px; |
| | | display: inline-block; |
| | | |
| | | &.normal { |
| | | background: #f0f9ff; |
| | | color: #409eff; |
| | | } |
| | | |
| | | &.warning { |
| | | background: #fef7e0; |
| | | color: #e6a23c; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .maintenance-list { |
| | | max-height: 300px; |
| | | overflow-y: auto; |
| | | |
| | | .maintenance-item { |
| | | padding: 15px; |
| | | border-bottom: 1px solid #ebeef5; |
| | | margin-bottom: 10px; |
| | | |
| | | &:last-child { |
| | | border-bottom: none; |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .record-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 8px; |
| | | |
| | | .record-date { |
| | | font-size: 14px; |
| | | color: #909399; |
| | | } |
| | | } |
| | | |
| | | .record-content { |
| | | .record-title { |
| | | font-weight: bold; |
| | | color: #303133; |
| | | margin-bottom: 5px; |
| | | } |
| | | |
| | | .record-desc { |
| | | font-size: 14px; |
| | | color: #606266; |
| | | margin-bottom: 5px; |
| | | line-height: 1.4; |
| | | } |
| | | |
| | | .record-operator { |
| | | font-size: 12px; |
| | | color: #909399; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | // ååºå¼è®¾è®¡ |
| | | @media (max-width: 1200px) { |
| | | .modules-container { |
| | | grid-template-columns: 1fr; |
| | | } |
| | | } |
| | | |
| | | @media (max-width: 768px) { |
| | | .info-grid, |
| | | .monitoring-grid, |
| | | .safety-grid { |
| | | grid-template-columns: 1fr; |
| | | } |
| | | } |
| | | </style> |
| | |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="è§æ ¼åå·" prop="deviceModel"> |
| | | <el-input v-model="form.deviceModel" placeholder="请è¾å
¥è§æ ¼åå·" /> |
| | | <el-input v-model="form.deviceModel" :disabled="form.deviceModel != null ? true : false" placeholder="请è¾å
¥è§æ ¼åå·" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | |
| | | @selection-change="handleSelectionChange" |
| | | @pagination="changePage" |
| | | > |
| | | <template #operation="{ row }"> |
| | | <el-button type="primary" text @click="edit(row.id)" icon="editPen"> |
| | | ç¼è¾ |
| | | </el-button> |
| | | <el-button |
| | | type="danger" |
| | | text |
| | | icon="delete" |
| | | @click="deleteRow(row.id)" |
| | | > |
| | | å é¤ |
| | | </el-button> |
| | | </template> |
| | | </PIMTable> |
| | | </div> |
| | | <Modal ref="modalRef" @success="getTableData"></Modal> |
| | | <el-dialog v-model="qrDialogVisible" title="äºç»´ç " width="300px"> |
| | | <div style="text-align:center;"> |
| | | <img :src="qrCodeUrl" alt="äºç»´ç " style="width:200px;height:200px;" /> |
| | | <div style="margin:10px 0;"> |
| | | <el-button type="primary" @click="downloadQRCode">ä¸è½½äºç»´ç å¾ç</el-button> |
| | | </div> |
| | | </div> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | import Modal from "./Modal.vue"; |
| | | import { ElMessageBox, ElMessage } from "element-plus"; |
| | | import dayjs from "dayjs"; |
| | | import QRCode from "qrcode"; |
| | | import { ref } from "vue"; |
| | | |
| | | defineOptions({ |
| | | name: "设å¤å°è´¦", |
| | |
| | | const multipleList = ref([]); |
| | | const { proxy } = getCurrentInstance(); |
| | | const modalRef = ref(); |
| | | const qrDialogVisible = ref(false); |
| | | const qrCodeUrl = ref(""); |
| | | const qrRowData = ref(null); |
| | | |
| | | const { |
| | | filters, |
| | | columns, |
| | |
| | | align: "center", |
| | | prop: "createTime", |
| | | }, |
| | | { |
| | | fixed: "right", |
| | | label: "æä½", |
| | | dataType: "slot", |
| | | slot: "operation", |
| | | align: "center", |
| | | width: "200px", |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: 'right', |
| | | width: 140, |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | edit(row.id) |
| | | }, |
| | | }, |
| | | { |
| | | name: "çæäºç»´ç ", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | showQRCode(row) |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | ] |
| | | ); |
| | | |
| | |
| | | }); |
| | | }; |
| | | |
| | | const showQRCode = async (row) => { |
| | | // ä½ å¯ä»¥èªå®ä¹äºç»´ç å
å®¹ï¼æ¯å¦ row.id æ row.deviceName |
| | | const qrContent = JSON.stringify(row); // æ `${row.id}` |
| | | qrCodeUrl.value = await QRCode.toDataURL(qrContent); |
| | | qrRowData.value = row; |
| | | qrDialogVisible.value = true; |
| | | }; |
| | | |
| | | const downloadQRCode = () => { |
| | | const a = document.createElement("a"); |
| | | a.href = qrCodeUrl.value; |
| | | a.download = `${qrRowData.value.deviceName || "äºç»´ç "}.png`; |
| | | a.click(); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | filters.entryDate = [ |
| | | dayjs().format("YYYY-MM-DD"), |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <!-- æç´¢è¡¨å --> |
| | | <div class="search_form"> |
| | | <el-form :model="searchForm" :inline="true"> |
| | | <el-form-item label="卿°ç½åç§°ï¼"> |
| | | <el-input v-model="searchForm.tankName" placeholder="请è¾å
¥å¨æ°ç½åç§°" clearable style="width: 200px" /> |
| | | </el-form-item> |
| | | <el-form-item label="卿°ç½ç±»åï¼"> |
| | | <el-select v-model="searchForm.tankType" placeholder="è¯·éæ©å¨æ°ç½ç±»å" clearable style="width: 200px"> |
| | | <el-option label="æ¶²åæ°å¨ç½" value="æ¶²åæ°å¨ç½" /> |
| | | <el-option label="å缩æ°å¨ç½" value="å缩æ°å¨ç½" /> |
| | | <el-option label="å¤©ç¶æ°å¨ç½" value="å¤©ç¶æ°å¨ç½" /> |
| | | <el-option label="æ°§æ°å¨ç½" value="æ°§æ°å¨ç½" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="é¢è¦ç±»åï¼"> |
| | | <el-select v-model="searchForm.warningType" placeholder="è¯·éæ©é¢è¦ç±»å" clearable style="width: 200px"> |
| | | <el-option label="æ°ä½ä¸è¶³" value="æ°ä½ä¸è¶³" /> |
| | | <el-option label="ååå¼å¸¸" value="ååå¼å¸¸" /> |
| | | <el-option label="温度å¼å¸¸" value="温度å¼å¸¸" /> |
| | | <el-option label="æ³æ¼é¢è¦" value="æ³æ¼é¢è¦" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="é¢è¦çº§å«ï¼"> |
| | | <el-select v-model="searchForm.warningLevel" placeholder="è¯·éæ©é¢è¦çº§å«" clearable style="width: 200px"> |
| | | <el-option label="ç´§æ¥" value="ç´§æ¥" /> |
| | | <el-option label="éè¦" value="éè¦" /> |
| | | <el-option label="ä¸è¬" value="ä¸è¬" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleQuery">æç´¢</el-button> |
| | | <el-button @click="resetQuery">éç½®</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | |
| | | <!-- æ°æ®è¡¨æ ¼ --> |
| | | <div class="table_list"> |
| | | <!-- æä½æé® --> |
| | | <div class="table-operations"> |
| | | <el-button type="primary" @click="handleAdd">æ°å¢é¢è¦è§å</el-button> |
| | | <el-button type="success" @click="handleBatchProcess">æ¹éå¤ç</el-button> |
| | | <el-button @click="handleExport">导åº</el-button> |
| | | </div> |
| | | <el-table |
| | | :data="tableData" |
| | | border |
| | | v-loading="tableLoading" |
| | | @selection-change="handleSelectionChange" |
| | | style="width: 100%" |
| | | height="calc(100vh - 280px)" |
| | | > |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table-column align="center" label="åºå·" type="index" width="60" /> |
| | | |
| | | <!-- åºç¡ä¿¡æ¯å段 --> |
| | | <el-table-column label="卿°ç½ç¼ç " prop="tankCode" width="120" show-overflow-tooltip /> |
| | | <el-table-column label="卿°ç½åç§°" prop="tankName" width="200" show-overflow-tooltip /> |
| | | <el-table-column label="卿°ç½ç±»å" prop="tankType" width="120" show-overflow-tooltip /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" width="150" show-overflow-tooltip /> |
| | | <el-table-column label="容积(m³)" prop="volume" width="100" show-overflow-tooltip /> |
| | | |
| | | <!-- åºåç¸å
³å段 --> |
| | | <el-table-column label="å½åæ°ä½é" prop="currentGasLevel" width="120" show-overflow-tooltip> |
| | | <template #default="scope"> |
| | | <span :class="getGasLevelClass(scope.row)">{{ scope.row.currentGasLevel }}%</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="å®å
¨æ°ä½é" prop="safetyGasLevel" width="120" show-overflow-tooltip /> |
| | | <el-table-column label="æä½æ°ä½é" prop="minGasLevel" width="120" show-overflow-tooltip /> |
| | | <el-table-column label="æé«æ°ä½é" prop="maxGasLevel" width="120" show-overflow-tooltip /> |
| | | <el-table-column label="å½ååå(MPa)" prop="currentPressure" width="140" show-overflow-tooltip /> |
| | | |
| | | <!-- é¢è¦è§ååæ®µ --> |
| | | <el-table-column label="é¢è¦ç±»å" prop="warningType" width="100" show-overflow-tooltip> |
| | | <template #default="scope"> |
| | | <el-tag :type="getWarningTypeTag(scope.row.warningType)"> |
| | | {{ scope.row.warningType }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="é¢è¦çº§å«" prop="warningLevel" width="100" show-overflow-tooltip> |
| | | <template #default="scope"> |
| | | <el-tag :type="getWarningLevelTag(scope.row.warningLevel)"> |
| | | {{ scope.row.warningLevel }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="é¢è¦éå¼" prop="warningThreshold" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="æ¯å¦å¯ç¨" prop="isEnabled" width="100" show-overflow-tooltip> |
| | | <template #default="scope"> |
| | | <el-switch v-model="scope.row.isEnabled" @change="handleEnableChange(scope.row)" /> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <!-- æ¶é´ç¸å
³å段 --> |
| | | <el-table-column label="é¢è¦æ¶é´" prop="warningTime" width="150" show-overflow-tooltip /> |
| | | <el-table-column label="é¢è¦æç»å¤©æ°" prop="warningDuration" width="120" show-overflow-tooltip /> |
| | | <el-table-column label="æåæ´æ°æ¶é´" prop="lastUpdateTime" width="150" show-overflow-tooltip /> |
| | | <el-table-column label="é¢è®¡å
è£
æ¶é´" prop="expectedRefillTime" width="150" show-overflow-tooltip /> |
| | | <el-table-column label="é¢è®¡ç¼ºæ°æ¶é´" prop="expectedShortageTime" width="150" show-overflow-tooltip> |
| | | <template #default="scope"> |
| | | <div v-if="scope.row.expectedShortageTime"> |
| | | <div v-if="getCountdown(scope.row.expectedShortageTime).isExpired" class="countdown-expired"> |
| | | <el-tag type="danger">已缺æ°</el-tag> |
| | | </div> |
| | | <div v-else class="countdown-timer"> |
| | | <span :class="getCountdownClass(scope.row.expectedShortageTime)"> |
| | | {{ getCountdown(scope.row.expectedShortageTime).text }} |
| | | </span> |
| | | </div> |
| | | </div> |
| | | <span v-else>-</span> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <!-- æä½å --> |
| | | <el-table-column fixed="right" label="æä½" width="200" align="center"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" size="small" @click="handleEdit(scope.row)">ç¼è¾</el-button> |
| | | <el-button link type="success" size="small" @click="handleProcess(scope.row)">å¤ç</el-button> |
| | | <el-button link type="danger" size="small" @click="handleDelete(scope.row)">å é¤</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <!-- å页 --> |
| | | <pagination |
| | | v-show="total > 0" |
| | | :total="total" |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | :page="page.current" |
| | | :limit="page.size" |
| | | @pagination="paginationChange" |
| | | /> |
| | | </div> |
| | | |
| | | <!-- æ°å¢/ç¼è¾é¢è¦è§åå¼¹çª --> |
| | | <el-dialog |
| | | v-model="dialogFormVisible" |
| | | :title="operationType === 'add' ? 'æ°å¢é¢è¦è§å' : 'ç¼è¾é¢è¦è§å'" |
| | | width="50%" |
| | | @close="closeDialog" |
| | | > |
| | | <el-form :model="form" :rules="rules" ref="formRef" label-width="140px"> |
| | | <el-row :gutter="20"> |
| | | <!-- åºç¡ä¿¡æ¯ --> |
| | | <el-col :span="12"> |
| | | <el-form-item label="卿°ç½ç¼ç ï¼" prop="tankCode"> |
| | | <el-input v-model="form.tankCode" placeholder="请è¾å
¥å¨æ°ç½ç¼ç " /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="卿°ç½åç§°ï¼" prop="tankName"> |
| | | <el-input v-model="form.tankName" placeholder="请è¾å
¥å¨æ°ç½åç§°" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="卿°ç½ç±»åï¼" prop="tankType"> |
| | | <el-select v-model="form.tankType" placeholder="è¯·éæ©å¨æ°ç½ç±»å" style="width: 100%"> |
| | | <el-option label="æ¶²åæ°å¨ç½" value="æ¶²åæ°å¨ç½" /> |
| | | <el-option label="å缩æ°å¨ç½" value="å缩æ°å¨ç½" /> |
| | | <el-option label="å¤©ç¶æ°å¨ç½" value="å¤©ç¶æ°å¨ç½" /> |
| | | <el-option label="æ°§æ°å¨ç½" value="æ°§æ°å¨ç½" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="è§æ ¼åå·ï¼" prop="specificationModel"> |
| | | <el-input v-model="form.specificationModel" placeholder="请è¾å
¥è§æ ¼åå·" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="容积(m³)ï¼" prop="volume"> |
| | | <el-input-number v-model="form.volume" :min="0" :precision="2" style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å½åæ°ä½é(%)ï¼" prop="currentGasLevel"> |
| | | <el-input-number v-model="form.currentGasLevel" :min="0" :max="100" :precision="1" style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <!-- åºåç¸å
³ --> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å®å
¨æ°ä½é(%)ï¼" prop="safetyGasLevel"> |
| | | <el-input-number v-model="form.safetyGasLevel" :min="0" :max="100" :precision="1" style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æä½æ°ä½é(%)ï¼" prop="minGasLevel"> |
| | | <el-input-number v-model="form.minGasLevel" :min="0" :max="100" :precision="1" style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æé«æ°ä½é(%)ï¼" prop="maxGasLevel"> |
| | | <el-input-number v-model="form.maxGasLevel" :min="0" :max="100" :precision="1" style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å½ååå(MPa)ï¼" prop="currentPressure"> |
| | | <el-input-number v-model="form.currentPressure" :min="0" :precision="2" style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <!-- é¢è¦è§å --> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="é¢è¦ç±»åï¼" prop="warningType"> |
| | | <el-select v-model="form.warningType" placeholder="è¯·éæ©é¢è¦ç±»å" style="width: 100%"> |
| | | <el-option label="æ°ä½ä¸è¶³" value="æ°ä½ä¸è¶³" /> |
| | | <el-option label="ååå¼å¸¸" value="ååå¼å¸¸" /> |
| | | <el-option label="温度å¼å¸¸" value="温度å¼å¸¸" /> |
| | | <el-option label="æ³æ¼é¢è¦" value="æ³æ¼é¢è¦" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="é¢è¦çº§å«ï¼" prop="warningLevel"> |
| | | <el-select v-model="form.warningLevel" placeholder="è¯·éæ©é¢è¦çº§å«" style="width: 100%"> |
| | | <el-option label="ç´§æ¥" value="ç´§æ¥" /> |
| | | <el-option label="éè¦" value="éè¦" /> |
| | | <el-option label="ä¸è¬" value="ä¸è¬" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="é¢è¦éå¼ï¼" prop="warningThreshold"> |
| | | <el-input-number v-model="form.warningThreshold" :min="0" :precision="2" style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ¯å¦å¯ç¨ï¼" prop="isEnabled"> |
| | | <el-switch v-model="form.isEnabled" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <!-- æ¶é´ç¸å
³ --> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="é¢è¦æ¶é´ï¼" prop="warningTime"> |
| | | <el-date-picker |
| | | v-model="form.warningTime" |
| | | type="datetime" |
| | | placeholder="è¯·éæ©é¢è¦æ¶é´" |
| | | style="width: 100%" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="é¢è®¡å
è£
æ¶é´ï¼" prop="expectedRefillTime"> |
| | | <el-date-picker |
| | | v-model="form.expectedRefillTime" |
| | | type="datetime" |
| | | placeholder="è¯·éæ©é¢è®¡å
è£
æ¶é´" |
| | | style="width: 100%" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="é¢è®¡ç¼ºæ°æ¶é´ï¼" prop="expectedShortageTime"> |
| | | <el-date-picker |
| | | v-model="form.expectedShortageTime" |
| | | type="datetime" |
| | | placeholder="è¯·éæ©é¢è®¡ç¼ºæ°æ¶é´" |
| | | style="width: 100%" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="é¢è¦è§åæè¿°ï¼" prop="warningRule"> |
| | | <el-input |
| | | v-model="form.warningRule" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥é¢è¦è§åæè¿°" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button @click="closeDialog">åæ¶</el-button> |
| | | <el-button type="primary" @click="submitForm">确认</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- 缺æ°é¢è¦å¼¹æ¡ --> |
| | | <el-dialog |
| | | v-model="shortageWarningVisible" |
| | | title="â ï¸ ç¼ºæ°é¢è¦" |
| | | width="400px" |
| | | :close-on-click-modal="false" |
| | | :close-on-press-escape="false" |
| | | :show-close="false" |
| | | > |
| | | <div class="shortage-warning-content"> |
| | | <div class="warning-icon"> |
| | | <el-icon size="48" color="#f56c6c"><WarningFilled /></el-icon> |
| | | </div> |
| | | <div class="warning-message"> |
| | | <h3>{{ currentWarningTank.tankName }}</h3> |
| | | <p>卿°ç½å·²ç¼ºæ°ï¼è¯·åæ¶å¤çï¼</p> |
| | | <p class="warning-details"> |
| | | 卿°ç½ç¼ç ï¼{{ currentWarningTank.tankCode }}<br> |
| | | 卿°ç½ç±»åï¼{{ currentWarningTank.tankType }}<br> |
| | | å½åæ°ä½éï¼{{ currentWarningTank.currentGasLevel }}% |
| | | </p> |
| | | </div> |
| | | </div> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="handleShortageWarning">ç«å³å¤ç</el-button> |
| | | <el-button @click="closeShortageWarning">ç¨åå¤ç</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- 缺æ°é¢è¦å¼¹æ¡ --> |
| | | <el-dialog |
| | | v-model="shortageWarningVisible" |
| | | title="â ï¸ ç¼ºæ°é¢è¦" |
| | | width="400px" |
| | | :close-on-click-modal="false" |
| | | :close-on-press-escape="false" |
| | | :show-close="false" |
| | | > |
| | | <div class="shortage-warning-content"> |
| | | <div class="warning-icon"> |
| | | <el-icon size="48" color="#f56c6c"><WarningFilled /></el-icon> |
| | | </div> |
| | | <div class="warning-message"> |
| | | <h3>{{ currentWarningTank.tankName }}</h3> |
| | | <p>卿°ç½å·²ç¼ºæ°ï¼è¯·åæ¶å¤çï¼</p> |
| | | <p class="warning-details"> |
| | | 卿°ç½ç¼ç ï¼{{ currentWarningTank.tankCode }}<br> |
| | | 卿°ç½ç±»åï¼{{ currentWarningTank.tankType }}<br> |
| | | å½åæ°ä½éï¼{{ currentWarningTank.currentGasLevel }}% |
| | | </p> |
| | | </div> |
| | | </div> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="handleShortageWarning">ç«å³å¤ç</el-button> |
| | | <el-button @click="closeShortageWarning">ç¨åå¤ç</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted, onUnmounted } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { WarningFilled } from '@element-plus/icons-vue' |
| | | import pagination from '@/components/PIMTable/Pagination.vue' |
| | | // 注éæAPI导å
¥ï¼ä½¿ç¨åæ°æ® |
| | | // import { |
| | | // getStockWarningPage, |
| | | // addStockWarning, |
| | | // updateStockWarning, |
| | | // deleteStockWarning, |
| | | // batchProcessStockWarning, |
| | | // exportStockWarning, |
| | | // toggleStockWarningStatus |
| | | // } from '@/api/inventoryManagement/stockWarning.js' |
| | | |
| | | const { proxy } = getCurrentInstance() |
| | | |
| | | // ååºå¼æ°æ® |
| | | const tableData = ref([]) |
| | | const tableLoading = ref(false) |
| | | const selectedRows = ref([]) |
| | | const dialogFormVisible = ref(false) |
| | | const operationType = ref('add') |
| | | const total = ref(0) |
| | | |
| | | // 缺æ°é¢è¦ç¸å
³ |
| | | const shortageWarningVisible = ref(false) |
| | | const currentWarningTank = ref({}) |
| | | const countdownTimer = ref(null) |
| | | |
| | | // å页忰 |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 10 |
| | | }) |
| | | |
| | | // æç´¢è¡¨å |
| | | const searchForm = reactive({ |
| | | tankName: '', |
| | | tankType: '', |
| | | warningType: '', |
| | | warningLevel: '' |
| | | }) |
| | | |
| | | // è¡¨åæ°æ® |
| | | const form = reactive({ |
| | | id: null, |
| | | tankCode: '', |
| | | tankName: '', |
| | | tankType: '', |
| | | specificationModel: '', |
| | | volume: 0, |
| | | currentGasLevel: 0, |
| | | safetyGasLevel: 0, |
| | | minGasLevel: 0, |
| | | maxGasLevel: 0, |
| | | currentPressure: 0, |
| | | warningType: '', |
| | | warningLevel: '', |
| | | warningThreshold: 0, |
| | | isEnabled: true, |
| | | warningTime: '', |
| | | warningDuration: 0, |
| | | lastUpdateTime: '', |
| | | expectedRefillTime: '', |
| | | expectedShortageTime: '', |
| | | warningRule: '' |
| | | }) |
| | | |
| | | // 表åéªè¯è§å |
| | | const rules = { |
| | | tankCode: [{ required: true, message: '请è¾å
¥å¨æ°ç½ç¼ç ', trigger: 'blur' }], |
| | | tankName: [{ required: true, message: '请è¾å
¥å¨æ°ç½åç§°', trigger: 'blur' }], |
| | | tankType: [{ required: true, message: 'è¯·éæ©å¨æ°ç½ç±»å', trigger: 'change' }], |
| | | warningType: [{ required: true, message: 'è¯·éæ©é¢è¦ç±»å', trigger: 'change' }], |
| | | warningLevel: [{ required: true, message: 'è¯·éæ©é¢è¦çº§å«', trigger: 'change' }], |
| | | warningThreshold: [{ required: true, message: '请è¾å
¥é¢è¦éå¼', trigger: 'blur' }] |
| | | } |
| | | |
| | | // è·åå计æ¶ä¿¡æ¯ |
| | | const getCountdown = (expectedTime) => { |
| | | if (!expectedTime) return { text: '-', isExpired: false } |
| | | |
| | | const now = new Date().getTime() |
| | | const expected = new Date(expectedTime).getTime() |
| | | const diff = expected - now |
| | | |
| | | if (diff <= 0) { |
| | | return { text: '已缺æ°', isExpired: true } |
| | | } |
| | | |
| | | const days = Math.floor(diff / (1000 * 60 * 60 * 24)) |
| | | const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)) |
| | | const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60)) |
| | | |
| | | if (days > 0) { |
| | | return { text: `${days}天${hours}å°æ¶`, isExpired: false } |
| | | } else if (hours > 0) { |
| | | return { text: `${hours}å°æ¶${minutes}åé`, isExpired: false } |
| | | } else { |
| | | return { text: `${minutes}åé`, isExpired: false } |
| | | } |
| | | } |
| | | |
| | | // è·ååè®¡æ¶æ ·å¼ç±» |
| | | const getCountdownClass = (expectedTime) => { |
| | | if (!expectedTime) return '' |
| | | |
| | | const now = new Date().getTime() |
| | | const expected = new Date(expectedTime).getTime() |
| | | const diff = expected - now |
| | | |
| | | if (diff <= 0) { |
| | | return 'countdown-expired' |
| | | } else if (diff <= 24 * 60 * 60 * 1000) { // 24å°æ¶å
|
| | | return 'countdown-urgent' |
| | | } else if (diff <= 7 * 24 * 60 * 60 * 1000) { // 7天å
|
| | | return 'countdown-warning' |
| | | } else { |
| | | return 'countdown-normal' |
| | | } |
| | | } |
| | | |
| | | // æ£æ¥ç¼ºæ°é¢è¦ |
| | | const checkShortageWarnings = () => { |
| | | tableData.value.forEach(tank => { |
| | | if (tank.expectedShortageTime) { |
| | | const countdown = getCountdown(tank.expectedShortageTime) |
| | | if (countdown.isExpired && !tank.warningShown) { |
| | | // æ è®°å·²æ¾ç¤ºé¢è¦ï¼é¿å
éå¤å¼¹æ¡ |
| | | tank.warningShown = true |
| | | showShortageWarning(tank) |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | |
| | | // æ¾ç¤ºç¼ºæ°é¢è¦å¼¹æ¡ |
| | | const showShortageWarning = (tank) => { |
| | | currentWarningTank.value = tank |
| | | shortageWarningVisible.value = true |
| | | |
| | | // ææ¾æç¤ºé³ï¼å¯éï¼ |
| | | // const audio = new Audio('/path/to/warning-sound.mp3') |
| | | // audio.play() |
| | | } |
| | | |
| | | // å¤ç缺æ°é¢è¦ |
| | | const handleShortageWarning = () => { |
| | | ElMessage.success(`æ£å¨å¤ç卿°ç½ ${currentWarningTank.value.tankName} ç缺æ°é®é¢`) |
| | | shortageWarningVisible.value = false |
| | | // è¿éå¯ä»¥è°ç¨å¤çAPI |
| | | } |
| | | // å¤ç缺æ°é¢è¦ |
| | | const closeShortageWarning = () => { |
| | | // ElMessage.success(`æ£å¨å¤ç卿°ç½ ${currentWarningTank.value.tankName} ç缺æ°é®é¢`) |
| | | shortageWarningVisible.value = false |
| | | // è¿éå¯ä»¥è°ç¨å¤çAPI |
| | | } |
| | | |
| | | |
| | | |
| | | // çæåæ°æ® |
| | | const generateMockData = () => { |
| | | const mockData = [ |
| | | { |
| | | id: 1, |
| | | tankCode: 'TANK001', |
| | | tankName: 'æ¶²åæ°å¨ç½A', |
| | | tankType: 'æ¶²åæ°å¨ç½', |
| | | specificationModel: 'LPG-5000L', |
| | | volume: 5000, |
| | | currentGasLevel: 15, |
| | | safetyGasLevel: 30, |
| | | minGasLevel: 10, |
| | | maxGasLevel: 95, |
| | | currentPressure: 2.5, |
| | | warningType: 'æ°ä½ä¸è¶³', |
| | | warningLevel: 'ç´§æ¥', |
| | | warningThreshold: 20, |
| | | isEnabled: true, |
| | | warningTime: '2024-01-15 08:30:00', |
| | | warningDuration: 3, |
| | | lastUpdateTime: '2024-01-15 10:00:00', |
| | | expectedRefillTime: '2024-01-16 14:00:00', |
| | | expectedShortageTime: '2024-01-15 18:30:00', // ä»å¤©ä¸å6:30ç¼ºæ° |
| | | warningRule: '彿°ä½éä½äº20%æ¶è§¦åé¢è¦' |
| | | }, |
| | | { |
| | | id: 2, |
| | | tankCode: 'TANK002', |
| | | tankName: 'å缩æ°å¨ç½B', |
| | | tankType: 'å缩æ°å¨ç½', |
| | | specificationModel: 'COMP-3000L', |
| | | volume: 3000, |
| | | currentGasLevel: 45, |
| | | safetyGasLevel: 25, |
| | | minGasLevel: 15, |
| | | maxGasLevel: 90, |
| | | currentPressure: 8.2, |
| | | warningType: 'ååå¼å¸¸', |
| | | warningLevel: 'éè¦', |
| | | warningThreshold: 10, |
| | | isEnabled: true, |
| | | warningTime: '2024-01-14 16:20:00', |
| | | warningDuration: 2, |
| | | lastUpdateTime: '2024-01-15 09:15:00', |
| | | expectedRefillTime: '2024-01-17 09:00:00', |
| | | expectedShortageTime: '2024-01-18 12:00:00', // 3天åç¼ºæ° |
| | | warningRule: 'å½ååè¶
è¿8MPaæ¶è§¦åé¢è¦' |
| | | }, |
| | | { |
| | | id: 3, |
| | | tankCode: 'TANK003', |
| | | tankName: 'å¤©ç¶æ°å¨ç½C', |
| | | tankType: 'å¤©ç¶æ°å¨ç½', |
| | | specificationModel: 'NG-8000L', |
| | | volume: 8000, |
| | | currentGasLevel: 75, |
| | | safetyGasLevel: 20, |
| | | minGasLevel: 10, |
| | | maxGasLevel: 95, |
| | | currentPressure: 4.8, |
| | | warningType: '温度å¼å¸¸', |
| | | warningLevel: 'ä¸è¬', |
| | | warningThreshold: 5, |
| | | isEnabled: true, |
| | | warningTime: '2024-01-13 11:45:00', |
| | | warningDuration: 1, |
| | | lastUpdateTime: '2024-01-15 08:45:00', |
| | | expectedRefillTime: '2024-01-20 10:00:00', |
| | | expectedShortageTime: '2024-01-22 15:30:00', // 7天åç¼ºæ° |
| | | warningRule: '彿¸©åº¦è¶
è¿60°Cæ¶è§¦åé¢è¦' |
| | | }, |
| | | { |
| | | id: 4, |
| | | tankCode: 'TANK004', |
| | | tankName: 'æ°§æ°å¨ç½D', |
| | | tankType: 'æ°§æ°å¨ç½', |
| | | specificationModel: 'O2-2000L', |
| | | volume: 2000, |
| | | currentGasLevel: 8, |
| | | safetyGasLevel: 25, |
| | | minGasLevel: 5, |
| | | maxGasLevel: 90, |
| | | currentPressure: 6.5, |
| | | warningType: 'æ³æ¼é¢è¦', |
| | | warningLevel: 'ç´§æ¥', |
| | | warningThreshold: 15, |
| | | isEnabled: true, |
| | | warningTime: '2024-01-15 07:15:00', |
| | | warningDuration: 4, |
| | | lastUpdateTime: '2024-01-15 11:30:00', |
| | | expectedRefillTime: '2024-01-15 16:00:00', |
| | | expectedShortageTime: '2024-01-15 14:00:00', // ä»å¤©ä¸å2ç¹ç¼ºæ° |
| | | warningRule: '彿£æµå°æ°ä½æ³æ¼æ¶è§¦åé¢è¦' |
| | | }, |
| | | { |
| | | id: 5, |
| | | tankCode: 'TANK005', |
| | | tankName: 'æ¶²åæ°å¨ç½E', |
| | | tankType: 'æ¶²åæ°å¨ç½', |
| | | specificationModel: 'LPG-6000L', |
| | | volume: 6000, |
| | | currentGasLevel: 35, |
| | | safetyGasLevel: 30, |
| | | minGasLevel: 15, |
| | | maxGasLevel: 95, |
| | | currentPressure: 3.2, |
| | | warningType: 'æ°ä½ä¸è¶³', |
| | | warningLevel: 'éè¦', |
| | | warningThreshold: 20, |
| | | isEnabled: false, |
| | | warningTime: '2024-01-14 14:30:00', |
| | | warningDuration: 2, |
| | | lastUpdateTime: '2024-01-15 09:00:00', |
| | | expectedRefillTime: '2024-01-19 08:00:00', |
| | | expectedShortageTime: '2024-01-21 10:00:00', // 6天åç¼ºæ° |
| | | warningRule: '彿°ä½éä½äº20%æ¶è§¦åé¢è¦' |
| | | }, |
| | | { |
| | | id: 6, |
| | | tankCode: 'TANK006', |
| | | tankName: 'å缩æ°å¨ç½F', |
| | | tankType: 'å缩æ°å¨ç½', |
| | | specificationModel: 'COMP-4000L', |
| | | volume: 4000, |
| | | currentGasLevel: 85, |
| | | safetyGasLevel: 20, |
| | | minGasLevel: 10, |
| | | maxGasLevel: 90, |
| | | currentPressure: 7.8, |
| | | warningType: 'ååå¼å¸¸', |
| | | warningLevel: 'ä¸è¬', |
| | | warningThreshold: 8, |
| | | isEnabled: true, |
| | | warningTime: '2024-01-12 09:20:00', |
| | | warningDuration: 1, |
| | | lastUpdateTime: '2024-01-15 08:30:00', |
| | | expectedRefillTime: '2024-01-25 14:00:00', |
| | | expectedShortageTime: '2024-01-28 16:00:00', // 13天åç¼ºæ° |
| | | warningRule: 'å½ååè¶
è¿8MPaæ¶è§¦åé¢è¦' |
| | | }, |
| | | { |
| | | id: 7, |
| | | tankCode: 'TANK007', |
| | | tankName: 'å¤©ç¶æ°å¨ç½G', |
| | | tankType: 'å¤©ç¶æ°å¨ç½', |
| | | specificationModel: 'NG-10000L', |
| | | volume: 10000, |
| | | currentGasLevel: 92, |
| | | safetyGasLevel: 15, |
| | | minGasLevel: 8, |
| | | maxGasLevel: 95, |
| | | currentPressure: 5.2, |
| | | warningType: '温度å¼å¸¸', |
| | | warningLevel: 'éè¦', |
| | | warningThreshold: 6, |
| | | isEnabled: true, |
| | | warningTime: '2024-01-11 16:45:00', |
| | | warningDuration: 1, |
| | | lastUpdateTime: '2024-01-15 07:45:00', |
| | | expectedRefillTime: '2024-01-30 09:00:00', |
| | | expectedShortageTime: '2024-02-05 12:00:00', // 21天åç¼ºæ° |
| | | warningRule: '彿¸©åº¦è¶
è¿60°Cæ¶è§¦åé¢è¦' |
| | | }, |
| | | { |
| | | id: 8, |
| | | tankCode: 'TANK008', |
| | | tankName: 'æ°§æ°å¨ç½H', |
| | | tankType: 'æ°§æ°å¨ç½', |
| | | specificationModel: 'O2-1500L', |
| | | volume: 1500, |
| | | currentGasLevel: 12, |
| | | safetyGasLevel: 30, |
| | | minGasLevel: 8, |
| | | maxGasLevel: 90, |
| | | currentPressure: 4.5, |
| | | warningType: 'æ³æ¼é¢è¦', |
| | | warningLevel: 'ç´§æ¥', |
| | | warningThreshold: 12, |
| | | isEnabled: true, |
| | | warningTime: '2024-01-15 06:30:00', |
| | | warningDuration: 5, |
| | | lastUpdateTime: '2024-01-15 12:15:00', |
| | | expectedRefillTime: '2024-01-15 20:00:00', |
| | | expectedShortageTime: '2024-01-15 17:30:00', // ä»å¤©ä¸å5:30ç¼ºæ° |
| | | warningRule: '彿£æµå°æ°ä½æ³æ¼æ¶è§¦åé¢è¦' |
| | | } |
| | | ] |
| | | |
| | | // æ ¹æ®æç´¢æ¡ä»¶è¿æ»¤æ°æ® |
| | | let filteredData = mockData.filter(item => { |
| | | if (searchForm.tankName && !item.tankName.includes(searchForm.tankName)) return false |
| | | if (searchForm.tankType && item.tankType !== searchForm.tankType) return false |
| | | if (searchForm.warningType && item.warningType !== searchForm.warningType) return false |
| | | if (searchForm.warningLevel && item.warningLevel !== searchForm.warningLevel) return false |
| | | return true |
| | | }) |
| | | |
| | | // å页å¤ç |
| | | const start = (page.current - 1) * page.size |
| | | const end = start + page.size |
| | | const paginatedData = filteredData.slice(start, end) |
| | | |
| | | return { |
| | | records: paginatedData, |
| | | total: filteredData.length |
| | | } |
| | | } |
| | | |
| | | // è·ååè¡¨æ°æ® |
| | | const getList = async () => { |
| | | tableLoading.value = true |
| | | try { |
| | | // 模æç½ç»å»¶è¿ |
| | | await new Promise(resolve => setTimeout(resolve, 500)) |
| | | |
| | | const result = generateMockData() |
| | | tableData.value = result.records |
| | | total.value = result.total |
| | | |
| | | // æ£æ¥ç¼ºæ°é¢è¦ |
| | | checkShortageWarnings() |
| | | } catch (error) { |
| | | console.error('è·åå表失败:', error) |
| | | ElMessage.error('è·åå表失败') |
| | | } finally { |
| | | tableLoading.value = false |
| | | } |
| | | } |
| | | |
| | | // æç´¢ |
| | | const handleQuery = () => { |
| | | page.current = 1 |
| | | getList() |
| | | } |
| | | |
| | | // éç½®æç´¢ |
| | | const resetQuery = () => { |
| | | Object.keys(searchForm).forEach(key => { |
| | | searchForm[key] = '' |
| | | }) |
| | | handleQuery() |
| | | } |
| | | |
| | | // å页åå |
| | | const paginationChange = (obj) => { |
| | | page.current = obj.page |
| | | page.size = obj.limit |
| | | getList() |
| | | } |
| | | |
| | | // è¡¨æ ¼éæ©åå |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection |
| | | } |
| | | |
| | | // æ°å¢ |
| | | const handleAdd = () => { |
| | | operationType.value = 'add' |
| | | resetForm() |
| | | dialogFormVisible.value = true |
| | | } |
| | | |
| | | // ç¼è¾ |
| | | const handleEdit = (row) => { |
| | | operationType.value = 'edit' |
| | | Object.assign(form, row) |
| | | dialogFormVisible.value = true |
| | | } |
| | | |
| | | // å¤çé¢è¦ |
| | | const handleProcess = async (row) => { |
| | | try { |
| | | // 模æAPIè°ç¨å»¶è¿ |
| | | await new Promise(resolve => setTimeout(resolve, 300)) |
| | | ElMessage.success(`æ£å¨å¤çé¢è¦ï¼${row.tankName}`) |
| | | getList() |
| | | } catch (error) { |
| | | ElMessage.error('å¤çé¢è¦å¤±è´¥') |
| | | } |
| | | } |
| | | |
| | | // å é¤ |
| | | const handleDelete = async (row) => { |
| | | try { |
| | | await ElMessageBox.confirm(`ç¡®å®è¦å é¤é¢è¦è§åï¼${row.tankName}åï¼`, 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | }) |
| | | |
| | | // 模æAPIè°ç¨å»¶è¿ |
| | | await new Promise(resolve => setTimeout(resolve, 300)) |
| | | ElMessage.success('å 餿å') |
| | | getList() |
| | | } catch (error) { |
| | | if (error !== 'cancel') { |
| | | ElMessage.error('å é¤å¤±è´¥') |
| | | } |
| | | } |
| | | } |
| | | |
| | | // æ¹éå¤ç |
| | | const handleBatchProcess = async () => { |
| | | if (selectedRows.value.length === 0) { |
| | | ElMessage.warning('è¯·éæ©è¦å¤ççé¢è¦') |
| | | return |
| | | } |
| | | |
| | | try { |
| | | // 模æAPIè°ç¨å»¶è¿ |
| | | await new Promise(resolve => setTimeout(resolve, 500)) |
| | | ElMessage.success(`æ¹éå¤çäº ${selectedRows.value.length} æ¡é¢è¦`) |
| | | getList() |
| | | } catch (error) { |
| | | ElMessage.error('æ¹éå¤ç失败') |
| | | } |
| | | } |
| | | |
| | | // å¯¼åº |
| | | const handleExport = async () => { |
| | | try { |
| | | // 模æAPIè°ç¨å»¶è¿ |
| | | await new Promise(resolve => setTimeout(resolve, 800)) |
| | | |
| | | // çæå¯¼åºæ°æ® |
| | | const exportData = generateMockData().records |
| | | const csvContent = generateCSV(exportData) |
| | | |
| | | // å建ä¸è½½é¾æ¥ |
| | | const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' }) |
| | | const url = window.URL.createObjectURL(blob) |
| | | const link = document.createElement('a') |
| | | link.href = url |
| | | link.download = `卿°ç½é¢è¦æ°æ®_${new Date().getTime()}.csv` |
| | | link.click() |
| | | window.URL.revokeObjectURL(url) |
| | | |
| | | ElMessage.success('å¯¼åºæå') |
| | | } catch (error) { |
| | | ElMessage.error('导åºå¤±è´¥') |
| | | } |
| | | } |
| | | |
| | | // çæCSVå
容 |
| | | const generateCSV = (data) => { |
| | | const headers = [ |
| | | '卿°ç½ç¼ç ', '卿°ç½åç§°', '卿°ç½ç±»å', 'è§æ ¼åå·', '容积(m³)', |
| | | 'å½åæ°ä½é(%)', 'å®å
¨æ°ä½é(%)', 'æä½æ°ä½é(%)', 'æé«æ°ä½é(%)', |
| | | 'å½ååå(MPa)', 'é¢è¦ç±»å', 'é¢è¦çº§å«', 'é¢è¦éå¼', 'æ¯å¦å¯ç¨', |
| | | 'é¢è¦æ¶é´', 'é¢è¦æç»å¤©æ°', 'æåæ´æ°æ¶é´', 'é¢è®¡å
è£
æ¶é´', 'é¢è®¡ç¼ºæ°æ¶é´', 'é¢è¦è§åæè¿°' |
| | | ] |
| | | |
| | | const csvRows = [headers.join(',')] |
| | | |
| | | data.forEach(item => { |
| | | const row = [ |
| | | item.tankCode, |
| | | item.tankName, |
| | | item.tankType, |
| | | item.specificationModel, |
| | | item.volume, |
| | | item.currentGasLevel, |
| | | item.safetyGasLevel, |
| | | item.minGasLevel, |
| | | item.maxGasLevel, |
| | | item.currentPressure, |
| | | item.warningType, |
| | | item.warningLevel, |
| | | item.warningThreshold, |
| | | item.isEnabled ? 'æ¯' : 'å¦', |
| | | item.warningTime, |
| | | item.warningDuration, |
| | | item.lastUpdateTime, |
| | | item.expectedRefillTime, |
| | | item.expectedShortageTime, |
| | | item.warningRule |
| | | ] |
| | | csvRows.push(row.join(',')) |
| | | }) |
| | | |
| | | return csvRows.join('\n') |
| | | } |
| | | |
| | | // å¯ç¨ç¶æåå |
| | | const handleEnableChange = async (row) => { |
| | | try { |
| | | // 模æAPIè°ç¨å»¶è¿ |
| | | await new Promise(resolve => setTimeout(resolve, 200)) |
| | | ElMessage.success(`${row.tankName} çå¯ç¨ç¶æå·²æ´æ°`) |
| | | } catch (error) { |
| | | ElMessage.error('ç¶ææ´æ°å¤±è´¥') |
| | | // æ¢å¤åç¶æ |
| | | row.isEnabled = !row.isEnabled |
| | | } |
| | | } |
| | | |
| | | // æäº¤è¡¨å |
| | | const submitForm = async () => { |
| | | try { |
| | | await proxy.$refs.formRef.validate() |
| | | |
| | | // 模æAPIè°ç¨å»¶è¿ |
| | | await new Promise(resolve => setTimeout(resolve, 500)) |
| | | |
| | | if (operationType.value === 'add') { |
| | | ElMessage.success('æ°å¢æå') |
| | | } else { |
| | | ElMessage.success('ç¼è¾æå') |
| | | } |
| | | |
| | | closeDialog() |
| | | getList() |
| | | } catch (error) { |
| | | if (!error.errors) { |
| | | ElMessage.error(operationType.value === 'add' ? 'æ°å¢å¤±è´¥' : 'ç¼è¾å¤±è´¥') |
| | | } |
| | | } |
| | | } |
| | | |
| | | // å
³éå¼¹çª |
| | | const closeDialog = () => { |
| | | dialogFormVisible.value = false |
| | | resetForm() |
| | | } |
| | | |
| | | // é置表å |
| | | const resetForm = () => { |
| | | Object.keys(form).forEach(key => { |
| | | if (key === 'isEnabled') { |
| | | form[key] = true |
| | | } else if (typeof form[key] === 'number') { |
| | | form[key] = 0 |
| | | } else { |
| | | form[key] = '' |
| | | } |
| | | }) |
| | | proxy.$refs.formRef?.resetFields() |
| | | } |
| | | |
| | | // è·åæ°ä½éæ ·å¼ç±» |
| | | const getGasLevelClass = (row) => { |
| | | if (row.currentGasLevel < row.minGasLevel) { |
| | | return 'text-danger' |
| | | } else if (row.currentGasLevel > row.maxGasLevel) { |
| | | return 'text-warning' |
| | | } |
| | | return 'text-success' |
| | | } |
| | | |
| | | // è·åé¢è¦ç±»åæ ç¾æ ·å¼ |
| | | const getWarningTypeTag = (type) => { |
| | | const typeMap = { |
| | | 'æ°ä½ä¸è¶³': 'danger', |
| | | 'ååå¼å¸¸': 'warning', |
| | | '温度å¼å¸¸': 'info', |
| | | 'æ³æ¼é¢è¦': 'danger' |
| | | } |
| | | return typeMap[type] || 'info' |
| | | } |
| | | |
| | | // è·åé¢è¦çº§å«æ ç¾æ ·å¼ |
| | | const getWarningLevelTag = (level) => { |
| | | const levelMap = { |
| | | 'ç´§æ¥': 'danger', |
| | | 'éè¦': 'warning', |
| | | 'ä¸è¬': 'info' |
| | | } |
| | | return levelMap[level] || 'info' |
| | | } |
| | | |
| | | // å¯å¨å计æ¶å®æ¶å¨ |
| | | const startCountdownTimer = () => { |
| | | countdownTimer.value = setInterval(() => { |
| | | checkShortageWarnings() |
| | | }, 60000) // æ¯å鿣æ¥ä¸æ¬¡ |
| | | } |
| | | |
| | | // 忢å计æ¶å®æ¶å¨ |
| | | const stopCountdownTimer = () => { |
| | | if (countdownTimer.value) { |
| | | clearInterval(countdownTimer.value) |
| | | countdownTimer.value = null |
| | | } |
| | | } |
| | | |
| | | // 页é¢å è½½ |
| | | onMounted(() => { |
| | | getList() |
| | | startCountdownTimer() |
| | | }) |
| | | |
| | | // 页é¢å¸è½½ |
| | | onUnmounted(() => { |
| | | stopCountdownTimer() |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .app-container { |
| | | padding: 20px; |
| | | |
| | | .table-operations { |
| | | text-align: right; |
| | | margin-bottom: 20px; |
| | | |
| | | .el-button { |
| | | margin-right: 10px; |
| | | } |
| | | } |
| | | |
| | | .table_list { |
| | | background: #fff; |
| | | border-radius: 4px; |
| | | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); |
| | | } |
| | | |
| | | .text-danger { |
| | | color: #f56c6c; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .text-warning { |
| | | color: #e6a23c; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .text-success { |
| | | color: #67c23a; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | text-align: right; |
| | | } |
| | | |
| | | // åè®¡æ¶æ ·å¼ |
| | | .countdown-timer { |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .countdown-normal { |
| | | color: #67c23a; |
| | | } |
| | | |
| | | .countdown-warning { |
| | | color: #e6a23c; |
| | | } |
| | | |
| | | .countdown-urgent { |
| | | color: #f56c6c; |
| | | animation: blink 1s infinite; |
| | | } |
| | | |
| | | .countdown-expired { |
| | | color: #f56c6c; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | @keyframes blink { |
| | | 0%, 50% { opacity: 1; } |
| | | 51%, 100% { opacity: 0.5; } |
| | | } |
| | | |
| | | // 缺æ°é¢è¦å¼¹æ¡æ ·å¼ |
| | | .shortage-warning-content { |
| | | text-align: center; |
| | | padding: 20px 0; |
| | | |
| | | .warning-icon { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .warning-message { |
| | | h3 { |
| | | color: #f56c6c; |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | p { |
| | | margin-bottom: 10px; |
| | | color: #606266; |
| | | } |
| | | |
| | | .warning-details { |
| | | background: #f5f7fa; |
| | | padding: 15px; |
| | | border-radius: 4px; |
| | | text-align: left; |
| | | font-size: 14px; |
| | | line-height: 1.6; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div> |
| | | <el-dialog |
| | | v-model="dialogFormVisible" |
| | | :title="operationType === 'add' ? 'æ°å¢å
¥è' : 'ç¼è¾äººå'" |
| | | width="50%" |
| | | @close="closeDia" |
| | | > |
| | | <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef"> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æä»½ï¼" prop="payDate"> |
| | | <el-date-picker |
| | | v-model="form.payDate" |
| | | type="month" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM" |
| | | placeholder="è¯·éæ©æä»½" |
| | | clearable |
| | | :disabled="operationType === 'edit'" |
| | | style="width: 100%" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å§åï¼" prop="staffId"> |
| | | <el-select v-model="form.staffId" placeholder="è¯·éæ©äººå" style="width: 100%" @change="handleSelect" :disabled="operationType === 'edit'"> |
| | | <el-option |
| | | v-for="item in personList" |
| | | :key="item.id" |
| | | :label="item.staffName" |
| | | :value="item.id" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="åºåºå¤å¤©æ°ï¼" prop="shouldAttendedNum"> |
| | | <el-input v-model="form.shouldAttendedNum" placeholder="请è¾å
¥" clearable type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å®é
åºå¤å¤©æ°ï¼" prop="actualAttendedNum"> |
| | | <el-input v-model="form.actualAttendedNum" placeholder="请è¾å
¥" clearable type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="åºæ¬å·¥èµï¼" prop="basicSalary"> |
| | | <el-input v-model="form.basicSalary" placeholder="请è¾å
¥" clearable type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å²ä½å·¥èµï¼" prop="postSalary"> |
| | | <el-input v-model="form.postSalary" placeholder="请è¾å
¥" clearable type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å
¥ç¦»èç¼ºå¤æ£æ¬¾ï¼" prop="deductionAbsenteeism"> |
| | | <el-input v-model="form.deductionAbsenteeism" placeholder="请è¾å
¥" clearable type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç
åæ£æ¬¾ï¼" prop="sickLeaveDeductions"> |
| | | <el-input v-model="form.sickLeaveDeductions" placeholder="请è¾å
¥" clearable type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="äºåæ£æ¬¾ï¼" prop="deductionPersonalLeave"> |
| | | <el-input v-model="form.deductionPersonalLeave" placeholder="请è¾å
¥" clearable type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å¿è®°æå¡æ£æ¬¾ï¼" prop="forgetClockDeduct"> |
| | | <el-input v-model="form.forgetClockDeduct" style="width: 100%" type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="绩æå¾åï¼" prop="performanceScore"> |
| | | <el-input v-model="form.performanceScore" placeholder="请è¾å
¥" clearable type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="绩æå·¥èµï¼" prop="performancePay"> |
| | | <el-input v-model="form.performancePay" placeholder="请è¾å
¥" clearable type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="åºåå计ï¼" prop="payableWages"> |
| | | <el-input v-model="form.payableWages" placeholder="请è¾å
¥" clearable type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="社ä¿ä¸ªäººï¼" prop="socialSecurityIndividuals"> |
| | | <el-input v-model="form.socialSecurityIndividuals" :precision="0" :step="1" style="width: 100%" type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="社ä¿å
¬å¸ï¼" prop="socialSecurityCompanies"> |
| | | <el-input v-model="form.socialSecurityCompanies" :precision="0" :step="1" style="width: 100%" type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="社ä¿å计ï¼" prop="socialSecurityTotal"> |
| | | <el-input v-model="form.socialSecurityTotal" :precision="0" :step="1" style="width: 100%" type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å
¬ç§¯é个人ï¼" prop="providentFundIndividuals"> |
| | | <el-input v-model="form.providentFundIndividuals" :precision="0" :step="1" style="width: 100%" type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å
¬ç§¯éå
¬å¸ï¼" prop="providentFundCompany"> |
| | | <el-input v-model="form.providentFundCompany" :precision="0" :step="1" style="width: 100%" type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å
¬ç§¯éå计ï¼" prop="providentFundTotal"> |
| | | <el-input v-model="form.providentFundTotal" :precision="0" :step="1" style="width: 100%" type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="åºç¨å·¥èµï¼" prop="taxableWaget"> |
| | | <el-input v-model="form.taxableWaget" :precision="0" :step="1" style="width: 100%" type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="个人æå¾ç¨ï¼" prop="personalIncomeTax"> |
| | | <el-input v-model="form.personalIncomeTax" :step="0.1" style="width: 100%" type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å®åå·¥èµï¼" prop="actualWages"> |
| | | <el-input v-model="form.actualWages" style="width: 100%" type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm">确认</el-button> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref} from "vue"; |
| | | import {getStaffJoinInfo, getStaffOnJob, staffJoinAdd, staffJoinUpdate} from "@/api/personnelManagement/onboarding.js"; |
| | | import {compensationAdd, compensationUpdate} from "@/api/personnelManagement/payrollManagement.js"; |
| | | const { proxy } = getCurrentInstance() |
| | | const emit = defineEmits(['close']) |
| | | |
| | | const dialogFormVisible = ref(false); |
| | | const operationType = ref('') |
| | | const data = reactive({ |
| | | form: { |
| | | payDate: "", |
| | | staffId: "", |
| | | name: "", |
| | | shouldAttendedNum: "", |
| | | actualAttendedNum: "", |
| | | basicSalary: "", |
| | | postSalary: "", |
| | | deductionAbsenteeism: "", |
| | | sickLeaveDeductions: "", |
| | | deductionPersonalLeave: "", |
| | | forgetClockDeduct: "", |
| | | performanceScore: "", |
| | | performancePay: "", |
| | | payableWages: "", |
| | | socialSecurityIndividuals: "", |
| | | socialSecurityCompanies: "", |
| | | socialSecurityTotal: "", |
| | | providentFundIndividuals: "", |
| | | providentFundCompany: "", |
| | | providentFundTotal: "", |
| | | taxableWaget: "", |
| | | personalIncomeTax: "", |
| | | actualWages: "", |
| | | }, |
| | | rules: { |
| | | payDate: [{ required: true, message: "è¯·éæ©", trigger: "change" },], |
| | | staffId: [{ required: true, message: "è¯·éæ©", trigger: "change" },], |
| | | staffName: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | shouldAttendedNum: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | actualAttendedNum: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | basicSalary: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | postSalary: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | deductionAbsenteeism: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | sickLeaveDeductions: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | deductionPersonalLeave: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | forgetClockDeduct: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | performanceScore: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | performancePay: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | payableWages: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | socialSecurityIndividuals: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | socialSecurityCompanies: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | socialSecurityTotal: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | providentFundIndividuals: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | providentFundCompany: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | providentFundTotal: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | taxableWaget: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | personalIncomeTax: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | actualWages: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | }, |
| | | }); |
| | | const { form, rules } = toRefs(data); |
| | | const personList = ref([]); |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openDialog = (type, row) => { |
| | | operationType.value = type; |
| | | dialogFormVisible.value = true; |
| | | getStaffOnJob().then(res => { |
| | | personList.value = res.data |
| | | }) |
| | | form.value = {} |
| | | if (operationType.value === 'edit') { |
| | | getStaffJoinInfo(row.id).then(res => { |
| | | form.value = {...row} |
| | | form.value.payDate = form.value.payDate + '-01' |
| | | }) |
| | | } |
| | | } |
| | | const handleSelect = (value) => { |
| | | console.log('value', value) |
| | | const index = personList.value.findIndex(row => row.id === value) |
| | | if (index > -1) { |
| | | form.value.name = personList.value[index].staffName |
| | | } |
| | | } |
| | | // æäº¤äº§å表å |
| | | const submitForm = () => { |
| | | proxy.$refs.formRef.validate(valid => { |
| | | if (valid) { |
| | | form.value.staffState = 1 |
| | | if (operationType.value === "add") { |
| | | compensationAdd(form.value).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | }) |
| | | } else { |
| | | compensationUpdate(form.value).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | }) |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | // 计ç®ååå¹´é |
| | | const calculateContractTerm = () => { |
| | | if (form.value.contractStartTime && form.value.contractEndTime) { |
| | | const startDate = new Date(form.value.contractStartTime); |
| | | const endDate = new Date(form.value.contractEndTime); |
| | | |
| | | if (endDate > startDate) { |
| | | // 计ç®å¹´ä»½å·® |
| | | const yearDiff = endDate.getFullYear() - startDate.getFullYear(); |
| | | const monthDiff = endDate.getMonth() - startDate.getMonth(); |
| | | const dayDiff = endDate.getDate() - startDate.getDate(); |
| | | |
| | | let years = yearDiff; |
| | | |
| | | // å¦æç»ææ¥æçææ¥å°äºå¼å§æ¥æçææ¥ï¼ååå»1å¹´ |
| | | if (monthDiff < 0 || (monthDiff === 0 && dayDiff < 0)) { |
| | | years = yearDiff - 1; |
| | | } |
| | | |
| | | form.value.contractTerm = Math.max(0, years); |
| | | } else { |
| | | form.value.contractTerm = 0; |
| | | } |
| | | } else { |
| | | form.value.contractTerm = 0; |
| | | } |
| | | }; |
| | | |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | dialogFormVisible.value = false; |
| | | emit('close') |
| | | }; |
| | | defineExpose({ |
| | | openDialog, |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title">å§åï¼</span> |
| | | <el-input |
| | | v-model="searchForm.name" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥å§åæç´¢" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | /> |
| | | <span class="search_title ml10">æä»½ï¼</span> |
| | | <el-date-picker |
| | | v-model="searchForm.payDateStr" |
| | | type="month" |
| | | @change="handleQuery" |
| | | value-format="YYYY-MM" |
| | | format="YYYY-MM" |
| | | placeholder="è¯·éæ©æä»½" |
| | | style="width: 240px" |
| | | clearable |
| | | /> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px" |
| | | >æç´¢</el-button |
| | | > |
| | | </div> |
| | | <div> |
| | | <el-button type="primary" @click="openForm('add')">æ°å¢èªèµ</el-button> |
| | | <!-- <el-button @click="handleOut">导åº</el-button>--> |
| | | <el-button type="danger" plain @click="handleDelete">å é¤</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | :total="page.total" |
| | | ></PIMTable> |
| | | </div> |
| | | <form-dia ref="formDia" @close="handleQuery"></form-dia> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import {onMounted, ref} from "vue"; |
| | | import FormDia from "@/views/personnelManagement/payrollManagement/components/formDia.vue"; |
| | | import {staffJoinDel} from "@/api/personnelManagement/onboarding.js"; |
| | | import {ElMessageBox} from "element-plus"; |
| | | import dayjs from "dayjs"; |
| | | import {compensationDelete, compensationListPage} from "@/api/personnelManagement/payrollManagement.js"; |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | name: "", |
| | | payDateStr: "", |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "èªèµæä»½", |
| | | prop: "payDate", |
| | | }, |
| | | { |
| | | label: "å§å", |
| | | prop: "name", |
| | | }, |
| | | { |
| | | label: "åºåºå¤å¤©æ°", |
| | | prop: "shouldAttendedNum", |
| | | width:100 |
| | | }, |
| | | { |
| | | label: "å®é
åºå¤å¤©æ°", |
| | | prop: "actualAttendedNum", |
| | | width:110 |
| | | }, |
| | | { |
| | | label: "åºæ¬å·¥èµ", |
| | | prop: "basicSalary", |
| | | }, |
| | | { |
| | | label: "å²ä½å·¥èµ", |
| | | prop: "postSalary", |
| | | width:100 |
| | | }, |
| | | { |
| | | label: "å
¥ç¦»èç¼ºå¤æ£æ¬¾", |
| | | prop: "deductionAbsenteeism", |
| | | width:130 |
| | | }, |
| | | { |
| | | label: "ç
åæ£æ¬¾", |
| | | prop: "sickLeaveDeductions", |
| | | width:100 |
| | | }, |
| | | { |
| | | label: "äºåæ£æ¬¾", |
| | | prop: "deductionPersonalLeave", |
| | | width:100 |
| | | }, |
| | | { |
| | | label: "å¿è®°æå¡æ£æ¬¾", |
| | | prop: "forgetClockDeduct", |
| | | width:110 |
| | | }, |
| | | { |
| | | label: "绩æå¾å", |
| | | prop: "performanceScore", |
| | | width:150 |
| | | }, |
| | | { |
| | | label: "绩æå·¥èµ", |
| | | prop: "performancePay", |
| | | width: 120 |
| | | }, |
| | | { |
| | | label: "åºåå计", |
| | | prop: "payableWages", |
| | | width:150 |
| | | }, |
| | | { |
| | | label: "社ä¿ä¸ªäºº", |
| | | prop: "socialSecurityIndividuals", |
| | | }, |
| | | { |
| | | label: "社ä¿å
¬å¸", |
| | | prop: "socialSecurityCompanies", |
| | | width: 120 |
| | | }, |
| | | { |
| | | label: "社ä¿å计", |
| | | prop: "socialSecurityTotal", |
| | | width: 120 |
| | | }, |
| | | { |
| | | label: "å
¬ç§¯é个人", |
| | | prop: "providentFundIndividuals", |
| | | width: 120 |
| | | }, |
| | | { |
| | | label: "å
¬ç§¯éå
¬å¸", |
| | | prop: "providentFundCompany", |
| | | width: 120 |
| | | }, |
| | | { |
| | | label: "å
¬ç§¯éå计", |
| | | prop: "providentFundTotal", |
| | | width: 120 |
| | | }, |
| | | { |
| | | label: "åºç¨å·¥èµ", |
| | | prop: "taxableWaget", |
| | | }, |
| | | { |
| | | label: "个人æå¾ç¨", |
| | | prop: "personalIncomeTax", |
| | | width: 120 |
| | | }, |
| | | { |
| | | label: "å®åå·¥èµ", |
| | | prop: "actualWages", |
| | | width: 120 |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: 'right', |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openForm("edit", row); |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const tableLoading = ref(false); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | const formDia = ref() |
| | | const { proxy } = getCurrentInstance() |
| | | |
| | | const handleDateChange = (value,type) => { |
| | | searchForm.value.entryDateEnd = null |
| | | searchForm.value.entryDateStart = null |
| | | if(type === 1){ |
| | | if (value) { |
| | | searchForm.value.entryDateStart = dayjs(value).format("YYYY-MM-DD"); |
| | | } |
| | | }else{ |
| | | if (value) { |
| | | searchForm.value.entryDateEnd = dayjs(value).format("YYYY-MM-DD"); |
| | | } |
| | | } |
| | | getList(); |
| | | }; |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const pagination = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | compensationListPage({...page, ...searchForm.value, staffState: 1}).then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records |
| | | page.total = res.data.total; |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | | }) |
| | | }; |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openForm = (type, row) => { |
| | | nextTick(() => { |
| | | formDia.value?.openDialog(type, row) |
| | | }) |
| | | }; |
| | | |
| | | // å é¤ |
| | | const handleDelete = () => { |
| | | let ids = []; |
| | | if (selectedRows.value.length > 0) { |
| | | ids = selectedRows.value.map((item) => item.id); |
| | | } else { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | | } |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | compensationDelete(ids).then((res) => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/staff/staffJoinLeaveRecord/export", {staffState: 1}, "人åå
¥è.xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped></style> |
| | |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ°éï¼" prop="quantity"> |
| | | <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="form.quantity" placeholder="请è¾å
¥" clearable :precision="2"/> |
| | | <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="form.quantity" placeholder="请è¾å
¥" |
| | | clearable :precision="2"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ£æµç»æï¼" prop="checkResult"> |
| | | <el-select v-model="form.checkResult"> |
| | | <el-option label="åæ ¼" value="åæ ¼" /> |
| | | <el-option label="ä¸åæ ¼" value="ä¸åæ ¼" /> |
| | | <el-option label="åæ ¼" value="åæ ¼"/> |
| | | <el-option label="ä¸åæ ¼" value="ä¸åæ ¼"/> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ£éªåï¼" prop="checkName"> |
| | | <el-input v-model="form.checkName" placeholder="请è¾å
¥" clearable/> |
| | | |
| | | |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <div style="margin-bottom: 10px;text-align: right"> |
| | | <el-button type="danger" plain @click="handleDelete">å é¤</el-button> |
| | | </div> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :tableLoading="tableLoading" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | height="400" |
| | | > |
| | | <template #slot="{ row }"> |
| | | <el-input v-model="row.testValue" clearable/> |
| | | </template> |
| | | </PIMTable> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm">确认</el-button> |
| | |
| | | import {getOptions} from "@/api/procurementManagement/procurementLedger.js"; |
| | | import {productTreeList} from "@/api/basicData/product.js"; |
| | | import {qualityInspectAdd, qualityInspectUpdate} from "@/api/qualityManagement/rawMaterialInspection.js"; |
| | | const { proxy } = getCurrentInstance() |
| | | import {ElMessageBox} from "element-plus"; |
| | | import {qualityInspectParamDel, qualityInspectParamInfo} from "@/api/qualityManagement/qualityInspectParam.js"; |
| | | import {qualityInspectDetailByProductId} from "@/api/qualityManagement/metricMaintenance.js"; |
| | | |
| | | const {proxy} = getCurrentInstance() |
| | | const emit = defineEmits(['close']) |
| | | |
| | | const dialogFormVisible = ref(false); |
| | |
| | | checkResult: "", |
| | | }, |
| | | rules: { |
| | | checkTime: [{ required: false, message: "请è¾å
¥", trigger: "blur" },], |
| | | supplier: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | checkName: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | productId: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | model: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | unit: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | quantity: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | checkCompany: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | checkResult: [{ required: true, message: "è¯·éæ©æ£æµç»æ", trigger: "change" }], |
| | | checkTime: [{required: false, message: "请è¾å
¥", trigger: "blur"},], |
| | | supplier: [{required: true, message: "请è¾å
¥", trigger: "blur"}], |
| | | checkName: [{required: false, message: "请è¾å
¥", trigger: "blur"}], |
| | | productId: [{required: true, message: "请è¾å
¥", trigger: "blur"}], |
| | | model: [{required: false, message: "请è¾å
¥", trigger: "blur"}], |
| | | unit: [{required: false, message: "请è¾å
¥", trigger: "blur"}], |
| | | quantity: [{required: true, message: "请è¾å
¥", trigger: "blur"}], |
| | | checkCompany: [{required: false, message: "请è¾å
¥", trigger: "blur"}], |
| | | checkResult: [{required: true, message: "è¯·éæ©æ£æµç»æ", trigger: "change"}], |
| | | }, |
| | | }); |
| | | const { form, rules } = toRefs(data); |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "ææ ", |
| | | prop: "parameterItem", |
| | | }, |
| | | { |
| | | label: "åä½", |
| | | prop: "unit", |
| | | }, |
| | | { |
| | | label: "æ åå¼", |
| | | prop: "standardValue", |
| | | }, |
| | | { |
| | | label: "å
æ§å¼", |
| | | prop: "controlValue", |
| | | }, |
| | | { |
| | | label: "æ£éªå¼", |
| | | prop: "testValue", |
| | | dataType: 'slot', |
| | | slot: 'slot', |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | |
| | | const {form, rules} = toRefs(data); |
| | | const supplierList = ref([]); |
| | | const productOptions = ref([]); |
| | | const currentProductId = ref(0); |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openDialog = (type, row) => { |
| | |
| | | getProductOptions(); |
| | | if (operationType.value === 'edit') { |
| | | form.value = {...row} |
| | | currentProductId.value = row.productId || 0 |
| | | getQualityInspectParamList(row.id) |
| | | } |
| | | } |
| | | const getProductOptions = () => { |
| | |
| | | }); |
| | | }; |
| | | const getModels = (value) => { |
| | | currentProductId.value = value |
| | | form.value.productName = findNodeById(productOptions.value, value); |
| | | if (currentProductId) { |
| | | getList(); |
| | | } |
| | | }; |
| | | const findNodeById = (nodes, productId) => { |
| | | for (let i = 0; i < nodes.length; i++) { |
| | |
| | | } |
| | | return null; // æ²¡ææ¾å°èç¹ï¼è¿ånull |
| | | }; |
| | | |
| | | function convertIdToValue(data) { |
| | | return data.map((item) => { |
| | | const { id, children, ...rest } = item; |
| | | const {id, children, ...rest} = item; |
| | | const newItem = { |
| | | ...rest, |
| | | value: id, // å° id æ¹ä¸º value |
| | |
| | | if (children && children.length > 0) { |
| | | newItem.children = convertIdToValue(children); |
| | | } |
| | | |
| | | |
| | | return newItem; |
| | | }); |
| | | } |
| | | |
| | | // æäº¤äº§å表å |
| | | const submitForm = () => { |
| | | proxy.$refs.formRef.validate(valid => { |
| | | if (valid) { |
| | | form.value.inspectType = 0 |
| | | const data = {...form.value, qualityInspectParams: tableData.value} |
| | | if (operationType.value === "add") { |
| | | qualityInspectAdd(form.value).then(res => { |
| | | qualityInspectAdd(data).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | }) |
| | | } else { |
| | | qualityInspectUpdate(form.value).then(res => { |
| | | qualityInspectUpdate(data).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | }) |
| | |
| | | } |
| | | }) |
| | | } |
| | | |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | |
| | | const handleDelete = () => { |
| | | let ids = []; |
| | | if (selectedRows.value.length > 0) { |
| | | ids = selectedRows.value.map((item) => item.id); |
| | | } else { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | | } |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | qualityInspectParamDel(ids).then((res) => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | |
| | | const getList = () => { |
| | | qualityInspectDetailByProductId(currentProductId.value).then(res => { |
| | | tableData.value = res.data; |
| | | }) |
| | | } |
| | | |
| | | const getQualityInspectParamList = (id) => { |
| | | qualityInspectParamInfo(id).then(res => { |
| | | tableData.value = res.data; |
| | | }) |
| | | } |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | tableData.value = [] |
| | | dialogFormVisible.value = false; |
| | | emit('close') |
| | | }; |
| | |
| | | clearable |
| | | :prefix-icon="Search" |
| | | /> |
| | | <span style="margin-left: 10px" class="search_title">æ£æµæ¥æï¼</span> |
| | | <el-date-picker v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange" |
| | | placeholder="è¯·éæ©" clearable @change="changeDaterange" /> |
| | | <span style="margin-left: 10px" class="search_title">æ£æµæ¥æï¼</span> |
| | | <el-date-picker v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange" |
| | | placeholder="è¯·éæ©" clearable @change="changeDaterange"/> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px" |
| | | >æç´¢</el-button |
| | | >æç´¢ |
| | | </el-button |
| | | > |
| | | </div> |
| | | <div> |
| | |
| | | <InspectionFormDia ref="inspectionFormDia" @close="handleQuery"></InspectionFormDia> |
| | | <FormDia ref="formDia" @close="handleQuery"></FormDia> |
| | | <files-dia ref="filesDia" @close="handleQuery"></files-dia> |
| | | <el-dialog v-model="dialogFormVisible" title="ç¼è¾æ£éªå" width="70%" |
| | | @close="closeDia"> |
| | | <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef"> |
| | | <el-form-item label="æ£éªåï¼" prop="checkName"> |
| | | <el-select v-model="form.checkName" placeholder="è¯·éæ©" clearable> |
| | | <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName" |
| | | :value="item.nickName"/> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm">确认</el-button> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import {Search} from "@element-plus/icons-vue"; |
| | | import {onMounted, ref} from "vue"; |
| | | import InspectionFormDia from "@/views/qualityManagement/rawMaterialInspection/components/inspectionFormDia.vue"; |
| | | import FormDia from "@/views/qualityManagement/rawMaterialInspection/components/formDia.vue"; |
| | | import {ElMessageBox} from "element-plus"; |
| | | import {qualityInspectDel, qualityInspectListPage} from "@/api/qualityManagement/rawMaterialInspection.js"; |
| | | import { |
| | | downloadQualityInspect, |
| | | qualityInspectDel, |
| | | qualityInspectListPage, qualityInspectUpdate, |
| | | submitQualityInspect |
| | | } from "@/api/qualityManagement/rawMaterialInspection.js"; |
| | | import FilesDia from "@/views/qualityManagement/rawMaterialInspection/components/filesDia.vue"; |
| | | import dayjs from "dayjs"; |
| | | import {userListNoPage} from "@/api/system/user.js"; |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | |
| | | entryDateStart: dayjs().format("YYYY-MM-DD"), |
| | | entryDateEnd: dayjs().add(1, "day").format("YYYY-MM-DD"), |
| | | }, |
| | | rules: { |
| | | checkName: [{required: true, message: "è¯·éæ©", trigger: "change"}], |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | const {searchForm, rules} = toRefs(data); |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "æ£æµæ¥æ", |
| | |
| | | prop: "checkResult", |
| | | dataType: "tag", |
| | | formatType: (params) => { |
| | | if (params == 'ä¸åæ ¼') { |
| | | if (params === 'ä¸åæ ¼') { |
| | | return "danger"; |
| | | } else if (params == 'åæ ¼') { |
| | | } else if (params === 'åæ ¼') { |
| | | return "success"; |
| | | } else { |
| | | return null; |
| | | } |
| | | }, |
| | | }, |
| | | { |
| | | label: "æäº¤ç¶æ", |
| | | prop: "inspectState", |
| | | formatData: (params) => { |
| | | if (params) { |
| | | return "å·²æäº¤"; |
| | | } else { |
| | | return "æªæäº¤"; |
| | | } |
| | | }, |
| | | }, |
| | |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 190, |
| | | width: 250, |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | |
| | | }, |
| | | }, |
| | | { |
| | | name: "æ°å¢æ£éªè®°å½", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openInspectionForm("edit", row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "éä»¶", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openFilesFormDia(row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "æäº¤", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | submit(row.id); |
| | | }, |
| | | }, |
| | | { |
| | | name: "åé
æ£éªå", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | if (!row.checkName) { |
| | | open(row) |
| | | } else { |
| | | proxy.$modal.msgError("æ£éªåå·²åå¨"); |
| | | } |
| | | }, |
| | | }, |
| | | { |
| | | name: "ä¸è½½", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | downLoadFile(row); |
| | | }, |
| | | }, |
| | | ], |
| | |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const tableLoading = ref(false); |
| | | const userList = ref([]); |
| | | const dialogFormVisible = ref(false); |
| | | const form = ref({ |
| | | checkName: "" |
| | | }); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0 |
| | | }); |
| | | const currentRow = ref(null) |
| | | const formDia = ref() |
| | | const filesDia = ref() |
| | | const inspectionFormDia = ref() |
| | | const { proxy } = getCurrentInstance() |
| | | const {proxy} = getCurrentInstance() |
| | | const changeDaterange = (value) => { |
| | | searchForm.value.entryDateStart = undefined; |
| | | searchForm.value.entryDateEnd = undefined; |
| | |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | const params = { ...searchForm.value, ...page }; |
| | | const params = {...searchForm.value, ...page}; |
| | | params.entryDate = undefined |
| | | qualityInspectListPage({...params, inspectType: 0}).then(res => { |
| | | tableLoading.value = false; |
| | |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | |
| | | // æä»· |
| | | const submit = async (id) => { |
| | | const res = await submitQualityInspect({id: id}) |
| | | if (res.code === 200) { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | getList(); |
| | | } |
| | | } |
| | | |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | dialogFormVisible.value = false; |
| | | }; |
| | | |
| | | const submitForm = () => { |
| | | if (currentRow.value) { |
| | | const data = { |
| | | ...form.value, |
| | | id: currentRow.value.id |
| | | } |
| | | qualityInspectUpdate(data).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | getList(); |
| | | }) |
| | | } |
| | | }; |
| | | |
| | | const open = async (row) => { |
| | | let userLists = await userListNoPage(); |
| | | userList.value = userLists.data; |
| | | currentRow.value = row |
| | | dialogFormVisible.value = true |
| | | } |
| | | |
| | | const downLoadFile = (row) => { |
| | | downloadQualityInspect({id: row.id}).then(res => { |
| | | // å建 blob 对象 |
| | | const blob = new Blob([res.data], {type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'}) |
| | | const downloadUrl = window.URL.createObjectURL(blob) |
| | | |
| | | // åå»ºä¸´æ¶ <a> æ ç¾è¿è¡ä¸è½½ |
| | | const link = document.createElement('a') |
| | | link.href = downloadUrl |
| | | link.download = 'æ£éªæ¥å.docx' // è¿éåå端ä¸è´ |
| | | document.body.appendChild(link) |
| | | link.click() |
| | | |
| | | // æ¸
ç |
| | | document.body.removeChild(link) |
| | | window.URL.revokeObjectURL(downloadUrl) |
| | | }) |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |