mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-09-21 14:19:18 +08:00
Merge pull request #4279 from bestony/agent/0268b42f/bes-21-groups-id-column
feat(admin): /admin/groups 列表设置新增 ID 列
This commit is contained in:
@@ -757,6 +757,7 @@ export default {
|
||||
public: 'Public',
|
||||
columns: {
|
||||
name: 'Name',
|
||||
id: 'ID',
|
||||
platform: 'Platform',
|
||||
rateMultiplier: 'Rate Multiplier',
|
||||
rpmOverride: 'RPM Override',
|
||||
|
||||
@@ -750,6 +750,7 @@ export default {
|
||||
"确定要删除订阅分组 '{name}' 吗?此操作会让所有绑定此订阅的用户的 API Key 失效,并删除所有相关的订阅记录。此操作无法撤销。",
|
||||
columns: {
|
||||
name: '名称',
|
||||
id: 'ID',
|
||||
platform: '平台',
|
||||
rateMultiplier: '费率倍数',
|
||||
rpmOverride: 'RPM 覆盖',
|
||||
|
||||
@@ -128,6 +128,12 @@
|
||||
}}</span>
|
||||
</template>
|
||||
|
||||
<template #cell-id="{ value }">
|
||||
<span class="font-mono text-xs text-gray-500 dark:text-gray-400"
|
||||
>#{{ value }}</span
|
||||
>
|
||||
</template>
|
||||
|
||||
<template #cell-platform="{ value }">
|
||||
<span
|
||||
:class="[
|
||||
@@ -3612,10 +3618,19 @@ const appStore = useAppStore();
|
||||
const onboardingStore = useOnboardingStore();
|
||||
|
||||
const ALWAYS_VISIBLE_COLUMNS = new Set(["name", "actions"]);
|
||||
// Default hidden columns (hidden on first load / after schema bumps).
|
||||
const DEFAULT_HIDDEN_COLUMNS = ["id"];
|
||||
const HIDDEN_COLUMNS_KEY = "group-hidden-columns";
|
||||
// Bump when adding new default-hidden columns so existing admins pick them up once.
|
||||
const COLUMN_SETTINGS_VERSION_KEY = "group-column-settings-version";
|
||||
const COLUMN_SETTINGS_VERSION = 2;
|
||||
const VERSION_NEW_HIDDEN_COLUMNS: Record<number, string[]> = {
|
||||
2: ["id"],
|
||||
};
|
||||
|
||||
const allColumns = computed<Column[]>(() => [
|
||||
{ key: "name", label: t("admin.groups.columns.name"), sortable: true },
|
||||
{ key: "id", label: t("admin.groups.columns.id"), sortable: true },
|
||||
{
|
||||
key: "platform",
|
||||
label: t("admin.groups.columns.platform"),
|
||||
@@ -3665,16 +3680,51 @@ const loadSavedColumns = () => {
|
||||
hiddenColumns.clear();
|
||||
try {
|
||||
const saved = localStorage.getItem(HIDDEN_COLUMNS_KEY);
|
||||
if (!saved) return;
|
||||
const parsed = JSON.parse(saved);
|
||||
if (!Array.isArray(parsed)) return;
|
||||
|
||||
const validKeys = getValidHiddenColumnKeys();
|
||||
parsed
|
||||
.filter((key): key is string => typeof key === "string" && validKeys.has(key))
|
||||
.forEach((key) => hiddenColumns.add(key));
|
||||
|
||||
if (saved) {
|
||||
const parsed = JSON.parse(saved);
|
||||
if (Array.isArray(parsed)) {
|
||||
parsed
|
||||
.filter(
|
||||
(key): key is string =>
|
||||
typeof key === "string" && validKeys.has(key),
|
||||
)
|
||||
.forEach((key) => hiddenColumns.add(key));
|
||||
}
|
||||
|
||||
// Existing admins: auto-hide columns newly added as default-hidden.
|
||||
const storedVersion = Number(
|
||||
localStorage.getItem(COLUMN_SETTINGS_VERSION_KEY) ?? "1",
|
||||
);
|
||||
if (storedVersion < COLUMN_SETTINGS_VERSION) {
|
||||
let mutated = false;
|
||||
for (let v = storedVersion + 1; v <= COLUMN_SETTINGS_VERSION; v++) {
|
||||
for (const key of VERSION_NEW_HIDDEN_COLUMNS[v] ?? []) {
|
||||
if (validKeys.has(key) && !hiddenColumns.has(key)) {
|
||||
hiddenColumns.add(key);
|
||||
mutated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mutated) {
|
||||
saveColumnsToStorage();
|
||||
} else {
|
||||
localStorage.setItem(
|
||||
COLUMN_SETTINGS_VERSION_KEY,
|
||||
String(COLUMN_SETTINGS_VERSION),
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DEFAULT_HIDDEN_COLUMNS.forEach((key) => {
|
||||
if (validKeys.has(key)) hiddenColumns.add(key);
|
||||
});
|
||||
saveColumnsToStorage();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to load group column settings:", error);
|
||||
DEFAULT_HIDDEN_COLUMNS.forEach((key) => hiddenColumns.add(key));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3683,6 +3733,10 @@ const saveColumnsToStorage = () => {
|
||||
const validKeys = getValidHiddenColumnKeys();
|
||||
const keys = [...hiddenColumns].filter((key) => validKeys.has(key));
|
||||
localStorage.setItem(HIDDEN_COLUMNS_KEY, JSON.stringify(keys));
|
||||
localStorage.setItem(
|
||||
COLUMN_SETTINGS_VERSION_KEY,
|
||||
String(COLUMN_SETTINGS_VERSION),
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("Failed to save group column settings:", error);
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ const {
|
||||
const messages: Record<string, string> = {
|
||||
'admin.groups.columnSettings': 'Column Settings',
|
||||
'admin.groups.columns.name': 'Name',
|
||||
'admin.groups.columns.id': 'ID',
|
||||
'admin.groups.columns.platform': 'Platform',
|
||||
'admin.groups.columns.billingType': 'Billing Type',
|
||||
'admin.groups.columns.rateMultiplier': 'Rate Multiplier',
|
||||
@@ -251,7 +252,7 @@ describe('admin GroupsView column settings', () => {
|
||||
localStorage.clear()
|
||||
})
|
||||
|
||||
it('renders all group columns by default in the current order', async () => {
|
||||
it('hides the id column by default while keeping other group columns visible', async () => {
|
||||
const wrapper = await mountView()
|
||||
|
||||
expect(columnKeys(wrapper)).toEqual([
|
||||
@@ -266,6 +267,8 @@ describe('admin GroupsView column settings', () => {
|
||||
'status',
|
||||
'actions',
|
||||
])
|
||||
expect(localStorage.getItem('group-hidden-columns')).toBe(JSON.stringify(['id']))
|
||||
expect(localStorage.getItem('group-column-settings-version')).toBe('2')
|
||||
})
|
||||
|
||||
it('applies saved hidden columns on mount and ignores unknown keys', async () => {
|
||||
@@ -273,6 +276,26 @@ describe('admin GroupsView column settings', () => {
|
||||
'group-hidden-columns',
|
||||
JSON.stringify(['usage', 'capacity', 'removed_column', 'name', 'actions']),
|
||||
)
|
||||
localStorage.setItem('group-column-settings-version', '2')
|
||||
|
||||
const wrapper = await mountView()
|
||||
|
||||
expect(columnKeys(wrapper)).toEqual([
|
||||
'name',
|
||||
'id',
|
||||
'platform',
|
||||
'billing_type',
|
||||
'rate_multiplier',
|
||||
'is_exclusive',
|
||||
'account_count',
|
||||
'status',
|
||||
'actions',
|
||||
])
|
||||
})
|
||||
|
||||
it('auto-hides id for existing saved column prefs after version bump', async () => {
|
||||
localStorage.setItem('group-hidden-columns', JSON.stringify(['usage']))
|
||||
// No version key → treated as version 1, migrate to 2 and hide id.
|
||||
|
||||
const wrapper = await mountView()
|
||||
|
||||
@@ -283,9 +306,14 @@ describe('admin GroupsView column settings', () => {
|
||||
'rate_multiplier',
|
||||
'is_exclusive',
|
||||
'account_count',
|
||||
'capacity',
|
||||
'status',
|
||||
'actions',
|
||||
])
|
||||
expect(JSON.parse(localStorage.getItem('group-hidden-columns')!)).toEqual(
|
||||
expect.arrayContaining(['usage', 'id']),
|
||||
)
|
||||
expect(localStorage.getItem('group-column-settings-version')).toBe('2')
|
||||
})
|
||||
|
||||
it('toggles a column and persists hidden column keys', async () => {
|
||||
@@ -305,7 +333,31 @@ describe('admin GroupsView column settings', () => {
|
||||
'status',
|
||||
'actions',
|
||||
])
|
||||
expect(localStorage.getItem('group-hidden-columns')).toBe(JSON.stringify(['usage']))
|
||||
expect(JSON.parse(localStorage.getItem('group-hidden-columns')!)).toEqual(
|
||||
expect.arrayContaining(['id', 'usage']),
|
||||
)
|
||||
})
|
||||
|
||||
it('can show the id column from column settings', async () => {
|
||||
const wrapper = await mountView()
|
||||
|
||||
await openColumnSettings(wrapper)
|
||||
await clickColumnToggle(wrapper, 'ID')
|
||||
|
||||
expect(columnKeys(wrapper)).toEqual([
|
||||
'name',
|
||||
'id',
|
||||
'platform',
|
||||
'billing_type',
|
||||
'rate_multiplier',
|
||||
'is_exclusive',
|
||||
'account_count',
|
||||
'capacity',
|
||||
'usage',
|
||||
'status',
|
||||
'actions',
|
||||
])
|
||||
expect(localStorage.getItem('group-hidden-columns')).toBe(JSON.stringify([]))
|
||||
})
|
||||
|
||||
it('skips usage and capacity fetches until consuming columns are shown', async () => {
|
||||
|
||||
Reference in New Issue
Block a user