wwl
2025-06-26 f1bd6c371da44538248ea8fd479f0f4a2180e337
今日通知,限制电话输入位数,富文本
6个文件已修改
2个文件已添加
2个文件已删除
670 ■■■■■ 已修改文件
package.json 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/index.html 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main.js 74 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/12.vue 212 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ceshi.vue 198 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/index_v1.vue 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/tijian/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/tijianall/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/tongbuDict/index.vue 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vue.config.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json
@@ -36,31 +36,48 @@
    "url": "https://gitee.com/y_project/RuoYi-Vue.git"
  },
  "dependencies": {
    "@fortawesome/fontawesome-svg-core": "^6.7.2",
    "@fortawesome/free-solid-svg-icons": "^6.7.2",
    "@riophae/vue-treeselect": "0.4.0",
    "@tinymce/tinymce-vue": "^3.2.8",
    "@tiptap/extension-font-family": "^2.22.3",
    "@tiptap/extension-image": "^2.22.3",
    "@tiptap/extension-table": "^2.22.3",
    "@tiptap/extension-table-cell": "^2.22.3",
    "@tiptap/extension-table-header": "^2.22.3",
    "@tiptap/extension-table-row": "^2.22.3",
    "@tiptap/extension-text-style": "^2.22.3",
    "@tiptap/starter-kit": "^2.22.3",
    "@tiptap/vue-2": "^2.22.3",
    "axios": "0.24.0",
    "babel-polyfill": "^6.26.0",
    "big.js": "^6.2.2",
    "clipboard": "2.0.8",
    "cnchar": "^3.2.6",
    "core-js": "3.25.3",
    "docx": "^9.5.1",
    "echarts": "4.9.0",
    "element-ui": "2.15.10",
    "file-saver": "^2.0.5",
    "fuse.js": "6.4.3",
    "highlight.js": "9.18.5",
    "html2canvas": "^1.4.1",
    "js-beautify": "1.13.0",
    "js-cookie": "3.0.1",
    "jsbarcode": "^3.11.6",
    "jsencrypt": "3.0.0-rc.1",
    "jspdf": "^3.0.1",
    "lodash": "^4.17.21",
    "moment": "^2.30.1",
    "nprogress": "0.2.0",
    "pdfmake": "^0.2.20",
    "pinyin-match": "^1.2.2",
    "print-js": "^1.6.0",
    "quill": "1.3.7",
    "screenfull": "5.0.2",
    "sortablejs": "1.10.2",
    "tduck-form-generator": "^1.8.0",
    "tinymce": "^7.9.1",
    "ua-parser-js": "^1.0.37",
    "vue": "2.6.12",
    "vue-barcode": "^1.3.0",
@@ -73,6 +90,7 @@
    "vue-qr": "^4.0.9",
    "vue-quill-editor": "^3.0.6",
    "vue-router": "3.4.9",
    "vue2-editor": "^2.10.3",
    "vuedraggable": "2.24.3",
    "vuex": "3.6.0",
    "xlsx": "^0.18.5"
@@ -97,7 +115,10 @@
    "script-ext-html-webpack-plugin": "2.1.5",
    "script-loader": "^0.7.2",
    "svg-sprite-loader": "5.1.1",
    "vue-template-compiler": "2.6.12"
    "vue-loader": "^15.11.1",
    "vue-template-compiler": "2.6.12",
    "webpack": "^4.46.0",
    "webpack-cli": "^3.3.12"
  },
  "engines": {
    "node": ">=8.9",
public/index.html
@@ -2,6 +2,9 @@
<html>
<head>
  <script src="https://cdn.jsdelivr.net/npm/pdfmake@0.2.7/build/pdfmake.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/pdfmake@0.2.7/build/vfs_fonts.js"></script>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta name="renderer" content="webkit">
src/main.js
@@ -1,10 +1,8 @@
import Vue from "vue";
import Cookies from "js-cookie";
import "babel-polyfill";
import Element from "element-ui";
import "./assets/styles/element-variables.scss";
import "@/assets/styles/index.scss"; // global css
import "@/assets/styles/ruoyi.scss"; // ruoyi css
import App from "./App";
@@ -14,25 +12,7 @@
import plugins from "./plugins"; // plugins
import { download } from "@/utils/request";
import Print from "vue-print-nb";
// import Updater from "./utils/AutoUpdate.js";
//前端重新部署通知用户刷新网页
// const AutoUpdate = new Updater()
// AutoUpdate.on('update',()=>{
//   setTimeout(async()=>{
//       const result = confirm('当前版本已更新,请点击确定刷新页面体验');
//       if(result){
//         location.reload();
//       }
//   },500)
// })
import JsonExcel from "vue-json-excel";
Vue.component("downloadExcel", JsonExcel);
import "./assets/icons"; // icon
import "./permission"; // permission control
import { getDicts } from "@/api/system/dict/data";
@@ -45,36 +25,27 @@
  selectDictLabels,
  handleTree,
} from "@/utils/ruoyi";
// 分页组件
import Pagination from "@/components/Pagination";
// 分页组件
// import { monitorZoom } from "@/utils/devicePixelRatio.js";
// const m = monitorZoom();
// if (window.screen.width * window.devicePixelRatio >= 3840) {
//   document.body.style.zoom = 100 / (Number(m) / 2); // 屏幕为 4k 时
// } else {
//   document.body.style.zoom = 100 / Number(m);
// }
// 自定义表格工具组件
import RightToolbar from "@/components/RightToolbar";
// 富文本组件
import Editor from "@/components/Editor";
// 文件上传组件
import FileUpload from "@/components/FileUpload";
// 图片上传组件
import ImageUpload from "@/components/ImageUpload";
// 图片预览组件
import ImagePreview from "@/components/ImagePreview";
// 字典标签组件
import DictTag from "@/components/DictTag";
// 头部标签组件
import VueMeta from "vue-meta";
// 字典数据组件
import DictData from "@/components/DictData";
import * as echarts from "echarts";
import VueBarcode from "vue-barcode";
Vue.component("downloadExcel", JsonExcel);
Vue.component("barcode", VueBarcode);
Vue.component("DictTag", DictTag);
Vue.component("Pagination", Pagination);
Vue.component("RightToolbar", RightToolbar);
Vue.component("Editor", Editor);
Vue.component("FileUpload", FileUpload);
Vue.component("ImageUpload", ImageUpload);
Vue.component("ImagePreview", ImagePreview);
// 全局方法挂载
Vue.prototype.getDicts = getDicts;
@@ -87,36 +58,15 @@
Vue.prototype.download = download;
Vue.prototype.handleTree = handleTree;
Vue.prototype.$echarts = echarts;
import VueBarcode from "vue-barcode";
Vue.component("barcode", VueBarcode);
// 全局组件挂载
Vue.component("DictTag", DictTag);
Vue.component("Pagination", Pagination);
Vue.component("RightToolbar", RightToolbar);
Vue.component("Editor", Editor);
Vue.component("FileUpload", FileUpload);
Vue.component("ImageUpload", ImageUpload);
Vue.component("ImagePreview", ImagePreview);
Vue.use(directive);
Vue.use(plugins);
Vue.use(VueMeta);
Vue.use(Print);
DictData.install();
/**
 * If you don't want to use mock-server
 * you want to use MockJs for mock api
 * you can execute: mockXHR()
 *
 * Currently MockJs will be used in the production environment,
 * please remove it before going online! ! !
 */
