Merge branch 'addwork'

This commit is contained in:
jiangs 2025-07-23 16:59:25 +08:00
commit 0b3047f469
19 changed files with 2351 additions and 12 deletions

View File

@ -8,6 +8,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="icon" href="/favicon.ico">
<title>实验室检验系统</title>
<!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]-->
<style>
html,

View File

@ -21,14 +21,18 @@
"element-plus": "2.4.3",
"file-saver": "2.0.5",
"fuse.js": "6.6.2",
"jquery": "^3.7.1",
"js-beautify": "^1.14.11",
"js-cookie": "3.0.5",
"jsencrypt": "3.3.2",
"nprogress": "0.2.0",
"pinia": "2.1.7",
"pinyin-pro": "^3.26.0",
"select2": "^4.1.0-rc.0",
"vue": "3.4.0",
"vue-cropper": "1.1.1",
"vue-router": "4.2.5",
"vue3-select2-component": "^0.1.7",
"vuedraggable": "^4.1.0"
},
"devDependencies": {

View File

@ -8,7 +8,6 @@ export function queryComDictListService(query) {
params: query
})
}
//增加字典数据
export function addComDictService(data) {
return request({
@ -25,4 +24,15 @@ export function updateComDictService(data) {
method: 'post',
data
})
}
}
// 根据字典类型查询字典数据信息
export function getComDicts(zdlb) {
return request({
url: '/comdict/getComDicts',
method: 'get',
params: zdlb
})
}

View File

@ -0,0 +1,18 @@
import request from '@/utils/request'
// 查询字典数据列表
export function querylabInstrList(query) {
return request({
url: '/instr/query',
method: 'get',
params: query
})
}
// 查询字典数据列表
export function querylabInstrListByLisgroup(query) {
return request({
url: '/instr/querybylisgroup',
method: 'get',
params: query
})
}

View File

@ -0,0 +1,59 @@
import request from '@/utils/request'
// 查询数据列表
export function queryLabPatList(query) {
return request({
url: '/liswork/samplelist',
method: 'get',
params: query
})
}
// 查询数据
export function queryLabPat(query) {
return request({
url: '/liswork/sampleinfo',
method: 'get',
params: query
})
}
// 查询服务器时间
export function getDate() {
return request({
url: '/liswork/getdate',
method: 'get',
})
}
//增加字典数据
export function addLabPatService(data) {
return request({
url: '/liswork/add',
method: 'post',
data
})
}
//修改字典数据
export function updateLabPatService(data) {
return request({
url: '/liswork/update',
method: 'post',
data
})
}
// 查询数据列表
export function queryLabResults(query) {
return request({
url: '/liswork/resultinfo',
method: 'get',
params: query
})
}
// 批量删除结果
export function deleteresult(data) {
return request({
url: '/liswork/deleteresult',
method: 'post',
data: data
})
}

44
src/api/mzcx/cydj.js Normal file
View File

@ -0,0 +1,44 @@
import request from '@/utils/request'
// 查询采样登记列表
export function querySQD(query) {
return request({
url: '/mzcx/querySQD',
method: 'get',
params: query
})
}
// 查询采样登记详细
export function getReqmain(sqh) {
return request({
url: '/system/reqmain/' + sqh,
method: 'get'
})
}
// 新增采样登记
export function addReqmain(data) {
return request({
url: '/system/reqmain',
method: 'post',
data: data
})
}
// 修改采样登记
export function updateReqmain(data) {
return request({
url: '/system/reqmain',
method: 'put',
data: data
})
}
// 删除采样登记
export function delReqmain(sqh) {
return request({
url: '/system/reqmain/' + sqh,
method: 'delete'
})
}

43
src/api/pinyin.js Normal file
View File

@ -0,0 +1,43 @@
// pinyin.js - 拼音转换工具
// src/utils/pinyin-utils.js
import { pinyin } from 'pinyin-pro';
/**
* 获取文本的拼音首字母
* @param {string} text - 要转换的文本
* @returns {string} - 拼音首字母字符串
*/
export function getFirstLetter(text) {
if (!text) return '';
// 获取拼音(不带音调,数组形式)
const pinyinArray = pinyin(text, { toneType: "none", type: "array" });
// 提取每个拼音的首字母并连接
return pinyinArray.map(word => word.charAt(0)).join('');
}
/**
* 获取文本的拼音全拼
* @param {string} text - 要转换的文本
* @returns {string} - 拼音全拼字符串
*/
export function getFullPinyin(text) {
if (!text) return '';
// 获取拼音(不带音调,字符串形式)
return pinyin(text, { toneType: "none" }).replace(/\s+/g, '');
}
/**
* 处理选项数据,添加拼音和首字母属性
* @param {Array} options - 原始选项数组,每个元素包含id和text属性
* @returns {Array} - 处理后的选项数组,每个元素包含pinyin和firstLetters属性
*/
export function processOptions(options) {
return options.map(option => ({
...option,
pinyin: getFullPinyin(option.text),
firstLetters: getFirstLetter(option.text)
}));
}

View File

@ -7,6 +7,11 @@ import 'element-plus/dist/index.css'
import locale from 'element-plus/es/locale/lang/zh-cn'
import '@/assets/styles/index.scss' // global css
// 先导入 jQuery 并设置全局变量
import * as $ from 'jquery';
window.jQuery = $;
window.$ = $;
import App from './App'
import store from './store'
@ -24,7 +29,7 @@ import elementIcons from '@/components/SvgIcon/svgicon'
import './permission' // permission control
import { useDict } from '@/utils/dict'
import {useDict, comDict} from '@/utils/dict'
import { parseTime, resetForm, addDateRange, handleTree, selectDictLabel, selectDictLabels } from '@/utils/ruoyi'
// 分页组件
@ -47,6 +52,7 @@ import DictTag from '@/components/DictTag'
const app = createApp(App)
// 全局方法挂载
app.config.globalProperties.useDict = useDict
app.config.globalProperties.download = download
app.config.globalProperties.parseTime = parseTime
@ -66,12 +72,14 @@ app.component('ImagePreview', ImagePreview)
app.component('RightToolbar', RightToolbar)
app.component('Editor', Editor)
//VUE3标准方法注入全局方法
app.provide('comDict', comDict);
app.use(router)
app.use(store)
app.use(plugins)
app.use(elementIcons)
app.component('svg-icon', SvgIcon)
directive(app)
// 使用element-plus 并且设置全局的大小

View File

@ -1,6 +1,6 @@
import useDictStore from '@/store/modules/dict'
import { getDicts } from '@/api/system/dict/data'
import { getComDicts } from '@/api/liswork/dict/ComDict.js'
/**
* 获取字典数据
*/
@ -21,4 +21,45 @@ export function useDict(...args) {
})
return toRefs(res.value);
})()
}
/**
* 获取字典数据(改进版)
* 返回 Promise,确保所有字典数据加载完成后才 resolve
*/
export function comDict(...args) {
const res = ref({});
const promises = [];
args.forEach((dictType) => {
res.value[dictType] = [];
const dicts = useDictStore().getDict(dictType);
if (dicts) {
// 缓存存在,直接赋值
res.value[dictType] = dicts;
} else {
// 缓存不存在,发起请求并记录 Promise
const promise = getComDicts({ zdlb: dictType }).then(resp => {
const dictList = resp.data.map(p => ({
label: p.zdmc,
value: p.zddh,
elTagType: "",
elTagClass: ""
}));
res.value[dictType] = dictList;
useDictStore().setDict(dictType, dictList);
// console.log(`${dictType} 字典加载完成`, dictList);
return dictList;
});
promises.push(promise);
}
});
// 等待所有 Promise 完成后才返回
return Promise.all(promises).then(() => {
// console.log('所有请求的字典已加载完成', res.value);
return toRefs(res.value);
});
}

View File

