feat:诊所问题优化,气泡卡片优化,修复了导入药品的时候无法打开开方组件并且切换tab的问题
This commit is contained in:
@@ -54,12 +54,15 @@ export namespace AuthApi {
|
||||
* 登录
|
||||
*/
|
||||
export async function loginApi(data: AuthApi.LoginParams) {
|
||||
// PC 管理端固定 web,供单机登录按端区分会话
|
||||
const clientType = 'web';
|
||||
if (data.account) {
|
||||
return requestClient.post<AuthApi.LoginResult>('login', {
|
||||
account: data.account,
|
||||
password: data.password,
|
||||
code: data.code,
|
||||
admin_id: data.admin_id,
|
||||
client_type: clientType,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -67,6 +70,7 @@ export async function loginApi(data: AuthApi.LoginParams) {
|
||||
login_method: data.login_method || 'phone',
|
||||
password: data.password,
|
||||
code: data.code,
|
||||
client_type: clientType,
|
||||
};
|
||||
|
||||
if (data.login_method === 'phone') {
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
} from '@vben/request';
|
||||
import { useAccessStore } from '@vben/stores';
|
||||
|
||||
import { message } from 'ant-design-vue';
|
||||
import { message, Modal } from 'ant-design-vue';
|
||||
// eslint-disable-next-line n/no-extraneous-import
|
||||
import { Base64 } from 'js-base64';
|
||||
|
||||
@@ -37,6 +37,8 @@ function createRequestClient(baseURL: string) {
|
||||
/**
|
||||
* 重新认证逻辑
|
||||
*/
|
||||
/** 防重复:并发 401 只弹一次重新登录提示 */
|
||||
let authModalShowing = false;
|
||||
async function doReAuthenticate() {
|
||||
const accessStore = useAccessStore();
|
||||
const authStore = useAuthStore();
|
||||
@@ -47,6 +49,21 @@ function createRequestClient(baseURL: string) {
|
||||
) {
|
||||
accessStore.setLoginExpired(true);
|
||||
} else {
|
||||
// 被踢/登录失效时用模态框提示,确认后再退出
|
||||
if (!authModalShowing) {
|
||||
authModalShowing = true;
|
||||
await new Promise<void>((resolve) => {
|
||||
Modal.warning({
|
||||
title: '登录失效',
|
||||
content: '账号需重新登录',
|
||||
okText: '重新登录',
|
||||
centered: true,
|
||||
onOk: () => resolve(),
|
||||
onCancel: () => resolve(),
|
||||
});
|
||||
});
|
||||
authModalShowing = false;
|
||||
}
|
||||
await authStore.logout(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import type { Dayjs } from 'dayjs';
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
import { useUserStore } from '@vben/stores';
|
||||
|
||||
import dayjs from 'dayjs';
|
||||
import {
|
||||
@@ -35,9 +36,15 @@ import {
|
||||
} from '#/views/system/store/api';
|
||||
import { getSalespersonList } from '#/views/system/store/api/salesperson';
|
||||
import { resolveAvatarUrl } from '#/views/system/store-input/utils/inputUser';
|
||||
import AddDoctorFromStoreModal from '#/views/system/store/components/AddDoctorFromStoreModal.vue';
|
||||
import { canAddStoreDoctor } from '#/views/system/admin/_shared/platform-admin-role';
|
||||
|
||||
const RangePicker = DatePicker.RangePicker;
|
||||
|
||||
const userStore = useUserStore();
|
||||
// 是否允许「添加医生」:超管/管理员/省经理/市经理/业务员
|
||||
const canAddDoctor = computed(() => canAddStoreDoctor(userStore.userInfo));
|
||||
|
||||
const storeId = ref(0);
|
||||
const loading = ref(false);
|
||||
const activeTab = ref('basic');
|
||||
@@ -121,6 +128,25 @@ const [DoctorModal, DoctorModalApi] = useVbenModal({
|
||||
connectedComponent: DoctorCardModal,
|
||||
});
|
||||
|
||||
/** 添加医生弹窗:诊所详情医生团队 Tab 内入口 */
|
||||
const [AddDoctorModal, AddDoctorModalApi] = useVbenModal({
|
||||
connectedComponent: AddDoctorFromStoreModal,
|
||||
});
|
||||
|
||||
/**
|
||||
* 打开「添加医生」弹窗:默认绑定当前门店,提交成功后刷新医生团队列表
|
||||
*/
|
||||
const openAddDoctorModal = () => {
|
||||
AddDoctorModalApi.setData({
|
||||
storeId: storeId.value,
|
||||
storeName: (store.value as any)?.name || '',
|
||||
onSuccess: () => {
|
||||
loadCard();
|
||||
},
|
||||
});
|
||||
AddDoctorModalApi.open();
|
||||
};
|
||||
|
||||
function searchTimeParam(): [string, string] {
|
||||
return [
|
||||
searchTime.value[0].format('YYYY-MM-DD 00:00:00'),
|
||||
@@ -256,6 +282,7 @@ function clinicTypeText(v: number) {
|
||||
|
||||
<template>
|
||||
<Modal :title="modalTitle">
|
||||
<AddDoctorModal />
|
||||
<Spin :spinning="loading">
|
||||
<div v-if="cardData" class="mb-4 flex flex-wrap items-center justify-between gap-3 px-1">
|
||||
<div class="text-sm text-muted-foreground">统计时间范围</div>
|
||||
@@ -399,6 +426,15 @@ function clinicTypeText(v: number) {
|
||||
|
||||
<Tabs.TabPane v-if="isClinic" key="doctors" tab="诊所医生团队">
|
||||
<div class="pl-4">
|
||||
<div v-if="canAddDoctor" class="mb-3">
|
||||
<Button
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="openAddDoctorModal"
|
||||
>
|
||||
添加医生
|
||||
</Button>
|
||||
</div>
|
||||
<Empty v-if="doctorList.length === 0" description="暂无医生" />
|
||||
<div v-else class="grid grid-cols-1 gap-3 md:grid-cols-2">
|
||||
<div
|
||||
|
||||
@@ -83,8 +83,6 @@ const prescriptionStore = usePrescriptionStore();
|
||||
/** 处方类型来自后端下发(store.categories) */
|
||||
const categories = computed(() => prescriptionStore.categories);
|
||||
|
||||
const rxSwipeStartX = ref(0);
|
||||
const rxSwipeStartY = ref(0);
|
||||
|
||||
const allowInsuranceCategory = computed(
|
||||
() => Number(prescriptionStore.registerStoreInfo?.allow_insurance_category ?? 0) === 1,
|
||||
@@ -445,26 +443,6 @@ const tabChange = async (id: number) => {
|
||||
}
|
||||
};
|
||||
|
||||
/** 记录左右滑起点 */
|
||||
const onRxPanelPointerDown = (e: PointerEvent) => {
|
||||
rxSwipeStartX.value = e.clientX;
|
||||
rxSwipeStartY.value = e.clientY;
|
||||
};
|
||||
|
||||
/** 左右滑切换相邻处方类型 */
|
||||
const onRxPanelPointerUp = (e: PointerEvent) => {
|
||||
const dx = e.clientX - rxSwipeStartX.value;
|
||||
const dy = e.clientY - rxSwipeStartY.value;
|
||||
if (Math.abs(dx) < 80 || Math.abs(dx) <= Math.abs(dy)) return;
|
||||
const list = categories.value || [];
|
||||
if (list.length < 2) return;
|
||||
const idx = list.findIndex((c) => Number(c.value) === Number(prescriptionStore.activeCategory));
|
||||
if (idx < 0) return;
|
||||
const nextIdx = dx < 0 ? idx + 1 : idx - 1;
|
||||
if (nextIdx < 0 || nextIdx >= list.length) return;
|
||||
tabChange(list[nextIdx].value);
|
||||
};
|
||||
|
||||
/**
|
||||
* 检测并显示转诊提示
|
||||
* @description 当切换到中药处方时,如果当前诊所为西医诊所,显示转诊提示
|
||||
@@ -1058,11 +1036,7 @@ const cancelSaveCommonPrescription = () => {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="rx-swipe-panel"
|
||||
@pointerdown="onRxPanelPointerDown"
|
||||
@pointerup="onRxPanelPointerUp"
|
||||
>
|
||||
<div class="rx-swipe-panel">
|
||||
|
||||
<!-- 费用类型选择和添加商品按钮 -->
|
||||
<div class="mb-4 flex items-center justify-between">
|
||||
|
||||
@@ -576,16 +576,15 @@ const handleSwitchClinicType = () => {
|
||||
</p>
|
||||
<p class="text-sm text-gray-500">
|
||||
专业:
|
||||
|
||||
<span
|
||||
:class="
|
||||
doctor.identity === 1
|
||||
doctor.doctor?.identity === 1
|
||||
? 'bg-green-100 text-green-700'
|
||||
: 'bg-gray-100 text-gray-700'
|
||||
"
|
||||
class="rounded px-2 py-1"
|
||||
>
|
||||
{{ doctor.identity === 1 ? '中医' : '西医' }}
|
||||
{{ doctor.doctor?.identity === 1 ? '中医' : '西医' }}
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -322,7 +322,21 @@ function parseRecipeContent(content: string | Record<string, unknown>) {
|
||||
alt="签名"
|
||||
style="width: 120px; height: 50px; display: inline-block"
|
||||
/>
|
||||
<span v-else>{{ item.content?.doctor?.name }}</span>
|
||||
<!-- 二次签名:相冲继续开方时展示第二张医生签名 -->
|
||||
<img
|
||||
v-if="
|
||||
item.doctor_second_sign == 1 &&
|
||||
item.doctor_info?.identity_info?.sign_image
|
||||
"
|
||||
:src="
|
||||
getImageSource(item.doctor_info.identity_info.sign_image)
|
||||
"
|
||||
alt="二次签名"
|
||||
style="width: 120px; height: 50px; display: inline-block"
|
||||
/>
|
||||
<span v-else-if="!item.doctor_info?.identity_info?.sign_image">{{
|
||||
item.content?.doctor?.name
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="signature">
|
||||
<label>审核药师:</label>
|
||||
|
||||
@@ -419,9 +419,6 @@ const categories = ref([
|
||||
]);
|
||||
/** 后端默认处方类型 */
|
||||
const prescriptionTypeDefault = ref(2);
|
||||
/** 内容区左右滑切换 Tab */
|
||||
const rxSwipeStartX = ref(0);
|
||||
const rxSwipeStartY = ref(0);
|
||||
|
||||
// 当前状态
|
||||
const activePatient = ref<null | Patient>(null);
|
||||
@@ -1488,25 +1485,6 @@ function tabChange(id) {
|
||||
focusActiveCategoryTab();
|
||||
}
|
||||
|
||||
/** 记录左右滑起点 */
|
||||
function onRxPanelPointerDown(e: PointerEvent) {
|
||||
rxSwipeStartX.value = e.clientX;
|
||||
rxSwipeStartY.value = e.clientY;
|
||||
}
|
||||
|
||||
/** 左右滑切换相邻处方类型 */
|
||||
function onRxPanelPointerUp(e: PointerEvent) {
|
||||
const dx = e.clientX - rxSwipeStartX.value;
|
||||
const dy = e.clientY - rxSwipeStartY.value;
|
||||
if (Math.abs(dx) < 80 || Math.abs(dx) <= Math.abs(dy)) return;
|
||||
const list = categories.value || [];
|
||||
if (list.length < 2) return;
|
||||
const idx = list.findIndex((c) => Number(c.value) === Number(activeCategory.value));
|
||||
if (idx < 0) return;
|
||||
const nextIdx = dx < 0 ? idx + 1 : idx - 1;
|
||||
if (nextIdx < 0 || nextIdx >= list.length) return;
|
||||
tabChange(list[nextIdx].value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测并显示转诊提示
|
||||
@@ -2860,11 +2838,7 @@ watch(
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="rx-swipe-panel"
|
||||
@pointerdown="onRxPanelPointerDown"
|
||||
@pointerup="onRxPanelPointerUp"
|
||||
>
|
||||
<div class="rx-swipe-panel">
|
||||
|
||||
<SpecialPrescriptionImportCard
|
||||
v-if="hasSpecialPrescriptionRecord"
|
||||
|
||||
@@ -18,3 +18,13 @@ export function canEditDoctorServiceUser(userInfo: PlatformAdminUserInfo): boole
|
||||
export function canManageStoreBankCard(userInfo: PlatformAdminUserInfo): boolean {
|
||||
return isPlatformSuperAdmin(userInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否可在诊所页/诊所详情发起「添加医生」操作
|
||||
* 角色:1 超级管理员 / 2 系统管理员 / 3 省经理 / 4 市经理 / 6 业务员
|
||||
* 数据范围由后端 StoreService::assertCanViewStore 兜底校验
|
||||
*/
|
||||
export function canAddStoreDoctor(userInfo: PlatformAdminUserInfo): boolean {
|
||||
const roleId = Number(userInfo?.role_id ?? userInfo?.roles?.id);
|
||||
return [1, 2, 3, 4, 6].includes(roleId);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
<script lang="ts" setup>
|
||||
/**
|
||||
* 诊所「添加医生」弹窗
|
||||
* 复用 doctor/doctor 的表单 schema 子集(infoModalFormProps),
|
||||
* 诊所字段由外部传入并锁定显示,提交时强制写入选中 store_id,
|
||||
* 成功后通过传入的 onSuccess 回调刷新父级医生列表。
|
||||
*/
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
import { useVbenForm } from '#/adapter/form';
|
||||
import { createDoctor } from '#/views/doctor/doctor/api';
|
||||
import { infoModalFormProps } from '#/views/doctor/doctor/config/form';
|
||||
|
||||
// 当前门店信息(外部 setData 传入)
|
||||
const storeId = ref(0);
|
||||
const storeName = ref('');
|
||||
// 提交成功后回调(由父组件注入,用于刷新医生团队列表)
|
||||
const onSuccess = ref<(() => void) | null>(null);
|
||||
|
||||
const [Form, formApi] = useVbenForm(infoModalFormProps);
|
||||
|
||||
const [Modal, modalApi] = useVbenModal({
|
||||
closeOnClickModal: false,
|
||||
fullscreenButton: false,
|
||||
draggable: true,
|
||||
onCancel() {
|
||||
modalApi.close();
|
||||
},
|
||||
onConfirm: async () => {
|
||||
// 校验表单通过后再提交
|
||||
formApi.validate().then(async (e: any) => {
|
||||
if (!e.valid) return;
|
||||
const values = await formApi.getValues();
|
||||
// 强制写入当前诊所 id(数组形式,匹配后端 normalizeStoreIds)
|
||||
values.store_id = [storeId.value];
|
||||
modalApi.setState({ loading: true, confirmLoading: true });
|
||||
createDoctor(values)
|
||||
.then(() => {
|
||||
message.success('添加成功');
|
||||
// 通知父组件刷新医生团队列表
|
||||
onSuccess.value?.();
|
||||
modalApi.close();
|
||||
})
|
||||
.finally(() => {
|
||||
modalApi.setState({ loading: false, confirmLoading: false });
|
||||
});
|
||||
});
|
||||
await formApi.validateAndSubmitForm();
|
||||
},
|
||||
onOpenChange(isOpen: boolean) {
|
||||
if (!isOpen) return;
|
||||
const data = modalApi.getData<{
|
||||
storeId: number;
|
||||
storeName?: string;
|
||||
onSuccess?: () => void;
|
||||
}>() || { storeId: 0 };
|
||||
storeId.value = Number(data.storeId || 0);
|
||||
storeName.value = data.storeName || '';
|
||||
onSuccess.value = typeof data.onSuccess === 'function' ? data.onSuccess : null;
|
||||
if (storeId.value) {
|
||||
// 1) 锁定诊所字段:禁用 + 默认值
|
||||
formApi.setValues({ store_id: [storeId.value] });
|
||||
formApi.updateSchema([
|
||||
{
|
||||
fieldName: 'store_id',
|
||||
componentProps: {
|
||||
disabled: true,
|
||||
placeholder: `当前诊所:${storeName.value || storeId.value}`,
|
||||
},
|
||||
},
|
||||
]);
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Modal class="w-[60%]" title="添加医生">
|
||||
<Form />
|
||||
</Modal>
|
||||
</template>
|
||||
@@ -39,6 +39,7 @@ import BindConsultationModal from './components/BindConsultationModal.vue';
|
||||
import BindSpecialPrescriptionDoctorModal from './components/BindSpecialPrescriptionDoctorModal.vue';
|
||||
import StoreExternalFieldModal from './components/StoreExternalFieldModal.vue';
|
||||
import SalespersonCommissionDrawer from './components/SalespersonCommissionDrawer.vue';
|
||||
import AddDoctorFromStoreModal from './components/AddDoctorFromStoreModal.vue';
|
||||
import StoreCardModal from '#/components/store-card/StoreCardModal.vue';
|
||||
import BankCardReportModal from '#/views/system/store-bank-card/components/BankCardReportModal.vue';
|
||||
import BankCardStatusModal from '#/views/system/store-bank-card/components/BankCardStatusModal.vue';
|
||||
@@ -46,7 +47,10 @@ import BankCardStoreEditModal from '#/views/system/store-bank-card/components/Ba
|
||||
import { getStoreBankCardReportDetail } from '#/views/system/store-bank-card/api';
|
||||
import { formOptions } from './config/search';
|
||||
import { gridOptions } from './config/table';
|
||||
import { canManageStoreBankCard } from '#/views/system/admin/_shared/platform-admin-role';
|
||||
import {
|
||||
canAddStoreDoctor,
|
||||
canManageStoreBankCard,
|
||||
} from '#/views/system/admin/_shared/platform-admin-role';
|
||||
|
||||
const userStore = useUserStore();
|
||||
const router = useRouter();
|
||||
@@ -60,6 +64,9 @@ const canManageBankCard = computed(() =>
|
||||
canManageStoreBankCard(userStore.userInfo),
|
||||
);
|
||||
|
||||
// 是否允许「添加医生」:超管/管理员/省经理/市经理/业务员
|
||||
const canAddDoctor = computed(() => canAddStoreDoctor(userStore.userInfo));
|
||||
|
||||
// 跳转到审核页面
|
||||
const goToAudit = () => {
|
||||
router.push('/system/store-input/audit');
|
||||
@@ -94,6 +101,11 @@ const [StoreCardModalComp, StoreCardModalApi] = useVbenModal({
|
||||
connectedComponent: StoreCardModal,
|
||||
});
|
||||
|
||||
/** 添加医生弹窗:诊所列表行操作和详情医生团队共用 */
|
||||
const [AddDoctorModalComp, addDoctorModalApi] = useVbenModal({
|
||||
connectedComponent: AddDoctorFromStoreModal,
|
||||
});
|
||||
|
||||
/** 打开门店详情卡片 */
|
||||
function openStoreCard(row: Record<string, any>) {
|
||||
if (!row?.id) return;
|
||||
@@ -101,6 +113,22 @@ function openStoreCard(row: Record<string, any>) {
|
||||
StoreCardModalApi.open();
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开「添加医生」弹窗
|
||||
* @param row 诊所行数据,需要 id 和 name
|
||||
*/
|
||||
const openAddDoctorModal = (row: any) => {
|
||||
addDoctorModalApi.setData({
|
||||
storeId: Number(row?.id || 0),
|
||||
storeName: row?.name || '',
|
||||
onSuccess: () => {
|
||||
// 刷新诊所列表/详情卡(医生列表数据来自 store card)
|
||||
gridApi.query();
|
||||
},
|
||||
});
|
||||
addDoctorModalApi.open();
|
||||
};
|
||||
|
||||
const openQrCodeModal = (url, title, address) => {
|
||||
QrCodePreviewApi.setData({
|
||||
// 表单值
|
||||
@@ -416,6 +444,7 @@ const handleSwitchClinicType = (row: any) => {
|
||||
<BankCardStatusModalComponent />
|
||||
<BankCardStoreEditModalComponent />
|
||||
<StoreCardModalComp />
|
||||
<AddDoctorModalComp />
|
||||
<QrCodePreviewModal />
|
||||
<DrugPriceModalComponent />
|
||||
<BindConsultationModalComponent />
|
||||
@@ -669,6 +698,14 @@ const handleSwitchClinicType = (row: any) => {
|
||||
ifShow: isPlatformAdmin,
|
||||
onClick: showDrugPriceModal.bind(null, row),
|
||||
},
|
||||
{
|
||||
label: '添加医生',
|
||||
type: 'link',
|
||||
icon: 'ant-design:user-add-outlined',
|
||||
size: 'small',
|
||||
ifShow: canAddDoctor,
|
||||
onClick: openAddDoctorModal.bind(null, row),
|
||||
},
|
||||
{
|
||||
label: '绑定特色方医生',
|
||||
type: 'link',
|
||||
|
||||
@@ -38,6 +38,8 @@ const logisticsShowWhNameUser = ref(false);
|
||||
const logisticsShowWhNameClinic = ref(true);
|
||||
/** 业务员是否允许编辑/改价/配置所属诊所(默认否) */
|
||||
const salespersonStoreEditEnabled = ref(false);
|
||||
/** 业务端单机登录:医生/药师/诊所管理员等同一账号仅 1 手机 + 1 网页(默认否) */
|
||||
const doctorSingleDeviceLogin = ref(false);
|
||||
/** 开票通知渠道:subscribe / sms,默认仅订阅消息 */
|
||||
const invoiceNoticeChannels = ref<string[]>(['subscribe']);
|
||||
|
||||
@@ -49,12 +51,13 @@ function readStoredTab() {
|
||||
stored === 'miniprogram' ||
|
||||
stored === 'logistics' ||
|
||||
stored === 'salesperson' ||
|
||||
stored === 'invoice_notice'
|
||||
stored === 'invoice_notice' ||
|
||||
stored === 'doctor_login' ||
|
||||
stored === 'oa_notify'
|
||||
) {
|
||||
if (stored === 'price_adjust' || stored === 'input_audit' || stored === 'miniprogram' || stored === 'oa_notify') {
|
||||
activeKey.value = stored;
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
function parseBoolConfig(val: unknown, defaultVal: boolean): boolean {
|
||||
if (val === undefined || val === null || val === '') return defaultVal;
|
||||
@@ -115,6 +118,9 @@ async function load() {
|
||||
if (row.config_key === 'salesperson_store_edit_enabled') {
|
||||
salespersonStoreEditEnabled.value = parseBoolConfig(row.config_value, false);
|
||||
}
|
||||
if (row.config_key === 'doctor_single_device_login') {
|
||||
doctorSingleDeviceLogin.value = parseBoolConfig(row.config_value, false);
|
||||
}
|
||||
if (row.config_key === 'invoice_notice_channels') {
|
||||
let channels: unknown = row.config_value;
|
||||
if (typeof channels === 'string') {
|
||||
@@ -188,6 +194,14 @@ async function handleSave() {
|
||||
description: '允许业务员编辑/改价/配置所属诊所',
|
||||
sort: 300,
|
||||
},
|
||||
{
|
||||
config_key: 'doctor_single_device_login',
|
||||
config_value: doctorSingleDeviceLogin.value ? '1' : '0',
|
||||
value_type: 'bool',
|
||||
config_group: 'auth',
|
||||
description: '业务端单机登录(医生/药师/诊所管理员等:1手机+1网页)',
|
||||
sort: 310,
|
||||
},
|
||||
{
|
||||
config_key: 'invoice_notice_channels',
|
||||
config_value: JSON.stringify(
|
||||
@@ -303,6 +317,20 @@ onMounted(() => {
|
||||
</div>
|
||||
</Tabs.TabPane>
|
||||
|
||||
<Tabs.TabPane key="doctor_login" tab="登录安全">
|
||||
<div class="py-4">
|
||||
<div class="mb-2 font-medium">单机登录</div>
|
||||
<div class="mb-2 text-sm text-gray-500">
|
||||
适用于医生/药师/诊所管理员/平台管理员/业务员及 PC 管理端。关闭时不限制登录设备;开启后同一账号仅允许 1 个手机端会话 + 1 个 PC 网页会话,同端后登录会使先登录失效;同手机号下不同身份互不影响
|
||||
</div>
|
||||
<Switch
|
||||
v-model:checked="doctorSingleDeviceLogin"
|
||||
checked-children="开启"
|
||||
un-checked-children="关闭"
|
||||
/>
|
||||
</div>
|
||||
</Tabs.TabPane>
|
||||
|
||||
<Tabs.TabPane key="invoice_notice" tab="开票通知">
|
||||
<div class="py-4">
|
||||
<div class="mb-2 font-medium">患者开票通知渠道</div>
|
||||
|
||||
Reference in New Issue
Block a user