From 2ee7a81c2eb0df1fc473da6dbbaa13df662967c5 Mon Sep 17 00:00:00 2001 From: wwl <xchao828@163.com> Date: 星期三, 02 七月 2025 15:43:59 +0800 Subject: [PATCH] 1 --- src/views/111111.vue | 335 +++++++++++++++ src/views/index.vue | 198 +++----- src/views/system/tijian/index.vue | 12 /dev/null | 198 --------- package.json | 4 src/api/system/tijian.js | 8 src/views/system/package/index.vue | 466 ++++++--------------- src/utils/websocket.js | 80 +++ 8 files changed, 641 insertions(+), 660 deletions(-) diff --git a/package.json b/package.json index 3a3e495..7b4bb63 100644 --- a/package.json +++ b/package.json @@ -68,13 +68,17 @@ "jsencrypt": "3.0.0-rc.1", "jspdf": "^3.0.1", "lodash": "^4.17.21", + "mammoth": "^1.9.1", "moment": "^2.30.1", "nprogress": "0.2.0", + "pdf2json": "^3.1.6", + "pdfjs-dist": "^5.3.31", "pdfmake": "^0.2.20", "pinyin-match": "^1.2.2", "print-js": "^1.6.0", "quill": "1.3.7", "screenfull": "5.0.2", + "socket.io-client": "^4.8.1", "sortablejs": "1.10.2", "tduck-form-generator": "^1.8.0", "tinymce": "^7.9.1", diff --git a/src/api/system/tijian.js b/src/api/system/tijian.js index 26d8c33..0394c36 100644 --- a/src/api/system/tijian.js +++ b/src/api/system/tijian.js @@ -55,13 +55,13 @@ }); } -export function getProParentIdDxList() { +export function getProParentIdDxList(xb) { return request({ url: "/hosp/project/getProParentIdDxList", method: "get", - // params: { - // pname: pname, - // }, + params: { + xb: xb, + }, }); } diff --git a/src/utils/websocket.js b/src/utils/websocket.js new file mode 100644 index 0000000..a525f68 --- /dev/null +++ b/src/utils/websocket.js @@ -0,0 +1,80 @@ +// src/utils/websocket.js +let socket = null; +let reconnectAttempts = 0; +const maxReconnectAttempts = 5; +const reconnectInterval = 5000; +let messageCallback = null; + +const initWebSocket = (token, callback) => { + if (socket && socket.readyState === WebSocket.OPEN) { + console.log('WebSocket 宸茶繛鎺ワ紝鏃犻渶閲嶅鍒濆鍖�'); + return; + } + + if (!token) { + console.error('鏈彁渚� token锛屾棤娉曞缓绔� WebSocket 杩炴帴'); + callback('error', '鏈壘鍒� token锛屾棤娉曞缓绔� WebSocket 杩炴帴'); + return; + } + + const wsUrl = `ws://192.168.1.2:5011/ws?token=${encodeURIComponent(token)}`; + console.log('灏濊瘯杩炴帴 WebSocket:', wsUrl); + + try { + socket = new WebSocket(wsUrl); + } catch (error) { + console.error('WebSocket 鍒濆鍖栧け璐�:', error); + callback('error', '鏃犳硶鍒濆鍖� WebSocket 杩炴帴'); + return; + } + + messageCallback = callback; + + socket.onopen = () => { + console.log('WebSocket 杩炴帴鎴愬姛'); + reconnectAttempts = 0; + }; + + socket.onmessage = (event) => { + console.log('WebSocket 鏀跺埌鍘熷娑堟伅:', event.data); + if (messageCallback) { + messageCallback('message', event.data); + } + }; + + socket.onerror = (error) => { + console.error('WebSocket 閿欒:', error); + if (messageCallback) { + messageCallback('error', 'WebSocket 杩炴帴閿欒'); + } + }; + + socket.onclose = (event) => { + console.log('WebSocket 杩炴帴鍏抽棴锛屼唬鐮�:', event.code, '鍘熷洜:', event.reason); + if (reconnectAttempts < maxReconnectAttempts) { + setTimeout(() => { + console.log(`灏濊瘯閲嶈繛 (${reconnectAttempts + 1}/${maxReconnectAttempts})`); + reconnectAttempts++; + initWebSocket(token, callback); + }, reconnectInterval); + } else { + if (messageCallback) { + messageCallback('error', 'WebSocket 閲嶈繛澶辫触锛岃妫�鏌ョ綉缁滄垨鏈嶅姟鍣�'); + } + } + }; +}; + +const closeWebSocket = () => { + if (socket) { + socket.close(1000, '娴忚鍣ㄥ叧闂紝姝e父鏂紑'); + socket = null; + console.log('WebSocket 杩炴帴宸插叧闂�'); + } +}; + +window.addEventListener('beforeunload', () => { + closeWebSocket(); +}); + +export { initWebSocket, closeWebSocket }; \ No newline at end of file diff --git a/src/views/111111.vue b/src/views/111111.vue new file mode 100644 index 0000000..039340f --- /dev/null +++ b/src/views/111111.vue @@ -0,0 +1,335 @@ +<template> + <div> + <h3>鍓嶇 Word 缂栬緫鍣紙TinyMCE锛�</h3> + <div class="actions"> + <input type="file" accept=".docx" @change="importWord" ref="fileInput" style="margin-right: 10px;" /> + <button @click="exportToWord">瀵煎嚭 Word</button> + <button @click="exportToPDF">瀵煎嚭 PDF</button> + </div> + <editor v-model="content" :init="editorInit" :api-key="apiKey"></editor> + </div> +</template> +<script> +import Editor from '@tinymce/tinymce-vue'; +import { Document, Packer, Paragraph, TextRun, ImageRun, Table as DocxTable, TableRow as DocxTableRow, TableCell as DocxTableCell } from 'docx'; +import { saveAs } from 'file-saver'; +import jsPDF from 'jspdf'; +import html2canvas from 'html2canvas'; +import mammoth from 'mammoth'; + +export default { + components: { Editor }, + data() { + return { + apiKey: '3ceaxd5ckw4te35xj38vj3p5rmmeyv0x8pq2yrr92rwdiqzp', + content: '', + editorInit: { + height: 500, + menubar: true, + plugins: [ + 'advlist autolink lists link image charmap print preview anchor', + 'searchreplace visualblocks code fullscreen', + 'insertdatetime media table paste code help wordcount' + ], + toolbar: + 'undo redo | formatselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | image table | removeformat | help', + images_upload_handler: (blobInfo, success, failure) => { + const reader = new FileReader(); + reader.onload = () => success(reader.result); + reader.onerror = () => failure('鍥剧墖涓婁紶澶辫触'); + reader.readAsDataURL(blobInfo.blob()); + }, + content_style: 'body { font-family: SimSun, Arial; font-size: 14px; }', + table_default_attributes: { border: 1 }, + readonly: false, + language: 'zh-CN', + }, + }; + }, + methods: { + /** 瀵煎叆 Word 鏂囨。 */ + importWord(event) { + const file = event.target.files[0]; + if (!file) { + this.$message.error('璇烽�夋嫨涓�涓� .docx 鏂囦欢'); + return; + } + if (!file.name.endsWith('.docx')) { + this.$message.error('璇蜂笂浼� .docx 鏍煎紡鐨勬枃浠�'); + return; + } + + const reader = new FileReader(); + reader.onload = async (e) => { + try { + const arrayBuffer = e.target.result; + const result = await mammoth.convertToHtml({ arrayBuffer }); + this.content = result.value || '<p>鏃犲唴瀹�</p>'; + this.$message.success('Word 鏂囨。瀵煎叆鎴愬姛'); + this.$refs.fileInput.value = ''; + } catch (err) { + console.error('瀵煎叆 Word 澶辫触锛�', err); + this.$message.error('瀵煎叆 Word 鏂囨。澶辫触锛�' + err.message); + } + }; + reader.onerror = () => { + this.$message.error('璇诲彇鏂囦欢澶辫触'); + }; + reader.readAsArrayBuffer(file); + }, + + /** 瀵煎嚭涓� Word */ + exportToWord() { + if (!this.content || this.content.trim() === '') { + this.$message.error('缂栬緫鍣ㄥ唴瀹逛负绌猴紝鏃犳硶瀵煎嚭'); + return; + } + this.parseHtmlToDocx(this.content).then((elements) => { + const doc = new Document({ + sections: [{ properties: {}, children: elements }], + }); + + Packer.toBlob(doc).then((blob) => { + saveAs(blob, '鏂囨。.docx'); + this.$message.success('瀵煎嚭 Word 鎴愬姛'); + }).catch((err) => { + console.error('鐢熸垚 Word 澶辫触锛�', err); + this.$message.error('鐢熸垚 Word 澶辫触锛�' + err.message); + }); + }).catch((err) => { + console.error('瑙f瀽 HTML 澶辫触锛�', err); + this.$message.error('瑙f瀽 HTML 澶辫触锛�' + err.message); + }); + }, + + /** 瑙f瀽 HTML 涓� docx 鍏冪礌 */ + parseHtmlToDocx(html) { + return new Promise((resolve, reject) => { + if (!html || typeof html !== 'string') { + reject(new Error('鏃犳晥鐨� HTML 鍐呭')); + return; + } + + console.log('Input HTML:', html); // 璋冭瘯杈撳叆 HTML + + const parser = new DOMParser(); + const doc = parser.parseFromString(html, 'text/html'); + if (!doc || !doc.body) { + reject(new Error('HTML 瑙f瀽澶辫触锛氭枃妗g粨鏋勬棤鏁�')); + return; + } + + const elements = []; + const imagePromises = []; + + const processNode = (node) => { + if (node.nodeType !== Node.ELEMENT_NODE) { + return; + } + + console.log('Processing node:', node.tagName); // 璋冭瘯鑺傜偣 + + if (node.tagName === 'P') { + const childNodes = node.childNodes ? Array.from(node.childNodes) : []; + const textRuns = childNodes.map((child) => { + if (child.nodeType === Node.TEXT_NODE) { + return new TextRun({ text: child.textContent || '' }); + } else if (child.tagName === 'B') { + return new TextRun({ text: child.textContent || '', bold: true }); + } else if (child.tagName === 'I') { + return new TextRun({ text: child.textContent || '', italics: true }); + } else if (child.tagName === 'IMG') { + const promise = this.getImageBase64FromUrl(child.src).then(({ base64, width, height }) => { + return new ImageRun({ + data: base64, + transformation: { width, height }, + }); + }).catch((err) => { + console.error('鍥剧墖鍔犺浇澶辫触锛�', err, 'URL:', child.src); + return new TextRun(`[鍥剧墖: ${child.alt || '鍥惧儚'}]`); + }); + imagePromises.push(promise); + return promise; + } + return new TextRun({ text: child.textContent || '' }); + }).filter(Boolean); + if (textRuns.length) { + elements.push(new Paragraph({ children: textRuns })); + } + } else if (node.tagName === 'H1') { + elements.push(new Paragraph({ text: node.textContent || '', heading: 'Heading1' })); + } else if (node.tagName === 'UL' || node.tagName === 'OL') { + const children = node.children ? Array.from(node.children) : []; + children.forEach((li) => { + elements.push( + new Paragraph({ + text: li.textContent || '', + bullet: node.tagName === 'UL' ? { level: 0 } : { level: 0, number: true }, + }) + ); + }); + } else if (node.tagName === 'TABLE') { + const rows = node.querySelectorAll('tr') ? Array.from(node.querySelectorAll('tr')) : []; + const tableRows = rows.map((tr) => { + const cells = tr.querySelectorAll('td, th') ? Array.from(tr.querySelectorAll('td, th')) : []; + const tableCells = cells.map((cell) => { + return new DocxTableCell({ + children: [new Paragraph(cell.textContent || '')], + }); + }); + return new DocxTableRow({ children: tableCells }); + }); + if (tableRows.length) { + elements.push(new DocxTable({ rows: tableRows })); + } + } + const children = node.children ? Array.from(node.children) : []; + children.forEach(processNode); + }; + + const nodes = doc.body.childNodes ? Array.from(doc.body.childNodes) : []; + if (nodes.length === 0) { + console.warn('HTML 鏂囨。鏃犳湁鏁堣妭鐐�'); + resolve(elements); + return; + } + + nodes.forEach(processNode); + + Promise.all(imagePromises).then((imageRuns) => { + let imageIndex = 0; + elements.forEach((element, index) => { + if (!(element instanceof Paragraph)) { + console.log('Skipping non-Paragraph element at index', index, 'type:', element.constructor.name); + return; // 璺宠繃闈� Paragraph 鍏冪礌 + } + if (!Array.isArray(element.children)) { + console.warn('Element at index', index, 'has invalid children:', element.children); + element.children = []; // 鍒濆鍖栦负绌烘暟缁� + return; + } + console.log('Processing element at index', index, 'children:', element.children); + element.children = element.children.map((child, childIndex) => { + if (child instanceof Promise) { + const imageRun = imageRuns[imageIndex++] || new TextRun('[鍥剧墖鍔犺浇澶辫触]'); + console.log('Replacing Promise at child index', childIndex, 'with:', imageRun); + return imageRun; + } + return child; + }); + }); + resolve(elements); + }).catch((err) => { + console.error('鍥剧墖澶勭悊澶辫触锛�', err); + reject(new Error('鍥剧墖澶勭悊澶辫触锛�' + err.message)); + }); + }); + }, + + /** 鑾峰彇鍥剧墖鐨� Base64 鏁版嵁鍜屽昂瀵� */ + getImageBase64FromUrl(url) { + return new Promise((resolve, reject) => { + if (!url) { + reject(new Error('鍥剧墖 URL 涓虹┖')); + return; + } + + console.log('Fetching image:', url); + + if (url.startsWith('data:image/')) { + const base64 = url.split(',')[1]; + const img = new Image(); + img.onload = () => { + const maxWidth = 200; + const maxHeight = 200; + let { width, height } = img; + if (width > maxWidth || height > maxHeight) { + const ratio = Math.min(maxWidth / width, maxHeight / height); + width = Math.round(width * ratio); + height = Math.round(height * ratio); + } + resolve({ base64, width, height }); + }; + img.onerror = () => reject(new Error('Base64 鍥剧墖鍔犺浇澶辫触')); + img.src = url; + return; + } + + fetch(url, { mode: 'cors' }) + .then((response) => { + if (!response.ok) throw new Error('缃戠粶鍥剧墖鍔犺浇澶辫触'); + return response.blob(); + }) + .then((blob) => { + const reader = new FileReader(); + reader.onloadend = () => { + const base64 = reader.result.split(',')[1]; + const img = new Image(); + img.onload = () => { + const maxWidth = 200; + const maxHeight = 200; + let { width, height } = img; + if (width > maxWidth || height > maxHeight) { + const ratio = Math.min(maxWidth / width, maxHeight / height); + width = Math.round(width * ratio); + height = Math.round(height * ratio); + } + resolve({ base64, width, height }); + }; + img.onerror = () => reject(new Error('鍥剧墖璇诲彇澶辫触')); + img.src = reader.result; + }; + reader.onerror = () => reject(new Error('鍥剧墖璇诲彇澶辫触')); + reader.readAsDataURL(blob); + }) + .catch((err) => reject(err)); + }); + }, + + /** 瀵煎嚭涓� PDF */ + exportToPDF() { + if (!this.content || this.content.trim() === '') { + this.$message.error('缂栬緫鍣ㄥ唴瀹逛负绌猴紝鏃犳硶瀵煎嚭'); + return; + } + const contentElement = document.createElement('div'); + contentElement.innerHTML = this.content; + contentElement.style.padding = '10px'; + document.body.appendChild(contentElement); + + html2canvas(contentElement, { scale: 2 }) + .then((canvas) => { + const doc = new jsPDF(); + const imgData = canvas.toDataURL('image/png'); + doc.addImage(imgData, 'PNG', 10, 10, 190, 0); + doc.save('鏂囨。.pdf'); + this.$message.success('瀵煎嚭 PDF 鎴愬姛'); + document.body.removeChild(contentElement); + }) + .catch((err) => { + console.error('鐢熸垚 PDF 澶辫触锛�', err); + this.$message.error('鐢熸垚 PDF 澶辫触锛�' + err.message); + document.body.removeChild(contentElement); + }); + }, + }, +}; +</script> +<style> +.actions { + margin-top: 10px; + margin-bottom: 10px; +} +.actions button { + padding: 8px 16px; + margin-right: 10px; + background-color: #409eff; + color: white; + border: none; + border-radius: 4px; + cursor: pointer; +} +.actions button:hover { + background-color: #66b1ff; +} +</style> \ No newline at end of file diff --git a/src/views/ceshi.vue b/src/views/ceshi.vue deleted file mode 100644 index 4a8f64d..0000000 --- a/src/views/ceshi.vue +++ /dev/null @@ -1,198 +0,0 @@ -<template> - <div> - <h3>鍓嶇 Word 缂栬緫鍣紙TinyMCE锛�</h3> - <editor v-model="content" :init="editorInit" :api-key="apiKey"></editor> - <div class="actions"> - <button @click="exportToWord">瀵煎嚭 Word</button> - <button @click="exportToPDF">瀵煎嚭 PDF</button> - </div> - </div> -</template> - -<script> -import Editor from '@tinymce/tinymce-vue'; -import { Document, Packer, Paragraph, TextRun, ImageRun, Table as DocxTable, TableRow as DocxTableRow, TableCell as DocxTableCell } from 'docx'; -import { saveAs } from 'file-saver'; -import jsPDF from 'jspdf'; -import html2canvas from 'html2canvas'; - -export default { - components: { Editor }, - data() { - return { - apiKey: '3ceaxd5ckw4te35xj38vj3p5rmmeyv0x8pq2yrr92rwdiqzp', // 鎮ㄧ殑 TinyMCE API 瀵嗛挜 - content: ` - - `, - editorInit: { - height: 500, - menubar: true, - plugins: [ - 'advlist autolink lists link image charmap print preview anchor', - 'searchreplace visualblocks code fullscreen', - 'insertdatetime media table paste code help wordcount' - ], - toolbar: - 'undo redo | formatselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | image table | removeformat | help', - images_upload_handler: (blobInfo, success, failure) => { - const reader = new FileReader(); - reader.onload = () => success(reader.result); - reader.onerror = () => failure('鍥剧墖涓婁紶澶辫触'); - reader.readAsDataURL(blobInfo.blob()); - }, - content_style: 'body { font-family: SimSun, Arial; font-size: 14px; }', - table_default_attributes: { border: 1 }, - readonly: false, - language: 'zh_CN', // 灏濊瘯 zh-CN - }, - }; - }, - methods: { - exportToWord() { - this.parseHtmlToDocx(this.content).then((elements) => { - const doc = new Document({ - sections: [{ properties: {}, children: elements }], - }); - - Packer.toBlob(doc).then((blob) => { - saveAs(blob, '鏂囨。.docx'); - }).catch((err) => { - console.error('鐢熸垚 Word 澶辫触锛�', err); - }); - }).catch((err) => { - console.error('瑙f瀽 HTML 澶辫触锛�', err); - }); - }, - parseHtmlToDocx(html) { - return new Promise((resolve, reject) => { - const parser = new DOMParser(); - const doc = parser.parseFromString(html, 'text/html'); - const elements = []; - - const processNode = (node, callback) => { - if (node.nodeType === Node.ELEMENT_NODE) { - if (node.tagName === 'P') { - const textRuns = Array.from(node.childNodes).map((child) => { - if (child.nodeType === Node.TEXT_NODE) { - return new TextRun({ text: child.textContent || '' }); - } else if (child.tagName === 'B') { - return new TextRun({ text: child.textContent || '', bold: true }); - } else if (child.tagName === 'I') { - return new TextRun({ text: child.textContent || '', italics: true }); - } else if (child.tagName === 'IMG') { - this.getImageBase64FromUrl(child.src).then((base64) => { - callback(null, new ImageRun({ - data: base64, - transformation: { width: 200, height: 200 }, - })); - }).catch((err) => { - console.error('鍥剧墖鍔犺浇澶辫触锛�', err); - callback(null, new TextRun(`[鍥剧墖: ${child.alt || '鍥惧儚'}]`)); - }); - return null; - } - return new TextRun({ text: child.textContent || '' }); - }).filter(Boolean); - if (textRuns.length) { - elements.push(new Paragraph({ children: textRuns })); - } - } else if (node.tagName === 'H1') { - elements.push(new Paragraph({ text: node.textContent || '', heading: 'Heading1' })); - } else if (node.tagName === 'UL' || node.tagName === 'OL') { - Array.from(node.children).forEach((li) => { - elements.push( - new Paragraph({ - text: li.textContent || '', - bullet: node.tagName === 'UL' ? { level: 0 } : { level: 0, number: true }, - }) - ); - }); - } else if (node.tagName === 'TABLE') { - const rows = Array.from(node.querySelectorAll('tr')).map((tr) => { - const cells = Array.from(tr.querySelectorAll('td, th')).map((cell) => { - return new DocxTableCell({ - children: [new Paragraph(cell.textContent || '')], - }); - }); - return new DocxTableRow({ children: cells }); - }); - elements.push(new DocxTable({ rows })); - } - Array.from(node.children).forEach((child) => processNode(child, callback)); - } - callback(null); - }; - - const nodes = Array.from(doc.body.childNodes); - let completed = 0; - const checkCompletion = () => { - completed++; - if (completed === nodes.length) { - resolve(elements); - } - }; - - if (nodes.length === 0) { - resolve(elements); - } else { - nodes.forEach((node) => { - processNode(node, checkCompletion); - }); - } - }); - }, - getImageBase64FromUrl(url) { - return new Promise((resolve, reject) => { - fetch(url, { mode: 'cors' }) - .then((response) => { - if (!response.ok) throw new Error('缃戠粶鍥剧墖鍔犺浇澶辫触'); - return response.blob(); - }) - .then((blob) => { - const reader = new FileReader(); - reader.onloadend = () => resolve(reader.result.split(',')[1]); - reader.onerror = () => reject(new Error('鍥剧墖璇诲彇澶辫触')); - reader.readAsDataURL(blob); - }) - .catch((err) => reject(err)); - }); - }, - exportToPDF() { - const contentElement = document.createElement('div'); - contentElement.innerHTML = this.content; - contentElement.style.padding = '10px'; - document.body.appendChild(contentElement); - - html2canvas(contentElement, { scale: 2 }) - .then((canvas) => { - const doc = new jsPDF(); - const imgData = canvas.toDataURL('image/png'); - doc.addImage(imgData, 'PNG', 10, 10, 190, 0); - doc.save('鏂囨。.pdf'); - }) - .catch((err) => { - console.error('鐢熸垚 PDF 澶辫触锛�', err); - document.body.removeChild(contentElement); - }); - }, - }, -}; -</script> - -<style> -.actions { - margin-top: 10px; -} -.actions button { - padding: 8px 16px; - margin-right: 10px; - background-color: #409eff; - color: white; - border: none; - border-radius: 4px; - cursor: pointer; -} -.actions button:hover { - background-color: #66b1ff; -} -</style> \ No newline at end of file diff --git a/src/views/index.vue b/src/views/index.vue index 1ea2590..268ec38 100644 --- a/src/views/index.vue +++ b/src/views/index.vue @@ -1,28 +1,5 @@ <template> <div class="centre"> - <!-- 浠婃棩閫氱煡 --> - <div style="display: flex; justify-content: center; align-items: center;"> - <h4>浠婃棩閫氱煡</h4> - </div> - <div class="notice-area"> - <el-carousel :interval="2000" direction="vertical" :autoplay="true" :loop="true" height="120px" - v-if="groupedNoticeList.length > 0" class="carousel"> - <el-carousel-item v-for="(group, index) in groupedNoticeList" :key="index"> - <div class="notice-group"> - <div class="notice-item" v-for="notice in group" :key="notice.noticeId" - @click="goToNotice(notice.noticeId)"> - <el-tag size="small" :type="notice.noticeType === '1' ? 'info' : 'warning'"> - {{ notice.noticeType === '1' ? '閫氱煡' : '鍏憡' }} - </el-tag> - <span class="notice-title">{{ notice.noticeTitle || '鏃犳爣棰�' }}</span> - <span class="notice-time">{{ parseTime(notice.createTime, '{y}-{m}-{d}') || '鏃犳椂闂�' }}</span> - </div> - </div> - </el-carousel-item> - </el-carousel> - <div v-else class="no-notice">鏆傛棤閫氱煡</div> - </div> - <!-- 浠婃棩缁熻 --> <div style="display: flex; justify-content: center; align-items: center;"> <h4>浠婃棩缁熻</h4> @@ -79,6 +56,7 @@ <script> import { getCustomer, getOrder, getReportToday, getTobeToday, getPieChart, getChart } from "@/api/home"; import { noticeToday } from "@/api/system/notice"; +import { initWebSocket } from "@/utils/websocket"; const echarts = require('echarts/lib/echarts'); require('echarts/lib/component/title'); require('echarts/lib/component/tooltip'); @@ -101,27 +79,18 @@ teamYYNum: [], PieChart: [], PieChart2: [], - noticeList: [], - groupedNoticeList: [], // 鍒嗙粍鍚庣殑閫氱煡鍒楄〃 loading: false }; }, created() { this.getList(); + this.initWebSocket(); }, watch: { $route(to, from) { window.location.reload(); - }, - noticeList: { - handler(newList) { - // 灏嗛�氱煡鎸夋瘡缁勪笁鏉″垎缁� - this.groupedNoticeList = this.chunkArray(newList, 3); - console.log('groupedNoticeList:', this.groupedNoticeList); // 璋冭瘯 - }, - deep: true } }, @@ -132,49 +101,91 @@ query: { noticeId } }); }, + + // 鍒濆鍖� WebSocket 杩炴帴 + initWebSocket() { + const token = this.$store.state.user.token || ''; + initWebSocket(token, (type, data) => { + if (type === 'error') { + this.$notify.error({ + title: '閿欒', + message: data, + duration: 5000, + position: 'top-right' + }); + return; + } + + try { + const message = JSON.parse(data); + console.log('WebSocket 瑙f瀽鍚庢秷鎭�:', message); + if (message.noticeId && message.noticeTitle) { + const noticeTypeLabel = message.noticeType === '1' ? '閫氱煡' : '鍏憡'; + this.$notify({ + title: `鏂�${noticeTypeLabel}`, + message: message.noticeTitle || '鏃犳爣棰�', + type: 'success', + duration: 5000, // 鎮仠 5 绉� + position: 'top-right', + offset: 50, + onClick: () => { + this.goToNotice(message.noticeId); + } + }); + } else { + console.log('鏈煡娑堟伅绫诲瀷:', message); + } + } catch (error) { + console.error('娑堟伅瑙f瀽澶辫触:', error, '鍘熷鏁版嵁:', data); + this.$notify.info({ + title: '娑堟伅', + message: `鏈嶅姟鍣ㄥ洖搴斿瓧绗︿覆: ${data}`, + duration: 5000, + position: 'top-right', + offset: 50 + }); + } + }); + }, + getList() { this.loading = true; - // 鏌ヨ鎵�鏈夊叕鍛� + // 鏌ヨ鎵�鏈夊叕鍛婏紙浠呯敤浜庡垵濮嬪寲鏁版嵁锛屽彲鏍规嵁闇�瑕佷繚鐣欐垨绉婚櫎锛� noticeToday().then(response => { console.log('Notice API response:', response); - this.noticeList = response.rows || response.data || []; - console.log('noticeList:', this.noticeList); this.loading = false; - this.$nextTick(() => { - console.log('Carousel updated'); - }); }).catch(error => { console.error('Notice API error:', error); - this.$message.error("鑾峰彇閫氱煡澶辫触锛�" + error.message); + this.$notify.error({ + title: '閿欒', + message: `鑾峰彇閫氱煡澶辫触锛�${error.message}`, + duration: 5000, + position: 'top-right' + }); this.loading = false; }); - // 鏌ヨ浠婃棩鐧昏 getCustomer().then(response => { this.Customer = response.data || response; this.loading = false; }); - // 鏌ヨ浠婃棩宸叉 getOrder().then(response => { this.Order = response.data || response; this.loading = false; }); - // 鏌ヨ浠婃棩鎶ュ憡 getReportToday().then(response => { this.ReportToday = response.data || response; this.loading = false; }); - // 鏌ヨ浠婃棩寰呮 getTobeToday().then(response => { this.TobeToday = response.data || response; this.loading = false; }); - // 鎶樼嚎鍥� getChart().then(response => { response.data.forEach(item => { this.LineChart.push(item.date); @@ -211,7 +222,6 @@ this.loading = false; }); - // 楗肩姸鍥� getPieChart().then(response => { if (response.data) { if (response.data.tjdj == 0 || !response.data.tjdj?.length) { @@ -281,23 +291,6 @@ }); }, - // 鏁扮粍鍒嗙粍鏂规硶 - chunkArray(array, size) { - if (!array || array.length === 0) return []; - const result = []; - for (let i = 0; i < array.length; i += size) { - result.push(array.slice(i, i + size)); - } - // 纭繚寰幆婊氬姩骞虫粦锛岃嫢涓嶈冻 size 鏉★紝琛ラ綈 - if (array.length % size !== 0 && array.length > size) { - const lastGroup = result[result.length - 1]; - while (lastGroup.length < size) { - lastGroup.push(array[lastGroup.length % array.length]); - } - } - return result; - }, - parseTime(time, cFormat) { if (!time) return ''; try { @@ -327,62 +320,6 @@ margin: 15px; background-color: #f3f3f3; padding: 10px; -} - -.notice-area { - width: 100%; - min-height: 120px; - /* 璋冩暣涓轰笁鏉¢�氱煡楂樺害 */ - background-color: #fff; - margin: 10px 0; - padding: 0 20px; -} - -.carousel { - width: 100% !important; -} - -.notice-group { - display: flex; - flex-direction: column; - height: 120px; - /* 纭繚鍖呭惈涓夋潯閫氱煡 */ -} - -.notice-item { - display: flex; - align-items: center; - width: 100%; - height: 40px; - line-height: 40px; - font-size: 14px; - cursor: pointer; -} - -.notice-title { - margin-left: 10px; - font-size: 14px; - color: #333; - flex-grow: 1; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.notice-time { - font-size: 12px; - color: #999; - margin-left: 20px; -} - -.no-notice { - width: 100%; - height: 120px; - /* 涓庤疆鎾珮搴︿竴鑷� */ - line-height: 120px; - text-align: center; - color: #999; - font-size: 14px; } .top { @@ -448,4 +385,27 @@ background-color: #fff; margin-right: 20px; } + +/* 鑷畾涔� Element UI 閫氱煡鏍峰紡 */ +.el-notification { + min-width: 300px; + background-color: #f0f9eb; + border-color: #e1f3d8; + color: #67c23a; + font-size: 16px; + padding: 15px 20px; +} + +.el-notification__title { + font-weight: bold; +} + +.el-notification__content { + font-size: 14px; + color: #333; +} + +.el-notification__closeBtn { + color: #999; +} </style> \ No newline at end of file diff --git a/src/views/system/package/index.vue b/src/views/system/package/index.vue index af9f3af..6dc6de8 100644 --- a/src/views/system/package/index.vue +++ b/src/views/system/package/index.vue @@ -39,16 +39,11 @@ <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> </el-row> - <!-- - element-loading-background="rgba(0, 0, 0, 0.1)" - element-loading-spinner="el-icon-loading" - element-loading-text="姝e湪鍔犺浇涓�..." --> <template> <el-table v-loading="loading" style="width: 100%" :data="packageList" @selection-change="handleSelectionChange" border> <el-table-column fixed type="selection" width="40" align="center" :show-overflow-tooltip="true" /> <el-table-column label="搴忓彿" align="center" width="50" prop="newID" fixed /> - <!-- <el-table-column label="缂栧彿" align="center" prop="pacId" /> --> <el-table-column label="浣撴绫诲埆" width="100px" align="center" prop="categoryNames" fixed> <template slot-scope="scope"> <dict-tag :options="dict.type.dict_tjtype" :value="scope.row.tjCategory" /> @@ -57,55 +52,21 @@ <el-table-column label="濂楅鍚嶇О" align="center" prop="pacName" width="150px" fixed /> <el-table-column label="鍘熶环" width="80px" align="center" prop="price" fixed></el-table-column> <el-table-column label="鎶樻墸" width="80px" align="center" prop="limits" fixed></el-table-column> - <el-table-column label="鐜颁环" width="80px" align="center" prop="newPrice" fixed> - </el-table-column> - <el-table-column label="鍗曢」鍒楄〃" align="center" prop="allProName" width="1200px"> - </el-table-column> - <!-- <el-table-column - label="椤圭洰鏄庣粏" - align="center" - prop="allSonName" - :show-overflow-tooltip="true" - > - </el-table-column>--> + <el-table-column label="鐜颁环" width="80px" align="center" prop="newPrice" fixed></el-table-column> + <el-table-column label="鍗曢」鍒楄〃" align="center" prop="allProName" width="1200px"></el-table-column> <el-table-column label="濂楅鎻忚堪" align="center" :show-overflow-tooltip="true" width="120px"> <template slot-scope="scope"> <div class="showInline">{{ scope.row.pacRemark }}</div> </template> </el-table-column> - <!-- <el-table-column - label="鍥剧墖" - align="center" - prop="pacPhone" - width="100" - :show-overflow-tooltip="true" - > - <template slot-scope="scope"> - <image-preview :src="scope.row.pacPhone" :width="50" :height="50" /> - </template> - </el-table-column> --> - <el-table-column label="鍏抽敭瀛�" width="110px" align="center" prop="keyNames"></el-table-column> <el-table-column label="鏄惁涓婃灦" width="94px" align="center" prop="isOnSale"> <template slot-scope="scope"> <dict-tag :options="dict.type.sys_yes_no" :value="scope.row.isOnSale" /> </template> </el-table-column> - <!-- <el-table-column - label="璇︾粏浠嬬粛" - :show-overflow-tooltip="true" - width="100px" - align="center" - prop="detail" - ></el-table-column> --> <el-table-column label="鎺掑簭" width="50px" align="center" prop="sort"></el-table-column> <el-table-column label="灏忕▼搴忎环鏍�" width="90px" align="center" prop="retailPrice"></el-table-column> - <!-- <el-table-column - label="鍘熶环" - width="90px" - align="center" - prop="counterPrice" - ></el-table-column> --> <el-table-column label="宸插敭鏁伴噺" width="90px" align="center" prop="saleNum"></el-table-column> <el-table-column label="鐘舵��" align="center" prop="pacStatus" fixed="right" width="100px"> <template slot-scope="scope"> @@ -119,8 +80,6 @@ v-hasPermi="['system:package:edit']" title="淇敼"></el-button> <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['system:package:remove']" title="鍒犻櫎"></el-button> - <!-- <el-button size="mini" type="text" icon="el-icon-circle-check" @click="handleSeach(scope.row)" - v-hasPermi="['system:package:Seach']" title="濂楅璇︽儏"></el-button> --> </template> </el-table-column> </el-table> @@ -136,8 +95,6 @@ <!-- 淇敼浣撴濂楅瀵硅瘽妗� --> <el-dialog :title="title" :visible.sync="open" width="1400px" append-to-body :close-on-click-modal="false"> <el-form ref="form" :model="form" :rules="rules" label-width="100px" :inline="true"> - <!-- <div class="dialo"> - <div class="dialo1"> --> <el-form-item label="濂楅鍚嶇О" prop="pacName"> <span slot="label" style="display: inline-block; border-bottom: 2px solid blue" @click="handlePackage"> 濂楅鍚嶇О @@ -145,51 +102,23 @@ <el-input v-model="form.pacName" placeholder="璇疯緭鍏ュ椁愬悕绉�" style="width: 150px" /> </el-form-item> <el-form-item label="濂楅鐘舵��" prop="pacStatus"> - <!-- <el-radio-group v-model="form.pacStatus"> - <el-radio :label="0">鍚敤</el-radio> - <el-radio :label="1">鍋滅敤</el-radio> - </el-radio-group> --> <el-select v-model="form.pacStatus" placeholder="璇烽�夋嫨鐘舵��" style="width: 150px" filterable clearable> <el-option v-for="dict in dict.type.sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value"></el-option> </el-select> </el-form-item> - - <!-- <el-form-item label="濂楅绫荤洰" prop="categoryId"> - <el-select - v-model="form.categoryId" - placeholder="璇烽�夋嫨濂楅绫荤洰" - style="width: 150px" - @change="shangpin" - filterable - clearablez - > - <el-option - v-for="item in categoryList" - :key="item.id" - :label="item.name" - :value="item.id" - ></el-option> - </el-select> - </el-form-item> --> <el-form-item label="浣撴绫诲埆" prop="tjCategory"> <el-select v-model="form.tjCategory" placeholder="璇烽�夋嫨浣撴绫诲埆" style="width: 150px" filterable clearable> <el-option v-for="dict in dict.type.dict_tjtype" :key="dict.value" :label="dict.label" :value="dict.value"></el-option> </el-select> </el-form-item> - <el-form-item label="鏄惁涓婃灦" prop="isOnSale"> - <!-- <el-radio-group v-model="form.pacStatus"> - <el-radio :label="0">鍚敤</el-radio> - <el-radio :label="1">鍋滅敤</el-radio> - </el-radio-group> --> <el-select v-model="form.isOnSale" placeholder="璇烽�夋嫨鏄惁涓婃灦" style="width: 140px" filterable clearable> <el-option v-for="dict in dict.type.sys_yes_no" :key="dict.value" :label="dict.label" :value="dict.value"></el-option> </el-select> </el-form-item> - <el-form-item label="鎺掑簭" prop="sort"> <el-input v-model="form.sort" placeholder="璇疯緭鍏ユ帓搴�" style="width: 150px" /> </el-form-item> @@ -197,13 +126,12 @@ <el-input v-model="form.retailPrice" placeholder="璇疯緭鍏ュ皬绋嬪簭浠锋牸" style="width: 150px" /> </el-form-item> <el-form-item label="鍘熶环" prop="pics"> - <el-input v-model="pics" placeholder="璇疯緭鍏ュ師浠�" style="width: 150px" /> + <el-input v-model="pics" placeholder="璇疯緭鍏ュ師浠�" style="width: 150px" type="number" /> </el-form-item> <el-form-item label="鎶樻墸"> <el-input-number style="width: 150px" v-model="youhui" :precision="2" :step="0.1" :max="10" :min="0.1" - @change="debounceNumberChange" :debounce="3000"></el-input-number> + @change="debounceNumberChange" :debounce="3000"></el-input-number> </el-form-item> - <el-form-item label="鐜颁环" prop="xianprice"> <el-input v-model="form.xianprice" placeholder="鐜颁环" clearable style="width: 140px" @input="changeXianjia" type="number" :debounce="3000" min="0"/> @@ -214,7 +142,6 @@ <el-option v-for="item in keywordList" :key="item.id" :label="item.keyword" :value="item.id"></el-option> </el-select> </el-form-item> - <div v-if="!isCollapsed" style="display: flex"> <div> <el-form-item label="濂楅鎻忚堪" prop="pacRemark"> @@ -222,56 +149,19 @@ rows="2"></el-input> </el-form-item> <el-form-item label="璇︾粏浠嬬粛" prop="detail"> - <!-- <el-input - v-model="form.detail" - placeholder="璇疯緭鍏ヨ缁嗕粙缁�" - style="width: 200px" - /> --> <editor v-model="form.detail" :min-height="192" style="width: 670px" /> </el-form-item> </div> - <!-- </div> --> <div class="dialo2"> <el-form-item label="鍥剧墖"> <image-upload v-model="form.pacPhone" /> </el-form-item> </div> - <!-- </div> --> </div> </el-form> <el-button type="primary" plain size="mini" @click="toggleCollapse">{{ isCollapsed ? "灞曞紑" : "鏀惰捣" }}</el-button> - <!-- <el-button type="primary" plain size="mini" icon="el-icon-plus" @click="addmembers()">鏂板鍗曢」</el-button> - <el-table v-loading="loading" :data="form.tjProjectList" @selection-change="handleSelectionChange" border - max-height="275" style="margin: 10px 0"> - <el-table-column label="搴忓彿" align="center" type="index" /> - <el-table-column label="椤圭洰鍚嶇О" align="center" prop="proName" width="180px"> - <template slot-scope="scope"> - <el-select filterable v-model="scope.row.proName" placeholder="璇烽�夋嫨椤圭洰鍚嶇О" @change="getSelectValue"> - <el-option v-for="(item, index) in allList" :key="index" :label="item.proName" :value="item.proName"> - </el-option> - </el-select> - </template> - </el-table-column> - <el-table-column label="椤圭洰鏄庣粏" align="center" prop="allSonProName" width="400px" :show-overflow-tooltip="true"> - </el-table-column> - <el-table-column label="鍘熶环(鍏�)" align="center" prop="proPrice" width="80px" /> - <el-table-column label="鐜颁环(鍏�)" align="center" prop="priceNow" width="80px"> - <template slot-scope="scope"> - <el-input v-model="scope.row.priceNow" autocomplete="off" placeholder="璇疯緭鍏ュ唴瀹�"></el-input> - </template> - </el-table-column> - <el-table-column label="鎿嶄綔" fixed="right" align="center" class-name="small-padding fixed-width"> - <template slot-scope="scope"> - <el-button size="mini" type="text" icon="el-icon-circle-plus-outline" @click="addmembers(scope.row)" - v-hasPermi="['system:package:edit']" title="鏂板琛�"></el-button> - <el-button size="mini" type="text" icon="el-icon-delete" @click.native.prevent="Delete(scope.$index)" - v-hasPermi="['hosp:consumables:remove']" title="鍒犻櫎"></el-button> - </template> - </el-table-column> - </el-table> --> - <el-row style="display: flex; width: 1300px"> <el-col> <div style="text-align: center; margin-bottom: 10px; margin-top: 10px"> @@ -287,29 +177,6 @@ :limit.sync="queryParams1.pageSize" @pagination="getDataList" /> </div> </el-col> - <!-- <el-col :span="6"> - <div - style="text-align: center; margin-bottom: 10px; margin-top: 10px" - > - 鏄庣粏椤圭洰鍒楄〃 - </div> - <div class="tab3"> - <el-tree - class="filter-tree" - v-loading="loading" - :data="TreedataList" - node-key="proId" - :props="defaultProps" - :filter-node-method="filterNode" - show-checkbox - @check-change="handleCurrentChecked1" - :default-checked-keys="checkedListkey" - ref="trees" - :render-content="renderContent" - > - </el-tree> - </div> - </el-col> --> <el-col> <div class="grid-content bg-purple"> <div style=" @@ -324,12 +191,10 @@ :span-method="objectSpanMethod"> <el-table-column prop="proName" label="妫�鏌ラ」鐩�"> </el-table-column> - <el-table-column prop="priceOrd" label="鍘熶环" align="center" width="80px"> </el-table-column> <el-table-column label="鎶樻墸" width="100px"> <template slot-scope="scope"> - <!-- 鍙緭鍏ョ函鏁板瓧鎶樻墸 --> <el-input v-model.number="scope.row.limits" @input="calculateDiscount(scope.row)" placeholder="杈撳叆鎶樻墸" size="small" type="number" min="0" step="0.1" max="10"> </el-input> @@ -343,54 +208,16 @@ </el-button> </template> </el-table-column> - <!-- <el-table-column prop="proName" label="鏄庣粏椤圭洰" width="260px"> - </el-table-column> --> - - <!-- <el-table-column - label="鎿嶄綔" - align="center" - fixed="right" - class-name="small-padding fixed-width" - width="50px" - > - <template slot-scope="scope"> - <el-button - size="mini" - type="text" - icon="el-icon-delete" - @click="handleDeletes(scope.row)" - title="鍒犻櫎" - ></el-button> - </template> - </el-table-column>--> </el-table> <h4 style="font-weight: 600;padding-left:20px">涓�鍏遍�変腑{{DataList.length}}椤癸紝鍚堣锛歿{ form.xianprice }}鍏�</h4> </div> </el-col> </el-row> - <div slot="footer" class="dialog-footer"> <el-button type="primary" @click="submitForm">纭� 瀹�</el-button> <el-button @click="cancel">鍙� 娑�</el-button> </div> </el-dialog> - - <!-- 濂楅璇︽儏 --> - <!-- <el-dialog :title="title" :visible.sync="Seachopen" width="500px" append-to-body> - <template> - <el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange">鍏ㄩ��</el-checkbox> - <div style="margin: 15px 0px; width: 60px"></div> - <el-checkbox-group v-model="newproName" @change="handleCheckedCitiesChange"> - <el-checkbox style="margin: 15px 0px; width: 180px" v-for="item in allList" :label="item.proName" - :key="item.proId">{{ item.proName }}</el-checkbox> - </el-checkbox-group> - - <div slot="footer" class="dialog-footer"> - <el-button type="primary" @click="submitcheckbox">纭� 瀹�</el-button> - <el-button @click="cancel">鍙� 娑�</el-button> - </div> - </template> - </el-dialog> --> <Packages ref="aaa" @add="handleChanges" /> </div> </template> @@ -483,13 +310,16 @@ xianprice: null, counterPrice: null, limits: 10, + keywords: [], }, forms: {}, youhui: 10, - initializing: true, // 鍒濆鍖栨爣蹇� + initializing: true, debounceTimer: null, rules: { - + pacName: [{ required: true, message: "璇疯緭鍏ュ椁愬悕绉�", trigger: "blur" }], + pics: [{ required: true, message: "璇疯緭鍏ュ師浠�", trigger: "blur" }], + xianprice: [{ required: true, message: "璇疯緭鍏ョ幇浠�", trigger: "blur" }], }, }; }, @@ -498,7 +328,6 @@ this.getKeyword(); this.getCategory(); }, - methods: { debounceNumberChange(currentValue, oldValue) { clearTimeout(this.debounceTimer); @@ -506,16 +335,18 @@ this.numberChange(currentValue, oldValue); }, 300); }, - + numberChange(currentValue, oldValue) { + // 瀹炵幇鎶樻墸鍙樺寲鐨勯�昏緫锛堝鏋滈渶瑕侊級 + }, updateProPrice(row) { - const proPrice = new Big(row.priceOrd); - const limits = new Big(row.limits); + const proPrice = new Big(row.priceOrd || 0); + const limits = new Big(row.limits || 10); const result = proPrice.times(limits.div(10)); row.priceNow = result.toNumber(); this.form.xianprice = this.DataList.reduce((sum, item) => { - return sum.plus(new Big(item.priceNow || "0")); + return sum.plus(new Big(item.priceNow || 0)); }, new Big(0)).toNumber(); - this.youhui = (Math.floor((this.form.xianprice / this.pics) * 100) / 100) * 10; + this.youhui = this.pics ? (Math.floor((this.form.xianprice / this.pics) * 100) / 100) * 10 : 10; }, calculateDiscount(row) { if (row.limits > 10) { @@ -530,37 +361,79 @@ }, filterNode(value, data) { if (!value) return true; - return data.proName.indexOf(value) !== -1 || data.proEngName.indexOf(value) !== -1; + return data.proName.indexOf(value) !== -1 || (data.proEngName && data.proEngName.indexOf(value) !== -1); }, getList() { this.loading = true; getPacTjProjectList().then((response) => { - this.allList = response.data; + this.allList = response.data || []; this.loading = false; }); getPacList(this.queryParams).then((response) => { response.rows.forEach((item, index) => { item.newID = (this.queryParams.pageNum - 1) * this.queryParams.pageSize + index + 1; }); - this.total = response.total; - this.packageList = response.rows; + this.total = response.total || 0; + this.packageList = response.rows || []; this.loading = false; + }).catch(() => { + this.loading = false; + this.$message.error("鑾峰彇濂楅鍒楄〃澶辫触"); }); }, getKeyword() { this.loading = true; listKeyword(this.queryParams).then((response) => { - this.keywordList = response.rows; + this.keywordList = response.rows || []; + this.loading = false; + }).catch(() => { + this.loading = false; + this.$message.error("鑾峰彇鍏抽敭瀛楀垪琛ㄥけ璐�"); }); }, sel(val) { - let id = val; - this.keys = id.join(","); + const maleId = '4'; // 鈥滅敺鈥濈殑 ID + const femaleId = '5'; // 鈥滃コ鈥濈殑 ID + let selectedIds = [...val]; // 澶嶅埗褰撳墠閫変腑鐨� ID 鏁扮粍 + + // 瀹炵幇鈥滅敺鈥濆拰鈥滃コ鈥濅簰鏂ラ�昏緫 + if (selectedIds.includes(maleId) && selectedIds.includes(femaleId)) { + selectedIds = selectedIds.slice(-1); // 淇濈暀鏈�鍚庨�変腑鐨勪竴涓� + this.$message.warning('鈥滅敺鈥濆拰鈥滃コ鈥濆叧閿瓧浜掓枼锛屽彧鑳介�夋嫨涓�涓紒'); + } + + // 鏇存柊 form.keywords 鍜� keys + this.form.keywords = selectedIds; + this.keys = selectedIds.join(','); + + // 璋冪敤 getDataList锛屼紶閫掓墍鏈夐�変腑鐨勫叧閿瓧 ID锛堥�楀彿鍒嗛殧锛� + this.getDataList({ xb: this.keys }); }, getCategory() { this.loading = true; listCategory(this.queryParams).then((response) => { - this.categoryList = response.rows; + this.categoryList = response.rows || []; + this.loading = false; + }).catch(() => { + this.loading = false; + this.$message.error('鑾峰彇濂楅绫荤洰澶辫触'); + }); + }, + getDataList(params = {}) { + this.loading = true; + const query = { ...this.queryParams1, ...params }; + search(query).then((response) => { + this.Treedata = response.data.list || []; + this.total1 = response.data.total || 0; + this.pics = this.DataList.reduce((total, item) => total + (item.priceOrd || 0), 0); + this.$nextTick(() => { + this.$refs.tree.setCheckedKeys(this.checkedNodes); + this.initializing = false; + }); + this.loading = false; + }).catch(() => { + this.loading = false; + this.$message.error('鑾峰彇椤圭洰鍒楄〃澶辫触'); }); }, shangpin(vals) {}, @@ -586,8 +459,9 @@ xianprice: null, counterPrice: null, limits: 10, + keywords: [], }; - this.initializing = true; + this.initializing = true; this.resetForm("form"); }, handleQuery() { @@ -629,7 +503,7 @@ this.checkedListkey = []; this.checkedNodes = []; this.getDataList(); - this.youhui = 10 + this.youhui = 10; }, handleStatusChange(row) { let data = { @@ -637,10 +511,11 @@ pacStatus: row.pacStatus, }; let text = row.pacStatus === "0" ? "鍚敤" : "鍋滅敤"; - this.$confirm("纭瑕�" + text + row.pacName + "濂楅鍚楋紵") + this.$modal + .confirm("纭瑕�" + text + row.pacName + "濂楅鍚楋紵") .then(() => updateStatus(data)) .then(() => { - this.msgSuccess(text + "鎴愬姛"); + this.$modal.msgSuccess(text + "鎴愬姛"); }) .catch(() => { row.pacStatus = row.pacStatus === "0" ? "0" : "1"; @@ -676,7 +551,7 @@ getPacInFo(row.pacId).then((response) => { const data = response.data || {}; Object.keys(data).forEach((key) => { - this.$set(this.form, key, response.data[key]); + this.$set(this.form, key, data[key]); }); this.youhui = data.limits || 10; this.pics = data.price || 0; @@ -689,9 +564,7 @@ this.checkedkey = this.DataList.map(item => item.proId || ''); this.checkedListkey = [...this.checkedkey]; this.checkedNodes = [...this.checkedkey]; - return this.getDataList(); - }).then(() => { this.loading = false; this.$nextTick(() => { @@ -706,32 +579,23 @@ if (this.form.pacName) { if (!this.form.tjProjectList) { this.form.tjProjectList = []; - this.form.tjProjectList.push({ - id: parseInt(length), - proName: "", - allSonProName: "", - proPrice: "", - priceNow: "", - proId: "", - }); - } else { - this.form.tjProjectList.push({ - id: parseInt(length), - proName: "", - allSonProName: "", - proPrice: "", - priceNow: "", - proId: "", - }); } + this.form.tjProjectList.push({ + id: this.form.tjProjectList.length + 1, + proName: "", + allSonProName: "", + proPrice: "", + priceNow: "", + proId: "", + }); } else { - Message.warning("璇峰厛濉啓濂楅鍚嶇О"); + this.$modal.msgWarning("璇峰厛濉啓濂楅鍚嶇О"); } this.$forceUpdate(); }, Delete(index) { if (this.form.tjProjectList.length === 0) { - this.$alert("璇峰厛閫夋嫨瑕佸垹闄ょ殑鏁版嵁", "鎻愮ず", { confirmButtonText: "纭畾" }); + this.$modal.alert("璇峰厛閫夋嫨瑕佸垹闄ょ殑鏁版嵁", "鎻愮ず", { confirmButtonText: "纭畾" }); } else { this.form.tjProjectList.splice(index, 1); } @@ -801,20 +665,6 @@ </span> ); }, - getDataList() { - this.loading = true; - search(this.queryParams1).then((response) => { - this.Treedata = response.data.list; - this.total1 = response.data.total; - this.pics = this.DataList.reduce((total, item) => total + item.priceOrd, 0); - this.$nextTick(() => { - this.$refs.tree.setCheckedKeys(this.checkedNodes); - this.initializing = false; - }); - - }); - this.loading = false; - }, handleFilterInput() { this.queryParams1.page = 1; this.getDataList(); @@ -824,7 +674,7 @@ }, handleCurrentChecked(data, checked, indeterminate) { if (this.initializing) { - return; // 鍒濆鍖栨椂涓嶅鐞� + return; } if (checked) { if (!this.DataList.some((item) => item.proId === data.proId)) { @@ -848,57 +698,21 @@ } this.updateTotalPrice(); } - }, updateTotalPrice() { this.form.xianprice = this.DataList.reduce((sum, item) => { - return sum.plus(new Big(item.priceNow || "0")); + return sum.plus(new Big(item.priceNow || 0)); }, new Big(0)).toNumber(); - this.pics = this.DataList.reduce((total, item) => total + item.priceOrd, 0); + this.pics = this.DataList.reduce((total, item) => total + (item.priceOrd || 0), 0); }, changeXianjia() { - if (this.form.xianprice !== 0) { + if (this.form.xianprice !== 0 && this.pics) { this.youhui = (Math.floor((this.form.xianprice / this.pics) * 100) / 100) * 10; } }, - /* numberChangeXianPrice(currentValue, oldValue) { - if (this.form.xianprice === this.lastXianPrice || !this.form.xianprice) return; - clearTimeout(this.debounceTimer); - this.debounceTimer = setTimeout(() => { - this.$confirm("纭畾淇敼鎵�鏈夊瓙椤圭殑鎶樻墸鍚楋紵", "鎻愮ず", { - confirmButtonText: "纭畾", - cancelButtonText: "鍙栨秷", - type: "warning", - }) - .then(() => { - this.youhui = currentValue; - let totalYsprice = new Big(0); - this.DataList.forEach((item) => { - item.limits = this.youhui; - const ordPrice = new Big(item.priceOrd); - const discount = new Big(item.limits); - const result = ordPrice.times(discount.div(10)); - item.priceNow = result.toNumber(); - totalYsprice = totalYsprice.plus(new Big(item.priceNow)); - }); - if (!totalYsprice.eq(this.form.xianprice)) { - const diff = new Big(this.form.xianprice).minus(totalYsprice); - if (this.DataList.length > 0) { - const lastItem = this.DataList[this.DataList.length - 1]; - const newYsPrice = new Big(lastItem.priceNow).plus(diff).toNumber(); - this.$set(this.DataList[this.DataList.length - 1], "priceNow", newYsPrice); - } - } - this.lastXianPrice = this.form.xianprice; - }) - .catch(() => { - this.youhui = oldValue; - }); - }, 500); - }, */ spliceData() { - for (var i = 0; i < this.DataList.length; i++) { - for (var j = i + 1; j < this.DataList.length; j++) { + for (let i = 0; i < this.DataList.length; i++) { + for (let j = i + 1; j < this.DataList.length; j++) { if (this.DataList[i].proId === this.DataList[j].proId) { this.DataList.splice(j, 1); j--; @@ -910,60 +724,59 @@ handleCurrentChecked1(data, checked, checkedNodes) { if (!checked) { this.DataList = this.DataList.filter((item) => item.proId !== data.proId); - this.TotalPrice1 = this.DataList.reduce((sum, item) => sum + item.priceOrd, 0); + this.TotalPrice1 = this.DataList.reduce((sum, item) => sum + (item.priceOrd || 0), 0); this.pics = this.TotalPrice1; } else { this.DataList.push(data); - this.pics = this.DataList.reduce((sum, item) => sum + item.priceOrd, 0); + this.pics = this.DataList.reduce((sum, item) => sum + (item.priceOrd || 0), 0); this.spliceData(); this.TotalPrice1 = this.pics; } }, handleDeletes(row) { this.DataList = this.DataList.filter((item) => item.proParentId !== row.proParentId); - this.TotalPrice1 = this.DataList.reduce((sum, item) => sum + item.priceOrd, 0); + this.TotalPrice1 = this.DataList.reduce((sum, item) => sum + (item.priceOrd || 0), 0); }, submitForm() { - // 妫�鏌ョ幇浠锋槸鍚﹀彂鐢熷彉鍖� - if (this.form.xianprice !== this.lastXianPrice) { - this.$confirm("纭畾淇敼鎵�鏈夊瓙椤圭殑鎶樻墸鍚楋紵", "鎻愮ず", { - confirmButtonText: "纭畾", - cancelButtonText: "鍙栨秷", - type: "warning", - }).then(() => { - // 鏇存柊鎵�鏈夊瓙椤圭殑鎶樻墸 - this.youhui = (Math.floor((this.form.xianprice / this.pics) * 100) / 100) * 10; - let totalYsprice = new Big(0); - this.DataList.forEach((item) => { - item.limits = this.youhui; - const ordPrice = new Big(item.priceOrd); - const discount = new Big(item.limits); - const result = ordPrice.times(discount.div(10)); - item.priceNow = result.toNumber(); - totalYsprice = totalYsprice.plus(new Big(item.priceNow)); - }); - - if (!totalYsprice.eq(this.form.xianprice)) { - const diff = new Big(this.form.xianprice).minus(totalYsprice); - if (this.DataList.length > 0) { - const lastItem = this.DataList[this.DataList.length - 1]; - const newYsPrice = new Big(lastItem.priceNow).plus(diff).toNumber(); - this.$set(this.DataList[this.DataList.length - 1], "priceNow", newYsPrice); - } + this.$refs.form.validate((valid) => { + if (valid) { + if (this.form.xianprice !== this.lastXianPrice) { + this.$modal + .confirm("纭畾淇敼鎵�鏈夊瓙椤圭殑鎶樻墸鍚楋紵", "鎻愮ず", { + confirmButtonText: "纭畾", + cancelButtonText: "鍙栨秷", + type: "warning", + }) + .then(() => { + this.youhui = (Math.floor((this.form.xianprice / this.pics) * 100) / 100) * 10; + let totalYsprice = new Big(0); + this.DataList.forEach((item) => { + item.limits = this.youhui; + const ordPrice = new Big(item.priceOrd || 0); + const discount = new Big(item.limits); + const result = ordPrice.times(discount.div(10)); + item.priceNow = result.toNumber(); + totalYsprice = totalYsprice.plus(new Big(item.priceNow)); + }); + if (!totalYsprice.eq(this.form.xianprice)) { + const diff = new Big(this.form.xianprice).minus(totalYsprice); + if (this.DataList.length > 0) { + const lastItem = this.DataList[this.DataList.length - 1]; + const newYsPrice = new Big(lastItem.priceNow).plus(diff).toNumber(); + this.$set(this.DataList[this.DataList.length - 1], "priceNow", newYsPrice); + } + } + return this.saveData(); + }) + .catch(() => { + this.form.xianprice = this.lastXianPrice; + }); + } else { + this.saveData(); } - - // 淇濆瓨鏁版嵁 - return this.saveData(); - }).catch(() => { - // 鐢ㄦ埛鍙栨秷鎿嶄綔锛屾仮澶嶅師鏉ョ殑鐜颁环 - this.form.xianprice = this.lastXianPrice; - }); - } else { - // 鐜颁环娌℃湁鍙樺寲锛岀洿鎺ヤ繚瀛� - this.saveData(); - } + } + }); }, - // 鏂板涓�涓柟娉曞鐞嗕繚瀛橀�昏緫 saveData() { this.form.limits = this.youhui; this.form.price = this.pics; @@ -985,7 +798,7 @@ pacName: this.form.pacName, limits: this.form.limits, pacStatus: this.form.pacStatus, - packageProjects: packageProjects, + packageProjects: packageProjects, newPrice: this.form.xianprice, price: this.pics, pacId: this.form.pacId || null, @@ -996,10 +809,12 @@ pacRemark: this.form.pacRemark, detail: this.form.detail, }; - return saveOreditTjPacNew(data).then((res) => { + this.$modal.msgSuccess("淇濆瓨鎴愬姛"); this.open = false; this.getList(); + }).catch(() => { + this.$message.error("淇濆瓨澶辫触"); }); }, handleDelete(row) { @@ -1027,11 +842,11 @@ }, }; </script> + <style> .el-tooltip__popper { max-width: 800px; } - .showInline { overflow: hidden; text-overflow: ellipsis; @@ -1040,35 +855,22 @@ line-clamp: 2; -webkit-box-orient: vertical; } - .pag { width: 100%; display: flex; justify-content: center; } - .pag1 { width: 30%; } - .dialog-footer { position: absolute; left: 40%; bottom: 2%; } - .tab3 { max-height: 400px; overflow-y: auto; border: 1px solid #d9d9d9; } - -/* .custom-tree-node { - flex: 1; - display: flex; - align-items: center; - justify-content: space-between; - font-size: 14px; - padding-right: 8px; - } */ </style> \ No newline at end of file diff --git a/src/views/system/tijian/index.vue b/src/views/system/tijian/index.vue index 37b2ed6..fc937f1 100644 --- a/src/views/system/tijian/index.vue +++ b/src/views/system/tijian/index.vue @@ -2572,6 +2572,8 @@ }, handleClick(tab, event) { if (this.activeNames == "second") { + console.log(this.form); + this.DataList = []; this.checkedkey = []; this.TreedataList = []; @@ -2590,15 +2592,11 @@ }); } }, - // gaibian(val){ - // let pname = val; - // getProParentIdDxList(pname).then(response=>{ - // this.Treedata = response.data.list; - // }) - // }, getDataList() { this.loading = true; - getProParentIdDxList().then((response) => { + console.log(this.form); + + getProParentIdDxList(this.form.cusSex).then((response) => { this.Treedata = response.data.list; // 鍥炴樉 TreedataList 鍒� DataList -- Gitblit v1.8.0