feat: VIP功能绑定、VIP病历模块、字典模块、传方按钮移动到顶部导航栏
This commit is contained in:
27
apps/web-antd/src/views/system/dict/disease/api/index.ts
Normal file
27
apps/web-antd/src/views/system/dict/disease/api/index.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* 疾病诊断字典 API(yii_disease)
|
||||
*/
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
const prefix = 'disease-dict/';
|
||||
|
||||
export async function getDiseaseDictList(data: any) {
|
||||
return requestClient.get<any>(`${prefix}list`, { params: data });
|
||||
}
|
||||
|
||||
export async function createDiseaseDict(data: Record<string, any>) {
|
||||
return requestClient.post<any>(`${prefix}create`, data);
|
||||
}
|
||||
|
||||
export async function updateDiseaseDict(data: Record<string, any>) {
|
||||
return requestClient.post<any>(`${prefix}update`, data);
|
||||
}
|
||||
|
||||
export async function deleteDiseaseDict(data: { ids: number[] }) {
|
||||
return requestClient.post<any>(`${prefix}delete`, data);
|
||||
}
|
||||
|
||||
/** 同步空拼音首拼/全拼 */
|
||||
export async function syncDiseaseDictPinyin() {
|
||||
return requestClient.post<any>(`${prefix}sync-pinyin`, {});
|
||||
}
|
||||
269
apps/web-antd/src/views/system/dict/disease/index.vue
Normal file
269
apps/web-antd/src/views/system/dict/disease/index.vue
Normal file
@@ -0,0 +1,269 @@
|
||||
<script lang="ts" setup>
|
||||
/**
|
||||
* 疾病诊断字典(yii_disease)
|
||||
* 挂在字典管理下,维护接诊诊断库
|
||||
*/
|
||||
import type { VxeGridListeners } from '#/adapter/vxe-table';
|
||||
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { Page, useVbenModal } from '@vben/common-ui';
|
||||
|
||||
import { Button, message, Modal as AntModal } from 'ant-design-vue';
|
||||
|
||||
import { useVbenForm } from '#/adapter/form';
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
import { TableAction } from '#/components/table-action';
|
||||
|
||||
import {
|
||||
createDiseaseDict,
|
||||
deleteDiseaseDict,
|
||||
getDiseaseDictList,
|
||||
syncDiseaseDictPinyin,
|
||||
updateDiseaseDict,
|
||||
} from './api';
|
||||
|
||||
defineOptions({ name: 'DiseaseDict' });
|
||||
|
||||
const hasTopTableDropDownActions = ref(false);
|
||||
const syncing = ref(false);
|
||||
const isUpdate = ref(false);
|
||||
|
||||
const formOptions = {
|
||||
schema: [
|
||||
{
|
||||
component: 'VbenInput',
|
||||
fieldName: 'keyword',
|
||||
label: '关键字',
|
||||
componentProps: { placeholder: '名称/代码/首拼/全拼' },
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const gridOptions = {
|
||||
checkboxConfig: { highlight: true, labelField: '' },
|
||||
columns: [
|
||||
{ type: 'checkbox', width: 60 },
|
||||
{ field: 'id', title: 'ID', width: 80 },
|
||||
{ field: 'diagnose_code', title: '诊断代码', width: 120 },
|
||||
{ field: 'name', title: '诊断名称', minWidth: 180 },
|
||||
{ field: 'pinyin', title: '首拼', width: 120 },
|
||||
{ field: 'pinyin_full', title: '全拼', minWidth: 160 },
|
||||
{ field: 'major_number', title: '主编号', width: 120 },
|
||||
{ field: 'ref_number', title: '次编号', width: 120 },
|
||||
{ field: 'created_at', title: '创建时间', width: 170 },
|
||||
{ title: '操作', slots: { default: 'action' }, width: 140, fixed: 'right' },
|
||||
],
|
||||
keepSource: true,
|
||||
pagerConfig: {},
|
||||
proxyConfig: {
|
||||
ajax: {
|
||||
query: async ({ page }: any, formValues: any) => {
|
||||
return await getDiseaseDictList({
|
||||
page: page.currentPage,
|
||||
pageSize: page.pageSize,
|
||||
...formValues,
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
height: 'auto',
|
||||
toolbarConfig: {
|
||||
search: true,
|
||||
refresh: true,
|
||||
slots: { buttons: 'toolbar-buttons' },
|
||||
},
|
||||
};
|
||||
|
||||
const gridEvents: VxeGridListeners<any> = {
|
||||
checkboxChange() {
|
||||
hasTopTableDropDownActions.value =
|
||||
gridApi.grid.getCheckboxRecords().length > 0;
|
||||
},
|
||||
checkboxAll() {
|
||||
hasTopTableDropDownActions.value =
|
||||
gridApi.grid.getCheckboxRecords().length > 0;
|
||||
},
|
||||
};
|
||||
|
||||
const [Grid, gridApi] = useVbenVxeGrid({
|
||||
formOptions,
|
||||
gridOptions: gridOptions as any,
|
||||
gridEvents,
|
||||
});
|
||||
|
||||
const [Form, formApi] = useVbenForm({
|
||||
wrapperClass: 'grid-cols-12',
|
||||
commonConfig: {
|
||||
formItemClass: 'col-span-12',
|
||||
componentProps: { class: 'w-full' },
|
||||
},
|
||||
layout: 'horizontal',
|
||||
schema: [
|
||||
{
|
||||
component: 'VbenInput',
|
||||
fieldName: 'id',
|
||||
label: 'ID',
|
||||
dependencies: { show: false, triggerFields: ['id'] },
|
||||
},
|
||||
{
|
||||
component: 'VbenInput',
|
||||
fieldName: 'name',
|
||||
label: '诊断名称',
|
||||
rules: 'required',
|
||||
},
|
||||
{
|
||||
component: 'VbenInput',
|
||||
fieldName: 'diagnose_code',
|
||||
label: '诊断代码',
|
||||
formItemClass: 'col-span-6',
|
||||
},
|
||||
{
|
||||
component: 'VbenInput',
|
||||
fieldName: 'major_number',
|
||||
label: '主编号',
|
||||
formItemClass: 'col-span-6',
|
||||
},
|
||||
{
|
||||
component: 'VbenInput',
|
||||
fieldName: 'ref_number',
|
||||
label: '次编号',
|
||||
formItemClass: 'col-span-6',
|
||||
},
|
||||
{
|
||||
component: 'VbenInput',
|
||||
fieldName: 'pinyin',
|
||||
label: '拼音首拼',
|
||||
formItemClass: 'col-span-6',
|
||||
componentProps: { placeholder: '可留空,保存时按名称自动生成' },
|
||||
},
|
||||
{
|
||||
component: 'VbenInput',
|
||||
fieldName: 'pinyin_full',
|
||||
label: '拼音全拼',
|
||||
componentProps: { placeholder: '可留空,保存时按名称自动生成' },
|
||||
},
|
||||
],
|
||||
showDefaultActions: false,
|
||||
});
|
||||
|
||||
const [FormModal, formModalApi] = useVbenModal({
|
||||
class: 'w-[640px]',
|
||||
draggable: true,
|
||||
onConfirm: async () => {
|
||||
const e = await formApi.validate();
|
||||
if (!e.valid) return;
|
||||
const values = await formApi.getValues();
|
||||
formModalApi.setState({ confirmLoading: true });
|
||||
try {
|
||||
if (isUpdate.value) {
|
||||
await updateDiseaseDict(values);
|
||||
} else {
|
||||
await createDiseaseDict(values);
|
||||
}
|
||||
message.success('保存成功');
|
||||
gridApi.query();
|
||||
formModalApi.close();
|
||||
} finally {
|
||||
formModalApi.setState({ confirmLoading: false });
|
||||
}
|
||||
},
|
||||
onOpenChange(isOpen: boolean) {
|
||||
if (!isOpen) {
|
||||
formApi.resetForm();
|
||||
return;
|
||||
}
|
||||
const data = formModalApi.getData<{ values?: any; update?: boolean }>();
|
||||
isUpdate.value = !!data?.update;
|
||||
if (data?.values && data.update) {
|
||||
formApi.setValues({ ...data.values });
|
||||
} else {
|
||||
formApi.resetForm();
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
function showModal(row: any = {}, update = false) {
|
||||
formModalApi.setData({ values: row, update });
|
||||
formModalApi.open();
|
||||
}
|
||||
|
||||
async function handleDelete(ids: number[]) {
|
||||
await deleteDiseaseDict({ ids });
|
||||
message.success('删除成功');
|
||||
gridApi.query();
|
||||
}
|
||||
|
||||
/** 手动同步空拼音(疾病库量大,可能稍慢) */
|
||||
function handleSyncPinyin() {
|
||||
AntModal.confirm({
|
||||
title: '同步拼音',
|
||||
content:
|
||||
'将扫描疾病诊断中首拼或全拼为空的记录并自动生成,已有值不会覆盖。确认执行?',
|
||||
onOk: async () => {
|
||||
syncing.value = true;
|
||||
try {
|
||||
const res = await syncDiseaseDictPinyin();
|
||||
message.success(
|
||||
`同步完成:更新 ${Number(res?.updated || 0)} 条,跳过 ${Number(res?.skipped || 0)} 条`,
|
||||
);
|
||||
gridApi.query();
|
||||
} finally {
|
||||
syncing.value = false;
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<Page auto-content-height title="疾病诊断">
|
||||
<FormModal :title="`${isUpdate ? '编辑' : '新增'}疾病诊断`">
|
||||
<Form />
|
||||
</FormModal>
|
||||
<Grid>
|
||||
<template #toolbar-buttons>
|
||||
<TableAction
|
||||
:actions="[
|
||||
{
|
||||
label: '新增',
|
||||
type: 'primary',
|
||||
onClick: () => showModal({}, false),
|
||||
},
|
||||
{
|
||||
label: '批量删除',
|
||||
danger: true,
|
||||
ifShow: () => hasTopTableDropDownActions,
|
||||
popConfirm: {
|
||||
title: '确认删除所选?',
|
||||
confirm: () => {
|
||||
const ids = gridApi.grid
|
||||
.getCheckboxRecords()
|
||||
.map((r: any) => r.id);
|
||||
handleDelete(ids);
|
||||
},
|
||||
},
|
||||
},
|
||||
]"
|
||||
/>
|
||||
<Button class="ml-2" :loading="syncing" @click="handleSyncPinyin">
|
||||
同步拼音
|
||||
</Button>
|
||||
</template>
|
||||
<template #action="{ row }">
|
||||
<TableAction
|
||||
:actions="[
|
||||
{ label: '编辑', onClick: () => showModal(row, true) },
|
||||
{
|
||||
label: '删除',
|
||||
danger: true,
|
||||
popConfirm: {
|
||||
title: '确认删除?',
|
||||
confirm: () => handleDelete([row.id]),
|
||||
},
|
||||
},
|
||||
]"
|
||||
/>
|
||||
</template>
|
||||
</Grid>
|
||||
</Page>
|
||||
</template>
|
||||
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* 公共医嘱字典 API(xk_doctor_order)
|
||||
*/
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
const prefix = 'doctor-order/';
|
||||
|
||||
export async function getDoctorOrderDictList(data: any) {
|
||||
return requestClient.get<any>(`${prefix}list`, { params: data });
|
||||
}
|
||||
|
||||
export async function createDoctorOrderDict(data: Record<string, any>) {
|
||||
return requestClient.post<any>(`${prefix}create`, data);
|
||||
}
|
||||
|
||||
export async function updateDoctorOrderDict(data: Record<string, any>) {
|
||||
return requestClient.post<any>(`${prefix}update`, data);
|
||||
}
|
||||
|
||||
export async function deleteDoctorOrderDict(data: { ids?: number[]; id?: number }) {
|
||||
return requestClient.post<any>(`${prefix}delete`, data);
|
||||
}
|
||||
|
||||
/** 同步空拼音首拼/全拼 */
|
||||
export async function syncDoctorOrderDictPinyin() {
|
||||
return requestClient.post<any>(`${prefix}sync-pinyin`, {});
|
||||
}
|
||||
235
apps/web-antd/src/views/system/dict/doctor-order/index.vue
Normal file
235
apps/web-antd/src/views/system/dict/doctor-order/index.vue
Normal file
@@ -0,0 +1,235 @@
|
||||
<script lang="ts" setup>
|
||||
/**
|
||||
* 公共医嘱字典(xk_doctor_order)
|
||||
* 挂在字典管理下,维护接诊公共医嘱
|
||||
*/
|
||||
import type { VxeGridListeners } from '#/adapter/vxe-table';
|
||||
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { Page, useVbenModal } from '@vben/common-ui';
|
||||
|
||||
import { Button, message, Modal as AntModal } from 'ant-design-vue';
|
||||
|
||||
import { useVbenForm } from '#/adapter/form';
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
import { TableAction } from '#/components/table-action';
|
||||
|
||||
import {
|
||||
createDoctorOrderDict,
|
||||
deleteDoctorOrderDict,
|
||||
getDoctorOrderDictList,
|
||||
syncDoctorOrderDictPinyin,
|
||||
updateDoctorOrderDict,
|
||||
} from './api';
|
||||
|
||||
defineOptions({ name: 'DoctorOrderDict' });
|
||||
|
||||
const hasTopTableDropDownActions = ref(false);
|
||||
const syncing = ref(false);
|
||||
const isUpdate = ref(false);
|
||||
|
||||
const formOptions = {
|
||||
schema: [
|
||||
{
|
||||
component: 'VbenInput',
|
||||
fieldName: 'keyword',
|
||||
label: '关键字',
|
||||
componentProps: { placeholder: '内容/首拼/全拼' },
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const gridOptions = {
|
||||
checkboxConfig: { highlight: true, labelField: '' },
|
||||
columns: [
|
||||
{ type: 'checkbox', width: 60 },
|
||||
{ field: 'id', title: 'ID', width: 80 },
|
||||
{ field: 'name', title: '医嘱内容', minWidth: 220 },
|
||||
{ field: 'pinyin_initials', title: '首拼', width: 120 },
|
||||
{ field: 'pinyin_full', title: '全拼', minWidth: 160 },
|
||||
{ field: 'created_at', title: '创建时间', width: 170 },
|
||||
{ title: '操作', slots: { default: 'action' }, width: 140, fixed: 'right' },
|
||||
],
|
||||
keepSource: true,
|
||||
pagerConfig: {},
|
||||
proxyConfig: {
|
||||
ajax: {
|
||||
query: async ({ page }: any, formValues: any) => {
|
||||
return await getDoctorOrderDictList({
|
||||
page: page.currentPage,
|
||||
pageSize: page.pageSize,
|
||||
...formValues,
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
height: 'auto',
|
||||
toolbarConfig: {
|
||||
search: true,
|
||||
refresh: true,
|
||||
slots: { buttons: 'toolbar-buttons' },
|
||||
},
|
||||
};
|
||||
|
||||
const gridEvents: VxeGridListeners<any> = {
|
||||
checkboxChange() {
|
||||
hasTopTableDropDownActions.value =
|
||||
gridApi.grid.getCheckboxRecords().length > 0;
|
||||
},
|
||||
checkboxAll() {
|
||||
hasTopTableDropDownActions.value =
|
||||
gridApi.grid.getCheckboxRecords().length > 0;
|
||||
},
|
||||
};
|
||||
|
||||
const [Grid, gridApi] = useVbenVxeGrid({
|
||||
formOptions,
|
||||
gridOptions: gridOptions as any,
|
||||
gridEvents,
|
||||
});
|
||||
|
||||
const [Form, formApi] = useVbenForm({
|
||||
wrapperClass: 'grid-cols-12',
|
||||
commonConfig: {
|
||||
formItemClass: 'col-span-12',
|
||||
componentProps: { class: 'w-full' },
|
||||
},
|
||||
layout: 'horizontal',
|
||||
schema: [
|
||||
{
|
||||
component: 'VbenInput',
|
||||
fieldName: 'id',
|
||||
label: 'ID',
|
||||
dependencies: { show: false, triggerFields: ['id'] },
|
||||
},
|
||||
{
|
||||
component: 'VbenInput',
|
||||
fieldName: 'name',
|
||||
label: '医嘱内容',
|
||||
rules: 'required',
|
||||
componentProps: { placeholder: '请输入医嘱内容' },
|
||||
},
|
||||
],
|
||||
showDefaultActions: false,
|
||||
});
|
||||
|
||||
const [FormModal, formModalApi] = useVbenModal({
|
||||
class: 'w-[560px]',
|
||||
draggable: true,
|
||||
onConfirm: async () => {
|
||||
const e = await formApi.validate();
|
||||
if (!e.valid) return;
|
||||
const values = await formApi.getValues();
|
||||
formModalApi.setState({ confirmLoading: true });
|
||||
try {
|
||||
if (isUpdate.value) {
|
||||
await updateDoctorOrderDict(values);
|
||||
} else {
|
||||
await createDoctorOrderDict(values);
|
||||
}
|
||||
message.success('保存成功');
|
||||
gridApi.query();
|
||||
formModalApi.close();
|
||||
} finally {
|
||||
formModalApi.setState({ confirmLoading: false });
|
||||
}
|
||||
},
|
||||
onOpenChange(isOpen: boolean) {
|
||||
if (!isOpen) {
|
||||
formApi.resetForm();
|
||||
return;
|
||||
}
|
||||
const data = formModalApi.getData<{ values?: any; update?: boolean }>();
|
||||
isUpdate.value = !!data?.update;
|
||||
if (data?.values && data.update) {
|
||||
formApi.setValues({ ...data.values });
|
||||
} else {
|
||||
formApi.resetForm();
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
function showModal(row: any = {}, update = false) {
|
||||
formModalApi.setData({ values: row, update });
|
||||
formModalApi.open();
|
||||
}
|
||||
|
||||
async function handleDelete(ids: number[]) {
|
||||
await deleteDoctorOrderDict({ ids });
|
||||
message.success('删除成功');
|
||||
gridApi.query();
|
||||
}
|
||||
|
||||
function handleSyncPinyin() {
|
||||
AntModal.confirm({
|
||||
title: '同步拼音',
|
||||
content:
|
||||
'将扫描公共医嘱中首拼或全拼为空的记录并自动生成,已有值不会覆盖。确认执行?',
|
||||
onOk: async () => {
|
||||
syncing.value = true;
|
||||
try {
|
||||
const res = await syncDoctorOrderDictPinyin();
|
||||
message.success(
|
||||
`同步完成:更新 ${Number(res?.updated || 0)} 条,跳过 ${Number(res?.skipped || 0)} 条`,
|
||||
);
|
||||
gridApi.query();
|
||||
} finally {
|
||||
syncing.value = false;
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<Page auto-content-height title="公共医嘱">
|
||||
<FormModal :title="`${isUpdate ? '编辑' : '新增'}公共医嘱`">
|
||||
<Form />
|
||||
</FormModal>
|
||||
<Grid>
|
||||
<template #toolbar-buttons>
|
||||
<TableAction
|
||||
:actions="[
|
||||
{
|
||||
label: '新增',
|
||||
type: 'primary',
|
||||
onClick: () => showModal({}, false),
|
||||
},
|
||||
{
|
||||
label: '批量删除',
|
||||
danger: true,
|
||||
ifShow: () => hasTopTableDropDownActions,
|
||||
popConfirm: {
|
||||
title: '确认删除所选?',
|
||||
confirm: () => {
|
||||
const ids = gridApi.grid
|
||||
.getCheckboxRecords()
|
||||
.map((r: any) => r.id);
|
||||
handleDelete(ids);
|
||||
},
|
||||
},
|
||||
},
|
||||
]"
|
||||
/>
|
||||
<Button class="ml-2" :loading="syncing" @click="handleSyncPinyin">
|
||||
同步拼音
|
||||
</Button>
|
||||
</template>
|
||||
<template #action="{ row }">
|
||||
<TableAction
|
||||
:actions="[
|
||||
{ label: '编辑', onClick: () => showModal(row, true) },
|
||||
{
|
||||
label: '删除',
|
||||
danger: true,
|
||||
popConfirm: {
|
||||
title: '确认删除?',
|
||||
confirm: () => handleDelete([row.id]),
|
||||
},
|
||||
},
|
||||
]"
|
||||
/>
|
||||
</template>
|
||||
</Grid>
|
||||
</Page>
|
||||
</template>
|
||||
34
apps/web-antd/src/views/system/dict/tcm/api/index.ts
Normal file
34
apps/web-antd/src/views/system/dict/tcm/api/index.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* 中医字典 API(疾病 / 治法 / 证候)
|
||||
*/
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
const prefix = 'tcm-dict/';
|
||||
|
||||
export type TcmDictType = 'diseases' | 'method' | 'syndrome';
|
||||
|
||||
export async function getTcmDictList(data: {
|
||||
type: TcmDictType;
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
keyword?: string;
|
||||
}) {
|
||||
return requestClient.get<any>(`${prefix}list`, { params: data });
|
||||
}
|
||||
|
||||
export async function createTcmDict(data: Record<string, any>) {
|
||||
return requestClient.post<any>(`${prefix}create`, data);
|
||||
}
|
||||
|
||||
export async function updateTcmDict(data: Record<string, any>) {
|
||||
return requestClient.post<any>(`${prefix}update`, data);
|
||||
}
|
||||
|
||||
export async function deleteTcmDict(data: { type: TcmDictType; ids: number[] }) {
|
||||
return requestClient.post<any>(`${prefix}delete`, data);
|
||||
}
|
||||
|
||||
/** 手动同步空拼音首拼 */
|
||||
export async function syncTcmDictPinyin(type: TcmDictType) {
|
||||
return requestClient.post<any>(`${prefix}sync-pinyin`, { type });
|
||||
}
|
||||
@@ -0,0 +1,275 @@
|
||||
<script lang="ts" setup>
|
||||
/**
|
||||
* 中医字典列表(疾病 / 治法 / 证候共用)
|
||||
* 支持 CRUD + 手动「同步拼音首拼」(仅补空值)
|
||||
*/
|
||||
import type { VxeGridListeners } from '#/adapter/vxe-table';
|
||||
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import { Page, useVbenModal } from '@vben/common-ui';
|
||||
|
||||
import { Button, message, Modal as AntModal } from 'ant-design-vue';
|
||||
|
||||
import { useVbenForm } from '#/adapter/form';
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
import { TableAction } from '#/components/table-action';
|
||||
|
||||
import {
|
||||
createTcmDict,
|
||||
deleteTcmDict,
|
||||
getTcmDictList,
|
||||
syncTcmDictPinyin,
|
||||
updateTcmDict,
|
||||
type TcmDictType,
|
||||
} from '../api';
|
||||
|
||||
const props = defineProps<{
|
||||
dictType: TcmDictType;
|
||||
pageTitle: string;
|
||||
pageName: string;
|
||||
}>();
|
||||
|
||||
defineOptions({ name: 'TcmDictListPage' });
|
||||
|
||||
const hasTopTableDropDownActions = ref(false);
|
||||
const syncing = ref(false);
|
||||
|
||||
const formOptions = {
|
||||
schema: [
|
||||
{
|
||||
component: 'VbenInput',
|
||||
fieldName: 'keyword',
|
||||
label: '关键字',
|
||||
componentProps: { placeholder: '名称/编码/首拼' },
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const gridOptions = computed(() => ({
|
||||
checkboxConfig: { highlight: true, labelField: '' },
|
||||
columns: [
|
||||
{ type: 'checkbox', width: 60 },
|
||||
{ field: 'id', title: 'ID', width: 80 },
|
||||
{ field: 'code', title: '代码', width: 120 },
|
||||
{ field: 'number', title: '编号', width: 120 },
|
||||
{ field: 'name', title: '名称', minWidth: 160 },
|
||||
{ field: 'alias', title: '别名', minWidth: 120 },
|
||||
{ field: 'initials_of_pinyin', title: '拼音首拼', width: 120 },
|
||||
{ field: 'pinyin_full', title: '拼音全拼', minWidth: 160 },
|
||||
{ field: 'created_at', title: '创建时间', width: 170 },
|
||||
{ title: '操作', slots: { default: 'action' }, width: 140, fixed: 'right' },
|
||||
],
|
||||
keepSource: true,
|
||||
pagerConfig: {},
|
||||
proxyConfig: {
|
||||
ajax: {
|
||||
query: async ({ page }: any, formValues: any) => {
|
||||
return await getTcmDictList({
|
||||
type: props.dictType,
|
||||
page: page.currentPage,
|
||||
pageSize: page.pageSize,
|
||||
...formValues,
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
height: 'auto',
|
||||
toolbarConfig: {
|
||||
search: true,
|
||||
refresh: true,
|
||||
slots: { buttons: 'toolbar-buttons' },
|
||||
},
|
||||
}));
|
||||
|
||||
const gridEvents: VxeGridListeners<any> = {
|
||||
checkboxChange() {
|
||||
hasTopTableDropDownActions.value =
|
||||
gridApi.grid.getCheckboxRecords().length > 0;
|
||||
},
|
||||
checkboxAll() {
|
||||
hasTopTableDropDownActions.value =
|
||||
gridApi.grid.getCheckboxRecords().length > 0;
|
||||
},
|
||||
};
|
||||
|
||||
const [Grid, gridApi] = useVbenVxeGrid({
|
||||
formOptions,
|
||||
gridOptions: gridOptions.value as any,
|
||||
gridEvents,
|
||||
});
|
||||
|
||||
const isUpdate = ref(false);
|
||||
const [Form, formApi] = useVbenForm({
|
||||
wrapperClass: 'grid-cols-12',
|
||||
commonConfig: {
|
||||
formItemClass: 'col-span-12',
|
||||
componentProps: { class: 'w-full' },
|
||||
},
|
||||
layout: 'horizontal',
|
||||
schema: [
|
||||
{
|
||||
component: 'VbenInput',
|
||||
fieldName: 'id',
|
||||
label: 'ID',
|
||||
dependencies: { show: false, triggerFields: ['id'] },
|
||||
},
|
||||
{
|
||||
component: 'VbenInput',
|
||||
fieldName: 'name',
|
||||
label: '名称',
|
||||
rules: 'required',
|
||||
},
|
||||
{
|
||||
component: 'VbenInput',
|
||||
fieldName: 'code',
|
||||
label: '代码',
|
||||
formItemClass: 'col-span-6',
|
||||
},
|
||||
{
|
||||
component: 'VbenInput',
|
||||
fieldName: 'number',
|
||||
label: '编号',
|
||||
formItemClass: 'col-span-6',
|
||||
},
|
||||
{
|
||||
component: 'VbenInput',
|
||||
fieldName: 'alias',
|
||||
label: '别名',
|
||||
},
|
||||
{
|
||||
component: 'VbenInput',
|
||||
fieldName: 'initials_of_pinyin',
|
||||
label: '拼音首拼',
|
||||
componentProps: { placeholder: '保存时按名称自动生成,可留空' },
|
||||
},
|
||||
{
|
||||
component: 'VbenInput',
|
||||
fieldName: 'pinyin_full',
|
||||
label: '拼音全拼',
|
||||
componentProps: { placeholder: '保存时按名称自动生成,可留空' },
|
||||
},
|
||||
],
|
||||
showDefaultActions: false,
|
||||
});
|
||||
|
||||
const [FormModal, formModalApi] = useVbenModal({
|
||||
class: 'w-[640px]',
|
||||
draggable: true,
|
||||
onConfirm: async () => {
|
||||
const e = await formApi.validate();
|
||||
if (!e.valid) return;
|
||||
const values = await formApi.getValues();
|
||||
formModalApi.setState({ confirmLoading: true });
|
||||
try {
|
||||
const payload = { ...values, type: props.dictType };
|
||||
if (isUpdate.value) {
|
||||
await updateTcmDict(payload);
|
||||
} else {
|
||||
await createTcmDict(payload);
|
||||
}
|
||||
message.success('保存成功');
|
||||
gridApi.query();
|
||||
formModalApi.close();
|
||||
} finally {
|
||||
formModalApi.setState({ confirmLoading: false });
|
||||
}
|
||||
},
|
||||
onOpenChange(isOpen: boolean) {
|
||||
if (!isOpen) {
|
||||
formApi.resetFields();
|
||||
return;
|
||||
}
|
||||
const data = formModalApi.getData<{ values?: any; update?: boolean }>();
|
||||
isUpdate.value = !!data?.update;
|
||||
if (data?.values && data.update) {
|
||||
formApi.setValues({ ...data.values });
|
||||
} else {
|
||||
formApi.resetFields();
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
function showModal(row: any = {}, update = false) {
|
||||
formModalApi.setData({ values: row, update });
|
||||
formModalApi.open();
|
||||
}
|
||||
|
||||
async function handleDelete(ids: number[]) {
|
||||
await deleteTcmDict({ type: props.dictType, ids });
|
||||
message.success('删除成功');
|
||||
gridApi.query();
|
||||
}
|
||||
|
||||
/** 手动同步:补全空首拼/全拼,并纠正名称含数字但旧拼音丢数字的脏数据 */
|
||||
function handleSyncPinyin() {
|
||||
AntModal.confirm({
|
||||
title: '同步拼音',
|
||||
content: `将扫描「${props.pageTitle}」中首拼/全拼为空(或含数字名称需纠正)的记录并自动生成。确认执行?`,
|
||||
onOk: async () => {
|
||||
syncing.value = true;
|
||||
try {
|
||||
const res = await syncTcmDictPinyin(props.dictType);
|
||||
message.success(
|
||||
`同步完成:更新 ${Number(res?.updated || 0)} 条,跳过 ${Number(res?.skipped || 0)} 条`,
|
||||
);
|
||||
gridApi.query();
|
||||
} finally {
|
||||
syncing.value = false;
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<Page auto-content-height :title="pageTitle">
|
||||
<FormModal :title="`${isUpdate ? '编辑' : '新增'}${pageTitle}`">
|
||||
<Form />
|
||||
</FormModal>
|
||||
<Grid>
|
||||
<template #toolbar-buttons>
|
||||
<TableAction
|
||||
:actions="[
|
||||
{
|
||||
label: '新增',
|
||||
type: 'primary',
|
||||
onClick: () => showModal({}, false),
|
||||
},
|
||||
{
|
||||
label: '批量删除',
|
||||
danger: true,
|
||||
ifShow: () => hasTopTableDropDownActions,
|
||||
popConfirm: {
|
||||
title: '确认删除所选?',
|
||||
confirm: () => {
|
||||
const ids = gridApi.grid
|
||||
.getCheckboxRecords()
|
||||
.map((r: any) => r.id);
|
||||
handleDelete(ids);
|
||||
},
|
||||
},
|
||||
},
|
||||
]"
|
||||
/>
|
||||
<Button class="ml-2" :loading="syncing" @click="handleSyncPinyin">
|
||||
同步拼音
|
||||
</Button>
|
||||
</template>
|
||||
<template #action="{ row }">
|
||||
<TableAction
|
||||
:actions="[
|
||||
{ label: '编辑', onClick: () => showModal(row, true) },
|
||||
{
|
||||
label: '删除',
|
||||
danger: true,
|
||||
popConfirm: {
|
||||
title: '确认删除?',
|
||||
confirm: () => handleDelete([row.id]),
|
||||
},
|
||||
},
|
||||
]"
|
||||
/>
|
||||
</template>
|
||||
</Grid>
|
||||
</Page>
|
||||
</template>
|
||||
15
apps/web-antd/src/views/system/dict/tcm/diseases/index.vue
Normal file
15
apps/web-antd/src/views/system/dict/tcm/diseases/index.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<script lang="ts" setup>
|
||||
/**
|
||||
* 中医疾病字典(xk_traditional_chinese_medicine_diseases)
|
||||
*/
|
||||
import TcmDictListPage from '../components/TcmDictListPage.vue';
|
||||
|
||||
defineOptions({ name: 'TcmDiseasesDict' });
|
||||
</script>
|
||||
<template>
|
||||
<TcmDictListPage
|
||||
dict-type="diseases"
|
||||
page-title="中医疾病"
|
||||
page-name="TcmDiseasesDict"
|
||||
/>
|
||||
</template>
|
||||
15
apps/web-antd/src/views/system/dict/tcm/method/index.vue
Normal file
15
apps/web-antd/src/views/system/dict/tcm/method/index.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<script lang="ts" setup>
|
||||
/**
|
||||
* 中医治法字典(xk_traditional_chinese_medicine_method)
|
||||
*/
|
||||
import TcmDictListPage from '../components/TcmDictListPage.vue';
|
||||
|
||||
defineOptions({ name: 'TcmMethodDict' });
|
||||
</script>
|
||||
<template>
|
||||
<TcmDictListPage
|
||||
dict-type="method"
|
||||
page-title="中医治法"
|
||||
page-name="TcmMethodDict"
|
||||
/>
|
||||
</template>
|
||||
15
apps/web-antd/src/views/system/dict/tcm/syndrome/index.vue
Normal file
15
apps/web-antd/src/views/system/dict/tcm/syndrome/index.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<script lang="ts" setup>
|
||||
/**
|
||||
* 中医证候字典(xk_traditional_chinese_medicine_syndrome)
|
||||
*/
|
||||
import TcmDictListPage from '../components/TcmDictListPage.vue';
|
||||
|
||||
defineOptions({ name: 'TcmSyndromeDict' });
|
||||
</script>
|
||||
<template>
|
||||
<TcmDictListPage
|
||||
dict-type="syndrome"
|
||||
page-title="中医证候"
|
||||
page-name="TcmSyndromeDict"
|
||||
/>
|
||||
</template>
|
||||
Reference in New Issue
Block a user