@ -100,7 +100,7 @@ service.interceptors.response.use(res => {
} else if (code === 601) {
ElMessage({ message: msg, type: 'warning' })
return Promise.reject(new Error(msg))
} else if (code !== 200) {
} else if (code !== 200 && code !== 0) {
ElNotification.error({ title: msg })
return Promise.reject('error')
} else {

View File

@ -1,5 +1,6 @@
<script setup>
import { computed } from "vue";
import { getToken } from "@/utils/auth";
import {queryComDictListService,addComDictService,updateComDictService} from "../../../api/liswork/dict/ComDict.js";
const { proxy } = getCurrentInstance();
@ -34,12 +35,26 @@ const title = ref('');
// return item.zddh+'('+item.zdmc+')';
// });
// });
/*** 用户导入参数 */
const upload = reactive({
// 是否显示弹出层(用户导入)
open: false,
// 弹出层标题(用户导入)
title: "",
// 是否禁用上传
isUploading: false,
// 是否更新已经存在的用户数据
updateSupport: 0,
// 设置上传的请求头部
headers: { Authorization: "Bearer " + getToken() },
// 上传的地址
url: import.meta.env.VITE_APP_BASE_API + "/comdict/importData"
});
function resetData(zdlb){
queryParams.value = {
pageNum: 1,
pageSize: 10,
pageSize: 15,
zdmc: undefined,
zdlb: zdlb,
zddh: undefined,
@ -123,11 +138,39 @@ function handleUpdate(){
function handleDelete(){
}
/** 导入按钮操作 */
function handleImport() {
upload.title = "字典导入";
upload.open = true;
};
/** 导出按钮操作 */
function handleExport() {
proxy.download("comdict/export", {
...queryParams.value,
},`user_${new Date().getTime()}.xlsx`);
};
/** 下载模板操作 */
function importTemplate() {
proxy.download("comdict/importTemplate", {
}, `user_template_${new Date().getTime()}.xlsx`);
};
/** 提交上传文件 */
function submitFileForm() {
proxy.$refs["uploadRef"].submit();
};
/**文件上传中处理 */
const handleFileUploadProgress = (event, file, fileList) => {
upload.isUploading = true;
};
/** 文件上传成功处理 */
const handleFileSuccess = (response, file, fileList) => {
upload.open = false;
upload.isUploading = false;
proxy.$refs["uploadRef"].handleRemove(file);
proxy.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true });
handleQuery()
};
//导出
function handleExport(){
}
//多选框选中数据
function handleSelectionChange(){
@ -173,6 +216,38 @@ function cancel() {
}
//提交表单数据
function submitForm() {
proxy.$refs["dictRef"].validate(valid => {
if (valid) {
if (form.value.zdlb != undefined && form.value.zdlb != '') {
updateComDictService(form.value).then(response => {
proxy.$modal.msgSuccess("修改成功");
open.value = false;
getList();
}).catch(error => {
reset();
});
} else {
form.value.zdlb = queryParams.value.zdlb;
addComDictService(form.value).then(response => {
proxy.$modal.msgSuccess("新增成功");
open.value = false;
getList();
}).catch(error => {
form.value.zdlb = '';
});
}
}
});
}
function cancel() {
open.value = false;
reset();
}
getTypeList()
</script>
@ -188,6 +263,9 @@ getTypeList()
<div class="card-content">
<p class="clickable" v-for="item in typeList" :key="item.zdlb" @click="refreshDetail(item.zddh)">{{ item.zdmc }}</p>
</div>
<div class="card-content">
<p class="clickable" v-for="item in typeList" :key="item.zdlb" @click="refreshDetail(item.zddh)">{{ item.zdmc }}</p>
</div>
</div>
</el-col>
<!-- 字典明细-->
@ -216,6 +294,9 @@ getTypeList()
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete" v-hasPermi="['system:dict:remove']">删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="info" plain icon="Upload" @click="handleImport" v-hasPermi="['system:dict:import']">导入</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['system:dict:export']">导出</el-button>
</el-col>
@ -263,11 +344,45 @@ getTypeList()
</div>
</template>
</el-dialog>
<!-- 用户导入对话框 -->
<el-dialog :title="upload.title" v-model="upload.open" width="400px" append-to-body>
<el-upload
ref="uploadRef"
:limit="1"
accept=".xlsx, .xls"
:headers="upload.headers"
:action="upload.url + '?updateSupport=' + upload.updateSupport"
:disabled="upload.isUploading"
:on-progress="handleFileUploadProgress"
:on-success="handleFileSuccess"
:auto-upload="false"
drag
>
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<template #tip>
<div class="el-upload__tip text-center">
<div class="el-upload__tip">
<el-checkbox v-model="upload.updateSupport" />是否覆盖已经存在的字典数据
</div>
<span>仅允许导入xls、xlsx格式文件。</span>
<el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;" @click="importTemplate">下载模板</el-link>
</div>
</template>
</el-upload>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitFileForm">确 定</el-button>
<el-button @click="upload.open = false">取 消</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<style scoped lang="scss">
.card-content {
.card-content {
max-height: 450px; /* 设置最大高度 */
overflow-y: auto; /* 超出高度时显示垂直滚动条 */

View File

@ -0,0 +1,214 @@
<template>
<div class="dict-input-wrapper">
<el-input
v-model="displayValue"
:placeholder="placeholder"
:clearable="clearable"
:disabled="isDictLoading || disabled"
@blur="handleBlur"
@clear="handleClear"
@dblclick="handleDblClick"
>
<template #prefix>
<el-icon v-if="isDictLoading" size="16"><Loading /></el-icon>
</template>
<template #suffix>
<el-icon @click="openDictSelector" size="16" class="select-icon">
<ArrowDown />
</el-icon>
</template>
</el-input>
<!-- 字典选择弹窗 -->
<el-dialog
v-model="dialogVisible"
:title="dialogTitle"
width="500px"
@close="handleDialogClose"
>
<el-input
v-model="searchKey"
placeholder="搜索(支持名称、编码、简拼)..."
class="mb-4"
clearable
@clear="filterDictData"
@input="filterDictData"
/>
<el-table
:data="filteredDictData"
height="300px"
border
@row-click="selectItem"
@row-dblclick="selectItem"
>
<el-table-column prop="value" label="编码" width="100" />
<el-table-column prop="label" label="名称" width="200" />
<el-table-column prop="pinyin" label="简拼" width="150" /> <!-- 显示简拼便于调试 -->
<el-table-column label="操作" width="100">
<template #default="scope">
<el-button size="small" type="primary" @click="selectItem(scope.row)">选择</el-button>
</template>
</el-table-column>
</el-table>
</el-dialog>
</div>
</template>
<script setup>
import { ref, computed, watch, onMounted } from 'vue';
import { Loading, ArrowDown } from '@element-plus/icons-vue';
import { getFirstLetter } from '@/api/pinyin.js'; // 引入拼音处理工具
// 组件参数
const props = defineProps({
modelValue: { type: [String, Number], default: '' },
dictType: { type: String, required: true },
placeholder: { type: String, default: '请输入或双击选择' },
clearable: { type: Boolean, default: true },
disabled: {type: Boolean, default: false},
fetchDict: {type: Function, required: true},
dialogTitle: {type: String, default: '选择字典项'}
});
// 组件事件
const emit = defineEmits(['update:modelValue', 'update:labelValue', 'select']);
// 内部状态
const tempValue = ref('');
const labelValue = ref('');
const dictData = ref([]); // 存储带简拼的字典数据
const filteredDictData = ref([]);
const isDictLoading = ref(true);
const dialogVisible = ref(false);
const searchKey = ref('');
// 显示值计算
const displayValue = computed({
get() {
return labelValue.value || tempValue.value || props.modelValue || '';
},
set(newValue) {
tempValue.value = newValue;
if (labelValue.value && newValue !== labelValue.value) {
labelValue.value = '';
emit('update:labelValue', '');
}
}
});
// 加载字典数据(并添加简拼字段)
const loadDictData = async () => {
try {
isDictLoading.value = true;
const rawData = await props.fetchDict(props.dictType);
// 为每个字典项添加简拼字段
dictData.value = (rawData || []).map(item => ({
...item,
pinyin: getFirstLetter(item.label) // 新增pinyin字段存储简拼
}));
filteredDictData.value = [...dictData.value];
} catch (error) {
console.error(`加载${props.dictType}字典失败:`, error);
dictData.value = [];
filteredDictData.value = [];
} finally {
isDictLoading.value = false;
}
};
// 核心搜索逻辑(支持模糊搜索+简拼搜索)
const filterDictData = () => {
const key = searchKey.value.trim().toLowerCase();
if (!key) {
filteredDictData.value = [...dictData.value];
return;
}
filteredDictData.value = dictData.value.filter(item => {
// 1. 模糊搜索:匹配label(名称)或value(编码)
const matchLabel = item.label.toLowerCase().includes(key);
const matchValue = String(item.value).toLowerCase().includes(key);
// 2. 简拼搜索:匹配首字母简拼
const matchPinyin = item.pinyin.toLowerCase().includes(key);
// 满足任一条件即匹配
return matchLabel || matchValue || matchPinyin;
});
};
// 双击事件处理
const handleDblClick = () => {
if (!props.disabled && !isDictLoading.value) {
dialogVisible.value = true;
}
};
// 打开弹窗
const openDictSelector = () => {
if (!props.disabled && !isDictLoading.value) {
dialogVisible.value = true;
searchKey.value = '';
filterDictData();
}
};
// 选择字典项
const selectItem = (item) => {
emit('update:modelValue', item.value);
emit('update:labelValue', item.label);
emit('select', item);
tempValue.value = item.value;
labelValue.value = item.label;
dialogVisible.value = false;
};
// 其他方法(失焦、清空等)保持不变
const handleBlur = () => { /* ... */
};
const handleClear = () => { /* ... */
};
const handleDialogClose = () => {
dialogVisible.value = false;
};
// 监听初始值变化
watch(() => props.modelValue, (newVal) => {
tempValue.value = newVal || '';
if (newVal && !isDictLoading.value) {
const matched = dictData.value.find(item => String(item.value) === String(newVal));
labelValue.value = matched?.label || newVal;
emit('update:labelValue', labelValue.value);
}
}, {immediate: true});
// 组件挂载时加载字典
onMounted(async () => {
await loadDictData();
});
</script>
<style scoped>
/* 样式保持不变 */
.dict-input-wrapper {
position: relative;
}
.select-icon {
cursor: pointer;
color: #666;
margin-left: 5px;
}
.select-icon:hover {
color: #409eff;
}
:deep(.el-input__suffix) {
gap: 4px;
}
</style>

View File

@ -0,0 +1,102 @@
<template>
<div class="custom-select2">
<Select2
v-model="currentValue"
:options="processedOptions"
:settings="select2Settings"
@update:modelValue="handleChange"
:disabled="isDisabled"
/>
</div>
</template>
<script setup>
//import { ref, computed, watch, defineProps, defineEmits } from 'vue';
import Select2 from 'vue3-select2-component';
import 'select2/dist/css/select2.min.css';
import { processOptions } from '@/api/pinyin.js'; // 引入拼音处理工具
// 定义组件props
const props = defineProps({
options: {
type: Array,
default: () => []
},
value: {
type: [String, Number, Object],
default: null
},
placeholder: {
type: String,
default: '请选择'
},
disabled: {
type: Boolean,
default: false
},
width: {
type: String,
default: '200px'
}
});
// 定义组件emits
const emits = defineEmits(['update:modelValue', 'change']);
// 处理选项数据
const processedOptions = computed(() => {
return processOptions(props.options);
});
// 当前值
const currentValue = ref(props.value);
// Select2设置
const select2Settings = computed(() => ({
placeholder: props.placeholder,
allowClear: true,
width: props.width,
dropdownAutoWidth: false,
// 自定义搜索函数
matcher: (params, data) => {
if (!params.term || params.term.trim() === '') {
return data;
}
const term = params.term.toLowerCase();
// 检查文本、拼音或拼音首字母是否匹配
if (
data.text.toLowerCase().includes(term) ||
data.pinyin.toLowerCase().includes(term) ||
data.firstLetters.toLowerCase().includes(term)
) {
return data;
}
return null;
}
}));
// 跟踪禁用状态
const isDisabled = computed(() => props.disabled);
// 监听外部值变化
watch(() => props.value, (newVal) => {
currentValue.value = newVal;
});
// 处理值变更
const handleChange = (value) => {
currentValue.value = value;
emits('update:modelValue', value);
emits('change', value);
};
</script>
<style scoped>
.custom-select2 {
width: 100%;
}
</style>

View File

@ -0,0 +1,144 @@
<template>
<div class="compact-form">
<el-col :span="24" :xs="24">
<el-form :model="labPat" label-width="100px" class="compact-form" label-position="left">
<el-form-item label="病人来源" label-width="70px">
<el-col :span="16">
<dict-input v-model="labPat.brly" :dict-type="'PT'" placeholder="请输入病人来源" :fetch-dict="fetchDict" @update:labelValue="(label) => labPat.brlyLabel = label" dialog-title="选择病人来源"/>
</el-col>
<el-col :span="8">
<el-switch v-model="labPat.jzbz" active-text="急诊" active-color="#FD0101"></el-switch>
</el-col>
</el-form-item>
<el-form-item label="病 历 号" label-width="70px">
<el-input v-model="labPat.brdh" placeholder="请输入病历号"></el-input>
</el-form-item>
<el-form-item label="姓 名" label-width="70px">
<el-input v-model="labPat.brxm" placeholder="请输入姓名"></el-input>
</el-form-item>
<el-form-item label="性 别" label-width="70px">
<el-col :span="8">
<dict-input v-model="labPat.brxb" placeholder="性别" :dict-type="'SX'" :fetch-dict="fetchDict" @update:labelValue="(label) => labPat.brxbLabel = label"/>
</el-col>
<el-col :span="4"><div>年龄</div></el-col>
<el-col :span="6">
<el-input v-model="labPat.nl" placeholder="年龄"></el-input>
</el-col>
<el-col :span="6">
<dict-input v-model="labPat.nldw" placeholder="年月" :dict-type="'AU'" :fetch-dict="fetchDict" @update:labelValue="(label) => labPat.nldwLabel = label"/>
</el-col>
</el-form-item>
<el-form-item label="送检科室" label-width="70px">
<dict-input v-model="labPat.ksdh" placeholder="请输入科室" :dict-type="'DP'" :fetch-dict="fetchDict" @update:labelValue="(label) => labPat.ksdhLabel = label"/>
</el-form-item>
<el-form-item label="床 号" label-width="70px">
<el-input v-model="labPat.ch" placeholder="请输入床号"></el-input>
</el-form-item>
<el-form-item label="样本类型" label-width="70px">
<dict-input v-model="labPat.yblx" placeholder="请输入样本类型" :dict-type="'BT'" :fetch-dict="fetchDict" @update:labelValue="(label) => labPat.yblxLabel = label"/>
</el-form-item>
<el-form-item label="申请医生" label-width="70px">
<dict-input v-model="labPat.sjys" placeholder="请输入申请医生" :dict-type="'SRD'" :fetch-dict="fetchDict" @update:labelValue="(label) => labPat.sjysLabel = label"/>
</el-form-item>
<el-form-item label="上机时间" label-width="70px">
<el-date-picker v-model="labPat.sqsj" type="datetime" placeholder="上机时间" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss"></el-date-picker>
</el-form-item>
<el-form-item label="采样时间" label-width="70px">
<el-date-picker v-model="labPat.cyrq" type="datetime" placeholder="采样时间" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss"></el-date-picker>
</el-form-item>
<el-form-item label="报告时间" label-width="70px">
<el-date-picker v-model="labPat.dysj" type="datetime" placeholder="报告时间" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss"></el-date-picker>
</el-form-item>
<el-form-item label="临床诊断" label-width="70px">
<el-input v-model="labPat.zd" placeholder="请输入临床诊断"></el-input>
</el-form-item>
<el-form-item label="备 注" label-width="70px">
<el-input v-model="labPat.bz" placeholder="请输入备注"></el-input>
</el-form-item>
<el-form-item label="检验医生" label-width="70px">
<el-input v-model="labPat.yhdh" placeholder="请输入检验医生"></el-input>
</el-form-item>
<el-form-item label="审核医生" label-width="70px">
<el-input v-model="labPat.hdys" placeholder="请输入审核医生"></el-input>
</el-form-item>
<el-form-item label="审核状态" >
<el-radio-group v-model="labPat.jgbz">
<el-radio :label="0">未审核</el-radio>
<el-radio :label="2">已审核</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<div class="compact-form">
<el-button type="primary" @click="saveMain">保存</el-button>
<el-button @click="resetMain">重置</el-button>
</div>
</el-col>
</div>
</template>
<script setup>
import DictInput from './DictInput.vue';
const props = defineProps({
labPat: {
type: Object,
required: true
},
//结果主键
labPatKey:{
type: Array,
default: () => []
}
});
const emit = defineEmits(['update:labPat']);
// 通过inject获取全局方法
const comDict = inject('comDict');
// 保存方法
const saveMain = () => {
// 提交时可获取原始值(brly)和标签(brlyLabel)
console.log('提交数据:', {
rawValue: props.labPat.brly,
label: props.labPat.brlyLabel,
...props.labPat
});
// 实际项目中调用接口提交数据
};
// 重置方法
const resetMain = () => {
emit('update:labPat', {
brly: '',
brlyLabel: '',
ksdh: '',
ksdhLabel: '',
sjys: '',
sjysLabel: '',
brxb: '',
brxbLabel: '',
nldw: '',
nldwLabel: '',
yblx: '',
yblxLabel: '',
// 保留其他字段的默认值
...props.labPat,
jzbz: props.labPat.jzbz || 0,
jgbz: props.labPat.jgbz || 0
});
}
// 字典获取方法(适配子组件)
const fetchDict = async (dictType) => {
const dictRefs = await comDict(dictType);
// 根据实际字典结构返回数组(需与子组件匹配)
return dictRefs[dictType]?.value || [];
};
</script>
<style scoped lang="scss">
.compact-form .el-form-item {
margin-bottom: 10px;
}
.compact-form .el-form-item__label {
padding-bottom: 5px;
}
</style>

View File

@ -0,0 +1,206 @@
<template>
<div class="table-container">
<el-input
v-model="searchText"
placeholder="输入条码号搜索"
class="mb-4"
@keyup.enter="search"
>
<template #append>
<el-button @click="search">搜索</el-button>
</template>
</el-input>
<el-table
:data="labPatList"
stripe
class="card-content"
:header-cell-style="headerCellStyle"
:cell-style="cellStyle"
@row-click="handleRowClick"
style="width: 100%"
border
>
<el-table-column prop="finish" label="完成" width="70">
<template #default="scope">
<span>{{ scope.row.finish === 1 ? '已完成' : '未完成' }}</span>
</template>
</el-table-column>
<el-table-column prop="jgbz" label="审核" width="25" align="center" header-align="center" >
<template #default="scope">
<el-checkbox :model-value="scope.row.jgbz === '2'" disabled>
</el-checkbox>
</template>
</el-table-column>
<el-table-column prop="alarmflag" label="报警" width="25">
<template #default="scope">
<el-checkbox :model-value="scope.row.alarmflag === '1'" disabled>
</el-checkbox>
</template>
</el-table-column>
<el-table-column prop="brly" label="类型" width="50" show-overflow-tooltip></el-table-column>
<el-table-column prop="autojgbz" label="自审" width="25" >
<template #default="scope">
<el-checkbox :model-value="scope.row.autojgbz === '1'" disabled>
</el-checkbox>
</template>
</el-table-column>
<el-table-column prop="ybh" label="样本号" width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="brxm" label="病人姓名" width="100" show-overflow-tooltip></el-table-column>
<el-table-column prop="brdh" label="病历号" width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="ch" label="床号" width="80" show-overflow-tooltip ></el-table-column>
<el-table-column prop="brxb" label="病人性别" width="80" show-overflow-tooltip ></el-table-column>
<el-table-column prop="nl" label="年" width="40" show-overflow-tooltip ></el-table-column>
<el-table-column prop="nldw" label="龄" width="30" show-overflow-tooltip ></el-table-column>
<el-table-column prop="ksdh" label="科室" width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="yblx" label="标本" width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="dybz" label="打印" width="25" show-overflow-tooltip >
<template #default="scope">
<el-checkbox :model-value="scope.row.dybz === '1'" disabled>
</el-checkbox>
</template>
</el-table-column>
<el-table-column prop="fslx" label="发送" width="25">
<template #default="scope">
<el-checkbox :model-value="scope.row.dybz === '1'" disabled>
</el-checkbox>
</template>
</el-table-column>
<el-table-column prop="shcs" label="次数" width="25" show-overflow-tooltip ></el-table-column>
<el-table-column prop="sqh" label="申请号/条码" width="100" show-overflow-tooltip></el-table-column>
<el-table-column prop="jymd" label="检验目的" width="100" show-overflow-tooltip></el-table-column>
<el-table-column prop="yhdh" label="检验医生" width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="yljg" label="送检医院" width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="jyrq" label="检验日期" v-if="false"></el-table-column>
<el-table-column prop="yq" label="仪器" v-if="false"></el-table-column>
</el-table>
<el-pagination
class="mt-4"
background
layout="total, sizes, prev, pager, next, jumper"
:total="total"
:page-sizes="[5, 10, 15, 20]"
:page-size="pageSize"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
>
</el-pagination>
</div>
</template>
<script setup>
const props = defineProps({
labPatList: {
type: Array,
default: () => []
},
total: {
type: Number,
default: 0
}
})
const emits = defineEmits(['select', 'search', 'page-change'])
const searchText = ref('')
const pageSize = ref(15)
const currentPage = ref(1)
const search = () => {
emits('search', searchText.value, currentPage.value, pageSize.value)
}
const handleRowClick = (row) => {
emits('select', row)
}
const handleSizeChange = (val) => {
pageSize.value = val
emits('page-change', currentPage.value, pageSize.value)
}
const handleCurrentChange = (val) => {
currentPage.value = val
emits('page-change', currentPage.value, pageSize.value)
}
onMounted(() => {
emits('page-change', currentPage.value, pageSize.value)
})
// 设置列头颜色
const headerCellStyle = ({ row, column, rowIndex, columnIndex }) => {
return {
// backgroundColor: '#A6CAF0', // 浅蓝色
color: '#0050b3', // 文字颜色
fontWeight: 'bold' // 文字加粗
};
};
//设置内容格式
const cellStyle = ({ row, column, rowIndex, columnIndex }) => {
// console.log('检查单元格样式:', row, column); // 调试输出
// 使用 === 比较时注意值的类型(数字 vs 字符串)
if (column.property === 'finish' && row.status === '1') {
return {
backgroundColor: '#006400', // 使用驼峰式写法(可选)
fontWeight: 'bold',
color: 'white', // 添加文字颜色,确保可读性
height: '25px',
lineHeight: '25px'
};
}
if (column.property === 'jgbz' && row.status === '2') {
return {
backgroundColor: '#FF69B4',
fontWeight: 'bold',
height: '25px',
lineHeight: '25px'
};
}
if (column.property === 'alarmflag' && row.status === '1') {
return {
backgroundColor: '#FF0000',
fontWeight: 'bold',
color: 'white',
height: '25px',
lineHeight: '25px'
};
}
return {
height: '25px',
lineHeight: '25px',
padding: '0 0px'
}; // 默认不设置样式
};
</script>
<style scoped lang="scss">
.compact-form .el-form-item {
padding: 10px;
margin-bottom: 10px;
}
.compact-form .el-form-item__label {
padding-bottom: 5px;
}
.card-content {
max-height: 620px; /* 设置最大高度 */
overflow-y: auto; /* 超出高度时显示垂直滚动条 */
padding: 10px; /* 保持与卡片默认一致的内边距 */
}
.clickable:hover {
cursor: pointer; /* 鼠标悬停时显示手型 */
transition: all 0.3s; /* 平滑过渡效果 */
color: blue;
}
.card-content.el-table__row.current-row {
background-color: #e6f4ff !important;
color: #0050b3 !important; /* 文字颜色 */
}
.card-content.el-table__row.current-row:hover {
background-color: #d6e8ff !important;
}
</style>

View File

@ -0,0 +1,240 @@
<template>
<div class="compact-form">
<el-table
:data="tableData"
border
stripe
highlight-current-row
@selection-change="handleSelectionChange"
class="custom-table-container"
height="640px"
style="width: 100%; --table-row-height: 32px;"
:header-cell-style="{ backgroundColor: '#f5f7fa' }"
>
<el-table-column
type="index" prop="id" label="" width="45" :index="getRowIndex" >
</el-table-column>
<el-table-column type="selection" width="30"></el-table-column>
<el-table-column prop="jyrq" label="检验日期" v-if="false"></el-table-column>
<el-table-column prop="yq" label="仪器" v-if="false"></el-table-column>
<el-table-column prop="ybh" label="样本号" v-if="false"></el-table-column>
<el-table-column prop="xmdh" label="项目" width="60" show-overflow-tooltip>
</el-table-column>
<el-table-column prop="xmmc" label="名称" width="100" show-overflow-tooltip>
</el-table-column>
<el-table-column prop="csjg" label="结果" width="100" >
<template #default="scope">
<el-input v-model="scope.row.csjg" size="small" class="full-width-input"></el-input>
</template>
</el-table-column>
<el-table-column prop="od" label="OD" width="60" v-if="false">
<template #default="scope">
<el-input v-model="scope.row.od" size="small" class="full-width-input"></el-input>
</template>
</el-table-column>
<el-table-column prop="cutoff" label="SCO" width="60" v-if="false">
<template #default="scope">
<el-input v-model="scope.row.od" size="small" class="full-width-input"></el-input>
</template>
</el-table-column>
<el-table-column prop="refs" label="参考值" width="100" show-overflow-tooltip>
</el-table-column>
<el-table-column prop="dw" label="单位" width="100" show-overflow-tooltip >
</el-table-column>
</el-table>
</div>
</template>
<script setup>
//import {ref, reactive, watch, toRefs, nextTick} from 'vue';
import {deleteresult, queryLabResults} from "@/api/liswork/work/LisWork.js";
import {delType} from "@/api/system/dict/type.js";
import {ElMessageBox} from "element-plus";
const { proxy } = getCurrentInstance();
const props = defineProps({
// 表格数据
tableData: {type: Array,default: () => []},
//主键
tableKey:{type: Array, default: () => []},
// 部门选项
// departments: {
// type: Array,
// default: () => []
// },
// 是否只读
readonly: {type: Boolean, default: false}
});
const { tableData, tableKey, readonly,undeleteflag,hasChanges } = toRefs(props);
const emits = defineEmits([
'add', // 新增行
'save', // 保存数据
'delete', // 删除行
'batch-delete', // 批量删除
'fetchLabResults' //刷新数据
]);
// 选中的行
const selectedRows = ref([]);
const filteredList = ref([]);
// 原始数据副本,用于检测变化
const originalData = ref(JSON.parse(JSON.stringify(props.tableData)));
// 处理选择变化
const handleSelectionChange = (val) => {
selectedRows.value = val;
if (val.length === 0) {
emits('delfalg', true);
}else{
emits('delfalg', false);
}
};
// 新增行
const handleAdd = () => {
// emits('add');
// 创建新行数据
const newRow = {
jyrq: tableKey.jyrq,
yq: tableKey.yq,
ybh: tableKey.ybh
};
// 添加到表格数据
tableData.value.push(newRow);
// 动画结束后移除标记
// 可选:滚动到表格底部并聚焦到第一个输入框
nextTick(() => {
const tableData = document.querySelector('.el-table__body-wrapper');
if (tableData) {
tableData.scrollTop = tableData.scrollHeight;
}
// 聚焦到新行的第一个输入框
const inputs = document.querySelectorAll('.el-input__inner');
if (inputs.length > 0) {
inputs[4].focus(); // 通常最后一个是操作列的按钮,所以取倒数第二个
}
})
};
// 保存数据
const handleSave = () => {
if (hasChanges.value) {
emits('save', props.tableData);
// 保存后更新原始数据
// originalData.value = JSON.parse(JSON.stringify(props.tableData));
hasChanges.value = false;
}
};
// 删除行
const handleDelete = (row) => {
emits('delete', row);
tableData.value = tableData.value.filter(item => item.id !== row.id);
};
// 批量删除(调用API)
const handleBatchDelete = async () => {
try {
if (selectedRows.length === 0) {
return;
}
// 确认删除
await ElMessageBox.confirm(
`确定要删除选中的 ${selectedRows.value.length} 条记录吗?`,
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}
);
await deleteresult(selectedRows.value);
fetchLabResults();
} catch (error) {
// 错误已经在拦截器中处理,这里可以不做处理或添加额外逻辑
console.error('删除失败:', error);
}
}
// 重置表格的修改状态
const resetChange = () => {
// 原始数据副本,用于检测变化
originalData.value = JSON.parse(JSON.stringify(props.tableData));
hasChanges.value = false;
};
const fetchLabResults = () => {
emits('fetchLabResults');
}
// 监听数据变化
watch(() => props.tableData, (newVal, oldVal) => {
// 简单比较数据是否有变化
//hasChanges.value = JSON.stringify(newVal) !== JSON.stringify(originalData.value);
}, { deep: true });
// 获取行号(支持分页时显示正确行号)
const getRowIndex = (index) => {
// 如果有分页,可以根据当前页码计算真实行号
// return (currentPage - 1) * pageSize + index + 1;
// 无分页时直接返回索引+1
return index + 1;
};
// 暴露方法给父组件
defineExpose({
handleAdd,
handleDelete,
handleSave,
handleBatchDelete
});
</script>
<style scoped>
/* 移除单元格内边距 */
.custom-table-container /deep/ .el-table__cell {
padding: 0 !important;
}
/* 表格行高 */
.custom-table-container /deep/ .el-table__row {
height: var(--table-row-height) !important;
}
/* 输入框占满单元格 */
.full-width-input /deep/ .el-input__inner {
width: 100%;
height: calc(var(--table-row-height) - 2px); /* 减去上下边框 */
padding: 0 0px; /* 减小内边距 */
border: 0px solid #dcdfe6;
border-radius: 0;
box-sizing: border-box;
background-color: transparent; /* 可选:透明背景 */
}
/* 输入框聚焦效果 */
.full-width-input /deep/ .el-input__inner:focus {
border-color: #409eff;
box-shadow: 0 0 0 0px rgba(64, 158, 255, 0.2);
outline: none;
}
/* 新增行动画 */
.el-table__body-wrapper {
overflow: visible !important; /* 确保动画不被裁剪 */
}
.new-row-enter-active {
animation: fadeIn 0.5s ease;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
</style>

View File

@ -0,0 +1,505 @@
<template>
<div class="app-container">
<el-row :gutter="10" class="compact-form">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['system:dict:add']">新增明细</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="delResultFlag" @click="handleDelete" v-hasPermi="['system:dict:remove']">删除明细</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="changeResultFlag" @click="handleUpdate" v-hasPermi="['system:dict:edit']">保存</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" @click="handleCheck" v-hasPermi="['system:dict:import']">初报</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Download" @click="handleCheck" v-hasPermi="['system:dict:import']">初审</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="info" plain icon="Upload" @click="handleUnCheck" v-hasPermi="['system:dict:export']">取消初审</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Download" @click="handleCheck" v-hasPermi="['system:dict:import']">审核</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="info" plain icon="Upload" @click="handleUnCheck" v-hasPermi="['system:dict:export']">取消审核</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="primary" plain icon="Edit" @click="handleUnCheck" v-hasPermi="['system:dict:export']">预览</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="primary" plain icon="Edit" @click="handleUnCheck" v-hasPermi="['system:dict:export']">打印</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Upload" @click="handleUnCheck" v-hasPermi="['system:dict:export']">上一个</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Download" @click="handleUnCheck" v-hasPermi="['system:dict:export']">下一个</el-button>
</el-col>
</el-row>
<el-row :gutter="10" class="compact-form" >
<el-form :model="queryParams" ref="queryRef" :inline="true" :rules="rules" >
<el-form-item class="compact-form" label="" label-width="0px" prop="ybh" >
<el-col :span="1.5">样本编号</el-col>
<el-col :span="4.5">
<el-input v-model="queryParams.ybh" clearable placeholder="样本编号" prefix-icon="Search" @keyup.enter="handleQueryYbh" @clear="handleQueryYbh" />
</el-col>
<el-col :span="1.5"><div>检验日期</div></el-col>
<el-col :span="3.5">
<el-date-picker v-model="queryParams.jyrq" type="date" label-width="20px" placeholder="检验日期" value-format="YYYY-MM-DD" :clearable="false" @change="handleQuery" ></el-date-picker>
</el-col>
<el-col :span="1.5"><div>部门组别</div></el-col>
<el-col :span="3.5">
<Ddlb
v-model="queryParams.instrGroup"
:options="instrGroupOptions"
placeholder="请选择部门组别"
@change="handleinstrGroupChange"
:value="setInstrGroup"
label-width="40px"
/>
</el-col><el-col :span="1"><div>仪器</div></el-col>
<el-col :span="4">
<Ddlb
v-model="queryParams.yq"
:options="instrOptions"
placeholder="请选择仪器"
@change="handleYqChange"
:value="setInstr"
/>
</el-col>
</el-form-item>
</el-form>
</el-row>
<el-row :gutter="5">
<el-col :span="5" :xs="24">
<div class="compact-form">
<LabPatForm v-model:labPat="labPat" ref="labPatRef" @save="savelabPat" @reset="resetlabPat" />
</div>
</el-col>
<el-col :span="10" :xs="24">
<div class="compact-form">
<LabResultForm ref="labResultRef"
:tableData="labResuts"
:tableKey="queryParams"
@add="addLabResult"
@delete="deleteLabResults"
@edit="editLabResult"
@delfalg="setdelResultFlag"
@changefalg="setchangeResultFlag"
@fetchLabResults="fetchLabResults"
/>
</div>
</el-col>
<el-col :span="9" :xs="24">
<div class="compact-form">
<LabPatListForm
:labPatList="labPatList"
:labPatKey="queryParams"
:total="total"
@select="selectJob"
@search="searchJobs"
@page-change="pageChange"
/>
</div>
</el-col>
</el-row>
</div>
</template>
<script setup>
import {getDate,queryLabPatList,queryLabResults,updateLabPatService,queryLabPat} from "../../../api/liswork/work/LisWork.js";
import {querylabInstrList,querylabInstrListByLisgroup} from "../../../api/liswork/dict/LabInstr.js";
import {getComDicts, queryComDictListService} from "../../../api/liswork/dict/ComDict.js";
import LabPatForm from './components/labpat.vue'
import LabResultForm from './components/labresult.vue'
import LabPatListForm from './components/labpatlist.vue'
import Ddlb from './components/ddlb.vue'
const single = ref(true);
const delResultFlag = ref(true);
const changeResultFlag = ref(true);
const loading = ref(true);
const instrGroupOptions = ref([]);
const instrOptions = ref([]);
const labPatList = ref([])
const patdata = reactive({
form: {},
labPat: {
jyrq: '',
yq: '',
ybh: '',
brly:'',
jzbz:'',
brdh:'',
brxm:'',
brxb:'',
nl:null,
nldw:'1',
ksdh:'',
ch:'',
sjys:'',
sqsj:'',
cyrq:'',
dysj:'',
zd:'',
bz:'',
yhdh:'',
hdys:'',
jgbz:'0',
yblx:''
},
rules: {}
});
const { labPat } = toRefs(patdata);
const labResuts = ref([])
const total = ref(0)
const currentLabResults = ref([])
const searchText = ref('')
const pageSize = ref(10)
const currentPage = ref(1)
const setInstrGroup=ref('')
const setInstr=ref('')
const yq0=ref('')
const jyrq0=ref('')
const ybh0=ref('')
const querydata = reactive({
form: {},
queryParams: {
pageNum: 1,
pageSize: 10,
jyrq: formatDate(new Date()),
yq: '1',
ybh: '1',
days: 1,
instrGroup:'#'
},
rules: {
ybh: [],
jyrq: [],
instrGroup: [],
yq: [],
}
,
});
const { queryParams, form, rules } = toRefs(querydata);
//子组件labResult.vue
const labResultRef = ref(null);
//子组件labPatRef.vue
const labPatRef = ref(null);
// 页面载入时获取基本默认值参数信息,后面有扩展需要都放这里
const loadYqConfig = async () => {
// 使用 .value 获取响应式数据的值
jyrq0.value='2022-06-19';//formatDate(new Date());
yq0.value='COBAS';
ybh0.value='1';
querydata.queryParams.jyrq = jyrq0.value;
querydata.queryParams.yq = yq0.value;
querydata.queryParams.ybh = ybh0.value;
querydata.queryParams.instrGroup = 'A2';
}
// 加载部门下拉列表
function loadinstrGroupOptions(){
loading.value = true;
getComDicts({zdlb: 'GROUP'}).then(response => {
instrGroupOptions.value = response.data.map(item => ({
id: item.zddh,
text: item.zdmc
}));
loading.value = false;
setInstrGroup.value=querydata.queryParams.instrGroup;
});
loadYqConfig();
}
// 部门组别变化时更新仪器下拉框
const handleinstrGroupChange = (value) => {
queryParams.value.instrGroup = value
// 清空仪器选择并重新加载
// queryParams.value.yq = '';
instrOptions.value = [];
// 加载对应组别的仪器数据
loadinstrOptions();
}
// 仪器变化时的处理函数
const handleYqChange = (value) => {
if (value === null || value === '') {
queryParams.value.yq = yq0.value;
setInstr.value= yq0.value;
}else {
yq0.value=value;
queryParams.value.yq = value;
handleQuery();
}
}
// 加载仪器下拉列表
const loadinstrOptions = () => {
loading.value = true;
querylabInstrListByLisgroup({pageNum: 1, pageSize: 100,lisgroup: queryParams.value.instrGroup})
.then(response => {
if (response.rows) {
instrOptions.value = toRaw(response.rows).map(item => ({
id: item.yq.trimEnd(),
text: item.yqmc
}))
loading.value = false;
setInstr.value=querydata.queryParams.yq;
} else {
throw new Error('仪器响应数据为空');
}
})
.catch(error => {
console.error('仪器数据加载失败', error);
loading.value = false;
});
// console.error('aaa', queryParams.value);
//console.log('test22:', instrOptions.value);
}
//获取服务器时间
const serverDate = computed(() => {
return formatDate(new Date());
});
//切换仪器或检验日期后重置页码
function resetData(){
queryParams.value = {
pageNum: 1,
pageSize: 15,
}
searchText.value = ''
currentPage.value = 1
pageSize.value = 15
}
//载入样本列表(右边labpatlist.vue组件)
const fetchlabPatList = async (search = '', page = 1, size = 15) => {
loading.value = true;
queryParams.value.pageSize = size;
queryParams.value.pageNum = page;
queryLabPatList(queryParams.value).then(response => {
labPatList.value = response.rows;
total.value = response.total;
loading.value = false;
}) .catch(error => {
console.error('列表数据加载失败', error);
loading.value = false;
});
}
//载入样本编辑表单(左边labpat.vue组件)
const fetchLabPat = async () => {
loading.value = true;
queryLabPat(queryParams.value).then(response => {
labPat.value = response.data;
loadingPatLabel();
loading.value = false;
}) .catch(error => {
console.error('列表数据加载失败', error);
loading.value = false;
});
}
//载入样本结果表单(中间labresult.vue组件)
const fetchLabResults = async () => {
loading.value = true;
// console.log('test', queryParams.value);
queryLabResults({jyrq: queryParams.value.jyrq,yq: queryParams.value.yq,ybh: queryParams.value.ybh}).then(response => {
// console.log('RESULT:', response);
labResuts.value = response.data;
loading.value = false;
}) .catch(error => {
console.error('列表数据加载失败', error);
loading.value = false;
});
}
//保存样本表单
const savelabPat = async (labPat) => {
// 实际项目中这里应该是API调用
console.log('保存主表:', labPat)
if (!labPat.id) {
// 新增
labPat.id = Date.now()
labPatList.value.unshift({...labPat})
} else {
// 更新
const index = labPatList.value.findIndex(item => item.id === labPat.id)
if (index !== -1) {
labPatList.value.splice(index, 1, {...labPat})
}
}
alert('保存成功')
}
//重置结果表单
const resetlabPat = () => {
labResuts.value = []
currentLabResults.value = []
}
//新增结果列
const addLabResult = async (LabResult) => {
// 实际项目中这里应该是API调用
console.log('添加明细:', LabResult)
if (!LabResult.xh) {
LabResult.xh = currentLabResults.value.length + 1
}
const index = currentLabResults.value.findIndex(item => item.xh === LabResult.xh)
if (index !== -1) {
currentLabResults.value.splice(index, 1, {...LabResult})
} else {
currentLabResults.value.push({...LabResult})
}
alert('添加成功')
}
//删除结果列
const deleteLabResults = async (xhList) => {
// 实际项目中这里应该是API调用
console.log('删除明细:', xhList)
currentLabResults.value = currentLabResults.value.filter(item => !xhList.includes(item.xh))
alert('删除成功')
}
//修改结果列
const editLabResult = (LabResult) => {
console.log('编辑明细:', LabResult)
// 在表单中填充数据
// 这里不需要做任何事情,因为组件已经绑定了数据
}
//样本列表点击切换样本信息,同步载入左边样本信息表单和中间结果表单
const selectJob = async (job) => {
// 复制选中的job数据到当前编辑状态
// Object.assign(labPat.value, {...job})
queryParams.value.jyrq = job.jyrq;
queryParams.value.yq = job.yq;
queryParams.value.ybh = job.ybh;
checkQuery()
//await nextTick();
// 获取对应的明细数据
await fetchLabPat();
await fetchLabResults();
}
//样本列表检索时刷新列表信息
const searchJobs = async (text, page, size) => {
searchText.value = text
currentPage.value = page
pageSize.value = size
loadlabPatList()
}
//样本列表翻页时刷新列表信息
const pageChange = async (page, size) => {
currentPage.value = page
pageSize.value = size
loadlabPatList()
}
//刷新样本列表方法封装
const loadlabPatList = async () => {
await fetchlabPatList(searchText.value, currentPage.value, pageSize.value)
}
/** 查询服务器时间 */
function getdate() {
getDate().then(response => {
serverDate.value= formatDate(new Date(response.data));
})
}
//日期格式化
function formatDate(date) {
const year = date.getFullYear();
// 月份是从0开始的,所以要加1
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day} 00:00:00`;
}
const setdelResultFlag = (value) =>{
delResultFlag.value=value;
}
const setchangeResultFlag = (value) =>{
changeResultFlag.value=value;
}
//新增
const handleAdd = () => {
labResultRef.value?.handleAdd();
};
function handleUpdate(){
}
function handleDelete(){
labResultRef.value?.handleBatchDelete();
}
function loadingPatLabel(){
// labPatRef.value?.loadingLabel();
}
function handleCheck(){
}
function handleUnCheck(){
}
function handlePrint(){
}
function handleQueryDetail(){
}
//切换仪器或检验日期时载入
const handleQuery= async()=>{
if (checkQuery()===false) return false
// resetData();
await loadlabPatList();
//暂时默认打开1号样本,后面由参数控制
querydata.queryParams.ybh='1';
await handleQueryYbh();
}
//切换样本号时载入
const handleQueryYbh = async()=>{
if (checkQuery()===false) return false
await fetchLabPat();
await fetchLabResults();
}
//主键空置拦截
function checkQuery(){
if (querydata.queryParams.jyrq === ''|| querydata.queryParams.jyrq === null) {
querydata.queryParams.jyrq = jyrq0.value
return false;
}
if (querydata.queryParams.yq === ''|| querydata.queryParams.yq === null) {
querydata.queryParams.yq = yq0.value
return false;
}
if (querydata.queryParams.ybh === ''|| querydata.queryParams.ybh === null) {
querydata.queryParams.ybh = ybh0.value
return false;
}
jyrq0.value=querydata.queryParams.jyrq
yq0.value=querydata.queryParams.yq
ybh0.value=querydata.queryParams.ybh
}
//打开页面需要先初始化的内容都放这里
onMounted(() => {
loadYqConfig();
loadinstrGroupOptions(); // 页面加载时获取部门组别数据
loadinstrOptions();
loadlabPatList();
})
</script>
<style scoped lang="scss">
.compact-form .el-form-item {
padding: 5px;
margin-bottom: 5px;
}
.compact-form .el-form-item__label {
padding-bottom: 0px;
}
.card-content {
max-height: 450px; /* 设置最大高度 */
overflow-y: auto; /* 超出高度时显示垂直滚动条 */
padding: 5px; /* 保持与卡片默认一致的内边距 */
}
.clickable:hover {
cursor: pointer; /* 鼠标悬停时显示手型 */
transition: all 0.3s; /* 平滑过渡效果 */
color: blue;
}
</style>

View File

@ -0,0 +1,582 @@
<template>
<div class="app-container">
<el-row :gutter="5" class="compact-form" :span="24" >
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-position="left" >
<el-col :span="24" :xs="24">
<el-form-item label="" label-width="0px" prop="brdh" >
<el-col :span="6">
<div> 就诊卡号/病历号/磁卡号: </div>
<el-input
v-model="queryParams.brdh"
placeholder="就诊卡号/病历号/磁卡号"
clearable
@keyup.enter="handleQuery"
/>
</el-col>
<el-col :span="2">
<el-radio-group v-model="queryParams.zt" size="default">
<el-radio v-for="(item, index) in showconfirmOptions" :key="index" :label="item.value"
:disabled="item.disabled">{{item.label}}</el-radio>
</el-radio-group>
</el-col>
<el-col :span="1"> <div> 申请获取期限: </div></el-col>
<el-col :span="6">
<el-radio-group v-model="queryParams.subday" size="default">
<el-radio v-for="(item, index) in subdayOptions" :key="index" :label="item.value"
:disabled="item.disabled">{{item.label}}</el-radio>
</el-radio-group>
</el-col>
<el-col :span="2">
<el-select v-model="queryParams.cardtype" placeholder="卡类型" clearable :style="{width: '100%'}">
<el-option v-for="(item, index) in cardtypeOptions" :key="index" :label="item.label"
:value="item.value" :disabled="item.disabled"></el-option>
</el-select>
</el-col>
<el-col :span="1.5">
<el-button type="primary" icon="Search" @click="handleQuery">读卡</el-button>
</el-col>
<el-col :span="1.5">
<el-button icon="Refresh" @click="resetQuery">查找病人</el-button>
</el-col>
</el-form-item>
</el-col>
</el-form>
</el-row>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="Search"
@click="handleQuery"
v-hasPermi="['system:reqmain:Search']"
>查询</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="Printer"
:disabled="single"
@click="printAll"
v-hasPermi="['system:reqmain:add']"
>打印</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="Printer"
:disabled="freesingle"
@click="printSigne"
v-hasPermi="['system:reqmain:edit']"
>单打条码</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="Printer"
:disabled="freesingle"
@click="printBackpaper"
v-hasPermi="['system:reqmain:edit']"
>单打回单</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="Delete"
@click="cancel"
v-hasPermi="['system:reqmain:export']"
>取消采样</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table ref="tableRef" class="compact-form my-table" :data="reqmainList" @selection-change="handleSelectionChange" @select="handleSelect" height="530px" :cell-style="tableCellStyle">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="项目名称" align="center" prop="sqxmmc" width="200" show-overflow-tooltip/>
<el-table-column label="项目代码" align="center" prop="sqxmdh" width="100" show-overflow-tooltip/>
<el-table-column label="项目类别" align="center" prop="cp_xmlb" />
<el-table-column label="样本类型" align="center" prop="yblx" />
<el-table-column label="条码号" align="center" prop="sqh" width="150" show-overflow-tooltip/>
<el-table-column label="申请时间" align="center" prop="sqsj" width="180" show-overflow-tooltip>
<template #default="scope">
<span>{{ parseTime(scope.row.sqsj, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
</template>
</el-table-column>
<el-table-column label="病人姓名" align="center" prop="brxm" show-overflow-tooltip/>
<el-table-column label="申请医生" align="center" prop="sqys" :formatter="formatDict('SRD')" show-overflow-tooltip/>
<el-table-column label="序号" align="center" prop="xh" show-overflow-tooltip/>
<el-table-column label="数量" align="center" prop="sl" show-overflow-tooltip/>
<el-table-column label="单价" align="center" prop="dj" show-overflow-tooltip/>
<el-table-column label="状态" align="center" prop="zt" show-overflow-tooltip/>
<el-table-column label="计价" align="center" prop="jjzt" >
<template #default="scope">
<el-checkbox :model-value="scope.row.jjzt === '1'" disabled>
</el-checkbox>
</template>
</el-table-column>
<el-table-column label="病人代号" align="center" prop="brdh" show-overflow-tooltip/>
<el-table-column label="备注1" align="center" prop="detailBZ1" show-overflow-tooltip/>
<el-table-column label="备注2" align="center" prop="detailBZ2" show-overflow-tooltip/>
<el-table-column label="颜色" align="center" prop="cp_color" v-if="false" show-overflow-tooltip/>
<el-table-column label="确认标识" align="center" prop="cp_cflag" v-if="false" show-overflow-tooltip/>
<el-table-column label="科室" align="center" prop="ksdh" :formatter="formatDict('DP')" show-overflow-tooltip/>
<el-table-column label="病人类型" align="center" prop="brly" :formatter="formatDict('PT')" show-overflow-tooltip/>
<el-table-column label="性别" align="center" prop="brxb" :formatter="formatDict('SX')" show-overflow-tooltip/>
<el-table-column label="生日" align="center" prop="brsr" width="180" show-overflow-tooltip>
<template #default="scope">
<span>{{ parseTime(scope.row.brsr, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="床号" align="center" prop="ch" width="50" show-overflow-tooltip/>
<el-table-column label="诊断" align="center" prop="zd" width="150" show-overflow-tooltip/>
<el-table-column label="条码类别" align="center" prop="bgddh" v-if="false" show-overflow-tooltip/>
<el-table-column label="年龄" align="center" prop="nl" show-overflow-tooltip/>
<el-table-column label="年龄单位" align="center" prop="nldw" :formatter="formatDict('AU')" show-overflow-tooltip/>
<el-table-column label="采样时间" align="center" prop="cysj" width="180"show-overflow-tooltip>
<template #default="scope">
<span>{{ parseTime(scope.row.cysj, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
</template>
</el-table-column>
</el-table>
<!-- 汇总行 -->
<div class="table-summary">
<div class="summary-item">
<span class="summary-label">条码数:</span>
<span class="summary-value">{{ idsnew.length }}</span>
</div>
<div class="summary-item">
<span class="summary-label">项目数:</span>
<span class="summary-value">{{ totalRows }}</span>
</div>
<div class="summary-item">
<span class="summary-label">合计金额:</span>
<span class="summary-value">{{ totalPrice.toFixed(2) }}</span>
</div>
</div>
</div>
</template>
<script setup>
import { querySQD, getReqmain, delReqmain, addReqmain, updateReqmain } from "@/api/mzcx/cydj.js";
const comDict = inject('comDict');
// 字典数据存储
const dictData = ref({});
const tableRef = ref(null);
const { proxy } = getCurrentInstance();
// 选中的行
const selectedRows = ref([]);
const reqmainList = ref([]);
const open = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref([]);
// 新增:计算属性,返回去重后的ids数组
const idsnew = computed(() => {
return [...new Set(ids.value)];
});
const single = ref(true);
const freesingle = ref(true);
const cardtypeOptions = ref([{"label": "就诊卡","value": 1},{"label": "医保卡","value": 2},{"label": "电子医保卡","value": 3},{"label": "身份证", "value": 4}])
const showconfirmOptions = ref([{"label": "未打印", "value": 1},{"label": "已打印", "value": 11}])
const subdayOptions = ref([{"label": "1天","value": 1},{"label": "3天", "value": 3},{"label": "1周","value": 7},{"label": "2周","value": 14},{"label": "1月", "value": 30},{"label": "3月", "value": 90},{"label": "1年","value": 365},{"label": "2年","value": 730}])
const data = reactive({
form: {},
queryParams: {
brdh: null,
stime: null,
etime: null,
klx: null,
zt: 1,
subday: 3000,
cardtype:null
},
rules: {
brdh: [
{ required: true, message: "病人代码不能为空", trigger: "blur" }
],
subday: [],
}
});
const { queryParams, form, rules } = toRefs(data);
// 标志位:是否是程序自动勾选(避免循环触发事件)
const isAutoSelect = ref(false);
/**
* 监听单选勾选/取消事件
* @param {Array} selection 目前已选中的行
* @param {Object} row 当前操作的行数据
* @param {Boolean} selected 是否勾选(true=勾选,false=取消)
*/
const handleSelect = (selection, row, selected) => {
if (isAutoSelect.value) return;
const targetSqh = row.sqh;
const targetxh = row.xh;
if (!targetSqh) return;
// 先收集需要自动勾选的行(避免在循环中修改数据)
const rowsToSelect = reqmainList.value.filter(
item => item.sqh === targetSqh && item.xh !== targetxh
);
// 如果有需要自动勾选的行,才开启标志位
if (rowsToSelect.length > 0) {
rowsToSelect.forEach(item => {
tableRef.value.toggleRowSelection(item, selected);
isAutoSelect.value = true;
});
setTimeout(() => isAutoSelect.value = false, 0);
}
};
// 字典格式化方法
const formatDict =(dictType) => {
return (row, column, value) => {
// 从全局字典中获取映射值
return dictData.value[dictType].find(item => String(item.value) === String(value).trim())?.label||value ;
};
};
// 定义“空数据”的判断函数
const isEmptyData = (data) => {
// 处理 null/undefined
if (data === null || data === undefined) return true;
// 处理空数组
if (Array.isArray(data) && data.length === 0) return true;
// 处理空对象(无任何属性)
if (typeof data === 'object' && Object.keys(data).length === 0) return true;
// 处理空字符串
if (typeof data === 'string' && data.trim() === '') return true;
return false;
};
/**
* 获取指定天数偏移后的日期时间字符串
* @param {number} days 偏移天数(正数表示未来,负数表示过去)
* @returns {string} 格式化的日期时间字符串 'yyyy-mm-dd HH:MM:SS'
*/
function getDateOffset(days) {
const now = new Date();
const offsetTimestamp = now.getTime() + days * 24 * 60 * 60 * 1000;
const targetDate = new Date(offsetTimestamp);
const year = targetDate.getFullYear();
const month = String(targetDate.getMonth() + 1).padStart(2, '0');
const day = String(targetDate.getDate()).padStart(2, '0');
// const hours = String(targetDate.getHours()).padStart(2, '0');
// const minutes = String(targetDate.getMinutes()).padStart(2, '0');
//const seconds = String(targetDate.getSeconds()).padStart(2, '0');
// return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
return `${year}-${month}-${day} 00:00:00`;
}
function getSubday() {
const days=0 - queryParams.value.subday;
queryParams.value.stime=getDateOffset(days);
queryParams.value.etime=getDateOffset(1);
}
/** 查询采样登记列表 */
function getList() {
if(isEmptyData(queryParams.value.brdh)) proxy.$modal.alert("请刷卡或输入门诊号!");
else {
loading.value = true;
getSubday();
querySQD(queryParams.value).then(response => {
if (isEmptyData(response.data)) proxy.$modal.alert("没有检索的数据!");
reqmainList.value = response.data;
loading.value = false;
single.value=false;
// 新增:数据加载完成后触发全选
// 延迟执行(确保DOM已更新)
setTimeout(() => {
if (tableRef.value) {
tableRef.value.toggleAllSelection(); // 调用全选方法
}
}, 0);
});
}
}
// 取消按钮
function cancel() {
// open.value = false;
// reset();
}
// 表单重置
function reset() {
form.value = {
sqh: null,
xh: null,
sqxmdh: null,
sqxmmc: null,
sl: null,
dj: null,
detailZT: null,
detailJJZT: null,
ksdh: null,
sqys: null,
sqsj: null,
jsys: null,
jssj: null,
brly: null,
brdh: null,
brxm: null,
zt: null,
jjzt: null,
brxb: null,
brsr: null,
jzbz: null,
cp_xmlb: null,
cp_color: null,
cp_cflag: null,
detailBZ1: null,
ch: null,
detailBZ2: null,
bz1: null,
bz2: null,
bz3: null,
yblx: null,
zxys: null,
zxsj: null,
bgddh: null,
nl: null,
nldw: null,
zd: null,
cysj: null
};
freesingle.value=false;
single.value=false;
proxy.resetForm("reqmainRef");
}
/** 搜索按钮操作 */
function handleQuery() {
getList();
}
/** 重置按钮操作 */
function resetQuery() {
proxy.resetForm("queryRef");
handleQuery();
}
// 多选框选中数据
function handleSelectionChange(selection) {
if (isAutoSelect.value) return;
selectedRows.value = selection;
ids.value = selection.map(item => item.sqh);
//console.log('ids:', ids.value);
// console.log('selectedRows:', selectedRows.value);
}
/** 打印选择 */
function printAll(row) {
console.log('idsnew:', idsnew.value);
if (idsnew.value.length=== 0) {
return;
}
apiprintAll(idsnew.value).then(response => {
proxy.$modal.msgSuccess("打印成功");
open.value = false;
freesingle.value=false;
}).catch(() => {
});
}
/** 单打条码*/
function printSigne(row) {
if (idsnew.value.length === 0) {
return;
}
apiprintAll(idsnew.value).then(response => {
proxy.$modal.msgSuccess("打印成功");
open.value = false;
freesingle.value=false;
}).catch(() => {
});
}
/** 打印回单 */
function printBackpaper(row) {
if (idsnew.value.length === 0) {
return;
}
apiprintAll(idsnew.value).then(response => {
proxy.$modal.msgSuccess("打印成功");
open.value = false;
}).catch(() => {
});
}
const totalRows = computed(() => {
return reqmainList.value.length || 0;
});
const totalPrice = computed(() => {
return reqmainList.value.reduce((sum, row) => {
const price = parseFloat(row.dj) || 0;
return sum + price;
}, 0);
});
// 组件挂载时加载字典
onMounted(async () => {
// 加载病人来源字典
const dictRefs = await comDict('PT', 'DP', 'SRD','BT','SX','AU');
// 从 ref 中获取实际数据
dictData.value = {
PT: toRaw(dictRefs.PT.value) || [],
DP: toRaw(dictRefs.DP.value) || [],
SRD: toRaw(dictRefs.SRD.value) || [],
BT: toRaw(dictRefs.BT.value) || [],
SX: toRaw(dictRefs.SX.value) || [],
AU: toRaw(dictRefs.AU.value) || []
};
});
// 表格单元格样式(仅作用于“项目类别”列)
const tableCellStyle = ({ row, column }) => {
// 只对“项目类别”列生效
if (column.label === '项目类别') {
// 1. 转换颜色(十进制→十六进制)
const bgColor = decimalToHexColor(row.cp_color);
// 2. 自动计算文字颜色(确保和背景色对比度足够)
const textColor = getContrastTextColor(bgColor);
return {
backgroundColor: bgColor, // 背景色(转换后的值)
color: textColor, // 文字色(自动适配)
textAlign: 'center', // 文字居中
fontWeight: '500' // 文字加粗(提升可读性)
};
}
return {}; // 其他列保持默认样式
};
// 十进制颜色值转十六进制颜色码(适配BGR转RGB)
const decimalToHexColor = (decimal) => {
if (!decimal && decimal !== 0) return '#FFFFFF'; // 空值默认白色
// 1. 十进制转十六进制(去除前缀0x,大写)
let hex = parseInt(decimal, 10).toString(16).toUpperCase();
// 2. 不足6位则前面补0(确保是6位)
if (hex.length < 6) {
hex = hex.padStart(6, '0'); // 例如:192→"C0"→补0为"0000C0"
}
// 3. BGR转RGB(反转字节顺序:前两位和后两位交换)
// 例:80FFFF → 拆分为80、FF、FF → 反转后FF、FF、80 → FFFF80
const r = hex.substring(4, 6); // 取后两位
const g = hex.substring(2, 4); // 取中间两位
const b = hex.substring(0, 2); // 取前两位
const rgbHex = r + g + b;
return `#${rgbHex}`; // 最终颜色码
};
// 辅助函数:根据背景色计算文字颜色(黑/白)
const getContrastTextColor = (bgColor) => {
// 提取RGB值(如#FFFF80 → R=255, G=255, B=128)
const r = parseInt(bgColor.slice(1, 3), 16);
const g = parseInt(bgColor.slice(3, 5), 16);
const b = parseInt(bgColor.slice(5, 7), 16);
// 计算亮度(标准公式)
const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
// 亮度>0.5用黑色,否则用白色(确保清晰)
return luminance > 0.5 ? '#333333' : '#FFFFFF';
};
</script>
<style scoped lang="scss">
.compact-form .el-form-item {
padding: 5px;
margin-bottom: 5px;
}
.compact-form .el-form-item__label {
padding-bottom: 0px;
}
::v-deep .my-table .el-table__row td {
padding: 1px 0; /* 减小行高 */
}
::v-deep .my-table .el-table__header-wrapper th {
padding: 6px 0; /* 表头内边距 */
background-color: #b3d8ff !important; /* 表头背景色(保留之前的设置) */
color: #333; /* 文字颜色加深,提升可读性 */
font-weight: 500; /* 文字加粗 */
}
::v-deep .my-table .el-table__cell {
padding: 0 2px; /* 减小列间距 */
}
/* 可选:调整表格整体样式 */
::v-deep .my-table {
font-size: 13px; /* 适当减小字体 */
}
::v-deep .my-table .el-table__cell,
::v-deep .my-table .el-table__header-wrapper th {
border-width: 1px;
border-color: #ebeef5;
}
.card-content {
max-height: 450px; /* 设置最大高度 */
overflow-y: auto; /* 超出高度时显示垂直滚动条 */
padding: 5px; /* 保持与卡片默认一致的内边距 */
}
.clickable:hover {
cursor: pointer; /* 鼠标悬停时显示手型 */
transition: all 0.3s; /* 平滑过渡效果 */
color: blue;
}
/* 汇总行样式 */
.table-summary {
display: flex;
align-items: center;
justify-content: flex-start;
padding: 6px 16px;
margin-top: 8px;
background-color: #f5f7fa;
border: 1px solid #ebeef5;
border-radius: 4px;
font-weight: 500;
line-height: 24px; /* 汇总行文字行高 */
.summary-item {
display: flex;
align-items: center;
margin-left: 24px;
.summary-label {
color: #606266;
margin-right: 8px;
}
.summary-value {
color: #303133;
min-width: 40px;
text-align: left;/* 核心:数值左对齐 */
}
/* 单独设置"单价合计"的值为红色 */
&:nth-child(3) .summary-value {
color: #f56c6c; /* Element UI 红色主题色 */
font-weight: 600; /* 可选:加粗字体 */
}
}
}
</style>

View File

@ -62,4 +62,7 @@ export default defineConfig(({ mode, command }) => {
}
}
}
optimizeDeps: {
include: ['jquery', 'select2', 'vue3-select2-component']
}
})