fix(login): 修复获取用户绑定租户列表时用户名为空导致的URL错误

确保username参数存在,避免因为空值造成接口调用失败

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 属性校验,防止无效或匿名组件被注册到全局
This commit is contained in:
2025-12-14 14:22:55 +08:00
parent e1b9d36153
commit 5bfadb9174
16 changed files with 367 additions and 237 deletions

View File

@@ -50,8 +50,10 @@ export function logout() {
// 获取验证码 // 获取验证码
export function getUserBindTenantList(username) { export function getUserBindTenantList(username) {
// 确保username存在避免构建出错误的URL
const safeUsername = username || '';
return request({ return request({
url: '/system/tenant/user-bind/'+username, url: '/system/tenant/user-bind/' + safeUsername,
headers: { headers: {
isToken: false isToken: false
}, },

View File

@@ -1,28 +1,16 @@
<template> <template>
<div class="editor-container">
<div> <div>
<el-upload <el-upload :action="uploadUrl" :before-upload="handleBeforeUpload" :on-success="handleUploadSuccess"
:action="uploadUrl" :on-error="handleUploadError" name="file" :show-file-list="false" :headers="headers" class="editor-img-uploader"
:before-upload="handleBeforeUpload" v-if="type == 'url'">
:on-success="handleUploadSuccess"
:on-error="handleUploadError"
name="file"
:show-file-list="false"
:headers="headers"
class="editor-img-uploader"
v-if="type == 'url'"
>
<i ref="uploadRef" class="editor-img-uploader"></i> <i ref="uploadRef" class="editor-img-uploader"></i>
</el-upload> </el-upload>
</div> </div>
<div class="editor"> <div class="editor">
<quill-editor <quill-editor ref="quillEditorRef" :content="content" @update:content="content = $event" contentType="html"
ref="quillEditorRef" @textChange="(e) => $emit('update:modelValue', content)" :options="options" :style="styles" />
v-model:content="content" </div>
contentType="html"
@textChange="(e) => $emit('update:modelValue', content)"
:options="options"
:style="styles"
/>
</div> </div>
</template> </template>
@@ -30,10 +18,11 @@
import { QuillEditor } from "@vueup/vue-quill"; import { QuillEditor } from "@vueup/vue-quill";
import "@vueup/vue-quill/dist/vue-quill.snow.css"; import "@vueup/vue-quill/dist/vue-quill.snow.css";
import { getToken } from "@/utils/auth"; import { getToken } from "@/utils/auth";
import { ref, computed, watch, onMounted } from 'vue';
const { proxy } = getCurrentInstance(); import modal from '@/plugins/modal';
const quillEditorRef = ref(); const quillEditorRef = ref();
const uploadRef = ref();
const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + "/common/upload"); // 上传的图片服务器地址 const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + "/common/upload"); // 上传的图片服务器地址
const headers = ref({ const headers = ref({
Authorization: "Bearer " + getToken() Authorization: "Bearer " + getToken()
@@ -115,32 +104,34 @@ watch(() => props.modelValue, (v) => {
// 如果设置了上传地址则自定义图片上传事件 // 如果设置了上传地址则自定义图片上传事件
onMounted(() => { onMounted(() => {
if (props.type == 'url') { if (props.type == 'url') {
let quill = quillEditorRef.value.getQuill(); let quill = quillEditorRef.value?.getQuill();
if (quill) {
let toolbar = quill.getModule("toolbar"); let toolbar = quill.getModule("toolbar");
toolbar.addHandler("image", (value) => { toolbar.addHandler("image", (value) => {
if (value) { if (value && uploadRef.value) {
proxy.$refs.uploadRef.click(); uploadRef.value.click();
} else { } else {
quill.format("image", false); quill.format("image", false);
} }
}); });
} }
}
}); });
// 上传前校检格式和大小 // 上传前校检格式和大小
function handleBeforeUpload(file) { 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); const isJPG = type.includes(file.type);
//检验文件格式 //检验文件格式
if (!isJPG) { if (!isJPG) {
proxy.$modal.msgError(`图片格式错误!`); modal.msgError(`图片格式错误!`);
return false; return false;
} }
// 校检文件大小 // 校检文件大小
if (props.fileSize) { if (props.fileSize) {
const isLt = file.size / 1024 / 1024 < props.fileSize; const isLt = file.size / 1024 / 1024 < props.fileSize;
if (!isLt) { if (!isLt) {
proxy.$modal.msgError(`上传文件大小不能超过 ${props.fileSize} MB!`); modal.msgError(`上传文件大小不能超过 ${props.fileSize} MB!`);
return false; return false;
} }
} }
@@ -152,21 +143,24 @@ function handleUploadSuccess(res, file) {
// 如果上传成功 // 如果上传成功
if (res.code == 200) { if (res.code == 200) {
// 获取富文本实例 // 获取富文本实例
let quill = toRaw(quillEditorRef.value).getQuill(); let quill = quillEditorRef.value?.getQuill();
if (quill) {
// 获取光标位置 // 获取光标位置
let length = quill.selection.savedRange.index; let range = quill.selection?.savedRange || quill.getSelection();
let length = range?.index || 0;
// 插入图片res.url为服务器返回的图片链接地址 // 插入图片res.url为服务器返回的图片链接地址
quill.insertEmbed(length, "image", import.meta.env.VITE_APP_BASE_API + res.fileName); quill.insertEmbed(length, "image", import.meta.env.VITE_APP_BASE_API + res.fileName);
// 调整光标到最后 // 调整光标到最后
quill.setSelection(length + 1); quill.setSelection(length + 1);
}
} else { } else {
proxy.$modal.msgError("图片插入失败"); modal.msgError("图片插入失败");
} }
} }
// 上传失败处理 // 上传失败处理
function handleUploadError() { function handleUploadError() {
proxy.$modal.msgError("图片插入失败"); modal.msgError("图片插入失败");
} }
</script> </script>
@@ -174,76 +168,96 @@ function handleUploadError() {
.editor-img-uploader { .editor-img-uploader {
display: none; display: none;
} }
.editor, .ql-toolbar {
.editor,
.ql-toolbar {
white-space: pre-wrap !important; white-space: pre-wrap !important;
line-height: normal !important; line-height: normal !important;
} }
.quill-img { .quill-img {
display: none; display: none;
} }
.ql-snow .ql-tooltip[data-mode="link"]::before { .ql-snow .ql-tooltip[data-mode="link"]::before {
content: "请输入链接地址:"; content: "请输入链接地址:";
} }
.ql-snow .ql-tooltip.ql-editing a.ql-action::after { .ql-snow .ql-tooltip.ql-editing a.ql-action::after {
border-right: 0px; border-right: 0px;
content: "保存"; content: "保存";
padding-right: 0px; padding-right: 0px;
} }
.ql-snow .ql-tooltip[data-mode="video"]::before { .ql-snow .ql-tooltip[data-mode="video"]::before {
content: "请输入视频地址:"; content: "请输入视频地址:";
} }
.ql-snow .ql-picker.ql-size .ql-picker-label::before, .ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before { .ql-snow .ql-picker.ql-size .ql-picker-item::before {
content: "14px"; content: "14px";
} }
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before, .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 { .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
content: "10px"; content: "10px";
} }
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before, .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 { .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
content: "18px"; content: "18px";
} }
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before, .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 { .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
content: "32px"; content: "32px";
} }
.ql-snow .ql-picker.ql-header .ql-picker-label::before, .ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-snow .ql-picker.ql-header .ql-picker-item::before { .ql-snow .ql-picker.ql-header .ql-picker-item::before {
content: "文本"; content: "文本";
} }
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before, .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 { .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
content: "标题1"; content: "标题1";
} }
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before, .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 { .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
content: "标题2"; content: "标题2";
} }
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before, .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 { .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
content: "标题3"; content: "标题3";
} }
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before, .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 { .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
content: "标题4"; content: "标题4";
} }
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before, .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 { .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
content: "标题5"; content: "标题5";
} }
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before, .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 { .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
content: "标题6"; content: "标题6";
} }
.ql-snow .ql-picker.ql-font .ql-picker-label::before, .ql-snow .ql-picker.ql-font .ql-picker-label::before,
.ql-snow .ql-picker.ql-font .ql-picker-item::before { .ql-snow .ql-picker.ql-font .ql-picker-item::before {
content: "标准字体"; content: "标准字体";
} }
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before, .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 { .ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
content: "衬线字体"; content: "衬线字体";
} }
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before, .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 { .ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
content: "等宽字体"; content: "等宽字体";

View File

@@ -39,7 +39,9 @@
</template> </template>
<script setup> <script setup>
import { ref, computed, watch } from 'vue';
import { getToken } from "@/utils/auth"; import { getToken } from "@/utils/auth";
import modal from '@/plugins/modal';
const props = defineProps({ const props = defineProps({
modelValue: [String, Object, Array], modelValue: [String, Object, Array],
@@ -65,7 +67,7 @@ const props = defineProps({
} }
}); });
const { proxy } = getCurrentInstance(); const fileUpload = ref(null);
const emit = defineEmits(); const emit = defineEmits();
const number = ref(0); const number = ref(0);
const uploadList = ref([]); const uploadList = ref([]);
@@ -104,7 +106,7 @@ function handleBeforeUpload(file) {
const fileExt = fileName[fileName.length - 1]; const fileExt = fileName[fileName.length - 1];
const isTypeOk = props.fileType.indexOf(fileExt) >= 0; const isTypeOk = props.fileType.indexOf(fileExt) >= 0;
if (!isTypeOk) { if (!isTypeOk) {
proxy.$modal.msgError(`文件格式不正确, 请上传${props.fileType.join("/")}格式文件!`); modal.msgError(`文件格式不正确, 请上传${props.fileType.join("/")}格式文件!`);
return false; return false;
} }
} }
@@ -112,23 +114,23 @@ function handleBeforeUpload(file) {
if (props.fileSize) { if (props.fileSize) {
const isLt = file.size / 1024 / 1024 < props.fileSize; const isLt = file.size / 1024 / 1024 < props.fileSize;
if (!isLt) { if (!isLt) {
proxy.$modal.msgError(`上传文件大小不能超过 ${props.fileSize} MB!`); modal.msgError(`上传文件大小不能超过 ${props.fileSize} MB!`);
return false; return false;
} }
} }
proxy.$modal.loading("正在上传文件,请稍候..."); modal.loading("正在上传文件,请稍候...");
number.value++; number.value++;
return true; return true;
} }
// 文件个数超出 // 文件个数超出
function handleExceed() { function handleExceed() {
proxy.$modal.msgError(`上传文件数量不能超过 ${props.limit} 个!`); modal.msgError(`上传文件数量不能超过 ${props.limit} 个!`);
} }
// 上传失败 // 上传失败
function handleUploadError(err) { function handleUploadError(err) {
proxy.$modal.msgError("上传文件失败"); modal.msgError("上传文件失败");
} }
// 上传成功回调 // 上传成功回调
@@ -138,9 +140,9 @@ function handleUploadSuccess(res, file) {
uploadedSuccessfully(); uploadedSuccessfully();
} else { } else {
number.value--; number.value--;
proxy.$modal.closeLoading(); modal.closeLoading();
proxy.$modal.msgError(res.msg); modal.msgError(res.msg);
proxy.$refs.fileUpload.handleRemove(file); fileUpload.value.handleRemove(file);
uploadedSuccessfully(); uploadedSuccessfully();
} }
} }
@@ -158,7 +160,7 @@ function uploadedSuccessfully() {
uploadList.value = []; uploadList.value = [];
number.value = 0; number.value = 0;
emit("update:modelValue", listToString(fileList.value)); emit("update:modelValue", listToString(fileList.value));
proxy.$modal.closeLoading(); modal.closeLoading();
} }
} }

