182 lines
5.8 KiB
Vue
182 lines
5.8 KiB
Vue
<script lang="ts" setup>
|
||
/**
|
||
* 系统配置 - 传方:进接诊 / 审方 / 小程序价格可见范围
|
||
* 价格门禁只约束诊所小程序;PC 审方端始终可见,不读这两项
|
||
*/
|
||
import { onMounted, ref, watch } from 'vue';
|
||
|
||
import { Button, Switch, message } from 'ant-design-vue';
|
||
|
||
import StoreMultiSearch from '#/components/form/components/store-multi-search.vue';
|
||
|
||
import { getSystemConfigList, saveSystemConfig } from '../api';
|
||
|
||
defineOptions({ name: 'ImageTransferConfigPanel' });
|
||
|
||
const loading = ref(false);
|
||
const saving = ref(false);
|
||
const toReception = ref(false);
|
||
const adminAudit = ref(true);
|
||
/** 全部诊所小程序可见传方报价 */
|
||
const priceVisibleAll = ref(false);
|
||
/** all=关时生效的门店白名单 */
|
||
const priceVisibleStoreIds = ref<number[]>([]);
|
||
|
||
function isOn(value: unknown) {
|
||
return value === '1' || value === 1 || value === true || value === 'true';
|
||
}
|
||
|
||
/** 把配置里的 json/数组/逗号串归一成 number[] */
|
||
function parseStoreIds(raw: unknown): number[] {
|
||
let list: unknown = raw;
|
||
if (typeof raw === 'string') {
|
||
const text = raw.trim();
|
||
if (!text) return [];
|
||
try {
|
||
list = JSON.parse(text);
|
||
} catch {
|
||
list = text.split(',');
|
||
}
|
||
}
|
||
if (!Array.isArray(list)) return [];
|
||
const ids: number[] = [];
|
||
for (const item of list) {
|
||
const n = Number(item);
|
||
if (Number.isFinite(n) && n > 0) ids.push(n);
|
||
}
|
||
return [...new Set(ids)];
|
||
}
|
||
|
||
async function load() {
|
||
loading.value = true;
|
||
try {
|
||
const list = await getSystemConfigList();
|
||
const rows = Array.isArray(list) ? list : list?.data || [];
|
||
for (const row of rows) {
|
||
if (row.config_key === 'image_transfer_to_reception') {
|
||
toReception.value = isOn(row.config_value);
|
||
}
|
||
if (row.config_key === 'image_transfer_admin_audit') {
|
||
adminAudit.value = isOn(row.config_value);
|
||
}
|
||
if (row.config_key === 'image_transfer_price_visible_all') {
|
||
priceVisibleAll.value = isOn(row.config_value);
|
||
}
|
||
if (row.config_key === 'image_transfer_price_visible_store_ids') {
|
||
priceVisibleStoreIds.value = parseStoreIds(row.config_value);
|
||
}
|
||
}
|
||
} finally {
|
||
loading.value = false;
|
||
}
|
||
}
|
||
|
||
/** 打开「全部可见」时清空白名单,避免误解成还要再勾门店 */
|
||
watch(priceVisibleAll, (on) => {
|
||
if (on) priceVisibleStoreIds.value = [];
|
||
});
|
||
|
||
/** 四个配置一起保存;门店名单存 json 数组字符串 */
|
||
async function handleSave() {
|
||
saving.value = true;
|
||
try {
|
||
await saveSystemConfig([
|
||
{
|
||
config_key: 'image_transfer_to_reception',
|
||
config_value: toReception.value ? '1' : '0',
|
||
value_type: 'bool',
|
||
config_group: 'image_transfer',
|
||
description: '识图传方确认后是否进入接诊',
|
||
},
|
||
{
|
||
config_key: 'image_transfer_admin_audit',
|
||
config_value: adminAudit.value ? '1' : '0',
|
||
value_type: 'bool',
|
||
config_group: 'image_transfer',
|
||
description: '不进接诊时是否需要后台审方',
|
||
},
|
||
{
|
||
config_key: 'image_transfer_price_visible_all',
|
||
config_value: priceVisibleAll.value ? '1' : '0',
|
||
value_type: 'bool',
|
||
config_group: 'image_transfer',
|
||
description: '识图传方小程序是否对全部诊所展示报价',
|
||
},
|
||
{
|
||
config_key: 'image_transfer_price_visible_store_ids',
|
||
config_value: JSON.stringify(
|
||
priceVisibleAll.value ? [] : priceVisibleStoreIds.value,
|
||
),
|
||
value_type: 'json',
|
||
config_group: 'image_transfer',
|
||
description: '识图传方价格可见门店ID白名单(json数组)',
|
||
},
|
||
]);
|
||
message.success('保存成功');
|
||
} finally {
|
||
saving.value = false;
|
||
}
|
||
}
|
||
|
||
onMounted(load);
|
||
</script>
|
||
|
||
<template>
|
||
<div class="cfg-panel" :class="{ 'opacity-60': loading }">
|
||
<div class="cfg-panel-body">
|
||
<div class="mb-2 font-medium text-[hsl(var(--foreground))]">
|
||
识图传方确认后是否进入接诊
|
||
</div>
|
||
<div class="mb-4 text-sm text-[hsl(var(--muted-foreground))]">
|
||
关闭后只生成传方订单,不挂号、不跳接诊
|
||
</div>
|
||
<Switch
|
||
v-model:checked="toReception"
|
||
checked-children="进接诊"
|
||
un-checked-children="不进"
|
||
/>
|
||
|
||
<div class="mb-2 mt-6 font-medium text-[hsl(var(--foreground))]">
|
||
不进接诊时是否需要后台审方
|
||
</div>
|
||
<div class="mb-4 text-sm text-[hsl(var(--muted-foreground))]">
|
||
关闭后用户提交即推 MES;驳回仍会退回诊所和上传人
|
||
</div>
|
||
<Switch
|
||
v-model:checked="adminAudit"
|
||
checked-children="需要"
|
||
un-checked-children="跳过"
|
||
/>
|
||
|
||
<div class="mb-2 mt-6 font-medium text-[hsl(var(--foreground))]">
|
||
小程序是否全部诊所可见传方价格
|
||
</div>
|
||
<div class="mb-4 text-sm text-[hsl(var(--muted-foreground))]">
|
||
开启后所有诊所医生/管理员都能看药价、代煎费、运费;关闭则仅下方白名单门店可见。PC
|
||
审方端始终可见,不受此开关影响。
|
||
</div>
|
||
<Switch
|
||
v-model:checked="priceVisibleAll"
|
||
checked-children="全部可见"
|
||
un-checked-children="按白名单"
|
||
/>
|
||
|
||
<div v-if="!priceVisibleAll" class="mt-6">
|
||
<div class="mb-2 font-medium text-[hsl(var(--foreground))]">
|
||
可看价格的诊所白名单
|
||
</div>
|
||
<div class="mb-3 text-sm text-[hsl(var(--muted-foreground))]">
|
||
未勾选任何诊所时,小程序端不展示报价(仍可正常传方)
|
||
</div>
|
||
<StoreMultiSearch
|
||
v-model:value="priceVisibleStoreIds"
|
||
placeholder="搜索并添加可看价格的诊所"
|
||
/>
|
||
</div>
|
||
</div>
|
||
<div class="cfg-panel-footer">
|
||
<Button type="primary" :loading="saving" @click="handleSave">保存本模块配置</Button>
|
||
</div>
|
||
</div>
|
||
</template>
|