更新
This commit is contained in:
@@ -0,0 +1,227 @@
|
||||
<template>
|
||||
<div class="prescription-ai-visibility">
|
||||
<el-card v-loading="loading" shadow="never" class="!border-none">
|
||||
<div class="text-xl font-medium mb-[20px]">处方 AI 一致度可见范围</div>
|
||||
<el-alert type="info" :closable="false" show-icon class="mb-5">
|
||||
<template #title>指定用户组或用户可查看一致度</template>
|
||||
<div class="leading-6">
|
||||
用户命中任一指定系统角色,或被单独指定,即可查看桌面端“与 AI
|
||||
一致度”、逐味对照和一致度统计。AI
|
||||
报告继续按原有权限开放,已有报告不受影响,患者与处方的数据范围保持原有规则。
|
||||
</div>
|
||||
</el-alert>
|
||||
|
||||
<el-alert
|
||||
v-if="loadError"
|
||||
:title="loadError"
|
||||
type="error"
|
||||
:closable="false"
|
||||
show-icon
|
||||
class="mb-5"
|
||||
/>
|
||||
<div v-if="loading" role="status" class="mb-5">正在读取当前可见范围…</div>
|
||||
|
||||
<el-form
|
||||
v-if="hasLoaded"
|
||||
class="ls-form"
|
||||
:model="formData"
|
||||
:disabled="!ready || loading || saving"
|
||||
label-width="140px"
|
||||
>
|
||||
<el-form-item label="指定用户组" prop="role_ids">
|
||||
<div class="w-full max-w-[640px]">
|
||||
<el-select
|
||||
v-model="formData.role_ids"
|
||||
class="w-full"
|
||||
multiple
|
||||
filterable
|
||||
clearable
|
||||
placeholder="请选择系统角色,可搜索角色名称"
|
||||
>
|
||||
<el-option
|
||||
v-for="role in roleOptions"
|
||||
:key="role.id"
|
||||
:label="role.name"
|
||||
:value="role.id"
|
||||
/>
|
||||
</el-select>
|
||||
<div class="form-tips">账号拥有任一指定角色即可命中。</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="指定用户" prop="admin_ids">
|
||||
<div class="w-full max-w-[640px]">
|
||||
<el-select
|
||||
v-model="formData.admin_ids"
|
||||
class="w-full"
|
||||
multiple
|
||||
filterable
|
||||
clearable
|
||||
placeholder="请选择用户,可搜索姓名或账号"
|
||||
>
|
||||
<el-option
|
||||
v-for="admin in adminOptions"
|
||||
:key="admin.id"
|
||||
:label="admin.label"
|
||||
:value="admin.id"
|
||||
/>
|
||||
</el-select>
|
||||
<div class="form-tips">
|
||||
单独指定的用户无需同时命中用户组。当前不在可选列表中的已配置 ID
|
||||
会保留,移除后保存才会取消该项授权。
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="生效规则">
|
||||
<div>
|
||||
<div class="leading-6">指定用户组与指定用户按“或”生效。</div>
|
||||
<div class="form-tips">
|
||||
两项均为空时,所有账号(包括超级管理员)均隐藏一致度、对照与统计。
|
||||
拥有本页管理权限不自动获得一致度查看权,超级管理员也需命中上述名单。
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-alert
|
||||
v-if="ready && !formData.role_ids.length && !formData.admin_ids.length"
|
||||
title="当前选择为空:保存后所有账号将隐藏一致度、对照与统计,AI 报告仍保留。"
|
||||
type="warning"
|
||||
:closable="false"
|
||||
show-icon
|
||||
class="mb-5"
|
||||
/>
|
||||
<el-alert
|
||||
v-if="saveError"
|
||||
:title="saveError"
|
||||
type="error"
|
||||
:closable="false"
|
||||
show-icon
|
||||
class="mb-5"
|
||||
/>
|
||||
<el-button :disabled="loading || saving" @click="loadConfig">
|
||||
{{ loadError ? '重试加载' : '重新加载' }}
|
||||
</el-button>
|
||||
</el-card>
|
||||
|
||||
<footer-btns v-if="canManage">
|
||||
<el-button
|
||||
type="primary"
|
||||
:loading="saving"
|
||||
:disabled="!ready || loading || saving"
|
||||
@click="handleSubmit"
|
||||
>
|
||||
{{ saving ? '正在保存' : '保存' }}
|
||||
</el-button>
|
||||
</footer-btns>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="prescriptionAiVisibility">
|
||||
import { computed, reactive, ref } from 'vue'
|
||||
|
||||
import type {
|
||||
PrescriptionAiVisibilityConfig,
|
||||
PrescriptionAiVisibilityOptions
|
||||
} from '@/api/setting/prescription_ai_visibility'
|
||||
import {
|
||||
getPrescriptionAiCapabilities,
|
||||
getPrescriptionAiVisibilityConfig,
|
||||
getPrescriptionAiVisibilityOptions,
|
||||
setPrescriptionAiVisibilityConfig
|
||||
} from '@/api/setting/prescription_ai_visibility'
|
||||
import feedback from '@/utils/feedback'
|
||||
|
||||
const loading = ref(false)
|
||||
const saving = ref(false)
|
||||
const ready = ref(false)
|
||||
const hasLoaded = ref(false)
|
||||
const canManage = ref(false)
|
||||
const loadError = ref('')
|
||||
const saveError = ref('')
|
||||
const formData = reactive<PrescriptionAiVisibilityConfig>({ role_ids: [], admin_ids: [] })
|
||||
const optionsData = reactive<PrescriptionAiVisibilityOptions>({ roles: [], admins: [] })
|
||||
|
||||
const roleOptions = computed(() => {
|
||||
const options = new Map(optionsData.roles.map((role) => [role.id, role]))
|
||||
for (const id of formData.role_ids) {
|
||||
if (!options.has(id)) {
|
||||
options.set(id, { id, name: `已配置角色 #${id}(当前不在可选列表)` })
|
||||
}
|
||||
}
|
||||
return [...options.values()]
|
||||
})
|
||||
|
||||
const adminOptions = computed(() => {
|
||||
const options = new Map(
|
||||
optionsData.admins.map((admin) => [
|
||||
admin.id,
|
||||
{ id: admin.id, label: `${admin.name || `用户 #${admin.id}`}(${admin.account})` }
|
||||
])
|
||||
)
|
||||
for (const id of formData.admin_ids) {
|
||||
if (!options.has(id)) {
|
||||
options.set(id, { id, label: `已配置用户 #${id}(当前不在可选列表)` })
|
||||
}
|
||||
}
|
||||
return [...options.values()]
|
||||
})
|
||||
|
||||
const assignConfig = (config: PrescriptionAiVisibilityConfig) => {
|
||||
formData.role_ids = [...config.role_ids]
|
||||
formData.admin_ids = [...config.admin_ids]
|
||||
}
|
||||
|
||||
const loadConfig = async () => {
|
||||
if (loading.value || saving.value) return
|
||||
loading.value = true
|
||||
ready.value = false
|
||||
canManage.value = false
|
||||
loadError.value = ''
|
||||
saveError.value = ''
|
||||
try {
|
||||
const capabilities = await getPrescriptionAiCapabilities()
|
||||
if (capabilities.can_manage_visibility !== true) {
|
||||
loadError.value = '当前账号无权管理处方 AI 一致度可见范围。'
|
||||
return
|
||||
}
|
||||
canManage.value = true
|
||||
const [config, options] = await Promise.all([
|
||||
getPrescriptionAiVisibilityConfig(),
|
||||
getPrescriptionAiVisibilityOptions()
|
||||
])
|
||||
if (!Array.isArray(options?.roles) || !Array.isArray(options?.admins)) {
|
||||
throw new Error('可选用户组或用户响应格式不正确')
|
||||
}
|
||||
// Apply both responses together; an incomplete load cannot overwrite the current policy.
|
||||
assignConfig(config)
|
||||
optionsData.roles = options.roles
|
||||
optionsData.admins = options.admins
|
||||
hasLoaded.value = true
|
||||
ready.value = true
|
||||
} catch {
|
||||
loadError.value = '可见范围加载失败,尚未读取完整配置。请重试加载后再保存。'
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (!ready.value || !canManage.value || loading.value || saving.value) return
|
||||
saving.value = true
|
||||
saveError.value = ''
|
||||
try {
|
||||
const config = await setPrescriptionAiVisibilityConfig({
|
||||
role_ids: [...formData.role_ids],
|
||||
admin_ids: [...formData.admin_ids]
|
||||
})
|
||||
assignConfig(config)
|
||||
feedback.msgSuccess('可见范围已保存')
|
||||
} catch {
|
||||
saveError.value = '保存结果未确认,当前选择已保留。请重试保存,或重新加载以确认服务端策略。'
|
||||
} finally {
|
||||
saving.value = false
|
||||
}
|
||||
}
|
||||
|
||||
void loadConfig()
|
||||
</script>
|
||||
Reference in New Issue
Block a user