View File

@@ -47,6 +47,8 @@
<script setup> <script setup>
import { getToken } from "@/utils/auth"; import { getToken } from "@/utils/auth";
import { ref, computed, watch, getCurrentInstance } from 'vue';
import modal from '@/plugins/modal';
const props = defineProps({ const props = defineProps({
modelValue: [String, Object, Array], modelValue: [String, Object, Array],
@@ -72,7 +74,6 @@ const props = defineProps({
}, },
}); });
const { proxy } = getCurrentInstance();
const emit = defineEmits(); const emit = defineEmits();
const number = ref(0); const number = ref(0);
const uploadList = ref([]); const uploadList = ref([]);
@@ -82,6 +83,7 @@ const baseUrl = import.meta.env.VITE_APP_BASE_API;
const uploadImgUrl = ref(import.meta.env.VITE_APP_BASE_API + "/common/upload"); // 上传的图片服务器地址 const uploadImgUrl = ref(import.meta.env.VITE_APP_BASE_API + "/common/upload"); // 上传的图片服务器地址
const headers = ref({ Authorization: "Bearer " + getToken() }); const headers = ref({ Authorization: "Bearer " + getToken() });
const fileList = ref([]); const fileList = ref([]);
const imageUpload = ref(null);
const showTip = computed( const showTip = computed(
() => props.isShowTip && (props.fileType || props.fileSize) () => props.isShowTip && (props.fileType || props.fileSize)
); );
@@ -124,7 +126,7 @@ function handleBeforeUpload(file) {
isImg = file.type.indexOf("image") > -1; isImg = file.type.indexOf("image") > -1;
} }
if (!isImg) { if (!isImg) {
proxy.$modal.msgError( modal.msgError(
`文件格式不正确, 请上传${props.fileType.join("/")}图片格式文件!` `文件格式不正确, 请上传${props.fileType.join("/")}图片格式文件!`
); );
return false; return false;
@@ -132,17 +134,17 @@ function handleBeforeUpload(file) {
if (props.fileSize) { if (props.fileSize) {
const isLt = file.size / 1024 / 1024 < props.fileSize; const isLt = file.size / 1024 / 1024 < props.fileSize;
if (!isLt) { if (!isLt) {
proxy.$modal.msgError(`上传头像图片大小不能超过 ${props.fileSize} MB!`); modal.msgError(`上传头像图片大小不能超过 ${props.fileSize} MB!`);
return false; return false;
} }
} }
proxy.$modal.loading("正在上传图片,请稍候..."); modal.loading("正在上传图片,请稍候...");
number.value++; number.value++;
} }
// 文件个数超出 // 文件个数超出
function handleExceed() { function handleExceed() {
proxy.$modal.msgError(`上传文件数量不能超过 ${props.limit} 个!`); modal.msgError(`上传文件数量不能超过 ${props.limit} 个!`);
} }
// 上传成功回调 // 上传成功回调
@@ -152,9 +154,9 @@ function handleUploadSuccess(res, file) {
uploadedSuccessfully(); uploadedSuccessfully();
} else { } else {
number.value--; number.value--;
proxy.$modal.closeLoading(); modal.closeLoading();
proxy.$modal.msgError(res.msg); modal.msgError(res.msg);
proxy.$refs.imageUpload.handleRemove(file); imageUpload.value.handleRemove(file);
uploadedSuccessfully(); uploadedSuccessfully();
} }
} }
@@ -176,14 +178,14 @@ function uploadedSuccessfully() {
uploadList.value = []; uploadList.value = [];
number.value = 0; number.value = 0;
emit("update:modelValue", listToString(fileList.value)); emit("update:modelValue", listToString(fileList.value));
proxy.$modal.closeLoading(); modal.closeLoading();
} }
} }
// 上传失败 // 上传失败
function handleUploadError() { function handleUploadError() {
proxy.$modal.msgError("上传图片失败"); modal.msgError("上传图片失败");
proxy.$modal.closeLoading(); modal.closeLoading();
} }
// 预览 // 预览

