项目排序

This commit is contained in:
wyuu 2025-12-18 17:31:21 +08:00
parent 3af945b0f3
commit 9e5365c96f
10 changed files with 119 additions and 204 deletions

View File

@ -116,7 +116,7 @@ const visibleChange = (val: any) => {
currentIndex.value = filterData.value.findIndex(item => item[props.value!] === props.data); currentIndex.value = filterData.value.findIndex(item => item[props.value!] === props.data);
if (currentIndex.value >= 0) { if (currentIndex.value >= 0) {
tableRef.value.setCurrentRow(filterData.value[currentIndex.value]); tableRef.value.setCurrentRow(filterData.value[currentIndex.value]);
tableRef.value.setScrollTop(currentIndex.value * 30); tableRef.value.setScrollTop(currentIndex.value);
} }
}, 10); }, 10);
} }
@ -238,7 +238,7 @@ const handleKeydown = (e: any) => {
tableRef.value.setCurrentRow(filterData.value[currentIndex.value]); tableRef.value.setCurrentRow(filterData.value[currentIndex.value]);
// 滚动到当前行 // 滚动到当前行
tableRef.value.setScrollTop(currentIndex.value * 30); tableRef.value.setScrollTop(currentIndex.value);
// 回车确认 // 回车确认
if (e.key === "Enter") { if (e.key === "Enter") {

View File

@ -6,8 +6,9 @@
:highlight-current-row="config.highlightCurrentRow || false" :row-class-name="config.rowClassName" :highlight-current-row="config.highlightCurrentRow || false" :row-class-name="config.rowClassName"
:header-cell-style="config.headerCellStyle" :cell-style="config.cellStyle" :max-height="config.maxHeight" :header-cell-style="config.headerCellStyle" :cell-style="config.cellStyle" :max-height="config.maxHeight"
:show-summary="config.summary" :summary-method="getSummaries" :sum-text="config.sumText" :height="config.height" :show-summary="config.summary" :summary-method="getSummaries" :sum-text="config.sumText" :height="config.height"
:size="config.size || 'default'" :empty-text="config.emptyText || '暂无数据'" :row-key="config.key" :class="{ 'drag-table': enableRowDrag }" :size="config.size || 'default'"
@selection-change="handleSelectionChange" @current-change="handleCurrentChange" @row-click="handleRowClick" :empty-text="config.emptyText || '暂无数据'" @selection-change="handleSelectionChange"
@current-change="handleCurrentChange" @row-click="handleRowClick"
:header-cell-class-name="enableColumnDrag ? 'el-table-header-cell' : ''" @row-dblclick="handleRowDblclick" :header-cell-class-name="enableColumnDrag ? 'el-table-header-cell' : ''" @row-dblclick="handleRowDblclick"
@sort-change="handleSortChange" v-bind="$attrs"> @sort-change="handleSortChange" v-bind="$attrs">
@ -137,6 +138,11 @@ const props = defineProps({
enableColumnDrag: { enableColumnDrag: {
type: Boolean, type: Boolean,
default: false default: false
},
// 拖拽行
enableRowDrag: {
type: Boolean,
default: false
} }
}); });
@ -152,6 +158,7 @@ const emit = defineEmits([
"page-change", "page-change",
"size-change", "size-change",
"column-drag-end", "column-drag-end",
"row-drag-end"
]); ]);
// 响应式数据 // 响应式数据
@ -247,6 +254,9 @@ onMounted(() => {
if (props.enableColumnDrag && tableRef.value) { if (props.enableColumnDrag && tableRef.value) {
initColumnDrag(); initColumnDrag();
} }
if (props.enableRowDrag && tableRef.value) {
initRowDrag();
}
}); });
@ -318,6 +328,37 @@ const initColumnDrag = () => {
}; };
// 初始化行拖拽
const initRowDrag = () => {
const tableBody = tableRef.value.$el.querySelector('.el-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 = tableData.value.splice(oldIndex, 1)[0]
tableData.value.splice(newIndex, 0, moveRow)
// 重新更新排序值
tableData.value.forEach((item: any, index) => {
item.sort = index + 1
})
// console.log("🚀 ~ initRowDrag ~ tableData.value:", tableData.value)
emit('row-drag-end', {
oldIndex,
newIndex,
list: tableData.value
})
}
})
};
// 暴露方法 // 暴露方法
const clearSelection = () => { const clearSelection = () => {
tableRef.value?.clearSelection(); tableRef.value?.clearSelection();
@ -339,8 +380,8 @@ const setScrollTo = (top: number) => {
tableRef.value?.scrollTo(top); tableRef.value?.scrollTo(top);
}; };
const setScrollTop = (height: number) => { const setScrollTop = (index: number) => {
tableRef.value?.setScrollTop(height); tableRef.value?.setScrollTop(index * 30); //30px/行
}; };
const clearSort = () => { const clearSort = () => {

View File

@ -1,147 +0,0 @@
<template>
<!-- 参数设置 -->
<div>
<el-form ref="form" :model="formData" :rules="rules" label-width="80px" size="small" class="form-inline" inline>
<el-row>
<span>说明:公式中阴阳对照请用NC,PC表示</span>
</el-row>
<el-form-item label="测试波长" prop="csbc">
<el-input placeholder="测试波长" v-model="formData.csbc"></el-input>
</el-form-item>
<el-form-item label="参考波长" prop="ckbc">
<el-input placeholder="参考波长" v-model="formData.ckbc"></el-input>
<el-button type="primary" @click="">滤光片波长对照表...</el-button>
</el-form-item>
<el-form-item label="阳性判断公式" prop="yxgs" label-width="100px">
<el-input placeholder="阳性判断公式" v-model="formData.yxgs" style="width: 400px;"></el-input>
</el-form-item>
<el-form-item label="上灰区" prop="shq">
<el-input placeholder="上灰区" v-model="formData.shq">
<template #append>% </template>
</el-input>
</el-form-item>
<el-form-item label="下灰区" prop="xhq">
<el-input placeholder="下灰区" v-model="formData.xhq">
<template #append>% </template>
</el-input>
</el-form-item>
<el-form-item label="阴性对照下限" prop="negxx" label-width="100px">
<el-input placeholder="阴性对照下限" v-model="formData.negxx" style="width: 100px;"></el-input>
</el-form-item>
<el-form-item label="阳性对照下限" prop="posxx" label-width="100px">
<el-input placeholder="阳性对照下限" v-model="formData.posxx"></el-input>
</el-form-item>
<el-form-item label="阴性对照上限" prop="negsx" label-width="100px">
<el-input placeholder="阴性对照上限" v-model="formData.negsx" style="width: 100px;"></el-input>
</el-form-item>
<el-form-item label="阳性对照上限" prop="possx" label-width="100px">
<el-input placeholder="阳性对照上限" v-model="formData.possx"></el-input>
</el-form-item>
<el-divider></el-divider>
<el-form-item label="项目性质" prop="xmxz">
<el-radio-group v-model="formData.xmxz">
<el-radio value="1">定性</el-radio>
<el-radio value="2">定量</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="移动模式" prop="ydfs">
<el-radio-group v-model="formData.ydfs">
<el-radio value="1">连续</el-radio>
<el-radio value="2">步进</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="测试模式" prop="csms">
<el-radio-group v-model="formData.csms">
<el-radio value="1">终点法</el-radio>
<el-radio value="2">两点法</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="振板频率" prop="zbpl">
<el-radio-group v-model="formData.zbpl">
<el-radio value="1">高</el-radio>
<el-radio value="2">中</el-radio>
<el-radio value="3">低</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="空白形式" prop="kbms">
<el-radio-group v-model="formData.kbms">
<el-radio value="1">空气</el-radio>
<el-radio value="2">试剂</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="振板时间" prop="zbsj">
<el-input placeholder="振板时间" v-model="formData.zbsj"></el-input>秒
</el-form-item>
<el-divider></el-divider>
<el-form-item label="默认模板" prop="mrmb">
<el-input placeholder="默认模板" v-model="formData.mrmb"></el-input>
</el-form-item>
<el-form-item label="默认试剂" prop="mrsjph">
<el-input placeholder="默认试剂" v-model="formData.mrsjph"></el-input>
<el-button type="primary" @click="">试剂维护</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const formData = ref({
csbc: '',
ckbc: '',
yxgs: '',
shq: '',
xhq: '',
negxx: '',
posxx: '',
negsx: '',
possx: '',
xmxz: '',
ydfs: '',
csms: '',
zbpl: '',
kbms: '',
zbsj: '',
mrmb: '',
mrsjph: ''
});
const rules = ref({
// name: [
// { required: true, message: '请输入姓名', trigger: 'blur' }
// ],
// sex: [
// { required: true, message: '请选择性别', trigger: 'change' }
// ]
});
const props = defineProps({
// 是否显示
// visible: {
// type: Boolean,
// required: true,
// default: false
// }
});
</script>
<style scoped lang="scss">
.form-inline {
padding: 10px;
background-color: #f5f7fa;
height: auto;
.el-input {
width: 150px;
}
.el-form-item {
margin-right: 10px;
margin-bottom: 2px;
}
}
</style>

View File

@ -138,7 +138,7 @@ const handleEnter = () => {
prevSpecimen.value = res.data prevSpecimen.value = res.data
tableData.value.push(res.data) tableData.value.push(res.data)
nextTick(() => { nextTick(() => {
tableRef.value.setScrollTop(tableData.value.length * 30); tableRef.value.setScrollTop(tableData.value.length);
}) })
currentScanCount.value++; currentScanCount.value++;
} }

View File

@ -24,6 +24,11 @@
<el-input v-model="scope.row.channel" placeholder="请输入通道号" class="full-width-input" /> <el-input v-model="scope.row.channel" placeholder="请输入通道号" class="full-width-input" />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="项目" align="center">
<template #default="scope">
<SelectTable v-model:data="scope.row.xmid" :tableData="xmList" class="full-width-input" />
</template>
</el-table-column>
</el-table> </el-table>
</el-col> </el-col>
<el-col :span="6"> <el-col :span="6">
@ -39,6 +44,8 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { queryXmInfoNewService } from '@/api/liswork/labItem/labItemApi';
const yq = defineModel<string>();
const tableData = ref<Array<{ channel: string }>>([]); const tableData = ref<Array<{ channel: string }>>([]);
const handleSave = () => { const handleSave = () => {
@ -53,6 +60,23 @@ const delItem = () => {
const allClear = () => { const allClear = () => {
} }
const xmList = ref<Array<{ xmmc: string, xmid: string }>>([]);
const getXmList = () => {
queryXmInfoNewService({ yq: yq.value }).then((res: any) => {
xmList.value = res.rows.map((item: any) => {
return {
label: item.xmmc,
value: item.xmid.toString(),
}
})
})
};
watch(() => yq.value, (val) => {
if (val) {
getXmList();
}
}, { immediate: true });
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">

View File

@ -204,7 +204,10 @@ watch(yq, (newVal) => {
if (newVal !== undefined) { if (newVal !== undefined) {
getList() getList()
} }
}, { deep: true }) }, {
immediate: true,
deep: true
})
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">

View File

@ -204,7 +204,10 @@ watch(yq, (newVal) => {
if (newVal !== undefined) { if (newVal !== undefined) {
getList() getList()
} }
}, { deep: true }) }, {
immediate: true,
deep: true
})
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">

View File

@ -362,14 +362,14 @@ const getSjcjList = () => {
cjList.value = res.data cjList.value = res.data
}) })
} }
onMounted(() => {
})
watch(yq, (newVal) => { watch(yq, (newVal) => {
getDzList() getDzList()
getSjList() getSjList()
}, { deep: true }) }, {
immediate: true,
deep: true
})
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">

