feat(i18n): 实现国际化支持并优化代码结构
- 在i18n模块中实现懒加载本地化配置,限制加载指定语言文件 - 为床位管理、合同管理、客户管理等界面组件添加国际化标签和消息 - 集成vue-i18n在多个组件中添加翻译功能和多语言支持 - 更新CDSS告警和规则管理界面以支持多语言显示 - 优化store模块导入结构,添加pinia依赖注入 - 实现表单验证消息和操作提示的国际化处理
This commit is contained in:
@@ -10,20 +10,16 @@ const messages = {
|
||||
|
||||
// Lazy load locale messages
|
||||
const loadLocaleMessages = async () => {
|
||||
const localeFiles = import.meta.glob('./locales/*.json', { eager: true })
|
||||
const localeFiles = import.meta.glob('./locales/{zhCN,enUS,viVN}.json', { eager: true })
|
||||
const localeMap = {
|
||||
'zhCN': 'zh-CN',
|
||||
'enUS': 'en',
|
||||
'viVN': 'vi'
|
||||
}
|
||||
for (const path in localeFiles) {
|
||||
const localeName = path.match(/\.\/locales\/(.+)\.json$/)?.[1]
|
||||
if (!localeName) continue
|
||||
|
||||
let isoCode
|
||||
if (localeName === 'zhCN') isoCode = 'zh-CN'
|
||||
else if (localeName === 'enUS') isoCode = 'en'
|
||||
else if (localeName === 'viVN') isoCode = 'vi'
|
||||
else {
|
||||
isoCode = localeName.replace(/([A-Z])/g, '-$1').toLowerCase()
|
||||
}
|
||||
|
||||
if (!messages[isoCode]) messages[isoCode] = {}
|
||||
const isoCode = localeMap[localeName]
|
||||
if (!isoCode) continue
|
||||
messages[isoCode] = { ...messages[isoCode], ...localeFiles[path].default }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { createPinia } from 'pinia'
|
||||
const store = createPinia()
|
||||
|
||||
export default store
|
||||
@@ -3,13 +3,13 @@
|
||||
<el-card shadow="never">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span class="card-title">床位管理</span>
|
||||
<span class="card-title">{{ $t('basic.bedspace.title') }}</span>
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="Plus"
|
||||
@click="handleAdd"
|
||||
>
|
||||
新增床位
|
||||
{{ $t('basic.bedspace.addBed') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
@@ -18,34 +18,34 @@
|
||||
:model="queryParams"
|
||||
label-width="80px"
|
||||
>
|
||||
<el-form-item label="床号">
|
||||
<el-form-item :label="$t('basic.bedspace.bedNo')">
|
||||
<el-input
|
||||
v-model="queryParams.bedNo"
|
||||
placeholder="床号"
|
||||
:placeholder="$t('basic.bedspace.bedNo')"
|
||||
clearable
|
||||
style="width: 140px"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-form-item :label="$t('common.status')">
|
||||
<el-select
|
||||
v-model="queryParams.status"
|
||||
placeholder="全部"
|
||||
:placeholder="$t('common.all')"
|
||||
clearable
|
||||
style="width: 120px"
|
||||
>
|
||||
<el-option
|
||||
label="空闲"
|
||||
:label="$t('basic.bedspace.statusFree')"
|
||||
:value="0"
|
||||
/><el-option
|
||||
label="占用"
|
||||
:label="$t('basic.bedspace.statusOccupied')"
|
||||
:value="1"
|
||||
/>
|
||||
<el-option
|
||||
label="清洁"
|
||||
:label="$t('basic.bedspace.statusClean')"
|
||||
:value="2"
|
||||
/><el-option
|
||||
label="维修"
|
||||
:label="$t('basic.bedspace.statusRepair')"
|
||||
:value="3"
|
||||
/>
|
||||
</el-select>
|
||||
@@ -56,13 +56,13 @@
|
||||
icon="Search"
|
||||
@click="handleQuery"
|
||||
>
|
||||
搜索
|
||||
{{ $t('common.search') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
icon="Refresh"
|
||||
@click="resetQuery"
|
||||
>
|
||||
重置
|
||||
{{ $t('common.reset') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
@@ -74,32 +74,32 @@
|
||||
>
|
||||
<vxe-column
|
||||
type="seq"
|
||||
title="序号"
|
||||
:title="$t('common.seq')"
|
||||
width="60"
|
||||
/>
|
||||
<vxe-column
|
||||
field="bedNo"
|
||||
title="床号"
|
||||
:title="$t('basic.bedspace.bedNo')"
|
||||
width="100"
|
||||
/>
|
||||
<vxe-column
|
||||
field="bedName"
|
||||
title="床位名"
|
||||
:title="$t('basic.bedspace.bedName')"
|
||||
width="120"
|
||||
/>
|
||||
<vxe-column
|
||||
field="wardName"
|
||||
title="病区"
|
||||
:title="$t('basic.bedspace.ward')"
|
||||
width="120"
|
||||
/>
|
||||
<vxe-column
|
||||
field="deptName"
|
||||
title="科室"
|
||||
:title="$t('basic.bedspace.dept')"
|
||||
width="120"
|
||||
/>
|
||||
<vxe-column
|
||||
field="bedType"
|
||||
title="类型"
|
||||
:title="$t('basic.bedspace.type')"
|
||||
width="80"
|
||||
align="center"
|
||||
>
|
||||
@@ -108,13 +108,13 @@
|
||||
:type="row.bedType === 2 ? 'danger' : row.bedType === 3 ? 'warning' : 'info'"
|
||||
size="small"
|
||||
>
|
||||
{{ { 1: '普通', 2: 'ICU', 3: '急诊' }[row.bedType] || '普通' }}
|
||||
{{ { 1: $t('basic.bedspace.typeNormal'), 2: 'ICU', 3: $t('basic.bedspace.typeEmergency') }[row.bedType] || $t('basic.bedspace.typeNormal') }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column
|
||||
field="status"
|
||||
title="状态"
|
||||
:title="$t('common.status')"
|
||||
width="80"
|
||||
align="center"
|
||||
>
|
||||
@@ -128,7 +128,7 @@
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column
|
||||
title="操作"
|
||||
:title="$t('common.action')"
|
||||
width="220"
|
||||
fixed="right"
|
||||
>
|
||||
@@ -139,7 +139,7 @@
|
||||
icon="Edit"
|
||||
@click="handleEdit(row)"
|
||||
>
|
||||
编辑
|
||||
{{ $t('common.edit') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="row.status === 0"
|
||||
@@ -147,7 +147,7 @@
|
||||
link
|
||||
@click="changeStatus(row, 1)"
|
||||
>
|
||||
占用
|
||||
{{ $t('basic.bedspace.statusOccupied') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="row.status === 1"
|
||||
@@ -155,7 +155,7 @@
|
||||
link
|
||||
@click="changeStatus(row, 2)"
|
||||
>
|
||||
清洁
|
||||
{{ $t('basic.bedspace.statusClean') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="row.status === 2"
|
||||
@@ -163,7 +163,7 @@
|
||||
link
|
||||
@click="changeStatus(row, 0)"
|
||||
>
|
||||
空闲
|
||||
{{ $t('basic.bedspace.statusFree') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="row.status !== 3"
|
||||
@@ -171,7 +171,7 @@
|
||||
link
|
||||
@click="changeStatus(row, 3)"
|
||||
>
|
||||
维修
|
||||
{{ $t('basic.bedspace.statusRepair') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
@@ -179,7 +179,7 @@
|
||||
icon="Delete"
|
||||
@click="handleDelete(row)"
|
||||
>
|
||||
删除
|
||||
{{ $t('common.delete') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</vxe-column>
|
||||
@@ -205,50 +205,50 @@
|
||||
label-width="80px"
|
||||
>
|
||||
<el-form-item
|
||||
label="床号"
|
||||
:label="$t('basic.bedspace.bedNo')"
|
||||
prop="bedNo"
|
||||
>
|
||||
<el-input
|
||||
v-model="form.bedNo"
|
||||
placeholder="床号"
|
||||
:placeholder="$t('basic.bedspace.bedNo')"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="床位名">
|
||||
<el-form-item :label="$t('basic.bedspace.bedName')">
|
||||
<el-input
|
||||
v-model="form.bedName"
|
||||
placeholder="床位名"
|
||||
:placeholder="$t('basic.bedspace.bedName')"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="病区">
|
||||
<el-form-item :label="$t('basic.bedspace.ward')">
|
||||
<el-input
|
||||
v-model="form.wardName"
|
||||
placeholder="病区"
|
||||
:placeholder="$t('basic.bedspace.ward')"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="科室">
|
||||
<el-form-item :label="$t('basic.bedspace.dept')">
|
||||
<el-input
|
||||
v-model="form.deptName"
|
||||
placeholder="科室"
|
||||
:placeholder="$t('basic.bedspace.dept')"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="类型">
|
||||
<el-form-item :label="$t('basic.bedspace.type')">
|
||||
<el-select
|
||||
v-model="form.bedType"
|
||||
style="width:100%"
|
||||
>
|
||||
<el-option
|
||||
label="普通"
|
||||
:label="$t('basic.bedspace.typeNormal')"
|
||||
:value="1"
|
||||
/><el-option
|
||||
label="ICU"
|
||||
:value="2"
|
||||
/><el-option
|
||||
label="急诊"
|
||||
:label="$t('basic.bedspace.typeEmergency')"
|
||||
:value="3"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-form-item :label="$t('common.remark')">
|
||||
<el-input
|
||||
v-model="form.remark"
|
||||
type="textarea"
|
||||
@@ -258,28 +258,30 @@
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="formVisible = false">
|
||||
取消
|
||||
{{ $t('common.cancel') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="submitForm"
|
||||
>
|
||||
确定
|
||||
{{ $t('common.confirm') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { ref, onMounted, computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { getBedPage, addBed, updateBed, deleteBed, updateBedStatus } from './components/api'
|
||||
const { t } = useI18n()
|
||||
const loading = ref(false); const tableData = ref([]); const total = ref(0)
|
||||
const queryParams = ref({ bedNo: '', status: undefined, pageNo: 1, pageSize: 10 })
|
||||
const formVisible = ref(false); const formTitle = ref('新增床位'); const isEdit = ref(false); const formRef = ref()
|
||||
const form = ref({ id: null, bedNo: '', bedName: '', wardName: '', deptName: '', bedType: 1, remark: '' })
|
||||
const rules = { bedNo: [{ required: true, message: '请输入床号', trigger: 'blur' }] }
|
||||
const statusText = (s) => ({ 0: '空闲', 1: '占用', 2: '清洁', 3: '维修' }[s] || '未知')
|
||||
const rules = computed(() => ({ bedNo: [{ required: true, message: t('basic.bedspace.msgInputBedNo'), trigger: 'blur' }] }))
|
||||
const statusText = (s) => ({ 0: t('basic.bedspace.statusFree'), 1: t('basic.bedspace.statusOccupied'), 2: t('basic.bedspace.statusClean'), 3: t('basic.bedspace.statusRepair') }[s] || t('common.unknown'))
|
||||
const statusType = (s) => ({ 0: 'success', 1: 'danger', 2: 'info', 3: 'warning' }[s] || 'info')
|
||||
function getList() {
|
||||
loading.value = true
|
||||
@@ -287,16 +289,16 @@ function getList() {
|
||||
}
|
||||
function handleQuery() { queryParams.value.pageNo = 1; getList() }
|
||||
function resetQuery() { queryParams.value = { bedNo: '', status: undefined, pageNo: 1, pageSize: 10 }; getList() }
|
||||
function handleAdd() { isEdit.value = false; formTitle.value = '新增床位'; form.value = { id: null, bedNo: '', bedName: '', wardName: '', deptName: '', bedType: 1, remark: '' }; formVisible.value = true }
|
||||
function handleEdit(row) { isEdit.value = true; formTitle.value = '编辑床位'; form.value = { ...row }; formVisible.value = true }
|
||||
function handleAdd() { isEdit.value = false; formTitle.value = t('basic.bedspace.addTitle'); form.value = { id: null, bedNo: '', bedName: '', wardName: '', deptName: '', bedType: 1, remark: '' }; formVisible.value = true }
|
||||
function handleEdit(row) { isEdit.value = true; formTitle.value = t('basic.bedspace.editTitle'); form.value = { ...row }; formVisible.value = true }
|
||||
function submitForm() {
|
||||
formRef.value.validate(valid => { if (!valid) return
|
||||
const action = isEdit.value ? updateBed(form.value) : addBed(form.value)
|
||||
action.then(res => { if (res.code === 200) { ElMessage.success(isEdit.value ? '修改成功' : '新增成功'); formVisible.value = false; getList() } else ElMessage.error(res.msg || '操作失败') })
|
||||
action.then(res => { if (res.code === 200) { ElMessage.success(isEdit.value ? t('basic.bedspace.msgEditSuccess') : t('basic.bedspace.msgAddSuccess')); formVisible.value = false; getList() } else ElMessage.error(res.msg || t('common.operationFailed')) })
|
||||
})
|
||||
}
|
||||
function handleDelete(row) { ElMessageBox.confirm('确认删除该床位?', '提示', { type: 'warning' }).then(() => { deleteBed(row.id).then(res => { if (res.code === 200) { ElMessage.success('删除成功'); getList() } }) }).catch(() => {}) }
|
||||
function changeStatus(row, status) { updateBedStatus(row.id, status).then(res => { if (res.code === 200) { ElMessage.success('状态已更新'); getList() } }) }
|
||||
function handleDelete(row) { ElMessageBox.confirm(t('basic.bedspace.msgConfirmDelete'), t('common.prompt'), { type: 'warning' }).then(() => { deleteBed(row.id).then(res => { if (res.code === 200) { ElMessage.success(t('basic.bedspace.msgDeleteSuccess')); getList() } }) }).catch(() => {}) }
|
||||
function changeStatus(row, status) { updateBedStatus(row.id, status).then(res => { if (res.code === 200) { ElMessage.success(t('basic.bedspace.msgStatusUpdated')); getList() } }) }
|
||||
onMounted(() => getList())
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -2,16 +2,16 @@
|
||||
<div class="app-container">
|
||||
<el-card shadow="never">
|
||||
<template #header>
|
||||
<span class="card-title">合同管理</span>
|
||||
<span class="card-title">{{ $t('basic.contract.title') }}</span>
|
||||
</template>
|
||||
<el-form
|
||||
:inline="true"
|
||||
:model="queryParams"
|
||||
>
|
||||
<el-form-item label="搜索">
|
||||
<el-form-item :label="$t('common.search')">
|
||||
<el-input
|
||||
v-model="queryParams.searchKey"
|
||||
placeholder="搜索"
|
||||
:placeholder="$t('common.search')"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
@@ -22,14 +22,14 @@
|
||||
icon="Search"
|
||||
@click="handleQuery"
|
||||
>
|
||||
搜索
|
||||
{{ $t('common.search') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
icon="Plus"
|
||||
@click="handleAdd"
|
||||
>
|
||||
新增
|
||||
{{ $t('common.add') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
@@ -40,29 +40,29 @@
|
||||
>
|
||||
<vxe-column
|
||||
type="seq"
|
||||
title="序号"
|
||||
:title="$t('common.seq')"
|
||||
width="60"
|
||||
/>
|
||||
<vxe-column
|
||||
field="name"
|
||||
title="名称"
|
||||
:title="$t('basic.contract.name')"
|
||||
/>
|
||||
<vxe-column
|
||||
field="code"
|
||||
title="编码"
|
||||
:title="$t('basic.contract.code')"
|
||||
/>
|
||||
<vxe-column
|
||||
field="status"
|
||||
title="状态"
|
||||
:title="$t('common.status')"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.status === '0' ? 'success' : 'info'">
|
||||
{{ row.status === '0' ? '正常' : '停用' }}
|
||||
{{ row.status === '0' ? $t('common.normal') : $t('common.disabled') }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column
|
||||
title="操作"
|
||||
:title="$t('common.action')"
|
||||
width="150"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
@@ -71,14 +71,14 @@
|
||||
link
|
||||
@click="handleEdit(row)"
|
||||
>
|
||||
编辑
|
||||
{{ $t('common.edit') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
link
|
||||
@click="handleDelete(row)"
|
||||
>
|
||||
删除
|
||||
{{ $t('common.delete') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</vxe-column>
|
||||
@@ -88,13 +88,15 @@
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { ElMessage } from 'element-plus'
|
||||
const { t } = useI18n()
|
||||
const queryParams = ref({ searchKey: '', pageNum: 1, pageSize: 10 })
|
||||
const tableData = ref([])
|
||||
const handleQuery = () => { tableData.value = [] }
|
||||
const handleAdd = () => { ElMessage.info('新增功能开发中') }
|
||||
const handleEdit = (row) => { ElMessage.info('编辑功能开发中') }
|
||||
const handleDelete = (row) => { ElMessage.info('删除功能开发中') }
|
||||
const handleAdd = () => { ElMessage.info(t('common.developing')) }
|
||||
const handleEdit = (row) => { ElMessage.info(t('common.developing')) }
|
||||
const handleDelete = (row) => { ElMessage.info(t('common.developing')) }
|
||||
onMounted(() => handleQuery())
|
||||
</script>
|
||||
<style scoped>.card-title { font-weight: bold; font-size: 16px; }</style>
|
||||
|
||||
@@ -2,16 +2,16 @@
|
||||
<div class="app-container">
|
||||
<el-card shadow="never">
|
||||
<template #header>
|
||||
<span class="card-title">客户数据</span>
|
||||
<span class="card-title">{{ $t('basic.customer.title') }}</span>
|
||||
</template>
|
||||
<el-form
|
||||
:inline="true"
|
||||
:model="queryParams"
|
||||
>
|
||||
<el-form-item label="搜索">
|
||||
<el-form-item :label="$t('common.search')">
|
||||
<el-input
|
||||
v-model="queryParams.searchKey"
|
||||
placeholder="搜索"
|
||||
:placeholder="$t('common.search')"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
@@ -22,14 +22,14 @@
|
||||
icon="Search"
|
||||
@click="handleQuery"
|
||||
>
|
||||
搜索
|
||||
{{ $t('common.search') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
icon="Plus"
|
||||
@click="handleAdd"
|
||||
>
|
||||
新增
|
||||
{{ $t('common.add') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
@@ -40,29 +40,29 @@
|
||||
>
|
||||
<vxe-column
|
||||
type="seq"
|
||||
title="序号"
|
||||
:title="$t('common.seq')"
|
||||
width="60"
|
||||
/>
|
||||
<vxe-column
|
||||
field="name"
|
||||
title="名称"
|
||||
:title="$t('basic.customer.name')"
|
||||
/>
|
||||
<vxe-column
|
||||
field="code"
|
||||
title="编码"
|
||||
:title="$t('basic.customer.code')"
|
||||
/>
|
||||
<vxe-column
|
||||
field="status"
|
||||
title="状态"
|
||||
:title="$t('common.status')"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.status === '0' ? 'success' : 'info'">
|
||||
{{ row.status === '0' ? '正常' : '停用' }}
|
||||
{{ row.status === '0' ? $t('common.normal') : $t('common.disabled') }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column
|
||||
title="操作"
|
||||
:title="$t('common.action')"
|
||||
width="150"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
@@ -71,14 +71,14 @@
|
||||
link
|
||||
@click="handleEdit(row)"
|
||||
>
|
||||
编辑
|
||||
{{ $t('common.edit') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
link
|
||||
@click="handleDelete(row)"
|
||||
>
|
||||
删除
|
||||
{{ $t('common.delete') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</vxe-column>
|
||||
@@ -88,13 +88,15 @@
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { ElMessage } from 'element-plus'
|
||||
const { t } = useI18n()
|
||||
const queryParams = ref({ searchKey: '', pageNum: 1, pageSize: 10 })
|
||||
const tableData = ref([])
|
||||
const handleQuery = () => { tableData.value = [] }
|
||||
const handleAdd = () => { ElMessage.info('新增功能开发中') }
|
||||
const handleEdit = (row) => { ElMessage.info('编辑功能开发中') }
|
||||
const handleDelete = (row) => { ElMessage.info('删除功能开发中') }
|
||||
const handleAdd = () => { ElMessage.info(t('common.developing')) }
|
||||
const handleEdit = (row) => { ElMessage.info(t('common.developing')) }
|
||||
const handleDelete = (row) => { ElMessage.info(t('common.developing')) }
|
||||
onMounted(() => handleQuery())
|
||||
</script>
|
||||
<style scoped>.card-title { font-weight: bold; font-size: 16px; }</style>
|
||||
|
||||
@@ -186,20 +186,22 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { ref, onMounted, computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { getFeePage, addFee, updateFee } from './components/api'
|
||||
const { t } = useI18n()
|
||||
const loading = ref(false); const tableData = ref([]); const total = ref(0)
|
||||
const queryParams = ref({ searchKey: '', pageNo: 1, pageSize: 10 })
|
||||
const formVisible = ref(false); const formTitle = ref('新增项目'); const isEdit = ref(false); const formRef = ref()
|
||||
const form = ref({ id: null, conditionCode: '', name: '', typeCode: 'TREAT' })
|
||||
const rules = { conditionCode: [{ required: true, message: '请输入编码', trigger: 'blur' }], name: [{ required: true, message: '请输入名称', trigger: 'blur' }] }
|
||||
const rules = computed(() => ({ conditionCode: [{ required: true, message: t('basic.fee.msgInputCode'), trigger: 'blur' }], name: [{ required: true, message: t('basic.fee.msgInputName'), trigger: 'blur' }] }))
|
||||
function getList() { loading.value = true; getFeePage(queryParams.value).then(res => { tableData.value = res.data?.records || []; total.value = res.data?.total || 0 }).finally(() => { loading.value = false }) }
|
||||
function handleQuery() { queryParams.value.pageNo = 1; getList() }
|
||||
function resetQuery() { queryParams.value = { searchKey: '', pageNo: 1, pageSize: 10 }; getList() }
|
||||
function handleAdd() { isEdit.value = false; formTitle.value = '新增项目'; form.value = { id: null, conditionCode: '', name: '', typeCode: 'TREAT' }; formVisible.value = true }
|
||||
function handleEdit(row) { isEdit.value = true; formTitle.value = '编辑项目'; form.value = { ...row }; formVisible.value = true }
|
||||
function submitForm() { formRef.value.validate(valid => { if (!valid) return; const action = isEdit.value ? updateFee(form.value) : addFee(form.value); action.then(res => { if (res.code === 200) { ElMessage.success(isEdit.value ? '修改成功' : '新增成功'); formVisible.value = false; getList() } else ElMessage.error(res.msg || '操作失败') }) }) }
|
||||
function submitForm() { formRef.value.validate(valid => { if (!valid) return; const action = isEdit.value ? updateFee(form.value) : addFee(form.value); action.then(res => { if (res.code === 200) { ElMessage.success(isEdit.value ? '修改成功' : '新增成功'); formVisible.value = false; getList() } else ElMessage.error(res.msg || t('common.operationFailed')) }) }) }
|
||||
onMounted(() => getList())
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<template>
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!-- 查询表单 -->
|
||||
<el-form
|
||||
@@ -447,6 +447,7 @@
|
||||
</template>
|
||||
|
||||
<script setup name="Organization">
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import {
|
||||
addOrganization,
|
||||
deleteOrganization,
|
||||
@@ -458,6 +459,7 @@ import {
|
||||
updateOrganization
|
||||
} from './components/api';
|
||||
|
||||
const { t } = useI18n()
|
||||
const { proxy } = getCurrentInstance();
|
||||
const loading = ref(true);
|
||||
const showSearch = ref(true);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<template>
|
||||
<div
|
||||
style="display: flex; justify-content: space-between; height: 90vh"
|
||||
class="app-container"
|
||||
>
|
||||
<el-card style="width: 30%">
|
||||
<template #header>
|
||||
<span style="vertical-align: middle">病区</span>
|
||||
<span style="vertical-align: middle">{{ $t('basic.ward.wardArea') }}</span>
|
||||
</template>
|
||||
<div style="width: 100%">
|
||||
<el-button
|
||||
@@ -13,7 +13,7 @@
|
||||
class="mb8"
|
||||
@click="onIncrease"
|
||||
>
|
||||
新增
|
||||
{{ $t('common.add') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
@@ -21,7 +21,7 @@
|
||||
class="mb8"
|
||||
@click="handleEnableBatch('wardRef')"
|
||||
>
|
||||
批量启用
|
||||
{{ $t('basic.ward.batchEnable') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
@@ -29,7 +29,7 @@
|
||||
class="mb8"
|
||||
@click="handleUnableBatch('wardRef')"
|
||||
>
|
||||
批量停用
|
||||
{{ $t('basic.ward.batchDisable') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
style="float: right"
|
||||
@@ -504,7 +504,8 @@
|
||||
</template>
|
||||
|
||||
<script setup name="Ward">
|
||||
import {onMounted, ref} from 'vue';
|
||||
import {computed, onMounted, ref} from 'vue';
|
||||
import {useI18n} from 'vue-i18n';
|
||||
import {
|
||||
addLocation,
|
||||
deleteLocation,
|
||||
@@ -517,6 +518,7 @@ import {
|
||||
import {ElMessage} from 'element-plus';
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
const { t } = useI18n();
|
||||
// 病区参数
|
||||
const queryParams = ref({
|
||||
pageNum: 1,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<template>
|
||||
<template>
|
||||
<div>
|
||||
<vxe-table
|
||||
ref="medicineRef"
|
||||
@@ -7,18 +7,18 @@
|
||||
@cell-click="clickRow"
|
||||
>
|
||||
<vxe-column
|
||||
title="项目名称"
|
||||
:title="$t('catalog.diagnosis.itemNameFull')"
|
||||
align="center"
|
||||
field="name"
|
||||
width="300"
|
||||
/>
|
||||
<vxe-column
|
||||
title="零售价"
|
||||
:title="$t('catalog.diagnosis.retailPrice')"
|
||||
align="center"
|
||||
field="retailPrice"
|
||||
/>
|
||||
<vxe-column
|
||||
title="最高零售价"
|
||||
:title="$t('catalog.diagnosis.maxRetailPrice')"
|
||||
align="center"
|
||||
field="maximumRetailPrice"
|
||||
/>
|
||||
@@ -29,6 +29,9 @@
|
||||
<script setup>
|
||||
import {getDiagnosisTreatmentList} from './diagnosistreatment';
|
||||
import {ref, watch} from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const props = defineProps({
|
||||
itemType: {
|
||||
|
||||
@@ -1,95 +1,95 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :model="queryParams" ref="queryFormRef" :inline="true" v-show="showSearch" label-width="100px">
|
||||
<el-form-item label="就诊ID" prop="encounterId">
|
||||
<el-input v-model="queryParams.encounterId" placeholder="请输入就诊ID" clearable style="width: 200px" @keyup.enter="handleQuery" />
|
||||
<el-form-item :label="$t('cdss.alerts.encounterId')" prop="encounterId">
|
||||
<el-input v-model="queryParams.encounterId" :placeholder="$t('cdss.alerts.enterEncounterId')" clearable style="width: 200px" @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="严重程度" prop="severity">
|
||||
<el-select v-model="queryParams.severity" placeholder="请选择" clearable style="width: 140px">
|
||||
<el-form-item :label="$t('cdss.alerts.severity')" prop="severity">
|
||||
<el-select v-model="queryParams.severity" :placeholder="$t('common.pleaseSelect')" clearable style="width: 140px">
|
||||
<el-option label="INFO" value="INFO" />
|
||||
<el-option label="WARNING" value="WARNING" />
|
||||
<el-option label="CRITICAL" value="CRITICAL" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="确认状态" prop="acknowledged">
|
||||
<el-select v-model="queryParams.acknowledged" placeholder="请选择" clearable style="width: 140px">
|
||||
<el-option label="未确认" :value="0" />
|
||||
<el-option label="已确认" :value="1" />
|
||||
<el-form-item :label="$t('cdss.alerts.ackStatus')" prop="acknowledged">
|
||||
<el-select v-model="queryParams.acknowledged" :placeholder="$t('common.pleaseSelect')" clearable style="width: 140px">
|
||||
<el-option :label="$t('cdss.alerts.unacknowledged')" :value="0" />
|
||||
<el-option :label="$t('cdss.alerts.acknowledged')" :value="1" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
<el-button type="warning" icon="Monitor" @click="handleEvaluate">评估规则</el-button>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">{{ $t('common.search') }}</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">{{ $t('common.reset') }}</el-button>
|
||||
<el-button type="warning" icon="Monitor" @click="handleEvaluate">{{ $t('cdss.alerts.evaluateRules') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<vxe-table :data="alertList" :loading="loading" border stripe height="auto">
|
||||
<vxe-column type="seq" title="序号" width="70" />
|
||||
<vxe-column field="alertTitle" title="告警标题" min-width="200" show-overflow />
|
||||
<vxe-column field="severity" title="严重程度" width="120" align="center">
|
||||
<vxe-column type="seq" :title="$t('cdss.alerts.seq')" width="70" />
|
||||
<vxe-column field="alertTitle" :title="$t('cdss.alerts.alertTitle')" min-width="200" show-overflow />
|
||||
<vxe-column field="severity" :title="$t('cdss.alerts.severity')" width="120" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="severityTagType(row.severity)">{{ row.severity }}</el-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="ruleName" title="规则名称" width="160" show-overflow />
|
||||
<vxe-column field="alertMessage" title="告警详情" min-width="240" show-overflow />
|
||||
<vxe-column field="suggestion" title="处理建议" min-width="200" show-overflow />
|
||||
<vxe-column field="acknowledged" title="状态" width="100" align="center">
|
||||
<vxe-column field="ruleName" :title="$t('cdss.alerts.ruleName')" width="160" show-overflow />
|
||||
<vxe-column field="alertMessage" :title="$t('cdss.alerts.alertMessage')" min-width="240" show-overflow />
|
||||
<vxe-column field="suggestion" :title="$t('cdss.alerts.suggestion')" min-width="200" show-overflow />
|
||||
<vxe-column field="acknowledged" :title="$t('common.status')" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.acknowledged === 1 ? 'success' : 'danger'">
|
||||
{{ row.acknowledged === 1 ? '已确认' : '未确认' }}
|
||||
{{ row.acknowledged === 1 ? $t('cdss.alerts.acknowledged') : $t('cdss.alerts.unacknowledged') }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="acknowledgedBy" title="确认人" width="120" />
|
||||
<vxe-column field="createTime" title="触发时间" width="180" />
|
||||
<vxe-column title="操作" width="120" fixed="right" align="center">
|
||||
<vxe-column field="acknowledgedBy" :title="$t('cdss.alerts.acknowledgedBy')" width="120" />
|
||||
<vxe-column field="createTime" :title="$t('cdss.alerts.triggerTime')" width="180" />
|
||||
<vxe-column :title="$t('common.operation')" width="120" fixed="right" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button v-if="row.acknowledged === 0" link type="primary" icon="Check" v-hasPermi="['cdss:alert:acknowledge']" @click="handleAcknowledge(row)">确认</el-button>
|
||||
<el-button v-if="row.acknowledged === 0" link type="primary" icon="Check" v-hasPermi="['cdss:alert:acknowledge']" @click="handleAcknowledge(row)">{{ $t('cdss.alerts.acknowledge') }}</el-button>
|
||||
<span v-else class="text-gray">-</span>
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
|
||||
<el-dialog title="评估CDSS规则" v-model="evaluateDialogVisible" width="500px" append-to-body>
|
||||
<el-dialog :title="$t('cdss.alerts.evaluateDialogTitle')" v-model="evaluateDialogVisible" width="500px" append-to-body>
|
||||
<el-form :model="evaluateForm" label-width="100px">
|
||||
<el-form-item label="就诊ID" required>
|
||||
<el-input v-model="evaluateForm.encounterId" placeholder="请输入就诊ID" />
|
||||
<el-form-item :label="$t('cdss.alerts.encounterId')" required>
|
||||
<el-input v-model="evaluateForm.encounterId" :placeholder="$t('cdss.alerts.enterEncounterId')" />
|
||||
</el-form-item>
|
||||
<el-form-item label="患者ID" required>
|
||||
<el-input v-model="evaluateForm.patientId" placeholder="请输入患者ID" />
|
||||
<el-form-item :label="$t('cdss.alerts.patientId')" required>
|
||||
<el-input v-model="evaluateForm.patientId" :placeholder="$t('cdss.alerts.enterPatientId')" />
|
||||
</el-form-item>
|
||||
<el-form-item label="触发类型">
|
||||
<el-select v-model="evaluateForm.triggerType" placeholder="请选择" clearable>
|
||||
<el-option label="医嘱" value="order" />
|
||||
<el-option label="入院" value="admission" />
|
||||
<el-option label="出院" value="discharge" />
|
||||
<el-option label="生命体征" value="vital_sign" />
|
||||
<el-form-item :label="$t('cdss.alerts.triggerType')">
|
||||
<el-select v-model="evaluateForm.triggerType" :placeholder="$t('common.pleaseSelect')" clearable>
|
||||
<el-option :label="$t('cdss.alerts.triggerOrder')" value="order" />
|
||||
<el-option :label="$t('cdss.alerts.triggerAdmission')" value="admission" />
|
||||
<el-option :label="$t('cdss.alerts.triggerDischarge')" value="discharge" />
|
||||
<el-option :label="$t('cdss.alerts.triggerVitalSign')" value="vital_sign" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="科室ID">
|
||||
<el-input v-model="evaluateForm.departmentId" placeholder="请输入科室ID" />
|
||||
<el-form-item :label="$t('cdss.alerts.departmentId')">
|
||||
<el-input v-model="evaluateForm.departmentId" :placeholder="$t('cdss.alerts.enterDepartmentId')" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="evaluateDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="submitEvaluate">确认评估</el-button>
|
||||
<el-button @click="evaluateDialogVisible = false">{{ $t('common.cancel') }}</el-button>
|
||||
<el-button type="primary" @click="submitEvaluate">{{ $t('cdss.alerts.confirmEvaluate') }}</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog title="确认告警" v-model="acknowledgeDialogVisible" width="450px" append-to-body>
|
||||
<el-dialog :title="$t('cdss.alerts.ackDialogTitle')" v-model="acknowledgeDialogVisible" width="450px" append-to-body>
|
||||
<el-form :model="acknowledgeForm" label-width="80px">
|
||||
<el-form-item label="告警标题">
|
||||
<el-form-item :label="$t('cdss.alerts.alertTitle')">
|
||||
<span>{{ acknowledgeForm.alertTitle }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="确认备注">
|
||||
<el-input v-model="acknowledgeForm.remark" type="textarea" :rows="3" placeholder="请输入备注" />
|
||||
<el-form-item :label="$t('cdss.alerts.ackRemark')">
|
||||
<el-input v-model="acknowledgeForm.remark" type="textarea" :rows="3" :placeholder="$t('common.pleaseEnter')" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="acknowledgeDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="submitAcknowledge">确认</el-button>
|
||||
<el-button @click="acknowledgeDialogVisible = false">{{ $t('common.cancel') }}</el-button>
|
||||
<el-button type="primary" @click="submitAcknowledge">{{ $t('common.confirm') }}</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
@@ -97,9 +97,12 @@
|
||||
|
||||
<script setup name="CdssAlerts" ref="queryFormRef">
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { evaluateRules, getAlerts, acknowledgeAlert } from '@/api/cdss/cdssAlert'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const alertList = ref([])
|
||||
const loading = ref(false)
|
||||
const showSearch = ref(true)
|
||||
@@ -172,7 +175,7 @@ const handleEvaluate = () => {
|
||||
|
||||
const submitEvaluate = async () => {
|
||||
if (!evaluateForm.encounterId || !evaluateForm.patientId) {
|
||||
ElMessage.error('就诊ID和患者ID不能为空')
|
||||
ElMessage.error(t('cdss.alerts.errorEmptyIds'))
|
||||
return
|
||||
}
|
||||
try {
|
||||
|
||||
@@ -66,50 +66,50 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-divider content-position="left">执行历史</el-divider>
|
||||
<el-divider content-position="left">{{ $t('cdss.rules.executionHistory') }}</el-divider>
|
||||
<vxe-table :data="executionHistory" :loading="historyLoading" border stripe height="auto" size="small">
|
||||
<vxe-column type="seq" title="序号" width="60" />
|
||||
<vxe-column field="ruleCode" title="规则编码" width="120" />
|
||||
<vxe-column field="encounterId" title="就诊ID" width="100" />
|
||||
<vxe-column field="matched" title="是否命中" width="90" align="center">
|
||||
<vxe-column type="seq" :title="$t('cdss.rules.seq')" width="60" />
|
||||
<vxe-column field="ruleCode" :title="$t('cdss.rules.ruleCode')" width="120" />
|
||||
<vxe-column field="encounterId" :title="$t('cdss.rules.encounterId')" width="100" />
|
||||
<vxe-column field="matched" :title="$t('cdss.rules.matched')" width="90" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.matched ? 'success' : 'info'" size="small">{{ row.matched ? '命中' : '未命中' }}</el-tag>
|
||||
<el-tag :type="row.matched ? 'success' : 'info'" size="small">{{ row.matched ? $t('cdss.rules.matchedYes') : $t('cdss.rules.matchedNo') }}</el-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="executionResult" title="执行结果" min-width="150" show-overflow />
|
||||
<vxe-column field="durationMs" title="耗时(ms)" width="100" align="center" />
|
||||
<vxe-column field="executionTime" title="执行时间" width="170" />
|
||||
<vxe-column field="executionResult" :title="$t('cdss.rules.executionResult')" min-width="150" show-overflow />
|
||||
<vxe-column field="durationMs" :title="$t('cdss.rules.durationMs')" width="100" align="center" />
|
||||
<vxe-column field="executionTime" :title="$t('cdss.rules.executionTime')" width="170" />
|
||||
</vxe-table>
|
||||
</div>
|
||||
|
||||
<vxe-table v-else :data="ruleList" :loading="loading" border stripe height="auto">
|
||||
<vxe-column type="seq" title="序号" width="70" />
|
||||
<vxe-column field="ruleCode" title="规则编码" width="120" />
|
||||
<vxe-column field="ruleName" title="规则名称" min-width="180" show-overflow />
|
||||
<vxe-column field="ruleType" title="规则类型" width="110" align="center">
|
||||
<vxe-column type="seq" :title="$t('cdss.rules.seq')" width="70" />
|
||||
<vxe-column field="ruleCode" :title="$t('cdss.rules.ruleCode')" width="120" />
|
||||
<vxe-column field="ruleName" :title="$t('cdss.rules.ruleName')" min-width="180" show-overflow />
|
||||
<vxe-column field="ruleType" :title="$t('cdss.rules.ruleType')" width="110" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag size="small">{{ row.ruleType }}</el-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="severity" title="严重程度" width="100" align="center">
|
||||
<vxe-column field="severity" :title="$t('cdss.rules.severity')" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="severityTagType(row.severity)" effect="dark">{{ row.severity }}</el-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="priority" title="优先级" width="90" align="center">
|
||||
<vxe-column field="priority" :title="$t('cdss.rules.priority')" width="90" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="priorityTagType(row.priority)" size="small">{{ priorityLabel(row.priority) }}</el-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="category" title="分类" width="110" show-overflow />
|
||||
<vxe-column field="conditionExpr" title="条件表达式" min-width="200" show-overflow />
|
||||
<vxe-column field="actionExpr" title="执行动作" min-width="200" show-overflow />
|
||||
<vxe-column field="status" title="状态" width="80" align="center">
|
||||
<vxe-column field="category" :title="$t('cdss.rules.category')" width="110" show-overflow />
|
||||
<vxe-column field="conditionExpr" :title="$t('cdss.rules.conditionExpr')" min-width="200" show-overflow />
|
||||
<vxe-column field="actionExpr" :title="$t('cdss.rules.actionExpr')" min-width="200" show-overflow />
|
||||
<vxe-column field="status" :title="$t('common.status')" width="80" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.status === 1 ? 'success' : 'info'">{{ row.status === 1 ? '启用' : '停用' }}</el-tag>
|
||||
<el-tag :type="row.status === 1 ? 'success' : 'info'">{{ row.status === 1 ? $t('common.enabled') : $t('common.disabled') }}</el-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="sortOrder" title="排序" width="70" align="center" />
|
||||
<vxe-column field="sortOrder" :title="$t('cdss.rules.sortOrder')" width="70" align="center" />
|
||||
</vxe-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<div class="welcome-content">
|
||||
<div class="greeting">
|
||||
<h1>{{ getGreeting() }},{{ userStore.nickName || userStore.name }}</h1>
|
||||
<p>欢迎使用{{ userStore.hospitalName || '医院' }}管理系统</p>
|
||||
<p>{{ $t('home.welcomeSystem', { name: userStore.hospitalName || $t('home.defaultHospital') }) }}</p>
|
||||
</div>
|
||||
<div
|
||||
v-if="userStore.roles.length > 0"
|
||||
@@ -58,7 +58,7 @@
|
||||
<span :class="stat.trend > 0 ? 'trend-up' : 'trend-down'">
|
||||
{{ stat.trend > 0 ? '↑' : '↓' }} {{ Math.abs(stat.trend).toFixed(2) }}%
|
||||
</span>
|
||||
<span class="trend-label">较昨日</span>
|
||||
<span class="trend-label">{{ $t('home.vsYesterday') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -67,20 +67,20 @@
|
||||
<!-- 快捷功能入口 -->
|
||||
<div class="quick-access-section">
|
||||
<div class="section-header">
|
||||
<h3>快捷功能</h3>
|
||||
<h3>{{ $t('home.quickFunctions') }}</h3>
|
||||
<div>
|
||||
<el-button
|
||||
text
|
||||
type="primary"
|
||||
@click="showConfig"
|
||||
>
|
||||
配置
|
||||
{{ $t('home.configure') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-loading="quickAccessLoading"
|
||||
element-loading-text="加载快捷功能..."
|
||||
:element-loading-text="$t('home.loadingFunctions')"
|
||||
>
|
||||
<div class="quick-access-grid">
|
||||
<div
|
||||
@@ -108,7 +108,7 @@
|
||||
<!-- 待办事项 -->
|
||||
<div class="todo-section">
|
||||
<div class="section-header">
|
||||
<h3>待办事项</h3>
|
||||
<h3>{{ $t('home.todo') }}</h3>
|
||||
<el-badge
|
||||
:value="todoList.length"
|
||||
class="todo-badge"
|
||||
@@ -118,7 +118,7 @@
|
||||
type="primary"
|
||||
@click="showAllTodos"
|
||||
>
|
||||
查看全部
|
||||
{{ $t('home.viewAll') }}
|
||||
</el-button>
|
||||
</el-badge>
|
||||
</div>
|
||||
@@ -152,7 +152,7 @@
|
||||
class="empty-todo"
|
||||
>
|
||||
<el-empty
|
||||
description="暂无待办事项"
|
||||
:description="$t('home.noTodos')"
|
||||
:image-size="60"
|
||||
/>
|
||||
</div>
|
||||
@@ -162,13 +162,13 @@
|
||||
<!-- 今日日程 -->
|
||||
<div class="schedule-section">
|
||||
<div class="section-header">
|
||||
<h3>今日日程</h3>
|
||||
<h3>{{ $t('home.todaySchedule') }}</h3>
|
||||
<el-button
|
||||
text
|
||||
type="primary"
|
||||
@click="showSchedule"
|
||||
>
|
||||
管理日程
|
||||
{{ $t('home.manageSchedule') }}
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="schedule-list">
|
||||
@@ -202,7 +202,7 @@
|
||||
class="empty-schedule"
|
||||
>
|
||||
<el-empty
|
||||
description="暂无日程安排"
|
||||
:description="$t('home.noSchedule')"
|
||||
:image-size="60"
|
||||
/>
|
||||
</div>
|
||||
@@ -215,6 +215,7 @@
|
||||
import { ref, computed, onMounted, onUnmounted } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { markRaw } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import useUserStore from '@/store/modules/user'
|
||||
import { getHomeStatistics, getPendingEmrCount } from '@/api/home'
|
||||
import { listTodo } from '@/api/workflow/task.js'
|
||||
@@ -307,6 +308,7 @@ import SvgIcon from '@/components/SvgIcon'
|
||||
|
||||
const userStore = useUserStore()
|
||||
const router = useRouter()
|
||||
const { t } = useI18n()
|
||||
|
||||
// 统计数据(从后端获取)
|
||||
const statisticsData = ref({
|
||||
@@ -326,38 +328,38 @@ const statisticsData = ref({
|
||||
})
|
||||
|
||||
// 不同角色的统计数据配置
|
||||
const roleStatsConfig = {
|
||||
const roleStatsConfig = computed(() => ({
|
||||
admin: [
|
||||
{ key: 'totalPatients', label: '在院患者', icon: markRaw(User), type: 'primary', iconColor: '#3B82F6' },
|
||||
{ key: 'todayRevenue', label: '今日收入', icon: markRaw(Money), type: 'success', iconColor: '#10B981' },
|
||||
{ key: 'appointments', label: '今日预约', icon: markRaw(Calendar), type: 'warning', iconColor: '#F59E0B' },
|
||||
{ key: 'pendingApprovals', label: '待审核', icon: markRaw(Document), type: 'danger', iconColor: '#EF4444' }
|
||||
{ key: 'totalPatients', label: t('home.stat.totalPatients'), icon: markRaw(User), type: 'primary', iconColor: '#3B82F6' },
|
||||
{ key: 'todayRevenue', label: t('home.stat.todayRevenue'), icon: markRaw(Money), type: 'success', iconColor: '#10B981' },
|
||||
{ key: 'appointments', label: t('home.stat.appointments'), icon: markRaw(Calendar), type: 'warning', iconColor: '#F59E0B' },
|
||||
{ key: 'pendingApprovals', label: t('home.stat.pendingApprovals'), icon: markRaw(Document), type: 'danger', iconColor: '#EF4444' }
|
||||
],
|
||||
doctor: [
|
||||
{ key: 'myPatients', label: '我的患者', icon: markRaw(User), type: 'primary', iconColor: '#3B82F6' },
|
||||
{ key: 'todayAppointments', label: '今日门诊', icon: markRaw(Calendar), type: 'success', iconColor: '#10B981' },
|
||||
{ key: 'pendingEmr', label: '待写病历', icon: markRaw(Document), type: 'warning', iconColor: '#F59E0B' },
|
||||
{ key: 'prescriptions', label: '今日处方', icon: markRaw(Box), type: 'info', iconColor: '#64748B' }
|
||||
{ key: 'myPatients', label: t('home.stat.myPatients'), icon: markRaw(User), type: 'primary', iconColor: '#3B82F6' },
|
||||
{ key: 'todayAppointments', label: t('home.stat.todayAppointments'), icon: markRaw(Calendar), type: 'success', iconColor: '#10B981' },
|
||||
{ key: 'pendingEmr', label: t('home.stat.pendingEmr'), icon: markRaw(Document), type: 'warning', iconColor: '#F59E0B' },
|
||||
{ key: 'prescriptions', label: t('home.stat.prescriptions'), icon: markRaw(Box), type: 'info', iconColor: '#64748B' }
|
||||
],
|
||||
nurse: [
|
||||
{ key: 'wardPatients', label: '病房患者', icon: markRaw(User), type: 'primary', iconColor: '#3B82F6' },
|
||||
{ key: 'todayTreatments', label: '今日治疗', icon: markRaw(Operation), type: 'success', iconColor: '#10B981' },
|
||||
{ key: 'vitalSigns', label: '待测体征', icon: markRaw(Monitor), type: 'warning', iconColor: '#F59E0B' },
|
||||
{ key: 'drugDistribution', label: '发药次数', icon: markRaw(Box), type: 'info', iconColor: '#64748B' }
|
||||
{ key: 'wardPatients', label: t('home.stat.wardPatients'), icon: markRaw(User), type: 'primary', iconColor: '#3B82F6' },
|
||||
{ key: 'todayTreatments', label: t('home.stat.todayTreatments'), icon: markRaw(Operation), type: 'success', iconColor: '#10B981' },
|
||||
{ key: 'vitalSigns', label: t('home.stat.vitalSigns'), icon: markRaw(Monitor), type: 'warning', iconColor: '#F59E0B' },
|
||||
{ key: 'drugDistribution', label: t('home.stat.drugDistribution'), icon: markRaw(Box), type: 'info', iconColor: '#64748B' }
|
||||
],
|
||||
pharmacist: [
|
||||
{ key: 'todayPrescriptions', label: '今日处方', icon: markRaw(Box), type: 'primary', iconColor: '#3B82F6' },
|
||||
{ key: 'pendingReview', label: '待审核', icon: markRaw(Document), type: 'warning', iconColor: '#F59E0B' },
|
||||
{ key: 'outOfStock', label: '缺货药品', icon: markRaw(Warning), type: 'danger', iconColor: '#EF4444' },
|
||||
{ key: 'nearExpiry', label: '近效期', icon: markRaw(Clock), type: 'info', iconColor: '#64748B' }
|
||||
{ key: 'todayPrescriptions', label: t('home.stat.todayPrescriptions'), icon: markRaw(Box), type: 'primary', iconColor: '#3B82F6' },
|
||||
{ key: 'pendingReview', label: t('home.stat.pendingReview'), icon: markRaw(Document), type: 'warning', iconColor: '#F59E0B' },
|
||||
{ key: 'outOfStock', label: t('home.stat.outOfStock'), icon: markRaw(Warning), type: 'danger', iconColor: '#EF4444' },
|
||||
{ key: 'nearExpiry', label: t('home.stat.nearExpiry'), icon: markRaw(Clock), type: 'info', iconColor: '#64748B' }
|
||||
],
|
||||
cashier: [
|
||||
{ key: 'todayPayments', label: '今日缴费', icon: markRaw(Money), type: 'primary', iconColor: '#3B82F6' },
|
||||
{ key: 'refundRequests', label: '退费申请', icon: markRaw(Document), type: 'warning', iconColor: '#F59E0B' },
|
||||
{ key: 'pendingInvoices', label: '待开发票', icon: markRaw(Files), type: 'info', iconColor: '#64748B' },
|
||||
{ key: 'insuranceClaims', label: '医保结算', icon: markRaw(Wallet), type: 'success', iconColor: '#10B981' }
|
||||
{ key: 'todayPayments', label: t('home.stat.todayPayments'), icon: markRaw(Money), type: 'primary', iconColor: '#3B82F6' },
|
||||
{ key: 'refundRequests', label: t('home.stat.refundRequests'), icon: markRaw(Document), type: 'warning', iconColor: '#F59E0B' },
|
||||
{ key: 'pendingInvoices', label: t('home.stat.pendingInvoices'), icon: markRaw(Files), type: 'info', iconColor: '#64748B' },
|
||||
{ key: 'insuranceClaims', label: t('home.stat.insuranceClaims'), icon: markRaw(Wallet), type: 'success', iconColor: '#10B981' }
|
||||
]
|
||||
}
|
||||
}))
|
||||
|
||||
// 从数据库获取用户配置的快捷功能ID列表
|
||||
const getUserQuickAccessConfig = async () => {
|
||||
@@ -593,48 +595,48 @@ const getDefaultQuickAccessConfig = () => {
|
||||
switch (role) {
|
||||
case 'doctor':
|
||||
return [
|
||||
{ key: 'outpatient', label: '门诊接诊', icon: 'chat-dot-round', iconColor: '#3B82F6', route: '/doctorstation' },
|
||||
{ key: 'emr', label: '病历管理', icon: 'document', iconColor: '#10B981', route: '/doctorstation/doctorphrase' },
|
||||
{ key: 'prescription', label: '开立处方', icon: 'box', iconColor: '#F59E0B', route: '/ybmanagement/ePrescribing' },
|
||||
{ key: 'history', label: '历史处方', icon: 'clock', iconColor: '#EF4444', route: '/clinicmanagement/historicalPrescription' },
|
||||
{ key: 'schedule', label: '排班管理', icon: 'calendar', iconColor: '#64748B', route: '/appoinmentmanage/deptManage' },
|
||||
{ key: 'inquiry', label: '患者查询', icon: 'search', iconColor: '#3B82F6', route: '/patientmanagement' }
|
||||
{ key: 'outpatient', label: t('home.defaultFunctions.outpatient'), icon: 'chat-dot-round', iconColor: '#3B82F6', route: '/doctorstation' },
|
||||
{ key: 'emr', label: t('home.defaultFunctions.emr'), icon: 'document', iconColor: '#10B981', route: '/doctorstation/doctorphrase' },
|
||||
{ key: 'prescription', label: t('home.defaultFunctions.prescription'), icon: 'box', iconColor: '#F59E0B', route: '/ybmanagement/ePrescribing' },
|
||||
{ key: 'history', label: t('home.defaultFunctions.history'), icon: 'clock', iconColor: '#EF4444', route: '/clinicmanagement/historicalPrescription' },
|
||||
{ key: 'schedule', label: t('home.defaultFunctions.schedule'), icon: 'calendar', iconColor: '#64748B', route: '/appoinmentmanage/deptManage' },
|
||||
{ key: 'inquiry', label: t('home.defaultFunctions.inquiry'), icon: 'search', iconColor: '#3B82F6', route: '/patientmanagement' }
|
||||
];
|
||||
case 'nurse':
|
||||
return [
|
||||
{ key: 'ward', label: '病房管理', icon: 'user', iconColor: '#3B82F6', route: '/inpatientNurse/inpatientNurseStation' },
|
||||
{ key: 'execution', label: '医嘱执行', icon: 'operation', iconColor: '#10B981', route: '/inpatientNurse/medicalOrderExecution' },
|
||||
{ key: 'proofread', label: '医嘱核对', icon: 'document', iconColor: '#F59E0B', route: '/inpatientNurse/medicalOrderProofread' },
|
||||
{ key: 'drugCollect', label: '领药管理', icon: 'box', iconColor: '#EF4444', route: '/inpatientNurse/medicineCollect' },
|
||||
{ key: 'tpr', label: '体温单', icon: 'monitor', iconColor: '#64748B', route: '/inpatientNurse/tprsheet' },
|
||||
{ key: 'nursing', label: '护理记录', icon: 'chat-dot-round', iconColor: '#3B82F6', route: '/inpatientNurse/nursingRecord' }
|
||||
{ key: 'ward', label: t('home.defaultFunctions.ward'), icon: 'user', iconColor: '#3B82F6', route: '/inpatientNurse/inpatientNurseStation' },
|
||||
{ key: 'execution', label: t('home.defaultFunctions.execution'), icon: 'operation', iconColor: '#10B981', route: '/inpatientNurse/medicalOrderExecution' },
|
||||
{ key: 'proofread', label: t('home.defaultFunctions.proofread'), icon: 'document', iconColor: '#F59E0B', route: '/inpatientNurse/medicalOrderProofread' },
|
||||
{ key: 'drugCollect', label: t('home.defaultFunctions.drugCollect'), icon: 'box', iconColor: '#EF4444', route: '/inpatientNurse/medicineCollect' },
|
||||
{ key: 'tpr', label: t('home.defaultFunctions.tpr'), icon: 'monitor', iconColor: '#64748B', route: '/inpatientNurse/tprsheet' },
|
||||
{ key: 'nursing', label: t('home.defaultFunctions.nursing'), icon: 'chat-dot-round', iconColor: '#3B82F6', route: '/inpatientNurse/nursingRecord' }
|
||||
];
|
||||
case 'pharmacist':
|
||||
return [
|
||||
{ key: 'dispensing', label: '发药管理', icon: 'box', iconColor: '#3B82F6', route: '/pharmacymanagement' },
|
||||
{ key: 'prescription', label: '处方审核', icon: 'document', iconColor: '#10B981', route: '/pharmacymanagement' },
|
||||
{ key: 'inventory', label: '库存管理', icon: 'van', iconColor: '#F59E0B', route: '/medicineStorage' },
|
||||
{ key: 'purchase', label: '采购管理', icon: 'shopping-cart', iconColor: '#EF4444', route: '/medicineStorage' },
|
||||
{ key: 'warning', label: '效期预警', icon: 'warning', iconColor: '#EF4444', route: '/medicationmanagement/statisticalManagement/statisticalManagement' },
|
||||
{ key: 'statistics', label: '用药统计', icon: 'data-line', iconColor: '#64748B', route: '/monitor' }
|
||||
{ key: 'dispensing', label: t('home.defaultFunctions.dispensing'), icon: 'box', iconColor: '#3B82F6', route: '/pharmacymanagement' },
|
||||
{ key: 'prescription', label: t('home.defaultFunctions.rxReview'), icon: 'document', iconColor: '#10B981', route: '/pharmacymanagement' },
|
||||
{ key: 'inventory', label: t('home.defaultFunctions.inventory'), icon: 'van', iconColor: '#F59E0B', route: '/medicineStorage' },
|
||||
{ key: 'purchase', label: t('home.defaultFunctions.purchase'), icon: 'shopping-cart', iconColor: '#EF4444', route: '/medicineStorage' },
|
||||
{ key: 'warning', label: t('home.defaultFunctions.warning'), icon: 'warning', iconColor: '#EF4444', route: '/medicationmanagement/statisticalManagement/statisticalManagement' },
|
||||
{ key: 'statistics', label: t('home.defaultFunctions.statistics'), icon: 'data-line', iconColor: '#64748B', route: '/monitor' }
|
||||
];
|
||||
case 'cashier':
|
||||
return [
|
||||
{ key: 'registration', label: '挂号收费', icon: 'money', iconColor: '#3B82F6', route: '/charge/outpatientregistration' },
|
||||
{ key: 'clinicCharge', label: '门诊收费', icon: 'wallet', iconColor: '#10B981', route: '/clinic/charge/cliniccharge' },
|
||||
{ key: 'refund', label: '退费管理', icon: 'document', iconColor: '#F59E0B', route: '/charge/clinicrefund' },
|
||||
{ key: 'invoice', label: '发票打印', icon: 'files', iconColor: '#EF4444', route: '/basicmanage/InvoiceManagement' },
|
||||
{ key: 'record', label: '收费记录', icon: 'clock', iconColor: '#64748B', route: '/charge/clinicRecord' },
|
||||
{ key: 'insurance', label: '医保结算', icon: 'bell', iconColor: '#3B82F6', route: '/ybmanagement' }
|
||||
{ key: 'registration', label: t('home.defaultFunctions.registration'), icon: 'money', iconColor: '#3B82F6', route: '/charge/outpatientregistration' },
|
||||
{ key: 'clinicCharge', label: t('home.defaultFunctions.clinicCharge'), icon: 'wallet', iconColor: '#10B981', route: '/clinic/charge/cliniccharge' },
|
||||
{ key: 'refund', label: t('home.defaultFunctions.refund'), icon: 'document', iconColor: '#F59E0B', route: '/charge/clinicrefund' },
|
||||
{ key: 'invoice', label: t('home.defaultFunctions.invoice'), icon: 'files', iconColor: '#EF4444', route: '/basicmanage/InvoiceManagement' },
|
||||
{ key: 'record', label: t('home.defaultFunctions.record'), icon: 'clock', iconColor: '#64748B', route: '/charge/clinicRecord' },
|
||||
{ key: 'insurance', label: t('home.defaultFunctions.insurance'), icon: 'bell', iconColor: '#3B82F6', route: '/ybmanagement' }
|
||||
];
|
||||
default: // admin
|
||||
return [
|
||||
{ key: 'patient', label: '患者管理', icon: 'user', iconColor: '#3B82F6', route: '/patient/patientmgr' },
|
||||
{ key: 'appointment', label: '预约管理', icon: 'calendar', iconColor: '#10B981', route: '/appoinmentmanage/outpatientAppointment' },
|
||||
{ key: 'doctor', label: '医生管理', icon: 'user', iconColor: '#F59E0B', route: '/doctorstation' },
|
||||
{ key: 'surgery', label: '手术管理', icon: 'operation', iconColor: '#EF4444', route: '/surgerymanage' },
|
||||
{ key: 'drug', label: '药品管理', icon: 'box', iconColor: '#64748B', route: '/pharmacymanagement' },
|
||||
{ key: 'statistic', label: '数据统计', icon: 'trend-charts', iconColor: '#3B82F6', route: '/monitor' }
|
||||
{ key: 'patient', label: t('home.defaultFunctions.patient'), icon: 'user', iconColor: '#3B82F6', route: '/patient/patientmgr' },
|
||||
{ key: 'appointment', label: t('home.defaultFunctions.appointment'), icon: 'calendar', iconColor: '#10B981', route: '/appoinmentmanage/outpatientAppointment' },
|
||||
{ key: 'doctor', label: t('home.defaultFunctions.doctor'), icon: 'user', iconColor: '#F59E0B', route: '/doctorstation' },
|
||||
{ key: 'surgery', label: t('home.defaultFunctions.surgery'), icon: 'operation', iconColor: '#EF4444', route: '/surgerymanage' },
|
||||
{ key: 'drug', label: t('home.defaultFunctions.drug'), icon: 'box', iconColor: '#64748B', route: '/pharmacymanagement' },
|
||||
{ key: 'statistic', label: t('home.defaultFunctions.statistic'), icon: 'trend-charts', iconColor: '#3B82F6', route: '/monitor' }
|
||||
];
|
||||
}
|
||||
};
|
||||
@@ -644,9 +646,9 @@ const todoList = ref([])
|
||||
|
||||
// 更新待办事项中的待写病历数量
|
||||
const updatePendingEmrTodo = () => {
|
||||
const pendingEmrTodo = todoList.value.find(item => item.title === '待写病历' || item.desc?.includes('患者等待写病历'));
|
||||
const pendingEmrTodo = todoList.value.find(item => item.title === t('home.pendingEmr') || item.desc?.includes('患者等待写病历'));
|
||||
if (pendingEmrTodo) {
|
||||
pendingEmrTodo.desc = `有${statisticsData.value.pendingEmr || 0}个患者等待写病历`;
|
||||
pendingEmrTodo.desc = t('home.pendingEmrDesc', { count: statisticsData.value.pendingEmr || 0 });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -656,23 +658,23 @@ const scheduleList = ref([])
|
||||
// 获取问候语
|
||||
const getGreeting = () => {
|
||||
const hour = new Date().getHours()
|
||||
if (hour < 6) return '夜深了'
|
||||
if (hour < 9) return '早上好'
|
||||
if (hour < 12) return '上午好'
|
||||
if (hour < 14) return '中午好'
|
||||
if (hour < 17) return '下午好'
|
||||
if (hour < 19) return '傍晚好'
|
||||
return '晚上好'
|
||||
if (hour < 6) return t('home.greeting.night')
|
||||
if (hour < 9) return t('home.greeting.morning')
|
||||
if (hour < 12) return t('home.greeting.forenoon')
|
||||
if (hour < 14) return t('home.greeting.noon')
|
||||
if (hour < 17) return t('home.greeting.afternoon')
|
||||
if (hour < 19) return t('home.greeting.evening')
|
||||
return t('home.greeting.night2')
|
||||
}
|
||||
|
||||
// 获取角色名称
|
||||
const getRoleName = (role) => {
|
||||
const roleMap = {
|
||||
admin: '管理员',
|
||||
doctor: '医生',
|
||||
nurse: '护士',
|
||||
pharmacist: '药剂师',
|
||||
cashier: '收费员'
|
||||
admin: t('home.role.admin'),
|
||||
doctor: t('home.role.doctor'),
|
||||
nurse: t('home.role.nurse'),
|
||||
pharmacist: t('home.role.pharmacist'),
|
||||
cashier: t('home.role.cashier')
|
||||
}
|
||||
return roleMap[role] || role
|
||||
}
|
||||
@@ -692,7 +694,7 @@ const getRoleTagType = (role) => {
|
||||
// 根据角色获取当前统计数据
|
||||
const currentStats = computed(() => {
|
||||
const role = userStore.roles[0] || 'admin'
|
||||
const baseConfig = roleStatsConfig[role] || roleStatsConfig.admin
|
||||
const baseConfig = roleStatsConfig.value[role] || roleStatsConfig.value.admin
|
||||
|
||||
// 合并配置和实际数据
|
||||
return baseConfig.map(stat => {
|
||||
@@ -814,7 +816,7 @@ const handleStatClick = (stat) => {
|
||||
if (exists) {
|
||||
router.push(path)
|
||||
} else {
|
||||
ElMessage.warning('您没有该页面的访问权限,请联系管理员添加菜单')
|
||||
ElMessage.warning(t('home.noAccess'))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -938,16 +940,15 @@ const fetchTodoList = async () => {
|
||||
}))
|
||||
|
||||
// 检查是否已经有"待写病历"任务,如果没有则添加
|
||||
const hasPendingEmrTask = todoData.some(task => task.title === '待写病历' || task.desc?.includes('患者等待写病历'));
|
||||
const hasPendingEmrTask = todoData.some(task => task.title === t('home.pendingEmr') || task.desc?.includes('患者等待写病历'));
|
||||
if (!hasPendingEmrTask && statisticsData.value.pendingEmr > 0) {
|
||||
// 添加待写病历任务
|
||||
const pendingEmrTask = {
|
||||
id: Date.now(), // 使用时间戳作为唯一ID
|
||||
title: '待写病历',
|
||||
desc: `有${statisticsData.value.pendingEmr || 0}个患者等待写病历`,
|
||||
id: Date.now(),
|
||||
title: t('home.pendingEmr'),
|
||||
desc: t('home.pendingEmrDesc', { count: statisticsData.value.pendingEmr || 0 }),
|
||||
priority: 'high',
|
||||
icon: markRaw(Document),
|
||||
time: '刚刚',
|
||||
time: t('home.justNow'),
|
||||
taskInfo: null
|
||||
};
|
||||
// 如果数组未满5个,添加到末尾;否则替换最后一个
|
||||
@@ -1043,21 +1044,21 @@ const fetchScheduleList = async () => {
|
||||
console.error('获取排班信息失败:', response.msg)
|
||||
// 如果API调用失败,使用默认数据
|
||||
scheduleList.value = [
|
||||
{ id: 1, time: '09:00', title: '科室晨会', location: '第一会议室', type: 'info', tag: '日常' },
|
||||
{ id: 2, time: '10:30', title: '病例讨论', location: '第二会议室', type: 'primary', tag: '会议' },
|
||||
{ id: 3, time: '14:00', title: '专家查房', location: '住院部3楼', type: 'warning', tag: '重要' },
|
||||
{ id: 4, time: '16:00', title: '新药培训', location: '培训中心', type: 'success', tag: '培训' }
|
||||
{ id: 1, time: '09:00', title: t('home.defaultSchedule.morningMeeting'), location: t('home.defaultSchedule.conferenceRoom1'), type: 'info', tag: t('home.defaultSchedule.daily') },
|
||||
{ id: 2, time: '10:30', title: t('home.defaultSchedule.caseDiscussion'), location: t('home.defaultSchedule.conferenceRoom2'), type: 'primary', tag: t('home.defaultSchedule.meeting') },
|
||||
{ id: 3, time: '14:00', title: t('home.defaultSchedule.wardRound'), location: t('home.defaultSchedule.ward3f'), type: 'warning', tag: t('home.defaultSchedule.important') },
|
||||
{ id: 4, time: '16:00', title: t('home.defaultSchedule.drugTraining'), location: t('home.defaultSchedule.trainingCenter'), type: 'success', tag: t('home.defaultSchedule.training') }
|
||||
]
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取排班信息异常:', error)
|
||||
// 如果出现异常,使用默认数据
|
||||
scheduleList.value = [
|
||||
{ id: 1, time: '09:00', title: '科室晨会', location: '第一会议室', type: 'info', tag: '日常' },
|
||||
{ id: 2, time: '10:30', title: '病例讨论', location: '第二会议室', type: 'primary', tag: '会议' },
|
||||
{ id: 3, time: '14:00', title: '专家查房', location: '住院部3楼', type: 'warning', tag: '重要' },
|
||||
{ id: 4, time: '16:00', title: '新药培训', location: '培训中心', type: 'success', tag: '培训' }
|
||||
]
|
||||
{ id: 1, time: '09:00', title: t('home.defaultSchedule.morningMeeting'), location: t('home.defaultSchedule.conferenceRoom1'), type: 'info', tag: t('home.defaultSchedule.daily') },
|
||||
{ id: 2, time: '10:30', title: t('home.defaultSchedule.caseDiscussion'), location: t('home.defaultSchedule.conferenceRoom2'), type: 'primary', tag: t('home.defaultSchedule.meeting') },
|
||||
{ id: 3, time: '14:00', title: t('home.defaultSchedule.wardRound'), location: t('home.defaultSchedule.ward3f'), type: 'warning', tag: t('home.defaultSchedule.important') },
|
||||
{ id: 4, time: '16:00', title: t('home.defaultSchedule.drugTraining'), location: t('home.defaultSchedule.trainingCenter'), type: 'success', tag: t('home.defaultSchedule.training') }
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
<template>
|
||||
<div style="padding:16px">
|
||||
<div style="margin-bottom:16px;display:flex;justify-content:space-between;align-items:center">
|
||||
<span style="font-size:18px;font-weight:bold">临床知识库</span>
|
||||
<span style="font-size:18px;font-weight:bold">{{ $t('knowledge.title') }}</span>
|
||||
<div>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="loadData"
|
||||
>
|
||||
刷新
|
||||
{{ $t('common.refresh') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
@click="showAdd = true"
|
||||
>
|
||||
新增知识
|
||||
{{ $t('knowledge.addKnowledge') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -53,43 +53,43 @@
|
||||
style="margin-bottom:16px"
|
||||
>
|
||||
<el-form inline>
|
||||
<el-form-item label="关键词">
|
||||
<el-form-item :label="$t('knowledge.keyword')">
|
||||
<el-input
|
||||
v-model="keyword"
|
||||
placeholder="指南/药物/诊断/操作"
|
||||
:placeholder="$t('knowledge.keywordPlaceholder')"
|
||||
clearable
|
||||
style="width:200px"
|
||||
@keyup.enter="loadData"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="分类">
|
||||
<el-form-item :label="$t('knowledge.category')">
|
||||
<el-select
|
||||
v-model="category"
|
||||
clearable
|
||||
style="width:140px"
|
||||
>
|
||||
<el-option
|
||||
label="临床指南"
|
||||
:label="$t('knowledge.cat.guideline')"
|
||||
value="guideline"
|
||||
/>
|
||||
<el-option
|
||||
label="药物信息"
|
||||
:label="$t('knowledge.cat.drug')"
|
||||
value="drug"
|
||||
/>
|
||||
<el-option
|
||||
label="诊断标准"
|
||||
:label="$t('knowledge.cat.diagnosis')"
|
||||
value="diagnosis"
|
||||
/>
|
||||
<el-option
|
||||
label="操作规范"
|
||||
:label="$t('knowledge.cat.procedure')"
|
||||
value="procedure"
|
||||
/>
|
||||
<el-option
|
||||
label="护理规范"
|
||||
:label="$t('knowledge.cat.nursing')"
|
||||
value="nursing"
|
||||
/>
|
||||
<el-option
|
||||
label="感染控制"
|
||||
:label="$t('knowledge.cat.infection')"
|
||||
value="infection"
|
||||
/>
|
||||
</el-select>
|
||||
@@ -99,10 +99,10 @@
|
||||
type="primary"
|
||||
@click="loadData"
|
||||
>
|
||||
搜索
|
||||
{{ $t('common.search') }}
|
||||
</el-button>
|
||||
<el-button @click="keyword='';category='';loadData()">
|
||||
重置
|
||||
{{ $t('common.reset') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
@@ -117,7 +117,7 @@
|
||||
>
|
||||
<el-table-column
|
||||
prop="category"
|
||||
label="分类"
|
||||
:label="$t('knowledge.category')"
|
||||
width="100"
|
||||
align="center"
|
||||
>
|
||||
@@ -129,30 +129,30 @@
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="title"
|
||||
label="标题"
|
||||
:label="$t('knowledge.titleCol')"
|
||||
min-width="200"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="keywords"
|
||||
label="关键词"
|
||||
:label="$t('knowledge.keywords')"
|
||||
width="150"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="source"
|
||||
label="来源"
|
||||
:label="$t('knowledge.source')"
|
||||
width="120"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="version"
|
||||
label="版本"
|
||||
:label="$t('knowledge.version')"
|
||||
width="80"
|
||||
align="center"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="status"
|
||||
label="状态"
|
||||
:label="$t('common.status')"
|
||||
width="80"
|
||||
align="center"
|
||||
>
|
||||
@@ -161,17 +161,17 @@
|
||||
:type="row.status==='ACTIVE'?'success':'info'"
|
||||
size="small"
|
||||
>
|
||||
{{ row.status==='ACTIVE'?'启用':'停用' }}
|
||||
{{ row.status==='ACTIVE'?$t('common.enabled'):$t('common.disabled') }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="updateTime"
|
||||
label="更新时间"
|
||||
:label="$t('knowledge.updateTime')"
|
||||
width="160"
|
||||
/>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
:label="$t('common.operation')"
|
||||
width="100"
|
||||
fixed="right"
|
||||
>
|
||||
@@ -181,7 +181,7 @@
|
||||
type="primary"
|
||||
@click="handleDetail(row)"
|
||||
>
|
||||
查看
|
||||
{{ $t('common.view') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -200,7 +200,7 @@
|
||||
<!-- 新增弹窗 -->
|
||||
<el-dialog
|
||||
v-model="showAdd"
|
||||
title="新增知识条目"
|
||||
:title="$t('knowledge.addDialogTitle')"
|
||||
width="650px"
|
||||
append-to-body
|
||||
>
|
||||
@@ -209,78 +209,78 @@
|
||||
label-width="100px"
|
||||
>
|
||||
<el-form-item
|
||||
label="标题"
|
||||
:label="$t('knowledge.titleCol')"
|
||||
required
|
||||
>
|
||||
<el-input
|
||||
v-model="formData.title"
|
||||
placeholder="请输入标题"
|
||||
:placeholder="$t('knowledge.titlePlaceholder')"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="分类"
|
||||
:label="$t('knowledge.category')"
|
||||
required
|
||||
>
|
||||
<el-select
|
||||
v-model="formData.category"
|
||||
placeholder="请选择"
|
||||
:placeholder="$t('knowledge.categoryPlaceholder')"
|
||||
>
|
||||
<el-option
|
||||
label="临床指南"
|
||||
:label="$t('knowledge.cat.guideline')"
|
||||
value="guideline"
|
||||
/>
|
||||
<el-option
|
||||
label="药物信息"
|
||||
:label="$t('knowledge.cat.drug')"
|
||||
value="drug"
|
||||
/>
|
||||
<el-option
|
||||
label="诊断标准"
|
||||
:label="$t('knowledge.cat.diagnosis')"
|
||||
value="diagnosis"
|
||||
/>
|
||||
<el-option
|
||||
label="操作规范"
|
||||
:label="$t('knowledge.cat.procedure')"
|
||||
value="procedure"
|
||||
/>
|
||||
<el-option
|
||||
label="护理规范"
|
||||
:label="$t('knowledge.cat.nursing')"
|
||||
value="nursing"
|
||||
/>
|
||||
<el-option
|
||||
label="感染控制"
|
||||
:label="$t('knowledge.cat.infection')"
|
||||
value="infection"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="关键词">
|
||||
<el-form-item :label="$t('knowledge.keywords')">
|
||||
<el-input
|
||||
v-model="formData.keywords"
|
||||
placeholder="多个关键词用逗号分隔"
|
||||
:placeholder="$t('knowledge.keywordsPlaceholder')"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="来源">
|
||||
<el-form-item :label="$t('knowledge.source')">
|
||||
<el-input
|
||||
v-model="formData.source"
|
||||
placeholder="如: 中华医学会"
|
||||
:placeholder="$t('knowledge.sourcePlaceholder')"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="内容">
|
||||
<el-form-item :label="$t('knowledge.content')">
|
||||
<el-input
|
||||
v-model="formData.content"
|
||||
type="textarea"
|
||||
:rows="6"
|
||||
placeholder="请输入知识内容"
|
||||
:placeholder="$t('knowledge.contentPlaceholder')"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="showAdd = false">
|
||||
取消
|
||||
{{ $t('common.cancel') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="submitForm"
|
||||
>
|
||||
确定
|
||||
{{ $t('common.confirm') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
@@ -296,31 +296,31 @@
|
||||
:column="2"
|
||||
border
|
||||
>
|
||||
<el-descriptions-item label="分类">
|
||||
<el-descriptions-item :label="$t('knowledge.category')">
|
||||
{{ categoryText(detailData.category) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="来源">
|
||||
<el-descriptions-item :label="$t('knowledge.source')">
|
||||
{{ detailData.source }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item
|
||||
label="关键词"
|
||||
:label="$t('knowledge.keywords')"
|
||||
:span="2"
|
||||
>
|
||||
{{ detailData.keywords }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="版本">
|
||||
<el-descriptions-item :label="$t('knowledge.version')">
|
||||
{{ detailData.version }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="状态">
|
||||
{{ detailData.status==='ACTIVE'?'启用':'停用' }}
|
||||
<el-descriptions-item :label="$t('common.status')">
|
||||
{{ detailData.status==='ACTIVE'?$t('common.enabled'):$t('common.disabled') }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<div style="margin-top:16px;padding:12px;background:#f5f7fa;border-radius:4px;min-height:100px;white-space:pre-wrap;">
|
||||
{{ detailData.content || '暂无内容' }}
|
||||
{{ detailData.content || $t('knowledge.noContent') }}
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="detailVisible = false">
|
||||
关闭
|
||||
{{ $t('common.close') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
@@ -328,10 +328,13 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {ref, onMounted} from 'vue'
|
||||
import {ref, computed, onMounted} from 'vue'
|
||||
import {useI18n} from 'vue-i18n'
|
||||
import {ElMessage} from 'element-plus'
|
||||
import {getKBPage, addKB} from './api'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const loading = ref(false)
|
||||
const kbData = ref([])
|
||||
const total = ref(0)
|
||||
@@ -343,19 +346,21 @@ const showAdd = ref(false)
|
||||
const detailVisible = ref(false)
|
||||
const detailData = ref({})
|
||||
|
||||
const statCards = ref([
|
||||
{label:'总条目', value:0, color:'#409eff'},
|
||||
{label:'指南', value:0, color:'#67c23a'},
|
||||
{label:'药物', value:0, color:'#e6a23c'},
|
||||
{label:'诊断', value:0, color:'#f56c6c'},
|
||||
{label:'操作规范', value:0, color:'#909399'},
|
||||
{label:'其他', value:0, color:'#409eff'}
|
||||
const stats = ref({total:0, guideline:0, drug:0, diagnosis:0, procedure:0, other:0})
|
||||
|
||||
const statCards = computed(() => [
|
||||
{label:t('knowledge.stats.total'), value:stats.value.total, color:'#409eff'},
|
||||
{label:t('knowledge.stats.guideline'), value:stats.value.guideline, color:'#67c23a'},
|
||||
{label:t('knowledge.stats.drug'), value:stats.value.drug, color:'#e6a23c'},
|
||||
{label:t('knowledge.stats.diagnosis'), value:stats.value.diagnosis, color:'#f56c6c'},
|
||||
{label:t('knowledge.stats.procedure'), value:stats.value.procedure, color:'#909399'},
|
||||
{label:t('knowledge.stats.other'), value:stats.value.other, color:'#409eff'}
|
||||
])
|
||||
|
||||
const formData = ref({title:'', category:'guideline', keywords:'', source:'', content:''})
|
||||
|
||||
function categoryText(c) {
|
||||
return {guideline:'临床指南',drug:'药物信息',diagnosis:'诊断标准',procedure:'操作规范',nursing:'护理规范',infection:'感染控制'}[c] || c
|
||||
return {guideline:t('knowledge.cat.guideline'),drug:t('knowledge.cat.drug'),diagnosis:t('knowledge.cat.diagnosis'),procedure:t('knowledge.cat.procedure'),nursing:t('knowledge.cat.nursing'),infection:t('knowledge.cat.infection')}[c] || c
|
||||
}
|
||||
|
||||
async function loadData() {
|
||||
@@ -364,15 +369,16 @@ async function loadData() {
|
||||
const r = await getKBPage({keyword:keyword.value, category:category.value, pageNo:pageNo.value, pageSize:pageSize.value})
|
||||
kbData.value = r.data?.records || []
|
||||
total.value = r.data?.total || 0
|
||||
// Stats
|
||||
let counts = {guideline:0, drug:0, diagnosis:0, procedure:0, nursing:0, infection:0}
|
||||
kbData.value.forEach(row => { if (counts[row.category] !== undefined) counts[row.category]++ })
|
||||
statCards.value[0].value = total.value
|
||||
statCards.value[1].value = counts.guideline
|
||||
statCards.value[2].value = counts.drug
|
||||
statCards.value[3].value = counts.diagnosis
|
||||
statCards.value[4].value = counts.procedure
|
||||
statCards.value[5].value = counts.nursing + counts.infection
|
||||
stats.value = {
|
||||
total: total.value,
|
||||
guideline: counts.guideline,
|
||||
drug: counts.drug,
|
||||
diagnosis: counts.diagnosis,
|
||||
procedure: counts.procedure,
|
||||
other: counts.nursing + counts.infection
|
||||
}
|
||||
} finally { loading.value = false }
|
||||
}
|
||||
|
||||
@@ -383,7 +389,7 @@ function handleDetail(row) {
|
||||
|
||||
async function submitForm() {
|
||||
await addKB(formData.value)
|
||||
ElMessage.success('新增成功')
|
||||
ElMessage.success(t('knowledge.addSuccess'))
|
||||
showAdd.value = false
|
||||
loadData()
|
||||
}
|
||||
|
||||
@@ -13,19 +13,19 @@
|
||||
class="sidebar-item"
|
||||
@click="navigateToTab(0)"
|
||||
>
|
||||
检验类型
|
||||
{{ $t('maintain.inspection.packageMgmt.sidebar.inspectionType') }}
|
||||
</div>
|
||||
<div
|
||||
class="sidebar-item"
|
||||
@click="navigateToTab(1)"
|
||||
>
|
||||
检验项目
|
||||
{{ $t('maintain.inspection.packageMgmt.sidebar.inspectionItem') }}
|
||||
</div>
|
||||
<div
|
||||
class="sidebar-item active"
|
||||
@click="navigateToTab(2)"
|
||||
>
|
||||
套餐设置
|
||||
{{ $t('maintain.inspection.packageMgmt.sidebar.packageSetup') }}
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
@@ -42,24 +42,24 @@
|
||||
<!-- 查询过滤区域 -->
|
||||
<section class="filter-bar">
|
||||
<div class="filter-item">
|
||||
<label>日期:</label>
|
||||
<label>{{ $t('maintain.inspection.packageMgmt.filter.date') }}</label>
|
||||
<input
|
||||
v-model="searchParams.startDate"
|
||||
type="date"
|
||||
placeholder="开始日期"
|
||||
:placeholder="$t('maintain.inspection.packageMgmt.placeholder.startDate')"
|
||||
>
|
||||
<span>至</span>
|
||||
<span>{{ $t('maintain.inspection.packageMgmt.filter.to') }}</span>
|
||||
<input
|
||||
v-model="searchParams.endDate"
|
||||
type="date"
|
||||
placeholder="结束日期"
|
||||
:placeholder="$t('maintain.inspection.packageMgmt.placeholder.endDate')"
|
||||
>
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>卫生机构:</label>
|
||||
<label>{{ $t('maintain.inspection.packageMgmt.filter.institution') }}</label>
|
||||
<el-select
|
||||
v-model="selectedTenantId"
|
||||
placeholder="请选择机构"
|
||||
:placeholder="$t('maintain.inspection.packageMgmt.placeholder.selectInstitution')"
|
||||
style="width: 150px;"
|
||||
clearable
|
||||
@change="handleSearch"
|
||||
@@ -73,41 +73,41 @@
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>套餐名称:</label>
|
||||
<label>{{ $t('maintain.inspection.packageMgmt.filter.packageName') }}</label>
|
||||
<input
|
||||
v-model="searchParams.packageName"
|
||||
type="text"
|
||||
placeholder="套餐名称"
|
||||
:placeholder="$t('maintain.inspection.packageMgmt.placeholder.packageName')"
|
||||
>
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>套餐级别:</label>
|
||||
<label>{{ $t('maintain.inspection.packageMgmt.filter.packageLevel') }}</label>
|
||||
<select v-model="searchParams.packageLevel">
|
||||
<option value="">
|
||||
请选择套餐级别
|
||||
{{ $t('maintain.inspection.packageMgmt.placeholder.selectPackageLevel') }}
|
||||
</option>
|
||||
<option value="全院套餐">
|
||||
全院套餐
|
||||
{{ $t('maintain.inspection.packageMgmt.options.hospitalPackage') }}
|
||||
</option>
|
||||
<option value="科室套餐">
|
||||
科室套餐
|
||||
{{ $t('maintain.inspection.packageMgmt.options.departmentPackage') }}
|
||||
</option>
|
||||
<option value="个人套餐">
|
||||
个人套餐
|
||||
{{ $t('maintain.inspection.packageMgmt.options.personalPackage') }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>套餐类别:</label>
|
||||
<label>{{ $t('maintain.inspection.packageMgmt.filter.packageCategory') }}</label>
|
||||
<select>
|
||||
<option>检验套餐</option>
|
||||
<option>{{ $t('maintain.inspection.packageMgmt.options.inspectionPackage') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-item filter-item-department">
|
||||
<label>科室:</label>
|
||||
<label>{{ $t('maintain.inspection.packageMgmt.filter.department') }}</label>
|
||||
<el-tree-select
|
||||
v-model="searchParams.department"
|
||||
placeholder="请选择科室"
|
||||
:placeholder="$t('maintain.inspection.packageMgmt.placeholder.selectDepartment')"
|
||||
:data="departments"
|
||||
:props="{
|
||||
value: 'name',
|
||||
@@ -122,10 +122,10 @@
|
||||
/>
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>用户:</label>
|
||||
<label>{{ $t('maintain.inspection.packageMgmt.filter.user') }}</label>
|
||||
<el-select
|
||||
v-model="searchParams.user"
|
||||
placeholder="请选择用户"
|
||||
:placeholder="$t('maintain.inspection.packageMgmt.placeholder.selectUser')"
|
||||
style="width: 150px;"
|
||||
clearable
|
||||
filterable
|
||||
@@ -153,7 +153,7 @@
|
||||
<i
|
||||
class="fas fa-search"
|
||||
style="margin-right: 6px;"
|
||||
/>查询
|
||||
/>{{ $t('maintain.inspection.packageMgmt.button.search') }}
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-reset"
|
||||
@@ -162,7 +162,7 @@
|
||||
<i
|
||||
class="fas fa-redo"
|
||||
style="margin-right: 6px;"
|
||||
/>重置
|
||||
/>{{ $t('maintain.inspection.packageMgmt.button.reset') }}
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
@@ -171,7 +171,7 @@
|
||||
<i
|
||||
class="fas fa-plus"
|
||||
style="margin-right: 6px;"
|
||||
/>新增
|
||||
/>{{ $t('maintain.inspection.packageMgmt.button.add') }}
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-export"
|
||||
@@ -180,7 +180,7 @@
|
||||
<i
|
||||
class="fas fa-download"
|
||||
style="margin-right: 6px;"
|
||||
/>导出
|
||||
/>{{ $t('maintain.inspection.packageMgmt.button.export') }}
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-copy"
|
||||
@@ -189,7 +189,7 @@
|
||||
<i
|
||||
class="fas fa-arrow-left"
|
||||
style="margin-right: 6px;"
|
||||
/>返回
|
||||
/>{{ $t('maintain.inspection.packageMgmt.button.back') }}
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
@@ -199,28 +199,28 @@
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>卫生机构</th>
|
||||
<th>日期</th>
|
||||
<th>套餐名称</th>
|
||||
<th>套餐类别</th>
|
||||
<th>套餐级别</th>
|
||||
<th>科室</th>
|
||||
<th>用户</th>
|
||||
<th>{{ $t('maintain.inspection.packageMgmt.table.id') }}</th>
|
||||
<th>{{ $t('maintain.inspection.packageMgmt.table.institution') }}</th>
|
||||
<th>{{ $t('maintain.inspection.packageMgmt.table.date') }}</th>
|
||||
<th>{{ $t('maintain.inspection.packageMgmt.table.packageName') }}</th>
|
||||
<th>{{ $t('maintain.inspection.packageMgmt.table.packageCategory') }}</th>
|
||||
<th>{{ $t('maintain.inspection.packageMgmt.table.packageLevel') }}</th>
|
||||
<th>{{ $t('maintain.inspection.packageMgmt.table.department') }}</th>
|
||||
<th>{{ $t('maintain.inspection.packageMgmt.table.user') }}</th>
|
||||
<th class="text-right">
|
||||
金额
|
||||
{{ $t('maintain.inspection.packageMgmt.table.amount') }}
|
||||
</th>
|
||||
<th class="text-right">
|
||||
服务费
|
||||
{{ $t('maintain.inspection.packageMgmt.table.serviceFee') }}
|
||||
</th>
|
||||
<th class="text-right">
|
||||
总金额
|
||||
{{ $t('maintain.inspection.packageMgmt.table.totalAmount') }}
|
||||
</th>
|
||||
<th>组合套餐</th>
|
||||
<th>显示套餐名</th>
|
||||
<th>启用标志</th>
|
||||
<th>操作人</th>
|
||||
<th>操作</th>
|
||||
<th>{{ $t('maintain.inspection.packageMgmt.table.combinedPackage') }}</th>
|
||||
<th>{{ $t('maintain.inspection.packageMgmt.table.showPackageName') }}</th>
|
||||
<th>{{ $t('maintain.inspection.packageMgmt.table.enabledFlag') }}</th>
|
||||
<th>{{ $t('maintain.inspection.packageMgmt.table.operator') }}</th>
|
||||
<th>{{ $t('maintain.inspection.packageMgmt.table.action') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -370,7 +370,7 @@
|
||||
>
|
||||
</button>
|
||||
<div class="total-count">
|
||||
总数:{{ total }}
|
||||
{{ $t('maintain.inspection.packageMgmt.pagination.total') }}{{ total }}
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
@@ -381,6 +381,7 @@
|
||||
import {computed, onMounted, ref} from 'vue';
|
||||
import {useRouter} from 'vue-router';
|
||||
import {ElMessage, ElMessageBox} from 'element-plus';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import {getLocationTree} from '@/views/charge/outpatientregistration/components/outpatientregistration';
|
||||
import {listInspectionPackage, delInspectionPackage} from '@/api/system/inspectionPackage';
|
||||
import { getTenantPage } from '@/api/system/tenant';
|
||||
@@ -390,6 +391,7 @@ import useTagsViewStore from '@/store/modules/tagsView';
|
||||
// 创建路由实例
|
||||
const router = useRouter();
|
||||
const tagsViewStore = useTagsViewStore();
|
||||
const { t } = useI18n();
|
||||
|
||||
|
||||
// 侧边栏状态
|
||||
@@ -500,7 +502,7 @@ async function loadUserOptions() {
|
||||
)]
|
||||
allUserOptions.value = uniqueUsers.map(u => ({ value: u, label: u }))
|
||||
} catch (e) {
|
||||
ElMessage.error('加载用户列表失败')
|
||||
ElMessage.error(t('maintain.inspection.packageMgmt.message.loadUserListFailed'))
|
||||
} finally {
|
||||
userLoading.value = false
|
||||
}
|
||||
@@ -623,7 +625,7 @@ async function loadData() {
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
ElMessage.error('加载数据失败: ' + (error.message || '未知错误'))
|
||||
ElMessage.error(t('maintain.inspection.packageMgmt.message.loadDataFailed') + (error.message || t('maintain.inspection.packageMgmt.message.unknownError')))
|
||||
tableData.value = []
|
||||
total.value = 0
|
||||
} finally {
|
||||
@@ -643,7 +645,7 @@ const fetchTenantList = async () => {
|
||||
try {
|
||||
const response = await getTenantPage({ pageNum: 1, pageSize: 100 });
|
||||
|
||||
if (response.code !== 200) throw new Error(response.msg || '获取机构列表失败');
|
||||
if (response.code !== 200) throw new Error(response.msg || t('maintain.inspection.packageMgmt.message.fetchInstitutionFailed'));
|
||||
|
||||
let tenantData = [];
|
||||
const data = response.data;
|
||||
@@ -843,7 +845,7 @@ function handleAdd() {
|
||||
function handleEdit(item) {
|
||||
const packageId = item.basicInformationId || item.id;
|
||||
if (!packageId) {
|
||||
ElMessage.error('无法获取套餐ID,请刷新页面后重试');
|
||||
ElMessage.error(t('maintain.inspection.packageMgmt.message.cannotGetPackageId'));
|
||||
return;
|
||||
}
|
||||
window.location.href = `/maintainSystem/Inspection?tab=2&mode=edit&packageId=${packageId}`;
|
||||
@@ -853,7 +855,7 @@ function handleEdit(item) {
|
||||
function handleView(item) {
|
||||
const packageId = item.basicInformationId || item.id;
|
||||
if (!packageId) {
|
||||
ElMessage.error('无法获取套餐ID,请刷新页面后重试');
|
||||
ElMessage.error(t('maintain.inspection.packageMgmt.message.cannotGetPackageId'));
|
||||
return;
|
||||
}
|
||||
window.location.href = `/maintainSystem/Inspection?tab=2&mode=view&packageId=${packageId}`;
|
||||
@@ -863,11 +865,11 @@ function handleView(item) {
|
||||
async function handleDelete(item) {
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
`确定要删除套餐 "${item.name}" 吗?删除后将无法恢复。`,
|
||||
'确认删除',
|
||||
t('maintain.inspection.packageMgmt.message.confirmDelete', { name: item.name }),
|
||||
t('maintain.inspection.packageMgmt.message.confirmDeleteTitle'),
|
||||
{
|
||||
confirmButtonText: '确定删除',
|
||||
cancelButtonText: '取消',
|
||||
confirmButtonText: t('maintain.inspection.packageMgmt.message.confirmDeleteBtn'),
|
||||
cancelButtonText: t('maintain.inspection.packageMgmt.message.cancel'),
|
||||
type: 'warning'
|
||||
}
|
||||
)
|
||||
@@ -875,7 +877,7 @@ async function handleDelete(item) {
|
||||
// 获取套餐ID(优先使用 basicInformationId)
|
||||
const packageId = item.basicInformationId || item.id
|
||||
if (!packageId) {
|
||||
ElMessage.error('无法获取套餐ID,删除失败')
|
||||
ElMessage.error(t('maintain.inspection.packageMgmt.message.cannotGetPackageIdDelete'))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -883,16 +885,16 @@ async function handleDelete(item) {
|
||||
const response = await delInspectionPackage(packageId)
|
||||
|
||||
if (response && (response.code === 200 || response.code === 0)) {
|
||||
ElMessage.success('删除成功')
|
||||
ElMessage.success(t('maintain.inspection.packageMgmt.message.deleteSuccess'))
|
||||
// 删除成功后,重新加载列表数据
|
||||
loadData()
|
||||
} else {
|
||||
ElMessage.error(response?.msg || response?.message || '删除失败')
|
||||
ElMessage.error(response?.msg || response?.message || t('maintain.inspection.packageMgmt.message.deleteFailed'))
|
||||
}
|
||||
} catch (error) {
|
||||
if (error !== 'cancel' && error !== 'close') {
|
||||
console.error('删除失败:', error)
|
||||
ElMessage.error('删除失败: ' + (error?.message || error?.msg || '未知错误'))
|
||||
ElMessage.error(t('maintain.inspection.packageMgmt.message.deleteFailed') + (error?.message || error?.msg || t('maintain.inspection.packageMgmt.message.unknownError')))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,19 +5,19 @@
|
||||
type="primary"
|
||||
@click="handleDefault"
|
||||
>
|
||||
默认(M)
|
||||
{{ $t('maintain.chargeConfig.default') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
@click="handleSave"
|
||||
>
|
||||
保存(S)
|
||||
{{ $t('maintain.chargeConfig.save') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
@click="handleClose"
|
||||
>
|
||||
关闭(X)
|
||||
{{ $t('maintain.chargeConfig.close') }}
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
@@ -26,25 +26,25 @@
|
||||
class="config-tabs"
|
||||
>
|
||||
<el-tab-pane
|
||||
label="划价收费1"
|
||||
:label="$t('maintain.chargeConfig.tabCharge1')"
|
||||
name="tab1"
|
||||
>
|
||||
<div class="tab-content">
|
||||
划价收费1相关配置
|
||||
{{ $t('maintain.chargeConfig.tabCharge1Desc') }}
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane
|
||||
label="划价收费2"
|
||||
:label="$t('maintain.chargeConfig.tabCharge2')"
|
||||
name="tab2"
|
||||
>
|
||||
<div class="tab-content">
|
||||
划价收费2相关配置
|
||||
{{ $t('maintain.chargeConfig.tabCharge2Desc') }}
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane
|
||||
label="挂号处理"
|
||||
:label="$t('maintain.chargeConfig.tabRegistration')"
|
||||
name="tab3"
|
||||
>
|
||||
<el-form
|
||||
@@ -56,7 +56,7 @@
|
||||
<!-- 第一行 -->
|
||||
<div class="form-row">
|
||||
<el-form-item
|
||||
label="病历本费用(元)"
|
||||
:label="$t('maintain.chargeConfig.medicalRecordFee')"
|
||||
prop="medicalRecordFee"
|
||||
>
|
||||
<el-input-number
|
||||
@@ -78,7 +78,7 @@
|
||||
v-model="formData.medicalRecordFlag"
|
||||
style="margin-right: 8px;"
|
||||
/>
|
||||
<span>病历费入账标志</span>
|
||||
<span>{{ $t('maintain.chargeConfig.medicalRecordFlag') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-form-item>
|
||||
@@ -87,7 +87,7 @@
|
||||
<!-- 第二行 -->
|
||||
<div class="form-row">
|
||||
<el-form-item
|
||||
label="就诊卡费(元)"
|
||||
:label="$t('maintain.chargeConfig.patientCardFee')"
|
||||
prop="patientCardFee"
|
||||
>
|
||||
<el-input-number
|
||||
@@ -109,7 +109,7 @@
|
||||
v-model="formData.isNightShift"
|
||||
style="margin-right: 8px;"
|
||||
/>
|
||||
<span>是否启用晚班</span>
|
||||
<span>{{ $t('maintain.chargeConfig.isNightShift') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-form-item>
|
||||
@@ -128,12 +128,12 @@
|
||||
v-model="formData.patientCardFlag"
|
||||
style="margin-right: 8px;"
|
||||
/>
|
||||
<span>就诊卡记账标志</span>
|
||||
<span>{{ $t('maintain.chargeConfig.patientCardFlag') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="上午接诊起始时间"
|
||||
:label="$t('maintain.chargeConfig.morningStartTime')"
|
||||
prop="morningStartTime"
|
||||
>
|
||||
<el-input
|
||||
@@ -156,7 +156,7 @@
|
||||
v-model="formData.autoGenerateOutpatientNo"
|
||||
style="margin-right: 8px;"
|
||||
/>
|
||||
<span>自动产生门诊号</span>
|
||||
<span>{{ $t('maintain.chargeConfig.autoGenerateOutpatientNo') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-form-item>
|
||||
@@ -171,7 +171,7 @@
|
||||
v-model="formData.allowModifyOutpatientNo"
|
||||
style="margin-right: 8px;"
|
||||
/>
|
||||
<span>建档时是否允许修改门诊号</span>
|
||||
<span>{{ $t('maintain.chargeConfig.allowModifyOutpatientNo') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-form-item>
|
||||
@@ -180,7 +180,7 @@
|
||||
<!-- 第五行 -->
|
||||
<div class="form-row">
|
||||
<el-form-item
|
||||
label="下午起始时间"
|
||||
:label="$t('maintain.chargeConfig.afternoonStartTime')"
|
||||
prop="afternoonStartTime"
|
||||
>
|
||||
<el-input
|
||||
@@ -190,7 +190,7 @@
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="formData.isNightShift"
|
||||
label="晚上起始时间"
|
||||
:label="$t('maintain.chargeConfig.eveningStartTime')"
|
||||
prop="eveningStartTime"
|
||||
>
|
||||
<el-input
|
||||
@@ -203,7 +203,7 @@
|
||||
<!-- 第六行 -->
|
||||
<div class="form-row">
|
||||
<el-form-item
|
||||
label="挂号有效期(天)"
|
||||
:label="$t('maintain.chargeConfig.registrationValidity')"
|
||||
prop="registrationValidity"
|
||||
>
|
||||
<el-input-number
|
||||
@@ -215,7 +215,7 @@
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="挂号单据模式"
|
||||
:label="$t('maintain.chargeConfig.registrationDocumentMode')"
|
||||
prop="registrationDocumentMode"
|
||||
>
|
||||
<el-select
|
||||
@@ -223,11 +223,11 @@
|
||||
style="width: 150px"
|
||||
>
|
||||
<el-option
|
||||
label="使用发票"
|
||||
:label="$t('maintain.chargeConfig.optionInvoice')"
|
||||
value="使用发票"
|
||||
/>
|
||||
<el-option
|
||||
label="普通单据"
|
||||
:label="$t('maintain.chargeConfig.optionNormalDoc')"
|
||||
value="其他模式"
|
||||
/>
|
||||
</el-select>
|
||||
@@ -247,7 +247,7 @@
|
||||
v-model="formData.exemptFlag"
|
||||
style="margin-right: 8px;"
|
||||
/>
|
||||
<span>减免标志</span>
|
||||
<span>{{ $t('maintain.chargeConfig.exemptFlag') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-form-item>
|
||||
@@ -262,7 +262,7 @@
|
||||
v-model="formData.consultationFlag"
|
||||
style="margin-right: 8px;"
|
||||
/>
|
||||
<span>义诊标志</span>
|
||||
<span>{{ $t('maintain.chargeConfig.consultationFlag') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-form-item>
|
||||
@@ -277,7 +277,7 @@
|
||||
v-model="formData.enableHolidayFeeFloat"
|
||||
style="margin-right: 8px;"
|
||||
/>
|
||||
<span>启用法定节假日挂号费浮动</span>
|
||||
<span>{{ $t('maintain.chargeConfig.enableHolidayFeeFloat') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-form-item>
|
||||
@@ -286,7 +286,7 @@
|
||||
<!-- 第八行 -->
|
||||
<div class="form-row">
|
||||
<el-form-item
|
||||
label="监护人规定年龄(岁)"
|
||||
:label="$t('maintain.chargeConfig.guardianAge')"
|
||||
prop="guardianAge"
|
||||
>
|
||||
<el-input-number
|
||||
@@ -308,7 +308,7 @@
|
||||
v-model="formData.enableDoubleScreen"
|
||||
style="margin-right: 8px;"
|
||||
/>
|
||||
<span>门诊挂号启用双屏</span>
|
||||
<span>{{ $t('maintain.chargeConfig.enableDoubleScreen') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-form-item>
|
||||
@@ -327,7 +327,7 @@
|
||||
v-model="formData.optionalRegistrationType"
|
||||
style="margin-right: 8px;"
|
||||
/>
|
||||
<span>挂号类型可选择</span>
|
||||
<span>{{ $t('maintain.chargeConfig.optionalRegistrationType') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-form-item>
|
||||
@@ -336,38 +336,38 @@
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane
|
||||
label="挂号预约"
|
||||
:label="$t('maintain.chargeConfig.tabAppointment')"
|
||||
name="tab4"
|
||||
>
|
||||
<div class="tab-content">
|
||||
挂号预约相关配置
|
||||
{{ $t('maintain.chargeConfig.tabAppointmentDesc') }}
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane
|
||||
label="打印设置"
|
||||
:label="$t('maintain.chargeConfig.tabPrint')"
|
||||
name="tab5"
|
||||
>
|
||||
<el-checkbox v-model="formData.isPrint">
|
||||
是否打印挂号单
|
||||
{{ $t('maintain.chargeConfig.isPrint') }}
|
||||
</el-checkbox>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane
|
||||
label="其他选项"
|
||||
:label="$t('maintain.chargeConfig.tabOther')"
|
||||
name="tab6"
|
||||
>
|
||||
<div class="tab-content">
|
||||
其他选项相关配置
|
||||
{{ $t('maintain.chargeConfig.tabOtherDesc') }}
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane
|
||||
label="病人账户"
|
||||
:label="$t('maintain.chargeConfig.tabAccount')"
|
||||
name="tab7"
|
||||
>
|
||||
<div class="tab-content">
|
||||
病人账户相关配置
|
||||
{{ $t('maintain.chargeConfig.tabAccountDesc') }}
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
@@ -377,9 +377,11 @@
|
||||
<script setup>
|
||||
import {onMounted, reactive, ref} from 'vue';
|
||||
import {useRouter} from 'vue-router';
|
||||
import {useI18n} from 'vue-i18n';
|
||||
import {ElMessage} from 'element-plus';
|
||||
import {addConfig, listConfig, updateConfig} from '@/api/system/config';
|
||||
|
||||
const { t } = useI18n();
|
||||
const router = useRouter();
|
||||
const formRef = ref(null);
|
||||
const activeTab = ref('tab1');
|
||||
@@ -449,11 +451,11 @@ const loadConfigData = async (showSuccessMessage = true) => {
|
||||
}
|
||||
|
||||
if (showSuccessMessage) {
|
||||
ElMessage.success('配置数据加载成功');
|
||||
ElMessage.success(t('maintain.chargeConfig.msgLoadSuccess'));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载配置数据失败:', error);
|
||||
ElMessage.warning('无法加载配置数据,使用默认值');
|
||||
ElMessage.warning(t('maintain.chargeConfig.msgLoadFail'));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -486,7 +488,7 @@ const handleDefault = () => {
|
||||
guardianAge: '16',
|
||||
isPrint: false,
|
||||
});
|
||||
ElMessage.success('已恢复默认值');
|
||||
ElMessage.success(t('maintain.chargeConfig.msgResetDefault'));
|
||||
};
|
||||
|
||||
// 保存按钮点击事件
|
||||
@@ -592,25 +594,25 @@ const handleSave = async () => {
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取配置列表失败:', error);
|
||||
ElMessage.error('获取配置列表失败,无法保存参数');
|
||||
ElMessage.error(t('maintain.chargeConfig.msgGetConfigFail'));
|
||||
return;
|
||||
}
|
||||
|
||||
// 根据保存结果显示相应消息
|
||||
if (failedParams.length === 0) {
|
||||
ElMessage.success(`保存成功`);
|
||||
ElMessage.success(t('maintain.chargeConfig.msgSaveSuccess'));
|
||||
// 保存成功后重新加载数据,确保页面显示最新配置
|
||||
loadConfigData(false); // 不显示加载成功消息
|
||||
} else if (successCount > 0) {
|
||||
ElMessage.warning(`${successCount} 个参数保存成功,但以下 ${failedParams.length} 个参数保存失败: ${failedParams.join(', ')}`);
|
||||
ElMessage.warning(`${successCount} ${t('maintain.chargeConfig.msgPartialSuccess')} ${failedParams.length} ${t('maintain.chargeConfig.msgPartialFailed')}: ${failedParams.join(', ')}`);
|
||||
// 部分成功也重新加载数据
|
||||
loadConfigData(false); // 不显示加载成功消息
|
||||
} else {
|
||||
ElMessage.error(`所有参数保存失败,请检查系统配置`);
|
||||
ElMessage.error(t('maintain.chargeConfig.msgAllSaveFail'));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('保存过程中发生错误:', error);
|
||||
ElMessage.error('保存操作异常,请重试');
|
||||
ElMessage.error(t('maintain.chargeConfig.msgSaveError'));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -7,23 +7,23 @@
|
||||
:inline="true"
|
||||
label-width="80px"
|
||||
>
|
||||
<el-form-item label="日期">
|
||||
<el-form-item :label="$t('maintain.checkProject.packageMgmt.date')">
|
||||
<el-date-picker
|
||||
v-model="dateRange"
|
||||
type="daterange"
|
||||
range-separator="-"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
:start-placeholder="$t('maintain.checkProject.packageMgmt.startDate')"
|
||||
:end-placeholder="$t('maintain.checkProject.packageMgmt.endDate')"
|
||||
format="YYYY-MM-DD"
|
||||
value-format="YYYY-MM-DD"
|
||||
style="width: 240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="卫生机构">
|
||||
<el-form-item :label="$t('maintain.checkProject.packageMgmt.organization')">
|
||||
<el-select
|
||||
v-model="queryParams.organization"
|
||||
placeholder="请选择机构"
|
||||
:placeholder="$t('maintain.checkProject.packageMgmt.selectOrg')"
|
||||
style="width: 150px"
|
||||
clearable
|
||||
filterable
|
||||
@@ -37,19 +37,19 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="套餐名称">
|
||||
<el-form-item :label="$t('maintain.checkProject.packageMgmt.packageName')">
|
||||
<el-input
|
||||
v-model="queryParams.packageName"
|
||||
placeholder="请输入套餐名称"
|
||||
:placeholder="$t('maintain.checkProject.packageMgmt.inputPackageName')"
|
||||
style="width: 200px"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="套餐级别">
|
||||
<el-form-item :label="$t('maintain.checkProject.packageMgmt.packageLevel')">
|
||||
<el-select
|
||||
v-model="queryParams.packageLevel"
|
||||
placeholder="请选择套餐级别"
|
||||
:placeholder="$t('maintain.checkProject.packageMgmt.selectPackageLevel')"
|
||||
style="width: 150px"
|
||||
clearable
|
||||
>
|
||||
@@ -62,24 +62,24 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="套餐类别">
|
||||
<el-form-item :label="$t('maintain.checkProject.packageMgmt.packageType')">
|
||||
<el-select
|
||||
v-model="queryParams.packageType"
|
||||
placeholder="请选择套餐类别"
|
||||
:placeholder="$t('maintain.checkProject.packageMgmt.selectPackageType')"
|
||||
style="width: 150px"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
label="检查套餐"
|
||||
:label="$t('maintain.checkProject.packageMgmt.checkPackage')"
|
||||
value="检查套餐"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="科室">
|
||||
<el-form-item :label="$t('maintain.checkProject.packageMgmt.department')">
|
||||
<el-select
|
||||
v-model="queryParams.department"
|
||||
placeholder="请选择科室"
|
||||
:placeholder="$t('maintain.checkProject.packageMgmt.selectDepartment')"
|
||||
style="width: 150px"
|
||||
clearable
|
||||
filterable
|
||||
@@ -93,10 +93,10 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="用户">
|
||||
<el-form-item :label="$t('maintain.checkProject.packageMgmt.user')">
|
||||
<el-input
|
||||
v-model="queryParams.user"
|
||||
placeholder="请输入用户名称"
|
||||
:placeholder="$t('maintain.checkProject.packageMgmt.inputUserName')"
|
||||
style="width: 150px"
|
||||
clearable
|
||||
/>
|
||||
@@ -108,20 +108,20 @@
|
||||
icon="Search"
|
||||
@click="handleQuery"
|
||||
>
|
||||
查询
|
||||
{{ $t('maintain.checkProject.packageMgmt.query') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
icon="Refresh"
|
||||
@click="handleReset"
|
||||
>
|
||||
重置
|
||||
{{ $t('maintain.checkProject.packageMgmt.reset') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
icon="Plus"
|
||||
@click="handleAdd"
|
||||
>
|
||||
新增
|
||||
{{ $t('maintain.checkProject.packageMgmt.add') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
@@ -145,31 +145,31 @@
|
||||
/>
|
||||
<vxe-column
|
||||
field="organization"
|
||||
title="卫生机构"
|
||||
:title="$t('maintain.checkProject.packageMgmt.organization')"
|
||||
width="120"
|
||||
align="center"
|
||||
/>
|
||||
<vxe-column
|
||||
field="maintainDate"
|
||||
title="日期"
|
||||
:title="$t('maintain.checkProject.packageMgmt.date')"
|
||||
width="120"
|
||||
align="center"
|
||||
/>
|
||||
<vxe-column
|
||||
field="packageName"
|
||||
title="套餐名称"
|
||||
:title="$t('maintain.checkProject.packageMgmt.packageName')"
|
||||
min-width="150"
|
||||
show-overflow="title"
|
||||
/>
|
||||
<vxe-column
|
||||
field="packageType"
|
||||
title="套餐类别"
|
||||
:title="$t('maintain.checkProject.packageMgmt.packageType')"
|
||||
width="100"
|
||||
align="center"
|
||||
/>
|
||||
<vxe-column
|
||||
field="packageLevel"
|
||||
title="套餐级别"
|
||||
:title="$t('maintain.checkProject.packageMgmt.packageLevel')"
|
||||
width="100"
|
||||
align="center"
|
||||
>
|
||||
@@ -179,25 +179,25 @@
|
||||
</vxe-column>
|
||||
<vxe-column
|
||||
field="department"
|
||||
title="科室"
|
||||
:title="$t('maintain.checkProject.packageMgmt.department')"
|
||||
width="150"
|
||||
align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<span :title="row.department && /^[A-Z]\d{2}$/.test(row.department.trim()) ? '旧编码格式,建议编辑套餐重新选择科室' : ''">
|
||||
<span :title="row.department && /^[A-Z]\d{2}$/.test(row.department.trim()) ? $t('maintain.checkProject.packageMgmt.oldFormatHint') : ''">
|
||||
{{ getDeptName(row.department) }}
|
||||
</span>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column
|
||||
field="user"
|
||||
title="用户"
|
||||
:title="$t('maintain.checkProject.packageMgmt.user')"
|
||||
width="100"
|
||||
align="center"
|
||||
/>
|
||||
<vxe-column
|
||||
field="packagePrice"
|
||||
title="金额"
|
||||
:title="$t('maintain.checkProject.packageMgmt.amount')"
|
||||
width="100"
|
||||
align="center"
|
||||
>
|
||||
@@ -207,7 +207,7 @@
|
||||
</vxe-column>
|
||||
<vxe-column
|
||||
field="serviceFee"
|
||||
title="服务费"
|
||||
:title="$t('maintain.checkProject.packageMgmt.serviceFee')"
|
||||
width="100"
|
||||
align="center"
|
||||
>
|
||||
@@ -216,7 +216,7 @@
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column
|
||||
title="总金额"
|
||||
:title="$t('maintain.checkProject.packageMgmt.totalAmount')"
|
||||
width="100"
|
||||
align="center"
|
||||
>
|
||||
@@ -225,46 +225,46 @@
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column
|
||||
title="组合套餐"
|
||||
:title="$t('maintain.checkProject.packageMgmt.comboPackage')"
|
||||
width="100"
|
||||
align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.packagePriceEnabled === 1 ? 'success' : 'danger'">
|
||||
{{ row.packagePriceEnabled === 1 ? '是' : '否' }}
|
||||
{{ row.packagePriceEnabled === 1 ? $t('maintain.checkProject.packageMgmt.yes') : $t('maintain.checkProject.packageMgmt.no') }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column
|
||||
title="显示套餐名"
|
||||
:title="$t('maintain.checkProject.packageMgmt.showPackageName')"
|
||||
width="110"
|
||||
align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.showPackageName === 1 ? 'success' : 'info'">
|
||||
{{ row.showPackageName === 1 ? '是' : '否' }}
|
||||
{{ row.showPackageName === 1 ? $t('maintain.checkProject.packageMgmt.yes') : $t('maintain.checkProject.packageMgmt.no') }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column
|
||||
title="启用标志"
|
||||
:title="$t('maintain.checkProject.packageMgmt.enableFlag')"
|
||||
width="100"
|
||||
align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.isDisabled === 0 ? 'success' : 'danger'">
|
||||
{{ row.isDisabled === 0 ? '是' : '否' }}
|
||||
{{ row.isDisabled === 0 ? $t('maintain.checkProject.packageMgmt.yes') : $t('maintain.checkProject.packageMgmt.no') }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column
|
||||
field="creator"
|
||||
title="操作人"
|
||||
:title="$t('maintain.checkProject.packageMgmt.operator')"
|
||||
width="100"
|
||||
align="center"
|
||||
/>
|
||||
<vxe-column
|
||||
title="操作"
|
||||
:title="$t('maintain.checkProject.packageMgmt.actions')"
|
||||
width="180"
|
||||
align="center"
|
||||
fixed="right"
|
||||
@@ -275,7 +275,7 @@
|
||||
class="btn btn-edit"
|
||||
size="small"
|
||||
circle
|
||||
title="编辑"
|
||||
:title="$t('maintain.checkProject.packageMgmt.edit')"
|
||||
@click="handleEdit(row)"
|
||||
>
|
||||
✏️
|
||||
@@ -284,7 +284,7 @@
|
||||
class="btn btn-view"
|
||||
size="small"
|
||||
circle
|
||||
title="查看"
|
||||
:title="$t('maintain.checkProject.packageMgmt.view')"
|
||||
@click="handleView(row)"
|
||||
>
|
||||
👁️
|
||||
@@ -293,7 +293,7 @@
|
||||
class="btn btn-delete"
|
||||
size="small"
|
||||
circle
|
||||
title="删除"
|
||||
:title="$t('maintain.checkProject.packageMgmt.delete')"
|
||||
@click="handleDelete(row)"
|
||||
>
|
||||
✕
|
||||
@@ -322,6 +322,7 @@
|
||||
|
||||
<script setup>
|
||||
import {onMounted, reactive, ref} from 'vue'
|
||||
import {useI18n} from 'vue-i18n'
|
||||
import {ElMessage, ElMessageBox} from 'element-plus'
|
||||
import {getDicts} from '@/api/system/dict/data'
|
||||
import {listDept} from '@/api/system/dept'
|
||||
@@ -330,6 +331,8 @@ import {getTenantPage} from '@/api/system/tenant'
|
||||
import request from '@/utils/request'
|
||||
import useUserStore from '@/store/modules/user'
|
||||
|
||||
const {t} = useI18n()
|
||||
|
||||
// 定义emit事件
|
||||
const emit = defineEmits(['switch-to-settings'])
|
||||
|
||||
@@ -341,20 +344,20 @@ function handleDelete(row) {
|
||||
console.log('当前用户:', currentUser, '套餐创建者:', row.creator)
|
||||
//只有创建者本人才能删除(creator为空时不能删除)
|
||||
if(!row.creator){
|
||||
ElMessage.warning('该套餐创建者未知,无法删除')
|
||||
ElMessage.warning(t('maintain.checkProject.packageMgmt.creatorUnknown'))
|
||||
return
|
||||
}
|
||||
if(row.creator !== currentUser){
|
||||
ElMessage.warning(`该套餐由"${row.creator}"创建,您没有权限删除`)
|
||||
ElMessage.warning(t('maintain.checkProject.packageMgmt.noPermission', {creator: row.creator}))
|
||||
return
|
||||
}
|
||||
|
||||
ElMessageBox.confirm(
|
||||
`确认删除套餐ID:${row.id} - ${row.packageName} 吗?删除后将无法恢复`,
|
||||
'确认删除',
|
||||
t('maintain.checkProject.packageMgmt.confirmDeleteMsg', {id: row.id, name: row.packageName}),
|
||||
t('maintain.checkProject.packageMgmt.confirmDelete'),
|
||||
{
|
||||
confirmButtonText:'确定删除',
|
||||
cancelButtonText:'取消',
|
||||
confirmButtonText: t('maintain.checkProject.packageMgmt.confirmDeleteBtn'),
|
||||
cancelButtonText: t('maintain.checkProject.packageMgmt.cancel'),
|
||||
type: 'warning',
|
||||
buttonSize:'default'
|
||||
}
|
||||
@@ -362,18 +365,18 @@ function handleDelete(row) {
|
||||
try{const response = await delCheckPackage(row.id)
|
||||
|
||||
if(response && response.code === 200 || response.code === 0){
|
||||
ElMessage.success('删除成功')
|
||||
ElMessage.success(t('maintain.checkProject.packageMgmt.deleteSuccess'))
|
||||
handleQuery()
|
||||
}else{
|
||||
ElMessage.error(response?.msg || response?.message || '删除失败')
|
||||
ElMessage.error(response?.msg || response?.message || t('maintain.checkProject.packageMgmt.deleteFailed'))
|
||||
}
|
||||
}catch(error){
|
||||
console.error('删除失败:',error)
|
||||
const errorMsg = error?.response?.data?.msg || error?.message || ''
|
||||
if(errorMsg.includes('foreign key') || errorMsg.includes('violates foreign key')){
|
||||
ElMessage.warning('该套餐已被使用,无法删除')
|
||||
ElMessage.warning(t('maintain.checkProject.packageMgmt.packageInUse'))
|
||||
}else{
|
||||
ElMessage.error('删除失败:'+(error.message || '未知错误'))
|
||||
ElMessage.error(t('maintain.checkProject.packageMgmt.deleteFailed') + ':' + (error.message || '未知错误'))
|
||||
}
|
||||
}
|
||||
}).catch(() => {})
|
||||
@@ -648,7 +651,7 @@ function getDeptName(deptValue) {
|
||||
// 无法匹配时,返回原始编码值
|
||||
const isOldFormat = /^[A-Z]\d{2}$/.test(trimmedValue)
|
||||
if (isOldFormat) {
|
||||
return trimmedValue + ' (旧格式)'
|
||||
return trimmedValue + t('maintain.checkProject.packageMgmt.oldFormatSuffix')
|
||||
}
|
||||
|
||||
return trimmedValue
|
||||
@@ -687,7 +690,7 @@ async function handleQuery() {
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('查询失败:', error)
|
||||
ElMessage.error('查询失败: ' + (error.message || '未知错误'))
|
||||
ElMessage.error(t('maintain.checkProject.packageMgmt.queryFailed') + ': ' + (error.message || '未知错误'))
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
@@ -721,11 +724,11 @@ async function handleEdit(row) {
|
||||
if (response && (response.code === 200 || response.code === 0) && response.data) {
|
||||
emit('switch-to-settings', { mode: 'edit', data: response.data })
|
||||
} else {
|
||||
ElMessage.error('加载套餐数据失败')
|
||||
ElMessage.error(t('maintain.checkProject.packageMgmt.loadFailed'))
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载套餐数据失败:', error)
|
||||
ElMessage.error('数据加载失败,请重试')
|
||||
ElMessage.error(t('maintain.checkProject.packageMgmt.loadFailedRetry'))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -737,11 +740,11 @@ async function handleView(row) {
|
||||
if (response && (response.code === 200 || response.code === 0) && response.data) {
|
||||
emit('switch-to-settings', { mode: 'view', data: response.data })
|
||||
} else {
|
||||
ElMessage.error('加载套餐数据失败')
|
||||
ElMessage.error(t('maintain.checkProject.packageMgmt.loadFailed'))
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载套餐数据失败:', error)
|
||||
ElMessage.error('数据加载失败,请重试')
|
||||
ElMessage.error(t('maintain.checkProject.packageMgmt.loadFailedRetry'))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -933,4 +936,3 @@ async function handleView(row) {
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
type="primary"
|
||||
@click="handlePackageManagement"
|
||||
>
|
||||
套餐管理
|
||||
{{ $t('maintain.checkProject.packageSettings.btn.packageManagement') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="!isReadOnly"
|
||||
@@ -14,21 +14,21 @@
|
||||
:loading="loading"
|
||||
@click="handleRefresh"
|
||||
>
|
||||
刷新
|
||||
{{ $t('maintain.checkProject.packageSettings.btn.refresh') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="!isReadOnly"
|
||||
type="success"
|
||||
@click="handleSave"
|
||||
>
|
||||
保存
|
||||
{{ $t('maintain.checkProject.packageSettings.btn.save') }}
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 基本信息表单区 -->
|
||||
<div class="basic-info-section">
|
||||
<h3 class="section-title">
|
||||
基本信息
|
||||
{{ $t('maintain.checkProject.packageSettings.section.basicInfo') }}
|
||||
</h3>
|
||||
<el-form
|
||||
ref="basicFormRef"
|
||||
@@ -45,12 +45,12 @@
|
||||
:lg="6"
|
||||
>
|
||||
<el-form-item
|
||||
label="套餐类别"
|
||||
:label="$t('maintain.checkProject.packageSettings.form.packageType')"
|
||||
prop="packageType"
|
||||
>
|
||||
<el-select
|
||||
v-model="formData.packageType"
|
||||
placeholder="请选择套餐类别"
|
||||
:placeholder="$t('maintain.checkProject.packageSettings.placeholder.selectPackageType')"
|
||||
style="width: 100%"
|
||||
:disabled="isReadOnly"
|
||||
>
|
||||
@@ -69,12 +69,12 @@
|
||||
:lg="6"
|
||||
>
|
||||
<el-form-item
|
||||
label="套餐级别"
|
||||
:label="$t('maintain.checkProject.packageSettings.form.packageLevel')"
|
||||
prop="packageLevel"
|
||||
>
|
||||
<el-select
|
||||
v-model="formData.packageLevel"
|
||||
placeholder="请选择套餐级别"
|
||||
:placeholder="$t('maintain.checkProject.packageSettings.placeholder.selectPackageLevel')"
|
||||
style="width: 100%"
|
||||
:disabled="isReadOnly"
|
||||
@change="handlePackageLevelChange"
|
||||
@@ -97,12 +97,12 @@
|
||||
:lg="6"
|
||||
>
|
||||
<el-form-item
|
||||
label="科室选择"
|
||||
:label="$t('maintain.checkProject.packageSettings.form.department')"
|
||||
prop="department"
|
||||
>
|
||||
<el-select
|
||||
v-model="formData.department"
|
||||
placeholder="请选择科室"
|
||||
:placeholder="$t('maintain.checkProject.packageSettings.placeholder.selectDepartment')"
|
||||
style="width: 100%"
|
||||
:disabled="isReadOnly"
|
||||
>
|
||||
@@ -124,12 +124,12 @@
|
||||
:lg="6"
|
||||
>
|
||||
<el-form-item
|
||||
label="用户选择"
|
||||
:label="$t('maintain.checkProject.packageSettings.form.user')"
|
||||
prop="user"
|
||||
>
|
||||
<el-select
|
||||
v-model="formData.user"
|
||||
placeholder="请选择用户"
|
||||
:placeholder="$t('maintain.checkProject.packageSettings.placeholder.selectUser')"
|
||||
style="width: 100%"
|
||||
:disabled="isReadOnly"
|
||||
>
|
||||
@@ -148,12 +148,12 @@
|
||||
:lg="6"
|
||||
>
|
||||
<el-form-item
|
||||
label="套餐名称"
|
||||
:label="$t('maintain.checkProject.packageSettings.form.packageName')"
|
||||
prop="packageName"
|
||||
>
|
||||
<el-input
|
||||
v-model="formData.packageName"
|
||||
placeholder="请输入套餐名称"
|
||||
:placeholder="$t('maintain.checkProject.packageSettings.placeholder.inputPackageName')"
|
||||
:disabled="isReadOnly"
|
||||
/>
|
||||
</el-form-item>
|
||||
@@ -165,10 +165,10 @@
|
||||
:md="8"
|
||||
:lg="6"
|
||||
>
|
||||
<el-form-item label="卫生机构">
|
||||
<el-form-item :label="$t('maintain.checkProject.packageSettings.form.organization')">
|
||||
<el-select
|
||||
v-model="formData.organization"
|
||||
placeholder="请选择卫生机构"
|
||||
:placeholder="$t('maintain.checkProject.packageSettings.placeholder.selectOrganization')"
|
||||
style="width: 100%"
|
||||
:disabled="isReadOnly"
|
||||
>
|
||||
@@ -188,11 +188,11 @@
|
||||
:md="8"
|
||||
:lg="6"
|
||||
>
|
||||
<el-form-item label="套餐金额">
|
||||
<el-form-item :label="$t('maintain.checkProject.packageSettings.form.packagePrice')">
|
||||
<el-input
|
||||
v-model="packagePriceDisplay"
|
||||
:disabled="true"
|
||||
placeholder="自动计算"
|
||||
:placeholder="$t('maintain.checkProject.packageSettings.placeholder.autoCalculate')"
|
||||
>
|
||||
<template #append>
|
||||
元
|
||||
@@ -207,10 +207,10 @@
|
||||
:md="8"
|
||||
:lg="6"
|
||||
>
|
||||
<el-form-item label="折扣">
|
||||
<el-form-item :label="$t('maintain.checkProject.packageSettings.form.discount')">
|
||||
<el-input
|
||||
v-model="formData.discount"
|
||||
placeholder="请输入折扣"
|
||||
:placeholder="$t('maintain.checkProject.packageSettings.placeholder.inputDiscount')"
|
||||
:disabled="isReadOnly"
|
||||
@input="handleDiscountChange"
|
||||
>
|
||||
@@ -227,7 +227,7 @@
|
||||
:md="8"
|
||||
:lg="6"
|
||||
>
|
||||
<el-form-item label="制单人">
|
||||
<el-form-item :label="$t('maintain.checkProject.packageSettings.form.creator')">
|
||||
<el-input
|
||||
v-model="formData.creator"
|
||||
:disabled="true"
|
||||
@@ -241,16 +241,16 @@
|
||||
:md="8"
|
||||
:lg="6"
|
||||
>
|
||||
<el-form-item label="是否停用">
|
||||
<el-form-item :label="$t('maintain.checkProject.packageSettings.form.isDisabled')">
|
||||
<el-radio-group
|
||||
v-model="formData.isDisabled"
|
||||
:disabled="isReadOnly"
|
||||
>
|
||||
<el-radio :value="0">
|
||||
启用
|
||||
{{ $t('maintain.checkProject.packageSettings.radio.enabled') }}
|
||||
</el-radio>
|
||||
<el-radio :value="1">
|
||||
停用
|
||||
{{ $t('maintain.checkProject.packageSettings.radio.disabled') }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
@@ -262,16 +262,16 @@
|
||||
:md="8"
|
||||
:lg="6"
|
||||
>
|
||||
<el-form-item label="显示套餐名">
|
||||
<el-form-item :label="$t('maintain.checkProject.packageSettings.form.showPackageName')">
|
||||
<el-radio-group
|
||||
v-model="formData.showPackageName"
|
||||
:disabled="isReadOnly"
|
||||
>
|
||||
<el-radio :value="1">
|
||||
是
|
||||
{{ $t('maintain.checkProject.packageSettings.radio.yes') }}
|
||||
</el-radio>
|
||||
<el-radio :value="0">
|
||||
否
|
||||
{{ $t('maintain.checkProject.packageSettings.radio.no') }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
@@ -283,16 +283,16 @@
|
||||
:md="8"
|
||||
:lg="6"
|
||||
>
|
||||
<el-form-item label="生成服务费">
|
||||
<el-form-item :label="$t('maintain.checkProject.packageSettings.form.generateServiceFee')">
|
||||
<el-radio-group
|
||||
v-model="formData.generateServiceFee"
|
||||
:disabled="isReadOnly"
|
||||
>
|
||||
<el-radio :value="1">
|
||||
是
|
||||
{{ $t('maintain.checkProject.packageSettings.radio.yes') }}
|
||||
</el-radio>
|
||||
<el-radio :value="0">
|
||||
否
|
||||
{{ $t('maintain.checkProject.packageSettings.radio.no') }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
@@ -304,16 +304,16 @@
|
||||
:md="8"
|
||||
:lg="6"
|
||||
>
|
||||
<el-form-item label="套餐价格">
|
||||
<el-form-item :label="$t('maintain.checkProject.packageSettings.form.packagePriceEnabled')">
|
||||
<el-radio-group
|
||||
v-model="formData.packagePriceEnabled"
|
||||
:disabled="isReadOnly"
|
||||
>
|
||||
<el-radio :value="1">
|
||||
启用
|
||||
{{ $t('maintain.checkProject.packageSettings.radio.enabled') }}
|
||||
</el-radio>
|
||||
<el-radio :value="0">
|
||||
不启用
|
||||
{{ $t('maintain.checkProject.packageSettings.radio.notEnabled') }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
@@ -325,12 +325,12 @@
|
||||
:md="8"
|
||||
:lg="6"
|
||||
>
|
||||
<el-form-item label="服务费">
|
||||
<el-form-item :label="$t('maintain.checkProject.packageSettings.form.serviceFee')">
|
||||
<el-input-number
|
||||
v-model="formData.serviceFee"
|
||||
:precision="2"
|
||||
:min="0"
|
||||
placeholder="自动合计"
|
||||
:placeholder="$t('maintain.checkProject.packageSettings.placeholder.autoSum')"
|
||||
style="width: 100%"
|
||||
disabled
|
||||
/>
|
||||
@@ -343,11 +343,11 @@
|
||||
:md="12"
|
||||
:lg="12"
|
||||
>
|
||||
<el-form-item label="备注">
|
||||
<el-form-item :label="$t('maintain.checkProject.packageSettings.form.remark')">
|
||||
<el-input
|
||||
v-model="formData.remark"
|
||||
type="textarea"
|
||||
placeholder="请输入备注"
|
||||
:placeholder="$t('maintain.checkProject.packageSettings.placeholder.inputRemark')"
|
||||
:disabled="isReadOnly"
|
||||
/>
|
||||
</el-form-item>
|
||||
@@ -359,7 +359,7 @@
|
||||
<!-- 套餐明细表格区 -->
|
||||
<div class="package-detail-section">
|
||||
<h3 class="section-title">
|
||||
套餐明细
|
||||
{{ $t('maintain.checkProject.packageSettings.section.packageDetail') }}
|
||||
</h3>
|
||||
<vxe-table
|
||||
:data="detailData"
|
||||
@@ -369,13 +369,13 @@
|
||||
>
|
||||
<vxe-column
|
||||
type="seq"
|
||||
title="序号"
|
||||
:title="$t('maintain.checkProject.packageSettings.table.seq')"
|
||||
width="60"
|
||||
align="center"
|
||||
/>
|
||||
<vxe-column
|
||||
field="code"
|
||||
title="编号"
|
||||
:title="$t('maintain.checkProject.packageSettings.table.code')"
|
||||
width="120"
|
||||
align="center"
|
||||
>
|
||||
@@ -383,21 +383,21 @@
|
||||
<el-input
|
||||
v-if="row.editing"
|
||||
v-model="row.code"
|
||||
placeholder="请输入编号"
|
||||
:placeholder="$t('maintain.checkProject.packageSettings.placeholder.inputCode')"
|
||||
/>
|
||||
<span v-else>{{ row.code }}</span>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column
|
||||
field="itemName"
|
||||
title="项目名称/规格"
|
||||
:title="$t('maintain.checkProject.packageSettings.table.itemNameSpec')"
|
||||
min-width="200"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<div v-if="row.editing">
|
||||
<el-select
|
||||
v-model="row.itemId"
|
||||
placeholder="输入名称/首字母/编号搜索"
|
||||
:placeholder="$t('maintain.checkProject.packageSettings.placeholder.searchItem')"
|
||||
filterable
|
||||
remote
|
||||
:remote-method="(query) => handleProjectSearch(query, row)"
|
||||
@@ -410,7 +410,7 @@
|
||||
<el-option
|
||||
v-for="item in (row.filteredList || diagnosisTreatmentList)"
|
||||
:key="item.id"
|
||||
:label="(item.name || item.itemName || '未命名') + (item.busNo ? ' [' + item.busNo + ']' : '')"
|
||||
:label="(item.name || item.itemName || $t('maintain.checkProject.packageSettings.table.unnamed')) + (item.busNo ? ' [' + item.busNo + ']' : '')"
|
||||
:value="item.id"
|
||||
>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; width: 100%;">
|
||||
@@ -424,12 +424,12 @@
|
||||
<template #empty>
|
||||
<div style="padding: 10px; text-align: center; color: #999;">
|
||||
<div v-if="diagnosisTreatmentList.length > 0">
|
||||
无匹配项目<br>
|
||||
<small>请尝试其他关键词</small>
|
||||
{{ $t('maintain.checkProject.packageSettings.table.noMatchItem') }}<br>
|
||||
<small>{{ $t('maintain.checkProject.packageSettings.table.tryOtherKeywords') }}</small>
|
||||
</div>
|
||||
<div v-else>
|
||||
暂无项目数据<br>
|
||||
<small>请先在【系统管理-目录管理-诊疗项目】中添加项目</small>
|
||||
{{ $t('maintain.checkProject.packageSettings.table.noItemData') }}<br>
|
||||
<small>{{ $t('maintain.checkProject.packageSettings.table.addProjectHint') }}</small>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -440,7 +440,7 @@
|
||||
</vxe-column>
|
||||
<vxe-column
|
||||
field="dose"
|
||||
title="剂量"
|
||||
:title="$t('maintain.checkProject.packageSettings.table.dose')"
|
||||
width="100"
|
||||
align="center"
|
||||
>
|
||||
@@ -456,7 +456,7 @@
|
||||
</vxe-column>
|
||||
<vxe-column
|
||||
field="method"
|
||||
title="途径"
|
||||
:title="$t('maintain.checkProject.packageSettings.table.method')"
|
||||
width="80"
|
||||
align="center"
|
||||
>
|
||||
@@ -471,7 +471,7 @@
|
||||
</vxe-column>
|
||||
<vxe-column
|
||||
field="frequency"
|
||||
title="频次"
|
||||
:title="$t('maintain.checkProject.packageSettings.table.frequency')"
|
||||
width="80"
|
||||
align="center"
|
||||
>
|
||||
@@ -486,7 +486,7 @@
|
||||
</vxe-column>
|
||||
<vxe-column
|
||||
field="days"
|
||||
title="天数"
|
||||
:title="$t('maintain.checkProject.packageSettings.table.days')"
|
||||
width="100"
|
||||
align="center"
|
||||
>
|
||||
@@ -502,7 +502,7 @@
|
||||
</vxe-column>
|
||||
<vxe-column
|
||||
field="quantity"
|
||||
title="数量"
|
||||
:title="$t('maintain.checkProject.packageSettings.table.quantity')"
|
||||
width="100"
|
||||
align="center"
|
||||
>
|
||||
@@ -512,7 +512,7 @@
|
||||
v-model="row.quantity"
|
||||
:min="0"
|
||||
:precision="0"
|
||||
placeholder="请输入数量"
|
||||
:placeholder="$t('maintain.checkProject.packageSettings.placeholder.inputQuantity')"
|
||||
style="width: 100%"
|
||||
:controls="false"
|
||||
@change="calculateAmount(row)"
|
||||
@@ -522,7 +522,7 @@
|
||||
</vxe-column>
|
||||
<vxe-column
|
||||
field="unit"
|
||||
title="单位"
|
||||
:title="$t('maintain.checkProject.packageSettings.table.unit')"
|
||||
width="80"
|
||||
align="center"
|
||||
>
|
||||
@@ -533,7 +533,7 @@
|
||||
</vxe-column>
|
||||
<vxe-column
|
||||
field="unitPrice"
|
||||
title="单价"
|
||||
:title="$t('maintain.checkProject.packageSettings.table.unitPrice')"
|
||||
width="150"
|
||||
align="center"
|
||||
>
|
||||
@@ -541,7 +541,7 @@
|
||||
<el-input
|
||||
v-if="row.editing"
|
||||
v-model="row.unitPrice"
|
||||
placeholder="自动获取"
|
||||
:placeholder="$t('maintain.checkProject.packageSettings.placeholder.autoFetch')"
|
||||
style="width: 100%"
|
||||
size="small"
|
||||
disabled
|
||||
@@ -551,7 +551,7 @@
|
||||
</vxe-column>
|
||||
<vxe-column
|
||||
field="amount"
|
||||
title="金额"
|
||||
:title="$t('maintain.checkProject.packageSettings.table.amount')"
|
||||
width="100"
|
||||
align="center"
|
||||
>
|
||||
@@ -561,7 +561,7 @@
|
||||
</vxe-column>
|
||||
<vxe-column
|
||||
field="serviceCharge"
|
||||
title="服务费"
|
||||
:title="$t('maintain.checkProject.packageSettings.table.serviceCharge')"
|
||||
width="100"
|
||||
align="center"
|
||||
>
|
||||
@@ -571,7 +571,7 @@
|
||||
v-model="row.serviceCharge"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
placeholder="服务费"
|
||||
:placeholder="$t('maintain.checkProject.packageSettings.form.serviceFee')"
|
||||
style="width: 100%"
|
||||
:controls="false"
|
||||
@input="(val) => handleServiceChargeInput(val, row)"
|
||||
@@ -581,7 +581,7 @@
|
||||
</vxe-column>
|
||||
<vxe-column
|
||||
field="total"
|
||||
title="总金额"
|
||||
:title="$t('maintain.checkProject.packageSettings.table.total')"
|
||||
width="100"
|
||||
align="center"
|
||||
>
|
||||
@@ -591,7 +591,7 @@
|
||||
</vxe-column>
|
||||
<vxe-column
|
||||
field="origin"
|
||||
title="产地"
|
||||
:title="$t('maintain.checkProject.packageSettings.table.origin')"
|
||||
width="120"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
@@ -605,7 +605,7 @@
|
||||
</vxe-column>
|
||||
<vxe-column
|
||||
v-if="!isReadOnly"
|
||||
title="操作"
|
||||
:title="$t('maintain.checkProject.packageSettings.table.actions')"
|
||||
width="150"
|
||||
align="center"
|
||||
fixed="right"
|
||||
@@ -617,7 +617,7 @@
|
||||
class="btn btn-edit"
|
||||
size="small"
|
||||
circle
|
||||
title="编辑"
|
||||
:title="$t('maintain.checkProject.packageSettings.table.edit')"
|
||||
@click="handleEditRow(row)"
|
||||
>
|
||||
✏️
|
||||
@@ -627,7 +627,7 @@
|
||||
class="btn btn-confirm"
|
||||
size="small"
|
||||
circle
|
||||
title="保存"
|
||||
:title="$t('maintain.checkProject.packageSettings.btn.save')"
|
||||
@click="handleConfirmRow(row)"
|
||||
>
|
||||
✓
|
||||
@@ -636,7 +636,7 @@
|
||||
class="btn btn-add"
|
||||
size="small"
|
||||
circle
|
||||
title="添加"
|
||||
:title="$t('maintain.checkProject.packageSettings.table.add')"
|
||||
@click="handleAddRow"
|
||||
>
|
||||
+
|
||||
@@ -645,7 +645,7 @@
|
||||
class="btn btn-delete"
|
||||
size="small"
|
||||
circle
|
||||
title="删除"
|
||||
:title="$t('maintain.checkProject.packageSettings.table.delete')"
|
||||
@click="handleDeleteRow(rowIndex)"
|
||||
>
|
||||
✕
|
||||
@@ -660,6 +660,7 @@
|
||||
|
||||
<script setup>
|
||||
import {computed, onMounted, reactive, ref, watch} from 'vue'
|
||||
import {useI18n} from 'vue-i18n'
|
||||
import {ElMessage, ElMessageBox} from 'element-plus'
|
||||
import {getDicts} from '@/api/system/dict/data'
|
||||
import {listDept} from '@/api/system/dept'
|
||||
@@ -670,6 +671,8 @@ import useUserStore from '@/store/modules/user'
|
||||
import request from '@/utils/request'
|
||||
import cache from '@/plugins/cache'
|
||||
|
||||
const {t} = useI18n()
|
||||
|
||||
// 接收props
|
||||
const props = defineProps({
|
||||
mode: {
|
||||
@@ -692,13 +695,13 @@ const userStore = useUserStore()
|
||||
const pageTitle = computed(() => {
|
||||
switch (props.mode) {
|
||||
case 'add':
|
||||
return '套餐设置'
|
||||
return t('maintain.checkProject.packageSettings.pageTitle.add')
|
||||
case 'edit':
|
||||
return '编辑套餐'
|
||||
return t('maintain.checkProject.packageSettings.pageTitle.edit')
|
||||
case 'view':
|
||||
return '查看套餐'
|
||||
return t('maintain.checkProject.packageSettings.pageTitle.view')
|
||||
default:
|
||||
return '套餐设置'
|
||||
return t('maintain.checkProject.packageSettings.pageTitle.add')
|
||||
}
|
||||
})
|
||||
|
||||
@@ -738,17 +741,26 @@ const packagePriceDisplay = computed({
|
||||
})
|
||||
|
||||
// 表单验证规则
|
||||
const formRules = {
|
||||
packageType: [
|
||||
{ required: true, message: '请选择套餐类别', trigger: 'change' }
|
||||
],
|
||||
packageLevel: [
|
||||
{ required: true, message: '请选择套餐级别', trigger: 'change' }
|
||||
],
|
||||
packageName: [
|
||||
{ required: true, message: '请输入套餐名称', trigger: 'blur', type: 'string' }
|
||||
]
|
||||
}
|
||||
const formRules = computed(() => {
|
||||
const rules = {
|
||||
packageType: [
|
||||
{ required: true, message: t('maintain.checkProject.packageSettings.validation.selectPackageType'), trigger: 'change' }
|
||||
],
|
||||
packageLevel: [
|
||||
{ required: true, message: t('maintain.checkProject.packageSettings.validation.selectPackageLevel'), trigger: 'change' }
|
||||
],
|
||||
packageName: [
|
||||
{ required: true, message: t('maintain.checkProject.packageSettings.validation.inputPackageName'), trigger: 'blur', type: 'string' }
|
||||
]
|
||||
}
|
||||
if (formData.packageLevel === '2') {
|
||||
rules.department = [{ required: true, message: t('maintain.checkProject.packageSettings.validation.selectDepartment'), trigger: 'change' }]
|
||||
}
|
||||
if (formData.packageLevel === '3') {
|
||||
rules.user = [{ required: true, message: t('maintain.checkProject.packageSettings.validation.selectUser'), trigger: 'change' }]
|
||||
}
|
||||
return rules
|
||||
})
|
||||
|
||||
// 套餐级别选项
|
||||
const packageLevelOptions = ref([])
|
||||
@@ -1130,15 +1142,15 @@ async function loadDiagnosisTreatmentList(forceRefresh = false) {
|
||||
|
||||
// 只在强制刷新时显示成功消息
|
||||
if (forceRefresh) {
|
||||
ElMessage.success(`成功加载${allItems.length}个诊疗项目`)
|
||||
ElMessage.success(t('maintain.checkProject.packageSettings.message.loadItemsSuccess', { count: allItems.length }))
|
||||
}
|
||||
} else if (forceRefresh) {
|
||||
ElMessage.warning('未获取到诊疗项目数据')
|
||||
ElMessage.warning(t('maintain.checkProject.packageSettings.message.noItemData'))
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取诊疗项目列表失败:', error)
|
||||
if (forceRefresh) {
|
||||
ElMessage.error('获取诊疗项目列表失败')
|
||||
ElMessage.error(t('maintain.checkProject.packageSettings.message.loadItemsFailed'))
|
||||
}
|
||||
} finally {
|
||||
loading.value = false
|
||||
@@ -1155,23 +1167,13 @@ function handlePackageLevelChange(value) {
|
||||
formData.user = ''
|
||||
}
|
||||
|
||||
// 动态更新验证规则
|
||||
if (value === '2') {
|
||||
// 科室套餐,科室必填
|
||||
formRules.department = [{ required: true, message: '请选择科室', trigger: 'change' }]
|
||||
formRules.user = []
|
||||
} else if (value === '3') {
|
||||
// 个人套餐,用户必填
|
||||
formRules.user = [{ required: true, message: '请选择用户', trigger: 'change' }]
|
||||
formRules.department = []
|
||||
// 自动获取当前登录账号名称赋值给用户选择字段
|
||||
// 动态验证规则已移至 formRules computed 中
|
||||
|
||||
if (value === '3') {
|
||||
// 个人套餐,自动获取当前登录账号名称赋值给用户选择字段
|
||||
if (!formData.user && userStore.name) {
|
||||
formData.user = userStore.name
|
||||
}
|
||||
} else {
|
||||
// 全院套餐,都不必填
|
||||
formRules.department = []
|
||||
formRules.user = []
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1206,11 +1208,11 @@ function handleEditRow(row) {
|
||||
// 确认编辑
|
||||
function handleConfirmRow(row) {
|
||||
if (!row.itemName) {
|
||||
ElMessage.warning('请选择项目')
|
||||
ElMessage.warning(t('maintain.checkProject.packageSettings.message.selectItem'))
|
||||
return
|
||||
}
|
||||
if (!row.quantity || row.quantity <= 0) {
|
||||
ElMessage.warning('请输入有效数量')
|
||||
ElMessage.warning(t('maintain.checkProject.packageSettings.message.inputValidQuantity'))
|
||||
return
|
||||
}
|
||||
row.editing = false
|
||||
@@ -1218,15 +1220,15 @@ function handleConfirmRow(row) {
|
||||
|
||||
// 删除行
|
||||
function handleDeleteRow(index) {
|
||||
ElMessageBox.confirm('确定要删除这一行吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
ElMessageBox.confirm(t('maintain.checkProject.packageSettings.message.confirmDelete'), t('maintain.checkProject.packageSettings.message.tip'), {
|
||||
confirmButtonText: t('maintain.checkProject.packageSettings.btn.confirm'),
|
||||
cancelButtonText: t('maintain.checkProject.packageSettings.btn.cancel'),
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
detailData.value.splice(index, 1)
|
||||
calculatePackagePrice()
|
||||
calculateTotalServiceFee()
|
||||
ElMessage.success('删除成功')
|
||||
ElMessage.success(t('maintain.checkProject.packageSettings.message.deleteSuccess'))
|
||||
}).catch(() => {})
|
||||
}
|
||||
|
||||
@@ -1348,7 +1350,7 @@ function handleItemSelect(row) {
|
||||
|
||||
calculateAmount(row)
|
||||
} else {
|
||||
ElMessage.warning('未找到该项目信息')
|
||||
ElMessage.warning(t('maintain.checkProject.packageSettings.message.itemNotFound'))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1404,8 +1406,7 @@ function handleDiscountChange(value) {
|
||||
// 验证折扣范围
|
||||
const discountValue = parseFloat(formData.discount)
|
||||
if (discountValue && (discountValue < 0 || discountValue > 100)) {
|
||||
ElMessage.warning('折扣必须在0-100之间')
|
||||
// 重置为有效值
|
||||
ElMessage.warning(t('maintain.checkProject.packageSettings.message.discountRange'))
|
||||
if (discountValue < 0) {
|
||||
formData.discount = '0'
|
||||
} else if (discountValue > 100) {
|
||||
@@ -1462,13 +1463,13 @@ async function handleSave() {
|
||||
console.log('✓ 基本信息验证通过')
|
||||
} catch (validationError) {
|
||||
console.error('✗ 表单验证失败:', validationError)
|
||||
ElMessage.error('请完善必填项:' + Object.keys(validationError).join(', '))
|
||||
ElMessage.error(t('maintain.checkProject.packageSettings.message.completeRequired') + Object.keys(validationError).join(', '))
|
||||
return
|
||||
}
|
||||
|
||||
// 验证明细数据
|
||||
if (detailData.value.length === 0) {
|
||||
ElMessage.warning('请至少添加一条套餐明细')
|
||||
ElMessage.warning(t('maintain.checkProject.packageSettings.message.addAtLeastOneItem'))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1477,7 +1478,7 @@ async function handleSave() {
|
||||
// 检查是否有未确认的编辑行
|
||||
const hasEditingRow = detailData.value.some(row => row.editing)
|
||||
if (hasEditingRow) {
|
||||
ElMessage.warning('请先确认所有正在编辑的行')
|
||||
ElMessage.warning(t('maintain.checkProject.packageSettings.message.confirmAllEditingRows'))
|
||||
return
|
||||
}
|
||||
console.log('✓ 所有行已确认')
|
||||
@@ -1486,7 +1487,7 @@ async function handleSave() {
|
||||
const hasEmptyItem = detailData.value.some(row => !row.itemName || !row.quantity)
|
||||
if (hasEmptyItem) {
|
||||
console.error('✗ 存在空项目:', detailData.value.filter(row => !row.itemName || !row.quantity))
|
||||
ElMessage.warning('请完善所有明细项目信息(项目名称和数量为必填项)')
|
||||
ElMessage.warning(t('maintain.checkProject.packageSettings.message.completeAllDetailItems'))
|
||||
return
|
||||
}
|
||||
console.log('✓ 明细数据完整性验证通过')
|
||||
@@ -1496,7 +1497,7 @@ async function handleSave() {
|
||||
|
||||
// 验证折扣范围
|
||||
if (formData.discount && (parseFloat(formData.discount) < 0 || parseFloat(formData.discount) > 100)) {
|
||||
ElMessage.warning('折扣必须在0-100之间')
|
||||
ElMessage.warning(t('maintain.checkProject.packageSettings.message.discountRange'))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1564,7 +1565,7 @@ async function handleSave() {
|
||||
console.log('API响应:', response)
|
||||
|
||||
if (response && (response.code === 200 || response.code === 0)) {
|
||||
ElMessage.success('套餐数据已保存')
|
||||
ElMessage.success(t('maintain.checkProject.packageSettings.message.saveSuccess'))
|
||||
emit('save-success')
|
||||
// 如果有返回ID,更新formData.id以便后续更新
|
||||
if (response.data && !formData.id) {
|
||||
@@ -1573,7 +1574,7 @@ async function handleSave() {
|
||||
}
|
||||
} else {
|
||||
console.error('保存失败,响应:', response)
|
||||
ElMessage.error(response?.msg || response?.message || '保存失败,请检查表单数据')
|
||||
ElMessage.error(response?.msg || response?.message || t('maintain.checkProject.packageSettings.message.saveFailed'))
|
||||
}
|
||||
} catch (apiError) {
|
||||
console.error('API调用失败:', apiError)
|
||||
@@ -1582,8 +1583,8 @@ async function handleSave() {
|
||||
} catch (error) {
|
||||
console.error('保存过程出错:', error)
|
||||
if (error !== 'cancel') {
|
||||
const errorMsg = error.response?.data?.msg || error.message || '保存失败,请检查表单数据'
|
||||
ElMessage.error('保存失败: ' + errorMsg)
|
||||
const errorMsg = error.response?.data?.msg || error.message || t('maintain.checkProject.packageSettings.message.saveFailed')
|
||||
ElMessage.error(t('maintain.checkProject.packageSettings.message.saveFailedWithError') + errorMsg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<!-- 左侧导航栏 -->
|
||||
<div class="sidebar">
|
||||
<div class="sidebar-header">
|
||||
<h3>检查项目管理</h3>
|
||||
<h3>{{ $t('maintain.checkProject.title') }}</h3>
|
||||
</div>
|
||||
<div class="sidebar-menu">
|
||||
<!-- 明确列出所有导航项 -->
|
||||
@@ -12,28 +12,28 @@
|
||||
@click="handleMenuClick('检查类型')"
|
||||
>
|
||||
<span class="menu-icon">📋</span>
|
||||
<span class="menu-text">检查类型</span>
|
||||
<span class="menu-text">{{ $t('maintain.checkProject.menu.checkType') }}</span>
|
||||
</button>
|
||||
<button
|
||||
class="menu-item"
|
||||
@click="handleMenuClick('检查方法')"
|
||||
>
|
||||
<span class="menu-icon">🔬</span>
|
||||
<span class="menu-text">检查方法</span>
|
||||
<span class="menu-text">{{ $t('maintain.checkProject.menu.checkMethod') }}</span>
|
||||
</button>
|
||||
<button
|
||||
class="menu-item"
|
||||
@click="handleMenuClick('检查部位')"
|
||||
>
|
||||
<span class="menu-icon">🎯</span>
|
||||
<span class="menu-text">检查部位</span>
|
||||
<span class="menu-text">{{ $t('maintain.checkProject.menu.checkPart') }}</span>
|
||||
</button>
|
||||
<button
|
||||
class="menu-item"
|
||||
@click="handleMenuClick('套餐设置')"
|
||||
>
|
||||
<span class="menu-icon">📦</span>
|
||||
<span class="menu-text">套餐设置</span>
|
||||
<span class="menu-text">{{ $t('maintain.checkProject.menu.packageSettings') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -60,7 +60,7 @@
|
||||
<!-- 检查类型的表格视图 -->
|
||||
<template v-if="activeMenu === '检查类型'">
|
||||
<div class="header">
|
||||
<h1>{{ activeMenu }}管理</h1>
|
||||
<h1>{{ $t('maintain.checkProject.menuManage', { menu: $t('maintain.checkProject.menu.' + menuKeyMap[activeMenu]) }) }}</h1>
|
||||
<div class="header-actions">
|
||||
<button
|
||||
class="btn btn-add-new"
|
||||
@@ -77,31 +77,31 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 50px;">
|
||||
行
|
||||
{{ $t('maintain.checkProject.table.row') }}
|
||||
</th>
|
||||
<th style="width: 100px;">
|
||||
*编码
|
||||
{{ $t('maintain.checkProject.table.codeRequired') }}
|
||||
</th>
|
||||
<th style="width: 150px;">
|
||||
*名称
|
||||
{{ $t('maintain.checkProject.table.nameRequired') }}
|
||||
</th>
|
||||
<th style="width: 150px;">
|
||||
*检查类型
|
||||
{{ $t('maintain.checkProject.table.checkTypeRequired') }}
|
||||
</th>
|
||||
<th style="width: 120px;">
|
||||
选择部位
|
||||
{{ $t('maintain.checkProject.table.selectPart') }}
|
||||
</th>
|
||||
<th style="width: 150px;">
|
||||
*执行科室
|
||||
{{ $t('maintain.checkProject.table.departmentRequired') }}
|
||||
</th>
|
||||
<th style="width: 100px;">
|
||||
序号
|
||||
{{ $t('maintain.checkProject.table.orderNum') }}
|
||||
</th>
|
||||
<th style="width: 150px;">
|
||||
备注
|
||||
{{ $t('maintain.checkProject.table.remark') }}
|
||||
</th>
|
||||
<th style="width: 120px;">
|
||||
操作
|
||||
{{ $t('maintain.checkProject.table.actions') }}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -118,7 +118,7 @@
|
||||
<input
|
||||
v-model="item.code"
|
||||
type="text"
|
||||
placeholder="请输入编码"
|
||||
:placeholder="$t('maintain.checkProject.placeholder.enterCode')"
|
||||
>
|
||||
</template>
|
||||
<template v-else>
|
||||
@@ -130,7 +130,7 @@
|
||||
<input
|
||||
v-model="item.name"
|
||||
type="text"
|
||||
placeholder="请输入名称"
|
||||
:placeholder="$t('maintain.checkProject.placeholder.enterName')"
|
||||
>
|
||||
</template>
|
||||
<template v-else>
|
||||
@@ -144,7 +144,7 @@
|
||||
:class="{ 'placeholder-text': !item.type }"
|
||||
>
|
||||
<option value="">
|
||||
选择检查类型
|
||||
{{ $t('maintain.checkProject.placeholder.selectCheckType') }}
|
||||
</option>
|
||||
<option
|
||||
v-for="opt in checkTypeOptions"
|
||||
@@ -160,7 +160,7 @@
|
||||
<span
|
||||
v-else
|
||||
class="placeholder-text"
|
||||
>选择检查类型</span>
|
||||
>{{ $t('maintain.checkProject.placeholder.selectCheckType') }}</span>
|
||||
</template>
|
||||
</td>
|
||||
<td class="checkbox-container">
|
||||
@@ -177,7 +177,7 @@
|
||||
:class="{ 'placeholder-text': !item.department }"
|
||||
>
|
||||
<option value="">
|
||||
选择执行科室
|
||||
{{ $t('maintain.checkProject.placeholder.selectDepartment') }}
|
||||
</option>
|
||||
<option
|
||||
v-if="item.department"
|
||||
@@ -199,7 +199,7 @@
|
||||
<span
|
||||
v-else
|
||||
class="placeholder-text"
|
||||
>选择执行科室</span>
|
||||
>{{ $t('maintain.checkProject.placeholder.selectDepartment') }}</span>
|
||||
</template>
|
||||
</td>
|
||||
<td>
|
||||
@@ -218,7 +218,7 @@
|
||||
<input
|
||||
v-model="item.remark"
|
||||
type="text"
|
||||
placeholder="请输入备注"
|
||||
:placeholder="$t('maintain.checkProject.placeholder.enterRemark')"
|
||||
>
|
||||
</template>
|
||||
<template v-else>
|
||||
@@ -229,14 +229,14 @@
|
||||
<template v-if="item.editing">
|
||||
<button
|
||||
class="btn btn-confirm"
|
||||
title="保存"
|
||||
:title="$t('maintain.checkProject.action.save')"
|
||||
@click.stop="handleConfirm(index)"
|
||||
>
|
||||
✓
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-cancel"
|
||||
title="取消"
|
||||
:title="$t('maintain.checkProject.action.cancel')"
|
||||
@click.stop="handleCancelEdit(index)"
|
||||
>
|
||||
✕
|
||||
@@ -244,7 +244,7 @@
|
||||
<button
|
||||
v-if="!item.parentId"
|
||||
class="btn btn-add"
|
||||
title="添加子项"
|
||||
:title="$t('maintain.checkProject.action.addChild')"
|
||||
@click.stop="handleAdd(index)"
|
||||
>
|
||||
+
|
||||
@@ -253,7 +253,7 @@
|
||||
<template v-else>
|
||||
<button
|
||||
class="btn btn-edit"
|
||||
title="修改"
|
||||
:title="$t('maintain.checkProject.action.edit')"
|
||||
@click.stop="handleEdit(index)"
|
||||
>
|
||||
✏️
|
||||
@@ -261,14 +261,14 @@
|
||||
<button
|
||||
v-if="!item.parentId"
|
||||
class="btn btn-add"
|
||||
title="添加子项"
|
||||
:title="$t('maintain.checkProject.action.addChild')"
|
||||
@click.stop="handleAdd(index)"
|
||||
>
|
||||
+
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-delete"
|
||||
title="删除"
|
||||
:title="$t('maintain.checkProject.action.delete')"
|
||||
@click.stop="handleDelete(index)"
|
||||
>
|
||||
✕
|
||||
@@ -284,15 +284,15 @@
|
||||
<!-- 检查方法的表格视图 -->
|
||||
<template v-else-if="activeMenu === '检查方法'">
|
||||
<div class="header">
|
||||
<h1>{{ activeMenu }}管理</h1>
|
||||
<h1>{{ $t('maintain.checkProject.menuManage', { menu: $t('maintain.checkProject.menu.' + menuKeyMap[activeMenu]) }) }}</h1>
|
||||
</div>
|
||||
<div class="search-bar search-bar-method">
|
||||
<div class="search-filters">
|
||||
<div class="search-item">
|
||||
<label>检查类型</label>
|
||||
<label>{{ $t('maintain.checkProject.label.checkType') }}</label>
|
||||
<el-select
|
||||
v-model="searchParamsMethod.checkType"
|
||||
placeholder="选择检查类型"
|
||||
:placeholder="$t('maintain.checkProject.placeholder.selectCheckType')"
|
||||
style="width: 150px"
|
||||
>
|
||||
<el-option
|
||||
@@ -304,17 +304,17 @@
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="search-item">
|
||||
<label>名称</label>
|
||||
<label>{{ $t('maintain.checkProject.label.name') }}</label>
|
||||
<el-input
|
||||
v-model="searchParamsMethod.name"
|
||||
placeholder="名称/编码"
|
||||
:placeholder="$t('maintain.checkProject.placeholder.nameOrCode')"
|
||||
/>
|
||||
</div>
|
||||
<div class="search-item">
|
||||
<label>费用套餐</label>
|
||||
<label>{{ $t('maintain.checkProject.label.package') }}</label>
|
||||
<el-select
|
||||
v-model="searchParamsMethod.packageName"
|
||||
placeholder="选择使用套餐"
|
||||
:placeholder="$t('maintain.checkProject.placeholder.selectPackage')"
|
||||
style="width: 150px"
|
||||
filterable
|
||||
clearable
|
||||
@@ -335,25 +335,25 @@
|
||||
@mouseleave="hoverAddButton = false"
|
||||
@click="handleAddNewRow"
|
||||
>
|
||||
新增
|
||||
{{ $t('maintain.checkProject.button.add') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleSearch"
|
||||
>
|
||||
查询
|
||||
{{ $t('maintain.checkProject.button.search') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleReset"
|
||||
>
|
||||
重置
|
||||
{{ $t('maintain.checkProject.button.reset') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
@click="handleExport"
|
||||
>
|
||||
导出表格
|
||||
{{ $t('maintain.checkProject.button.export') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -363,31 +363,31 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 50px;">
|
||||
行
|
||||
{{ $t('maintain.checkProject.table.row') }}
|
||||
</th>
|
||||
<th style="width: 100px;">
|
||||
代码
|
||||
{{ $t('maintain.checkProject.table.code') }}
|
||||
</th>
|
||||
<th style="width: 150px;">
|
||||
名称
|
||||
{{ $t('maintain.checkProject.table.name') }}
|
||||
</th>
|
||||
<th style="width: 150px;">
|
||||
检查类型
|
||||
{{ $t('maintain.checkProject.table.checkType') }}
|
||||
</th>
|
||||
<th style="width: 150px;">
|
||||
套餐名称
|
||||
{{ $t('maintain.checkProject.table.packageName') }}
|
||||
</th>
|
||||
<th style="width: 100px;">
|
||||
曝光次数
|
||||
{{ $t('maintain.checkProject.table.exposureNum') }}
|
||||
</th>
|
||||
<th style="width: 100px;">
|
||||
序号
|
||||
{{ $t('maintain.checkProject.table.orderNum') }}
|
||||
</th>
|
||||
<th style="width: 150px;">
|
||||
备注
|
||||
{{ $t('maintain.checkProject.table.remark') }}
|
||||
</th>
|
||||
<th style="width: 120px;">
|
||||
操作
|
||||
{{ $t('maintain.checkProject.table.actions') }}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -404,7 +404,7 @@
|
||||
<input
|
||||
v-model="item.code"
|
||||
type="text"
|
||||
placeholder="请输入编码"
|
||||
:placeholder="$t('maintain.checkProject.placeholder.enterCode')"
|
||||
>
|
||||
</template>
|
||||
<template v-else>
|
||||
@@ -416,7 +416,7 @@
|
||||
<input
|
||||
v-model="item.name"
|
||||
type="text"
|
||||
placeholder="请输入方法名称"
|
||||
:placeholder="$t('maintain.checkProject.placeholder.enterMethodName')"
|
||||
>
|
||||
</template>
|
||||
<template v-else>
|
||||
@@ -427,7 +427,7 @@
|
||||
<template v-if="item.editing">
|
||||
<el-select
|
||||
v-model="item.checkType"
|
||||
placeholder="选择检查类型"
|
||||
:placeholder="$t('maintain.checkProject.placeholder.selectCheckType')"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
@@ -439,7 +439,7 @@
|
||||
</el-select>
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ getCheckTypeLabelForMethodPart(item.checkType) || '无' }}
|
||||
{{ getCheckTypeLabelForMethodPart(item.checkType) || $t('maintain.checkProject.text.none') }}
|
||||
</template>
|
||||
</td>
|
||||
|
||||
@@ -447,7 +447,7 @@
|
||||
<template v-if="item.editing">
|
||||
<el-select
|
||||
v-model="item.packageName"
|
||||
placeholder="请选择套餐"
|
||||
:placeholder="$t('maintain.checkProject.placeholder.selectPackage')"
|
||||
style="width: 100%"
|
||||
filterable
|
||||
clearable
|
||||
@@ -493,7 +493,7 @@
|
||||
<input
|
||||
v-model="item.remark"
|
||||
type="text"
|
||||
placeholder="请输入备注"
|
||||
:placeholder="$t('maintain.checkProject.placeholder.enterRemark')"
|
||||
>
|
||||
</template>
|
||||
<template v-else>
|
||||
@@ -504,14 +504,14 @@
|
||||
<template v-if="item.editing">
|
||||
<button
|
||||
class="btn btn-confirm"
|
||||
title="保存"
|
||||
:title="$t('maintain.checkProject.action.save')"
|
||||
@click.stop="handleConfirm(index)"
|
||||
>
|
||||
✓
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-cancel"
|
||||
title="取消"
|
||||
:title="$t('maintain.checkProject.action.cancel')"
|
||||
@click.stop="handleCancelEdit(index)"
|
||||
>
|
||||
✕
|
||||
@@ -520,21 +520,21 @@
|
||||
<template v-else>
|
||||
<button
|
||||
class="btn btn-edit"
|
||||
title="编辑"
|
||||
:title="$t('maintain.checkProject.action.edit')"
|
||||
@click.stop="handleEdit(index)"
|
||||
>
|
||||
✏️
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-confirm"
|
||||
title="保存"
|
||||
:title="$t('maintain.checkProject.action.save')"
|
||||
@click.stop="handleConfirm(index)"
|
||||
>
|
||||
✓
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-delete"
|
||||
title="删除"
|
||||
:title="$t('maintain.checkProject.action.delete')"
|
||||
@click.stop="handleDelete(index)"
|
||||
>
|
||||
✕
|
||||
@@ -550,14 +550,14 @@
|
||||
<!-- 检查部位的表格视图 -->
|
||||
<template v-else-if="activeMenu === '检查部位'">
|
||||
<div class="header">
|
||||
<h1>{{ activeMenu }}管理</h1>
|
||||
<h1>{{ $t('maintain.checkProject.menuManage', { menu: $t('maintain.checkProject.menu.' + menuKeyMap[activeMenu]) }) }}</h1>
|
||||
</div>
|
||||
<div class="search-bar search-bar-part">
|
||||
<div class="search-item">
|
||||
<label>检查类型</label>
|
||||
<label>{{ $t('maintain.checkProject.label.checkType') }}</label>
|
||||
<el-select
|
||||
v-model="searchParamsPart.checkType"
|
||||
placeholder="选择检查类型"
|
||||
:placeholder="$t('maintain.checkProject.placeholder.selectCheckType')"
|
||||
style="width: 150px"
|
||||
>
|
||||
<el-option
|
||||
@@ -569,17 +569,17 @@
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="search-item">
|
||||
<label>名称</label>
|
||||
<label>{{ $t('maintain.checkProject.label.name') }}</label>
|
||||
<el-input
|
||||
v-model="searchParamsPart.name"
|
||||
placeholder="名称/编码"
|
||||
:placeholder="$t('maintain.checkProject.placeholder.nameOrCode')"
|
||||
/>
|
||||
</div>
|
||||
<div class="search-item">
|
||||
<label>费用套餐</label>
|
||||
<label>{{ $t('maintain.checkProject.label.package') }}</label>
|
||||
<el-select
|
||||
v-model="searchParamsPart.packageName"
|
||||
placeholder="选择套餐"
|
||||
:placeholder="$t('maintain.checkProject.placeholder.selectPackage')"
|
||||
style="width: 150px"
|
||||
filterable
|
||||
clearable
|
||||
@@ -599,25 +599,25 @@
|
||||
type="primary"
|
||||
@click="handleAddNewRow"
|
||||
>
|
||||
新增
|
||||
{{ $t('maintain.checkProject.button.add') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleSearch"
|
||||
>
|
||||
查询
|
||||
{{ $t('maintain.checkProject.button.search') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleReset"
|
||||
>
|
||||
重置
|
||||
{{ $t('maintain.checkProject.button.reset') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
@click="handleExport"
|
||||
>
|
||||
导出表格
|
||||
{{ $t('maintain.checkProject.button.export') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -627,40 +627,40 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 50px;">
|
||||
行
|
||||
{{ $t('maintain.checkProject.table.row') }}
|
||||
</th>
|
||||
<th style="width: 100px;">
|
||||
*编码
|
||||
{{ $t('maintain.checkProject.table.codeRequired') }}
|
||||
</th>
|
||||
<th style="width: 100px;">
|
||||
*名称
|
||||
{{ $t('maintain.checkProject.table.nameRequired') }}
|
||||
</th>
|
||||
<th style="width: 120px;">
|
||||
检查类型
|
||||
{{ $t('maintain.checkProject.table.checkType') }}
|
||||
</th>
|
||||
<th style="width: 80px;">
|
||||
曝光次数
|
||||
{{ $t('maintain.checkProject.table.exposureNum') }}
|
||||
</th>
|
||||
<th style="width: 120px;">
|
||||
费用套餐
|
||||
{{ $t('maintain.checkProject.table.package') }}
|
||||
</th>
|
||||
<th style="width: 100px;">
|
||||
金额
|
||||
{{ $t('maintain.checkProject.table.price') }}
|
||||
</th>
|
||||
<th style="width: 100px;">
|
||||
序号
|
||||
{{ $t('maintain.checkProject.table.orderNum') }}
|
||||
</th>
|
||||
<th style="width: 120px;">
|
||||
服务范围
|
||||
{{ $t('maintain.checkProject.table.serviceScope') }}
|
||||
</th>
|
||||
<th style="width: 120px;">
|
||||
下级医技类型
|
||||
{{ $t('maintain.checkProject.table.subType') }}
|
||||
</th>
|
||||
<th style="width: 150px;">
|
||||
备注
|
||||
{{ $t('maintain.checkProject.table.remark') }}
|
||||
</th>
|
||||
<th style="width: 120px;">
|
||||
操作
|
||||
{{ $t('maintain.checkProject.table.actions') }}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -677,7 +677,7 @@
|
||||
<input
|
||||
v-model="item.code"
|
||||
type="text"
|
||||
placeholder="请输入编码"
|
||||
:placeholder="$t('maintain.checkProject.placeholder.enterCode')"
|
||||
>
|
||||
</template>
|
||||
<template v-else>
|
||||
@@ -689,7 +689,7 @@
|
||||
<input
|
||||
v-model="item.name"
|
||||
type="text"
|
||||
placeholder="请输入名称"
|
||||
:placeholder="$t('maintain.checkProject.placeholder.enterName')"
|
||||
>
|
||||
</template>
|
||||
<template v-else>
|
||||
@@ -700,7 +700,7 @@
|
||||
<template v-if="item.editing">
|
||||
<el-select
|
||||
v-model="item.checkType"
|
||||
placeholder="选择检查类型"
|
||||
:placeholder="$t('maintain.checkProject.placeholder.selectCheckType')"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
@@ -712,7 +712,7 @@
|
||||
</el-select>
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ getCheckTypeLabelForMethodPart(item.checkType) || '无' }}
|
||||
{{ getCheckTypeLabelForMethodPart(item.checkType) || $t('maintain.checkProject.text.none') }}
|
||||
</template>
|
||||
</td>
|
||||
<td>
|
||||
@@ -721,7 +721,7 @@
|
||||
v-model="item.exposureNum"
|
||||
type="number"
|
||||
min="0"
|
||||
placeholder="请输入曝光次数"
|
||||
:placeholder="$t('maintain.checkProject.placeholder.enterExposureNum')"
|
||||
>
|
||||
</template>
|
||||
<template v-else>
|
||||
@@ -732,7 +732,7 @@
|
||||
<template v-if="item.editing">
|
||||
<el-select
|
||||
v-model="item.packageName"
|
||||
placeholder="请选择套餐"
|
||||
:placeholder="$t('maintain.checkProject.placeholder.selectPackage')"
|
||||
style="width: 100%"
|
||||
filterable
|
||||
clearable
|
||||
@@ -758,7 +758,7 @@
|
||||
type="number"
|
||||
step="0.01"
|
||||
min="0"
|
||||
placeholder="请输入金额"
|
||||
:placeholder="$t('maintain.checkProject.placeholder.enterPrice')"
|
||||
>
|
||||
</template>
|
||||
<template v-else>
|
||||
@@ -770,7 +770,7 @@
|
||||
<input
|
||||
v-model="item.number"
|
||||
type="text"
|
||||
placeholder="请输入序号"
|
||||
:placeholder="$t('maintain.checkProject.placeholder.enterOrderNum')"
|
||||
>
|
||||
</template>
|
||||
<template v-else>
|
||||
@@ -781,7 +781,7 @@
|
||||
<template v-if="item.editing">
|
||||
<el-select
|
||||
v-model="item.serviceScope"
|
||||
placeholder="选择服务范围"
|
||||
:placeholder="$t('maintain.checkProject.placeholder.selectServiceScope')"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
@@ -793,14 +793,14 @@
|
||||
</el-select>
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ getServiceScopeLabel(item.serviceScope) || '无' }}
|
||||
{{ getServiceScopeLabel(item.serviceScope) || $t('maintain.checkProject.text.none') }}
|
||||
</template>
|
||||
</td>
|
||||
<td>
|
||||
<template v-if="item.editing">
|
||||
<el-select
|
||||
v-model="item.subType"
|
||||
placeholder="选择下级医技类型"
|
||||
:placeholder="$t('maintain.checkProject.placeholder.selectSubType')"
|
||||
style="width: 100%"
|
||||
clearable
|
||||
filterable
|
||||
@@ -822,7 +822,7 @@
|
||||
<input
|
||||
v-model="item.remark"
|
||||
type="text"
|
||||
placeholder="请输入备注"
|
||||
:placeholder="$t('maintain.checkProject.placeholder.enterRemark')"
|
||||
>
|
||||
</template>
|
||||
<template v-else>
|
||||
@@ -833,14 +833,14 @@
|
||||
<template v-if="item.editing">
|
||||
<button
|
||||
class="btn btn-confirm"
|
||||
title="保存"
|
||||
:title="$t('maintain.checkProject.action.save')"
|
||||
@click.stop="handleConfirm(index)"
|
||||
>
|
||||
✓
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-cancel"
|
||||
title="取消"
|
||||
:title="$t('maintain.checkProject.action.cancel')"
|
||||
@click.stop="handleCancelEdit(index)"
|
||||
>
|
||||
✕
|
||||
@@ -849,21 +849,21 @@
|
||||
<template v-else>
|
||||
<button
|
||||
class="btn btn-edit"
|
||||
title="编辑"
|
||||
:title="$t('maintain.checkProject.action.edit')"
|
||||
@click.stop="handleEdit(index)"
|
||||
>
|
||||
✏️
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-confirm"
|
||||
title="保存"
|
||||
:title="$t('maintain.checkProject.action.save')"
|
||||
@click.stop="handleConfirm(index)"
|
||||
>
|
||||
✓
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-delete"
|
||||
title="删除"
|
||||
:title="$t('maintain.checkProject.action.delete')"
|
||||
@click.stop="handleDelete(index)"
|
||||
>
|
||||
✕
|
||||
@@ -888,7 +888,7 @@
|
||||
‹
|
||||
</button>
|
||||
<span>
|
||||
第 {{ checkTypePagination.currentPage }} 页
|
||||
{{ $t('maintain.checkProject.pagination.page', { page: checkTypePagination.currentPage }) }}
|
||||
</span>
|
||||
<button
|
||||
class="pagination-btn"
|
||||
@@ -916,7 +916,10 @@
|
||||
|
||||
<script setup>
|
||||
import {computed, onMounted, reactive, ref} from 'vue';
|
||||
import {useI18n} from 'vue-i18n';
|
||||
import {ElMessage, ElMessageBox} from 'element-plus';
|
||||
|
||||
const {t} = useI18n();
|
||||
import {getDicts} from '@/api/system/dict/data';
|
||||
import {getList as getDeptList} from '@/views/basicmanage/organization/components/api';
|
||||
import {
|
||||
@@ -946,6 +949,8 @@ import PackageManagement from './components/PackageManagement.vue';
|
||||
const menus = ['检查类型', '检查方法', '检查部位', '套餐设置'];
|
||||
const activeMenu = ref('检查类型');
|
||||
|
||||
const menuKeyMap = {'检查类型': 'checkType', '检查方法': 'checkMethod', '检查部位': 'checkPart', '套餐设置': 'packageSettings'};
|
||||
|
||||
// 套餐视图状态: management-套餐管理列表, settings-套餐设置
|
||||
const packageView = ref('settings')
|
||||
// 套餐设置模式: add-新增, edit-编辑, view-查看
|
||||
@@ -1313,7 +1318,7 @@ onMounted(async () => {
|
||||
} catch (error) {
|
||||
console.error('获取数据失败:', error);
|
||||
// 如果API调用失败,显示友好提示
|
||||
alert('获取检查类型数据失败,请检查网络或服务状态');
|
||||
alert(t('maintain.checkProject.message.getDataFailed'));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1364,7 +1369,7 @@ function handleSwitchToSettings(params) {
|
||||
async function handleSaveSuccess() {
|
||||
console.log('保存成功')
|
||||
// 保存成功后保持在套餐设置界面,可以继续编辑或返回管理界面
|
||||
ElMessage.success('保存成功')
|
||||
ElMessage.success(t('maintain.checkProject.message.saveSuccess'))
|
||||
|
||||
// 刷新套餐列表数据
|
||||
try {
|
||||
@@ -1433,10 +1438,10 @@ async function loadMenuData(menu) {
|
||||
});
|
||||
});
|
||||
} else {
|
||||
ElMessage.warning('未获取到检查方法数据');
|
||||
ElMessage.warning(t('maintain.checkProject.message.noMethodData'));
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error(`加载检查方法数据失败: ${error.message || '未知错误'}`);
|
||||
ElMessage.error(t('maintain.checkProject.message.loadMethodFailed', { error: error.message || t('maintain.checkProject.text.unknownError') }));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1489,10 +1494,10 @@ async function loadMenuData(menu) {
|
||||
});
|
||||
});
|
||||
} else {
|
||||
ElMessage.warning('未获取到检查部位数据');
|
||||
ElMessage.warning(t('maintain.checkProject.message.noPartData'));
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error(`加载检查部位数据失败: ${error.message || '未知错误'}`);
|
||||
ElMessage.error(t('maintain.checkProject.message.loadPartFailed', { error: error.message || t('maintain.checkProject.text.unknownError') }));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1504,7 +1509,7 @@ async function loadMenuData(menu) {
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载菜单数据失败:', error);
|
||||
ElMessage.error(`加载${menu}数据失败,请检查网络或服务状态`);
|
||||
ElMessage.error(t('maintain.checkProject.message.loadMenuFailed', { menu }));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1571,7 +1576,7 @@ async function loadCheckTypeDataWithPagination(pageNo = 1, pageSize = 10) {
|
||||
|
||||
} catch (error) {
|
||||
console.error('加载检查类型数据失败:', error);
|
||||
ElMessage.error('加载检查类型数据失败,请检查网络或服务状态');
|
||||
ElMessage.error(t('maintain.checkProject.message.loadCheckTypeFailed'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1618,34 +1623,34 @@ async function handleConfirm(index) {
|
||||
|
||||
// 必填字段验证
|
||||
if (!item.code || item.code.trim() === '') {
|
||||
ElMessage.error('编码不能为空');
|
||||
ElMessage.error(t('maintain.checkProject.validation.codeRequired'));
|
||||
return;
|
||||
}
|
||||
if (!item.name || item.name.trim() === '') {
|
||||
ElMessage.error('名称不能为空');
|
||||
ElMessage.error(t('maintain.checkProject.validation.nameRequired'));
|
||||
return;
|
||||
}
|
||||
// 根据不同菜单验证检查类型字段
|
||||
if (activeMenu.value === '检查方法') {
|
||||
if (!item.checkType || item.checkType.trim() === '') {
|
||||
ElMessage.error('检查类型不能为空');
|
||||
ElMessage.error(t('maintain.checkProject.validation.checkTypeRequired'));
|
||||
return;
|
||||
}
|
||||
} else if (activeMenu.value === '检查类型') {
|
||||
if (!item.type || item.type.trim() === '') {
|
||||
ElMessage.error('检查类型不能为空');
|
||||
ElMessage.error(t('maintain.checkProject.validation.checkTypeRequired'));
|
||||
return;
|
||||
}
|
||||
} else if (activeMenu.value === '检查部位') {
|
||||
if (!item.checkType || item.checkType.trim() === '') {
|
||||
ElMessage.error('检查类型不能为空');
|
||||
ElMessage.error(t('maintain.checkProject.validation.checkTypeRequired'));
|
||||
return;
|
||||
}
|
||||
}
|
||||
// 检查类型才需要验证执行科室
|
||||
if (activeMenu.value === '检查类型') {
|
||||
if (!item.department || item.department.trim() === '') {
|
||||
ElMessage.error('执行科室不能为空');
|
||||
ElMessage.error(t('maintain.checkProject.validation.departmentRequired'));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1694,7 +1699,7 @@ async function handleConfirm(index) {
|
||||
if (newId) {
|
||||
item.id = newId;
|
||||
} else {
|
||||
ElMessage.warning('数据已保存,但未能获取ID,删除功能可能受影响');
|
||||
ElMessage.warning(t('maintain.checkProject.message.saveNoId'));
|
||||
}
|
||||
}
|
||||
} else if (activeMenu.value === '检查部位') {
|
||||
@@ -1776,13 +1781,13 @@ async function handleConfirm(index) {
|
||||
item.isNew = false;
|
||||
}
|
||||
// 显示保存成功提示
|
||||
ElMessage.success(`第 ${item.row} 行数据已保存`);
|
||||
ElMessage.success(t('maintain.checkProject.message.rowSaved', { row: item.row }));
|
||||
// 保存成功后自动刷新列表
|
||||
await loadMenuData(activeMenu.value);
|
||||
} catch (error) {
|
||||
console.error('保存失败,错误信息:', error);
|
||||
console.error('保存失败,错误详情:', error.response ? error.response.data : error);
|
||||
ElMessage.error('保存失败,请稍后重试');
|
||||
ElMessage.error(t('maintain.checkProject.message.saveFailed'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1801,13 +1806,13 @@ async function handleDelete(index) {
|
||||
String(item.id) !== 'null';
|
||||
|
||||
if (!hasValidId || item.isNew) {
|
||||
ElMessageBox.confirm('该行数据尚未保存,确定要删除吗?', '系统提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
ElMessageBox.confirm(t('maintain.checkProject.confirm.unsavedDelete'), t('maintain.checkProject.confirm.systemTip'), {
|
||||
confirmButtonText: t('maintain.checkProject.button.confirm'),
|
||||
cancelButtonText: t('maintain.checkProject.button.cancel'),
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
tableData.value.splice(index, 1);
|
||||
ElMessage.success('删除成功');
|
||||
ElMessage.success(t('maintain.checkProject.message.deleteSuccess'));
|
||||
}).catch(() => {
|
||||
console.log('用户取消删除操作');
|
||||
});
|
||||
@@ -1824,21 +1829,21 @@ async function handleDelete(index) {
|
||||
}
|
||||
|
||||
// 构建确认消息
|
||||
let confirmMessage = '确定要删除这一行吗?';
|
||||
let confirmMessage = t('maintain.checkProject.confirm.deleteRow');
|
||||
if (isParentRow && childRows.length > 0) {
|
||||
confirmMessage = `确定要删除这一行吗?\n该操作将同时删除 ${childRows.length} 个子行数据。`;
|
||||
confirmMessage = t('maintain.checkProject.confirm.deleteRowWithChildren', { count: childRows.length });
|
||||
}
|
||||
|
||||
ElMessageBox.confirm(confirmMessage, '系统提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
ElMessageBox.confirm(confirmMessage, t('maintain.checkProject.confirm.systemTip'), {
|
||||
confirmButtonText: t('maintain.checkProject.button.confirm'),
|
||||
cancelButtonText: t('maintain.checkProject.button.cancel'),
|
||||
type: 'warning'
|
||||
}).then(async () => {
|
||||
try {
|
||||
// 确保 ID 是有效的数字或字符串
|
||||
const validId = String(item.id).trim();
|
||||
if (!validId || validId === 'undefined' || validId === 'null') {
|
||||
ElMessage.error('删除失败,无效的ID');
|
||||
ElMessage.error(t('maintain.checkProject.message.deleteInvalidId'));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1853,9 +1858,9 @@ async function handleDelete(index) {
|
||||
|
||||
// 删除成功,刷新列表数据
|
||||
await loadMenuData(activeMenu.value);
|
||||
ElMessage.success(`删除成功!${isParentRow && childRows.length > 0 ? `已删除 1 个父行和 ${childRows.length} 个子行` : ''}`);
|
||||
ElMessage.success(isParentRow && childRows.length > 0 ? t('maintain.checkProject.message.deleteWithChildrenSuccess', { count: childRows.length }) : t('maintain.checkProject.message.deleteSuccess'));
|
||||
} catch (error) {
|
||||
ElMessage.error('删除失败,请稍后重试');
|
||||
ElMessage.error(t('maintain.checkProject.message.deleteFailed'));
|
||||
}
|
||||
}).catch(() => {
|
||||
// 用户取消删除操作
|
||||
@@ -1948,7 +1953,7 @@ function handleAdd(index) {
|
||||
const parentRow = tableData.value[index];
|
||||
|
||||
if (!parentRow.id) {
|
||||
ElMessage.warning('请先保存父行数据后再添加子行');
|
||||
ElMessage.warning(t('maintain.checkProject.message.saveParentFirst'));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2044,9 +2049,9 @@ async function handleSearch() {
|
||||
actions: true
|
||||
});
|
||||
});
|
||||
ElMessage.success(`搜索到${methodData.length}条检查方法数据`);
|
||||
ElMessage.success(t('maintain.checkProject.message.searchMethodSuccess', { count: methodData.length }));
|
||||
} else {
|
||||
ElMessage.warning('未搜索到检查方法数据');
|
||||
ElMessage.warning(t('maintain.checkProject.message.noMethodSearchResult'));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2098,9 +2103,9 @@ async function handleSearch() {
|
||||
actions: true
|
||||
});
|
||||
});
|
||||
ElMessage.success(`搜索到${partData.length}条检查部位数据`);
|
||||
ElMessage.success(t('maintain.checkProject.message.searchPartSuccess', { count: partData.length }));
|
||||
} else {
|
||||
ElMessage.warning('未搜索到检查部位数据');
|
||||
ElMessage.warning(t('maintain.checkProject.message.noPartSearchResult'));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2111,7 +2116,7 @@ async function handleSearch() {
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('搜索失败:', error);
|
||||
ElMessage.error(`搜索${activeMenu.value}数据失败: ${error.message || '未知错误'}`);
|
||||
ElMessage.error(t('maintain.checkProject.message.searchFailed', { error: error.message || t('maintain.checkProject.text.unknownError') }));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2141,7 +2146,7 @@ function handleReset() {
|
||||
break;
|
||||
}
|
||||
|
||||
ElMessage.info('搜索条件已重置');
|
||||
ElMessage.info(t('maintain.checkProject.message.resetSuccess'));
|
||||
}
|
||||
|
||||
// 处理导出表格功能
|
||||
@@ -2163,19 +2168,19 @@ function handleExport() {
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
window.URL.revokeObjectURL(url);
|
||||
ElMessage.success('检查方法数据导出成功');
|
||||
ElMessage.success(t('maintain.checkProject.message.exportMethodSuccess'));
|
||||
} else {
|
||||
data.text().then(text => {
|
||||
const errorObj = JSON.parse(text);
|
||||
ElMessage.error(errorObj.msg || errorObj.message || '导出检查方法数据失败');
|
||||
ElMessage.error(errorObj.msg || errorObj.message || t('maintain.checkProject.message.exportMethodFailed'));
|
||||
}).catch(() => {
|
||||
ElMessage.error('导出检查方法数据失败');
|
||||
ElMessage.error(t('maintain.checkProject.message.exportMethodFailed'));
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('导出检查方法数据失败:', error);
|
||||
ElMessage.error('导出检查方法数据失败');
|
||||
ElMessage.error(t('maintain.checkProject.message.exportMethodFailed'));
|
||||
});
|
||||
});
|
||||
} else if (activeMenu.value === '检查部位') {
|
||||
@@ -2193,24 +2198,24 @@ function handleExport() {
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
window.URL.revokeObjectURL(url);
|
||||
ElMessage.success('检查部位数据导出成功');
|
||||
ElMessage.success(t('maintain.checkProject.message.exportPartSuccess'));
|
||||
} else {
|
||||
data.text().then(text => {
|
||||
const errorObj = JSON.parse(text);
|
||||
ElMessage.error(errorObj.msg || errorObj.message || '导出检查部位数据失败');
|
||||
ElMessage.error(errorObj.msg || errorObj.message || t('maintain.checkProject.message.exportPartFailed'));
|
||||
}).catch(() => {
|
||||
ElMessage.error('导出检查部位数据失败');
|
||||
ElMessage.error(t('maintain.checkProject.message.exportPartFailed'));
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('导出检查部位数据失败:', error);
|
||||
ElMessage.error('导出检查部位数据失败');
|
||||
ElMessage.error(t('maintain.checkProject.message.exportPartFailed'));
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// 其他菜单的导出逻辑可以在这里扩展
|
||||
ElMessage.warning('该功能尚未实现');
|
||||
ElMessage.warning(t('maintain.checkProject.message.notImplemented'));
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -189,11 +189,12 @@ import {addLisGroup, delLisGroup, listLisGroup, updateLisGroup} from '@/api/syst
|
||||
import {getDicts} from "@/api/system/dict/data";
|
||||
import useUserStore from '@/store/modules/user';
|
||||
import {ElMessage, ElMessageBox} from 'element-plus';
|
||||
import {useI18n} from 'vue-i18n';
|
||||
|
||||
export default {
|
||||
name: 'LisGroupMaintain',
|
||||
setup() {
|
||||
// 获取用户store
|
||||
const { t } = useI18n();
|
||||
const userStore = useUserStore();
|
||||
|
||||
// 加载状态
|
||||
@@ -626,6 +627,7 @@ export default {
|
||||
})
|
||||
|
||||
return {
|
||||
t,
|
||||
tableData,
|
||||
bloodTubeOptions,
|
||||
startEdit,
|
||||
|
||||
@@ -1,46 +1,46 @@
|
||||
<template>
|
||||
<div style="padding:16px">
|
||||
<div style="margin-bottom:16px;display:flex;justify-content:space-between;align-items:center">
|
||||
<span style="font-size:18px;font-weight:bold">质控指标管理</span>
|
||||
<el-button type="primary" @click="handleCollect">采集指标</el-button>
|
||||
<span style="font-size:18px;font-weight:bold">{{ $t('quality.indicator.title') }}</span>
|
||||
<el-button type="primary" @click="handleCollect">{{ $t('quality.indicator.collect') }}</el-button>
|
||||
</div>
|
||||
<div style="margin-bottom:12px;display:flex;gap:8px;flex-wrap:wrap">
|
||||
<el-input v-model="q.indicatorCode" placeholder="指标编码" clearable style="width:120px" />
|
||||
<el-select v-model="q.indicatorCategory" placeholder="指标分类" clearable style="width:120px">
|
||||
<el-option label="病历质量" value="病历质量" />
|
||||
<el-option label="用药管理" value="用药管理" />
|
||||
<el-option label="手术管理" value="手术管理" />
|
||||
<el-option label="核心制度" value="核心制度" />
|
||||
<el-option label="安全管理" value="安全管理" />
|
||||
<el-option label="服务质量" value="服务质量" />
|
||||
<el-option label="运营效率" value="运营效率" />
|
||||
<el-input v-model="q.indicatorCode" :placeholder="$t('quality.indicator.indicatorCode')" clearable style="width:120px" />
|
||||
<el-select v-model="q.indicatorCategory" :placeholder="$t('quality.indicator.indicatorCategory')" clearable style="width:120px">
|
||||
<el-option :label="$t('quality.indicator.cat.medicalRecord')" value="病历质量" />
|
||||
<el-option :label="$t('quality.indicator.cat.medication')" value="用药管理" />
|
||||
<el-option :label="$t('quality.indicator.cat.surgery')" value="手术管理" />
|
||||
<el-option :label="$t('quality.indicator.cat.coreSystem')" value="核心制度" />
|
||||
<el-option :label="$t('quality.indicator.cat.safety')" value="安全管理" />
|
||||
<el-option :label="$t('quality.indicator.cat.serviceQuality')" value="服务质量" />
|
||||
<el-option :label="$t('quality.indicator.cat.efficiency')" value="运营效率" />
|
||||
</el-select>
|
||||
<el-input v-model="q.statPeriod" placeholder="统计周期(如2026-06)" clearable style="width:150px" />
|
||||
<el-button type="primary" @click="loadData">查询</el-button>
|
||||
<el-input v-model="q.statPeriod" :placeholder="$t('quality.indicator.statPeriodPlaceholder')" clearable style="width:150px" />
|
||||
<el-button type="primary" @click="loadData">{{ $t('common.search') }}</el-button>
|
||||
</div>
|
||||
<el-table :data="tableData" border stripe>
|
||||
<el-table-column prop="indicatorCode" label="编码" width="100" />
|
||||
<el-table-column prop="indicatorName" label="指标名称" min-width="160" show-overflow-tooltip />
|
||||
<el-table-column prop="indicatorCategory" label="分类" width="100" align="center">
|
||||
<el-table-column prop="indicatorCode" :label="$t('quality.indicator.code')" width="100" />
|
||||
<el-table-column prop="indicatorName" :label="$t('quality.indicator.indicatorName')" min-width="160" show-overflow-tooltip />
|
||||
<el-table-column prop="indicatorCategory" :label="$t('quality.indicator.category')" width="100" align="center">
|
||||
<template #default="{row}">
|
||||
<el-tag size="small">{{ row.indicatorCategory }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="targetValue" label="目标值" width="80" align="center" />
|
||||
<el-table-column prop="actualValue" label="实际值" width="80" align="center">
|
||||
<el-table-column prop="targetValue" :label="$t('quality.indicator.targetValue')" width="80" align="center" />
|
||||
<el-table-column prop="actualValue" :label="$t('quality.indicator.actualValue')" width="80" align="center">
|
||||
<template #default="{row}">
|
||||
<span :style="{color: row.actualValue && row.targetValue && row.actualValue >= row.targetValue ? '#67C23A' : '#F56C6C', fontWeight:'bold'}">
|
||||
{{ row.actualValue }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="unit" label="单位" width="60" align="center" />
|
||||
<el-table-column prop="statPeriod" label="统计周期" width="110" />
|
||||
<el-table-column prop="statDate" label="统计日期" width="110" />
|
||||
<el-table-column prop="status" label="状态" width="80" align="center">
|
||||
<el-table-column prop="unit" :label="$t('quality.indicator.unit')" width="60" align="center" />
|
||||
<el-table-column prop="statPeriod" :label="$t('quality.indicator.statPeriod')" width="110" />
|
||||
<el-table-column prop="statDate" :label="$t('quality.indicator.statDate')" width="110" />
|
||||
<el-table-column prop="status" :label="$t('common.status')" width="80" align="center">
|
||||
<template #default="{row}">
|
||||
<el-tag :type="row.status==='ACTIVE'?'success':'info'" size="small">
|
||||
{{ row.status === 'ACTIVE' ? '有效' : '无效' }}
|
||||
{{ row.status === 'ACTIVE' ? $t('quality.indicator.active') : $t('quality.indicator.inactive') }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -57,9 +57,12 @@
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { collectIndicators, getIndicatorList } from '@/api/quality'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const tableData = ref([])
|
||||
const total = ref(0)
|
||||
const q = ref({ pageNo: 1, pageSize: 10, indicatorCode: '', indicatorCategory: '', statPeriod: '' })
|
||||
@@ -72,7 +75,7 @@ const loadData = async () => {
|
||||
|
||||
const handleCollect = async () => {
|
||||
await collectIndicators({ statPeriod: q.value.statPeriod || undefined })
|
||||
ElMessage.success('指标采集完成')
|
||||
ElMessage.success(t('quality.indicator.collectDone'))
|
||||
loadData()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div style="margin-bottom:16px;display:flex;justify-content:space-between;align-items:center">
|
||||
<span style="font-size:18px;font-weight:bold">病历质量统计</span>
|
||||
<span style="font-size:18px;font-weight:bold">{{ $t('quality.statistics.title') }}</span>
|
||||
<div>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="loadData"
|
||||
>
|
||||
刷新
|
||||
{{ $t('common.refresh') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="warning"
|
||||
@click="exportReport"
|
||||
>
|
||||
导出报告
|
||||
{{ $t('quality.statistics.exportReport') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -53,35 +53,35 @@
|
||||
:inline="true"
|
||||
style="margin-bottom:16px"
|
||||
>
|
||||
<el-form-item label="就诊号">
|
||||
<el-form-item :label="$t('quality.statistics.encounterId')">
|
||||
<el-input
|
||||
v-model="q.encounterId"
|
||||
clearable
|
||||
placeholder="请输入就诊号"
|
||||
:placeholder="$t('quality.statistics.encounterIdPlaceholder')"
|
||||
style="width:180px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="科室">
|
||||
<el-form-item :label="$t('quality.statistics.department')">
|
||||
<el-select
|
||||
v-model="q.departmentName"
|
||||
clearable
|
||||
placeholder="请选择科室"
|
||||
:placeholder="$t('quality.statistics.departmentPlaceholder')"
|
||||
style="width:140px"
|
||||
>
|
||||
<el-option
|
||||
label="内科"
|
||||
:label="$t('quality.statistics.dept.internal')"
|
||||
value="内科"
|
||||
/>
|
||||
<el-option
|
||||
label="外科"
|
||||
:label="$t('quality.statistics.dept.surgery')"
|
||||
value="外科"
|
||||
/>
|
||||
<el-option
|
||||
label="妇产科"
|
||||
:label="$t('quality.statistics.dept.obgyn')"
|
||||
value="妇产科"
|
||||
/>
|
||||
<el-option
|
||||
label="儿科"
|
||||
:label="$t('quality.statistics.dept.pediatrics')"
|
||||
value="儿科"
|
||||
/>
|
||||
<el-option
|
||||
@@ -90,12 +90,12 @@
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="日期范围">
|
||||
<el-form-item :label="$t('quality.statistics.dateRange')">
|
||||
<el-date-picker
|
||||
v-model="q.dateRange"
|
||||
type="daterange"
|
||||
start-placeholder="开始"
|
||||
end-placeholder="结束"
|
||||
:start-placeholder="$t('quality.statistics.start')"
|
||||
:end-placeholder="$t('quality.statistics.end')"
|
||||
style="width:240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
@@ -104,10 +104,10 @@
|
||||
type="primary"
|
||||
@click="loadData"
|
||||
>
|
||||
查询
|
||||
{{ $t('common.search') }}
|
||||
</el-button>
|
||||
<el-button @click="resetQuery">
|
||||
重置
|
||||
{{ $t('common.reset') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
@@ -121,11 +121,12 @@
|
||||
<el-card shadow="hover">
|
||||
<template #header>
|
||||
<div style="display:flex;justify-content:space-between;align-items:center">
|
||||
<span>运行质控结果</span><el-tag
|
||||
<span>{{ $t('quality.statistics.runtimeResult') }}</span>
|
||||
<el-tag
|
||||
:type="runtimeResult.status==='PASS'?'success':'danger'"
|
||||
size="small"
|
||||
>
|
||||
{{ runtimeResult.status || '待检测' }}
|
||||
{{ runtimeResult.status || $t('quality.statistics.pending') }}
|
||||
</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
@@ -134,16 +135,16 @@
|
||||
border
|
||||
size="small"
|
||||
>
|
||||
<el-descriptions-item label="质控时间">
|
||||
<el-descriptions-item :label="$t('quality.statistics.checkTime')">
|
||||
{{ runtimeResult.checkTime || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="缺陷数">
|
||||
<el-descriptions-item :label="$t('quality.statistics.defectCount')">
|
||||
{{ runtimeResult.defectCount || 0 }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="严重缺陷">
|
||||
<el-descriptions-item :label="$t('quality.statistics.criticalDefects')">
|
||||
{{ runtimeResult.criticalDefects || 0 }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="一般缺陷">
|
||||
<el-descriptions-item :label="$t('quality.statistics.normalDefects')">
|
||||
{{ runtimeResult.normalDefects || 0 }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
@@ -153,11 +154,12 @@
|
||||
<el-card shadow="hover">
|
||||
<template #header>
|
||||
<div style="display:flex;justify-content:space-between;align-items:center">
|
||||
<span>终末质控评分</span><el-tag
|
||||
<span>{{ $t('quality.statistics.terminalScore') }}</span>
|
||||
<el-tag
|
||||
:type="terminalResult.score>=80?'success':terminalResult.score>=60?'warning':'danger'"
|
||||
size="large"
|
||||
>
|
||||
{{ terminalResult.score || 0 }}分
|
||||
{{ terminalResult.score || 0 }}{{ $t('quality.statistics.scoreUnit') }}
|
||||
</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
@@ -166,16 +168,16 @@
|
||||
border
|
||||
size="small"
|
||||
>
|
||||
<el-descriptions-item label="评分时间">
|
||||
<el-descriptions-item :label="$t('quality.statistics.scoreTime')">
|
||||
{{ terminalResult.checkTime || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="评分等级">
|
||||
<el-descriptions-item :label="$t('quality.statistics.scoreLevel')">
|
||||
{{ scoreLevel(terminalResult.score) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="甲级病历">
|
||||
<el-descriptions-item :label="$t('quality.statistics.gradeA')">
|
||||
{{ terminalResult.gradeA || 0 }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="乙级病历">
|
||||
<el-descriptions-item :label="$t('quality.statistics.gradeB')">
|
||||
{{ terminalResult.gradeB || 0 }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
@@ -187,28 +189,28 @@
|
||||
<el-card shadow="never">
|
||||
<template #header>
|
||||
<div style="display:flex;justify-content:space-between;align-items:center">
|
||||
<span>缺陷记录 ({{ defects.length }})</span>
|
||||
<span>{{ $t('quality.statistics.defectRecords') }} ({{ defects.length }})</span>
|
||||
<el-select
|
||||
v-model="defectFilter"
|
||||
clearable
|
||||
placeholder="筛选缺陷类型"
|
||||
:placeholder="$t('quality.statistics.filterDefectType')"
|
||||
style="width:140px"
|
||||
@change="filterDefects"
|
||||
>
|
||||
<el-option
|
||||
label="全部"
|
||||
:label="$t('quality.statistics.all')"
|
||||
value=""
|
||||
/>
|
||||
<el-option
|
||||
label="严重缺陷"
|
||||
:label="$t('quality.statistics.criticalDefect')"
|
||||
value="CRITICAL"
|
||||
/>
|
||||
<el-option
|
||||
label="主要缺陷"
|
||||
:label="$t('quality.statistics.majorDefect')"
|
||||
value="MAJOR"
|
||||
/>
|
||||
<el-option
|
||||
label="一般缺陷"
|
||||
:label="$t('quality.statistics.minorDefect')"
|
||||
value="MINOR"
|
||||
/>
|
||||
</el-select>
|
||||
@@ -220,18 +222,18 @@
|
||||
stripe
|
||||
>
|
||||
<el-table-column
|
||||
label="缺陷类型"
|
||||
:label="$t('quality.statistics.defectType')"
|
||||
prop="defectType"
|
||||
width="140"
|
||||
/>
|
||||
<el-table-column
|
||||
label="缺陷项"
|
||||
:label="$t('quality.statistics.defectItem')"
|
||||
prop="defectItem"
|
||||
min-width="180"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
label="严重程度"
|
||||
:label="$t('quality.statistics.severity')"
|
||||
prop="severity"
|
||||
width="110"
|
||||
align="center"
|
||||
@@ -241,12 +243,12 @@
|
||||
:type="s.row.severity==='CRITICAL'?'danger':s.row.severity==='MAJOR'?'warning':'info'"
|
||||
size="small"
|
||||
>
|
||||
{{ s.row.severity==='CRITICAL'?'严重缺陷':s.row.severity==='MAJOR'?'主要缺陷':'一般缺陷' }}
|
||||
{{ s.row.severity==='CRITICAL'?$t('quality.statistics.criticalDefect'):s.row.severity==='MAJOR'?$t('quality.statistics.majorDefect'):$t('quality.statistics.minorDefect') }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="整改状态"
|
||||
:label="$t('quality.statistics.rectifyStatus')"
|
||||
prop="rectifyStatus"
|
||||
width="100"
|
||||
align="center"
|
||||
@@ -256,12 +258,12 @@
|
||||
:type="s.row.rectifyStatus==='RECTIFIED'?'success':s.row.rectifyStatus==='RECTIFYING'?'warning':'info'"
|
||||
size="small"
|
||||
>
|
||||
{{ s.row.rectifyStatus==='RECTIFIED'?'已整改':s.row.rectifyStatus==='RECTIFYING'?'整改中':'待整改' }}
|
||||
{{ s.row.rectifyStatus==='RECTIFIED'?$t('quality.statistics.rectified'):s.row.rectifyStatus==='RECTIFYING'?$t('quality.statistics.rectifying'):$t('quality.statistics.pendingRectify') }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="发现时间"
|
||||
:label="$t('quality.statistics.discoverTime')"
|
||||
prop="discoverTime"
|
||||
width="160"
|
||||
/>
|
||||
@@ -272,9 +274,12 @@
|
||||
|
||||
<script setup>
|
||||
import {ref, reactive, computed, onMounted} from 'vue'
|
||||
import {useI18n} from 'vue-i18n'
|
||||
import {ElMessage} from 'element-plus'
|
||||
import {runtimeCheck, terminalCheck, getDefects, getQualityStatistics} from '@/api/quality'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const q = reactive({encounterId:'', departmentName:'', dateRange:null})
|
||||
const runtimeResult = ref({})
|
||||
const terminalResult = ref({})
|
||||
@@ -282,13 +287,13 @@ const defects = ref([])
|
||||
const defectFilter = ref('')
|
||||
const qualityStats = ref({})
|
||||
|
||||
const statCards = ref([
|
||||
{label:'总病历数', value:0, color:'#409eff'},
|
||||
{label:'甲级病历', value:0, color:'#67c23a'},
|
||||
{label:'乙级病历', value:0, color:'#e6a23c'},
|
||||
{label:'丙级病历', value:0, color:'#f56c6c'},
|
||||
{label:'缺陷总数', value:0, color:'#909399'},
|
||||
{label:'甲级率', value:'0%', color:'#409eff'}
|
||||
const statCards = computed(() => [
|
||||
{label:t('quality.statistics.totalRecords'), value:qualityStats.value.totalRecords||0, color:'#409eff'},
|
||||
{label:t('quality.statistics.gradeARecords'), value:qualityStats.value.gradeA||0, color:'#67c23a'},
|
||||
{label:t('quality.statistics.gradeBRecords'), value:qualityStats.value.gradeB||0, color:'#e6a23c'},
|
||||
{label:t('quality.statistics.gradeCRecords'), value:qualityStats.value.gradeC||0, color:'#f56c6c'},
|
||||
{label:t('quality.statistics.totalDefects'), value:qualityStats.value.totalDefects||0, color:'#909399'},
|
||||
{label:t('quality.statistics.gradeARate'), value:(qualityStats.value.gradeARate||0)+'%', color:'#409eff'}
|
||||
])
|
||||
|
||||
const filteredDefects = computed(() => {
|
||||
@@ -298,10 +303,10 @@ const filteredDefects = computed(() => {
|
||||
|
||||
function scoreLevel(score) {
|
||||
if (!score) return '-'
|
||||
if (score >= 90) return '甲级'
|
||||
if (score >= 75) return '乙级'
|
||||
if (score >= 60) return '丙级'
|
||||
return '不合格'
|
||||
if (score >= 90) return t('quality.statistics.levelA')
|
||||
if (score >= 75) return t('quality.statistics.levelB')
|
||||
if (score >= 60) return t('quality.statistics.levelC')
|
||||
return t('quality.statistics.levelFail')
|
||||
}
|
||||
|
||||
async function loadData() {
|
||||
@@ -320,14 +325,8 @@ async function loadData() {
|
||||
try {
|
||||
const r4 = await getQualityStatistics(q)
|
||||
qualityStats.value = r4.data || {}
|
||||
statCards.value[0].value = qualityStats.value.totalRecords || 0
|
||||
statCards.value[1].value = qualityStats.value.gradeA || 0
|
||||
statCards.value[2].value = qualityStats.value.gradeB || 0
|
||||
statCards.value[3].value = qualityStats.value.gradeC || 0
|
||||
statCards.value[4].value = qualityStats.value.totalDefects || 0
|
||||
statCards.value[5].value = (qualityStats.value.gradeARate || 0) + '%'
|
||||
} catch(e) {}
|
||||
} catch(e) { ElMessage.error('查询失败') }
|
||||
} catch(e) { ElMessage.error(t('quality.statistics.queryFailed')) }
|
||||
}
|
||||
|
||||
function resetQuery() {
|
||||
@@ -342,7 +341,7 @@ function resetQuery() {
|
||||
|
||||
function filterDefects() {}
|
||||
|
||||
function exportReport() { ElMessage.info('导出功能开发中') }
|
||||
function exportReport() { ElMessage.info(t('quality.statistics.exportWip')) }
|
||||
|
||||
onMounted(() => loadData())
|
||||
</script>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div style="margin-bottom:16px;display:flex;justify-content:space-between;align-items:center">
|
||||
<span style="font-size:18px;font-weight:bold">终末质控</span>
|
||||
<span style="font-size:18px;font-weight:bold">{{ $t('quality.terminal.title') }}</span>
|
||||
<div>
|
||||
<el-button type="primary" @click="runCheck" :loading="checkLoading">
|
||||
执行检查
|
||||
{{ $t('quality.terminal.runCheck') }}
|
||||
</el-button>
|
||||
<el-button @click="loadResults" :loading="resultsLoading">
|
||||
刷新结果
|
||||
{{ $t('quality.terminal.refreshResults') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -15,15 +15,15 @@
|
||||
<!-- 就诊号输入 -->
|
||||
<el-card shadow="never" style="margin-bottom:16px">
|
||||
<el-form :inline="true">
|
||||
<el-form-item label="就诊号">
|
||||
<el-input v-model="encounterId" clearable placeholder="请输入就诊号" style="width:200px" />
|
||||
<el-form-item :label="$t('quality.terminal.encounterId')">
|
||||
<el-input v-model="encounterId" clearable :placeholder="$t('quality.terminal.encounterIdPlaceholder')" style="width:200px" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="runCheck" :loading="checkLoading">
|
||||
执行终末检查
|
||||
{{ $t('quality.terminal.runTerminalCheck') }}
|
||||
</el-button>
|
||||
<el-button @click="loadResults" :loading="resultsLoading">
|
||||
查询结果
|
||||
{{ $t('quality.terminal.queryResults') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
@@ -35,23 +35,23 @@
|
||||
<el-card shadow="hover">
|
||||
<template #header>
|
||||
<div style="display:flex;justify-content:space-between;align-items:center">
|
||||
<span>终末质控评分</span>
|
||||
<span>{{ $t('quality.terminal.scoreTitle') }}</span>
|
||||
<el-tag :type="scoreTagType" size="large">
|
||||
{{ results.score || 0 }}分
|
||||
{{ results.score || 0 }}{{ $t('quality.terminal.scoreUnit') }}
|
||||
</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
<el-descriptions :column="2" border size="small">
|
||||
<el-descriptions-item label="检查时间">
|
||||
<el-descriptions-item :label="$t('quality.terminal.checkTime')">
|
||||
{{ results.checkTime || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="评分等级">
|
||||
<el-descriptions-item :label="$t('quality.terminal.scoreLevel')">
|
||||
{{ gradeText }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="检查项目数">
|
||||
<el-descriptions-item :label="$t('quality.terminal.totalItems')">
|
||||
{{ results.totalItems || 0 }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="通过项目数">
|
||||
<el-descriptions-item :label="$t('quality.terminal.passItems')">
|
||||
{{ results.passItems || 0 }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
@@ -60,14 +60,14 @@
|
||||
<el-col :span="12">
|
||||
<el-card shadow="hover">
|
||||
<template #header>
|
||||
<span>检查项目详情</span>
|
||||
<span>{{ $t('quality.terminal.checkItemDetails') }}</span>
|
||||
</template>
|
||||
<el-table :data="results.checks || []" border stripe size="small">
|
||||
<el-table-column label="检查项目" prop="item" min-width="180" />
|
||||
<el-table-column label="检查结果" prop="result" width="100" align="center">
|
||||
<el-table-column :label="$t('quality.terminal.checkItem')" prop="item" min-width="180" />
|
||||
<el-table-column :label="$t('quality.terminal.checkResult')" prop="result" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.result === 'PASS' ? 'success' : 'danger'" size="small">
|
||||
{{ scope.row.result === 'PASS' ? '通过' : '不通过' }}
|
||||
{{ scope.row.result === 'PASS' ? $t('quality.terminal.pass') : $t('quality.terminal.fail') }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -80,33 +80,33 @@
|
||||
<el-card shadow="never">
|
||||
<template #header>
|
||||
<div style="display:flex;justify-content:space-between;align-items:center">
|
||||
<span>缺陷记录 ({{ defects.length }})</span>
|
||||
<el-select v-model="defectFilter" clearable placeholder="筛选缺陷类型" style="width:140px">
|
||||
<el-option label="全部" value="" />
|
||||
<el-option label="严重缺陷" value="CRITICAL" />
|
||||
<el-option label="主要缺陷" value="MAJOR" />
|
||||
<el-option label="一般缺陷" value="MINOR" />
|
||||
<span>{{ $t('quality.terminal.defectRecords') }} ({{ defects.length }})</span>
|
||||
<el-select v-model="defectFilter" clearable :placeholder="$t('quality.terminal.filterDefectType')" style="width:140px">
|
||||
<el-option :label="$t('quality.terminal.all')" value="" />
|
||||
<el-option :label="$t('quality.terminal.criticalDefect')" value="CRITICAL" />
|
||||
<el-option :label="$t('quality.terminal.majorDefect')" value="MAJOR" />
|
||||
<el-option :label="$t('quality.terminal.minorDefect')" value="MINOR" />
|
||||
</el-select>
|
||||
</div>
|
||||
</template>
|
||||
<el-table :data="filteredDefects" border stripe>
|
||||
<el-table-column label="缺陷类型" prop="defectType" width="120" />
|
||||
<el-table-column label="缺陷项" prop="defectItem" min-width="180" show-overflow-tooltip />
|
||||
<el-table-column label="严重程度" prop="severity" width="110" align="center">
|
||||
<el-table-column :label="$t('quality.terminal.defectType')" prop="defectType" width="120" />
|
||||
<el-table-column :label="$t('quality.terminal.defectItem')" prop="defectItem" min-width="180" show-overflow-tooltip />
|
||||
<el-table-column :label="$t('quality.terminal.severity')" prop="severity" width="110" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag :type="severityType(scope.row.severity)" size="small">
|
||||
{{ severityText(scope.row.severity) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="整改状态" prop="rectifyStatus" width="110" align="center">
|
||||
<el-table-column :label="$t('quality.terminal.rectifyStatus')" prop="rectifyStatus" width="110" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag :type="rectifyStatusType(scope.row.rectifyStatus)" size="small">
|
||||
{{ rectifyStatusText(scope.row.rectifyStatus) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="120" align="center">
|
||||
<el-table-column :label="$t('common.operation')" width="120" align="center">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
v-if="scope.row.rectifyStatus !== 'RECTIFIED'"
|
||||
@@ -114,7 +114,7 @@
|
||||
size="small"
|
||||
@click="startRectify(scope.row)"
|
||||
>
|
||||
整改
|
||||
{{ $t('quality.terminal.rectify') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="scope.row.rectifyStatus === 'RECTIFYING'"
|
||||
@@ -122,7 +122,7 @@
|
||||
size="small"
|
||||
@click="completeRectify(scope.row)"
|
||||
>
|
||||
完成
|
||||
{{ $t('quality.terminal.complete') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -133,9 +133,12 @@
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, computed, onMounted } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { runTerminalCheck, getTerminalResults, startDefectRectify, completeDefectRectify } from '@/api/quality'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const encounterId = ref('')
|
||||
const results = reactive({
|
||||
score: 0,
|
||||
@@ -160,7 +163,7 @@ const scoreTagType = computed(() => {
|
||||
|
||||
const gradeText = computed(() => {
|
||||
if (!results.grade) return '-'
|
||||
const map = { 'A': '甲级', 'B': '乙级', 'C': '丙级', 'D': '不合格' }
|
||||
const map = { 'A': t('quality.terminal.gradeA'), 'B': t('quality.terminal.gradeB'), 'C': t('quality.terminal.gradeC'), 'D': t('quality.terminal.gradeFail') }
|
||||
return map[results.grade] || '-'
|
||||
})
|
||||
|
||||
@@ -176,9 +179,9 @@ function severityType(severity) {
|
||||
}
|
||||
|
||||
function severityText(severity) {
|
||||
if (severity === 'CRITICAL') return '严重缺陷'
|
||||
if (severity === 'MAJOR') return '主要缺陷'
|
||||
return '一般缺陷'
|
||||
if (severity === 'CRITICAL') return t('quality.terminal.criticalDefect')
|
||||
if (severity === 'MAJOR') return t('quality.terminal.majorDefect')
|
||||
return t('quality.terminal.minorDefect')
|
||||
}
|
||||
|
||||
function rectifyStatusType(status) {
|
||||
@@ -188,27 +191,27 @@ function rectifyStatusType(status) {
|
||||
}
|
||||
|
||||
function rectifyStatusText(status) {
|
||||
if (status === 'RECTIFIED') return '已整改'
|
||||
if (status === 'RECTIFYING') return '整改中'
|
||||
return '待整改'
|
||||
if (status === 'RECTIFIED') return t('quality.terminal.rectified')
|
||||
if (status === 'RECTIFYING') return t('quality.terminal.rectifying')
|
||||
return t('quality.terminal.pendingRectify')
|
||||
}
|
||||
|
||||
async function runCheck() {
|
||||
if (!encounterId.value) {
|
||||
ElMessage.warning('请输入就诊号')
|
||||
ElMessage.warning(t('quality.terminal.enterEncounterId'))
|
||||
return
|
||||
}
|
||||
checkLoading.value = true
|
||||
try {
|
||||
const res = await runTerminalCheck(encounterId.value)
|
||||
if (res.code === 200) {
|
||||
ElMessage.success('终末质控检查完成')
|
||||
ElMessage.success(t('quality.terminal.checkDone'))
|
||||
loadResults()
|
||||
} else {
|
||||
ElMessage.error(res.msg || '检查失败')
|
||||
ElMessage.error(res.msg || t('quality.terminal.checkFailed'))
|
||||
}
|
||||
} catch (e) {
|
||||
ElMessage.error('检查失败: ' + e.message)
|
||||
ElMessage.error(t('quality.terminal.checkFailed') + ': ' + e.message)
|
||||
} finally {
|
||||
checkLoading.value = false
|
||||
}
|
||||
@@ -216,7 +219,7 @@ async function runCheck() {
|
||||
|
||||
async function loadResults() {
|
||||
if (!encounterId.value) {
|
||||
ElMessage.warning('请输入就诊号')
|
||||
ElMessage.warning(t('quality.terminal.enterEncounterId'))
|
||||
return
|
||||
}
|
||||
resultsLoading.value = true
|
||||
@@ -233,7 +236,7 @@ async function loadResults() {
|
||||
defects.value = data.defects || []
|
||||
}
|
||||
} catch (e) {
|
||||
ElMessage.error('查询失败: ' + e.message)
|
||||
ElMessage.error(t('quality.terminal.queryFailed') + ': ' + e.message)
|
||||
} finally {
|
||||
resultsLoading.value = false
|
||||
}
|
||||
@@ -241,34 +244,34 @@ async function loadResults() {
|
||||
|
||||
async function startRectify(defect) {
|
||||
try {
|
||||
await ElMessageBox.confirm('确认开始整改此缺陷?', '确认操作', { type: 'warning' })
|
||||
await ElMessageBox.confirm(t('quality.terminal.confirmStartRectify'), t('quality.terminal.confirmOperation'), { type: 'warning' })
|
||||
const res = await startDefectRectify(defect.id)
|
||||
if (res.code === 200) {
|
||||
ElMessage.success('开始整改')
|
||||
ElMessage.success(t('quality.terminal.rectifyStarted'))
|
||||
loadResults()
|
||||
} else {
|
||||
ElMessage.error(res.msg || '操作失败')
|
||||
ElMessage.error(res.msg || t('quality.terminal.operationFailed'))
|
||||
}
|
||||
} catch (e) {
|
||||
if (e !== 'cancel') {
|
||||
ElMessage.error('操作失败: ' + e.message)
|
||||
ElMessage.error(t('quality.terminal.operationFailed') + ': ' + e.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function completeRectify(defect) {
|
||||
try {
|
||||
await ElMessageBox.confirm('确认完成整改?', '确认操作', { type: 'success' })
|
||||
await ElMessageBox.confirm(t('quality.terminal.confirmCompleteRectify'), t('quality.terminal.confirmOperation'), { type: 'success' })
|
||||
const res = await completeDefectRectify(defect.id)
|
||||
if (res.code === 200) {
|
||||
ElMessage.success('整改完成')
|
||||
ElMessage.success(t('quality.terminal.rectifyCompleted'))
|
||||
loadResults()
|
||||
} else {
|
||||
ElMessage.error(res.msg || '操作失败')
|
||||
ElMessage.error(res.msg || t('quality.terminal.operationFailed'))
|
||||
}
|
||||
} catch (e) {
|
||||
if (e !== 'cancel') {
|
||||
ElMessage.error('操作失败: ' + e.message)
|
||||
ElMessage.error(t('quality.terminal.operationFailed') + ': ' + e.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<template>
|
||||
<div style="padding:16px">
|
||||
<div style="margin-bottom:16px">
|
||||
<span style="font-size:18px;font-weight:bold">质量控制</span>
|
||||
<span style="font-size:18px;font-weight:bold">{{ $t('qualityEnhanced.title') }}</span>
|
||||
</div>
|
||||
<el-tabs
|
||||
v-model="tab"
|
||||
type="border-card"
|
||||
>
|
||||
<el-tab-pane
|
||||
label="核心制度指标"
|
||||
:label="$t('qualityEnhanced.coreSystemIndicator')"
|
||||
name="indicator"
|
||||
>
|
||||
<el-card
|
||||
@@ -19,17 +19,17 @@
|
||||
<div>
|
||||
<div style="font-size:24px;font-weight:bold;color:#409eff">
|
||||
{{ summary.total||0 }}
|
||||
</div><div>总指标</div>
|
||||
</div><div>{{ $t('qualityEnhanced.totalIndicators') }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div style="font-size:24px;font-weight:bold;color:#67c23a">
|
||||
{{ summary.meetTarget||0 }}
|
||||
</div><div>达标</div>
|
||||
</div><div>{{ $t('qualityEnhanced.metTarget') }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div style="font-size:24px;font-weight:bold;color:#e6a23c">
|
||||
{{ summary.meetRate||0 }}%
|
||||
</div><div>达标率</div>
|
||||
</div><div>{{ $t('qualityEnhanced.meetRate') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
@@ -38,7 +38,7 @@
|
||||
type="success"
|
||||
@click="showAdd=true"
|
||||
>
|
||||
新增指标
|
||||
{{ $t('qualityEnhanced.addIndicator') }}
|
||||
</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
@@ -48,45 +48,45 @@
|
||||
>
|
||||
<el-table-column
|
||||
prop="indicatorCode"
|
||||
label="指标编码"
|
||||
:label="$t('qualityEnhanced.indicatorCode')"
|
||||
width="120"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="indicatorName"
|
||||
label="指标名称"
|
||||
:label="$t('qualityEnhanced.indicatorName')"
|
||||
min-width="180"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="indicatorCategory"
|
||||
label="类别"
|
||||
:label="$t('qualityEnhanced.category')"
|
||||
width="100"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="targetValue"
|
||||
label="目标值"
|
||||
:label="$t('qualityEnhanced.targetValue')"
|
||||
width="80"
|
||||
align="center"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="actualValue"
|
||||
label="实际值"
|
||||
:label="$t('qualityEnhanced.actualValue')"
|
||||
width="80"
|
||||
align="center"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="departmentName"
|
||||
label="科室"
|
||||
:label="$t('qualityEnhanced.department')"
|
||||
width="120"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="statDate"
|
||||
label="统计日期"
|
||||
:label="$t('qualityEnhanced.statDate')"
|
||||
width="120"
|
||||
/>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane
|
||||
label="医嘱统计"
|
||||
:label="$t('qualityEnhanced.orderStats')"
|
||||
name="orderStats"
|
||||
>
|
||||
<div style="margin-bottom:12px">
|
||||
@@ -94,7 +94,7 @@
|
||||
type="success"
|
||||
@click="showOrder=true"
|
||||
>
|
||||
新增统计
|
||||
{{ $t('qualityEnhanced.addStats') }}
|
||||
</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
@@ -104,41 +104,41 @@
|
||||
>
|
||||
<el-table-column
|
||||
prop="statDate"
|
||||
label="日期"
|
||||
:label="$t('qualityEnhanced.date')"
|
||||
width="120"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="departmentName"
|
||||
label="科室"
|
||||
:label="$t('qualityEnhanced.department')"
|
||||
width="120"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="totalOrders"
|
||||
label="总医嘱"
|
||||
:label="$t('qualityEnhanced.totalOrders')"
|
||||
width="80"
|
||||
align="center"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="executedOrders"
|
||||
label="已执行"
|
||||
:label="$t('qualityEnhanced.executedOrders')"
|
||||
width="80"
|
||||
align="center"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="completedOrders"
|
||||
label="已完成"
|
||||
:label="$t('qualityEnhanced.completedOrders')"
|
||||
width="80"
|
||||
align="center"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="executeRate"
|
||||
label="执行率%"
|
||||
:label="$t('qualityEnhanced.executeRate')"
|
||||
width="80"
|
||||
align="center"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="completeRate"
|
||||
label="完成率%"
|
||||
:label="$t('qualityEnhanced.completeRate')"
|
||||
width="80"
|
||||
align="center"
|
||||
/>
|
||||
@@ -150,8 +150,10 @@
|
||||
|
||||
<script setup>
|
||||
import {ref,reactive,onMounted} from 'vue'
|
||||
import {useI18n} from 'vue-i18n'
|
||||
import {ElMessage} from 'element-plus'
|
||||
import {getIndicatorPage,addIndicator,getIndicatorSummary,getOrderStatsPage,addOrderStats} from './api'
|
||||
const { t } = useI18n()
|
||||
const tab=ref('indicator')
|
||||
const indicatorData=ref([]),orderData=ref([])
|
||||
const summary=ref({})
|
||||
@@ -162,7 +164,7 @@ const loadData=async()=>{
|
||||
const [i,s,o]=await Promise.all([getIndicatorPage({pageNo:1,pageSize:50}),getIndicatorSummary(),getOrderStatsPage({pageNo:1,pageSize:50})])
|
||||
indicatorData.value=i.data?.records||[];summary.value=s.data||{};orderData.value=o.data?.records||[]
|
||||
}
|
||||
const submitIndicator=async()=>{await addIndicator(indicatorForm);ElMessage.success('新增成功');showAdd.value=false;loadData()}
|
||||
const submitOrder=async()=>{await addOrderStats(orderForm);ElMessage.success('新增成功');showOrder.value=false;loadData()}
|
||||
const submitIndicator=async()=>{await addIndicator(indicatorForm);ElMessage.success(t('qualityEnhanced.addSuccess'));showAdd.value=false;loadData()}
|
||||
const submitOrder=async()=>{await addOrderStats(orderForm);ElMessage.success(t('qualityEnhanced.addSuccess'));showOrder.value=false;loadData()}
|
||||
onMounted(()=>loadData())
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user