Merge branch 'long-0507'
This commit is contained in:
Generated
+9731
File diff suppressed because it is too large
Load Diff
@@ -23,10 +23,10 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="daily-matrix__toolbar-right">
|
<div class="daily-matrix__toolbar-right">
|
||||||
<el-button :disabled="readOnly" type="primary" @click="openQuickAdd('blood')">+血糖</el-button>
|
<el-button :disabled="!canEditDailyRecord" type="primary" @click="openQuickAdd('blood')">+血糖</el-button>
|
||||||
<el-button :disabled="readOnly" @click="openQuickAdd('diet')">+饮食</el-button>
|
<el-button :disabled="!canEditDailyRecord" @click="openQuickAdd('diet')">+饮食</el-button>
|
||||||
<el-button :disabled="readOnly" @click="openQuickAdd('exercise')">+运动</el-button>
|
<el-button :disabled="!canEditDailyRecord" @click="openQuickAdd('exercise')">+运动</el-button>
|
||||||
<el-button :disabled="readOnly" @click="openQuickAdd('tracking')">+备注</el-button>
|
<el-button :disabled="!canEditDailyRecord" @click="openQuickAdd('tracking')">+备注</el-button>
|
||||||
<el-button @click="fetchTracking">刷新</el-button>
|
<el-button @click="fetchTracking">刷新</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -160,7 +160,7 @@
|
|||||||
</el-form>
|
</el-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<el-button @click="bloodDialogVisible = false">取消</el-button>
|
<el-button @click="bloodDialogVisible = false">取消</el-button>
|
||||||
<el-button type="primary" :loading="bloodSubmitting" @click="submitBlood">确定</el-button>
|
<el-button type="primary" :loading="bloodSubmitting" :disabled="!canEditDailyRecord" @click="submitBlood">确定</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
@@ -202,7 +202,7 @@
|
|||||||
</el-form>
|
</el-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<el-button @click="dietDialogVisible = false">取消</el-button>
|
<el-button @click="dietDialogVisible = false">取消</el-button>
|
||||||
<el-button type="primary" :loading="dietSubmitting" @click="submitDiet">确定</el-button>
|
<el-button type="primary" :loading="dietSubmitting" :disabled="!canEditDailyRecord" @click="submitDiet">确定</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
@@ -247,7 +247,7 @@
|
|||||||
</el-form>
|
</el-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<el-button @click="exerciseDialogVisible = false">取消</el-button>
|
<el-button @click="exerciseDialogVisible = false">取消</el-button>
|
||||||
<el-button type="primary" :loading="exerciseSubmitting" @click="submitExercise">确定</el-button>
|
<el-button type="primary" :loading="exerciseSubmitting" :disabled="!canEditDailyRecord" @click="submitExercise">确定</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
@@ -385,6 +385,7 @@ interface TrackingNoteRecord {
|
|||||||
|
|
||||||
type RangeMode = '7' | '30' | 'custom'
|
type RangeMode = '7' | '30' | 'custom'
|
||||||
type DialogKind = 'blood' | 'diet' | 'exercise' | 'tracking'
|
type DialogKind = 'blood' | 'diet' | 'exercise' | 'tracking'
|
||||||
|
const DAILY_RECORD_PERMS = ['tcm.diagnosis/dailyRecord']
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
age: undefined,
|
age: undefined,
|
||||||
@@ -396,7 +397,9 @@ const diagnosisId = computed(() => Number(props.diagnosisId || 0))
|
|||||||
const patientId = computed(() => Number(props.patientId || 0))
|
const patientId = computed(() => Number(props.patientId || 0))
|
||||||
const readOnly = computed(() => !!props.readOnly)
|
const readOnly = computed(() => !!props.readOnly)
|
||||||
const patientName = computed(() => props.patientName || '')
|
const patientName = computed(() => props.patientName || '')
|
||||||
const canViewTodoList = computed(() => hasPermission(['tcm.diagnosisTodo/lists']))
|
const hasDailyRecordPermission = computed(() => hasPermission(DAILY_RECORD_PERMS))
|
||||||
|
const canEditDailyRecord = computed(() => hasDailyRecordPermission.value && !readOnly.value)
|
||||||
|
const canViewTodoList = computed(() => hasDailyRecordPermission.value)
|
||||||
|
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const rangeMode = ref<RangeMode>('7')
|
const rangeMode = ref<RangeMode>('7')
|
||||||
@@ -849,6 +852,7 @@ function handleCustomRangeChange() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function openQuickAdd(kind: DialogKind) {
|
function openQuickAdd(kind: DialogKind) {
|
||||||
|
if (!canEditDailyRecord.value) return
|
||||||
const date = visibleDates.value[0] || formatDate(new Date())
|
const date = visibleDates.value[0] || formatDate(new Date())
|
||||||
if (kind === 'blood') {
|
if (kind === 'blood') {
|
||||||
bloodForm.value = createBloodForm(date)
|
bloodForm.value = createBloodForm(date)
|
||||||
@@ -876,7 +880,7 @@ function openQuickAdd(kind: DialogKind) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleCellClick(metric: string, date: string) {
|
function handleCellClick(metric: string, date: string) {
|
||||||
if (readOnly.value) return
|
if (!canEditDailyRecord.value) return
|
||||||
if (['fasting', 'postprandial', 'other', 'bp', 'western', 'insulin'].includes(metric)) {
|
if (['fasting', 'postprandial', 'other', 'bp', 'western', 'insulin'].includes(metric)) {
|
||||||
const source = bloodByDate.value.get(date)
|
const source = bloodByDate.value.get(date)
|
||||||
bloodForm.value = source ? { ...createBloodForm(date), ...source } : createBloodForm(date)
|
bloodForm.value = source ? { ...createBloodForm(date), ...source } : createBloodForm(date)
|
||||||
@@ -1014,7 +1018,7 @@ function getTrackingPreview(content: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function isCellClickable(metric: string, date: string) {
|
function isCellClickable(metric: string, date: string) {
|
||||||
if (readOnly.value) return false
|
if (!canEditDailyRecord.value) return false
|
||||||
if (metric !== 'tracking') return true
|
if (metric !== 'tracking') return true
|
||||||
return date === todayDate.value || !!getTrackingContent(date)
|
return date === todayDate.value || !!getTrackingContent(date)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
<div class="toolbar">
|
<div class="toolbar">
|
||||||
<el-button
|
<el-button
|
||||||
type="primary"
|
type="primary"
|
||||||
:disabled="!props.diagnosisId || !!props.readOnly"
|
:disabled="!props.diagnosisId || !!props.readOnly || !hasDailyRecordPermission"
|
||||||
@click="handleAdd"
|
@click="handleAdd"
|
||||||
v-perms="['tcm.diagnosisTodo/add']"
|
v-perms="DAILY_RECORD_PERMS"
|
||||||
>
|
>
|
||||||
+ 新增待办
|
+ 新增待办
|
||||||
</el-button>
|
</el-button>
|
||||||
@@ -55,7 +55,7 @@
|
|||||||
link
|
link
|
||||||
type="danger"
|
type="danger"
|
||||||
@click="handleCancel(row)"
|
@click="handleCancel(row)"
|
||||||
v-perms="['tcm.diagnosisTodo/cancel']"
|
v-perms="DAILY_RECORD_PERMS"
|
||||||
>
|
>
|
||||||
取消
|
取消
|
||||||
</el-button>
|
</el-button>
|
||||||
@@ -114,8 +114,12 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { FormInstance, FormRules } from 'element-plus'
|
import type { FormInstance, FormRules } from 'element-plus'
|
||||||
import { diagnosisTodoLists, diagnosisTodoAdd, diagnosisTodoCancel } from '@/api/tcm'
|
import { diagnosisTodoLists, diagnosisTodoAdd, diagnosisTodoCancel } from '@/api/tcm'
|
||||||
|
import { computed } from 'vue'
|
||||||
|
import { hasPermission } from '@/utils/perm'
|
||||||
import feedback from '@/utils/feedback'
|
import feedback from '@/utils/feedback'
|
||||||
|
|
||||||
|
const DAILY_RECORD_PERMS = ['tcm.diagnosis/dailyRecord']
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
diagnosisId: number | null | undefined
|
diagnosisId: number | null | undefined
|
||||||
patientId?: number | null
|
patientId?: number | null
|
||||||
@@ -124,6 +128,7 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
|
const hasDailyRecordPermission = computed(() => hasPermission(DAILY_RECORD_PERMS))
|
||||||
|
|
||||||
// pager 与项目内 <pagination v-model="pager" /> 约定的字段保持一致
|
// pager 与项目内 <pagination v-model="pager" /> 约定的字段保持一致
|
||||||
const pager = reactive({
|
const pager = reactive({
|
||||||
@@ -137,7 +142,7 @@ const pager = reactive({
|
|||||||
const filterStatus = ref<number | ''>('')
|
const filterStatus = ref<number | ''>('')
|
||||||
|
|
||||||
const fetchList = async () => {
|
const fetchList = async () => {
|
||||||
if (!props.diagnosisId || Number(props.diagnosisId) <= 0) {
|
if (!props.diagnosisId || Number(props.diagnosisId) <= 0 || !hasDailyRecordPermission.value) {
|
||||||
pager.lists = []
|
pager.lists = []
|
||||||
pager.count = 0
|
pager.count = 0
|
||||||
return
|
return
|
||||||
@@ -221,7 +226,7 @@ const disablePastDate = (date: Date) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleAdd = () => {
|
const handleAdd = () => {
|
||||||
if (!props.diagnosisId || props.readOnly) {
|
if (!props.diagnosisId || props.readOnly || !hasDailyRecordPermission.value) {
|
||||||
feedback.msgWarning('诊单未保存,无法添加待办')
|
feedback.msgWarning('诊单未保存,无法添加待办')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -260,6 +265,7 @@ const handleAddSubmit = async () => {
|
|||||||
|
|
||||||
// ========== 取消 ==========
|
// ========== 取消 ==========
|
||||||
const handleCancel = async (row: any) => {
|
const handleCancel = async (row: any) => {
|
||||||
|
if (!hasDailyRecordPermission.value || props.readOnly) return
|
||||||
try {
|
try {
|
||||||
await feedback.confirm(`确认取消「${row.remind_time_text} · ${truncate(row.content, 30)}」吗?`)
|
await feedback.confirm(`确认取消「${row.remind_time_text} · ${truncate(row.content, 30)}」吗?`)
|
||||||
} catch {
|
} catch {
|
||||||
|
|||||||
@@ -573,7 +573,13 @@
|
|||||||
</div>
|
</div>
|
||||||
<el-empty v-else description="请先保存诊单后查看" />
|
<el-empty v-else description="请先保存诊单后查看" />
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane label="日常记录" name="daily" :disabled="!formData.id" lazy>
|
<el-tab-pane
|
||||||
|
v-if="hasDailyRecordPermission"
|
||||||
|
label="日常记录"
|
||||||
|
name="daily"
|
||||||
|
:disabled="!formData.id"
|
||||||
|
lazy
|
||||||
|
>
|
||||||
<daily-matrix
|
<daily-matrix
|
||||||
v-if="formData.id"
|
v-if="formData.id"
|
||||||
:diagnosis-id="Number(formData.id)"
|
:diagnosis-id="Number(formData.id)"
|
||||||
@@ -736,6 +742,7 @@ const submitting = ref(false)
|
|||||||
|
|
||||||
/** 拥有后手机号可正常编辑,失焦不再强制脱敏 */
|
/** 拥有后手机号可正常编辑,失焦不再强制脱敏 */
|
||||||
const hasPhonePlainPermission = computed(() => hasPermission(['tcm.diagnosis/phonePlain']))
|
const hasPhonePlainPermission = computed(() => hasPermission(['tcm.diagnosis/phonePlain']))
|
||||||
|
const hasDailyRecordPermission = computed(() => hasPermission(['tcm.diagnosis/dailyRecord']))
|
||||||
/** 编辑且无明文权限:只读脱敏,点击切换查看完整号 */
|
/** 编辑且无明文权限:只读脱敏,点击切换查看完整号 */
|
||||||
const showPhoneMaskedEdit = computed(() => mode.value === 'edit' && !hasPhonePlainPermission.value)
|
const showPhoneMaskedEdit = computed(() => mode.value === 'edit' && !hasPhonePlainPermission.value)
|
||||||
const phoneRevealUnlocked = ref(false)
|
const phoneRevealUnlocked = ref(false)
|
||||||
@@ -790,6 +797,9 @@ watch([visible, activeTab], () => {
|
|||||||
if (activeTab.value === 'appointmentRecords' && !hasPermission(['doctor.appointment/lists'])) {
|
if (activeTab.value === 'appointmentRecords' && !hasPermission(['doctor.appointment/lists'])) {
|
||||||
activeTab.value = 'basic'
|
activeTab.value = 'basic'
|
||||||
}
|
}
|
||||||
|
if (activeTab.value === 'daily' && !hasDailyRecordPermission.value) {
|
||||||
|
activeTab.value = 'basic'
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ class AuthMiddleware
|
|||||||
$AdminUris = $adminAuthCache->getAdminUri() ?? [];
|
$AdminUris = $adminAuthCache->getAdminUri() ?? [];
|
||||||
$AdminUris = $this->formatUrl($AdminUris);
|
$AdminUris = $this->formatUrl($AdminUris);
|
||||||
|
|
||||||
if (in_array($accessUri, $AdminUris)) {
|
if (in_array($accessUri, $AdminUris) || $this->matchPermissionAlias($accessUri, $AdminUris)) {
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
return JsonService::fail('权限不足,无法访问或操作');
|
return JsonService::fail('权限不足,无法访问或操作');
|
||||||
@@ -103,6 +103,25 @@ class AuthMiddleware
|
|||||||
}, $data);
|
}, $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日常记录权限域:前端统一收口到 tcm.diagnosis/dailyRecord,
|
||||||
|
* 但待办/跟踪备注接口仍保留历史路由名,故在鉴权层做精确别名映射。
|
||||||
|
*/
|
||||||
|
private function matchPermissionAlias(string $accessUri, array $adminUris): bool
|
||||||
|
{
|
||||||
|
if (!in_array('tcm.diagnosis/dailyrecord', $adminUris, true)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return in_array($accessUri, [
|
||||||
|
'tcm.diagnosistodo/lists',
|
||||||
|
'tcm.diagnosistodo/add',
|
||||||
|
'tcm.diagnosistodo/cancel',
|
||||||
|
'tcm.diagnosis/trackingnotes',
|
||||||
|
'tcm.diagnosis/addtrackingnote',
|
||||||
|
], true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 面诊进度专用:auth.admin/lists、doctor.appointment/lists + progress_board=1,不校验菜单权限
|
* 面诊进度专用:auth.admin/lists、doctor.appointment/lists + progress_board=1,不校验菜单权限
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -31,7 +31,8 @@ use app\common\model\tcm\DiagnosisTodo;
|
|||||||
* cancel() → status=2 (已取消,仅 status=0 可取消)
|
* cancel() → status=2 (已取消,仅 status=0 可取消)
|
||||||
*
|
*
|
||||||
* 鉴权:
|
* 鉴权:
|
||||||
* add:诊单需存在;数据权限交由路由层「tcm.diagnosisTodo/add」节点 + 前端 tab disabled 控制。
|
* add:诊单需存在;数据权限交由路由层统一「tcm.diagnosis/dailyRecord」权限域控制,
|
||||||
|
* 并兼容历史 diagnosisTodo/* 接口路由。
|
||||||
* cancel:仅创建人本人或超级管理员 (role_id=1) 可取消,且仅 status=0 时。
|
* cancel:仅创建人本人或超级管理员 (role_id=1) 可取消,且仅 status=0 时。
|
||||||
*
|
*
|
||||||
* @package app\adminapi\logic\tcm
|
* @package app\adminapi\logic\tcm
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# 诊单编辑:日常记录统一权限(2026-05-07)
|
||||||
|
# 挂在「中医诊单」(perms=tcm.diagnosis/lists) 菜单下,按钮型权限节点:
|
||||||
|
# tcm.diagnosis/dailyRecord 日常记录(统一控制血糖/饮食/运动/跟踪备注/待办)
|
||||||
|
|
||||||
|
SET @diag_menu_id := (SELECT id FROM zyt_system_menu WHERE perms = 'tcm.diagnosis/lists' LIMIT 1);
|
||||||
|
|
||||||
|
INSERT INTO zyt_system_menu (
|
||||||
|
pid, type, name, icon, sort, perms, paths, component,
|
||||||
|
selected, params, is_cache, is_show, is_disable, create_time, update_time
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
@diag_menu_id, 'A', '日常记录', '', 59,
|
||||||
|
'tcm.diagnosis/dailyRecord', '', '',
|
||||||
|
'', '', 0, 1, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
|
||||||
|
FROM DUAL
|
||||||
|
WHERE @diag_menu_id IS NOT NULL
|
||||||
|
AND NOT EXISTS (SELECT 1 FROM zyt_system_menu WHERE perms = 'tcm.diagnosis/dailyRecord');
|
||||||
Reference in New Issue
Block a user