This commit is contained in:
wyuu 2026-04-08 18:04:00 +08:00
parent 38189dfd11
commit 29990c0ba9
16 changed files with 431 additions and 148 deletions

View File

@ -178,4 +178,20 @@ export function querymbmc(data?: Object) {
method: 'get', method: 'get',
params: data params: data
}); });
}
// 查询调整列表
export function queryInputcol(data?: Object) {
return request({
url: '/inputcol/query',
method: 'get',
params: data
});
}
// 整体调整列表
export function saveInputcol(data?: Object) {
return request({
url: '/inputcol/save',
method: 'put',
data: data
});
} }

View File

@ -17,9 +17,10 @@
--> -->
<template> <template>
<div class="select-table-container"> <div class="select-table-container">
<el-select ref="selectTable" v-model="selectShowValue" :placeholder="props.placeholder" :size="props.size" <el-select ref="selectTable" class="select-table__wrapper" v-model="selectShowValue"
:style="{ width: props.width }" @visible-change="visibleChange" @clear="clearHandle" :clearable="props.clearable" :placeholder="props.placeholder" :size="props.size" :style="{ width: props.width }"
:disabled="disabled" v-bind="$attrs"> @visible-change="visibleChange" @clear="clearHandle" :clearable="props.clearable" :disabled="disabled"
v-bind="$attrs">
<template #empty> <template #empty>
<div class="select-table-dropdown"> <div class="select-table-dropdown">
<div style="text-align: left;"> <div style="text-align: left;">
@ -215,6 +216,7 @@ watch(() => props.data, (newVal) => {
// 输入框键盘事件处理(专门处理上下键) // 输入框键盘事件处理(专门处理上下键)
const handleInputKeydown = (e: KeyboardEvent) => { const handleInputKeydown = (e: KeyboardEvent) => {
// 仅处理上下方向回车键 // 仅处理上下方向回车键
if (!['ArrowUp', 'ArrowDown', 'Enter'].includes(e.key)) return; if (!['ArrowUp', 'ArrowDown', 'Enter'].includes(e.key)) return;
// 阻止事件冒泡到输入框父元素 // 阻止事件冒泡到输入框父元素
@ -267,8 +269,14 @@ const handleKeydown = (e: any) => {
tableRef.value.scrollToRow(filterData.value[currentIndex.value]) tableRef.value.scrollToRow(filterData.value[currentIndex.value])
// 回车确认 // 回车确认
if (e.key === "Enter") { if (e.key === "Enter") {
if (searchKey.value.trim() !== '') {
// 如果输入框有内容,回车时先触发一次输入框的筛选逻辑,确保数据是最新的
filterDataHandle();
return
}
const currentRow = filterData.value[currentIndex.value]; const currentRow = filterData.value[currentIndex.value];
handleRowChange(currentRow); handleRowChange(currentRow);
emits('enter-press');
} }
} }
@ -346,9 +354,9 @@ const setLabel = (val: any) => {
const clearHandle = () => { const clearHandle = () => {
selectShowValue.value = ''; selectShowValue.value = '';
currentRow.value = null; currentRow.value = null;
tableRef.value.clearCurrentRow();
emits("update:data", null); emits("update:data", null);
emits('getDataValue', null); emits('getDataValue', null);
tableRef.value?.clearCurrentRow();
}; };
</script> </script>

View File

@ -16,7 +16,8 @@
<vxe-table :data="tableData" :loading="loading" border :checkbox-config="config.checkboxConfig" <vxe-table :data="tableData" :loading="loading" border :checkbox-config="config.checkboxConfig"
:height="scrollYConfig.height" @checkbox-change="handleCheckboxChange" :row-config="rowConfig" :height="scrollYConfig.height" @checkbox-change="handleCheckboxChange" :row-config="rowConfig"
:show-overflow="showOverflow" @current-change="handleRowClick" ref="tableRef" :size="size" :show-overflow="showOverflow" @current-change="handleRowClick" ref="tableRef" :size="size"
:current-row="currentRow" :scroll-y="scrollYConfig" :tooltip-config="{ appendToBody: true, zIndex: 3000 }" :class="{ 'drag-table': enableRowDrag }" :current-row="currentRow" :scroll-y="scrollYConfig"
:tooltip-config="{ appendToBody: true, zIndex: 3000 }"
:header-cell-class-name="enableColumnDrag ? 'el-table-header-cell' : ''" v-bind="$attrs"> :header-cell-class-name="enableColumnDrag ? 'el-table-header-cell' : ''" v-bind="$attrs">
<!-- 动态渲染列 --> <!-- 动态渲染列 -->
<template v-for="(column, i) in columns" :key="`${column.field}-${i}`"> <template v-for="(column, i) in columns" :key="`${column.field}-${i}`">
@ -111,10 +112,15 @@ const props = defineProps({
enableColumnDrag: { enableColumnDrag: {
type: Boolean, type: Boolean,
default: false default: false
},
// 拖拽行
enableRowDrag: {
type: Boolean,
default: false
} }
}) })
const emits = defineEmits(['current-change', "column-drag-end", "selection-change"]) const emits = defineEmits(['current-change', "column-drag-end", "row-drag-end", "selection-change"])
const tableRef = ref<any>(null) const tableRef = ref<any>(null)
const currentRow = ref<any>(null) const currentRow = ref<any>(null)
@ -164,6 +170,10 @@ onMounted(() => {
if (props.enableColumnDrag && tableRef.value) { if (props.enableColumnDrag && tableRef.value) {
initColumnDrag(); initColumnDrag();
} }
if (props.enableRowDrag && tableRef.value) {
initRowDrag();
}
}); });
// 监听数据变化时重置当前行 // 监听数据变化时重置当前行
@ -219,6 +229,38 @@ const initColumnDrag = () => {
}); });
}; };
// 初始化行拖拽
const initRowDrag = () => {
const tableBody = tableRef.value.$el.querySelector('.vxe-table--body-wrapper tbody');
const sortable = new Sortable(tableBody, {
animation: 150, // 拖拽动画时长
ghostClass: 'sortable-ghost', // 拖拽占位符样式
chosenClass: 'sortable-chosen', // 选中行样式
// 拖拽结束回调
onEnd: (evt: any) => {
const { oldIndex, newIndex } = evt
if (oldIndex === newIndex) return // 未改变位置则不处理
// 调整数组顺序
const moveRow = props.tableData.splice(oldIndex, 1)[0]
props.tableData.splice(newIndex, 0, moveRow)
// 重新更新排序值
props.tableData.forEach((item: any, index) => {
item.sort = index + 1
})
// console.log("🚀 ~ initRowDrag ~ props.tableData:", props.tableData)
emits('row-drag-end', {
oldIndex,
newIndex,
list: props.tableData
})
}
})
};
// 暴露公共方法 // 暴露公共方法
defineExpose({ defineExpose({

View File

@ -142,7 +142,7 @@ onMounted(() => {
overflow: hidden; overflow: hidden;
position: relative; position: relative;
//background: #fff; //background: #fff;
background: #0d9488; background: #304156;
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.15); box-shadow: 0 1px 4px rgba(0, 21, 41, 0.15);
//box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08); //box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
display: flex; display: flex;

View File

@ -1,6 +1,7 @@
export interface Emits { export interface Emits {
(e: "update:data", val: any): void; (e: "update:data", val: any): void;
(e: "getDataValue", val: any): void; (e: "getDataValue", val: any): void;
(e: "enter-press"): void;
} }
export interface Props { export interface Props {

View File

@ -258,7 +258,7 @@ interface QueryParams {
const ybJyrq = ref('') const ybJyrq = ref('')
watch(() => labPat.value, (newValue) => { watch(() => labPat.value, (newValue) => {
queryParams.value.ybh = newValue.ybh; queryParams.value.ybh = newValue.ybh ? newValue.ybh : '1';
ybJyrq.value = newValue.jyrq; ybJyrq.value = newValue.jyrq;
if (newValue.jgbz == '2') { if (newValue.jgbz == '2') {
activeName.value = 'first' activeName.value = 'first'
@ -407,7 +407,7 @@ const handleinstrGroupChange = () => {
} }
const mbStore = useCommonStore(); const mbStore = useCommonStore();
const yqHandleChange = () => { const yqHandleChange = () => {
queryParams.value.ybh = '' queryParams.value.ybh = '1'
zbLabResuts.value = []; zbLabResuts.value = [];
labPat.value = {} labPat.value = {}
mbStore.setLxsrList([]); mbStore.setLxsrList([]);
@ -454,7 +454,7 @@ const resultsHandle = (flag: boolean) => {
} }
fetchLabResults() fetchLabResults()
} }
const labInfo: any = ref({}) const labInfo: any = ref({}) // 当前选中样本的基本信息,用于左边和中间表单数据载入和更新
const highlightRowIndex = ref(-1) const highlightRowIndex = ref(-1)
const labPatListRef = ref() const labPatListRef = ref()
//样本列表点击切换样本信息,同步载入左边样本信息表单和中间结果表单 //样本列表点击切换样本信息,同步载入左边样本信息表单和中间结果表单
@ -702,14 +702,6 @@ const searchJobs = async (text: string, page: number, size: number) => {
fetchlabPatList() fetchlabPatList()
} }
// const handleSizeChange = (size: number) => {
// queryParams.value.pageSize = size
// fetchlabPatList()
// }
// const handleCurrentChange = (page: number) => {
// queryParams.value.pageNum = page
// fetchlabPatList()
// }
//载入样本列表(右边labpatlist.vue组件) //载入样本列表(右边labpatlist.vue组件)
const fetchlabPatList = () => { const fetchlabPatList = () => {
@ -735,7 +727,7 @@ const fetchlabPatList = () => {
} }
} else { } else {
labInfo.value = {} labInfo.value = {}
labPat.value = {} labPat.value = { ybh: '1' }
zbLabResuts.value = [] zbLabResuts.value = []
handleCreate() handleCreate()
} }

View File

@ -5,17 +5,17 @@
@keyup.enter="handleInputFocus" /> @keyup.enter="handleInputFocus" />
<el-button type="primary" :size="aotuSize" @click="batchHandle">扫码</el-button> <el-button type="primary" :size="aotuSize" @click="batchHandle">扫码</el-button>
</div> </div>
<el-form :model="labPat" label-width="4.5rem" class="compact-form" label-position="right"> <el-form :model="labPat" ref="formInfoRefs" label-width="4.5rem" class="compact-form" label-position="right">
<div :class="['sh_box', getColor(lastJgbz)]" v-if="lastJgbz != null && lastJgbz != 0 && lastJgbz != 'C'"> <div :class="['sh_box', getColor(lastJgbz)]" v-if="lastJgbz != null && lastJgbz != 0 && lastJgbz != 'C'">
<div class="text">{{ getLableType(lastJgbz) }}</div> <div class="text">{{ getLableType(lastJgbz) }}</div>
</div> </div>
<template v-for="v in labSysList" :key="v.xh"> <template v-for="(v, index) in labSysList" :key="v.xh">
<el-row :gutter="10" v-if="v.mrts == '病人来源'"> <el-row :gutter="10" v-if="v.mrts == '病人来源'">
<el-col :span="18"> <el-col :span="18">
<el-form-item :label="v.zdts" v-if="v.kj == '1'"> <el-form-item :label="v.zdts" v-if="v.kj == '1'">
<SelectTable v-model:data="labPat[v.zdmc]" :fields="brlyFields" :dictType="v.dict" placeholder="" <SelectTable v-model:data="labPat[v.zdmc]" :fields="brlyFields" :dictType="v.dict" placeholder=""
label="label" value="value" objKey="value" :border="true" size="small" label="label" value="value" objKey="value" :border="true" size="small" @getDataValue="handleFieldChange"
@getDataValue="handleFieldChange" /> @enter-press="selectEnter(index)" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6"> <el-col :span="6">
@ -25,37 +25,44 @@
</el-row> </el-row>
<el-form-item :label="v.zdts" v-if="v.kj == '1' && !v.dict && v.mrts != '年龄'"> <el-form-item :label="v.zdts" v-if="v.kj == '1' && !v.dict && v.mrts != '年龄'">
<el-input v-if="v.zdlb == '1'" v-model="labPat[v.zdmc]" @change="handleFieldChange" size="small" /> <el-input v-if="v.zdlb == '1'" v-model="labPat[v.zdmc]" @change="handleFieldChange" size="small"
@keydown.enter="nextFocus" />
<el-date-picker v-if="v.zdlb == '3'" v-model="labPat[v.zdmc]" type="datetime" format="YYYY-MM-DD HH:mm:ss" <el-date-picker v-if="v.zdlb == '3'" v-model="labPat[v.zdmc]" type="datetime" format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss" @change="handleFieldChange" size="small" style="width: 100%;" /> value-format="YYYY-MM-DD HH:mm:ss" @change="handleFieldChange" size="small" style="width: 100%;"
@keydown.enter="nextFocus" />
</el-form-item> </el-form-item>
<el-form-item :label="v.zdts" v-if="v.kj == '1' && v.mrts == '年龄'"> <el-form-item :label="v.zdts" v-if="v.kj == '1' && v.mrts == '年龄'">
<el-col :span="14" v-if="v.mrts == '年龄'"> <el-col :span="14" v-if="v.mrts == '年龄'">
<el-input v-model="labPat[v.zdmc]" @change="handleFieldChange" style="width:100%" size="small" /> <el-input v-model="labPat[v.zdmc]" @change="handleFieldChange" style="width:100%" size="small"
@keydown.enter="nextFocus" />
</el-col> </el-col>
<el-col :span="10"> <el-col :span="10">
<SelectTable v-model:data="labPat.nldw" :fields="ksdhFields" dictType="AU" label="label" value="value" <SelectTable v-model:data="labPat.nldw" :fields="ksdhFields" dictType="AU" label="label" value="value"
objKey="value" :border="true" size="small" @getDataValue="handleFieldChange" placeholder="" /> objKey="value" :border="true" size="small" @getDataValue="handleFieldChange" placeholder=""
@enter-press="selectEnter(index + 1)" />
</el-col> </el-col>
</el-form-item> </el-form-item>
<el-form-item :label="v.zdts" <el-form-item :label="v.zdts"
v-if="v.dict && v.kj == '1' && v.mrts != '病人来源' && v.mrts != '年龄单位' && v.mrts != '检验医师' && v.mrts != '核对医师'"> v-if="v.dict && v.kj == '1' && v.mrts != '病人来源' && v.mrts != '年龄单位' && v.mrts != '检验医师' && v.mrts != '核对医师'">
<SelectTable v-model:data="labPat[v.zdmc]" :fields="ksdhFields" :dictType="v.dict" label="label" value="value" <SelectTable v-model:data="labPat[v.zdmc]" :fields="ksdhFields" :dictType="v.dict" label="label" value="value"
objKey="value" :border="true" size="small" @getDataValue="handleFieldChange" placeholder="" /> objKey="value" :border="true" size="small" @getDataValue="handleFieldChange" placeholder=""
@enter-press="selectEnter(index + 1)" />
</el-form-item> </el-form-item>
<el-form-item :label="v.zdts" v-if="v.mrts == '检验医师' && v.kj == '1'"> <el-form-item :label="v.zdts" v-if="v.mrts == '检验医师' && v.kj == '1'">
<SelectTable v-model:data="labPat[v.zdmc]" :fields="ysFields" :tableData="userList || []" label="nickName" <SelectTable v-model:data="labPat[v.zdmc]" :fields="ysFields" :tableData="userList || []" label="nickName"
value="userName" objKey="userName" :border="true" size="small" @getDataValue="getJyysData" placeholder="" /> value="userName" objKey="userName" :border="true" size="small" @getDataValue="getJyysData" placeholder=""
@enter-press="selectEnter(index + 1)" />
</el-form-item> </el-form-item>
<el-form-item :label="v.zdts" v-if="v.mrts == '核对医师' && v.kj == '1'"> <el-form-item :label="v.zdts" v-if="v.mrts == '核对医师' && v.kj == '1'">
<SelectTable v-model:data="labPat[v.zdmc]" :fields="ysFields" :tableData="userList || []" label="nickName" <SelectTable v-model:data="labPat[v.zdmc]" :fields="ysFields" :tableData="userList || []" label="nickName"
value="userName" objKey="userName" :border="true" size="small" @getDataValue="getHdysData" placeholder="" /> value="userName" objKey="userName" :border="true" size="small" @getDataValue="getHdysData" placeholder=""
@enter-press="selectEnter(index + 1)" />
</el-form-item> </el-form-item>
</template> </template>
</el-form> </el-form>
@ -332,6 +339,63 @@ const getColor = (type: string) => {
return 'default'; return 'default';
} }
} }
const formInfoRefs = useTemplateRef('formInfoRefs')
const currentTarget = ref(null);
// 回车跳转到下一个表单元素
const nextFocus = (e?: Event, idx?: number) => {
if (e) e.preventDefault() // 禁止回车提交表单
// 找到所有可聚焦的表单项:
const els = formInfoRefs.value.$el.querySelectorAll(
'input:not([type="hidden"]):not([disabled]), select:not([disabled]), textarea:not([disabled]), ' +
'.select-table__wrapper .el-select__input:not([disabled]), ' + '.el-date-editor input:not([disabled])'
);
const arr = Array.from(els).filter((el: any) => {
// 额外过滤:排除隐藏元素、禁用状态的父级封装组件(如 SelectTable 被 disabled 时)
const isHidden = el.offsetParent === null;
const isDisabled = el.hasAttribute('disabled') || el.parentElement?.closest('.is-disabled') !== null;
return !isHidden && !isDisabled;
});
let index: number;
if (!idx) {
// 找到当前触发元素在列表中的位置
currentTarget.value = e?.target as HTMLElement;
// 兼容 SelectTable:如果点击的是组件外层,定位到内部输入框
if (currentTarget.value.closest('.select-table-container')) {
currentTarget.value = currentTarget.value.closest('.select-table-container').querySelector('.el-select__input');
}
index = arr.findIndex((item: any) => item === currentTarget.value || item.contains(currentTarget.value));
} else {
index = idx;
}
console.log('arr==>', arr);
// 跳转到下一个可聚焦元素(循环到第一个 if 最后一个)
if (index > -1) {
const nextIndex = (index + 1) % arr.length;
// 确保下一个元素存在且可聚焦
if (arr[nextIndex]) {
nextTick(() => {
(arr[nextIndex] as HTMLElement)?.focus();
});
console.log('arr[nextIndex]==>', arr[nextIndex], index, nextIndex);
// 针对 SelectTable 额外处理:聚焦后激活下拉框
if ((arr[nextIndex] as HTMLElement).closest('.select-table-container')) {
(arr[nextIndex] as HTMLElement).dispatchEvent(new Event('click'));
}
}
}
}
const selectEnter = (index: number) => {
const emptyEvent = new Event('keydown', { cancelable: true });
nextFocus(emptyEvent, index + 1)
}
onMounted(() => { onMounted(() => {
// 监听保存病人结果 // 监听保存病人结果
emitter.on('wswSaveResult', () => { emitter.on('wswSaveResult', () => {

View File

@ -1,6 +1,7 @@
<template> <template>
<div> <div>
<el-dialog v-model="visible" :title="title" :width="500" :close-on-click-modal="false" :draggable="true"> <el-dialog v-model="visible" :title="title" :width="500" :close-on-click-modal="false" :draggable="true"
@close="cancel">
<el-form ref="formRef" :model="formValue" label-width="100px"> <el-form ref="formRef" :model="formValue" label-width="100px">
<!-- 用户代号 --> <!-- 用户代号 -->
<el-form-item label="用户代号:"> <el-form-item label="用户代号:">
@ -99,9 +100,12 @@ const handleConfirm = async () => {
// 表单验证 // 表单验证
const valid = await formRef.value.validate(); const valid = await formRef.value.validate();
if (valid) { if (valid) {
checkYsUser({ ...props.formValue, ...props.labPatKey }).then((res: any) => { console.log('Form is valid', props.formValue);
checkYsUser({ ...props.labPatKey, ...props.formValue, }).then((res: any) => {
if (res.code == 0) { if (res.code == 0) {
emit('confirm', props.formValue) emit('confirm', props.formValue)
visible.value = false
} }
}) })

View File

@ -302,7 +302,7 @@ const handleinstrGroupChange = () => {
} }
const yqHandleChange = () => { const yqHandleChange = () => {
queryParams.value.ybh = '' queryParams.value.ybh = '1'
labResuts.value = [] labResuts.value = []
labPat.value = {} labPat.value = {}
mbStore.setLxsrList([]); mbStore.setLxsrList([]);

View File

@ -5,17 +5,17 @@
@keyup.enter="handleInputFocus" /> @keyup.enter="handleInputFocus" />
<el-button type="primary" :size="aotuSize" @click="batchHandle">扫码</el-button> <el-button type="primary" :size="aotuSize" @click="batchHandle">扫码</el-button>
</div> </div>
<el-form :model="labPat" label-width="4.5rem" class="compact-form" label-position="right"> <el-form :model="labPat" ref="formInfoRefs" label-width="4.5rem" class="compact-form" label-position="right">
<div :class="['sh_box', getColor(lastJgbz)]" v-if="lastJgbz != null && lastJgbz != 0 && lastJgbz != 'C'"> <div :class="['sh_box', getColor(lastJgbz)]" v-if="lastJgbz != null && lastJgbz != 0 && lastJgbz != 'C'">
<div class="text">{{ getLableType(lastJgbz) }}</div> <div class="text">{{ getLableType(lastJgbz) }}</div>
</div> </div>
<template v-for="v in labSysList" :key="v.xh"> <template v-for="(v, index) in labSysList" :key="v.xh">
<el-row :gutter="10" v-if="v.mrts == '病人来源'"> <el-row :gutter="10" v-if="v.mrts == '病人来源'">
<el-col :span="18"> <el-col :span="18">
<el-form-item :label="v.zdts" v-if="v.kj == '1'"> <el-form-item :label="v.zdts" v-if="v.kj == '1'">
<SelectTable v-model:data="labPat[v.zdmc]" :fields="brlyFields" :dictType="v.dict" placeholder="" <SelectTable v-model:data="labPat[v.zdmc]" :fields="brlyFields" :dictType="v.dict" placeholder=""
label="label" value="value" objKey="value" :border="true" size="small" label="label" value="value" objKey="value" size="small" @getDataValue="handleFieldChange"
@getDataValue="handleFieldChange" /> @enter-press="selectEnter(index)" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6"> <el-col :span="6">
@ -25,37 +25,44 @@
</el-row> </el-row>
<el-form-item :label="v.zdts" v-if="v.kj == '1' && !v.dict && v.mrts != '年龄'"> <el-form-item :label="v.zdts" v-if="v.kj == '1' && !v.dict && v.mrts != '年龄'">
<el-input v-if="v.zdlb == '1'" v-model="labPat[v.zdmc]" @change="handleFieldChange" size="small" /> <el-input v-if="v.zdlb == '1'" v-model="labPat[v.zdmc]" @change="handleFieldChange" size="small"
@keydown.enter="nextFocus" />
<el-date-picker v-if="v.zdlb == '3'" v-model="labPat[v.zdmc]" type="datetime" format="YYYY-MM-DD HH:mm:ss" <el-date-picker v-if="v.zdlb == '3'" v-model="labPat[v.zdmc]" type="datetime" format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss" @change="handleFieldChange" size="small" style="width: 100%;" /> value-format="YYYY-MM-DD HH:mm:ss" @change="handleFieldChange" size="small" style="width: 100%;"
@keydown.enter="nextFocus" />
</el-form-item> </el-form-item>
<el-form-item :label="v.zdts" v-if="v.kj == '1' && v.mrts == '年龄'"> <el-form-item :label="v.zdts" v-if="v.kj == '1' && v.mrts == '年龄'">
<el-col :span="14" v-if="v.mrts == '年龄'"> <el-col :span="14" v-if="v.mrts == '年龄'">
<el-input v-model="labPat[v.zdmc]" @change="handleFieldChange" style="width:100%" size="small" /> <el-input v-model="labPat[v.zdmc]" @change="handleFieldChange" style="width:100%" size="small"
@keydown.enter="nextFocus" />
</el-col> </el-col>
<el-col :span="10"> <el-col :span="10">
<SelectTable v-model:data="labPat.nldw" :fields="ksdhFields" dictType="AU" label="label" value="value" <SelectTable v-model:data="labPat.nldw" :fields="ksdhFields" dictType="AU" label="label" value="value"
objKey="value" :border="true" size="small" @getDataValue="handleFieldChange" placeholder="" /> objKey="value" size="small" @getDataValue="handleFieldChange" placeholder=""
@enter-press="selectEnter(index + 1)" />
</el-col> </el-col>
</el-form-item> </el-form-item>
<el-form-item :label="v.zdts" <el-form-item :label="v.zdts"
v-if="v.dict && v.kj == '1' && v.mrts != '病人来源' && v.mrts != '年龄单位' && v.mrts != '检验医师' && v.mrts != '核对医师'"> v-if="v.dict && v.kj == '1' && v.mrts != '病人来源' && v.mrts != '年龄单位' && v.mrts != '检验医师' && v.mrts != '核对医师'">
<SelectTable v-model:data="labPat[v.zdmc]" :fields="ksdhFields" :dictType="v.dict" label="label" value="value" <SelectTable v-model:data="labPat[v.zdmc]" :fields="ksdhFields" :dictType="v.dict" label="label" value="value"
objKey="value" :border="true" size="small" @getDataValue="handleFieldChange" placeholder="" /> objKey="value" size="small" @getDataValue="handleFieldChange" placeholder=""
@enter-press="selectEnter(index + 1)" />
</el-form-item> </el-form-item>
<el-form-item :label="v.zdts" v-if="v.mrts == '检验医师' && v.kj == '1'"> <el-form-item :label="v.zdts" v-if="v.mrts == '检验医师' && v.kj == '1'">
<SelectTable v-model:data="labPat[v.zdmc]" :fields="ysFields" :tableData="userList || []" label="nickName" <SelectTable v-model:data="labPat[v.zdmc]" :fields="ysFields" :tableData="userList || []" label="nickName"
value="userName" objKey="userName" :border="true" size="small" @getDataValue="getJyysData" placeholder="" /> value="userName" objKey="userName" size="small" @getDataValue="getJyysData" placeholder=""
@enter-press="selectEnter(index + 1)" />
</el-form-item> </el-form-item>
<el-form-item :label="v.zdts" v-if="v.mrts == '核对医师' && v.kj == '1'"> <el-form-item :label="v.zdts" v-if="v.mrts == '核对医师' && v.kj == '1'">
<SelectTable v-model:data="labPat[v.zdmc]" :fields="ysFields" :tableData="userList || []" label="nickName" <SelectTable v-model:data="labPat[v.zdmc]" :fields="ysFields" :tableData="userList || []" label="nickName"
value="userName" objKey="userName" :border="true" size="small" @getDataValue="getHdysData" placeholder="" /> value="userName" objKey="userName" size="small" @getDataValue="getHdysData" placeholder=""
@enter-press="selectEnter(index + 1)" />
</el-form-item> </el-form-item>
</template> </template>
</el-form> </el-form>
@ -112,7 +119,6 @@ const lastJgbz = ref();
const sqhValue = ref(''); // 条码号 const sqhValue = ref(''); // 条码号
const sqhRef = ref(); const sqhRef = ref();
watch(() => props.labPat, (newVal) => { watch(() => props.labPat, (newVal) => {
// console.log('newVal==>', newVal);
lastValue.value = JSON.stringify(newVal); lastValue.value = JSON.stringify(newVal);
lastJgbz.value = newVal?.jgbz; lastJgbz.value = newVal?.jgbz;
sqhValue.value = ''; sqhValue.value = '';
@ -326,6 +332,62 @@ const getColor = (type: string) => {
return 'default'; return 'default';
} }
} }
const formInfoRefs = useTemplateRef('formInfoRefs')
const currentTarget = ref(null);
// 回车跳转到下一个表单元素
const nextFocus = (e?: Event, idx?: number) => {
if (e) e.preventDefault() // 禁止回车提交表单
// 找到所有可聚焦的表单项:
const els = formInfoRefs.value.$el.querySelectorAll(
'input:not([type="hidden"]):not([disabled]), select:not([disabled]), textarea:not([disabled]), ' +
'.select-table__wrapper .el-select__input:not([disabled]), ' + '.el-date-editor input:not([disabled])'
);
const arr = Array.from(els).filter((el: any) => {
// 额外过滤:排除隐藏元素、禁用状态的父级封装组件(如 SelectTable 被 disabled 时)
const isHidden = el.offsetParent === null;
const isDisabled = el.hasAttribute('disabled') || el.parentElement?.closest('.is-disabled') !== null;
return !isHidden && !isDisabled;
});
let index: number;
if (!idx) {
// 找到当前触发元素在列表中的位置
currentTarget.value = e?.target as HTMLElement;
// 兼容 SelectTable:如果点击的是组件外层,定位到内部输入框
if (currentTarget.value.closest('.select-table-container')) {
currentTarget.value = currentTarget.value.closest('.select-table-container').querySelector('.el-select__input');
}
index = arr.findIndex((item: any) => item === currentTarget.value || item.contains(currentTarget.value));
} else {
index = idx;
}
// 跳转到下一个可聚焦元素(循环到第一个 if 最后一个)
if (index > -1) {
const nextIndex = (index + 1) % arr.length;
// 确保下一个元素存在且可聚焦
if (arr[nextIndex]) {
nextTick(() => {
(arr[nextIndex] as HTMLElement)?.focus();
});
// 针对 SelectTable 额外处理:聚焦后激活下拉框
if ((arr[nextIndex] as HTMLElement).closest('.select-table-container')) {
(arr[nextIndex] as HTMLElement).dispatchEvent(new Event('click'));
}
}
}
}
const selectEnter = (index: number) => {
const emptyEvent = new Event('keydown', { cancelable: true });
nextFocus(emptyEvent, index + 1)
}
onMounted(() => { onMounted(() => {
// 监听保存病人结果 // 监听保存病人结果
emitter.on('saveResult', () => { emitter.on('saveResult', () => {

View File

@ -0,0 +1,117 @@
/**
* @file index.vue 仪器默认参数设置
* @author: w
* @since: 2026-04-03
*/
<template>
<div class="params-box">
<el-row :gutter="10" class="table-toolbar">
<el-col :span="1.5">
<el-button type="primary" plain icon="Check" @click="handleSave">保存</el-button>
</el-col>
</el-row>
<div class="table-box">
<CustomVxeTable :table-data="tableData" :columns="tableColumns" size="small"
:scrollYConfig="{ enabled: true, rSize: 30, height: '100%', }" class="mytable-style" ref="tableRef"
:enableRowDrag="true" @row-drag-end="handleRowDragEnd">
<template #zdts="{ row }">
<el-input v-model="row.zdts" placeholder="请输入内容" class="full-width-input" />
</template>
<!-- 默认值 -->
<template #mrz="{ row }">
<SelectTable v-model:data="row.mrz" v-if="row.dict" :dictType="row.dict" objKey="value"
class="full-width-input" placeholder="" />
<el-input v-model="row.mrz" placeholder="请输入内容" class="full-width-input" v-else />
</template>
<template #mrts="{ row }">
<el-input v-model="row.mrts" placeholder="请输入内容" class="full-width-input" />
</template>
<template #kj="{ row }">
<el-checkbox v-model="row.kj" true-value="1" false-value="0" />
</template>
<template #kybj="{ row }">
<el-checkbox v-model="row.kybj" true-value="1" false-value="0" />
</template>
</CustomVxeTable>
</div>
</div>
</template>
<script setup lang="ts">
import { queryInputcol, saveInputcol } from '@/api/liswork/xtwh/ComOpt'
import { ElMessage } from 'element-plus'
const yq = defineModel<string>()
const tableData = ref([])
const tableColumns = ref([
{ field: 'zdts', title: '字段名称', align: 'center', slotName: 'zdts', resizable: true },
{ field: 'mrz', title: '默认值', align: 'center', slotName: 'mrz', resizable: true },
{ field: 'mrts', title: '提示文字', align: 'center', slotName: 'mrts', resizable: true },
{ field: 'kj', title: '可见', align: 'center', slotName: 'kj', resizable: true },
{ field: 'kybj', title: '可以编辑', align: 'center', slotName: 'kybj', resizable: true },
])
const handleRowDragEnd = (data: any) => {
tableData.value = []
// 更新行顺序
nextTick(() => {
tableData.value = data.list.map((item: any) => {
return {
...item,
xh: item.sort * 10,
}
})
})
}
const tableRef = useTemplateRef('tableRef')
const handleSave = () => {
saveInputcol(tableData.value).then(res => {
if (res.code == 0) {
ElMessage.success('保存成功')
}
})
}
const getParamsList = async () => {
queryInputcol({ yq: yq.value }).then(res => {
tableData.value = res.data
})
}
watch(yq, (newVal) => {
if (newVal) {
getParamsList()
}
}, {
immediate: true,
deep: true
})
</script>
<style scoped lang="scss">
.params-box {
height: calc(100% - 58px);
}
.table-box {
height: calc(100% - 45px);
}
.table-toolbar {
margin-bottom: 8px;
height: 36px;
line-height: 36px;
}
/* 可拖拽表格行样式提示 */
:deep(.drag-table .vxe-body--row) {
cursor: move;
/* 鼠标移入行显示拖拽光标 */
transition: background-color 0.2s;
}
</style>

View File

@ -14,7 +14,8 @@
</el-col> --> </el-col> -->
</el-row> </el-row>
<el-form ref="form" :model="formData" :rules="rules" label-width="120px" class="form-inline" inline> <el-form ref="form" :model="formData" :rules="rules" label-width="120px" class="form-inline" inline
:validate-on-rule-change="false">
<div style="display: flex;"> <div style="display: flex;">
<el-form-item label="项目" prop="xmdh"> <el-form-item label="项目" prop="xmdh">
<SelectTable v-model:data="xmdh" :tableData="xmList" style="width: 12rem;" @getDataValue='getXmInfo' /> <SelectTable v-model:data="xmdh" :tableData="xmList" style="width: 12rem;" @getDataValue='getXmInfo' />

View File

@ -54,7 +54,7 @@ const tableConfig = ref({
}) })
//退拽属性 //拖拽属性
const handleRowDragEnd = (data: any) => { const handleRowDragEnd = (data: any) => {
// 更新行顺序 // 更新行顺序
dataList.value = data.list.map((item: any) => { dataList.value = data.list.map((item: any) => {

View File

@ -49,6 +49,7 @@ import { useCommonStore } from '@/store/modules/commonStore';
import SysGlobal from './components/sysGlobal/index.vue' import SysGlobal from './components/sysGlobal/index.vue'
import SysInput from './components/sysInput/index.vue' import SysInput from './components/sysInput/index.vue'
import SysReport from './components/sysReport/index.vue' import SysReport from './components/sysReport/index.vue'
import SysDefaultParams from './components/sysDefaultParams/index.vue'
import SysParameter from './components/sysParameter/index.vue' import SysParameter from './components/sysParameter/index.vue'
import SysChannel from './components/sysChannel/index.vue' import SysChannel from './components/sysChannel/index.vue'
import SysSort from './components/sysSort/index.vue' import SysSort from './components/sysSort/index.vue'
@ -108,12 +109,13 @@ const queryParams = ref<QueryParams>({
const tabList = [ const tabList = [
{ key: 'SysGlobal', label: '全局设定', component: SysGlobal }, { key: 'SysGlobal', label: '全局设定', component: SysGlobal },
{ key: 'SysInput', label: '界面设定', component: SysInput }, { key: 'SysInput', label: '界面设定', component: SysInput },
{ key: 'SysDefaultParams', label: '默认界面参数', component: SysDefaultParams },
{ key: 'SysParameter', label: '参数', component: SysParameter }, { key: 'SysParameter', label: '参数', component: SysParameter },
{ key: 'SysChannel', label: '通道号', component: SysChannel }, { key: 'SysChannel', label: '通道号', component: SysChannel },
{ key: 'SysSort', label: '项目排序', component: SysSort }, { key: 'SysSort', label: '项目排序', component: SysSort },
{ key: 'SysReport', label: '报告单设置', component: SysReport }, { key: 'SysReport', label: '报告单设置', component: SysReport },
] ]
const activeName = ref('SysGlobal') const activeName = ref('SysDefaultParams')
// 计算当前要渲染的组件 // 计算当前要渲染的组件
const currentComponent = computed(() => { const currentComponent = computed(() => {

View File

@ -1,8 +1,6 @@
<template> <template>
<div class="login"> <div class="login">
<!-- <FloatingLines :enabled-waves="['top', 'middle', 'bottom']" :line-count="[10, 15, 20]" :line-distance="[8, 6, 4]" <el-form ref="loginRef" class="login-form" :model="loginForm" :rules="loginRules" :hide-required-asterisk="true">
:bend-radius="5.0" :bend-strength="-0.5" :interactive="true" :parallax="true" /> -->
<el-form ref="loginRef" class="login-form">
<div class="login-header"> <div class="login-header">
<div class="login-logo"> <div class="login-logo">
<img src="@/assets/images/logo_new.png" alt="系统Logo" /> <img src="@/assets/images/logo_new.png" alt="系统Logo" />
@ -17,8 +15,9 @@
<el-tabs v-model="activeName" type="card" @tab-click="handleClick" class="login-tabs"> <el-tabs v-model="activeName" type="card" @tab-click="handleClick" class="login-tabs">
<!-- 工号登录 Tab --> <!-- 工号登录 Tab -->
<el-tab-pane label="账号密码登录" name="first"> <el-tab-pane label="账号密码登录" name="first">
<el-form-item label="医疗机构:" prop="loginYLJG" class="custom-select"> <el-form-item label="医疗机构:" prop="loginParam.loginYLJG" class="custom-select">
<el-select v-model="loginForm.loginParam.loginYLJG" placeholder="请选择医疗机构" style="width: 100%"> <el-select v-model="loginForm.loginParam.loginYLJG" placeholder="请选择医疗机构" style="width: 100%"
@change="handleChange">
<template #prefix> <template #prefix>
<svg-icon icon-class="international" class="el-input__icon input-icon" /> <svg-icon icon-class="international" class="el-input__icon input-icon" />
</template> </template>
@ -26,7 +25,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="用户代号:" prop="username"> <el-form-item label="用户工号:" prop="username">
<el-input v-model="loginForm.username" type="text" size="large" auto-complete="off" placeholder="账号"> <el-input v-model="loginForm.username" type="text" size="large" auto-complete="off" placeholder="账号">
<template #prefix> <template #prefix>
<svg-icon icon-class="user" class="el-input__icon input-icon" /> <svg-icon icon-class="user" class="el-input__icon input-icon" />
@ -42,12 +41,6 @@
</template> </template>
</el-input> </el-input>
</el-form-item> </el-form-item>
<!-- 修复:移除空的el-form-item,验证码关闭时不渲染任何内容 -->
<el-form-item prop="code" v-if="!captchaEnabled" size="large">
</el-form-item>
<el-form-item prop="code" label="验 证 码 :" v-if="captchaEnabled"> <el-form-item prop="code" label="验 证 码 :" v-if="captchaEnabled">
<el-input v-model="loginForm.code" size="large" auto-complete="off" placeholder="验证码" style="width: 53%" <el-input v-model="loginForm.code" size="large" auto-complete="off" placeholder="验证码" style="width: 53%"
@keyup.enter="handleLogin"> @keyup.enter="handleLogin">
@ -75,7 +68,7 @@
<el-tab-pane label="扫码登录" name="second"> <el-tab-pane label="扫码登录" name="second">
<div class="tab-placeholder"> <div class="tab-placeholder">
<el-icon class="placeholder-icon"> <el-icon class="placeholder-icon">
<Sms /> <!-- <Sms /> -->
</el-icon> </el-icon>
<p>正在加载二维码...</p> <p>正在加载二维码...</p>
<el-button type="success" icon="wechat" class="wechat-login-btn">刷新二维码</el-button> <el-button type="success" icon="wechat" class="wechat-login-btn">刷新二维码</el-button>
@ -85,7 +78,7 @@
<el-tab-pane label="UKEY登录" name="third"> <el-tab-pane label="UKEY登录" name="third">
<div class="tab-placeholder"> <div class="tab-placeholder">
<el-icon class="placeholder-icon"> <el-icon class="placeholder-icon">
<Wechat /> <!-- <Wechat /> -->
</el-icon> </el-icon>
<p>UKEY登录功能开发中...</p> <p>UKEY登录功能开发中...</p>
</div> </div>
@ -94,7 +87,9 @@
</el-form> </el-form>
<div class="el-login-footer"> <div class="el-login-footer">
<span>版权所有(R)2022-2026 {{ oem.compay }} 电话:{{ oem.phone }} E-mail:{{ oem.Email }} version:{{ oem.version }}</span> <span>版权所有(R){{ oem.copyrightyear }} {{ oem.compay }} 电话:{{ oem.phone }} E-mail:{{ oem.Email }} version:{{
oem.version
}}</span>
</div> </div>
</div> </div>
</template> </template>
@ -102,12 +97,11 @@
<script setup> <script setup>
import { ref, watch, getCurrentInstance, onMounted } from 'vue'; import { ref, watch, getCurrentInstance, onMounted } from 'vue';
import { useRoute, useRouter } from 'vue-router'; import { useRoute, useRouter } from 'vue-router';
import { useFingerprint } from '@/utils/useFingerprint'; import { getCodeImg, getInfo, getLocalconfig, login } from "@/api/login";
import { getCodeImg, getInfo, getLocalconfig } from "@/api/login";
import Cookies from "js-cookie"; import Cookies from "js-cookie";
import { encrypt, decrypt } from "@/utils/jsencrypt"; import { encrypt, decrypt } from "@/utils/jsencrypt";
import useUserStore from '@/store/modules/user'; import useUserStore from '@/store/modules/user';
import FloatingLines from '@/components/Ballpit/index.vue';
import { useCommonStore } from '@/store/modules/commonStore' import { useCommonStore } from '@/store/modules/commonStore'
const mbStore = useCommonStore(); const mbStore = useCommonStore();
// 初始化响应式变量 // 初始化响应式变量
@ -116,31 +110,32 @@ const userStore = useUserStore();
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
const oem = ref({ const oem = ref({
appname: "实验室信息管理系统", appname: "区域检验数据平台",
phone: "", phone: "",
compay: "", compay: "",
version: "", version: "",
Email: "" Email: "",
copyrightyear: ""
}); });
const loginRef = ref(null); // 修复:直接用ref获取表单引用 const loginRef = useTemplateRef('loginRef');
const loginForm = ref({ const loginForm = ref({
username: "admin", username: "",
password: "", password: "",
rememberMe: false, rememberMe: false,
code: "", code: "",
uuid: "", uuid: "",
loginParam: { loginYLJG: "", localid: "" } loginParam: { loginYLJG: '1', localid: undefined, loginYLJGName: '' }
}); });
const selectOptions = ref([{ id: '1', name: '总院' }]); const selectOptions = ref([]);
const loginRules = ref({ // 修复:改为ref响应式,方便动态修改 const loginRules = ref({
username: [{ required: true, trigger: "blur", message: "请输入您的账号" }], 'loginParam.loginYLJG': [{ required: true, message: '请选择医疗机构', trigger: 'change' }],
// password: [{ required: true, trigger: "blur", message: "请输入您的密码" }], username: [{ required: true, trigger: "blur", message: "请输入您的工号" }],
hospid: [{ required: true, message: '请选择医疗机构', trigger: 'change' }], password: [{ required: true, trigger: "blur", message: "请输入您的密码" }],
code: [{ required: true, trigger: "change", message: "请输入验证码" }] code: [{ required: true, trigger: "change", message: "请输入验证码" }]
}); });
const codeUrl = ref(""); const codeUrl = ref("");
const loading = ref(false); const loading = ref(false);
const captchaEnabled = ref(true); const captchaEnabled = ref(false);
const register = ref(false); const register = ref(false);
const redirect = ref(undefined); const redirect = ref(undefined);
@ -155,32 +150,43 @@ watch(
{ immediate: true, deep: false } { immediate: true, deep: false }
); );
// 登录方法(修复proxy.$refs问题) const handleChange = (value) => {
const item = selectOptions.value.find(item => item.id == value);
loginForm.value.loginParam.loginYLJG = value;
loginForm.value.loginParam.loginYLJGName = item?.name || '';
}
// 登录方法
const handleLogin = async () => { const handleLogin = async () => {
loginForm.value.loginParam.loginYLJG loginRef.value.validate((valid) => {
loading.value = true; if (valid) {
Cookies.set("czlis_username", loginForm.value.username, { expires: 30 }); loading.value = true;
Cookies.set("czlis_loginYLJG", loginForm.value.loginParam.loginYLJG, { expires: 30 }); Cookies.set("czlis_username", loginForm.value.username, { expires: 30 });
// 调用action的登录方法 Cookies.set("czlis_loginYLJG", loginForm.value.loginParam.loginYLJG, { expires: 30 });
userStore.login(loginForm.value).then(() => { Cookies.set("czlis_loginYLJGName", loginForm.value.loginParam.loginYLJGName, { expires: 30 });
const query = route.query; // loginForm.value.password = encrypt(loginForm.value.password); // 密码加密
const otherQueryParams = Object.keys(query).reduce((acc, cur) => {
if (cur !== "redirect") { userStore.login(loginForm.value).then(() => {
acc[cur] = query[cur]; const query = route.query;
} const otherQueryParams = Object.keys(query).reduce((acc, cur) => {
return acc; if (cur !== "redirect") {
}, {}); acc[cur] = query[cur];
const targetPath = redirect.value || "/"; }
if (route.path !== targetPath) { return acc;
router.push({ path: targetPath, query: otherQueryParams }); }, {});
const targetPath = redirect.value || "/";
if (route.path !== targetPath) {
router.push({ path: targetPath, query: otherQueryParams });
}
}).catch(() => {
loading.value = false;
// 重新获取验证码
if (captchaEnabled.value) {
getCode();
}
});
} }
}).catch(() => { })
loading.value = false;
// 重新获取验证码
if (captchaEnabled.value) {
getCode();
}
});
}; };
// 获取验证码 // 获取验证码
@ -191,12 +197,6 @@ const getCode = () => {
codeUrl.value = "data:image/gif;base64," + res.img; codeUrl.value = "data:image/gif;base64," + res.img;
loginForm.value.uuid = res.uuid; loginForm.value.uuid = res.uuid;
} }
// 验证码关闭时移除校验规则,避免报错
if (!captchaEnabled.value) {
loginRules.value.code = [];
} else {
loginRules.value.code = [{ required: true, trigger: "change", message: "请输入验证码" }];
}
}); });
}; };
@ -204,70 +204,44 @@ const getCode = () => {
const getCookie = () => { const getCookie = () => {
const cookieUsername = Cookies.get("czlis_username"); const cookieUsername = Cookies.get("czlis_username");
const cookieloginYLJG = Cookies.get("czlis_loginYLJG"); const cookieloginYLJG = Cookies.get("czlis_loginYLJG");
//console.log('cookieloginYLJG', cookieloginYLJG); loginForm.value.username = cookieUsername;
if (cookieUsername !== undefined && cookieUsername !== null && cookieUsername !== "") { if (cookieloginYLJG) {
loginForm.value.username = cookieUsername;
}
if (cookieloginYLJG !== undefined && cookieloginYLJG !== null && cookieloginYLJG !== "") {
loginForm.value.loginParam.loginYLJG = cookieloginYLJG; loginForm.value.loginParam.loginYLJG = cookieloginYLJG;
loginForm.value.loginParam.loginYLJGName = selectOptions.value.find(item => item.id == cookieloginYLJG)?.name || '';
} else {
loginForm.value.loginParam.loginYLJG = selectOptions.value[0]?.id || '1';
loginForm.value.loginParam.loginYLJGName = selectOptions.value[0]?.name || '';
} }
//console.log('loginForm', loginForm);
}; };
// 获取本地配置 // 获取本地配置
const Localconfig = (localid) => { const Localconfig = () => {
getLocalconfig({ localid }).then(res => { getLocalconfig().then(res => {
if (res) { if (res) {
const { localconfig, hosplist, oem: oemData } = res; const { localconfig, hosplist, oem: oemData } = res;
mbStore.setDefaultConfig(localconfig) mbStore.setDefaultConfig(localconfig)
// 修复:赋值oem数据,显示动态标题
if (oemData) oem.value = oemData; if (oemData) oem.value = oemData;
// console.log('oemData', oemData); selectOptions.value = hosplist || [];
// console.log('oem', oem.value); getCookie();
// 修复:判重后更新下拉选项,避免递归
if (JSON.stringify(selectOptions.value) !== JSON.stringify(hosplist)) {
selectOptions.value = hosplist || [{ id: '1', name: '总院' }];
// 判重后赋值,避免重复修改触发更新
if (!selectOptions.value.some(item => item.id === loginForm.value.hospid)) {
loginForm.value.loginParam.loginYLJG = selectOptions.value[0]?.id || '1';
}
getCookie();
}
} }
}).catch(err => { }).catch(err => {
console.error("获取本地配置失败:", err); console.error("获取本地配置失败:", err);
}); });
}; };
// 获取指纹并加载配置
const { getFingerprint } = useFingerprint();
const refreshFingerprint = async () => {
try {
const res = await getFingerprint();
loginForm.value.loginParam.localid = res.visitorId
Localconfig(res.visitorId);
} catch (err) {
console.error("获取指纹失败:", err);
Localconfig("default"); // 兜底使用默认ID
}
};
// Tab切换事件(移除activeName手动赋值,避免递归) // Tab切换事件(移除activeName手动赋值,避免递归)
const handleClick = (tab) => { const handleClick = (tab) => {
console.log('当前Tab:', tab.name); // console.log('当前Tab:', tab.name);
// 仅在切回账号密码登录时刷新验证码 // 仅在切回账号密码登录时刷新验证码
if (tab.name === 'first' && captchaEnabled.value) { if (tab.name === 'first' && captchaEnabled.value) {
getCode(); getCode();
} }
}; };
// 页面挂载时初始化
onMounted(() => { Localconfig();
refreshFingerprint(); getCode();
getCode();
});
</script> </script>
<style lang='scss' scoped> <style lang='scss' scoped>

View File

@ -8,7 +8,7 @@
/* 严格的类型检查选项 */ /* 严格的类型检查选项 */
"strict": true /* 启用所有严格的类型检查选项。 */, "strict": true /* 启用所有严格的类型检查选项。 */,
"noImplicitAny": false,
/* 模块解析选项 */ /* 模块解析选项 */
"moduleResolution": "node" /* 指定模块解析策略:'node'(Node.js)或'classic'(TypeScript 1.6之前版本)。*/, "moduleResolution": "node" /* 指定模块解析策略:'node'(Node.js)或'classic'(TypeScript 1.6之前版本)。*/,
"baseUrl": "." /* 用于解析非绝对模块名称的基准目录。 */, "baseUrl": "." /* 用于解析非绝对模块名称的基准目录。 */,