feat: 111
This commit is contained in:
@@ -23,14 +23,14 @@ const medicinalApi = {
|
||||
},
|
||||
|
||||
/** 获取药材消耗记录 */
|
||||
getConsumptionRecords(id: number) {
|
||||
return http.get<any>(`${id}/consumption-records`);
|
||||
getConsumptionRecords(params: { id: number; pageNum?: number; pageSize?: number }) {
|
||||
console.log("获取添加记录,请求参数=", params);
|
||||
return http.get<ResPage<any>>(`consumption-records`, params); // 透传分页参数
|
||||
},
|
||||
|
||||
/** 获取药材添加记录 */
|
||||
getAdditionRecords(id: number, params?: { pageNum?: number; pageSize?: number }) {
|
||||
// 注意:这里把 id 放到路径里,分页走 params
|
||||
return http.get<any>(`/${id}/addition-records`, { params });
|
||||
getAdditionRecords(params: { id: number; pageNum?: number; pageSize?: number }) {
|
||||
return http.get<ResPage<any>>(`addition-records`, params);
|
||||
},
|
||||
|
||||
/** 添加药材 */
|
||||
@@ -39,13 +39,13 @@ const medicinalApi = {
|
||||
},
|
||||
|
||||
/** 修改药材添加记录 */
|
||||
updateAdditionRecord(id: number, params: UpdateMedicinalAddLogInput) {
|
||||
return http.put(`addition-records/${id}`, params);
|
||||
updateAdditionRecord(params: UpdateMedicinalAddLogInput) {
|
||||
return http.post(`addition-records`, params);
|
||||
},
|
||||
|
||||
/** 删除药材添加记录 */
|
||||
deleteAdditionRecord(id: number) {
|
||||
return http.delete(`addition-records/${id}`);
|
||||
deleteAdditionRecord(params: { id: number }) {
|
||||
return http.post(`addition-delete`, params);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -62,14 +62,15 @@ export interface MedicinalInfo {
|
||||
export interface AddMedicinalInput {
|
||||
medicinalTypeId: number;
|
||||
addWeight: number;
|
||||
unitPrice: number;
|
||||
totalPrice: number;
|
||||
medicinalName: string;
|
||||
}
|
||||
|
||||
/** 修改添加记录 */
|
||||
export interface UpdateMedicinalAddLogInput {
|
||||
id: number;
|
||||
addWeight: number;
|
||||
unitPrice: number;
|
||||
totalPrice: number;
|
||||
}
|
||||
|
||||
export { medicinalApi };
|
||||
|
||||
@@ -1,41 +1,149 @@
|
||||
import { moduleRequest } from "@/api/request";
|
||||
import { ResPage } from "@/api/interface";
|
||||
|
||||
const http = moduleRequest("/biz/weibingju/prescription/");
|
||||
|
||||
// -----------------------------
|
||||
// 类型定义(对应后端 DTO)
|
||||
// -----------------------------
|
||||
|
||||
/** 人员类型 */
|
||||
export enum PersonType {
|
||||
Employee = 1,
|
||||
Relative = 2
|
||||
}
|
||||
|
||||
/** 处方列表 DTO */
|
||||
export interface PrescriptionDto {
|
||||
id: number;
|
||||
personId: number;
|
||||
personName: string;
|
||||
personType: PersonType;
|
||||
employeeName?: string;
|
||||
visitDate?: string;
|
||||
canEdit: boolean;
|
||||
}
|
||||
|
||||
/** 处方药材 DTO */
|
||||
export interface PrescriptionHerbDto {
|
||||
Id: number;
|
||||
medicinalName: string;
|
||||
amountG: number;
|
||||
note?: string;
|
||||
}
|
||||
|
||||
/** 人员详情 DTO */
|
||||
export interface PersonDetailDto {
|
||||
id?: number;
|
||||
name: string;
|
||||
age?: number;
|
||||
weight?: number;
|
||||
height?: number;
|
||||
isEmployee: boolean;
|
||||
employeeId?: number;
|
||||
employeeName?: string;
|
||||
relationShip?: number;
|
||||
relationShipName?: string;
|
||||
}
|
||||
|
||||
/** 处方详情 DTO */
|
||||
export interface PrescriptionDetailDto {
|
||||
id: number;
|
||||
person: PersonDetailDto;
|
||||
diagnosisResult: string;
|
||||
userMedicinaAdvice: string;
|
||||
visitDate?: string;
|
||||
herbs: PrescriptionHerbDto[];
|
||||
canEdit: boolean;
|
||||
}
|
||||
|
||||
/** 保存处方输入 DTO */
|
||||
export interface SavePrescriptionInput {
|
||||
id?: number;
|
||||
person: PersonInputDto;
|
||||
diagnosisResult: string;
|
||||
userMedicinaAdvice: string;
|
||||
visitDate?: string;
|
||||
herbs: PrescriptionHerbInputDto[];
|
||||
}
|
||||
|
||||
/** 人员输入 DTO */
|
||||
export interface PersonInputDto {
|
||||
id?: number;
|
||||
name: string;
|
||||
age?: number;
|
||||
weight?: number;
|
||||
height?: number;
|
||||
isEmployee: boolean;
|
||||
employeeId?: number;
|
||||
relationShip?: number;
|
||||
}
|
||||
|
||||
/** 处方药材输入 DTO */
|
||||
export interface PrescriptionHerbInputDto {
|
||||
Id: number;
|
||||
amountG: number;
|
||||
note?: string;
|
||||
}
|
||||
|
||||
/** 人员 DTO(列表用) */
|
||||
export interface PersonDto {
|
||||
id: number;
|
||||
name: string;
|
||||
age?: number;
|
||||
employeeId?: number;
|
||||
}
|
||||
|
||||
/** 添加人员输入 DTO */
|
||||
export interface AddPersonInput {
|
||||
name: string;
|
||||
age?: number;
|
||||
weight?: number;
|
||||
height?: number;
|
||||
isEmployee: boolean;
|
||||
employeeId?: number;
|
||||
relationShip?: number;
|
||||
}
|
||||
|
||||
/** 关系类型 DTO */
|
||||
export interface RelationTypeDto {
|
||||
id: number;
|
||||
name: string;
|
||||
}
|
||||
|
||||
// -----------------------------
|
||||
// API 方法(对应后端接口)
|
||||
// -----------------------------
|
||||
|
||||
const prescriptionApi = {
|
||||
/** 获取处方列表(分页) */
|
||||
/** 获取处方列表 */
|
||||
getList(params: any) {
|
||||
return http.get<any>("list", params);
|
||||
return http.get<ResPage<PrescriptionDto>>("list", params);
|
||||
},
|
||||
|
||||
/** 获取处方详情 */
|
||||
getDetail(params: any) {
|
||||
return http.get<any>("detail", params);
|
||||
getDetail(id: number) {
|
||||
return http.get<PrescriptionDetailDto>(`getprescriptiondetile?id=${id}`);
|
||||
},
|
||||
|
||||
/** 保存处方(新增/编辑) */
|
||||
save(params: any) {
|
||||
const url = params.id ? "edit" : "add";
|
||||
return http.post<any>(url, params);
|
||||
save(params: SavePrescriptionInput) {
|
||||
return http.post<number>("add", params);
|
||||
},
|
||||
|
||||
/** 获取人员列表 */
|
||||
getPersonList(params: any) {
|
||||
return http.get<any>("persons", params, { loading: false });
|
||||
getPersonList(params: { type?: PersonType; employeeId?: number }) {
|
||||
return http.get<PersonDto[]>("persons", params);
|
||||
},
|
||||
|
||||
/** 新增人员 */
|
||||
addPerson(params: any) {
|
||||
return http.post<any>("addpersons", params);
|
||||
/** 添加人员 */
|
||||
addPerson(params: AddPersonInput) {
|
||||
return http.post<number>("addpersons", params);
|
||||
},
|
||||
|
||||
/** 获取亲属关系列表 */
|
||||
/** 获取关系类型 */
|
||||
getRelationTypes() {
|
||||
return http.get<any>("relation-types", {}, { loading: false });
|
||||
},
|
||||
|
||||
/** 搜索药材 */
|
||||
searchMedicinals(params: any) {
|
||||
return http.get<any>("medicinals/search", params, { loading: false });
|
||||
return http.get<RelationTypeDto[]>("relation-types");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -15,5 +15,5 @@
|
||||
|
||||
export * from "./organization";
|
||||
export * from "./ops";
|
||||
export * from "./WeiBingJu/medicinal";
|
||||
export * from "./WeiBingJu/prescription";
|
||||
export * from "./weibingju/medicinal";
|
||||
export * from "./weibingju/prescription";
|
||||
|
||||
@@ -134,10 +134,12 @@ export default class RequestHttp {
|
||||
this.apiNameArray.forEach(apiName => {
|
||||
let responseApiArray = responseUrl.split("/"); //分割
|
||||
let method = responseApiArray[responseApiArray.length - 1]; //取最后一个
|
||||
console.log("method=", method);
|
||||
console.log("noMessageApiNameArray=", this.noMessageApiNameArray);
|
||||
let result = this.noMessageApiNameArray.includes(method); //判断是否在不提示的数组中
|
||||
if (!result && responseUrl.includes(apiName)) {
|
||||
//如果不在不提示的数组中并且请求地址包含指定的方法
|
||||
ElMessage.success(data.msg);
|
||||
// ElMessage.success(data.msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Vendored
+65
-80
@@ -6,88 +6,73 @@
|
||||
// biome-ignore lint: disable
|
||||
export {}
|
||||
declare global {
|
||||
const EffectScope: (typeof import("vue"))["EffectScope"];
|
||||
const ElMessage: (typeof import("element-plus/es"))["ElMessage"];
|
||||
const ElMessageBox: (typeof import("element-plus/es"))["ElMessageBox"];
|
||||
const computed: (typeof import("vue"))["computed"];
|
||||
const createApp: (typeof import("vue"))["createApp"];
|
||||
const customRef: (typeof import("vue"))["customRef"];
|
||||
const defineAsyncComponent: (typeof import("vue"))["defineAsyncComponent"];
|
||||
const defineComponent: (typeof import("vue"))["defineComponent"];
|
||||
const effectScope: (typeof import("vue"))["effectScope"];
|
||||
const getCurrentInstance: (typeof import("vue"))["getCurrentInstance"];
|
||||
const getCurrentScope: (typeof import("vue"))["getCurrentScope"];
|
||||
const h: (typeof import("vue"))["h"];
|
||||
const inject: (typeof import("vue"))["inject"];
|
||||
const isProxy: (typeof import("vue"))["isProxy"];
|
||||
const isReactive: (typeof import("vue"))["isReactive"];
|
||||
const isReadonly: (typeof import("vue"))["isReadonly"];
|
||||
const isRef: (typeof import("vue"))["isRef"];
|
||||
const markRaw: (typeof import("vue"))["markRaw"];
|
||||
const nextTick: (typeof import("vue"))["nextTick"];
|
||||
const onActivated: (typeof import("vue"))["onActivated"];
|
||||
const onBeforeMount: (typeof import("vue"))["onBeforeMount"];
|
||||
const onBeforeRouteLeave: (typeof import("vue-router"))["onBeforeRouteLeave"];
|
||||
const onBeforeRouteUpdate: (typeof import("vue-router"))["onBeforeRouteUpdate"];
|
||||
const onBeforeUnmount: (typeof import("vue"))["onBeforeUnmount"];
|
||||
const onBeforeUpdate: (typeof import("vue"))["onBeforeUpdate"];
|
||||
const onDeactivated: (typeof import("vue"))["onDeactivated"];
|
||||
const onErrorCaptured: (typeof import("vue"))["onErrorCaptured"];
|
||||
const onMounted: (typeof import("vue"))["onMounted"];
|
||||
const onRenderTracked: (typeof import("vue"))["onRenderTracked"];
|
||||
const onRenderTriggered: (typeof import("vue"))["onRenderTriggered"];
|
||||
const onScopeDispose: (typeof import("vue"))["onScopeDispose"];
|
||||
const onServerPrefetch: (typeof import("vue"))["onServerPrefetch"];
|
||||
const onUnmounted: (typeof import("vue"))["onUnmounted"];
|
||||
const onUpdated: (typeof import("vue"))["onUpdated"];
|
||||
const onWatcherCleanup: (typeof import("vue"))["onWatcherCleanup"];
|
||||
const provide: (typeof import("vue"))["provide"];
|
||||
const reactive: (typeof import("vue"))["reactive"];
|
||||
const readonly: (typeof import("vue"))["readonly"];
|
||||
const ref: (typeof import("vue"))["ref"];
|
||||
const resolveComponent: (typeof import("vue"))["resolveComponent"];
|
||||
const shallowReactive: (typeof import("vue"))["shallowReactive"];
|
||||
const shallowReadonly: (typeof import("vue"))["shallowReadonly"];
|
||||
const shallowRef: (typeof import("vue"))["shallowRef"];
|
||||
const toRaw: (typeof import("vue"))["toRaw"];
|
||||
const toRef: (typeof import("vue"))["toRef"];
|
||||
const toRefs: (typeof import("vue"))["toRefs"];
|
||||
const toValue: (typeof import("vue"))["toValue"];
|
||||
const triggerRef: (typeof import("vue"))["triggerRef"];
|
||||
const unref: (typeof import("vue"))["unref"];
|
||||
const useAttrs: (typeof import("vue"))["useAttrs"];
|
||||
const useCssModule: (typeof import("vue"))["useCssModule"];
|
||||
const useCssVars: (typeof import("vue"))["useCssVars"];
|
||||
const useId: (typeof import("vue"))["useId"];
|
||||
const useLink: (typeof import("vue-router"))["useLink"];
|
||||
const useModel: (typeof import("vue"))["useModel"];
|
||||
const useRoute: (typeof import("vue-router"))["useRoute"];
|
||||
const useRouter: (typeof import("vue-router"))["useRouter"];
|
||||
const useSlots: (typeof import("vue"))["useSlots"];
|
||||
const useTemplateRef: (typeof import("vue"))["useTemplateRef"];
|
||||
const watch: (typeof import("vue"))["watch"];
|
||||
const watchEffect: (typeof import("vue"))["watchEffect"];
|
||||
const watchPostEffect: (typeof import("vue"))["watchPostEffect"];
|
||||
const watchSyncEffect: (typeof import("vue"))["watchSyncEffect"];
|
||||
const EffectScope: typeof import('vue')['EffectScope']
|
||||
const ElMessage: typeof import('element-plus/es')['ElMessage']
|
||||
const ElMessageBox: (typeof import("element-plus/es"))["ElMessageBox"]
|
||||
const computed: typeof import('vue')['computed']
|
||||
const createApp: typeof import('vue')['createApp']
|
||||
const customRef: typeof import('vue')['customRef']
|
||||
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
|
||||
const defineComponent: typeof import('vue')['defineComponent']
|
||||
const effectScope: typeof import('vue')['effectScope']
|
||||
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
|
||||
const getCurrentScope: typeof import('vue')['getCurrentScope']
|
||||
const h: typeof import('vue')['h']
|
||||
const inject: typeof import('vue')['inject']
|
||||
const isProxy: typeof import('vue')['isProxy']
|
||||
const isReactive: typeof import('vue')['isReactive']
|
||||
const isReadonly: typeof import('vue')['isReadonly']
|
||||
const isRef: typeof import('vue')['isRef']
|
||||
const markRaw: typeof import('vue')['markRaw']
|
||||
const nextTick: typeof import('vue')['nextTick']
|
||||
const onActivated: typeof import('vue')['onActivated']
|
||||
const onBeforeMount: typeof import('vue')['onBeforeMount']
|
||||
const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave']
|
||||
const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate']
|
||||
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
|
||||
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
|
||||
const onDeactivated: typeof import('vue')['onDeactivated']
|
||||
const onErrorCaptured: typeof import('vue')['onErrorCaptured']
|
||||
const onMounted: typeof import('vue')['onMounted']
|
||||
const onRenderTracked: typeof import('vue')['onRenderTracked']
|
||||
const onRenderTriggered: typeof import('vue')['onRenderTriggered']
|
||||
const onScopeDispose: typeof import('vue')['onScopeDispose']
|
||||
const onServerPrefetch: typeof import('vue')['onServerPrefetch']
|
||||
const onUnmounted: typeof import('vue')['onUnmounted']
|
||||
const onUpdated: typeof import('vue')['onUpdated']
|
||||
const onWatcherCleanup: typeof import('vue')['onWatcherCleanup']
|
||||
const provide: typeof import('vue')['provide']
|
||||
const reactive: typeof import('vue')['reactive']
|
||||
const readonly: typeof import('vue')['readonly']
|
||||
const ref: typeof import('vue')['ref']
|
||||
const resolveComponent: typeof import('vue')['resolveComponent']
|
||||
const shallowReactive: typeof import('vue')['shallowReactive']
|
||||
const shallowReadonly: typeof import('vue')['shallowReadonly']
|
||||
const shallowRef: typeof import('vue')['shallowRef']
|
||||
const toRaw: typeof import('vue')['toRaw']
|
||||
const toRef: typeof import('vue')['toRef']
|
||||
const toRefs: typeof import('vue')['toRefs']
|
||||
const toValue: typeof import('vue')['toValue']
|
||||
const triggerRef: typeof import('vue')['triggerRef']
|
||||
const unref: typeof import('vue')['unref']
|
||||
const useAttrs: typeof import('vue')['useAttrs']
|
||||
const useCssModule: typeof import('vue')['useCssModule']
|
||||
const useCssVars: typeof import('vue')['useCssVars']
|
||||
const useId: typeof import('vue')['useId']
|
||||
const useLink: typeof import('vue-router')['useLink']
|
||||
const useModel: typeof import('vue')['useModel']
|
||||
const useRoute: typeof import('vue-router')['useRoute']
|
||||
const useRouter: typeof import('vue-router')['useRouter']
|
||||
const useSlots: typeof import('vue')['useSlots']
|
||||
const useTemplateRef: typeof import('vue')['useTemplateRef']
|
||||
const watch: typeof import('vue')['watch']
|
||||
const watchEffect: typeof import('vue')['watchEffect']
|
||||
const watchPostEffect: typeof import('vue')['watchPostEffect']
|
||||
const watchSyncEffect: typeof import('vue')['watchSyncEffect']
|
||||
}
|
||||
// for type re-export
|
||||
declare global {
|
||||
// @ts-ignore
|
||||
export type {
|
||||
Component,
|
||||
ComponentPublicInstance,
|
||||
ComputedRef,
|
||||
DirectiveBinding,
|
||||
ExtractDefaultPropTypes,
|
||||
ExtractPropTypes,
|
||||
ExtractPublicPropTypes,
|
||||
InjectionKey,
|
||||
PropType,
|
||||
Ref,
|
||||
MaybeRef,
|
||||
MaybeRefOrGetter,
|
||||
VNode,
|
||||
WritableComputedRef
|
||||
} from "vue";
|
||||
import("vue");
|
||||
export type { Component, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue'
|
||||
import('vue')
|
||||
}
|
||||
|
||||
@@ -2,43 +2,36 @@
|
||||
|
||||
<template>
|
||||
<!-- 查询表单 -->
|
||||
<SearchForm v-show="isShowSearch" :search="_search" :reset="_reset" :columns="searchColumns" :search-param="searchParam" :search-col="searchCol" />
|
||||
<SearchForm v-show="isShowSearch" :search="_search" :reset="_reset" :columns="searchColumns"
|
||||
:search-param="searchParam" :search-col="searchCol" />
|
||||
|
||||
<!-- 表格主体 -->
|
||||
<div class="card table-main">
|
||||
<!-- 表格头部 操作按钮 -->
|
||||
<div class="table-header">
|
||||
<div class="header-button-lf">
|
||||
<slot name="tableHeader" :selected-list="selectedList" :selected-list-ids="selectedListIds" :is-selected="isSelected" />
|
||||
<slot name="tableHeader" :selected-list="selectedList" :selected-list-ids="selectedListIds"
|
||||
:is-selected="isSelected" />
|
||||
</div>
|
||||
<div v-if="toolButton" class="header-button-ri">
|
||||
<slot name="toolButton">
|
||||
<el-button v-if="showToolButton('refresh')" :icon="Refresh" circle @click="getTableList" />
|
||||
<el-button v-if="showToolButton('setting') && columns.length" :icon="Operation" circle @click="openColSetting" />
|
||||
<el-button v-if="showToolButton('search') && searchColumns?.length" :icon="Search" circle @click="isShowSearch = !isShowSearch" />
|
||||
<el-button v-if="showToolButton('setting') && columns.length" :icon="Operation" circle
|
||||
@click="openColSetting" />
|
||||
<el-button v-if="showToolButton('search') && searchColumns?.length" :icon="Search" circle
|
||||
@click="isShowSearch = !isShowSearch" />
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 表格主体 -->
|
||||
<el-table
|
||||
ref="tableRef"
|
||||
v-bind="$attrs"
|
||||
:id="uuid"
|
||||
:data="processTableData"
|
||||
:border="border"
|
||||
:row-key="rowKey"
|
||||
@selection-change="selectionChange"
|
||||
>
|
||||
<el-table ref="tableRef" v-bind="$attrs" :id="uuid" :data="processTableData" :border="border" :row-key="rowKey"
|
||||
@selection-change="selectionChange">
|
||||
<!-- 默认插槽 -->
|
||||
<slot />
|
||||
<template v-for="item in tableColumns" :key="item">
|
||||
<!-- selection || radio || index || expand || sort -->
|
||||
<el-table-column
|
||||
v-if="item.type && columnTypes.includes(item.type)"
|
||||
v-bind="item"
|
||||
:align="item.align ?? 'center'"
|
||||
:reserve-selection="item.type == 'selection'"
|
||||
>
|
||||
<el-table-column v-if="item.type && columnTypes.includes(item.type)" v-bind="item"
|
||||
:align="item.align ?? 'center'" :reserve-selection="item.type == 'selection'">
|
||||
<template #default="scope">
|
||||
<!-- expand -->
|
||||
<template v-if="item.type == 'expand'">
|
||||
@@ -51,7 +44,9 @@
|
||||
</el-radio>
|
||||
<!-- sort -->
|
||||
<el-tag v-if="item.type == 'sort'" class="move">
|
||||
<el-icon> <DCaret /></el-icon>
|
||||
<el-icon>
|
||||
<DCaret />
|
||||
</el-icon>
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -78,13 +73,8 @@
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<slot name="pagination">
|
||||
<Pagination
|
||||
v-if="pagination"
|
||||
:pageable="pageable"
|
||||
:pager-count="pagerCount"
|
||||
:handle-size-change="handleSizeChange"
|
||||
:handle-current-change="handleCurrentChange"
|
||||
/>
|
||||
<Pagination v-if="pagination" :pageable="pageable" :pager-count="pagerCount"
|
||||
:handle-size-change="handleSizeChange" :handle-current-change="handleCurrentChange" />
|
||||
</slot>
|
||||
</div>
|
||||
<!-- 列设置 -->
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<AssemblySize id="assemblySize" />
|
||||
<SearchMenu id="searchMenu" />
|
||||
<ThemeSetting id="themeSetting" />
|
||||
<Message id="message" />
|
||||
<!-- <Message id="message" /> -->
|
||||
<Fullscreen id="fullscreen" />
|
||||
<ChangeModule id="changeModule" />
|
||||
</div>
|
||||
@@ -18,7 +18,7 @@ import { computed } from "vue";
|
||||
import { useUserStore } from "@/stores/modules/user";
|
||||
import AssemblySize from "./components/AssemblySize.vue";
|
||||
import ThemeSetting from "./components/ThemeSetting.vue";
|
||||
import Message from "./components/Message.vue";
|
||||
// import Message from "./components/Message.vue";
|
||||
import Fullscreen from "./components/Fullscreen.vue";
|
||||
import Avatar from "./components/Avatar.vue";
|
||||
import ChangeModule from "./components/ChangeModule.vue";
|
||||
@@ -34,14 +34,17 @@ const username = computed(() => userStore.userInfo?.name);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding-right: 25px;
|
||||
|
||||
.header-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
& > * {
|
||||
|
||||
&>* {
|
||||
margin-left: 21px;
|
||||
color: var(--el-header-text-color);
|
||||
}
|
||||
}
|
||||
|
||||
.username {
|
||||
margin: 0 20px;
|
||||
font-size: 15px;
|
||||
|
||||
@@ -14,20 +14,19 @@
|
||||
</div>
|
||||
</template>
|
||||
<el-tabs v-model="activeName">
|
||||
<el-tab-pane
|
||||
v-for="(tab, index) in messageTypeOptions"
|
||||
:key="index"
|
||||
:label="tab.label + `(${messageStore.getUnReadCount(tab.value)})`"
|
||||
:name="tab.value"
|
||||
>
|
||||
<el-tab-pane v-for="(tab, index) in messageTypeOptions" :key="index"
|
||||
:label="tab.label + `(${messageStore.getUnReadCount(tab.value)})`" :name="tab.value">
|
||||
<div class="message-list">
|
||||
<div class="message-item" v-for="(msg, index2) in getNewUnRead(tab.value)" :key="index2">
|
||||
<img v-if="tab.value === MessageTypeDictEnum.INFORM" src="@/assets/images/msg01.png" alt="" class="message-icon" />
|
||||
<img v-else-if="tab.value === MessageTypeDictEnum.NOTICE" src="@/assets/images/msg03.png" alt="" class="message-icon" />
|
||||
<img v-if="tab.value === MessageTypeDictEnum.INFORM" src="@/assets/images/msg01.png" alt=""
|
||||
class="message-icon" />
|
||||
<img v-else-if="tab.value === MessageTypeDictEnum.NOTICE" src="@/assets/images/msg03.png" alt=""
|
||||
class="message-icon" />
|
||||
<img v-else src="@/assets/images/msg02.png" alt="" class="message-icon" />
|
||||
<div class="message-content">
|
||||
<!-- 如果未读class用message-title-black -->
|
||||
<span :class="{ 'message-title': msg.read, 'message-title-black': !msg.read }">{{ msg.subject }}</span>
|
||||
<span :class="{ 'message-title': msg.read, 'message-title-black': !msg.read }">{{ msg.subject
|
||||
}}</span>
|
||||
<span class="message-date">{{ msg.sendTimeFormat }}</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -95,6 +94,7 @@ function toMessage() {
|
||||
.el-link {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.message-empty {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -103,32 +103,40 @@ function toMessage() {
|
||||
height: 260px;
|
||||
line-height: 45px;
|
||||
}
|
||||
|
||||
.message-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.message-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 15px 0;
|
||||
border-bottom: 1px solid var(--el-border-color-light);
|
||||
|
||||
&:last-child {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.message-icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin: 0 20px 0 5px;
|
||||
}
|
||||
|
||||
.message-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.message-title {
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.message-title-black {
|
||||
margin-bottom: 2px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.message-date {
|
||||
font-size: 12px;
|
||||
color: var(--el-text-color-secondary);
|
||||
|
||||
+12
-19
@@ -1,14 +1,14 @@
|
||||
<template>
|
||||
<el-dialog :model-value="visible" @update:model-value="handleUpdateVisible" title="添加药材" width="600px" destroy-on-close>
|
||||
<el-dialog :model-value="visible" @update:model-value="handleUpdateVisible" title="添加药材" width="600px"
|
||||
destroy-on-close :close-on-click-modal="false">
|
||||
<el-form :model="form" label-width="120px" ref="formRef" class="mt-2" :rules="formRules">
|
||||
<!-- 药材下拉 + 未找到按钮 -->
|
||||
<el-form-item v-if="!isAddingNew" label="药材名称" prop="medicinalTypeId" style="display: flex; align-items: center">
|
||||
<el-select v-model="form.medicinalTypeId" placeholder="请选择药材" filterable style="flex: 1; margin-right: 8px">
|
||||
<el-option v-for="item in medicinalList" :key="item.id" :label="item.dictLabel" :value="item.id" />
|
||||
<el-form-item v-if="!isAddingNew" label="药材名称" prop="Id" style="display: flex; align-items: center">
|
||||
<el-select v-model="form.Id" placeholder="请选择药材" filterable style="flex: 1; margin-right: 8px">
|
||||
<el-option v-for="item in medicinalList" :key="item.id" :label="item.medicinalName" :value="item.id" />
|
||||
</el-select>
|
||||
<el-button type="text" @click="handleNotFound">未找到</el-button>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 新药材输入框 -->
|
||||
<el-form-item label="新药材名称" v-if="isAddingNew" prop="medicinalName">
|
||||
<el-input v-model="form.medicinalName" placeholder="请输入新药材名称" />
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, watch, computed } from "vue";
|
||||
import { medicinalApi } from "@/api/modules/biz/WeiBingJu/medicinal";
|
||||
import { medicinalApi } from "@/api/modules/biz/weibingju/medicinal";
|
||||
import { ElMessage, ElForm, FormRules } from "element-plus";
|
||||
|
||||
const props = defineProps({
|
||||
@@ -46,7 +46,7 @@ const isAddingNew = ref(false);
|
||||
|
||||
const formRef = ref<InstanceType<typeof ElForm>>();
|
||||
const form = reactive({
|
||||
medicinalTypeId: null as number | null,
|
||||
Id: null as number | null,
|
||||
addWeight: 0,
|
||||
// 前端改为 totalPrice
|
||||
totalPrice: 0,
|
||||
@@ -55,7 +55,7 @@ const form = reactive({
|
||||
|
||||
// 动态表单校验(注意 totalPrice 字段)
|
||||
const formRules = computed<FormRules>(() => ({
|
||||
medicinalTypeId: [{ required: !isAddingNew.value, message: "请选择药材", trigger: "change" }],
|
||||
Id: [{ required: !isAddingNew.value, message: "请选择药材", trigger: "change" }],
|
||||
medicinalName: [{ required: isAddingNew.value, message: "请输入新药材名称", trigger: "blur" }],
|
||||
addWeight: [
|
||||
{ required: true, message: "请输入添加量", trigger: "blur" },
|
||||
@@ -72,7 +72,6 @@ const fetchMedicinalList = async () => {
|
||||
const res = await medicinalApi.getDictList();
|
||||
medicinalList.value = res.data || [];
|
||||
} catch (err) {
|
||||
ElMessage.error("加载药材列表失败");
|
||||
medicinalList.value = [];
|
||||
}
|
||||
};
|
||||
@@ -96,7 +95,7 @@ const handleUpdateVisible = (newVisible: boolean) => {
|
||||
};
|
||||
const handleCancel = () => emit("update:visible", false);
|
||||
const handleResetForm = () => {
|
||||
form.medicinalTypeId = null;
|
||||
form.Id = null;
|
||||
form.addWeight = 0;
|
||||
form.totalPrice = 0;
|
||||
form.medicinalName = "";
|
||||
@@ -106,7 +105,7 @@ const handleResetForm = () => {
|
||||
|
||||
const handleNotFound = () => {
|
||||
isAddingNew.value = true;
|
||||
form.medicinalTypeId = null;
|
||||
form.Id = null;
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
@@ -123,15 +122,10 @@ const handleSubmit = async () => {
|
||||
ElMessage.warning("添加量需大于 0");
|
||||
return;
|
||||
}
|
||||
|
||||
// unitPrice = totalPrice / addWeight,保留两位
|
||||
const unitPrice = parseFloat((form.totalPrice / form.addWeight).toFixed(2));
|
||||
|
||||
// 构造后端期望的 payload(注意把 totalPrice 改为 unitPrice)
|
||||
const payload: any = {
|
||||
medicinalTypeId: form.medicinalTypeId,
|
||||
Id: form.Id,
|
||||
addWeight: form.addWeight,
|
||||
unitPrice: unitPrice,
|
||||
totalPrice: form.totalPrice,
|
||||
medicinalName: form.medicinalName
|
||||
};
|
||||
|
||||
@@ -141,7 +135,6 @@ const handleSubmit = async () => {
|
||||
emit("update:visible", false);
|
||||
emit("refreshList");
|
||||
} catch (err: any) {
|
||||
ElMessage.error(err.message || "添加失败");
|
||||
}
|
||||
};
|
||||
</script>
|
||||
+33
-39
@@ -1,17 +1,14 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:model-value="props.visible"
|
||||
:title="`${props.medicinalName} - 添加记录`"
|
||||
width="1200px"
|
||||
@close="handleDialogClose"
|
||||
@update:model-value="handleUpdateVisible"
|
||||
append-to-body
|
||||
>
|
||||
<ProTable ref="proTableRef" title="添加记录" :columns="columns" :request-api="getAdditionRecordsApi" :row-key="rowKey" :show-selection="false">
|
||||
<el-dialog :model-value="props.visible" :title="`${props.medicinalName} - 添加记录`" width="1200px"
|
||||
@close="handleDialogClose" @update:model-value="handleUpdateVisible" append-to-body
|
||||
:body-class="'el-dialog__body-new'" :close-on-click-modal="false">
|
||||
<ProTable ref="proTableRef" title="添加记录" :columns="columns" :request-api="getAdditionRecordsApi" :row-key="rowKey"
|
||||
:border="true" :show-selection="false">
|
||||
<!-- 行内列 slot:addWeight -->
|
||||
<template #addWeight="{ row }">
|
||||
<template v-if="editingId === row.id">
|
||||
<el-input-number v-model.number="editModel.addWeight" :min="0.01" :step="0.01" controls-position="right" size="small" />
|
||||
<el-input-number v-model.number="editModel.addWeight" :min="0.01" :step="0.01" controls-position="right"
|
||||
size="small" />
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ row.addWeight }}
|
||||
@@ -26,17 +23,11 @@
|
||||
<!-- totalPrice 列:查看时显示合计,编辑时可以修改 -->
|
||||
<template #totalPrice="{ row }">
|
||||
<template v-if="editingId === row.id">
|
||||
<el-input-number
|
||||
v-model.number="editModel.totalPrice"
|
||||
:min="0"
|
||||
:step="0.01"
|
||||
controls-position="right"
|
||||
size="small"
|
||||
placeholder="输入总价(元)"
|
||||
/>
|
||||
<el-input-number v-model.number="editModel.totalPrice" :min="0" :step="0.01" controls-position="right"
|
||||
size="small" placeholder="输入总价(元)" />
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ ((row.addWeight ?? 0) * (row.unitPrice ?? 0)).toFixed(2) }}
|
||||
{{ row.totalPrice }}
|
||||
</template>
|
||||
</template>
|
||||
|
||||
@@ -48,12 +39,15 @@
|
||||
<!-- 操作列 -->
|
||||
<template #operation="{ row }">
|
||||
<template v-if="editingId === row.id">
|
||||
<el-button size="small" type="primary" @click="saveRowEdit(row)" :loading="saving"> 保存 </el-button>
|
||||
<el-button size="small" type="primary" @click="saveRowEdit(row)" :loading="saving">保存</el-button>
|
||||
<el-button size="small" @click="cancelRowEdit">取消</el-button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-button type="text" size="small" @click="startRowEdit(row)"> 编辑 </el-button>
|
||||
<el-button type="text" size="small" text-color="#ff4d4f" @click="handleDeleteRecord(row.id)"> 删除 </el-button>
|
||||
<el-button v-if="row.canEdit" type="text" size="small" @click="startRowEdit(row)">编辑</el-button>
|
||||
<el-button v-if="row.canEdit" type="text" size="small" style="color: #ff4d4f"
|
||||
@click="handleDeleteRecord(row.id)">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</template>
|
||||
</ProTable>
|
||||
@@ -64,7 +58,6 @@
|
||||
/**
|
||||
* 单行行内编辑版本(总价 totalPrice 输入):
|
||||
* - 点击「编辑」:将该行复制到 editModel(editModel.addWeight & editModel.totalPrice),记录 editingId(只允许单行编辑)
|
||||
* - 保存:计算 unitPrice = totalPrice / addWeight,发送 unitPrice 到后端
|
||||
* - 取消:不调用后端,直接清除 editingId(恢复显示)
|
||||
*/
|
||||
|
||||
@@ -75,7 +68,7 @@ import { ElMessage, ElMessageBox } from "element-plus";
|
||||
|
||||
const props = defineProps({
|
||||
visible: { type: Boolean, default: false },
|
||||
medicinalId: { type: Number, required: true },
|
||||
id: { type: Number, required: true },
|
||||
medicinalName: { type: String, default: "药材" }
|
||||
});
|
||||
const emit = defineEmits(["update:visible", "close", "refreshList"]);
|
||||
@@ -86,7 +79,7 @@ const proTableRef = ref<any | null>(null);
|
||||
// 当前正在编辑的行 id(单行)
|
||||
const editingId = ref<number | null>(null);
|
||||
|
||||
// 编辑模型(只存一行):注意 totalPrice 而不是 unitPrice
|
||||
// 编辑模型(只存一行):注意 totalPrice
|
||||
const editModel = reactive({
|
||||
addWeight: 0,
|
||||
totalPrice: 0
|
||||
@@ -111,7 +104,8 @@ const rowKey = (row: any) => row.id;
|
||||
watch(
|
||||
() => props.visible,
|
||||
async val => {
|
||||
if (val && props.medicinalId) {
|
||||
if (val && props.id) {
|
||||
console.log("打开添加记录弹窗,药材ID=", props.id);
|
||||
await nextTick();
|
||||
proTableRef.value?.refresh?.();
|
||||
}
|
||||
@@ -121,7 +115,10 @@ watch(
|
||||
|
||||
// 将 ProTable 的请求透传到后端(ProTable 会带上 pageNum/pageSize 等)
|
||||
const getAdditionRecordsApi = (params: any) => {
|
||||
return medicinalApi.getAdditionRecords(props.medicinalId, params);
|
||||
return medicinalApi.getAdditionRecords({
|
||||
id: props.id,
|
||||
...params
|
||||
});
|
||||
};
|
||||
|
||||
// 开始编辑:把当前行复制到 editModel(addWeight 和 totalPrice)
|
||||
@@ -133,7 +130,7 @@ const startRowEdit = (row: any) => {
|
||||
editingId.value = row.id;
|
||||
editModel.addWeight = row.addWeight ?? 0;
|
||||
// 后端返回的是 unitPrice,前端要显示/编辑 totalPrice = unitPrice * addWeight
|
||||
editModel.totalPrice = Number(((row.unitPrice ?? 0) * (row.addWeight ?? 1)).toFixed(2));
|
||||
editModel.totalPrice = row.totalPrice;
|
||||
};
|
||||
|
||||
// 取消编辑:清空 editingId(恢复显示)
|
||||
@@ -157,12 +154,11 @@ const saveRowEdit = async (row: any) => {
|
||||
|
||||
try {
|
||||
saving.value = true;
|
||||
// 计算 unitPrice(保留两位)
|
||||
const unitPrice = parseFloat((editModel.totalPrice / editModel.addWeight).toFixed(2));
|
||||
|
||||
await medicinalApi.updateAdditionRecord(row.id, {
|
||||
await medicinalApi.updateAdditionRecord({
|
||||
id: row.id,
|
||||
addWeight: editModel.addWeight,
|
||||
unitPrice: unitPrice
|
||||
totalPrice: editModel.totalPrice
|
||||
});
|
||||
|
||||
ElMessage.success("保存成功");
|
||||
@@ -171,7 +167,6 @@ const saveRowEdit = async (row: any) => {
|
||||
emit("refreshList");
|
||||
cancelRowEdit();
|
||||
} catch (err: any) {
|
||||
ElMessage.error(err?.message || "保存失败");
|
||||
} finally {
|
||||
saving.value = false;
|
||||
}
|
||||
@@ -186,12 +181,11 @@ const handleDeleteRecord = async (id: number) => {
|
||||
})
|
||||
.then(async () => {
|
||||
try {
|
||||
await medicinalApi.deleteAdditionRecord(id);
|
||||
await medicinalApi.deleteAdditionRecord({ id: id });
|
||||
ElMessage.success("删除成功");
|
||||
await proTableRef.value?.refresh?.();
|
||||
emit("refreshList");
|
||||
} catch (err: any) {
|
||||
ElMessage.error(err?.message || "删除失败");
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
@@ -218,8 +212,8 @@ const handleUpdateVisible = (newVal: boolean) => {
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.mb-4 {
|
||||
margin-bottom: 16px;
|
||||
<style lang="scss">
|
||||
.el-dialog__body-new {
|
||||
height: 550px !important;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
@@ -0,0 +1,120 @@
|
||||
<template>
|
||||
<el-dialog :model-value="props.visible" :title="`${props.medicinalName} - 消耗记录`" width="800px"
|
||||
@close="handleDialogClose" @update:model-value="handleUpdateVisible" append-to-body
|
||||
:body-class="'el-dialog__body-new'" :close-on-click-modal="false">
|
||||
<!-- 统一使用ProTable实现列表(带分页),与AdditionRecordDialog风格保持一致 -->
|
||||
<ProTable ref="proTableRef" title="消耗记录列表" :columns="columns" :request-api="getConsumptionRecordsApi"
|
||||
:row-key="rowKey" :show-selection="false" :border="true">
|
||||
<!-- 人员列:包含家属标记的自定义渲染 -->
|
||||
<template #personName="{ row }">
|
||||
<span>{{ row.personName }}</span>
|
||||
<el-tag size="small" type="info" v-if="row.isRelative" style="margin-left: 8px">
|
||||
家属({{ row.employeeName || "未知员工" }})
|
||||
</el-tag>
|
||||
</template>
|
||||
|
||||
<!-- 使用时间:格式化渲染 -->
|
||||
<template #useTime="{ row }">
|
||||
{{ row.useTime ? formatDate(row.useTime) : "-" }}
|
||||
</template>
|
||||
</ProTable>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineProps, defineEmits, ref, watch, nextTick } from "vue";
|
||||
import ProTable from "@/components/ProTable/index.vue";
|
||||
import { medicinalApi } from "@/api";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
|
||||
/** 1. 定义Props(与父组件传参匹配,参考AdditionRecordDialog) */
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
id: { // 对应父组件传的「currentMedicinalId」,与AdditionRecordDialog的id参数统一
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
medicinalName: {
|
||||
type: String,
|
||||
default: "药材"
|
||||
}
|
||||
});
|
||||
|
||||
/** 2. 定义Emits(与AdditionRecordDialog事件机制统一) */
|
||||
const emit = defineEmits(["update:visible", "close", "refreshList"]);
|
||||
|
||||
/** 3. 状态管理(ProTable引用 + 无编辑状态,仅列表) */
|
||||
const proTableRef = ref<any | null>(null); // ProTable实例引用,用于刷新列表
|
||||
|
||||
/** 4. 列配置(与消耗记录字段匹配,仅保留展示列) */
|
||||
const columns = [
|
||||
{
|
||||
prop: "amountG",
|
||||
label: "使用量(g)",
|
||||
minWidth: 100
|
||||
},
|
||||
{
|
||||
prop: "personName",
|
||||
label: "使用人员",
|
||||
minWidth: 250,
|
||||
slotName: "personName" // 关联自定义模板
|
||||
},
|
||||
{
|
||||
prop: "useTime",
|
||||
label: "使用时间",
|
||||
minWidth: 150,
|
||||
slotName: "useTime" // 关联时间格式化模板
|
||||
}
|
||||
];
|
||||
|
||||
/** 5. 行唯一标识(与后端返回的主键匹配) */
|
||||
const rowKey = (row: any) => row.id;
|
||||
|
||||
/** 6. 接口请求(透传ProTable分页参数,与AdditionRecordDialog逻辑统一) */
|
||||
const getConsumptionRecordsApi = (params: any) => {
|
||||
// 调用药材消耗记录接口,携带「药材ID」和「分页参数」
|
||||
return medicinalApi.getConsumptionRecords({
|
||||
id: props.id, // 药材ID(必传)
|
||||
...params // 分页参数(pageNum、pageSize等,从ProTable传入)
|
||||
});
|
||||
};
|
||||
|
||||
/** 7. 时间格式化工具(与AdditionRecordDialog格式统一) */
|
||||
const formatDate = (dateStr: string) => {
|
||||
const d = new Date(String(dateStr).replace(" ", "T"));
|
||||
return isNaN(d.getTime()) ? dateStr : d.toLocaleString();
|
||||
};
|
||||
|
||||
/** 8. 弹窗显示/隐藏监听(弹窗显示时刷新列表,与AdditionRecordDialog逻辑统一) */
|
||||
watch(
|
||||
() => props.visible,
|
||||
async (isVisible) => {
|
||||
if (isVisible && props.id) {
|
||||
await nextTick(); // 等待ProTable渲染完成
|
||||
proTableRef.value?.refresh?.(); // 刷新列表数据
|
||||
}
|
||||
},
|
||||
{ immediate: true } // 初始加载时触发
|
||||
);
|
||||
|
||||
/** 9. 弹窗关闭逻辑(与AdditionRecordDialog统一,清空状态+通知父组件) */
|
||||
const handleDialogClose = () => {
|
||||
emit("update:visible", false); // 通知父组件更新弹窗状态
|
||||
emit("close"); // 触发关闭事件(可选)
|
||||
};
|
||||
|
||||
/** 10. 弹窗状态更新回调(与Element Plus Dialog事件匹配) */
|
||||
const handleUpdateVisible = (newVal: boolean) => {
|
||||
if (!newVal) { // 仅当弹窗关闭时执行清理逻辑
|
||||
handleDialogClose();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.el-dialog__body-new {
|
||||
height: 550px !important;
|
||||
}
|
||||
</style>
|
||||
+23
-38
@@ -1,30 +1,26 @@
|
||||
<template>
|
||||
<div class="table-box">
|
||||
<el-card class="mt-4">
|
||||
<ProTable ref="proTable" title="药材列表" :columns="columns" :request-api="medicinalApi.page">
|
||||
<template #tableHeader>
|
||||
<!-- 新增按钮:保持框架一致的 s-button 写法 -->
|
||||
<s-button suffix="药材" @click="onOpenAdd" />
|
||||
</template>
|
||||
|
||||
<template #operation="scope">
|
||||
<s-button link :opt="FormOptEnum.VIEW" size="small" @click="handleViewConsumption(scope.row)"> 查看消耗记录 </s-button>
|
||||
<s-button link :opt="FormOptEnum.VIEW" size="small" class="ml-2" @click="handleViewAddition(scope.row)"> 查看添加记录 </s-button>
|
||||
</template>
|
||||
</ProTable>
|
||||
</el-card>
|
||||
<ProTable ref="proTable" title="药材列表" :columns="columns" :request-api="medicinalApi.page">
|
||||
<template #tableHeader>
|
||||
<!-- 新增按钮:保持框架一致的 s-button 写法 -->
|
||||
<s-button suffix="药材" @click="onOpenAdd" />
|
||||
</template>
|
||||
|
||||
<template #operation="scope">
|
||||
<s-button link :opt="FormOptEnum.VIEW" size="small" @click="handleViewConsumption(scope.row)"> 查看消耗记录
|
||||
</s-button>
|
||||
<s-button link :opt="FormOptEnum.VIEW" size="small" class="ml-2" @click="handleViewAddition(scope.row)">
|
||||
查看添加记录 </s-button>
|
||||
</template>
|
||||
</ProTable>
|
||||
<!-- 消耗记录弹窗 -->
|
||||
<consumption-record-dialog v-model:visible="showConsumptionDialog" :medicinal-id="currentMedicinalId" :medicinal-name="currentMedicinalName" />
|
||||
<consumption-record-dialog v-model:visible="showConsumptionDialog" :id="currentMedicinalId"
|
||||
:medicinal-name="currentMedicinalName" />
|
||||
|
||||
<!-- 添加记录弹窗 -->
|
||||
<addition-record-dialog
|
||||
:visible="showAdditionDialog"
|
||||
:medicinal-id="currentMedicinalId"
|
||||
:medicinal-name="currentMedicinalName"
|
||||
@update:visible="val => (showAdditionDialog = val)"
|
||||
@refresh-list="handleRefresh"
|
||||
/>
|
||||
<addition-record-dialog :visible="showAdditionDialog" :id="currentMedicinalId"
|
||||
:medicinal-name="currentMedicinalName" @update:visible="val => (showAdditionDialog = val)"
|
||||
@refresh-list="handleRefresh" />
|
||||
|
||||
<!-- 新增药材弹窗 -->
|
||||
<add-medicinal-dialog v-model:visible="showAddMedicinalDialog" @refresh-list="handleRefresh" />
|
||||
@@ -40,7 +36,7 @@ import type { ColumnProps, ProTableInstance } from "@/components/ProTable/interf
|
||||
import { FormOptEnum } from "@/enums";
|
||||
|
||||
// 子组件
|
||||
//import ConsumptionRecordDialog from "./components/ConsumptionRecordDialog.vue";
|
||||
import ConsumptionRecordDialog from "./components/ConsumptionRecordDialog.vue";
|
||||
import AdditionRecordDialog from "./components/AdditionRecordDialog.vue";
|
||||
import AddMedicinalDialog from "./components/AddMedicinalDialog.vue";
|
||||
|
||||
@@ -56,9 +52,10 @@ const currentMedicinalName = ref<string>("");
|
||||
const columns: ColumnProps<MedicinalInfo>[] = [
|
||||
{ type: "selection", fixed: "left", width: 80 },
|
||||
{ prop: "medicinalName", label: "药材名称", search: { el: "input" } },
|
||||
{ prop: "totalUsedWeight", label: "使用量(g)" },
|
||||
{ prop: "stock", label: "药材库存(g)" },
|
||||
{ prop: "usedCost", label: "使用成本" },
|
||||
{ prop: "remainingValue", label: "剩余价值" },
|
||||
{ prop: "usedCost", label: "预估使用成本" },
|
||||
{ prop: "remainingValue", label: "预估剩余价值" },
|
||||
{ prop: "operation", label: "操作", width: 240, fixed: "right" }
|
||||
];
|
||||
|
||||
@@ -69,7 +66,7 @@ function onOpenAdd() {
|
||||
|
||||
// 查看消耗记录
|
||||
function handleViewConsumption(row: MedicinalInfo) {
|
||||
currentMedicinalId.value = row.medicinalId ?? (row as any).id ?? null;
|
||||
currentMedicinalId.value = row.Id ?? (row as any).id ?? null;
|
||||
currentMedicinalName.value = row.medicinalName ?? "";
|
||||
showConsumptionDialog.value = true;
|
||||
}
|
||||
@@ -78,7 +75,7 @@ function handleViewConsumption(row: MedicinalInfo) {
|
||||
function handleViewAddition(row: MedicinalInfo) {
|
||||
console.log("查看添加记录", row);
|
||||
// 直接设置正确的ID和名称,然后显示弹窗
|
||||
currentMedicinalId.value = row.medicinalId ?? (row as any).id ?? null;
|
||||
currentMedicinalId.value = row.id ?? (row as any).id ?? null;
|
||||
currentMedicinalName.value = row.medicinalName ?? "";
|
||||
showAdditionDialog.value = true;
|
||||
}
|
||||
@@ -88,15 +85,3 @@ function handleRefresh() {
|
||||
proTable.value?.refresh?.();
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.table-box {
|
||||
padding-bottom: 24px;
|
||||
}
|
||||
.mt-4 {
|
||||
margin-top: 16px;
|
||||
}
|
||||
.ml-2 {
|
||||
margin-left: 8px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,959 @@
|
||||
<template>
|
||||
<el-dialog :model-value="visible" :title="dialogTitle" width="1000px" destroy-on-close @close="handleClose"
|
||||
:body-class="'modal-class'" @update:model-value="handleVisibleChange" :close-on-click-modal="false">
|
||||
<!-- 表单根节点:查看模式禁用,新增/编辑模式可交互 -->
|
||||
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="120px" class="prescription-form"
|
||||
:disabled="isViewMode">
|
||||
<!-- 1. 人员信息 -->
|
||||
<el-card class="form-section" shadow="never">
|
||||
<template #header>
|
||||
<div class="section-title">人员信息</div>
|
||||
</template>
|
||||
|
||||
<!-- 人员类型 -->
|
||||
<el-form-item label="人员类型" prop="personType">
|
||||
<el-radio-group v-model="formData.personType" @change="handlePersonTypeChange" :disabled="isViewMode">
|
||||
<el-radio :label="1">公司员工</el-radio>
|
||||
<el-radio :label="2">员工家属</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 公司员工模式 -->
|
||||
<template v-if="formData.personType === 1">
|
||||
<!-- 员工姓名 -->
|
||||
<el-form-item label="员工姓名" prop="employeeInfo">
|
||||
<div class="flex items-center gap-2">
|
||||
<el-select v-if="showEmployeeSelect" v-model="formData.employeeId" placeholder="请选择员工" filterable
|
||||
:loading="employeeLoading" class="flex-1" @change="handleEmployeeChange" @clear="handleEmployeeClear"
|
||||
:disabled="isViewMode">
|
||||
<el-option v-for="item in employeeOptions" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
<!-- 新增/编辑模式显示"新增员工"按钮 -->
|
||||
<el-button v-if="!isViewMode" type="primary" size="small" @click="handleOpenAddEmployeeDialog">
|
||||
新增员工
|
||||
</el-button>
|
||||
</div>
|
||||
<el-input v-if="!showEmployeeSelect && !formData.employeeId" v-model="formData.newEmployeeName"
|
||||
placeholder="请输入员工姓名" class="mt-2" :disabled="isViewMode" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<!-- 员工家属模式 -->
|
||||
<template v-if="formData.personType === 2">
|
||||
<!-- 关联员工 -->
|
||||
<el-form-item label="关联员工" prop="relatedEmployeeInfo">
|
||||
<div class="flex items-center gap-2">
|
||||
<el-select v-if="showRelatedEmployeeSelect" v-model="formData.relatedEmployeeId" placeholder="请选择关联员工"
|
||||
filterable :loading="employeeLoading" class="flex-1" @change="handleRelatedEmployeeChange"
|
||||
@clear="handleRelatedEmployeeClear" :disabled="isViewMode">
|
||||
<el-option v-for="item in employeeOptions" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
<!-- 新增/编辑模式显示"新增关联员工"按钮 -->
|
||||
<el-button v-if="!isViewMode" type="primary" size="small" @click="handleOpenAddRelatedEmployeeDialog">
|
||||
新增员工
|
||||
</el-button>
|
||||
</div>
|
||||
<el-input v-if="!showRelatedEmployeeSelect && !formData.relatedEmployeeId"
|
||||
v-model="formData.newRelatedEmployeeName" placeholder="请输入关联员工姓名" class="mt-2" :disabled="isViewMode" />
|
||||
</el-form-item>
|
||||
|
||||
<!-- 家属姓名 -->
|
||||
<el-form-item label="家属姓名" prop="relativeInfo">
|
||||
<div class="flex items-center gap-2">
|
||||
<el-select v-if="showRelativeSelect && (formData.relatedEmployeeId || formData.newRelatedEmployeeName)"
|
||||
v-model="formData.relativeId" placeholder="请选择家属" filterable :loading="relativeLoading" class="flex-1"
|
||||
@change="handleRelativeChange" @clear="handleRelativeClear" :disabled="isViewMode">
|
||||
<el-option v-for="item in relativeOptions" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
<el-input v-else v-model="formData.newRelativeName" placeholder="请输入家属姓名" class="flex-1"
|
||||
:disabled="!formData.relatedEmployeeId && !formData.newRelatedEmployeeName || isViewMode" />
|
||||
<!-- 新增/编辑模式显示"新增家属"按钮 -->
|
||||
<el-button
|
||||
v-if="!isViewMode && showRelativeSelect && formData.relatedEmployeeId && !formData.newRelatedEmployeeName"
|
||||
type="primary" size="small" @click="handleOpenAddRelativeDialog">
|
||||
新增家属
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 亲属关系 -->
|
||||
<el-form-item label="亲属关系" prop="relationShip">
|
||||
<el-select v-model="formData.relationShip" placeholder="请选择亲属关系" :disabled="isViewMode">
|
||||
<el-option v-for="item in relationTypes" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<!-- 出生日期、体重、身高 -->
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="出生日期" prop="birthday">
|
||||
<el-date-picker v-model="formData.birthday" type="date" placeholder="请选择出生日期" format="YYYY-MM-DD"
|
||||
value-format="YYYY-MM-DD" class="w-full" :disabled="isViewMode" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="当前体重(kg)" prop="weight">
|
||||
<el-input-number v-model="formData.weight" :min="0" :max="500" :precision="1" placeholder="请输入体重"
|
||||
class="w-full" :disabled="isViewMode" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="身高(cm)" prop="height">
|
||||
<el-input-number v-model="formData.height" :min="0" :max="300" :precision="1" placeholder="请输入身高"
|
||||
class="w-full" :disabled="isViewMode" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
|
||||
<!-- 2. 药材消耗 -->
|
||||
<el-card class="form-section" shadow="never">
|
||||
<template #header>
|
||||
<div class="section-title">
|
||||
药材消耗
|
||||
<!-- 新增/编辑模式显示"添加药材"按钮 -->
|
||||
<el-button v-if="!isViewMode" type="primary" size="small" class="ml-4" @click="addHerb">
|
||||
添加药材
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-table :data="formData.herbs" border>
|
||||
<el-table-column label="药材名称--剩余量" width="200">
|
||||
<template #default="{ row, $index }">
|
||||
<el-select v-model="row.id" placeholder="请选择药材" filterable :loading="medicinalLoading"
|
||||
@change="handleMedicinalChange($index)" :disabled="isViewMode">
|
||||
<el-option v-for="item in medicinalOptions" :key="item.id"
|
||||
:label="`${item.medicinalName}--${item.stock}g`" :value="item.id" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="消耗(g)" width="200">
|
||||
<template #default="{ row }">
|
||||
<el-input-number v-model="row.amountG" :min="0" :precision="2" placeholder="消耗量" class="w-full"
|
||||
:disabled="isViewMode" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" min-width="80">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model="row.note" placeholder="请输入备注" :disabled="isViewMode" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="80">
|
||||
<template #default="{ $index }">
|
||||
<!-- 新增/编辑模式显示"移除"按钮 -->
|
||||
<el-button v-if="!isViewMode" type="danger" size="small" @click="removeHerb($index)">
|
||||
移除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<!-- 3. 诊断信息 -->
|
||||
<el-card class="form-section" shadow="never">
|
||||
<template #header>
|
||||
<div class="section-title">诊断信息</div>
|
||||
</template>
|
||||
|
||||
<el-form-item label="诊断结果" prop="diagnosisResult">
|
||||
<el-input v-model="formData.diagnosisResult" type="textarea" :rows="3" placeholder="请输入诊断结果"
|
||||
:disabled="isViewMode" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="用药建议" prop="userMedicinaAdvice">
|
||||
<el-input v-model="formData.userMedicinaAdvice" type="textarea" :rows="3" placeholder="请输入用药建议"
|
||||
:disabled="isViewMode" />
|
||||
</el-form-item>
|
||||
</el-card>
|
||||
|
||||
<!-- 4. 就诊信息 -->
|
||||
<el-card class="form-section" shadow="never">
|
||||
<template #header>
|
||||
<div class="section-title">就诊信息</div>
|
||||
</template>
|
||||
|
||||
<el-form-item label="就诊时间" prop="visitDate">
|
||||
<el-date-picker v-model="formData.visitDate" type="datetime" placeholder="请选择就诊时间" format="YYYY-MM-DD HH:mm"
|
||||
value-format="YYYY-MM-DD HH:mm:ss" class="w-full" :disabled="isViewMode" />
|
||||
</el-form-item>
|
||||
</el-card>
|
||||
</el-form>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="handleClose">取消</el-button>
|
||||
<!-- 新增/编辑模式显示提交按钮 -->
|
||||
<el-button v-if="!isViewMode" type="primary" :loading="submitLoading" @click="handleSubmit">
|
||||
{{ isEdit ? '更新' : '保存' }}
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 新增员工弹窗(仅在新增/编辑模式显示) -->
|
||||
<el-dialog v-if="!isViewMode" v-model="showAddEmployeeDialog" title="新增员工" width="400px">
|
||||
<el-form :model="newEmployeeForm" label-width="80px" ref="newEmployeeFormRef">
|
||||
<el-form-item label="员工姓名" prop="name">
|
||||
<el-input v-model="newEmployeeForm.name" placeholder="请输入员工姓名" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="showAddEmployeeDialog = false">取消</el-button>
|
||||
<el-button type="primary" @click="confirmAddEmployee">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 新增关联员工弹窗(仅在新增/编辑模式显示) -->
|
||||
<el-dialog v-if="!isViewMode" v-model="showAddRelatedEmployeeDialog" title="新增关联员工" width="400px">
|
||||
<el-form :model="newRelatedEmployeeForm" label-width="80px" ref="newRelatedEmployeeFormRef">
|
||||
<el-form-item label="员工姓名" prop="name">
|
||||
<el-input v-model="newRelatedEmployeeForm.name" placeholder="请输入员工姓名" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="showAddRelatedEmployeeDialog = false">取消</el-button>
|
||||
<el-button type="primary" @click="confirmAddRelatedEmployee">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 新增家属弹窗(仅在新增/编辑模式显示) -->
|
||||
<el-dialog v-if="!isViewMode" v-model="showAddRelativeDialog" title="新增家属" width="400px">
|
||||
<el-form :model="newRelativeForm" label-width="80px" ref="newRelativeFormRef">
|
||||
<el-form-item label="家属姓名" prop="name">
|
||||
<el-input v-model="newRelativeForm.name" placeholder="请输入家属姓名" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="showAddRelativeDialog = false">取消</el-button>
|
||||
<el-button type="primary" @click="confirmAddRelative">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import type { FormInstance, FormRules } from 'element-plus'
|
||||
|
||||
import { prescriptionApi } from '@/api'
|
||||
import { medicinalApi } from '@/api/modules/biz/weibingju/medicinal'
|
||||
|
||||
// 接口定义
|
||||
interface Employee {
|
||||
id: string | number;
|
||||
name: string;
|
||||
birthday?: string;
|
||||
height?: number;
|
||||
}
|
||||
interface Relative {
|
||||
id: string | number;
|
||||
name: string;
|
||||
employeeId?: string | number;
|
||||
birthday?: string;
|
||||
height?: number;
|
||||
relationShip?: number;
|
||||
}
|
||||
interface Medicinal { id: number | string; medicinalName: string; stock: number }
|
||||
interface Herb { id?: number | string; medicinalName: string; amountG: number; note: string }
|
||||
|
||||
// Props定义:区分新增(无id)、编辑(有id且isEdit=true)、查看(有id且isEdit=false)
|
||||
interface Props {
|
||||
visible: boolean;
|
||||
prescriptionId?: number;
|
||||
isEdit: boolean
|
||||
}
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
visible: false,
|
||||
prescriptionId: undefined,
|
||||
isEdit: false
|
||||
})
|
||||
const emit = defineEmits<{
|
||||
"update:visible": [value: boolean];
|
||||
"refresh-list": [];
|
||||
}>()
|
||||
|
||||
// 核心模式判断:查看模式 = 有处方ID且非编辑
|
||||
const isViewMode = computed(() => !!props.prescriptionId && !props.isEdit)
|
||||
// 弹窗标题:根据模式动态显示
|
||||
const dialogTitle = computed(() => {
|
||||
if (isViewMode.value) return '查看就诊处方'
|
||||
return props.isEdit ? '编辑就诊处方' : '新增就诊处方'
|
||||
})
|
||||
|
||||
// 表单引用 & 状态
|
||||
const formRef = ref<FormInstance>()
|
||||
const newEmployeeFormRef = ref<FormInstance>()
|
||||
const newRelatedEmployeeFormRef = ref<FormInstance>()
|
||||
const newRelativeFormRef = ref<FormInstance>()
|
||||
const submitLoading = ref(false)
|
||||
const isEdit = computed(() => props.isEdit)
|
||||
|
||||
// 表单数据
|
||||
const formData = ref({
|
||||
personType: 1,
|
||||
employeeId: undefined as string | number | undefined,
|
||||
newEmployeeName: '',
|
||||
relatedEmployeeId: undefined as string | number | undefined,
|
||||
newRelatedEmployeeName: '',
|
||||
relativeId: undefined as string | number | undefined,
|
||||
newRelativeName: '',
|
||||
relationShip: undefined as number | undefined,
|
||||
birthday: undefined as string | undefined,
|
||||
weight: undefined as number | undefined,
|
||||
height: undefined as number | undefined,
|
||||
herbs: [] as Herb[],
|
||||
diagnosisResult: '',
|
||||
userMedicinaAdvice: '',
|
||||
visitDate: ''
|
||||
})
|
||||
|
||||
// 表单校验规则
|
||||
const formRules: FormRules = {
|
||||
personType: [{ required: true, message: '请选择人员类型', trigger: 'change' }],
|
||||
employeeInfo: [{
|
||||
required: true,
|
||||
validator: (rule, value, callback) => {
|
||||
if (formData.value.personType === 1) {
|
||||
if (!formData.value.employeeId && !formData.value.newEmployeeName) {
|
||||
callback(new Error('请选择或输入员工姓名'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
},
|
||||
trigger: ['change', 'blur']
|
||||
}],
|
||||
relatedEmployeeInfo: [{
|
||||
required: true,
|
||||
validator: (rule, value, callback) => {
|
||||
if (formData.value.personType === 2) {
|
||||
if (!formData.value.relatedEmployeeId && !formData.value.newRelatedEmployeeName) {
|
||||
callback(new Error('请选择或输入关联员工姓名'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
},
|
||||
trigger: ['change', 'blur']
|
||||
}],
|
||||
relativeInfo: [{
|
||||
required: true,
|
||||
validator: (rule, value, callback) => {
|
||||
if (formData.value.personType === 2) {
|
||||
if (!formData.value.relativeId && !formData.value.newRelativeName) {
|
||||
callback(new Error('请选择或输入家属姓名'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
},
|
||||
trigger: ['change', 'blur']
|
||||
}],
|
||||
relationShip: [{
|
||||
required: formData.value.personType === 2,
|
||||
message: '请选择亲属关系',
|
||||
trigger: 'change'
|
||||
}],
|
||||
visitDate: [{ required: true, message: '请选择就诊时间', trigger: 'change' }],
|
||||
diagnosisResult: [{ required: true, message: '请输入诊断结果', trigger: 'blur' }]
|
||||
}
|
||||
|
||||
// 数据源 & 弹窗状态
|
||||
const employeeOptions = ref<Employee[]>([])
|
||||
const employeeLoading = ref(false)
|
||||
const showEmployeeSelect = ref(true)
|
||||
const showRelatedEmployeeSelect = ref(true)
|
||||
|
||||
const relativeOptions = ref<Relative[]>([])
|
||||
const relativeLoading = ref(false)
|
||||
const showRelativeSelect = ref(true)
|
||||
|
||||
const relationTypes = ref<{ id: number; name: string }[]>([])
|
||||
const medicinalOptions = ref<Medicinal[]>([])
|
||||
const medicinalLoading = ref(false)
|
||||
|
||||
const showAddEmployeeDialog = ref(false)
|
||||
const showAddRelatedEmployeeDialog = ref(false)
|
||||
const showAddRelativeDialog = ref(false)
|
||||
const newEmployeeForm = ref({ name: '' })
|
||||
const newRelatedEmployeeForm = ref({ name: '' })
|
||||
const newRelativeForm = ref({ name: '' })
|
||||
|
||||
// 本地临时人员集合
|
||||
const localCreatedPersons = ref<Array<{
|
||||
tempId: string
|
||||
name: string
|
||||
isEmployee: boolean
|
||||
employeeTempId?: string
|
||||
employeeId?: number
|
||||
relationShip?: number
|
||||
}>>([])
|
||||
|
||||
// 生成临时ID
|
||||
const genTempId = (prefix = 'tmp') => `${prefix}_${Date.now()}_${Math.floor(Math.random() * 1000)}`
|
||||
|
||||
// 检查名称重复
|
||||
const checkNameDuplicate = (name: string, isEmployee: boolean) => {
|
||||
const normalizedName = name.trim()
|
||||
if (isEmployee) {
|
||||
return employeeOptions.value.some(item =>
|
||||
(item.name || '').trim() === normalizedName ||
|
||||
localCreatedPersons.value.some(p => p.isEmployee && p.name.trim() === normalizedName)
|
||||
)
|
||||
} else {
|
||||
return relativeOptions.value.some(item =>
|
||||
(item.name || '').trim() === normalizedName ||
|
||||
localCreatedPersons.value.some(p => !p.isEmployee && p.name.trim() === normalizedName)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// 加载数据接口
|
||||
const fetchEmployees = async (keyword?: string) => {
|
||||
try {
|
||||
employeeLoading.value = true
|
||||
const params: any = { type: 1 }
|
||||
if (keyword) params.keyword = keyword
|
||||
const res: any = await prescriptionApi.getPersonList(params)
|
||||
employeeOptions.value = (res && res.data) ? res.data : []
|
||||
} catch (err) {
|
||||
console.error('获取员工列表失败', err)
|
||||
employeeOptions.value = []
|
||||
} finally {
|
||||
employeeLoading.value = false
|
||||
}
|
||||
}
|
||||
const loadRelatives = async (employeeId: number | string) => {
|
||||
try {
|
||||
relativeLoading.value = true
|
||||
if (typeof employeeId === 'string' && employeeId.startsWith('tmp_')) {
|
||||
relativeOptions.value = []
|
||||
showRelativeSelect.value = false
|
||||
ElMessage.info('该员工为本地新增,暂无家属数据,请手动输入家属姓名')
|
||||
} else {
|
||||
const res: any = await prescriptionApi.getPersonList({ type: 2, employeeId })
|
||||
relativeOptions.value = (res && res.data) ? res.data : []
|
||||
showRelativeSelect.value = relativeOptions.value.length > 0
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('加载家属失败', err)
|
||||
relativeOptions.value = []
|
||||
showRelativeSelect.value = false
|
||||
} finally {
|
||||
relativeLoading.value = false
|
||||
}
|
||||
}
|
||||
const fetchRelationTypes = async () => {
|
||||
try {
|
||||
const res: any = await prescriptionApi.getRelationTypes()
|
||||
relationTypes.value = (res && res.data) ? res.data : []
|
||||
} catch (err) {
|
||||
relationTypes.value = [
|
||||
{ id: 1, name: '配偶' },
|
||||
{ id: 2, name: '子女' },
|
||||
{ id: 3, name: '父母' },
|
||||
{ id: 4, name: '兄弟姐妹' },
|
||||
{ id: 5, name: '其他' }
|
||||
]
|
||||
console.error('获取关系类型失败', err)
|
||||
}
|
||||
}
|
||||
const loadAllMedicinals = async () => {
|
||||
try {
|
||||
medicinalLoading.value = true
|
||||
const res: any = await medicinalApi.getDictList()
|
||||
medicinalOptions.value = (res && res.data) ? res.data : []
|
||||
} catch (err) {
|
||||
console.error('加载药材失败', err)
|
||||
medicinalOptions.value = []
|
||||
} finally {
|
||||
medicinalLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 选择回调
|
||||
const handleEmployeeChange = (selectedId: string | number | undefined) => {
|
||||
if (selectedId && !isViewMode.value) { // 仅在非查看模式执行
|
||||
formData.value.newEmployeeName = ''
|
||||
showEmployeeSelect.value = true
|
||||
const selectedEmployee = employeeOptions.value.find(item => item.id === selectedId)
|
||||
if (selectedEmployee) {
|
||||
formData.value.birthday = selectedEmployee.birthday
|
||||
formData.value.height = selectedEmployee.height
|
||||
}
|
||||
}
|
||||
}
|
||||
const handleEmployeeClear = () => {
|
||||
if (!isViewMode.value) { // 仅在非查看模式执行
|
||||
formData.value.newEmployeeName = ''
|
||||
formData.value.birthday = undefined
|
||||
formData.value.height = undefined
|
||||
}
|
||||
}
|
||||
const handleRelatedEmployeeChange = (selectedId: string | number | undefined) => {
|
||||
if (selectedId && !isViewMode.value) { // 仅在非查看模式执行
|
||||
formData.value.newRelatedEmployeeName = ''
|
||||
showRelatedEmployeeSelect.value = true
|
||||
formData.value.relativeId = undefined
|
||||
formData.value.newRelativeName = ''
|
||||
loadRelatives(selectedId)
|
||||
}
|
||||
}
|
||||
const handleRelatedEmployeeClear = () => {
|
||||
if (!isViewMode.value) { // 仅在非查看模式执行
|
||||
formData.value.newRelatedEmployeeName = ''
|
||||
formData.value.relativeId = undefined
|
||||
formData.value.newRelativeName = ''
|
||||
formData.value.birthday = undefined
|
||||
formData.value.height = undefined
|
||||
formData.value.relationShip = undefined
|
||||
relativeOptions.value = []
|
||||
}
|
||||
}
|
||||
const handleRelativeChange = (selectedId: string | number | undefined) => {
|
||||
if (selectedId && !isViewMode.value) { // 仅在非查看模式执行
|
||||
formData.value.newRelativeName = ''
|
||||
showRelativeSelect.value = true
|
||||
const selectedRelative = relativeOptions.value.find(item => item.id === selectedId)
|
||||
if (selectedRelative) {
|
||||
formData.value.birthday = selectedRelative.birthday
|
||||
formData.value.height = selectedRelative.height
|
||||
formData.value.relationShip = selectedRelative.relationShip
|
||||
}
|
||||
}
|
||||
}
|
||||
const handleRelativeClear = () => {
|
||||
if (!isViewMode.value) { // 仅在非查看模式执行
|
||||
formData.value.newRelativeName = ''
|
||||
formData.value.birthday = undefined
|
||||
formData.value.height = undefined
|
||||
formData.value.relationShip = undefined
|
||||
}
|
||||
}
|
||||
const handleMedicinalChange = (index: number) => {
|
||||
if (!isViewMode.value) { // 仅在非查看模式执行
|
||||
const selectedMedicinalId = formData.value.herbs[index].id;
|
||||
if (selectedMedicinalId) {
|
||||
const sel = medicinalOptions.value.find(m => m.id === selectedMedicinalId);
|
||||
formData.value.herbs[index].medicinalName = sel ? sel.medicinalName : '';
|
||||
} else {
|
||||
formData.value.herbs[index].medicinalName = '';
|
||||
}
|
||||
}
|
||||
};
|
||||
const handlePersonTypeChange = () => {
|
||||
if (!isViewMode.value) { // 仅在非查看模式执行
|
||||
formData.value.employeeId = undefined
|
||||
formData.value.newEmployeeName = ''
|
||||
formData.value.relatedEmployeeId = undefined
|
||||
formData.value.newRelatedEmployeeName = ''
|
||||
formData.value.relativeId = undefined
|
||||
formData.value.newRelativeName = ''
|
||||
formData.value.relationShip = undefined
|
||||
formData.value.birthday = undefined
|
||||
formData.value.height = undefined
|
||||
showEmployeeSelect.value = true
|
||||
showRelatedEmployeeSelect.value = true
|
||||
showRelativeSelect.value = true
|
||||
}
|
||||
}
|
||||
const addHerb = () => {
|
||||
if (!isViewMode.value) { // 仅在非查看模式执行
|
||||
formData.value.herbs.push({ id: undefined, medicinalName: '', amountG: 0, note: '' })
|
||||
}
|
||||
}
|
||||
const removeHerb = (index: number) => {
|
||||
if (!isViewMode.value) { // 仅在非查看模式执行
|
||||
formData.value.herbs.splice(index, 1)
|
||||
}
|
||||
}
|
||||
|
||||
// 新增员工相关
|
||||
const handleOpenAddEmployeeDialog = () => {
|
||||
if (!isViewMode.value) {
|
||||
formData.value.employeeId = undefined
|
||||
formData.value.newEmployeeName = ''
|
||||
formData.value.birthday = undefined
|
||||
formData.value.height = undefined
|
||||
newEmployeeForm.value.name = ''
|
||||
showAddEmployeeDialog.value = true
|
||||
}
|
||||
}
|
||||
const confirmAddEmployee = async () => {
|
||||
if (!newEmployeeFormRef.value || isViewMode.value) return
|
||||
try {
|
||||
await newEmployeeFormRef.value.validate()
|
||||
const name = newEmployeeForm.value.name.trim()
|
||||
if (checkNameDuplicate(name, true)) {
|
||||
ElMessage.warning('该员工姓名已存在,请更换姓名')
|
||||
return
|
||||
}
|
||||
const tempId = genTempId('tmp_emp')
|
||||
employeeOptions.value.unshift({ id: tempId, name })
|
||||
localCreatedPersons.value.push({ tempId, name, isEmployee: true })
|
||||
formData.value.employeeId = tempId
|
||||
formData.value.newEmployeeName = ''
|
||||
formData.value.birthday = undefined
|
||||
formData.value.height = undefined
|
||||
showEmployeeSelect.value = true
|
||||
showAddEmployeeDialog.value = false
|
||||
newEmployeeForm.value.name = ''
|
||||
ElMessage.success('员工已添加')
|
||||
} catch (err) { }
|
||||
}
|
||||
|
||||
// 新增关联员工相关
|
||||
const handleOpenAddRelatedEmployeeDialog = () => {
|
||||
if (!isViewMode.value) {
|
||||
formData.value.relatedEmployeeId = undefined
|
||||
formData.value.newRelatedEmployeeName = ''
|
||||
formData.value.relativeId = undefined
|
||||
formData.value.newRelativeName = ''
|
||||
formData.value.birthday = undefined
|
||||
formData.value.height = undefined
|
||||
formData.value.relationShip = undefined
|
||||
newRelatedEmployeeForm.value.name = ''
|
||||
showAddRelatedEmployeeDialog.value = true
|
||||
}
|
||||
}
|
||||
const confirmAddRelatedEmployee = async () => {
|
||||
if (!newRelatedEmployeeFormRef.value || isViewMode.value) return
|
||||
try {
|
||||
await newRelatedEmployeeFormRef.value.validate()
|
||||
const name = newRelatedEmployeeForm.value.name.trim()
|
||||
if (checkNameDuplicate(name, true)) {
|
||||
ElMessage.warning('该员工姓名已存在,请更换姓名')
|
||||
return
|
||||
}
|
||||
const tempId = genTempId('tmp_emp')
|
||||
employeeOptions.value.unshift({ id: tempId, name })
|
||||
localCreatedPersons.value.push({ tempId, name, isEmployee: true })
|
||||
formData.value.relatedEmployeeId = tempId
|
||||
formData.value.newRelatedEmployeeName = ''
|
||||
formData.value.relativeId = undefined
|
||||
formData.value.newRelativeName = ''
|
||||
formData.value.birthday = undefined
|
||||
formData.value.height = undefined
|
||||
formData.value.relationShip = undefined
|
||||
showRelatedEmployeeSelect.value = true
|
||||
showAddRelatedEmployeeDialog.value = false
|
||||
newRelatedEmployeeForm.value.name = ''
|
||||
loadRelatives(tempId)
|
||||
ElMessage.success('关联员工已添加')
|
||||
} catch (err) { }
|
||||
}
|
||||
|
||||
// 新增家属相关
|
||||
const handleOpenAddRelativeDialog = () => {
|
||||
if (!isViewMode.value) {
|
||||
formData.value.relativeId = undefined
|
||||
formData.value.newRelativeName = ''
|
||||
formData.value.birthday = undefined
|
||||
formData.value.height = undefined
|
||||
formData.value.relationShip = undefined
|
||||
newRelativeForm.value.name = ''
|
||||
showAddRelativeDialog.value = true
|
||||
}
|
||||
}
|
||||
const confirmAddRelative = async () => {
|
||||
if (!newRelativeFormRef.value || isViewMode.value) return
|
||||
try {
|
||||
await newRelativeFormRef.value.validate()
|
||||
const name = newRelativeForm.value.name.trim()
|
||||
const employeeId = formData.value.relatedEmployeeId
|
||||
if (!employeeId) {
|
||||
ElMessage.warning('请先选择关联员工')
|
||||
return
|
||||
}
|
||||
if (checkNameDuplicate(name, false)) {
|
||||
ElMessage.warning('该家属姓名已存在,请更换姓名')
|
||||
return
|
||||
}
|
||||
const tempId = genTempId('tmp_rel')
|
||||
relativeOptions.value.unshift({ id: tempId, name, employeeId })
|
||||
localCreatedPersons.value.push({
|
||||
tempId,
|
||||
name,
|
||||
isEmployee: false,
|
||||
employeeTempId: typeof employeeId === 'string' && employeeId.startsWith('tmp_') ? employeeId : undefined,
|
||||
employeeId: typeof employeeId === 'number' ? employeeId : undefined,
|
||||
relationShip: formData.value.relationShip
|
||||
})
|
||||
formData.value.relativeId = tempId
|
||||
formData.value.newRelativeName = ''
|
||||
formData.value.birthday = undefined
|
||||
formData.value.height = undefined
|
||||
formData.value.relationShip = undefined
|
||||
showRelativeSelect.value = true
|
||||
showAddRelativeDialog.value = false
|
||||
newRelativeForm.value.name = ''
|
||||
ElMessage.success('家属已添加')
|
||||
} catch (err) { }
|
||||
}
|
||||
|
||||
// 重置/关闭/提交
|
||||
const handleClose = () => {
|
||||
emit('update:visible', false)
|
||||
resetForm()
|
||||
}
|
||||
const handleVisibleChange = (value: boolean) => {
|
||||
emit('update:visible', value)
|
||||
if (!value) resetForm()
|
||||
}
|
||||
const resetForm = () => {
|
||||
formData.value = {
|
||||
personType: 1,
|
||||
employeeId: undefined,
|
||||
newEmployeeName: '',
|
||||
relatedEmployeeId: undefined,
|
||||
newRelatedEmployeeName: '',
|
||||
relativeId: undefined,
|
||||
newRelativeName: '',
|
||||
relationShip: undefined,
|
||||
birthday: undefined,
|
||||
weight: undefined,
|
||||
height: undefined,
|
||||
herbs: [],
|
||||
diagnosisResult: '',
|
||||
userMedicinaAdvice: '',
|
||||
visitDate: ''
|
||||
}
|
||||
localCreatedPersons.value = []
|
||||
showEmployeeSelect.value = true
|
||||
showRelatedEmployeeSelect.value = true
|
||||
showRelativeSelect.value = true
|
||||
newEmployeeForm.value.name = ''
|
||||
newRelatedEmployeeForm.value.name = ''
|
||||
newRelativeForm.value.name = ''
|
||||
showAddEmployeeDialog.value = false
|
||||
showAddRelatedEmployeeDialog.value = false
|
||||
showAddRelativeDialog.value = false
|
||||
}
|
||||
const handleSubmit = async () => {
|
||||
if (!formRef.value || isViewMode.value) return
|
||||
try {
|
||||
await formRef.value.validate()
|
||||
} catch (err) {
|
||||
return
|
||||
}
|
||||
|
||||
submitLoading.value = true
|
||||
try {
|
||||
const personObj: any = {}
|
||||
const isPatientEmployee = formData.value.personType === 1
|
||||
personObj.isEmployee = isPatientEmployee
|
||||
|
||||
if (isPatientEmployee) {
|
||||
if (formData.value.employeeId) {
|
||||
if (typeof formData.value.employeeId === 'string' && String(formData.value.employeeId).startsWith('tmp_')) {
|
||||
const tmpEmp = localCreatedPersons.value.find(p => p.tempId === formData.value.employeeId && p.isEmployee)
|
||||
const name = tmpEmp ? tmpEmp.name : undefined
|
||||
if (name) {
|
||||
personObj.name = name
|
||||
personObj.employeeIsTemp = true
|
||||
personObj.employeeName = name
|
||||
} else {
|
||||
personObj.name = employeeOptions.value.find(e => e.id === formData.value.employeeId)?.name
|
||||
personObj.employeeIsTemp = true
|
||||
personObj.employeeName = personObj.name
|
||||
}
|
||||
} else {
|
||||
personObj.id = Number(formData.value.employeeId)
|
||||
personObj.name = employeeOptions.value.find(e => e.id === formData.value.employeeId)?.name
|
||||
}
|
||||
} else if (formData.value.newEmployeeName) {
|
||||
personObj.name = formData.value.newEmployeeName.trim()
|
||||
personObj.employeeIsTemp = true
|
||||
personObj.employeeName = personObj.name
|
||||
}
|
||||
} else {
|
||||
if (formData.value.relativeId) {
|
||||
if (typeof formData.value.relativeId === 'string' && String(formData.value.relativeId).startsWith('tmp_')) {
|
||||
const tmpRel = localCreatedPersons.value.find(p => p.tempId === formData.value.relativeId && !p.isEmployee)
|
||||
personObj.name = tmpRel ? tmpRel.name : relativeOptions.value.find(r => r.id === formData.value.relativeId)?.name
|
||||
personObj.tempId = formData.value.relativeId
|
||||
} else {
|
||||
personObj.id = Number(formData.value.relativeId)
|
||||
personObj.name = relativeOptions.value.find(r => r.id === formData.value.relativeId)?.name
|
||||
}
|
||||
} else if (formData.value.newRelativeName) {
|
||||
personObj.name = formData.value.newRelativeName.trim()
|
||||
}
|
||||
|
||||
if (formData.value.relatedEmployeeId) {
|
||||
if (typeof formData.value.relatedEmployeeId === 'string' && String(formData.value.relatedEmployeeId).startsWith('tmp_')) {
|
||||
const tmpEmp = localCreatedPersons.value.find(p => p.tempId === formData.value.relatedEmployeeId && p.isEmployee)
|
||||
const name = tmpEmp ? tmpEmp.name : employeeOptions.value.find(e => e.id === formData.value.relatedEmployeeId)?.name
|
||||
if (name) {
|
||||
personObj.employeeIsTemp = true
|
||||
personObj.employeeName = name
|
||||
} else {
|
||||
personObj.employeeId = formData.value.relatedEmployeeId
|
||||
}
|
||||
} else {
|
||||
personObj.employeeId = Number(formData.value.relatedEmployeeId)
|
||||
}
|
||||
} else if (formData.value.newRelatedEmployeeName) {
|
||||
personObj.employeeIsTemp = true
|
||||
personObj.employeeName = formData.value.newRelatedEmployeeName.trim()
|
||||
}
|
||||
|
||||
personObj.relationShip = formData.value.relationShip
|
||||
}
|
||||
|
||||
if ((!personObj.name || personObj.name === undefined) && personObj.id && typeof personObj.id === 'string' && String(personObj.id).startsWith('tmp_')) {
|
||||
const tmp = localCreatedPersons.value.find(p => p.tempId === personObj.id)
|
||||
if (tmp) personObj.name = tmp.name
|
||||
}
|
||||
|
||||
personObj.birthday = formData.value.birthday
|
||||
personObj.weight = formData.value.weight
|
||||
personObj.height = formData.value.height
|
||||
|
||||
const herbsPayload = formData.value.herbs.map(h => ({
|
||||
id: h.id || 0,
|
||||
amountG: h.amountG,
|
||||
note: h.note
|
||||
}))
|
||||
|
||||
const payload: any = {
|
||||
id: props.prescriptionId ?? undefined,
|
||||
person: personObj,
|
||||
diagnosisResult: formData.value.diagnosisResult,
|
||||
userMedicinaAdvice: formData.value.userMedicinaAdvice,
|
||||
visitDate: formData.value.visitDate,
|
||||
herbs: herbsPayload
|
||||
}
|
||||
|
||||
const res: any = await prescriptionApi.save(payload)
|
||||
|
||||
if (res && (res.code === 0 || res.data !== undefined)) {
|
||||
ElMessage.success(props.isEdit ? '处方更新成功' : '处方保存成功')
|
||||
emit('refresh-list')
|
||||
handleClose()
|
||||
} else {
|
||||
ElMessage.success('保存成功')
|
||||
emit('refresh-list')
|
||||
handleClose()
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('保存处方失败', err)
|
||||
} finally {
|
||||
submitLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 监听弹窗显示
|
||||
watch(() => props.visible, async (newVal) => {
|
||||
if (newVal) {
|
||||
resetForm()
|
||||
await Promise.all([
|
||||
fetchEmployees(),
|
||||
fetchRelationTypes(),
|
||||
loadAllMedicinals()
|
||||
])
|
||||
|
||||
// 编辑/查看模式:加载详情
|
||||
if ((props.isEdit || isViewMode.value) && props.prescriptionId) {
|
||||
try {
|
||||
const res: any = await prescriptionApi.getDetail(props.prescriptionId)
|
||||
const detail = res?.data ?? null
|
||||
|
||||
if (detail) {
|
||||
const person = detail.person || {}
|
||||
formData.value.personType = person.isEmployee ? 1 : 2
|
||||
|
||||
if (formData.value.personType === 1) {
|
||||
formData.value.employeeId = person.id ?? undefined
|
||||
formData.value.birthday = person.birthday ?? undefined
|
||||
formData.value.height = person.height ?? undefined
|
||||
} else {
|
||||
formData.value.relatedEmployeeId = person.employeeId ?? undefined
|
||||
formData.value.relativeId = person.id ?? undefined
|
||||
formData.value.birthday = person.birthday ?? undefined
|
||||
formData.value.height = person.height ?? undefined
|
||||
formData.value.relationShip = person.relationShip ?? undefined
|
||||
if (formData.value.relatedEmployeeId) {
|
||||
loadRelatives(formData.value.relatedEmployeeId)
|
||||
}
|
||||
}
|
||||
|
||||
formData.value.weight = person.weight ?? undefined
|
||||
formData.value.diagnosisResult = detail.diagnosisResult ?? ''
|
||||
formData.value.userMedicinaAdvice = detail.userMedicinaAdvice ?? ''
|
||||
formData.value.visitDate = detail.visitDate ?? ''
|
||||
formData.value.herbs = (detail.herbs || []).map((h: any) => ({
|
||||
id: h.medicinalId,
|
||||
medicinalName: h.medicinalName,
|
||||
amountG: h.amountG,
|
||||
note: h.note || ''
|
||||
}))
|
||||
}
|
||||
} catch (err) {
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.modal-class {
|
||||
max-height: 60vh !important;
|
||||
overflow-y: auto !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.prescription-form {
|
||||
.form-section {
|
||||
margin-bottom: 20px;
|
||||
|
||||
.section-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dialog-footer {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.items-center {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.gap-2 {
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.flex-1 {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.ml-4 {
|
||||
margin-left: 16px;
|
||||
}
|
||||
|
||||
.w-full {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.mt-2 {
|
||||
margin-top: 8px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,375 @@
|
||||
<template>
|
||||
<el-dialog v-model="visibleRef" title="处方报告" width="1500px" :body-class="'report-modal-body'" :show-close="false"
|
||||
:top="'0'" append-to-body>
|
||||
<!-- 报告核心内容 -->
|
||||
<div class="report-content">
|
||||
<!-- 3.1 就诊人基本信息 -->
|
||||
<div class="report-section">
|
||||
<h3 class="section-heading">一、就诊人基本信息</h3>
|
||||
<div class="info-grid">
|
||||
<div class="info-item">
|
||||
<span class="info-label">就诊人姓名:</span>
|
||||
<span class="info-value">{{ reportData.patientName || "暂无数据" }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="info-label">出生日期:</span>
|
||||
<span class="info-value">{{ reportData.birthday || "暂无数据" }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="info-label">身高:</span>
|
||||
<span class="info-value">{{ reportData.height ? `${reportData.height} cm` : "暂无数据" }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="info-label">体重:</span>
|
||||
<span class="info-value">{{ reportData.weight ? `${reportData.weight} kg` : "暂无数据" }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="info-label">就诊时间:</span>
|
||||
<span class="info-value">{{ reportData.visitDate || "暂无数据" }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 3.2 药材消耗明细(超紧凑卡片布局) -->
|
||||
<div class="report-section mt-16">
|
||||
<h3 class="section-heading">二、药材消耗明细</h3>
|
||||
<div class="herbs-grid-container">
|
||||
<!-- 单个药材卡片(更小尺寸) -->
|
||||
<div class="herb-card" v-for="(herb, index) in reportData.herbs" :key="index">
|
||||
<div class="herb-name">
|
||||
<span class="herb-label">名称:</span>
|
||||
{{ herb.medicinalName || "未命名药材" }}
|
||||
</div>
|
||||
<div class="herb-amount">
|
||||
<span class="herb-label">用量:</span>
|
||||
{{ herb.amountG !== undefined ? `${herb.amountG} g` : "0 g" }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 无药材空状态 -->
|
||||
<div v-if="reportData.herbs.length === 0" class="empty-herbs">
|
||||
<el-icon size="24" color="#9ca3af" class="empty-icon">
|
||||
<DocumentEmpty />
|
||||
</el-icon>
|
||||
<p class="empty-text">当前处方暂无药材消耗记录</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 3.3 诊断与用药建议 -->
|
||||
<div class="report-section mt-16">
|
||||
<h3 class="section-heading">三、诊断与用药建议</h3>
|
||||
<div class="advice-container">
|
||||
<div class="advice-item">
|
||||
<span class="advice-label">诊断结果:</span>
|
||||
<div class="advice-content">
|
||||
{{ reportData.diagnosisResult || "暂无诊断结果描述" }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="advice-item mt-8">
|
||||
<span class="advice-label">用药建议:</span>
|
||||
<div class="advice-content">
|
||||
{{ reportData.userMedicinaAdvice || "暂无用药建议描述" }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="handleClose">关闭报告</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from "vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { prescriptionApi } from "@/api";
|
||||
|
||||
// Props定义
|
||||
interface Props {
|
||||
modelValue: boolean;
|
||||
prescriptionId?: number;
|
||||
}
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
modelValue: false,
|
||||
prescriptionId: undefined,
|
||||
});
|
||||
|
||||
// 弹窗显隐控制
|
||||
const visibleRef = ref(props.modelValue);
|
||||
const emit = defineEmits<{
|
||||
"update:modelValue": [value: boolean];
|
||||
}>();
|
||||
|
||||
// 监听父组件传值,同步弹窗状态
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(newVal) => {
|
||||
visibleRef.value = newVal;
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
// 数据状态
|
||||
const loading = ref(false);
|
||||
const error = ref(false);
|
||||
const errorMsg = ref("");
|
||||
const reportData = ref({
|
||||
patientName: "",
|
||||
birthday: "",
|
||||
height: undefined,
|
||||
weight: undefined,
|
||||
visitDate: "",
|
||||
herbs: [] as Array<{ medicinalName: string; amountG: number; note: string }>,
|
||||
diagnosisResult: "",
|
||||
userMedicinaAdvice: "",
|
||||
});
|
||||
|
||||
// 加载报告数据
|
||||
const fetchReportData = async () => {
|
||||
if (!props.prescriptionId) return;
|
||||
try {
|
||||
loading.value = true;
|
||||
error.value = false;
|
||||
const res: any = await prescriptionApi.getDetail(props.prescriptionId);
|
||||
const detail = res?.data || {};
|
||||
const person = detail.person || {};
|
||||
reportData.value = {
|
||||
patientName: person.name || "",
|
||||
birthday: person.birthday || "",
|
||||
height: person.height,
|
||||
weight: person.weight,
|
||||
visitDate: detail.visitDate || "",
|
||||
herbs: (detail.herbs || []).map((h: any) => ({
|
||||
medicinalName: h.medicinalName || "未命名药材",
|
||||
amountG: h.amountG || 0,
|
||||
note: h.note || "",
|
||||
})),
|
||||
diagnosisResult: detail.diagnosisResult || "",
|
||||
userMedicinaAdvice: detail.userMedicinaAdvice || "",
|
||||
};
|
||||
} catch (err: any) {
|
||||
error.value = true;
|
||||
errorMsg.value = err.message || "加载报告失败,请检查网络";
|
||||
ElMessage.error(errorMsg.value);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 关闭弹窗
|
||||
const handleClose = () => {
|
||||
emit("update:modelValue", false);
|
||||
};
|
||||
|
||||
// 弹窗关闭前重置数据
|
||||
const handleBeforeClose = () => {
|
||||
reportData.value = {
|
||||
patientName: "",
|
||||
birthday: "",
|
||||
height: undefined,
|
||||
weight: undefined,
|
||||
visitDate: "",
|
||||
herbs: [],
|
||||
diagnosisResult: "",
|
||||
userMedicinaAdvice: "",
|
||||
};
|
||||
error.value = false;
|
||||
errorMsg.value = "";
|
||||
};
|
||||
|
||||
// 监听处方ID变化,重新加载数据
|
||||
watch(
|
||||
() => props.prescriptionId,
|
||||
(newId) => {
|
||||
if (props.modelValue && newId) {
|
||||
fetchReportData();
|
||||
}
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.report-modal-body {
|
||||
// padding: 20px !important;
|
||||
font-size: 14px;
|
||||
color: #303133;
|
||||
background: #fff;
|
||||
overflow-y: auto !important;
|
||||
max-height: 100vh !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* 报告通用样式 */
|
||||
.report-content {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.report-section {
|
||||
padding: 15px;
|
||||
border: 1px solid #e6e6e6;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 16px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.section-heading {
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
color: #1f2937;
|
||||
margin: 0 0 12px 0;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 2px solid #409eff;
|
||||
}
|
||||
|
||||
/* 就诊人基本信息样式 */
|
||||
.info-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
font-weight: 600;
|
||||
color: #4b5563;
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
flex: 1;
|
||||
word-break: break-all;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
/* 药材消耗明细样式(超紧凑设计) */
|
||||
.herbs-grid-container {
|
||||
// display: grid;
|
||||
// /* 核心:每列最小宽度缩小到150px,可根据需要进一步减小到120px */
|
||||
// grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
|
||||
// gap: 8px;
|
||||
/* 卡片间距缩小 */
|
||||
padding: 8px 0;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 15px;
|
||||
|
||||
}
|
||||
|
||||
/* 单个药材卡片(更小尺寸) */
|
||||
.herb-card {
|
||||
padding: 8px;
|
||||
/* 内边距大幅缩小 */
|
||||
border: 1px solid #e6e6e6;
|
||||
border-radius: 4px;
|
||||
background: #f9fafb;
|
||||
line-height: 1.3;
|
||||
/* 行高压缩 */
|
||||
font-size: 12px;
|
||||
/* 字体缩小 */
|
||||
min-width: 70px;
|
||||
}
|
||||
|
||||
/* 卡片内标签样式 */
|
||||
.herb-label {
|
||||
font-weight: 600;
|
||||
color: #4b5563;
|
||||
font-size: 13px;
|
||||
/* 标签字体更小 */
|
||||
}
|
||||
|
||||
/* 药材空状态样式 */
|
||||
.empty-herbs {
|
||||
grid-column: 1 / -1;
|
||||
text-align: center;
|
||||
padding: 30px 0;
|
||||
color: #9ca3af;
|
||||
background: #f9fafb;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
/* 诊断与用药建议样式 */
|
||||
.advice-container {
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.advice-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.advice-label {
|
||||
font-weight: 600;
|
||||
color: #4b5563;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.advice-content {
|
||||
padding: 8px 12px;
|
||||
border: 1px solid #e6e6e6;
|
||||
border-radius: 4px;
|
||||
min-height: 60px;
|
||||
line-height: 1.5;
|
||||
background: #f9fafb;
|
||||
word-break: break-all;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
/* 间距工具类 */
|
||||
.mt-8 {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.mt-16 {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
/* 加载/错误样式 */
|
||||
.loading-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
.loading-text {
|
||||
margin-top: 16px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.error-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 300px;
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.error-icon {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.error-text {
|
||||
margin-bottom: 16px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.retry-btn {
|
||||
min-width: 100px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,122 @@
|
||||
<template>
|
||||
<div class="table-box">
|
||||
<!-- 原有:处方列表(仅操作列新增“查看报告”按钮) -->
|
||||
<ProTable ref="proTable" title="处方列表" :columns="columns" :request-api="getPrescriptionListApi" :row-key="rowKey">
|
||||
<!-- 原有:表格头部按钮(不变) -->
|
||||
<template #tableHeader>
|
||||
<s-button suffix="处方" type="success" @click="handleAddPrescription" />
|
||||
</template>
|
||||
|
||||
<!-- 原有:就诊人类型自定义插槽(不变) -->
|
||||
<template #personType="scope">
|
||||
<el-space>
|
||||
<span v-if="scope.row.personType === 1">公司员工</span>
|
||||
<span v-else-if="scope.row.personType === 2">
|
||||
员工家属,所属员工:{{ scope.row.employeeName || "未知" }}
|
||||
</span>
|
||||
<span v-else>未知类型</span>
|
||||
</el-space>
|
||||
</template>
|
||||
|
||||
<!-- 关键改动:操作列新增“查看报告”按钮 -->
|
||||
<template #operation="{ row }">
|
||||
<s-button link :opt="FormOptEnum.VIEW" size="small" @click="handleViewDetail(row.id)">
|
||||
查看详情
|
||||
</s-button>
|
||||
<s-button v-if="row.canEdit" link :opt="FormOptEnum.EDIT" size="small" class="ml-2" @click="handleEdit(row.id)">
|
||||
编辑
|
||||
</s-button>
|
||||
<!-- 新增:触发报告弹窗 -->
|
||||
<s-button link :opt="FormOptEnum.VIEW" size="small" class="ml-2" @click="handleOpenReport(row.id)">
|
||||
查看报告
|
||||
</s-button>
|
||||
</template>
|
||||
</ProTable>
|
||||
|
||||
<!-- 原有:处方详情/编辑弹窗(不变) -->
|
||||
<PrescriptionDetailDialog v-model:visible="showDetailDialog" :prescription-id="currentPrescriptionId"
|
||||
:is-edit="isEdit" @refresh-list="handleRefresh" />
|
||||
|
||||
<!-- 关键改动:引入独立的报告弹窗组件 -->
|
||||
<PrescriptionReportDialog v-model="showReportDialog" :prescription-id="currentReportId" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="PrescriptionModule">
|
||||
import { ref } from "vue";
|
||||
import ProTable from "@/components/ProTable/index.vue";
|
||||
import type { ProTableInstance, ColumnProps } from "@/components/ProTable/interface";
|
||||
import { prescriptionApi } from "@/api";
|
||||
// 原有:引入详情弹窗组件(不变)
|
||||
import PrescriptionDetailDialog from "./components/PrescriptionDetailDialog.vue";
|
||||
// 关键改动:引入独立的报告弹窗组件
|
||||
import PrescriptionReportDialog from "./components/PrescriptionReportDialog.vue";
|
||||
import { FormOptEnum } from "@/enums";
|
||||
|
||||
// 原有:表格ref、详情弹窗状态(不变)
|
||||
const proTable = ref<ProTableInstance | null>(null);
|
||||
const showDetailDialog = ref(false);
|
||||
const currentPrescriptionId = ref<number | undefined>(undefined);
|
||||
const isEdit = ref(false);
|
||||
|
||||
// 关键改动:新增报告弹窗相关状态
|
||||
const showReportDialog = ref(false); // 报告弹窗显隐
|
||||
const currentReportId = ref<number | undefined>(undefined); // 当前报告对应的处方ID
|
||||
|
||||
// 原有:就诊人类型选项、表格列配置(不变)
|
||||
const personTypeOptions = [
|
||||
{ label: "公司员工", value: 1 },
|
||||
{ label: "员工家属", value: 2 }
|
||||
];
|
||||
const columns: ColumnProps<any>[] = [
|
||||
{ type: "selection", fixed: "left", width: 80 },
|
||||
{ prop: "personName", label: "就诊人", search: { el: "input" } },
|
||||
{
|
||||
prop: "personType",
|
||||
label: "就诊人类型",
|
||||
sortable: false,
|
||||
enum: personTypeOptions,
|
||||
search: { el: "select" }
|
||||
},
|
||||
{ prop: "visitDate", label: "就诊时间" },
|
||||
{ prop: "totalMedicineCost", label: "预估处方药材成本(元)" },
|
||||
{ prop: "operation", label: "操作", width: 280, fixed: "right" }
|
||||
];
|
||||
const rowKey = "id";
|
||||
const getPrescriptionListApi = (params: any) => {
|
||||
return prescriptionApi.getList(params);
|
||||
};
|
||||
|
||||
// 原有:新增、查看详情、编辑、刷新逻辑(不变)
|
||||
const handleAddPrescription = () => {
|
||||
currentPrescriptionId.value = undefined;
|
||||
isEdit.value = false;
|
||||
showDetailDialog.value = true;
|
||||
};
|
||||
const handleViewDetail = (id: number) => {
|
||||
currentPrescriptionId.value = id;
|
||||
isEdit.value = false;
|
||||
showDetailDialog.value = true;
|
||||
};
|
||||
const handleEdit = (id: number) => {
|
||||
currentPrescriptionId.value = id;
|
||||
isEdit.value = true;
|
||||
showDetailDialog.value = true;
|
||||
};
|
||||
const handleRefresh = () => {
|
||||
proTable.value?.refresh?.();
|
||||
};
|
||||
|
||||
// 关键改动:新增“打开报告弹窗”方法
|
||||
const handleOpenReport = (id: number) => {
|
||||
currentReportId.value = id; // 传递当前处方ID给报告组件
|
||||
showReportDialog.value = true; // 显示报告弹窗
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* 原有样式(不变):确保操作列按钮不换行 */
|
||||
.table-box {
|
||||
padding: 16px;
|
||||
}
|
||||
</style>
|
||||
@@ -19,17 +19,17 @@
|
||||
<el-tab-pane label="账号登录" name="pwd">
|
||||
<LoginForm :tenant-option="props.sysTenantOption" :tenant-options="props.tenantOptions" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="手机号登录" name="phone">
|
||||
<!-- <el-tab-pane label="手机号登录" name="phone">
|
||||
<LoginPhoneForm :tenant-option="props.sysTenantOption" :tenant-options="props.tenantOptions" />
|
||||
</el-tab-pane>
|
||||
</el-tab-pane> -->
|
||||
</el-tabs>
|
||||
<div class="fixed-corner">
|
||||
<span>{{ props.sysVersion }}</span>
|
||||
<!-- <span>{{ props.sysVersion }}</span> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Footer />
|
||||
<!-- <Footer /> -->
|
||||
<choose-module v-if="auth.showChooseModule" :show-modal="true" />
|
||||
</template>
|
||||
|
||||
@@ -62,7 +62,7 @@ interface LoginProps {
|
||||
|
||||
//默认值
|
||||
const props = reactive<LoginProps>({
|
||||
sysName: "SimpleAdmin",
|
||||
sysName: "未病局管理系统",
|
||||
sysVersion: "",
|
||||
sysLogo: "",
|
||||
sysTenantOption: TenantEnum.CLOSE,
|
||||
@@ -107,7 +107,8 @@ function updateSysConfig(props: LoginProps, config: ReturnType<typeof useConfigS
|
||||
|
||||
<style scoped lang="scss">
|
||||
@use "./index";
|
||||
.demo-tabs > .el-tabs__content {
|
||||
|
||||
.demo-tabs>.el-tabs__content {
|
||||
padding: 32px;
|
||||
font-size: 32px;
|
||||
font-weight: 600;
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
<template>
|
||||
<!-- 关键修改:v-model → :visible + @update:visible -->
|
||||
<el-dialog :visible="visible" @update:visible="handleUpdateVisible" :title="`${medicinalName} - 消耗记录`" width="800px">
|
||||
<el-table v-loading="loading" :data="consumptionRecords" border style="width: 100%" empty-text="暂无消耗记录">
|
||||
<el-table-column prop="amountG" label="使用量(g)" width="120"></el-table-column>
|
||||
<el-table-column label="使用人员" width="200">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.personName }}</span>
|
||||
<el-tag size="small" type="info" v-if="scope.row.isRelative" style="margin-left: 8px">
|
||||
家属({{ scope.row.employeeName || "未知员工" }})
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="useTime" label="使用时间" width="200">
|
||||
<template #default="scope">
|
||||
{{ scope.row.useTime ? new Date(scope.row.useTime).toLocaleString() : "-" }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineProps, defineEmits, ref, watch } from "vue";
|
||||
import { getConsumptionRecords, Medicinal } from "@/api/modules/biz/WeiBingJu/medicinal";
|
||||
import { ElMessage } from "element-plus";
|
||||
|
||||
// 1. 接收父组件prop
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
medicinalId: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
medicinalName: {
|
||||
type: String,
|
||||
default: "药材"
|
||||
}
|
||||
});
|
||||
|
||||
// 2. 定义发射事件:update:visible + 关闭通知
|
||||
const emit = defineEmits(["update:visible", "close"]);
|
||||
|
||||
// 状态数据
|
||||
const loading = ref(false);
|
||||
const consumptionRecords = ref<Medicinal.ConsumptionRecord[]>([]);
|
||||
|
||||
// 3. 监听弹窗状态变化
|
||||
const handleUpdateVisible = (newVisible: boolean) => {
|
||||
emit("update:visible", newVisible);
|
||||
// 弹窗关闭时清空数据
|
||||
if (!newVisible) {
|
||||
consumptionRecords.value = [];
|
||||
emit("close");
|
||||
}
|
||||
};
|
||||
|
||||
// 监听visible变化:弹窗显示时加载消耗记录
|
||||
watch(
|
||||
() => props.visible,
|
||||
async newVal => {
|
||||
if (newVal && props.medicinalId) {
|
||||
await fetchConsumptionRecords();
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
// 加载消耗记录
|
||||
const fetchConsumptionRecords = async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
const res = await getConsumptionRecords({ medicinalId: props.medicinalId });
|
||||
consumptionRecords.value = res;
|
||||
} catch (err: any) {
|
||||
ElMessage.error(err.message || "加载消耗记录失败");
|
||||
consumptionRecords.value = [];
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,714 +0,0 @@
|
||||
<template>
|
||||
<el-dialog :model-value="visible" @update:model-value="handleUpdateVisible" :title="dialogTitle" width="900px" destroy-on-close>
|
||||
<!-- 人员信息 -->
|
||||
<el-card shadow="hover" class="mb-4">
|
||||
<template #header><span>人员信息</span></template>
|
||||
<el-form :model="personForm" label-width="120px" :disabled="!isEdit" ref="personFormRef" :rules="personFormRules">
|
||||
<!-- 1. 人员类型 -->
|
||||
<el-form-item label="人员类型" required prop="isEmployee">
|
||||
<el-radio-group v-model="personForm.isEmployee" @change="handlePersonTypeChange">
|
||||
<el-radio :label="true">公司员工</el-radio>
|
||||
<el-radio :label="false">员工家属</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 2. 员工场景:员工选择/新增 -->
|
||||
<template v-if="personForm.isEmployee">
|
||||
<!-- 员工下拉选择(默认显示) -->
|
||||
<el-form-item v-if="showEmployeeSelect" label="员工姓名" required prop="employeeId">
|
||||
<el-select
|
||||
v-model="personForm.employeeId"
|
||||
placeholder="搜索或选择员工"
|
||||
filterable
|
||||
remote
|
||||
:remote-method="handleEmployeeSearch"
|
||||
@change="handleEmployeeChange"
|
||||
clearable
|
||||
>
|
||||
<!-- 正常员工选项 -->
|
||||
<el-option v-for="emp in employeeOptions" :key="emp.id" :label="emp.name" :value="emp.id" />
|
||||
<!-- 未找到选项(仅搜索后无结果时显示) -->
|
||||
<el-option v-if="employeeOptions.length === 0 && employeeKeyword" :key="0" :label="`未找到,新增员工:${employeeKeyword}`" :value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 员工新增文本框(点击"未找到"后显示) -->
|
||||
<el-form-item v-if="!showEmployeeSelect" label="员工姓名" required prop="newEmployeeName">
|
||||
<el-input
|
||||
v-model="personForm.newEmployeeName"
|
||||
placeholder="输入新员工姓名"
|
||||
@blur="() => (personForm.name = personForm.newEmployeeName)"
|
||||
/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<!-- 3. 家属场景:关联员工选择 + 家属选择/新增 -->
|
||||
<template v-else>
|
||||
<!-- 3.1 关联员工选择(第一步) -->
|
||||
<el-form-item v-if="showRelatedEmployeeSelect" label="关联员工" required prop="relatedEmployeeId">
|
||||
<el-select
|
||||
v-model="personForm.relatedEmployeeId"
|
||||
placeholder="搜索或选择关联员工"
|
||||
filterable
|
||||
remote
|
||||
:remote-method="handleRelatedEmployeeSearch"
|
||||
@change="handleRelatedEmployeeChange"
|
||||
clearable
|
||||
>
|
||||
<!-- 正常关联员工选项 -->
|
||||
<el-option v-for="emp in relatedEmployeeOptions" :key="emp.id" :label="emp.name" :value="emp.id" />
|
||||
<!-- 未找到选项 -->
|
||||
<el-option
|
||||
v-if="relatedEmployeeOptions.length === 0 && relatedEmployeeKeyword"
|
||||
:key="0"
|
||||
:label="`未找到,新增关联员工:${relatedEmployeeKeyword}`"
|
||||
:value="0"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 3.2 关联员工新增(点击"未找到"后显示) -->
|
||||
<el-form-item v-if="!showRelatedEmployeeSelect" label="关联员工姓名" required prop="newRelatedEmployeeName">
|
||||
<el-input v-model="personForm.newRelatedEmployeeName" placeholder="输入新关联员工姓名" />
|
||||
</el-form-item>
|
||||
|
||||
<!-- 3.3 家属选择(选择关联员工后显示) -->
|
||||
<el-form-item v-if="showRelativeSelect && personForm.relatedEmployeeId" label="家属姓名" required prop="relativeId">
|
||||
<el-select
|
||||
v-model="personForm.relativeId"
|
||||
placeholder="搜索或选择家属"
|
||||
filterable
|
||||
remote
|
||||
:remote-method="handleRelativeSearch"
|
||||
@change="handleRelativeChange"
|
||||
clearable
|
||||
>
|
||||
<!-- 正常家属选项 -->
|
||||
<el-option v-for="rel in relativeOptions" :key="rel.id" :label="rel.name" :value="rel.id" />
|
||||
<!-- 未找到选项 -->
|
||||
<el-option v-if="relativeOptions.length === 0 && relativeKeyword" :key="0" :label="`未找到,新增家属:${relativeKeyword}`" :value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 3.4 家属新增(点击"未找到"后显示 / 关联员工新增时同步显示) -->
|
||||
<el-form-item v-if="!showRelativeSelect || !showRelatedEmployeeSelect" label="家属姓名" required prop="newRelativeName">
|
||||
<el-input
|
||||
v-model="personForm.newRelativeName"
|
||||
placeholder="输入新家属姓名"
|
||||
@blur="() => (personForm.name = personForm.newRelativeName)"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 3.5 亲属关系(家属场景必选) -->
|
||||
<el-form-item label="亲属关系" required prop="relationShip" v-if="personForm.relatedEmployeeId || !showRelatedEmployeeSelect">
|
||||
<el-select v-model="personForm.relationShip" clearable>
|
||||
<el-option v-for="item in relationTypes" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<!-- 4. 公共信息:年龄/体重/身高(复用原有逻辑) -->
|
||||
<el-form-item label="年龄" prop="age">
|
||||
<el-input v-model.number="personForm.age" placeholder="输入年龄" />
|
||||
</el-form-item>
|
||||
<el-form-item label="体重(kg)" prop="weight">
|
||||
<el-input v-model.number="personForm.weight" placeholder="输入体重" />
|
||||
</el-form-item>
|
||||
<el-form-item label="身高(cm)" prop="height">
|
||||
<el-input v-model.number="personForm.height" placeholder="输入身高" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- 药材消耗、诊断建议等原有模块(保持不变) -->
|
||||
<el-card shadow="hover" class="mb-4">
|
||||
<template #header>
|
||||
<div class="flex justify-between items-center">
|
||||
<span>药材消耗</span>
|
||||
<el-button v-if="isEdit" type="primary" size="small" @click="handleAddHerb"> 添加药材 </el-button>
|
||||
</div>
|
||||
</template>
|
||||
<el-table :data="herbList" border :disabled="!isEdit" empty-text="暂无药材消耗记录">
|
||||
<el-table-column label="药材名称" required>
|
||||
<template #default="scope">
|
||||
<el-select
|
||||
v-model="scope.row.medicinalId"
|
||||
placeholder="搜索或选择药材"
|
||||
filterable
|
||||
remote
|
||||
:remote-method="kw => handleHerbSearch(kw, scope.$index)"
|
||||
@change="val => handleHerbChange(val, scope.$index)"
|
||||
:disabled="!isEdit"
|
||||
clearable
|
||||
>
|
||||
<el-option v-for="item in scope.row.medicinalOptions" :key="item.id" :label="item.name" :value="item.id" />
|
||||
<el-option
|
||||
v-if="scope.row.medicinalOptions.length === 0 && scope.row.keyword"
|
||||
:key="0"
|
||||
:label="`新增药材:${scope.row.keyword}`"
|
||||
:value="0"
|
||||
/>
|
||||
</el-select>
|
||||
<el-input v-if="scope.row.showNewInput" v-model="scope.row.newName" placeholder="输入新药材名称" class="mt-2" :disabled="!isEdit" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="消耗(g)" required>
|
||||
<template #default="scope">
|
||||
<el-input v-model.number="scope.row.amountG" type="number" min="0.1" placeholder="输入消耗克数" :disabled="!isEdit" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注">
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.note" placeholder="输入备注" :disabled="!isEdit" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" v-if="isEdit">
|
||||
<template #default="scope">
|
||||
<el-button type="text" text-color="#ff4d4f" @click="handleDeleteHerb(scope.$index)"> 删除 </el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<div class="flex gap-4 mb-4">
|
||||
<el-card shadow="hover" class="flex-1">
|
||||
<template #header><span>诊断结果</span></template>
|
||||
<el-input v-model="prescriptionForm.diagnosisResult" type="textarea" rows="5" placeholder="输入诊断结果" :disabled="!isEdit" />
|
||||
</el-card>
|
||||
<el-card shadow="hover" class="flex-1">
|
||||
<template #header><span>用药建议</span></template>
|
||||
<el-input v-model="prescriptionForm.userMedicinaAdvice" type="textarea" rows="5" placeholder="输入用药建议" :disabled="!isEdit" />
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<el-card shadow="hover" class="mb-4">
|
||||
<el-form-item label="就诊时间" required>
|
||||
<el-date-picker
|
||||
v-model="prescriptionForm.visitDate"
|
||||
type="datetime"
|
||||
placeholder="选择就诊时间"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
:disabled="!isEdit"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-card>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="handleCancel">取消</el-button>
|
||||
<el-button type="primary" @click="handleSave" v-if="isEdit">
|
||||
{{ prescriptionId ? "保存修改" : "新增处方" }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, watch, computed, nextTick } from "vue";
|
||||
import { ElMessage, ElMessageBox, ElForm, FormItemRule } from "element-plus";
|
||||
import { prescriptionApi } from "@/api/modules/biz/WeiBingJu/prescription";
|
||||
|
||||
// 1. props/emit定义
|
||||
const props = defineProps({
|
||||
visible: { type: Boolean, default: false },
|
||||
prescriptionId: { type: Number, default: 0 },
|
||||
isEdit: { type: Boolean, default: false }
|
||||
});
|
||||
const emit = defineEmits(["update:visible", "close", "refreshList"]);
|
||||
|
||||
// 2. 基础变量
|
||||
const dialogTitle = computed(() => {
|
||||
if (props.prescriptionId === 0) return "新增就诊处方";
|
||||
return props.isEdit ? "编辑处方" : "处方详情";
|
||||
});
|
||||
const loading = ref(false);
|
||||
const personFormRef = ref<InstanceType<typeof ElForm>>();
|
||||
const relationTypes = ref<any[]>([]); // 亲属关系列表
|
||||
const herbList = ref<any[]>([]); // 药材列表(原有逻辑)
|
||||
|
||||
// 3. 处方表单(原有逻辑)
|
||||
const prescriptionForm = reactive({
|
||||
diagnosisResult: "",
|
||||
userMedicinaAdvice: "",
|
||||
visitDate: new Date().toISOString().slice(0, 16) // 默认当前时间
|
||||
});
|
||||
|
||||
// 4. 人员表单(核心重构:区分员工/家属场景)
|
||||
const personForm = reactive({
|
||||
// 基础字段
|
||||
id: undefined, // 人员ID(编辑时用)
|
||||
name: "", // 人员姓名(最终提交用)
|
||||
isEmployee: true, // 是否员工(true=员工,false=家属)
|
||||
|
||||
// 员工场景字段
|
||||
employeeId: undefined, // 已选员工ID
|
||||
newEmployeeName: "", // 新增员工姓名
|
||||
|
||||
// 家属场景字段
|
||||
relatedEmployeeId: undefined, // 关联员工ID
|
||||
newRelatedEmployeeName: "", // 新增关联员工姓名
|
||||
relativeId: undefined, // 已选家属ID
|
||||
newRelativeName: "", // 新增家属姓名
|
||||
relationShip: undefined, // 亲属关系ID
|
||||
|
||||
// 公共字段
|
||||
age: undefined,
|
||||
weight: undefined,
|
||||
height: undefined
|
||||
});
|
||||
|
||||
// 5. 下拉/新增状态控制(核心:控制显示隐藏)
|
||||
const state = reactive({
|
||||
// 员工场景
|
||||
showEmployeeSelect: true, // 是否显示员工下拉(默认显示)
|
||||
employeeOptions: [] as any[], // 员工下拉选项
|
||||
employeeKeyword: "", // 员工搜索关键词
|
||||
|
||||
// 家属场景
|
||||
showRelatedEmployeeSelect: true, // 是否显示关联员工下拉(默认显示)
|
||||
relatedEmployeeOptions: [] as any[], // 关联员工下拉选项
|
||||
relatedEmployeeKeyword: "", // 关联员工搜索关键词
|
||||
|
||||
showRelativeSelect: true, // 是否显示家属下拉(默认显示)
|
||||
relativeOptions: [] as any[], // 家属下拉选项
|
||||
relativeKeyword: "" // 家属搜索关键词
|
||||
});
|
||||
|
||||
// 6. 表单验证规则
|
||||
const personFormRules = reactive<Record<string, FormItemRule[]>>({
|
||||
isEmployee: [{ required: true, message: "请选择人员类型", trigger: "change" }],
|
||||
employeeId: [{ required: true, message: "请选择员工", trigger: "change" }],
|
||||
newEmployeeName: [{ required: true, message: "请输入员工姓名", trigger: "blur" }],
|
||||
relatedEmployeeId: [{ required: true, message: "请选择关联员工", trigger: "change" }],
|
||||
newRelatedEmployeeName: [{ required: true, message: "请输入关联员工姓名", trigger: "blur" }],
|
||||
relativeId: [{ required: true, message: "请选择家属", trigger: "change" }],
|
||||
newRelativeName: [{ required: true, message: "请输入家属姓名", trigger: "blur" }],
|
||||
relationShip: [{ required: true, message: "请选择亲属关系", trigger: "change" }],
|
||||
age: [{ type: "number", message: "请输入合法年龄", trigger: "blur" }],
|
||||
weight: [{ type: "number", message: "请输入合法体重", trigger: "blur" }],
|
||||
height: [{ type: "number", message: "请输入合法身高", trigger: "blur" }]
|
||||
});
|
||||
|
||||
// 7. 初始化逻辑(监听弹窗显示/隐藏)
|
||||
watch(
|
||||
() => props.visible,
|
||||
async val => {
|
||||
if (val) {
|
||||
await fetchRelationTypes(); // 加载亲属关系
|
||||
if (props.prescriptionId) {
|
||||
await fetchPrescriptionDetail(); // 编辑/详情:加载已有数据
|
||||
} else {
|
||||
resetForm(); // 新增:重置表单
|
||||
}
|
||||
} else {
|
||||
resetForm(); // 弹窗关闭:重置表单
|
||||
emit("close");
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
// 8. 基础接口请求(原有逻辑优化)
|
||||
// 加载亲属关系
|
||||
const fetchRelationTypes = async () => {
|
||||
try {
|
||||
const res = await prescriptionApi.getRelationTypes();
|
||||
relationTypes.value = res || [];
|
||||
} catch (err) {
|
||||
relationTypes.value = [];
|
||||
ElMessage.error("加载亲属关系失败");
|
||||
}
|
||||
};
|
||||
|
||||
// 加载处方详情(编辑/详情场景)
|
||||
const fetchPrescriptionDetail = async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
const res = await prescriptionApi.getDetail({ id: props.prescriptionId });
|
||||
if (!res) return;
|
||||
|
||||
// 填充处方信息
|
||||
prescriptionForm.diagnosisResult = res.diagnosisResult || "";
|
||||
prescriptionForm.userMedicinaAdvice = res.userMedicinaAdvice || "";
|
||||
prescriptionForm.visitDate = res.visitDate || new Date().toISOString().slice(0, 16);
|
||||
|
||||
// 填充人员信息
|
||||
const { person } = res;
|
||||
if (person) {
|
||||
personForm.id = person.id;
|
||||
personForm.name = person.name;
|
||||
personForm.isEmployee = person.EmployeeId === undefined; // 员工:EmployeeId为空
|
||||
personForm.age = person.age;
|
||||
personForm.weight = person.weight;
|
||||
personForm.height = person.height;
|
||||
personForm.relationShip = person.RelationShip;
|
||||
|
||||
// 员工场景:赋值员工ID
|
||||
if (personForm.isEmployee) {
|
||||
personForm.employeeId = person.id;
|
||||
state.employeeOptions = [{ id: person.id, name: person.name }];
|
||||
}
|
||||
// 家属场景:赋值关联员工ID和家属ID
|
||||
else {
|
||||
personForm.relatedEmployeeId = person.EmployeeId;
|
||||
personForm.relativeId = person.id;
|
||||
// 加载关联员工选项
|
||||
state.relatedEmployeeOptions = [{ id: person.EmployeeId, name: res.employeeName || "" }];
|
||||
// 加载家属选项
|
||||
state.relativeOptions = [{ id: person.id, name: person.name }];
|
||||
}
|
||||
}
|
||||
|
||||
// 填充药材信息(原有逻辑)
|
||||
herbList.value = (res.herbs || []).map((h: any) => ({
|
||||
medicinalId: h.medicinalId,
|
||||
medicinalOptions: [{ id: h.medicinalId, name: h.medicinalName }],
|
||||
keyword: h.medicinalName,
|
||||
showNewInput: false,
|
||||
newName: "",
|
||||
amountG: h.amountG,
|
||||
note: h.note || ""
|
||||
}));
|
||||
} catch (err) {
|
||||
ElMessage.error("加载处方详情失败");
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 9. 员工场景交互逻辑
|
||||
// 员工下拉搜索
|
||||
const handleEmployeeSearch = async (keyword: string) => {
|
||||
state.employeeKeyword = keyword.trim();
|
||||
if (!keyword) {
|
||||
state.employeeOptions = [];
|
||||
return;
|
||||
}
|
||||
// 调用接口查询员工(personType=1表示员工)
|
||||
const res = await prescriptionApi.getPersonList({ personType: 1, keyword });
|
||||
state.employeeOptions = res || [];
|
||||
};
|
||||
|
||||
// 员工下拉选择(含"未找到"逻辑)
|
||||
const handleEmployeeChange = async (val: number) => {
|
||||
if (val === 0) {
|
||||
// 点击"未找到":隐藏下拉,显示新增文本框
|
||||
state.showEmployeeSelect = false;
|
||||
personForm.employeeId = undefined; // 清空下拉值
|
||||
personForm.newEmployeeName = state.employeeKeyword; // 预填搜索关键词
|
||||
} else {
|
||||
// 选择已有员工:显示下拉,清空新增文本框
|
||||
state.showEmployeeSelect = true;
|
||||
personForm.newEmployeeName = "";
|
||||
// 赋值人员姓名
|
||||
const selectedEmp = state.employeeOptions.find(emp => emp.id === val);
|
||||
if (selectedEmp) personForm.name = selectedEmp.name;
|
||||
}
|
||||
};
|
||||
|
||||
// 10. 家属场景交互逻辑
|
||||
// 关联员工下拉搜索
|
||||
const handleRelatedEmployeeSearch = async (keyword: string) => {
|
||||
state.relatedEmployeeKeyword = keyword.trim();
|
||||
if (!keyword) {
|
||||
state.relatedEmployeeOptions = [];
|
||||
return;
|
||||
}
|
||||
// 调用接口查询员工(personType=1表示员工)
|
||||
const res = await prescriptionApi.getPersonList({ personType: 1, keyword });
|
||||
state.relatedEmployeeOptions = res || [];
|
||||
};
|
||||
|
||||
// 关联员工下拉选择(含"未找到"逻辑)
|
||||
const handleRelatedEmployeeChange = async (val: number) => {
|
||||
if (val === 0) {
|
||||
// 点击"未找到":隐藏关联员工下拉,显示新增文本框+家属新增文本框
|
||||
state.showRelatedEmployeeSelect = false;
|
||||
state.showRelativeSelect = false; // 隐藏家属下拉
|
||||
personForm.relatedEmployeeId = undefined;
|
||||
personForm.newRelatedEmployeeName = state.relatedEmployeeKeyword;
|
||||
personForm.relativeId = undefined;
|
||||
} else {
|
||||
// 选择已有关联员工:显示关联员工下拉,加载家属列表
|
||||
state.showRelatedEmployeeSelect = true;
|
||||
state.showRelativeSelect = true; // 显示家属下拉
|
||||
personForm.newRelatedEmployeeName = "";
|
||||
personForm.newRelativeName = "";
|
||||
// 加载该员工的家属(personType=2表示家属,传employeeId)
|
||||
await handleLoadRelatives(val);
|
||||
}
|
||||
};
|
||||
|
||||
// 加载关联员工的家属列表
|
||||
const handleLoadRelatives = async (employeeId: number) => {
|
||||
try {
|
||||
const res = await prescriptionApi.getPersonList({
|
||||
personType: 2, // 假设personType=2表示家属
|
||||
employeeId
|
||||
});
|
||||
state.relativeOptions = res || [];
|
||||
} catch (err) {
|
||||
state.relativeOptions = [];
|
||||
ElMessage.error("加载家属列表失败");
|
||||
}
|
||||
};
|
||||
|
||||
// 家属下拉搜索
|
||||
const handleRelativeSearch = async (keyword: string) => {
|
||||
state.relativeKeyword = keyword.trim();
|
||||
if (!keyword || !personForm.relatedEmployeeId) {
|
||||
state.relativeOptions = [];
|
||||
return;
|
||||
}
|
||||
// 调用接口查询家属(传关联员工ID)
|
||||
const res = await prescriptionApi.getPersonList({
|
||||
personType: 2,
|
||||
employeeId: personForm.relatedEmployeeId,
|
||||
keyword
|
||||
});
|
||||
state.relativeOptions = res || [];
|
||||
};
|
||||
|
||||
// 家属下拉选择(含"未找到"逻辑)
|
||||
const handleRelativeChange = async (val: number) => {
|
||||
if (val === 0) {
|
||||
// 点击"未找到":隐藏家属下拉,显示家属新增文本框
|
||||
state.showRelativeSelect = false;
|
||||
personForm.relativeId = undefined;
|
||||
personForm.newRelativeName = state.relativeKeyword;
|
||||
} else {
|
||||
// 选择已有家属:显示家属下拉,清空新增文本框
|
||||
state.showRelativeSelect = true;
|
||||
personForm.newRelativeName = "";
|
||||
// 赋值家属姓名
|
||||
const selectedRel = state.relativeOptions.find(rel => rel.id === val);
|
||||
if (selectedRel) personForm.name = selectedRel.name;
|
||||
}
|
||||
};
|
||||
|
||||
// 11. 人员类型切换逻辑(重置状态)
|
||||
const handlePersonTypeChange = () => {
|
||||
// 重置所有状态
|
||||
state.showEmployeeSelect = true;
|
||||
state.showRelatedEmployeeSelect = true;
|
||||
state.showRelativeSelect = true;
|
||||
state.employeeOptions = [];
|
||||
state.relatedEmployeeOptions = [];
|
||||
state.relativeOptions = [];
|
||||
state.employeeKeyword = "";
|
||||
state.relatedEmployeeKeyword = "";
|
||||
state.relativeKeyword = "";
|
||||
|
||||
// 重置表单字段
|
||||
personForm.employeeId = undefined;
|
||||
personForm.newEmployeeName = "";
|
||||
personForm.relatedEmployeeId = undefined;
|
||||
personForm.newRelatedEmployeeName = "";
|
||||
personForm.relativeId = undefined;
|
||||
personForm.newRelativeName = "";
|
||||
personForm.relationShip = undefined;
|
||||
personForm.name = "";
|
||||
|
||||
// 重置表单验证
|
||||
nextTick(() => {
|
||||
personFormRef.value?.clearValidate();
|
||||
});
|
||||
};
|
||||
|
||||
// 12. 药材相关逻辑(保持原有)
|
||||
const handleAddHerb = () => {
|
||||
herbList.value.push({
|
||||
medicinalId: undefined,
|
||||
medicinalOptions: [],
|
||||
keyword: "",
|
||||
showNewInput: false,
|
||||
newName: "",
|
||||
amountG: undefined,
|
||||
note: ""
|
||||
});
|
||||
};
|
||||
|
||||
const handleDeleteHerb = (index: number) => {
|
||||
herbList.value.splice(index, 1);
|
||||
};
|
||||
|
||||
const handleHerbSearch = async (keyword: string, index: number) => {
|
||||
const res = await prescriptionApi.searchMedicinals({ keyword });
|
||||
herbList.value[index].keyword = keyword;
|
||||
herbList.value[index].medicinalOptions = res || [];
|
||||
};
|
||||
|
||||
const handleHerbChange = (val: number | 0, index: number) => {
|
||||
if (val === 0) {
|
||||
herbList.value[index].showNewInput = true;
|
||||
herbList.value[index].newName = herbList.value[index].keyword;
|
||||
} else {
|
||||
herbList.value[index].showNewInput = false;
|
||||
herbList.value[index].newName = "";
|
||||
}
|
||||
};
|
||||
|
||||
// 13. 表单提交/取消逻辑(优化参数组装)
|
||||
const handleSave = async () => {
|
||||
// 表单验证
|
||||
if (!personFormRef.value?.validate()) return;
|
||||
// 药材验证
|
||||
if (herbList.value.length === 0) {
|
||||
return ElMessage.warning("请至少添加一条药材消耗记录");
|
||||
}
|
||||
// 诊断结果验证
|
||||
if (!prescriptionForm.diagnosisResult.trim()) {
|
||||
return ElMessage.warning("请输入诊断结果");
|
||||
}
|
||||
|
||||
loading.value = true;
|
||||
try {
|
||||
// 处理新增员工/家属的情况
|
||||
let newPersonId: number | undefined = personForm.id;
|
||||
if (!newPersonId) {
|
||||
if (personForm.isEmployee) {
|
||||
// 新增员工
|
||||
if (state.showEmployeeSelect) {
|
||||
newPersonId = personForm.employeeId; // 选择已有员工
|
||||
} else {
|
||||
// 新增员工:调用addPerson接口
|
||||
newPersonId = await prescriptionApi.addPerson({
|
||||
name: personForm.newEmployeeName.trim(),
|
||||
isEmployee: true
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// 新增家属:先处理关联员工(如有新增)
|
||||
let relatedEmpId = personForm.relatedEmployeeId;
|
||||
if (!state.showRelatedEmployeeSelect) {
|
||||
// 新增关联员工
|
||||
relatedEmpId = await prescriptionApi.addPerson({
|
||||
name: personForm.newRelatedEmployeeName.trim(),
|
||||
isEmployee: true
|
||||
});
|
||||
}
|
||||
|
||||
// 新增家属
|
||||
if (state.showRelativeSelect) {
|
||||
newPersonId = personForm.relativeId; // 选择已有家属
|
||||
} else {
|
||||
// 新增家属:调用addPerson接口
|
||||
newPersonId = await prescriptionApi.addPerson({
|
||||
name: personForm.newRelativeName.trim(),
|
||||
isEmployee: false,
|
||||
EmployeeId: relatedEmpId,
|
||||
RelationShip: personForm.relationShip
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 组装药材参数
|
||||
const herbParams = herbList.value.map(h => ({
|
||||
medicinalId: h.medicinalId,
|
||||
amountG: h.amountG,
|
||||
note: h.note?.trim()
|
||||
}));
|
||||
|
||||
// 最终提交参数
|
||||
const submitParams = {
|
||||
id: props.prescriptionId || undefined,
|
||||
PersonId: newPersonId, // 人员ID(新增/编辑后的值)
|
||||
diagnosisResult: prescriptionForm.diagnosisResult.trim(),
|
||||
userMedicinaAdvice: prescriptionForm.userMedicinaAdvice.trim(),
|
||||
visitDate: prescriptionForm.visitDate,
|
||||
herbs: herbParams
|
||||
};
|
||||
|
||||
// 提交保存
|
||||
await prescriptionApi.save(submitParams);
|
||||
ElMessage.success(props.prescriptionId ? "修改成功" : "新增成功");
|
||||
emit("update:visible", false);
|
||||
emit("refreshList");
|
||||
} catch (err: any) {
|
||||
ElMessage.error(err.message || "保存失败");
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
if (props.isEdit) {
|
||||
ElMessageBox.confirm("是否放弃未保存的修改?", "确认取消", { type: "warning" })
|
||||
.then(() => emit("update:visible", false))
|
||||
.catch(); // 无逻辑时可省略函数体
|
||||
} else {
|
||||
emit("update:visible", false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleUpdateVisible = (newVisible: boolean) => {
|
||||
emit("update:visible", newVisible);
|
||||
};
|
||||
|
||||
// 重置表单
|
||||
const resetForm = () => {
|
||||
// 重置处方表单
|
||||
prescriptionForm.diagnosisResult = "";
|
||||
prescriptionForm.userMedicinaAdvice = "";
|
||||
prescriptionForm.visitDate = new Date().toISOString().slice(0, 16);
|
||||
|
||||
// 重置人员表单
|
||||
Object.assign(personForm, {
|
||||
id: undefined,
|
||||
name: "",
|
||||
isEmployee: true,
|
||||
employeeId: undefined,
|
||||
newEmployeeName: "",
|
||||
relatedEmployeeId: undefined,
|
||||
newRelatedEmployeeName: "",
|
||||
relativeId: undefined,
|
||||
newRelativeName: "",
|
||||
relationShip: undefined,
|
||||
age: undefined,
|
||||
weight: undefined,
|
||||
height: undefined
|
||||
});
|
||||
|
||||
// 重置状态
|
||||
Object.assign(state, {
|
||||
showEmployeeSelect: true,
|
||||
employeeOptions: [],
|
||||
employeeKeyword: "",
|
||||
showRelatedEmployeeSelect: true,
|
||||
relatedEmployeeOptions: [],
|
||||
relatedEmployeeKeyword: "",
|
||||
showRelativeSelect: true,
|
||||
relativeOptions: [],
|
||||
relativeKeyword: ""
|
||||
});
|
||||
|
||||
// 重置药材列表
|
||||
herbList.value = [];
|
||||
|
||||
// 重置表单验证
|
||||
nextTick(() => {
|
||||
personFormRef.value?.clearValidate();
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
.justify-between {
|
||||
justify-content: space-between;
|
||||
}
|
||||
.items-center {
|
||||
align-items: center;
|
||||
}
|
||||
.gap-4 {
|
||||
gap: 16px;
|
||||
}
|
||||
.flex-1 {
|
||||
flex: 1;
|
||||
}
|
||||
.el-form-item {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,103 +0,0 @@
|
||||
<template>
|
||||
<div class="table-box">
|
||||
<el-card class="mt-4">
|
||||
<ProTable ref="proTable" title="处方列表" :columns="columns" :request-api="getPrescriptionListApi" :row-key="rowKey">
|
||||
<template #tableHeader>
|
||||
<s-button suffix="处方" type="success" @click="handleAddPrescription" />
|
||||
</template>
|
||||
|
||||
<template #operation="scope">
|
||||
<s-button link :opt="FormOptEnum.VIEW" size="small" @click="handleViewDetail(scope.row.id)"> 查看详情 </s-button>
|
||||
<s-button link :opt="FormOptEnum.EDIT" size="small" class="ml-2" @click="handleEdit(scope.row.id)" v-if="scope.row.canEdit">
|
||||
编辑
|
||||
</s-button>
|
||||
</template>
|
||||
</ProTable>
|
||||
</el-card>
|
||||
|
||||
<!-- 弹窗:查看/编辑处方 -->
|
||||
<prescription-detail-dialog
|
||||
:visible="showDetailDialog"
|
||||
:prescription-id="currentPrescriptionId"
|
||||
:is-edit="isEdit"
|
||||
@update:visible="val => (showDetailDialog = val)"
|
||||
@refresh-list="handleRefresh"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="prescriptionModule">
|
||||
import { ref } from "vue";
|
||||
import ProTable from "@/components/ProTable/index.vue";
|
||||
import type { ProTableInstance, ColumnProps } from "@/components/ProTable/interface";
|
||||
import { prescriptionApi } from "@/api";
|
||||
import PrescriptionDetailDialog from "./components/PrescriptionDetailDialog.vue";
|
||||
import { FormOptEnum } from "@/enums";
|
||||
|
||||
// ProTable ref
|
||||
const proTable = ref<ProTableInstance | null>(null);
|
||||
|
||||
// 弹窗状态
|
||||
const showDetailDialog = ref(false);
|
||||
const currentPrescriptionId = ref<number | null>(null);
|
||||
const isEdit = ref(false);
|
||||
|
||||
// 表格列配置
|
||||
const columns: ColumnProps<any>[] = [
|
||||
{ type: "selection", fixed: "left", width: 80 },
|
||||
{ prop: "personName", label: "就诊人", search: { el: "input" } },
|
||||
{
|
||||
prop: "personType",
|
||||
label: "就诊人类型",
|
||||
formatter: (row: any) => (row.personType === 1 ? "公司员工" : `员工家属(${row.employeeName || "未知"})`)
|
||||
},
|
||||
{ prop: "visitDate", label: "就诊时间" },
|
||||
{ prop: "operation", label: "操作", width: 180, fixed: "right" }
|
||||
];
|
||||
|
||||
// rowKey定义
|
||||
const rowKey = (row: any) => row.id;
|
||||
|
||||
// 请求接口
|
||||
const getPrescriptionListApi = (params: any) => {
|
||||
return prescriptionApi.getList(params);
|
||||
};
|
||||
|
||||
// 新增处方
|
||||
const handleAddPrescription = () => {
|
||||
currentPrescriptionId.value = null;
|
||||
isEdit.value = true;
|
||||
showDetailDialog.value = true;
|
||||
};
|
||||
|
||||
// 查看详情
|
||||
const handleViewDetail = (id: number) => {
|
||||
currentPrescriptionId.value = id;
|
||||
isEdit.value = false;
|
||||
showDetailDialog.value = true;
|
||||
};
|
||||
|
||||
// 编辑
|
||||
const handleEdit = (id: number) => {
|
||||
currentPrescriptionId.value = id;
|
||||
isEdit.value = true;
|
||||
showDetailDialog.value = true;
|
||||
};
|
||||
|
||||
// 刷新表格
|
||||
const handleRefresh = () => {
|
||||
proTable.value?.refresh?.();
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.table-box {
|
||||
padding-bottom: 24px;
|
||||
}
|
||||
.mt-4 {
|
||||
margin-top: 16px;
|
||||
}
|
||||
.ml-2 {
|
||||
margin-left: 8px;
|
||||
}
|
||||
</style>
|
||||
@@ -5,34 +5,23 @@
|
||||
!-->
|
||||
<template>
|
||||
<div class="main-box">
|
||||
<TreeFilter
|
||||
ref="treeFilter"
|
||||
label="name"
|
||||
title="组织列表"
|
||||
:request-api="sysOrgApi.tree"
|
||||
:default-value="initParam.orgId"
|
||||
@change="changeTreeFilter"
|
||||
/>
|
||||
<TreeFilter ref="treeFilter" label="name" title="组织列表" :request-api="sysOrgApi.tree"
|
||||
:default-value="initParam.orgId" @change="changeTreeFilter" />
|
||||
<div class="table-box">
|
||||
<ProTable ref="proTable" :columns="columns" :request-api="sysRoleApi.page" :init-param="initParam">
|
||||
<!-- 表格 header 按钮 -->
|
||||
<template #tableHeader="scope">
|
||||
<s-button suffix="角色" @click="onOpen(FormOptEnum.ADD)" />
|
||||
<s-button
|
||||
type="danger"
|
||||
plain
|
||||
suffix="角色"
|
||||
:opt="FormOptEnum.DELETE"
|
||||
:disabled="!scope.isSelected"
|
||||
@click="onDelete(scope.selectedListIds, '删除所选角色')"
|
||||
/>
|
||||
<s-button type="danger" plain suffix="角色" :opt="FormOptEnum.DELETE" :disabled="!scope.isSelected"
|
||||
@click="onDelete(scope.selectedListIds, '删除所选角色')" />
|
||||
</template>
|
||||
<!-- 状态 -->
|
||||
<template #status="scope">
|
||||
<el-tag v-if="scope.row.status === CommonStatusEnum.ENABLE" type="success">{{
|
||||
dictStore.dictTranslation(SysDictEnum.COMMON_STATUS, scope.row.status)
|
||||
}}</el-tag>
|
||||
<el-tag v-else type="danger">{{ dictStore.dictTranslation(SysDictEnum.COMMON_STATUS, scope.row.status) }}</el-tag>
|
||||
}}</el-tag>
|
||||
<el-tag v-else type="danger">{{ dictStore.dictTranslation(SysDictEnum.COMMON_STATUS, scope.row.status)
|
||||
}}</el-tag>
|
||||
</template>
|
||||
<!-- 操作 -->
|
||||
<template #operation="scope">
|
||||
@@ -43,7 +32,8 @@
|
||||
<el-link type="primary" :underline="false" :icon="ArrowDown"> 授权 </el-link>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item v-for="(item, index) in cmdEnum" :key="index" :command="command(scope.row, item)">{{ item }}</el-dropdown-item>
|
||||
<el-dropdown-item v-for="(item, index) in cmdEnum" :key="index" :command="command(scope.row, item)">{{
|
||||
item }}</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
@@ -59,15 +49,9 @@
|
||||
<!-- 授权权限组件 -->
|
||||
<GrantPermission ref="grantPermissionRef" />
|
||||
<!-- 用户选择器 -->
|
||||
<user-selector
|
||||
ref="userSelectorRef"
|
||||
:org-tree-api="sysOrgApi.tree"
|
||||
:position-tree-api="sysPositionApi.tree"
|
||||
:role-tree-api="sysRoleApi.tree"
|
||||
:user-selector-api="sysUserApi.selector"
|
||||
multiple
|
||||
@successful="handleChooseUser"
|
||||
/>
|
||||
<user-selector ref="userSelectorRef" :org-tree-api="sysOrgApi.tree" :position-tree-api="sysPositionApi.tree"
|
||||
:role-tree-api="sysRoleApi.tree" :user-selector-api="sysUserApi.selector" multiple
|
||||
@successful="handleChooseUser" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -209,14 +193,14 @@ function handleCommand(command: Command) {
|
||||
successful: RefreshTable
|
||||
});
|
||||
break;
|
||||
case cmdEnum.GrantMobileResource:
|
||||
// 打开授权移动端资源组件
|
||||
grantMobileResourceRef.value?.onOpen({
|
||||
opt: FormOptEnum.EDIT,
|
||||
record: command.row,
|
||||
successful: RefreshTable
|
||||
});
|
||||
break;
|
||||
// case cmdEnum.GrantMobileResource:
|
||||
// // 打开授权移动端资源组件
|
||||
// grantMobileResourceRef.value?.onOpen({
|
||||
// opt: FormOptEnum.EDIT,
|
||||
// record: command.row,
|
||||
// successful: RefreshTable
|
||||
// });
|
||||
// break;
|
||||
case cmdEnum.GrantPermission:
|
||||
// 打开授权权限组件
|
||||
grantPermissionRef.value?.onOpen({
|
||||
|
||||
@@ -6,11 +6,17 @@
|
||||
<template>
|
||||
<div class="card">
|
||||
<el-tabs v-model="activeName" class="-mt-4">
|
||||
<el-tab-pane label="系统配置" name="sysConfig"><SysBaseConfig :sys-configs="sysBase" /></el-tab-pane>
|
||||
<el-tab-pane label="安全配置" name="safety"><SafetyConfig :sys-configs="safetyConfig" /></el-tab-pane>
|
||||
<el-tab-pane label="MQTT配置" name="mqtt"><MqttConfig :sys-configs="mqttConfig" /></el-tab-pane>
|
||||
<el-tab-pane label="文件配置" name="file">开发中......</el-tab-pane>
|
||||
<el-tab-pane label="其他配置" name="other"><OtherConfig v-if="activeName === 'other'" /></el-tab-pane>
|
||||
<el-tab-pane label="系统配置" name="sysConfig">
|
||||
<SysBaseConfig :sys-configs="sysBase" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="安全配置" name="safety">
|
||||
<SafetyConfig :sys-configs="safetyConfig" />
|
||||
</el-tab-pane>
|
||||
<!-- <el-tab-pane label="MQTT配置" name="mqtt"><MqttConfig :sys-configs="mqttConfig" /></el-tab-pane>
|
||||
<el-tab-pane label="文件配置" name="file">开发中......</el-tab-pane> -->
|
||||
<el-tab-pane label="其他配置" name="other">
|
||||
<OtherConfig v-if="activeName === 'other'" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
@@ -19,7 +25,7 @@
|
||||
import SysBaseConfig from "./components/sysBaseConfig.vue";
|
||||
import SafetyConfig from "./components/safetyConfig/index.vue";
|
||||
import OtherConfig from "./components/otherConfig/index.vue";
|
||||
import MqttConfig from "./components/mqttConfig/index.vue";
|
||||
// import MqttConfig from "./components/mqttConfig/index.vue";
|
||||
import { SysConfig, sysConfigApi } from "@/api";
|
||||
import { SysConfigTypeEnum } from "@/enums";
|
||||
|
||||
|
||||
@@ -58,28 +58,28 @@ enum BindType {
|
||||
const data: BindData[] = [
|
||||
{ title: "密码强度", description: "当前密码强度", value: "弱", bindType: BindType.Password, bindStatus: 0 },
|
||||
/*{ title: '密保手机', description: '已绑定手机', value: '138****8293', type: 'phone', bindStatus: 1 },
|
||||
{ title: '密保邮箱', description: '未绑定邮箱', value: '', type: 'email', bindStatus: 0 },
|
||||
{ title: '实名状态', description: '未实名', value: '', type: 'userReal', bindStatus: 0 },*/
|
||||
{ avatar: "ant-design:qq-outlined", title: "绑定QQ", description: "未绑定", value: "", bindType: BindType.QQ, bindStatus: 0, color: "1890FF" },
|
||||
{
|
||||
avatar: "ant-design:wechat-outlined",
|
||||
title: "绑定微信",
|
||||
description: "未绑定",
|
||||
value: "",
|
||||
bindType: BindType.WeChat,
|
||||
bindStatus: 0,
|
||||
color: "1AAD19"
|
||||
},
|
||||
{
|
||||
avatar: "ant-design:alipay-circle-outlined",
|
||||
title: "绑定支付宝",
|
||||
description: "未绑定",
|
||||
value: "",
|
||||
bindType: BindType.AliPay,
|
||||
bindStatus: 0,
|
||||
color: "178bf5"
|
||||
},
|
||||
{ avatar: "simple-icons:gitee", title: "绑定Gitee", description: "未绑定", value: "", bindType: BindType.Gitee, bindStatus: 0, color: "d84040" }
|
||||
{ title: '密保邮箱', description: '未绑定邮箱', value: '', type: 'email', bindStatus: 0 },
|
||||
{ title: '实名状态', description: '未实名', value: '', type: 'userReal', bindStatus: 0 },*/
|
||||
// { avatar: "ant-design:qq-outlined", title: "绑定QQ", description: "未绑定", value: "", bindType: BindType.QQ, bindStatus: 0, color: "1890FF" },
|
||||
// {
|
||||
// avatar: "ant-design:wechat-outlined",
|
||||
// title: "绑定微信",
|
||||
// description: "未绑定",
|
||||
// value: "",
|
||||
// bindType: BindType.WeChat,
|
||||
// bindStatus: 0,
|
||||
// color: "1AAD19"
|
||||
// },
|
||||
// {
|
||||
// avatar: "ant-design:alipay-circle-outlined",
|
||||
// title: "绑定支付宝",
|
||||
// description: "未绑定",
|
||||
// value: "",
|
||||
// bindType: BindType.AliPay,
|
||||
// bindStatus: 0,
|
||||
// color: "178bf5"
|
||||
// },
|
||||
// { avatar: "simple-icons:gitee", title: "绑定Gitee", description: "未绑定", value: "", bindType: BindType.Gitee, bindStatus: 0, color: "d84040" }
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -102,34 +102,55 @@ function bindAction(bindType: BindType) {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.list-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.item-content {
|
||||
flex-grow: 1;
|
||||
color: #585252; /* 调整字体颜色为深灰色 */
|
||||
color: #585252;
|
||||
|
||||
/* 调整字体颜色为深灰色 */
|
||||
}
|
||||
|
||||
.item-content h3 {
|
||||
margin: 0 0 10px; /* 添加一些间距 */
|
||||
margin: 0 0 10px;
|
||||
|
||||
/* 添加一些间距 */
|
||||
font-size: 16px;
|
||||
font-weight: normal; /* 调整标题字体为正常粗细 */
|
||||
color: #242425; /* 标题字体颜色稍深一点 */
|
||||
font-weight: normal;
|
||||
|
||||
/* 调整标题字体为正常粗细 */
|
||||
color: #242425;
|
||||
|
||||
/* 标题字体颜色稍深一点 */
|
||||
}
|
||||
|
||||
.item-content p {
|
||||
margin: 0; /* 移除段落默认的上下外边距 */
|
||||
margin: 0;
|
||||
|
||||
/* 移除段落默认的上下外边距 */
|
||||
font-size: 14px;
|
||||
color: #8f8f94; /* 标题字体颜色稍深一点 */
|
||||
color: #8f8f94;
|
||||
|
||||
/* 标题字体颜色稍深一点 */
|
||||
}
|
||||
|
||||
.item-action {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.item-action .el-button {
|
||||
font-weight: normal;
|
||||
color: #409eff; /* 为按钮文字设置主题颜色 */
|
||||
color: #409eff;
|
||||
|
||||
/* 为按钮文字设置主题颜色 */
|
||||
}
|
||||
|
||||
.bind-icon {
|
||||
padding-right: 10px;
|
||||
padding-left: 10px;
|
||||
|
||||
@@ -13,7 +13,9 @@
|
||||
<img :src="userInfo?.avatar" />
|
||||
<a style="cursor: pointer" @click="uploadAvatar">
|
||||
<div :class="userInfo?.avatar ? 'mask' : 'mask-notImg'">
|
||||
<el-icon><Upload /></el-icon>
|
||||
<el-icon>
|
||||
<Upload />
|
||||
</el-icon>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
@@ -31,7 +33,8 @@
|
||||
<el-divider />
|
||||
<div class="account-center-team">
|
||||
<div v-if="userInfo?.signature" class="mb-2" style="width: 100%">
|
||||
<el-image :src="userInfo?.signature" style="height: 120px; border: 1px solid rgb(236 236 236)" width="100%" />
|
||||
<el-image :src="userInfo?.signature" style="height: 120px; border: 1px solid rgb(236 236 236)"
|
||||
width="100%" />
|
||||
</div>
|
||||
<el-button @click="openSignName">打开签名板</el-button>
|
||||
</div>
|
||||
@@ -41,10 +44,18 @@
|
||||
<el-col :lg="17" :md="24">
|
||||
<div class="card">
|
||||
<el-tabs v-model="activeName" class="-mt-4" @tab-click="tabClick">
|
||||
<el-tab-pane label="基本信息" :name="centerStore.getAccountBasic"><AccountBasic /></el-tab-pane>
|
||||
<el-tab-pane label="账号相关" :name="centerStore.getFile"><AccountBind /></el-tab-pane>
|
||||
<el-tab-pane label="快捷方式" :name="centerStore.getShort"><ShortcutSetting /></el-tab-pane>
|
||||
<el-tab-pane label="我的消息" :name="centerStore.getMessage"><MyMessage /></el-tab-pane>
|
||||
<el-tab-pane label="基本信息" :name="centerStore.getAccountBasic">
|
||||
<AccountBasic />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="账号相关" :name="centerStore.getFile">
|
||||
<AccountBind />
|
||||
</el-tab-pane>
|
||||
<!-- <el-tab-pane label="快捷方式" :name="centerStore.getShort">
|
||||
<ShortcutSetting />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="我的消息" :name="centerStore.getMessage">
|
||||
<MyMessage />
|
||||
</el-tab-pane> -->
|
||||
</el-tabs>
|
||||
</div>
|
||||
</el-col>
|
||||
@@ -135,18 +146,21 @@ centerStore.$subscribe((mutations, state) => {
|
||||
.account-center-avatarHolder {
|
||||
margin-bottom: 24px;
|
||||
text-align: center;
|
||||
& > .avatar {
|
||||
|
||||
&>.avatar {
|
||||
width: 104px;
|
||||
height: 104px;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 20px;
|
||||
overflow: hidden;
|
||||
border-radius: 50%;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.mask {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
@@ -161,6 +175,7 @@ centerStore.$subscribe((mutations, state) => {
|
||||
border-radius: 50%;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.mask-notImg {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
@@ -175,12 +190,15 @@ centerStore.$subscribe((mutations, state) => {
|
||||
border-radius: 50%;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.avatar a:hover .mask {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.avatar a:hover .mask-notImg {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.username {
|
||||
margin-bottom: 4px;
|
||||
font-size: 20px;
|
||||
@@ -188,12 +206,14 @@ centerStore.$subscribe((mutations, state) => {
|
||||
line-height: 28px;
|
||||
}
|
||||
}
|
||||
|
||||
.account-center-detail {
|
||||
p {
|
||||
position: relative;
|
||||
padding-left: 26px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
i {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
@@ -202,16 +222,20 @@ centerStore.$subscribe((mutations, state) => {
|
||||
height: 14px;
|
||||
background: url("/src/assets/icons/userDetail.svg");
|
||||
}
|
||||
|
||||
.title {
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
.group {
|
||||
background-position: 0 -22px;
|
||||
}
|
||||
|
||||
.address {
|
||||
background-position: 0 -44px;
|
||||
}
|
||||
}
|
||||
|
||||
.account-center-team {
|
||||
.members {
|
||||
a {
|
||||
@@ -219,6 +243,7 @@ centerStore.$subscribe((mutations, state) => {
|
||||
height: 24px;
|
||||
margin: 12px 0;
|
||||
line-height: 24px;
|
||||
|
||||
.member {
|
||||
display: inline-block;
|
||||
max-width: 100px;
|
||||
@@ -231,6 +256,7 @@ centerStore.$subscribe((mutations, state) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-tabs__item) {
|
||||
font-size: large;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user