Vue.use(Element, {
  size: Cookies.get("size") || "medium", // set element-ui default size
});
DictData.install();
Vue.config.productionTip = false;
src/views/12.vue
File was deleted
src/views/ceshi.vue
New file
@@ -0,0 +1,198 @@
<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('解析 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>
src/views/index_v1.vue
File was deleted
src/views/system/tijian/index.vue
@@ -183,7 +183,7 @@
                trigger: 'blur',
              },
            ]">
              <el-input v-model="form.cusPhone" placeholder="请输入联系电话" :disabled="isDisabled"
              <el-input v-model="form.cusPhone" placeholder="请输入联系电话"  maxlength="11" :disabled="isDisabled"
                @input="form.cusPhone = $event.replace(/\s/g, '')" />
            </el-form-item>
src/views/system/tijianall/index.vue
@@ -182,6 +182,7 @@
              ]"
            >
              <el-input
             maxlength="11"
                v-model="form.cusPhone"
                placeholder="请输入电话"
                @input="form.cusPhone = $event.replace(/\s/g, '')"
src/views/system/tongbuDict/index.vue
New file
@@ -0,0 +1,57 @@
<template>
  <div class="app-container">
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
      <el-form-item label="选择院区" prop="status">
        <el-select v-model="queryParams.status" clearable style="width: 240px">
          <el-option v-for="area in hospitalAreas" :key="area.hospAreaId" :label="area.hospAreaName"
            :value="area.hospAreaId" />
        </el-select>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" size="mini" @click="tongbu(true)">同步字典</el-button>
        <el-button type="primary" size="mini" @click="tongbu(false)">只调用存储过程</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>
<script>
import { yuanqu, tongbuzidian } from "@/api/system/dict/type";
export default {
  name: "Dict",
  data() {
    return {
      // 显示搜索条件
      showSearch: true,
      // 字典表格数据
      typeList: [],
      // 院区数据
      hospitalAreas: [],
      // 查询参数
      queryParams: {
        status: undefined
      },
      // 表单参数
      form: {},
    };
  },
  created() {
    yuanqu().then((res) => {
      this.hospitalAreas = res.data || [];
      console.log(res);
    });
    this.getList();
  },
  methods: {
    tongbu(t) {
      tongbuzidian(t).then((res) => {
        console.log(res);
      })
    },
    getAreaName(status) {
      const area = this.hospitalAreas.find(area => area.hospAreaId === status);
      return area ? area.hospAreaName : status;
    }
  }
};
</script>
vue.config.js
@@ -57,7 +57,7 @@
        // target: `http://192.168.1.2:5011`,
        target: `http://192.168.1.113:5011`,
        target: `http://192.168.1.2:5011`,
        // // target: `http://192.168.0.99:8080/ltkj-admin`,
        // target: `https://ltpeis.xaltjdkj.cn:5011/ltkj-admin`,
        // target: `http://10.168.0.9:5011`,  `