|
|
@@ -0,0 +1,400 @@
|
|
|
+<script setup lang="ts">
|
|
|
+import { type VxeFormListeners, type VxeFormProps, VxeUI, type VxeGridProps } from 'vxe-pc-ui';
|
|
|
+import { usePagination, useRequest } from 'alova/client';
|
|
|
+import { notification } from 'ant-design-vue';
|
|
|
+import { getDictionaryMethod } from '@/request/api/dictionary.api';
|
|
|
+import dayjs from 'dayjs';
|
|
|
+import EditConfigured from '@/components/EditConfigured.vue';
|
|
|
+import EditMoreConfigured from '@/components/EditMoreConfigured.vue';
|
|
|
+import { analysisRequestData, type FlowRequestData } from '@/pages/aio/flow-config/index';
|
|
|
+
|
|
|
+defineOptions({ name: 'EquipmentConfiguredPage' });
|
|
|
+
|
|
|
+import type { DeviceManageModel, DeviceManageQuery } from '@/model/device.model';
|
|
|
+
|
|
|
+// 接口数据
|
|
|
+import { deviceManageMethod, updateDeviceRegisterOrganizationMethod } from '@/request/api/device.api';
|
|
|
+import { branchMethod } from '@/request/api/system.api';
|
|
|
+// 获取组织树
|
|
|
+const { data: branch, loading: branchLoading } = useRequest(branchMethod(0, 1, 1));
|
|
|
+
|
|
|
+const model = shallowRef<DeviceManageQuery>();
|
|
|
+
|
|
|
+// 获取设备类型
|
|
|
+const deviceTypes = ref<{ id: string; name: string }[]>([]);
|
|
|
+const deviceTypesLoading = ref(false);
|
|
|
+
|
|
|
+// 日期验证
|
|
|
+const updateTimeStart = ref<string>('');
|
|
|
+const updateTimeEnd = ref<string>('');
|
|
|
+// 禁用结束时间的日期(早于开始时间的日期)
|
|
|
+function disabledEndDate(current: any) {
|
|
|
+ if (!updateTimeStart.value) return false;
|
|
|
+ return current && current < dayjs(updateTimeStart.value);
|
|
|
+}
|
|
|
+
|
|
|
+const searchFormProps = reactive<VxeFormProps<DeviceManageQuery>>({
|
|
|
+ titleWidth: 100,
|
|
|
+ titleAlign: 'right',
|
|
|
+ titleColon: true,
|
|
|
+ data: {},
|
|
|
+ items: [
|
|
|
+ {
|
|
|
+ field: 'deviceCode',
|
|
|
+ title: '设备ID',
|
|
|
+ span: 6,
|
|
|
+ itemRender: { name: 'VxeInput', props: { placeholder: '请输入' } },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: 'orgId',
|
|
|
+ title: '组织名称',
|
|
|
+ span: 6,
|
|
|
+ itemRender: {
|
|
|
+ name: 'VxeTreeSelect',
|
|
|
+ props: {
|
|
|
+ loading: computed(() => branchLoading.value),
|
|
|
+ options: computed(() => branch.value),
|
|
|
+ optionProps: { value: 'id', label: 'label' },
|
|
|
+ clearable: true,
|
|
|
+ },
|
|
|
+ events: {
|
|
|
+ change(val: any) {
|
|
|
+ insArr.value = [];
|
|
|
+ if (val.data.orgId) {
|
|
|
+ // 清空表单中的机构名称字段
|
|
|
+ if (model.value) {
|
|
|
+ model.value.institutionId = '';
|
|
|
+ }
|
|
|
+ getInstitution(val.data.orgId);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: 'institutionId',
|
|
|
+ title: '机构名称',
|
|
|
+ span: 6,
|
|
|
+ itemRender: {
|
|
|
+ name: 'VxeTreeSelect',
|
|
|
+ props: {
|
|
|
+ loading: computed(() => insLoading.value),
|
|
|
+ options: computed(() => insArr.value),
|
|
|
+ optionProps: { value: 'id', label: 'label' },
|
|
|
+ clearable: true,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: 'isHaveResume',
|
|
|
+ title: '是否配置',
|
|
|
+ span: 6,
|
|
|
+ itemRender: {
|
|
|
+ name: 'VxeRadioGroup',
|
|
|
+ options: [
|
|
|
+ { label: '已配置', value: 'true' },
|
|
|
+ { label: '未配置', value: 'false' },
|
|
|
+ ],
|
|
|
+ props: {
|
|
|
+ strict: false,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+
|
|
|
+ {
|
|
|
+ field: 'updateBy',
|
|
|
+ title: '修改人',
|
|
|
+ span: 6,
|
|
|
+ itemRender: { name: 'VxeInput', props: { placeholder: '请输入' } },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: 'updateTime',
|
|
|
+ title: '修改时间',
|
|
|
+ span: 10,
|
|
|
+ slots: {
|
|
|
+ default: 'createTimes',
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: 'action',
|
|
|
+ span: 6,
|
|
|
+ itemRender: {
|
|
|
+ name: 'VxeButtonGroup',
|
|
|
+ options: [
|
|
|
+ { name: 'submits', type: 'submit', content: '查询', status: 'primary' },
|
|
|
+ { name: 'reset', type: 'reset', content: '清空', status: 'warning' },
|
|
|
+ { name: 'config', content: '配置', status: 'primary' },
|
|
|
+ ],
|
|
|
+ events: {
|
|
|
+ click(slotParams, { name }) {
|
|
|
+ if (name === 'config') {
|
|
|
+ importOrganization();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ ],
|
|
|
+});
|
|
|
+const insLoading = ref(false);
|
|
|
+const insArr = ref<any[]>([]);
|
|
|
+async function getInstitution(orgId: string | number) {
|
|
|
+ insLoading.value = true;
|
|
|
+ const res = await branchMethod(1, 0, Number(orgId));
|
|
|
+ if (res && res.length > 0) {
|
|
|
+ insArr.value = res;
|
|
|
+ }
|
|
|
+ insLoading.value = false;
|
|
|
+}
|
|
|
+const searchFormEmits: VxeFormListeners<DeviceManageQuery> = {
|
|
|
+ // 查询设备登记
|
|
|
+ submit({ data }) {
|
|
|
+ model.value = {
|
|
|
+ ...data,
|
|
|
+ updateTimeStart: updateTimeStart.value ? dayjs(updateTimeStart.value).format('YYYY-MM-DD HH:mm:ss') : '',
|
|
|
+ updateTimeEnd: updateTimeEnd.value ? dayjs(updateTimeEnd.value).format('YYYY-MM-DD HH:mm:ss') : '',
|
|
|
+ } as any;
|
|
|
+ },
|
|
|
+ // 重置
|
|
|
+ reset({ data }) {
|
|
|
+ model.value = { ...data } as any;
|
|
|
+ updateTimeStart.value = '';
|
|
|
+ updateTimeEnd.value = '';
|
|
|
+ },
|
|
|
+};
|
|
|
+// 设备列表
|
|
|
+const gridRef = ref<DeviceManageModel>();
|
|
|
+const gridOptions = reactive<VxeGridProps<DeviceManageModel>>({
|
|
|
+ id: 'tag-list',
|
|
|
+ border: true,
|
|
|
+ showOverflow: true,
|
|
|
+ height: 'auto',
|
|
|
+ autoResize: false,
|
|
|
+ syncResize: true,
|
|
|
+ scrollY: { enabled: true, gt: 0 },
|
|
|
+ toolbarConfig: {
|
|
|
+ custom: true,
|
|
|
+ zoom: true,
|
|
|
+ slots: {
|
|
|
+ tools: 'toolbar-extra',
|
|
|
+ },
|
|
|
+ },
|
|
|
+ columnConfig: {
|
|
|
+ resizable: true,
|
|
|
+ },
|
|
|
+ customConfig: {
|
|
|
+ storage: true,
|
|
|
+ },
|
|
|
+ columns: [
|
|
|
+ { type: 'checkbox', width: 60, fixed: 'left', title: '', align: 'center' },
|
|
|
+ { field: 'orgName', title: '组织名称' },
|
|
|
+ { field: 'warrant', title: '设备ID' },
|
|
|
+ {
|
|
|
+ title: '流程配置',
|
|
|
+ align: 'center',
|
|
|
+ children: [
|
|
|
+ { field: 'isPatientFile', title: '建档', formatter: (p: any) => yesNoFormatter(p.row.tabletSetsDetailResume.isPatientFile) },
|
|
|
+ { field: 'isTonguefaceUpload', title: '舌面诊', formatter: (p: any) => yesNoFormatter(p.row.tabletSetsDetailResume.isTonguefaceUpload) },
|
|
|
+ { field: 'tonguefaceUploadResultShowType', title: '舌面分析报告', formatter: (p: any) => showTypeFormatter(p.row.tabletSetsDetailResume.tonguefaceUploadResultShowType) },
|
|
|
+ { field: 'puisPulseUploadlse', title: '脉诊', formatter: (p: any) => yesNoFormatter(p.row.tabletSetsDetailResume.isPulseUpload) },
|
|
|
+ { field: 'pulseReportShowType', title: '脉象分析报告', formatter: (p: any) => showTypeFormatter(p.row.tabletSetsDetailResume.pulseReportShowType) },
|
|
|
+ { field: 'isTonguefaceAnalysis', title: '问诊', formatter: (p: any) => yesNoFormatter(p.row.tabletSetsDetailResume.isTonguefaceAnalysis) },
|
|
|
+ { field: 'healthAnalysisReportShowType', title: '健康分析报告', formatter: (p: any) => showTypeFormatter(p.row.tabletSetsDetailResume.healthAnalysisReportShowType) },
|
|
|
+ { field: 'isHealthAnalysisScheme', title: '调理方案', formatter: (p: any) => yesNoFormatter(p.row.tabletSetsDetailResume.isHealthAnalysisScheme) },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ { field: 'updateBy', title: '修改人' },
|
|
|
+ { field: 'updateTime', title: '修改时间' },
|
|
|
+ { field: 'remark', title: '备注' },
|
|
|
+ {
|
|
|
+ field: 'action',
|
|
|
+ title: '操作',
|
|
|
+ align: 'center',
|
|
|
+ width: 100,
|
|
|
+ showOverflow: false,
|
|
|
+ cellRender: {
|
|
|
+ name: 'VxeButtonGroup',
|
|
|
+ props: { mode: 'text' },
|
|
|
+ options: [{ content: '编辑', status: 'primary', name: 'editConfigured' }],
|
|
|
+ events: {
|
|
|
+ click({ row }: any, { name }: any) {
|
|
|
+ if (name === 'editConfigured') {
|
|
|
+ editConfigured(row as any);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ data: [],
|
|
|
+});
|
|
|
+const gridEvents: any = {};
|
|
|
+
|
|
|
+// 分页
|
|
|
+const { loading, page, pageSize, total, onSuccess, refresh } = usePagination((page, size) => deviceManageMethod(page, size, model.value), {
|
|
|
+ initialData: { data: [], total: 0 },
|
|
|
+ initialPage: 1,
|
|
|
+ initialPageSize: 100,
|
|
|
+ watchingStates: [model],
|
|
|
+ immediate: false,
|
|
|
+});
|
|
|
+onSuccess(({ data: { data } }) => {
|
|
|
+ console.log(data, '获取数据');
|
|
|
+ gridRef.value?.loadData(data);
|
|
|
+});
|
|
|
+
|
|
|
+// 获取设备类型
|
|
|
+async function getDeviceType() {
|
|
|
+ deviceTypesLoading.value = true;
|
|
|
+ const res = await getDictionaryMethod('fdhb_device_type');
|
|
|
+ if (res && res.length > 0) {
|
|
|
+ deviceTypes.value = res.map((item: any) => ({
|
|
|
+ id: item.value,
|
|
|
+ name: item.label,
|
|
|
+ }));
|
|
|
+ }
|
|
|
+ deviceTypesLoading.value = false;
|
|
|
+}
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ getDeviceType();
|
|
|
+ model.value = toRaw(searchFormProps.data);
|
|
|
+});
|
|
|
+
|
|
|
+// 表格显示格式化
|
|
|
+function yesNoFormatter(value: any) {
|
|
|
+ if (value === true) return '有';
|
|
|
+ if (value === false || value == null) return '无';
|
|
|
+ return String(value ?? '无');
|
|
|
+}
|
|
|
+function showTypeFormatter(value: any) {
|
|
|
+ // 与截图文案对应:"完整展示" / "无"
|
|
|
+ if (value === '1') return '完整展示';
|
|
|
+ if (value === '2') return '扫码查看';
|
|
|
+ if (!value || value === '0') return '无';
|
|
|
+ return String(value);
|
|
|
+}
|
|
|
+
|
|
|
+// 编辑辨识仪配置
|
|
|
+function editConfigured(model?: DeviceManageModel) {
|
|
|
+ VxeUI.modal.open({
|
|
|
+ // title: model?.id ? `修改配置` : `新增配置`,
|
|
|
+ title: `修改配置`,
|
|
|
+ // height: 850,
|
|
|
+ // width: 900,
|
|
|
+ fullscreen: true,
|
|
|
+ escClosable: true,
|
|
|
+ destroyOnClose: true,
|
|
|
+ id: `equirement-modal`,
|
|
|
+ remember: true,
|
|
|
+ storage: true,
|
|
|
+ slots: {
|
|
|
+ default() {
|
|
|
+ return h(EditConfigured, {
|
|
|
+ data: model,
|
|
|
+ onSubmit() {
|
|
|
+ refresh(page.value);
|
|
|
+ VxeUI.modal.close(`equirement-modal`);
|
|
|
+ },
|
|
|
+ } as any);
|
|
|
+ },
|
|
|
+ },
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+// 批量修改
|
|
|
+function importOrganization() {
|
|
|
+ const selectedRows = (gridRef.value?.getCheckboxRecords() as any[]) || [];
|
|
|
+ if (selectedRows.length === 0) {
|
|
|
+ notification.error({ message: '请先选择设备' });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ VxeUI.modal.open({
|
|
|
+ title: '批量修改',
|
|
|
+ fullscreen: true,
|
|
|
+ escClosable: true,
|
|
|
+ destroyOnClose: true,
|
|
|
+ id: 'import-more-configured',
|
|
|
+ remember: true,
|
|
|
+ storage: true,
|
|
|
+ slots: {
|
|
|
+ default() {
|
|
|
+ return h(EditMoreConfigured, {
|
|
|
+ data: selectedRows,
|
|
|
+ onSubmit() {
|
|
|
+ refresh(page.value);
|
|
|
+ VxeUI.modal.close('import-more-configured');
|
|
|
+ },
|
|
|
+ // onSubmit(org: any) {
|
|
|
+ // const deviceIds = selectedRows.map((item: DeviceManageModel) => item.id);
|
|
|
+ // batchUpdateDeviceManageMethod({ deviceIds, orgId: org.orgId, institutionId: org.institutionId })
|
|
|
+ // .then(() => {
|
|
|
+ // notification.success({ message: '批量修改成功' });
|
|
|
+ // refresh(page.value);
|
|
|
+ // VxeUI.modal.close('import-more-configured');
|
|
|
+ // })
|
|
|
+ // .catch(() => {
|
|
|
+ // notification.error({ message: '批量修改失败' });
|
|
|
+ // });
|
|
|
+ // },
|
|
|
+ });
|
|
|
+ },
|
|
|
+ },
|
|
|
+ });
|
|
|
+}
|
|
|
+</script>
|
|
|
+<template>
|
|
|
+ <div class="page-container flex flex-col">
|
|
|
+ <header class="flex-none mt-4">
|
|
|
+ <vxe-form v-bind="searchFormProps" v-on="searchFormEmits">
|
|
|
+ <template #createTimes>
|
|
|
+ <div class="date-range-container">
|
|
|
+ <a-date-picker v-model:value="updateTimeStart" placeholder="请选择开始时间" style="flex: 1" :show-time="{ format: 'HH:mm' }" />
|
|
|
+ <span class="date-separator">至</span>
|
|
|
+ <a-date-picker v-model:value="updateTimeEnd" placeholder="请选择结束时间" style="flex: 1" :disabledDate="disabledEndDate" :show-time="{ format: 'HH:mm' }" />
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </vxe-form>
|
|
|
+ </header>
|
|
|
+ <main class="flex-auto overflow-hidden">
|
|
|
+ <vxe-grid ref="gridRef" v-bind="gridOptions" v-on="gridEvents" :loading="loading">
|
|
|
+ <template #toolbar-extra>
|
|
|
+ <vxe-button style="margin-right: 12px" icon="vxe-icon-repeat" circle @click="refresh(page)"></vxe-button>
|
|
|
+ </template>
|
|
|
+ </vxe-grid>
|
|
|
+ </main>
|
|
|
+ <footer class="flex-none">
|
|
|
+ <vxe-pager
|
|
|
+ v-model:current-page="page"
|
|
|
+ v-model:page-size="pageSize"
|
|
|
+ :total="total"
|
|
|
+ :layouts="['Home', 'PrevJump', 'PrevPage', 'Number', 'NextPage', 'NextJump', 'End', 'Sizes', 'FullJump', 'Total']"
|
|
|
+ />
|
|
|
+ </footer>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+<style scoped lang="scss">
|
|
|
+.page-container {
|
|
|
+ padding: 0 24px;
|
|
|
+ max-height: var(--page-main-container);
|
|
|
+}
|
|
|
+.date-range-container {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 12px;
|
|
|
+ width: 100%;
|
|
|
+
|
|
|
+ .vxe-input {
|
|
|
+ flex: 1;
|
|
|
+ min-width: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .date-separator {
|
|
|
+ color: #666;
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: 500;
|
|
|
+ white-space: nowrap;
|
|
|
+ padding: 0 8px;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|