From 5bfadb9174615e9900f1bf30dc676fb1546da883 Mon Sep 17 00:00:00 2001 From: chenqi Date: Sun, 14 Dec 2025 14:22:55 +0800 Subject: [PATCH] =?UTF-8?q?fix(login):=20=E4=BF=AE=E5=A4=8D=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E7=94=A8=E6=88=B7=E7=BB=91=E5=AE=9A=E7=A7=9F=E6=88=B7?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E6=97=B6=E7=94=A8=E6=88=B7=E5=90=8D=E4=B8=BA?= =?UTF-8?q?=E7=A9=BA=E5=AF=BC=E8=87=B4=E7=9A=84URL=E9=94=99=E8=AF=AF=20?= =?UTF-8?q?=E7=A1=AE=E4=BF=9Dusername=E5=8F=82=E6=95=B0=E5=AD=98=E5=9C=A8?= =?UTF-8?q?=EF=BC=8C=E9=81=BF=E5=85=8D=E5=9B=A0=E4=B8=BA=E7=A9=BA=E5=80=BC?= =?UTF-8?q?=E9=80=A0=E6=88=90=E6=8E=A5=E5=8F=A3=E8=B0=83=E7=94=A8=E5=A4=B1?= =?UTF-8?q?=E8=B4=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit feat(editor): 重构富文本编辑器组件并优化图片上传逻辑 - 使用 Composition API 重构代码结构,提升可维护性 - 改进图片上传功能,增强对 quill 实例的安全访问 - 更新样式排版,提高组件可读性和一致性 refactor(file-upload): 移除旧代理引用,使用 modern Vue API 替换 `proxy` 调用为 `modal` 插件直接调用,提升代码清晰度与健壮性 refactor(image-upload): 替换旧实例调用方式,强化错误提示机制 统一使用 `modal` 进行消息提示和加载状态控制,改善用户体验 refactor(tree-select): 引入 Composition API 优化节点操作逻辑 移除 `getCurrentInstance` 的不必要使用,改为明确的模板引用管理 chore(main): 添加 util._extend 补丁以消除 Node.js 环境警告 解决开发环境下由于 Node.js 内建模块缺失造成的运行时警告问题 feat(template): 完善跌倒/坠床评估护理记录单模板 - 增加详细注释说明各部分作用,便于后续维护 - 明确组件名称为中文,利于业务识别 - 丰富表单交互细节及数据处理逻辑,支持动态打分、措施选择等功能 refactor(template-index): 加强模板组件自动注册逻辑 增加组件 name 属性校验,防止无效或匿名组件被注册到全局 --- openhis-ui-vue3/src/api/login.js | 4 +- .../src/components/Editor/index.vue | 112 ++++++++------ .../src/components/FileUpload/index.vue | 24 +-- .../src/components/ImageUpload/index.vue | 24 +-- .../src/components/TreeSelect/index.vue | 13 +- openhis-ui-vue3/src/main.js | 22 ++- .../src/template/FallBedFallAssessment.vue | 83 +++++++--- openhis-ui-vue3/src/template/index.js | 37 ++++- .../src/template/nursingRecordSheet.vue | 146 ++++++------------ .../src/template/outpatientMedicalRecord.vue | 39 +++-- .../src/template/useOptionsList.js | 37 ++++- .../src/template/股骨头坏死(模板1).vue | 4 +- .../views/drug/inHospitalDispensing/index.vue | 1 - openhis-ui-vue3/src/views/login.vue | 31 ++-- openhis-ui-vue3/test-util-extend.js | 25 +++ openhis-ui-vue3/vite.config.js | 2 +- 16 files changed, 367 insertions(+), 237 deletions(-) create mode 100644 openhis-ui-vue3/test-util-extend.js diff --git a/openhis-ui-vue3/src/api/login.js b/openhis-ui-vue3/src/api/login.js index dc96c258..9d793df9 100644 --- a/openhis-ui-vue3/src/api/login.js +++ b/openhis-ui-vue3/src/api/login.js @@ -50,8 +50,10 @@ export function logout() { // 获取验证码 export function getUserBindTenantList(username) { + // 确保username存在,避免构建出错误的URL + const safeUsername = username || ''; return request({ - url: '/system/tenant/user-bind/'+username, + url: '/system/tenant/user-bind/' + safeUsername, headers: { isToken: false }, diff --git a/openhis-ui-vue3/src/components/Editor/index.vue b/openhis-ui-vue3/src/components/Editor/index.vue index 0a696f22..c919df0f 100644 --- a/openhis-ui-vue3/src/components/Editor/index.vue +++ b/openhis-ui-vue3/src/components/Editor/index.vue @@ -1,28 +1,16 @@ @@ -30,10 +18,11 @@ import { QuillEditor } from "@vueup/vue-quill"; import "@vueup/vue-quill/dist/vue-quill.snow.css"; import { getToken } from "@/utils/auth"; - -const { proxy } = getCurrentInstance(); +import { ref, computed, watch, onMounted } from 'vue'; +import modal from '@/plugins/modal'; const quillEditorRef = ref(); +const uploadRef = ref(); const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + "/common/upload"); // 上传的图片服务器地址 const headers = ref({ Authorization: "Bearer " + getToken() @@ -115,32 +104,34 @@ watch(() => props.modelValue, (v) => { // 如果设置了上传地址则自定义图片上传事件 onMounted(() => { if (props.type == 'url') { - let quill = quillEditorRef.value.getQuill(); - let toolbar = quill.getModule("toolbar"); - toolbar.addHandler("image", (value) => { - if (value) { - proxy.$refs.uploadRef.click(); - } else { - quill.format("image", false); - } - }); + let quill = quillEditorRef.value?.getQuill(); + if (quill) { + let toolbar = quill.getModule("toolbar"); + toolbar.addHandler("image", (value) => { + if (value && uploadRef.value) { + uploadRef.value.click(); + } else { + quill.format("image", false); + } + }); + } } }); // 上传前校检格式和大小 function handleBeforeUpload(file) { - const type = ["image/jpeg", "image/jpg", "image/png", "image/svg"]; + const type = ["image/jpeg", "image/jpg", "image/png", "image/svg+xml"]; const isJPG = type.includes(file.type); //检验文件格式 if (!isJPG) { - proxy.$modal.msgError(`图片格式错误!`); + modal.msgError(`图片格式错误!`); return false; } // 校检文件大小 if (props.fileSize) { const isLt = file.size / 1024 / 1024 < props.fileSize; if (!isLt) { - proxy.$modal.msgError(`上传文件大小不能超过 ${props.fileSize} MB!`); + modal.msgError(`上传文件大小不能超过 ${props.fileSize} MB!`); return false; } } @@ -152,21 +143,24 @@ function handleUploadSuccess(res, file) { // 如果上传成功 if (res.code == 200) { // 获取富文本实例 - let quill = toRaw(quillEditorRef.value).getQuill(); - // 获取光标位置 - let length = quill.selection.savedRange.index; - // 插入图片,res.url为服务器返回的图片链接地址 - quill.insertEmbed(length, "image", import.meta.env.VITE_APP_BASE_API + res.fileName); - // 调整光标到最后 - quill.setSelection(length + 1); + let quill = quillEditorRef.value?.getQuill(); + if (quill) { + // 获取光标位置 + let range = quill.selection?.savedRange || quill.getSelection(); + let length = range?.index || 0; + // 插入图片,res.url为服务器返回的图片链接地址 + quill.insertEmbed(length, "image", import.meta.env.VITE_APP_BASE_API + res.fileName); + // 调整光标到最后 + quill.setSelection(length + 1); + } } else { - proxy.$modal.msgError("图片插入失败"); + modal.msgError("图片插入失败"); } } // 上传失败处理 function handleUploadError() { - proxy.$modal.msgError("图片插入失败"); + modal.msgError("图片插入失败"); } @@ -174,78 +168,98 @@ function handleUploadError() { .editor-img-uploader { display: none; } -.editor, .ql-toolbar { + +.editor, +.ql-toolbar { white-space: pre-wrap !important; line-height: normal !important; } + .quill-img { display: none; } + .ql-snow .ql-tooltip[data-mode="link"]::before { content: "请输入链接地址:"; } + .ql-snow .ql-tooltip.ql-editing a.ql-action::after { border-right: 0px; content: "保存"; padding-right: 0px; } + .ql-snow .ql-tooltip[data-mode="video"]::before { content: "请输入视频地址:"; } + .ql-snow .ql-picker.ql-size .ql-picker-label::before, .ql-snow .ql-picker.ql-size .ql-picker-item::before { content: "14px"; } + .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before, .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before { content: "10px"; } + .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before, .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before { content: "18px"; } + .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before, .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before { content: "32px"; } + .ql-snow .ql-picker.ql-header .ql-picker-label::before, .ql-snow .ql-picker.ql-header .ql-picker-item::before { content: "文本"; } + .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before, .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before { content: "标题1"; } + .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before, .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before { content: "标题2"; } + .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before, .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before { content: "标题3"; } + .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before, .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before { content: "标题4"; } + .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before, .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before { content: "标题5"; } + .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before, .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before { content: "标题6"; } + .ql-snow .ql-picker.ql-font .ql-picker-label::before, .ql-snow .ql-picker.ql-font .ql-picker-item::before { content: "标准字体"; } + .ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before, .ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before { content: "衬线字体"; } + .ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before, .ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before { content: "等宽字体"; } - + \ No newline at end of file diff --git a/openhis-ui-vue3/src/components/FileUpload/index.vue b/openhis-ui-vue3/src/components/FileUpload/index.vue index 2af9672e..38911eab 100644 --- a/openhis-ui-vue3/src/components/FileUpload/index.vue +++ b/openhis-ui-vue3/src/components/FileUpload/index.vue @@ -39,7 +39,9 @@ + +/* 备注信息列表样式 */ +.instructions-list { + list-style-type: none; + padding-left: 0; +} + \ No newline at end of file diff --git a/openhis-ui-vue3/src/template/index.js b/openhis-ui-vue3/src/template/index.js index 65055b2e..523c687f 100644 --- a/openhis-ui-vue3/src/template/index.js +++ b/openhis-ui-vue3/src/template/index.js @@ -1,17 +1,42 @@ -// 动态引入 template 目录下的所有 .vue 文件 +/** + * 模板组件注册模块 + * 动态引入 template 目录下的所有 .vue 文件,并将它们注册为全局组件 + */ + +// 动态引入 template 目录下的所有 .vue 文件(包括中文命名的文件) +// 使用 { eager: true } 表示立即加载所有匹配的文件 const templates = import.meta.glob('./*.vue', { eager: true }); +// 存储所有加载的组件 const components = []; // 遍历所有引入的文件 for (const path in templates) { - const component = templates[path].default; - components.push(component); + try { + // 获取组件的默认导出 + const component = templates[path].default; + + // 检查组件是否有 name 属性,如果没有则跳过 + if (component && component.name) { + components.push(component); + } else { + console.warn(`组件 ${path} 缺少 name 属性,将不会被注册`); + } + } catch (error) { + console.error(`加载组件 ${path} 时出错:`, error); + } } + +/** + * 注册所有组件到 Vue 应用实例 + * @param {Object} app - Vue 应用实例 + */ const registerComponents = (app) => { components.forEach((component) => { + // 使用组件的 name 属性作为组件名称进行注册 app.component(component.name, component); - }) -} -export { components, registerComponents }; + }); +}; +// 导出组件数组和注册函数 +export { components, registerComponents }; \ No newline at end of file diff --git a/openhis-ui-vue3/src/template/nursingRecordSheet.vue b/openhis-ui-vue3/src/template/nursingRecordSheet.vue index dcfb1ba0..f3d354f3 100644 --- a/openhis-ui-vue3/src/template/nursingRecordSheet.vue +++ b/openhis-ui-vue3/src/template/nursingRecordSheet.vue @@ -5,13 +5,11 @@ -->