View File

@ -3,24 +3,21 @@
<div class="sort_box"> <div class="sort_box">
<el-row :gutter="10" class="table-row"> <el-row :gutter="10" class="table-row">
<el-col :span="20" class="table-box"> <el-col :span="20" class="table-box">
<CustomTable ref="tableRef" :data="dataList" :columns="columns" :enable-column-drag="true" <CustomTable ref="tableRef" :data="dataList" :columns="columns" :config="tableConfig"
@row-click="handleRowClick" @column-drag-end="handleColumnDragEnd" :config="tableConfig"> @row-click="handleRowClick">
<template #xmgl="{ row }"> <template #sort="{ row }">
{{ formatDict(row.xmgl, 'XMGL') }} <el-input v-model="row.sort" class="full-width-input" />
</template>
<template #dyxh="{ row }">
<el-input v-model="row.dyxh" class="full-width-input" />
</template> </template>
</CustomTable> </CustomTable>
</el-col> </el-col>
<el-col :span="4"> <el-col :span="4">
<el-row :gutter="10" class="table-toolbar"> <el-row :gutter="10" class="table-toolbar">
<el-col :span="1.5"> <!-- <el-col :span="1.5">
<el-radio-group v-model="radio" @change="radioChange"> <el-radio-group v-model="radio" @change="radioChange">
<el-radio value="1">上下移动调整</el-radio> <el-radio value="1">上下移动调整</el-radio>
<el-radio value="2">手工输入工号</el-radio> <el-radio value="2">手工输入工号</el-radio>
</el-radio-group> </el-radio-group>
</el-col> </el-col> -->
<el-col :span="1.5"> <el-col :span="1.5">
<el-button type="primary" @click="refresh">刷新</el-button> <el-button type="primary" @click="refresh">刷新</el-button>
</el-col> </el-col>
@ -30,12 +27,12 @@
<el-col :span="1.5"> <el-col :span="1.5">
<el-button type="primary" :disabled="radio == '2'" @click="firstHandle">首位</el-button> <el-button type="primary" :disabled="radio == '2'" @click="firstHandle">首位</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <!-- <el-col :span="1.5">
<el-button type="primary" icon="top" :disabled="radio == '2'" @click="prevHandle">上移</el-button> <el-button type="primary" icon="top" :disabled="radio == '2'" @click="prevHandle">上移</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
<el-button type="primary" icon="bottom" :disabled="radio == '2'" @click="nextHandle">下移</el-button> <el-button type="primary" icon="bottom" :disabled="radio == '2'" @click="nextHandle">下移</el-button>
</el-col> </el-col> -->
<el-col :span="1.5"> <el-col :span="1.5">
<el-button type="primary" :disabled="radio == '2'" @click="lastHadnle">末位</el-button> <el-button type="primary" :disabled="radio == '2'" @click="lastHadnle">末位</el-button>
</el-col> </el-col>
@ -59,52 +56,45 @@ const props = defineProps({
}); });
interface DataItem { interface DataItem {
xmgl: string | number;
xmid: string | number; xmid: string | number;
xmdh: string | number;
xmmc: string | number; xmmc: string | number;
dyxh: string | number; sort: string | number;
fzdyxh: string | number;
} }
const currentIndex = ref(0); const currentIndex = ref(0);
const radio = ref('1'); const radio = ref('1');
const tableRef = ref(); const tableRef = ref();
const dataList = ref<DataItem[]>([]); const dataList = ref<DataItem[]>([]);
const columns = ref([ const columns = ref([
{ prop: 'xmgl', label: '项目类别', visible: true, align: 'center', slot: "xmgl" },
{ prop: 'xmid', label: '项目ID', visible: true, align: 'center', }, { prop: 'xmid', label: '项目ID', visible: true, align: 'center', },
{ prop: 'xmdh', label: '英文缩写', visible: true, align: 'center', },
{ prop: 'xmmc', label: '项目名称', visible: true, align: 'center', }, { prop: 'xmmc', label: '项目名称', visible: true, align: 'center', },
{ prop: 'dyxh', label: '整体排序', visible: false, align: 'center', slot: "dyxh" }, { prop: 'sort', label: '整体排序', visible: true, align: 'center', slot: "sort" },
{ prop: 'fzdyxh', label: '分组打印序号', visible: true, align: 'center', },
]); ]);
const tableConfig = ref({ const tableConfig = ref({
border: true, // 边框 border: true, // 边框
height: '100%', // 高度 height: '100%', // 高度
highlightCurrentRow: true, // 高亮当前行 highlightCurrentRow: true, // 高亮当前行
key: 'xmid'
}) })
//退拽属性 //退拽属性
const handleColumnDragEnd = (data: any) => { const handleColumnDragEnd = (data: any) => {
// 更新列配置 // 更新列配置
columns.value = data.columns; dataList.value = data.list;
} }
const handleRowClick = (row: DataItem) => { const handleRowClick = (row: DataItem) => {
currentIndex.value = dataList.value.indexOf(row); currentIndex.value = dataList.value.indexOf(row);
} }
const radioChange = (val: string) => {
if (val == '1') {
columns.value[4].visible = false const getList = () => {
} else {
columns.value[4].visible = true
}
} }
const refresh = () => { const refresh = () => {
getList();
} }
const cpHandle = () => { const cpHandle = () => {
@ -115,26 +105,19 @@ const firstHandle = () => {
tableRef.value.setCurrentRow(dataList.value[0]); tableRef.value.setCurrentRow(dataList.value[0]);
tableRef.value.setScrollTop(0) tableRef.value.setScrollTop(0)
} }
const prevHandle = () => {
if (currentIndex.value == 0) return;
currentIndex.value--;
tableRef.value.setCurrentRow(dataList.value[currentIndex.value]);
tableRef.value.setScrollTop(currentIndex.value * 30)
}
const nextHandle = () => {
if (currentIndex.value == dataList.value.length - 1) return;
currentIndex.value++;
tableRef.value.setCurrentRow(dataList.value[currentIndex.value]);
tableRef.value.setScrollTop(currentIndex.value * 30)
}
const lastHadnle = () => { const lastHadnle = () => {
currentIndex.value = dataList.value.length - 1; currentIndex.value = dataList.value.length - 1;
tableRef.value.setCurrentRow(dataList.value[dataList.value.length - 1]); tableRef.value.setCurrentRow(dataList.value[currentIndex.value]);
tableRef.value.setScrollTop(dataList.value.length * 30) tableRef.value.setScrollTop(dataList.value.length)
} }
onMounted(() => { onMounted(() => {
for (let index = 0; index < 20; index++) {
dataList.value.push(
{ xmid: 'ID' + index, xmmc: 'xmmc' + index, sort: '', }
)
}
}) })
</script> </script>
@ -170,4 +153,12 @@ onMounted(() => {
height: 100%; height: 100%;
} }
} }
/* 可拖拽表格行样式提示 */
:deep(.drag-table .el-table__row) {
cursor: move;
/* 鼠标移入行显示拖拽光标 */
transition: background-color 0.2s;
}
</style> </style>

View File

@ -109,10 +109,10 @@ const tabList = [
{ key: 'SysInput', label: '界面设定', component: SysInput }, { key: 'SysInput', label: '界面设定', component: SysInput },
{ 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('SysParameter') const activeName = ref('SysSort')
// 计算当前要渲染的组件 // 计算当前要渲染的组件
const currentComponent = computed(() => { const currentComponent = computed(() => {