Merge pull request #1220 from weak-fox/feat/account-privacy-mode-filter
feat: 管理员账号列表支持按 Privacy 状态筛选
This commit is contained in:
@@ -36,6 +36,7 @@ export async function list(
|
||||
status?: string
|
||||
group?: string
|
||||
search?: string
|
||||
privacy_mode?: string
|
||||
lite?: string
|
||||
},
|
||||
options?: {
|
||||
@@ -68,6 +69,7 @@ export async function listWithEtag(
|
||||
status?: string
|
||||
group?: string
|
||||
search?: string
|
||||
privacy_mode?: string
|
||||
lite?: string
|
||||
},
|
||||
options?: {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
<Select :model-value="filters.platform" class="w-40" :options="pOpts" @update:model-value="updatePlatform" @change="$emit('change')" />
|
||||
<Select :model-value="filters.type" class="w-40" :options="tOpts" @update:model-value="updateType" @change="$emit('change')" />
|
||||
<Select :model-value="filters.status" class="w-40" :options="sOpts" @update:model-value="updateStatus" @change="$emit('change')" />
|
||||
<Select :model-value="filters.privacy_mode" class="w-40" :options="privacyOpts" @update:model-value="updatePrivacyMode" @change="$emit('change')" />
|
||||
<Select :model-value="filters.group" class="w-40" :options="gOpts" @update:model-value="updateGroup" @change="$emit('change')" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -22,10 +23,18 @@ const emit = defineEmits(['update:searchQuery', 'update:filters', 'change']); co
|
||||
const updatePlatform = (value: string | number | boolean | null) => { emit('update:filters', { ...props.filters, platform: value }) }
|
||||
const updateType = (value: string | number | boolean | null) => { emit('update:filters', { ...props.filters, type: value }) }
|
||||
const updateStatus = (value: string | number | boolean | null) => { emit('update:filters', { ...props.filters, status: value }) }
|
||||
const updatePrivacyMode = (value: string | number | boolean | null) => { emit('update:filters', { ...props.filters, privacy_mode: value }) }
|
||||
const updateGroup = (value: string | number | boolean | null) => { emit('update:filters', { ...props.filters, group: value }) }
|
||||
const pOpts = computed(() => [{ value: '', label: t('admin.accounts.allPlatforms') }, { value: 'anthropic', label: 'Anthropic' }, { value: 'openai', label: 'OpenAI' }, { value: 'gemini', label: 'Gemini' }, { value: 'antigravity', label: 'Antigravity' }, { value: 'sora', label: 'Sora' }])
|
||||
const tOpts = computed(() => [{ value: '', label: t('admin.accounts.allTypes') }, { value: 'oauth', label: t('admin.accounts.oauthType') }, { value: 'setup-token', label: t('admin.accounts.setupToken') }, { value: 'apikey', label: t('admin.accounts.apiKey') }, { value: 'bedrock', label: 'AWS Bedrock' }])
|
||||
const sOpts = computed(() => [{ value: '', label: t('admin.accounts.allStatus') }, { value: 'active', label: t('admin.accounts.status.active') }, { value: 'inactive', label: t('admin.accounts.status.inactive') }, { value: 'error', label: t('admin.accounts.status.error') }, { value: 'rate_limited', label: t('admin.accounts.status.rateLimited') }, { value: 'temp_unschedulable', label: t('admin.accounts.status.tempUnschedulable') }])
|
||||
const privacyOpts = computed(() => [
|
||||
{ value: '', label: t('admin.accounts.allPrivacyModes') },
|
||||
{ value: '__unset__', label: t('admin.accounts.privacyUnset') },
|
||||
{ value: 'training_off', label: 'Privacy' },
|
||||
{ value: 'training_set_cf_blocked', label: 'CF' },
|
||||
{ value: 'training_set_failed', label: 'Fail' }
|
||||
])
|
||||
const gOpts = computed(() => [
|
||||
{ value: '', label: t('admin.accounts.allGroups') },
|
||||
{ value: 'ungrouped', label: t('admin.accounts.ungroupedGroup') },
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import { mount } from '@vue/test-utils'
|
||||
|
||||
import AccountTableFilters from '../AccountTableFilters.vue'
|
||||
|
||||
vi.mock('vue-i18n', async () => {
|
||||
const actual = await vi.importActual<typeof import('vue-i18n')>('vue-i18n')
|
||||
return {
|
||||
...actual,
|
||||
useI18n: () => ({
|
||||
t: (key: string) => key
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
describe('AccountTableFilters', () => {
|
||||
it('renders privacy mode options and emits privacy_mode updates', async () => {
|
||||
const wrapper = mount(AccountTableFilters, {
|
||||
props: {
|
||||
searchQuery: '',
|
||||
filters: {
|
||||
platform: '',
|
||||
type: '',
|
||||
status: '',
|
||||
group: '',
|
||||
privacy_mode: ''
|
||||
},
|
||||
groups: []
|
||||
},
|
||||
global: {
|
||||
stubs: {
|
||||
SearchInput: {
|
||||
template: '<div />'
|
||||
},
|
||||
Select: {
|
||||
props: ['modelValue', 'options'],
|
||||
emits: ['update:modelValue', 'change'],
|
||||
template: '<div class="select-stub" :data-options="JSON.stringify(options)" />'
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const selects = wrapper.findAll('.select-stub')
|
||||
expect(selects).toHaveLength(5)
|
||||
|
||||
const privacyOptions = JSON.parse(selects[3].attributes('data-options'))
|
||||
expect(privacyOptions).toEqual([
|
||||
{ value: '', label: 'admin.accounts.allPrivacyModes' },
|
||||
{ value: '__unset__', label: 'admin.accounts.privacyUnset' },
|
||||
{ value: 'training_off', label: 'Privacy' },
|
||||
{ value: 'training_set_cf_blocked', label: 'CF' },
|
||||
{ value: 'training_set_failed', label: 'Fail' }
|
||||
])
|
||||
})
|
||||
})
|
||||
@@ -1979,6 +1979,8 @@ export default {
|
||||
expiresAt: 'Expires At',
|
||||
actions: 'Actions'
|
||||
},
|
||||
allPrivacyModes: 'All Privacy States',
|
||||
privacyUnset: 'Unset',
|
||||
privacyTrainingOff: 'Training data sharing disabled',
|
||||
privacyCfBlocked: 'Blocked by Cloudflare, training may still be on',
|
||||
privacyFailed: 'Failed to disable training',
|
||||
|
||||
@@ -2017,6 +2017,8 @@ export default {
|
||||
expiresAt: '过期时间',
|
||||
actions: '操作'
|
||||
},
|
||||
allPrivacyModes: '全部Privacy状态',
|
||||
privacyUnset: '未设置',
|
||||
privacyTrainingOff: '已关闭训练数据共享',
|
||||
privacyCfBlocked: '被 Cloudflare 拦截,训练可能仍开启',
|
||||
privacyFailed: '关闭训练数据共享失败',
|
||||
|
||||
@@ -581,7 +581,7 @@ const {
|
||||
handlePageSizeChange: baseHandlePageSizeChange
|
||||
} = useTableLoader<Account, any>({
|
||||
fetchFn: adminAPI.accounts.list,
|
||||
initialParams: { platform: '', type: '', status: '', group: '', search: '' }
|
||||
initialParams: { platform: '', type: '', status: '', privacy_mode: '', group: '', search: '' }
|
||||
})
|
||||
|
||||
const {
|
||||
@@ -758,6 +758,7 @@ const refreshAccountsIncrementally = async () => {
|
||||
platform?: string
|
||||
type?: string
|
||||
status?: string
|
||||
privacy_mode?: string
|
||||
group?: string
|
||||
search?: string
|
||||
|
||||
|
||||
Reference in New Issue
Block a user