From 16cd1b41a66a3fd4756ebf451256f47fbe91ac35 Mon Sep 17 00:00:00 2001 From: blankll Date: Wed, 28 Oct 2026 01:29:52 +0800 Subject: [PATCH] fix: align source permission modal with permission editor conventions - replace the select + checkbox controls with AccessLevelPicker-style radio cards and Switch rows matching ConnectionPermissionEditor - restore the destructive detach affordance and inline footer confirm - resolve cancel copy through common.buttons.cancel - drop orphaned aiPermissions/modifySource keys and update the modal test --- src/__tests__/aiPermissions.test.ts | 2 +- src/lang/enUS.ts | 11 -- src/lang/zhCN.ts | 11 -- .../components/modify-source-modal.vue | 131 +++++++++++------- 4 files changed, 82 insertions(+), 73 deletions(-) diff --git a/src/__tests__/aiPermissions.test.ts b/src/__tests__/aiPermissions.test.ts index b5349dea..4d760174 100644 --- a/src/__tests__/aiPermissions.test.ts +++ b/src/__tests__/aiPermissions.test.ts @@ -263,7 +263,7 @@ describe('aI permission chain', () => { await wrapper.findAll('button').find(button => button.text() === 'dataStudio.detachSource.title')!.trigger('click') expect(wrapper.text()).toContain('dataStudio.detachSource.message') expect(mockStore.detachSourceFromSession).not.toHaveBeenCalled() - await wrapper.findAll('button').find(button => button.text() === 'aiPermissions.cancel')!.trigger('click') + await wrapper.findAll('button').find(button => button.text() === 'common.buttons.cancel')!.trigger('click') expect(wrapper.text()).not.toContain('dataStudio.detachSource.message') expect(wrapper.emitted('update:open')).toBeUndefined() }) diff --git a/src/lang/enUS.ts b/src/lang/enUS.ts index 3c637c45..0d9033e6 100644 --- a/src/lang/enUS.ts +++ b/src/lang/enUS.ts @@ -5,11 +5,7 @@ export const enUS = { unavailable: 'Unavailable', loadError: 'Could not load permissions', saving: 'Saving…', - conversationHelp: 'Uses the current connection permissions. Conversation limits can only restrict access; Ask/Auto only controls confirmation.', - useConnection: 'Use connection permissions', - limitConversation: 'Limit this conversation', deniedByConnection: 'Denied by connection permissions', - cancel: 'Cancel', conversationReadOnly: 'Read-only for this conversation', title: 'AI permissions', help: 'Applies to Data Studio and external MCP clients. Use system defaults or set permissions for this connection.', @@ -1158,13 +1154,6 @@ export const enUS = { title: 'Modify Datasource', accessPermissions: 'Access Permissions', inheritTitle: 'Use connection permissions', - inheritDesc: 'Uses the current connection permission chain.', - customTitle: 'Custom', - customDesc: 'Manually define which operations are allowed for this source.', - read: 'Read', - create: 'Create', - update: 'Update', - delete: 'Delete', saveChanges: 'Save Changes', modeDefault: 'Ask', modeFull: 'Auto', diff --git a/src/lang/zhCN.ts b/src/lang/zhCN.ts index a6a66358..9703ad04 100644 --- a/src/lang/zhCN.ts +++ b/src/lang/zhCN.ts @@ -5,11 +5,7 @@ export const zhCN = { unavailable: '暂不可用', loadError: '无法加载权限', saving: '正在保存…', - conversationHelp: '使用当前连接权限。会话设置只能进一步限制访问;询问/自动模式只控制操作确认。', - useConnection: '使用连接权限', - limitConversation: '限制当前会话', deniedByConnection: '连接权限已禁止', - cancel: '取消', conversationReadOnly: '当前会话只读', title: 'AI 权限', help: '适用于 Data Studio 和外部 MCP 客户端。可使用系统默认值,也可为此连接单独设置权限。', @@ -1158,13 +1154,6 @@ export const zhCN = { title: '修改数据源', accessPermissions: '访问权限', inheritTitle: '使用连接权限', - inheritDesc: '遵循连接当前的权限链,未单独设置的操作使用系统默认权限。', - customTitle: '自定义', - customDesc: '手动定义该数据源允许的操作。', - read: '读取', - create: '创建', - update: '更新', - delete: '删除', saveChanges: '保存修改', modeDefault: '询问', modeFull: '自动', diff --git a/src/views/data-studio/components/modify-source-modal.vue b/src/views/data-studio/components/modify-source-modal.vue index 911d967b..8bc89983 100644 --- a/src/views/data-studio/components/modify-source-modal.vue +++ b/src/views/data-studio/components/modify-source-modal.vue @@ -4,12 +4,13 @@ import { computed, ref, watch } from 'vue' import { useI18n } from 'vue-i18n' import { AI_ACTIONS, aiPreset, getAiPolicy, resolveAiPermissions } from '@/common' import { Button } from '@/components/ui/button' -import { Checkbox } from '@/components/ui/checkbox' -import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog' +import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog' import { Label } from '@/components/ui/label' -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select' +import { Switch } from '@/components/ui/switch' import { useDataStudioStore } from '@/store/dataStudioStore' +type SourceMode = 'inherit' | 'custom' + const props = defineProps<{ open: boolean, sourceIdx: number }>() const emit = defineEmits<{ 'update:open': [value: boolean] }>() const { t } = useI18n() @@ -17,13 +18,17 @@ const store = useDataStudioStore() const source = computed(() => store.activeSession?.sources.filter(s => !s.detached)[props.sourceIdx]) const base = ref({}) const local = ref({}) -const mode = ref<'inherit' | 'custom'>('inherit') +const mode = ref('inherit') const loaded = ref(false) const failedAction = ref<'load' | 'save' | 'detach'>('load') const loading = ref(false) const saving = ref(false) const error = ref('') const detachConfirming = ref(false) +const modeOptions: { value: SourceMode, label: string }[] = [ + { value: 'inherit', label: 'dataStudio.modifySource.inheritTitle' }, + { value: 'custom', label: 'aiPermissions.custom' }, +] const allowed = computed(() => AI_ACTIONS.filter(action => base.value[action] && (mode.value === 'inherit' || local.value[action] === true))) let request = 0 const load = async () => { @@ -105,19 +110,21 @@ const retry = () => failedAction.value === 'load' ? load() : failedAction.value