View File

@@ -29,8 +29,11 @@
</template> </template>
<script setup> <script setup>
import { ref, computed, watch, onMounted, nextTick } from 'vue';
import { getCurrentInstance } from 'vue';
const { proxy } = getCurrentInstance(); const selectTree = ref(null);
const treeSelect = ref(null);
const props = defineProps({ const props = defineProps({
/* 配置项 */ /* 配置项 */
@@ -83,10 +86,10 @@ function initHandle() {
nextTick(() => { nextTick(() => {
const selectedValue = valueId.value; const selectedValue = valueId.value;
if(selectedValue !== null && typeof (selectedValue) !== 'undefined') { if(selectedValue !== null && typeof (selectedValue) !== 'undefined') {
const node = proxy.$refs.selectTree.getNode(selectedValue) const node = selectTree.value.getNode(selectedValue)
if (node) { if (node) {
valueTitle.value = node.data[props.objMap.label] valueTitle.value = node.data[props.objMap.label]
proxy.$refs.selectTree.setCurrentKey(selectedValue) // 设置默认选中 selectTree.value.setCurrentKey(selectedValue) // 设置默认选中
defaultExpandedKey.value = [selectedValue] // 设置默认展开 defaultExpandedKey.value = [selectedValue] // 设置默认展开
} }
} else { } else {
@@ -98,11 +101,11 @@ function handleNodeClick(node) {
valueTitle.value = node[props.objMap.label] valueTitle.value = node[props.objMap.label]
valueId.value = node[props.objMap.value]; valueId.value = node[props.objMap.value];
defaultExpandedKey.value = []; defaultExpandedKey.value = [];
proxy.$refs.treeSelect.blur() treeSelect.value.blur()
selectFilterData('') selectFilterData('')
} }
function selectFilterData(val) { function selectFilterData(val) {
proxy.$refs.selectTree.filter(val) selectTree.value.filter(val)
} }
function filterNode(value, data) { function filterNode(value, data) {
if (!value) return true if (!value) return true

View File

@@ -1,5 +1,25 @@
import { createApp } from 'vue' import { createApp } from 'vue'
// 修复 util._extend 已弃用警告(仅在 Node.js 环境中需要)
if (typeof process !== 'undefined' && process.versions && process.versions.node) {
try {
import('util').then(util => {
if (!util._extend) {
util._extend = function(destination, source) {
for (var key in source) {
if (source.hasOwnProperty(key)) {
destination[key] = source[key];
}
}
return destination;
};
}
});
} catch (e) {
console.error('util._extend 补丁加载失败:', e);
}
}
import Cookies from 'js-cookie' import Cookies from 'js-cookie'
import ElementPlus from 'element-plus' import ElementPlus from 'element-plus'

View File

@@ -1,6 +1,8 @@
<template> <template>
<!-- 跌倒/坠床评估护理记录单主容器 -->
<div> <div>
<div class="business"> <div class="business">
<!-- 已有记录展示表格 -->
<el-table <el-table
:data="tableDataSource" :data="tableDataSource"
border border
@@ -8,10 +10,15 @@
fit fit
:header-cell-style="{ background: '#f2f2f2', color: 'black' }" :header-cell-style="{ background: '#f2f2f2', color: 'black' }"
> >
<!-- 记录时间列 -->
<el-table-column prop="content.recordTime" label="记录时间" /> <el-table-column prop="content.recordTime" label="记录时间" />
<!-- 评估分数列 -->
<el-table-column prop="content.totalScore" label="评估分数" /> <el-table-column prop="content.totalScore" label="评估分数" />
<!-- 护理措施列 -->
<el-table-column prop="content.patientCareSessionsTableList" label="护理措施" /> <el-table-column prop="content.patientCareSessionsTableList" label="护理措施" />
<!-- 责任护士列 -->
<el-table-column prop="content.nurseSignature" label="责任护士" /> <el-table-column prop="content.nurseSignature" label="责任护士" />
<!-- 操作列编辑和删除按钮 -->
<el-table-column label="操作" align="center"> <el-table-column label="操作" align="center">
<template #default="scope"> <template #default="scope">
<el-button <el-button
@@ -36,9 +43,12 @@
</el-table-column> </el-table-column>
</el-table> </el-table>
<!-- 跌倒/坠床评估护理记录单表单区域 -->
<div name="跌倒/坠床评估护理记录单" class="changeMajor" style="width: 99.9%"> <div name="跌倒/坠床评估护理记录单" class="changeMajor" style="width: 99.9%">
<div> <div>
<!-- 表单主体 -->
<el-form ref="formRef" :model="form" style="width: 99.9%"> <el-form ref="formRef" :model="form" style="width: 99.9%">
<!-- 标题行 -->
<el-form-item style="text-align: center"> <el-form-item style="text-align: center">
<div <div
style=" style="
@@ -54,10 +64,12 @@
</div> </div>
</el-form-item> </el-form-item>
<!-- 日期时间选择器 -->
<el-form-item label="日期:" class="changeMajorFromItem" style="width: 100%"> <el-form-item label="日期:" class="changeMajorFromItem" style="width: 100%">
<el-row :span="20"> <el-row :span="20">
<el-col :span="8" style="padding-left: 0px !important"> <el-col :span="8" style="padding-left: 0px !important">
<el-form-item> <el-form-item>
<!-- 日期时间选择器 -->
<el-date-picker <el-date-picker
v-model="form.ZKDATE" v-model="form.ZKDATE"
type="datetime" type="datetime"
@@ -67,6 +79,7 @@
style="width: 800px" style="width: 800px"
:disabled="admissionDataForm !== undefined" :disabled="admissionDataForm !== undefined"
/> />
<!-- 时间选择器被注释掉 -->
<!-- <span style="margin-left: 5px">时间</span> <!-- <span style="margin-left: 5px">时间</span>
<el-time-picker <el-time-picker
v-model="form.ZKTIME" v-model="form.ZKTIME"
@@ -77,6 +90,7 @@
/> --> /> -->
</el-form-item> </el-form-item>
</el-col> </el-col>
<!-- 新增/保存按钮 -->
<el-col :span="5"> <el-col :span="5">
<el-button <el-button
v-if="!updateFlag" v-if="!updateFlag"
@@ -100,6 +114,7 @@
</el-row> </el-row>
</el-form-item> </el-form-item>
<!-- 危险因素评估表格 -->
<el-form-item style="padding-top: 10px; margin: 0px !important"> <el-form-item style="padding-top: 10px; margin: 0px !important">
<el-table <el-table
:data="dangerData" :data="dangerData"
@@ -107,6 +122,7 @@
:span-method="handleSpan" :span-method="handleSpan"
style="text-align: center" style="text-align: center"
> >
<!-- 动态生成表格列 -->
<el-table-column <el-table-column
v-for="column in dangerColumns" v-for="column in dangerColumns"
:key="column.key" :key="column.key"
@@ -115,6 +131,7 @@
:label="column.title" :label="column.title"
align="center" align="center"
/> />
<!-- 选择列复选框 -->
<el-table-column prop="id" label="选择" width="80" align="center"> <el-table-column prop="id" label="选择" width="80" align="center">
<template #default="{ row }"> <template #default="{ row }">
<el-checkbox v-model="row.checked" @change="handleDangerChange(row)" /> <el-checkbox v-model="row.checked" @change="handleDangerChange(row)" />
@@ -123,6 +140,7 @@
</el-table> </el-table>
</el-form-item> </el-form-item>
<!-- 总分显示 -->
<el-form-item <el-form-item
style="text-align: center; margin-bottom: 0px; padding: 0px" style="text-align: center; margin-bottom: 0px; padding: 0px"
class="changeMajorFromItem" class="changeMajorFromItem"
@@ -135,6 +153,7 @@
</el-row> </el-row>
</el-form-item> </el-form-item>
<!-- 护理措施表格 -->
<el-form-item style="padding-top: 10px"> <el-form-item style="padding-top: 10px">
<el-table <el-table
:data="nursingData" :data="nursingData"
@@ -142,6 +161,7 @@
:span-method="arraySpanMethod" :span-method="arraySpanMethod"
style="width: 100%" style="width: 100%"
> >
<!-- 动态生成表格列 -->
<el-table-column <el-table-column
v-for="column in nursingColumns" v-for="column in nursingColumns"
:key="column.key" :key="column.key"
@@ -150,6 +170,7 @@
:label="column.title" :label="column.title"
align="center" align="center"
/> />
<!-- 选择列复选框 -->
<el-table-column prop="id" label="选择" width="80" align="center"> <el-table-column prop="id" label="选择" width="80" align="center">
<template #default="{ row }"> <template #default="{ row }">
<el-checkbox v-model="row.checked" @change="handleNursingChange(row)" /> <el-checkbox v-model="row.checked" @change="handleNursingChange(row)" />
@@ -158,6 +179,7 @@
</el-table> </el-table>
</el-form-item> </el-form-item>
<!-- 护士签字输入框 -->
<el-form-item <el-form-item
style="text-align: center; margin-bottom: 0px; padding: 0px" style="text-align: center; margin-bottom: 0px; padding: 0px"
class="changeMajorFromItem" class="changeMajorFromItem"
@@ -177,6 +199,7 @@
</el-row> </el-row>
</el-form-item> </el-form-item>
<!-- 备注信息 -->
<el-form-item> <el-form-item>
<el-row :span="20"> <el-row :span="20">
<el-col :span="5"> <el-col :span="5">
@@ -197,22 +220,24 @@
</template> </template>
<script setup> <script setup>
// 组件选项定义
defineOptions({ defineOptions({
name: 'FallBedFallAssessment', name: '跌倒/坠床评估护理记录单',
}); });
// 导入所需模块
import { ref, reactive, computed, onMounted } from 'vue'; import { ref, reactive, computed, onMounted } from 'vue';
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
// import { webapp_ws_ajax_run, urlAddRandomNo } from '@/utils/grwebapp'; // 使用路由相关功能
// import { useRoute, useRouter } from 'vue-router';
// 响应式数据
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
// 定义引用变量
const queryRef = ref(); const queryRef = ref();
const formRef = ref(); const formRef = ref();
// 基本数据变量
const wardCode = ref(''); const wardCode = ref('');
const patientId = ref(''); const patientId = ref('');
const visitId = ref(''); const visitId = ref('');
@@ -226,17 +251,18 @@ const totalScore = ref(0);
const lastSubmit = ref(''); const lastSubmit = ref('');
const admissionDataForm = ref(route.params.admissionData); const admissionDataForm = ref(route.params.admissionData);
// 表单数据模型
const form = reactive({ const form = reactive({
ZKDATE: '', ZKDATE: '', // 日期
ZKTIME: '', ZKTIME: '', // 时间
recordTime: '', recordTime: '', // 记录时间
totalScore: 0, totalScore: 0, // 总分
bedFallRiskAssessmentList: [], bedFallRiskAssessmentList: [], // 跌倒风险评估列表
nurseSignature: '', nurseSignature: '', // 护士签名
patientCareSessionsCheckedList: [], patientCareSessionsCheckedList: [], // 护理措施选中列表
}); });
// 危险因素表格列 // 危险因素表格列配置
const dangerColumns = [ const dangerColumns = [
{ {
key: 'content', key: 'content',
@@ -301,7 +327,7 @@ const dangerData = ref([
{ id: '27', evalContent: '麻醉止痛剂', score: 2, checked: false }, { id: '27', evalContent: '麻醉止痛剂', score: 2, checked: false },
]); ]);
// 护理措施表格列 // 护理措施表格列配置
const nursingColumns = [ const nursingColumns = [
{ {
key: 'content', key: 'content',
@@ -338,21 +364,21 @@ const instructions = [
'3.评分≥5高度风险每周至少评估一次需采取适宜的预防措施同时填写《预防患者跌倒/坠床知情告知书》', '3.评分≥5高度风险每周至少评估一次需采取适宜的预防措施同时填写《预防患者跌倒/坠床知情告知书》',
]; ];
// 计算属性 // 计算属性:计算选中的危险因素总分
const calculate = computed(() => { const calculate = computed(() => {
return dangerData.value return dangerData.value
.filter((option) => option.checked) .filter((option) => option.checked)
.reduce((total, option) => total + option.score, 0); .reduce((total, option) => total + option.score, 0);
}); });
// 计算属性:判断表单是否为空
const isFormEmpty = computed(() => { const isFormEmpty = computed(() => {
return ( return (
form.ZKDATE === '' && form.ZKTIME === '' && form.recordTime === '' && form.nurseSignature === '' form.ZKDATE === '' && form.ZKTIME === '' && form.recordTime === '' && form.nurseSignature === ''
); );
}); });
// 方法 - 不再需要handleData方法通过表单输入和按钮加载数据 // 危险因素选择变化处理函数
const handleDangerChange = (row) => { const handleDangerChange = (row) => {
totalScore.value = calculate.value; totalScore.value = calculate.value;
form.bedFallRiskAssessmentList = dangerData.value form.bedFallRiskAssessmentList = dangerData.value
@@ -360,12 +386,14 @@ const handleDangerChange = (row) => {
.map((item) => item.id); .map((item) => item.id);
}; };
// 护理措施选择变化处理函数
const handleNursingChange = (row) => { const handleNursingChange = (row) => {
form.patientCareSessionsCheckedList = nursingData.value form.patientCareSessionsCheckedList = nursingData.value
.filter((item) => item.checked) .filter((item) => item.checked)
.map((item) => item.id); .map((item) => item.id);
}; };
// 初始化函数:加载模拟数据
const init = async () => { const init = async () => {
// 使用模拟数据不再调用后端API // 使用模拟数据不再调用后端API
try { try {
@@ -427,6 +455,7 @@ const init = async () => {
} }
}; };
// 危险因素表格合并单元格处理函数
const handleSpan = ({ row, column, rowIndex, columnIndex }) => { const handleSpan = ({ row, column, rowIndex, columnIndex }) => {
if (columnIndex === 0) { if (columnIndex === 0) {
if (rowIndex === 0) { if (rowIndex === 0) {
@@ -473,6 +502,7 @@ const handleSpan = ({ row, column, rowIndex, columnIndex }) => {
return [1, 1]; return [1, 1];
}; };
// 护理措施表格合并单元格处理函数
const arraySpanMethod = ({ row, column, rowIndex, columnIndex }) => { const arraySpanMethod = ({ row, column, rowIndex, columnIndex }) => {
// 护理措施 // 护理措施
if (columnIndex === 0) { if (columnIndex === 0) {
@@ -489,8 +519,9 @@ const arraySpanMethod = ({ row, column, rowIndex, columnIndex }) => {
return [1, 1]; return [1, 1];
}; };
// 提交表单处理函数
const onSubmit = async () => { const onSubmit = async () => {
// 检查上次提交时间 // 检查上次提交时间,防止重复提交
if (lastSubmit.value && new Date() - lastSubmit.value < 2000) { if (lastSubmit.value && new Date() - lastSubmit.value < 2000) {
ElMessage.error('禁止重复提交!'); ElMessage.error('禁止重复提交!');
return; return;
@@ -562,6 +593,7 @@ const onSubmit = async () => {
} }
}; };
// 编辑记录处理函数
const handleUpdate = (row) => { const handleUpdate = (row) => {
const loginUser = JSON.parse(window.localStorage.getItem('loginUser')); const loginUser = JSON.parse(window.localStorage.getItem('loginUser'));
@@ -591,6 +623,7 @@ const handleUpdate = (row) => {
} }
}; };
// 重置表单函数
const reset = () => { const reset = () => {
Object.assign(form, { Object.assign(form, {
ZKDATE: '', ZKDATE: '',
@@ -623,6 +656,7 @@ const reset = () => {
} }
}; };
// 删除记录处理函数
const handleDelete = (row) => { const handleDelete = (row) => {
const loginUser = JSON.parse(window.localStorage.getItem('loginUser')); const loginUser = JSON.parse(window.localStorage.getItem('loginUser'));
@@ -646,6 +680,7 @@ const handleDelete = (row) => {
} }
}; };
// 打印预览函数(暂未实现)
const dc_ajax_preview = () => { const dc_ajax_preview = () => {
var args = { var args = {
report: urlAddRandomNo('./grf/NurseRecord_Pressure_208.grf'), report: urlAddRandomNo('./grf/NurseRecord_Pressure_208.grf'),
@@ -656,6 +691,7 @@ const dc_ajax_preview = () => {
webapp_ws_ajax_run(args); webapp_ws_ajax_run(args);
}; };
// 数据转换函数,用于报表打印
const transformData = () => { const transformData = () => {
const jsonDate = [...tableDataSource.value]; const jsonDate = [...tableDataSource.value];
@@ -802,7 +838,7 @@ const transformData = () => {
return transformedData; return transformedData;
}; };
// 生命周期钩子 // 组件挂载后执行的生命周期函数
onMounted(() => { onMounted(() => {
try { try {
// 安全获取用户信息 // 安全获取用户信息
@@ -831,6 +867,7 @@ onMounted(() => {
</script> </script>
<style scoped> <style scoped>
/* 页面样式定义 */
.business { .business {
background: white; background: white;
border-radius: 5px; border-radius: 5px;
@@ -894,4 +931,10 @@ onMounted(() => {
margin-bottom: 0px !important; margin-bottom: 0px !important;
} }
} }
/* 备注信息列表样式 */
.instructions-list {
list-style-type: none;
padding-left: 0;
}
</style> </style>

View File

@@ -1,17 +1,42 @@
// 动态引入 template 目录下的所有 .vue 文件 /**
* 模板组件注册模块
* 动态引入 template 目录下的所有 .vue 文件,并将它们注册为全局组件
*/
// 动态引入 template 目录下的所有 .vue 文件(包括中文命名的文件)
// 使用 { eager: true } 表示立即加载所有匹配的文件
const templates = import.meta.glob('./*.vue', { eager: true }); const templates = import.meta.glob('./*.vue', { eager: true });
// 存储所有加载的组件
const components = []; const components = [];
// 遍历所有引入的文件 // 遍历所有引入的文件
for (const path in templates) { for (const path in templates) {
try {
// 获取组件的默认导出
const component = templates[path].default; const component = templates[path].default;
// 检查组件是否有 name 属性,如果没有则跳过
if (component && component.name) {
components.push(component); components.push(component);
} else {
console.warn(`组件 ${path} 缺少 name 属性,将不会被注册`);
} }
} catch (error) {
console.error(`加载组件 ${path} 时出错:`, error);
}
}
/**
* 注册所有组件到 Vue 应用实例
* @param {Object} app - Vue 应用实例
*/
const registerComponents = (app) => { const registerComponents = (app) => {
components.forEach((component) => { components.forEach((component) => {
// 使用组件的 name 属性作为组件名称进行注册
app.component(component.name, component); app.component(component.name, component);
}) });
} };
export { components, registerComponents };
// 导出组件数组和注册函数
export { components, registerComponents };

View File

@@ -5,13 +5,11 @@
--> -->
<template> <template>
<div class="container"> <div class="container">
<!-- 页面头部标题 -->
<div class="header"> <div class="header">
<h2 class="title">乾安县人民医院</h2> <h2 class="title">乾安县人民医院</h2>
<h3 class="subtitle">患者护理记录单</h3> <h3 class="subtitle">患者护理记录单</h3>
</div> </div>
<!-- 护理记录表单 -->
<el-form :model="state.formData" label-position="top" class="nursing-form"> <el-form :model="state.formData" label-position="top" class="nursing-form">
<!-- 患者基本信息 --> <!-- 患者基本信息 -->
<div class="patient-info"> <div class="patient-info">
@@ -60,11 +58,9 @@
</el-row> </el-row>
</div> </div>
<!-- 生命体征记录表格 --> <!-- 基本信息记录表格 -->
<div class="vital-signs-table"> <div class="vital-signs-table">
<!-- 护理记录详细信息表格 -->
<el-table :data="state.formData.vitalSigns" border style="width: 100%"> <el-table :data="state.formData.vitalSigns" border style="width: 100%">
<!-- 记录日期列 -->
<el-table-column label="日期" width="100"> <el-table-column label="日期" width="100">
<template #default="scope"> <template #default="scope">
<el-date-picker <el-date-picker
@@ -77,7 +73,6 @@
></el-date-picker> ></el-date-picker>
</template> </template>
</el-table-column> </el-table-column>
<!-- 记录时间列 -->
<el-table-column label="时间" width="100"> <el-table-column label="时间" width="100">
<template #default="scope"> <template #default="scope">
<el-time-picker <el-time-picker
@@ -89,9 +84,7 @@
></el-time-picker> ></el-time-picker>
</template> </template>
</el-table-column> </el-table-column>
<!-- 基本信息列组 -->
<el-table-column label="基本信息"> <el-table-column label="基本信息">
<!-- 意识状态 -->
<el-table-column label="意识" width="80"> <el-table-column label="意识" width="80">
<template #default="scope"> <template #default="scope">
<el-select v-model="scope.row.consciousness" placeholder="选择"> <el-select v-model="scope.row.consciousness" placeholder="选择">
@@ -101,46 +94,38 @@
</el-select> </el-select>
</template> </template>
</el-table-column> </el-table-column>
<!-- 体温测量值 -->
<el-table-column label="体温℃" width="80"> <el-table-column label="体温℃" width="80">
<template #default="scope"> <template #default="scope">
<el-input v-model="scope.row.temperature" placeholder="体温"></el-input> <el-input v-model="scope.row.temperature" placeholder="体温"></el-input>
</template> </template>
</el-table-column> </el-table-column>
<!-- 心率测量值 -->
<el-table-column label="心率次/分" width="100"> <el-table-column label="心率次/分" width="100">
<template #default="scope"> <template #default="scope">
<el-input v-model="scope.row.heartRate" placeholder="心率"></el-input> <el-input v-model="scope.row.heartRate" placeholder="心率"></el-input>
</template> </template>
</el-table-column> </el-table-column>
<!-- 脉搏测量值 -->
<el-table-column label="脉搏次/分" width="100"> <el-table-column label="脉搏次/分" width="100">
<template #default="scope"> <template #default="scope">
<el-input v-model="scope.row.heartRate" placeholder="心率"></el-input> <el-input v-model="scope.row.heartRate" placeholder="心率"></el-input>
</template> </template>
</el-table-column> </el-table-column>
<!-- 呼吸频率 -->
<el-table-column label="呼吸次/分" width="100"> <el-table-column label="呼吸次/分" width="100">
<template #default="scope"> <template #default="scope">
<el-input v-model="scope.row.respiratoryRate" placeholder="呼吸"></el-input> <el-input v-model="scope.row.respiratoryRate" placeholder="呼吸"></el-input>
</template> </template>
</el-table-column> </el-table-column>
<!-- 血压测量值 -->
<el-table-column label="血压mmHg" width="120"> <el-table-column label="血压mmHg" width="120">
<template #default="scope"> <template #default="scope">
<el-input v-model="scope.row.bloodPressure" placeholder="血压"></el-input> <el-input v-model="scope.row.bloodPressure" placeholder="血压"></el-input>
</template> </template>
</el-table-column> </el-table-column>
<!-- 血氧饱和度 -->
<el-table-column label="血氧饱和度" width="120"> <el-table-column label="血氧饱和度" width="120">
<template #default="scope"> <template #default="scope">
<el-input v-model="scope.row.bloodPressure" placeholder="血压"></el-input> <el-input v-model="scope.row.bloodPressure" placeholder="血压"></el-input>
</template> </template>
</el-table-column> </el-table-column>
</el-table-column> </el-table-column>
<!-- 氧疗相关信息 -->
<el-table-column label="氧疗L/min" width="200"> <el-table-column label="氧疗L/min" width="200">
<!-- 氧疗方式 -->
<el-table-column label="方式" > <el-table-column label="方式" >
<template #default="scope"> <template #default="scope">
<el-select v-model="scope.row.intake" placeholder="选择"> <el-select v-model="scope.row.intake" placeholder="选择">
@@ -150,16 +135,13 @@
</el-select> </el-select>
</template> </template>
</el-table-column> </el-table-column>
<!-- 氧流量 -->
<el-table-column label="流量" width="80"> <el-table-column label="流量" width="80">
<template #default="scope"> <template #default="scope">
<el-input v-model="scope.row.flowRate" placeholder="流量"></el-input> <el-input v-model="scope.row.flowRate" placeholder="流量"></el-input>
</template> </template>
</el-table-column> </el-table-column>
</el-table-column> </el-table-column>
<!-- 入量记录 -->
<el-table-column label="入量" width="200"> <el-table-column label="入量" width="200">
<!-- 入量名称 -->
<el-table-column label="名称" > <el-table-column label="名称" >
<template #default="scope"> <template #default="scope">
<el-select v-model="scope.row.intake" placeholder="选择"> <el-select v-model="scope.row.intake" placeholder="选择">
@@ -169,22 +151,18 @@
</el-select> </el-select>
</template> </template>
</el-table-column> </el-table-column>
<!-- 入量毫升数 -->
<el-table-column label="ml" width="80"> <el-table-column label="ml" width="80">
<template #default="scope"> <template #default="scope">
<el-input v-model="scope.row.flowRate" placeholder="流量"></el-input> <el-input v-model="scope.row.flowRate" placeholder="流量"></el-input>
</template> </template>
</el-table-column> </el-table-column>
<!-- 入量途径 -->
<el-table-column label="途径" width="80"> <el-table-column label="途径" width="80">
<template #default="scope"> <template #default="scope">
<el-input v-model="scope.row.flowRate" placeholder="流量"></el-input> <el-input v-model="scope.row.flowRate" placeholder="流量"></el-input>
</template> </template>
</el-table-column> </el-table-column>
</el-table-column> </el-table-column>
<!-- 出量记录 -->
<el-table-column label="出量" width="200"> <el-table-column label="出量" width="200">
<!-- 出量名称 -->
<el-table-column label="名称" > <el-table-column label="名称" >
<template #default="scope"> <template #default="scope">
<el-select v-model="scope.row.intake" placeholder="选择"> <el-select v-model="scope.row.intake" placeholder="选择">
@@ -194,38 +172,32 @@
</el-select> </el-select>
</template> </template>
</el-table-column> </el-table-column>
<!-- 出量毫升数 -->
<el-table-column label="ml" width="80"> <el-table-column label="ml" width="80">
<template #default="scope"> <template #default="scope">
<el-input v-model="scope.row.flowRate" placeholder="流量"></el-input> <el-input v-model="scope.row.flowRate" placeholder="流量"></el-input>
</template> </template>
</el-table-column> </el-table-column>
</el-table-column> </el-table-column>
<!-- 皮肤情况记录 -->
<el-table-column label="皮肤情况" width="80"> <el-table-column label="皮肤情况" width="80">
<template #default="scope"> <template #default="scope">
<el-input v-model="scope.row.flowRate" placeholder="流量"></el-input> <el-input v-model="scope.row.flowRate" placeholder="流量"></el-input>
</template> </template>
</el-table-column> </el-table-column>
<!-- 管路护理记录 -->
<el-table-column label="管路护理" width="80"> <el-table-column label="管路护理" width="80">
<template #default="scope"> <template #default="scope">
<el-input v-model="scope.row.flowRate" placeholder="流量"></el-input> <el-input v-model="scope.row.flowRate" placeholder="流量"></el-input>
</template> </template>
</el-table-column> </el-table-column>
<!-- 病情与措施记录 -->
<el-table-column label="病情与措施" width="80"> <el-table-column label="病情与措施" width="80">
<template #default="scope"> <template #default="scope">
<el-input v-model="scope.row.flowRate" placeholder="流量"></el-input> <el-input v-model="scope.row.flowRate" placeholder="流量"></el-input>
</template> </template>
</el-table-column> </el-table-column>
<!-- 护士签名 -->
<el-table-column label="护士签名" width="100"> <el-table-column label="护士签名" width="100">
<template #default="scope"> <template #default="scope">
<el-input v-model="scope.row.nurseSignature" placeholder="签名"></el-input> <el-input v-model="scope.row.nurseSignature" placeholder="签名"></el-input>
</template> </template>
</el-table-column> </el-table-column>
<!-- 操作列提供删除功能 -->
<el-table-column label="操作" width="120" fixed="right"> <el-table-column label="操作" width="120" fixed="right">
<template #default="scope"> <template #default="scope">
<el-button type="danger" size="small" @click="removeVitalSign(scope.$index)" <el-button type="danger" size="small" @click="removeVitalSign(scope.$index)"
@@ -234,13 +206,12 @@
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<!-- 添加新记录按钮 -->
<div class="add-row"> <div class="add-row">
<el-button type="primary" @click="addVitalSign">添加记录</el-button> <el-button type="primary" @click="addVitalSign">添加记录</el-button>
</div> </div>
</div> </div>
<!-- 表单底部说明信息 --> <!-- 表单底部按钮 -->
<div class="form-actions"> <div class="form-actions">
<div> <div>
意识:①清醒②嗜睡③意识模糊④昏睡⑤谗妄⑥浅昏迷⑦中度昏迷⑧深昏迷⑨全麻未醒⑩镇静 意识:①清醒②嗜睡③意识模糊④昏睡⑤谗妄⑥浅昏迷⑦中度昏迷⑧深昏迷⑨全麻未醒⑩镇静
@@ -260,21 +231,12 @@
</template> </template>
<script setup> <script setup>
// 定义组件选项
defineOptions({ defineOptions({
name: 'NursingRecordSheet', name: 'NursingRecordSheet',
}); });
import { getCurrentInstance, onBeforeMount, onMounted, reactive } from 'vue';
// 导入所需Vue功能
import { getCurrentInstance, onBeforeMount, onMounted, reactive, ref } from 'vue';
// 获取组件实例代理
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
// 定义组件发射事件
const emits = defineEmits([]); const emits = defineEmits([]);
// 定义组件接收的属性
const props = defineProps({ const props = defineProps({
patientId: { patientId: {
type: String, type: String,
@@ -282,28 +244,28 @@ const props = defineProps({
}, },
}); });
// 表单数据状态管理 // 表单数据
const state = ref({ const state = ref({
formData: { formData: {
name: '', // 患者姓名 name: '',
age: '', // 年龄 age: '',
gender: '', // 性别 gender: '',
ward: '', // 病区 ward: '',
bedNumber: '', // 床号 bedNumber: '',
hospitalNumber: '', // 住院号 hospitalNumber: '',
diagnosis: '', // 入院诊断 diagnosis: '',
vitalSigns: [ // 生命体征记录数组 vitalSigns: [
{ {
date: new Date().toISOString().split('T')[0], // 默认当天日期 date: new Date().toISOString().split('T')[0],
time: new Date().toTimeString().slice(0, 5), // 默认当前时间 time: new Date().toTimeString().slice(0, 5),
consciousness: '清醒', // 意识状态默认值 consciousness: '清醒',
temperature: '', // 体温 temperature: '',
heartRate: '', // 心率 heartRate: '',
respiratoryRate: '', // 呼吸频率 respiratoryRate: '',
bloodPressure: '', // 血压 bloodPressure: '',
intake: '', // 入量 intake: '',
flowRate: '', // 流量 flowRate: '',
nurseSignature: '', // 护士签名 nurseSignature: '',
}, },
], ],
}, },
@@ -311,7 +273,7 @@ const state = ref({
}); });
// 添加生命体征记录方法 // 添加生命体征记录
const addVitalSign = () => { const addVitalSign = () => {
state.value.formData.vitalSigns.push({ state.value.formData.vitalSigns.push({
date: new Date().toISOString().split('T')[0], date: new Date().toISOString().split('T')[0],
@@ -328,16 +290,17 @@ const addVitalSign = () => {
}); });
}; };
// 删除指定索引的生命体征记录 // 删除生命体征记录
const removeVitalSign = (index) => { const removeVitalSign = (index) => {
state.value.formData.vitalSigns.splice(index, 1); state.value.formData.vitalSigns.splice(index, 1);
// 如果删除后没有记录,则自动添加一条空记录
if (state.value.formData.vitalSigns.length === 0) { if (state.value.formData.vitalSigns.length === 0) {
addVitalSign(); addVitalSign();
} }
}; };
// 重置整个表单数据
// 重置表单
const resetForm = () => { const resetForm = () => {
state.value.formData = { state.value.formData = {
name: '', name: '',
@@ -352,44 +315,34 @@ const resetForm = () => {
}; };
// 组件挂载前执行的逻辑
onBeforeMount(() => { onBeforeMount(() => {
// 如果有传入患者ID可以在此处加载患者数据 // 如果有patientId可以在这里加载患者数据
if (props.patientId) { if (props.patientId) {
// 加载患者数据的逻辑 // 加载患者数据的逻辑
} }
}); });
// 组件挂载完成后执行的逻辑
onMounted(() => { onMounted(() => {
// 组件挂载后的逻辑 // 组件挂载后的逻辑
}); });
// 表单提交方法
const submit = () => { const submit = () => {
// 触发submitOk事件传递表单数据给父组件 // ElMessage.success('提交成功');
emits('submitOk', state.formData); emits('submitOk', state.formData);
}; };
// 设置表单数据方法(供父组件调用)
const setFormData = (data) => { const setFormData = (data) => {
if (data) { if (data) {
state.value.formData = data; state.value.formData = data;
} }
}; };
// 暴露组件内部属性和方法给父组件使用
defineExpose({ state, submit, setFormData }); defineExpose({ state, submit, setFormData });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
// 容器样式
.container { .container {
padding: 20px; padding: 20px;
background-color: #fff; background-color: #fff;
} }
// 头部标题样式
.header { .header {
text-align: center; text-align: center;
margin-bottom: 20px; margin-bottom: 20px;
@@ -406,7 +359,6 @@ defineExpose({ state, submit, setFormData });
} }
} }
// 护理表单样式
.nursing-form { .nursing-form {
.patient-info { .patient-info {
padding: 15px; padding: 15px;

View File

@@ -64,13 +64,14 @@
value-format="YYYY-MM-DD" value-format="YYYY-MM-DD"
style="width: 100%" style="width: 100%"
/> />
<!-- <el-input v-model="formData.onsetDate" type="date" /> -->
</el-form-item> </el-form-item>
</div> </div>
</el-form-item> </el-form-item>
<!-- 病史信息区域标题 --> <!-- 病史信息区域标题 -->
<h4 class="section-title">病史信息</h4> <h4 class="section-title">病史信息</h4>
<!-- 2. 病史信息单行自适应排列 --> <!-- 2. 病史信息单行自适应排列新增调整 -->
<el-form-item class="form-section"> <el-form-item class="form-section">
<div class="single-row-layout"> <div class="single-row-layout">
<!-- 现病史输入项 --> <!-- 现病史输入项 -->
@@ -180,6 +181,14 @@ defineOptions({
components: { ElInput, ElMessage, ElForm, ElFormItem }, components: { ElInput, ElMessage, ElForm, ElFormItem },
}); });
// // Props与事件,去掉props.patientInfo改为直接从store获取
// const props = defineProps({
// patientInfo: {
// type: Object,
// required: true,
// },
// });
// 定义组件接收的属性(目前为空) // 定义组件接收的属性(目前为空)
const props = defineProps({}); const props = defineProps({});

View File

@@ -1,21 +1,50 @@
// 导入 API 函数,用于从服务器获取带有选项列表的数据
import { getListWithOptionList } from '@/views/basicmanage/caseTemplatesStatistics/api'; import { getListWithOptionList } from '@/views/basicmanage/caseTemplatesStatistics/api';
// 导入 Vue 3 的组合式 APIonMounted组件挂载后执行和 ref响应式数据
import { onMounted, ref } from 'vue'; import { onMounted, ref } from 'vue';
// 创建响应式数据:统计选项列表,初始为空数组
const statisticsOptionList = ref([]); const statisticsOptionList = ref([]);
/**
* 初始化统计选项列表数据
* 异步函数,通过 API 获取数据并更新到响应式变量中
*/
const initStatic = async () => { const initStatic = async () => {
try { try {
// 调用 API 获取数据
const res = await getListWithOptionList(); const res = await getListWithOptionList();
// 将获取到的数据赋值给响应式变量
statisticsOptionList.value = res.data; statisticsOptionList.value = res.data;
} catch (error) { } catch (error) {
// 错误处理:打印错误信息到控制台
console.log(error); console.log(error);
} }
}; };
/**
* Vue 3 组合式函数:用于获取和管理统计选项列表
* @returns {Object} 返回包含响应式数据和方法的对象
*/
export default function useOptionsList() { export default function useOptionsList() {
// 组件挂载后自动初始化数据
onMounted(() => {
initStatic(); initStatic();
});
/**
* 根据代码获取对应的选项列表
* @param {string} code - 统计类型代码
* @returns {Array} 返回匹配的选项列表,如果没有匹配则返回空数组
*/
const getStatisticsOptionList = (code) => { const getStatisticsOptionList = (code) => {
// 在统计选项列表中查找匹配代码的项,然后返回其 optionList 属性,如果没有找到则返回空数组
return statisticsOptionList.value.find((item) => item.code === code)?.optionList || []; return statisticsOptionList.value.find((item) => item.code === code)?.optionList || [];
}; };
// 返回响应式数据和方法供组件使用
return { return {
statisticsOptionList, statisticsOptionList, // 完整的统计选项列表
getStatisticsOptionList, getStatisticsOptionList, // 根据代码获取选项列表的方法
}; };
} }

View File

@@ -1,7 +1,7 @@
<template> <template>
<div class="template-content"> <div class="template-content">
<div class="template-header"> <div class="template-header">
<h3>股骨头坏死(模板1)</h3> <h3>股骨头坏死(模板11111111)</h3>
</div> </div>
<div class="template-body"> <div class="template-body">
<p>主诉左侧髋部疼痛X个月加重1周</p> <p>主诉左侧髋部疼痛X个月加重1周</p>
@@ -17,7 +17,7 @@
<script setup> <script setup>
defineOptions({ defineOptions({
name: 'Template1' name: '股骨头坏死(模板11111111)'
}) })
// 可以在这里添加组件逻辑 // 可以在这里添加组件逻辑
</script> </script>

View File

@@ -85,7 +85,6 @@
</div> </div>
</template> </template>
<script setup lang='ts'> <script setup lang='ts'>
import { is } from 'core-js/core/object'
import { getCurrentInstance, onBeforeMount, onMounted, reactive,ref } from 'vue' import { getCurrentInstance, onBeforeMount, onMounted, reactive,ref } from 'vue'
// const { proxy } = getCurrentInstance(); // const { proxy } = getCurrentInstance();
const emits = defineEmits([]) const emits = defineEmits([])

View File

@@ -234,7 +234,8 @@ onMounted(() => {
} }
// 获取医疗机构列表 // 获取医疗机构列表
getUserBindTenantList().then((res) => { if (loginForm.value.username) {
getUserBindTenantList(loginForm.value.username).then((res) => {
tenantOptions.value = res.data.map(item => ({ tenantOptions.value = res.data.map(item => ({
label: item.tenantName, label: item.tenantName,
value: item.id value: item.id
@@ -245,6 +246,7 @@ onMounted(() => {
currentTenantName.value = tenantOptions.value[0].label; currentTenantName.value = tenantOptions.value[0].label;
} }
}); });
}
}); });
function handleLogin() { function handleLogin() {
@@ -476,7 +478,10 @@ function handleUserName(value) {
//getCode(); //getCode();
getCookie(); getCookie();
// 只有当 username 存在时才获取租户列表
if (loginForm.value.username) {
getTenantList(loginForm.value.username); getTenantList(loginForm.value.username);
}
</script> </script>
<style> <style>

View File

@@ -0,0 +1,25 @@
// 测试util._extend是否存在
if (typeof process !== 'undefined' && process.versions && process.versions.node) {
try {
const util = require('util');
console.log('util._extend存在吗', typeof util._extend);
if (typeof util._extend === 'function') {
console.log('util._extend是一个函数');
} else {
console.log('util._extend不是一个函数添加兼容实现');
util._extend = function(destination, source) {
for (var key in source) {
if (source.hasOwnProperty(key)) {
destination[key] = source[key];
}
}
return destination;
};
console.log('兼容实现添加成功');
}
} catch (e) {
console.error('util模块加载失败:', e);
}
} else {
console.log('不在Node.js环境中');
}