feat(assets): add dimension analysis and authorized user previews
ci/woodpecker/push/woodpecker Pipeline was successful

Refactor asset drilldowns with combined dimension filters, parent summaries and progressive loading. Add the hidden /who read-only permission preview with scoped authorization, identity mapping and audit logging. Refine inventory counts and AI问数 presentation.
This commit is contained in:
shishengliang
2026-09-28 12:29:51 +08:00
parent 6de77adb47
commit f1b3f8d3da
69 changed files with 3871 additions and 536 deletions
+10 -3
View File
@@ -5,7 +5,14 @@ import type { AuthUser } from '../../auth/types.js';
import { canManageFeedback } from '../../auth/types.js';
import { uploadFeedbackImage } from './oss.js';
const app = new Hono();
const app = new Hono<{ Variables: { user: AuthUser } }>();
app.onError((error, c) => {
if (c.get('user')?.preview && ['ER_NO_SUCH_TABLE', 'ER_BAD_FIELD_ERROR'].includes((error as { code?: string }).code || ''))
return c.json({ message: '反馈存储尚未就绪,权限预览不会初始化或更新表结构,请联系管理员。', code: 'PREVIEW_FEEDBACK_STORAGE_UNAVAILABLE' }, 503);
console.error(error);
return c.text('Internal Server Error', 500);
});
const MAX_IMAGE_SIZE = 5 * 1024 * 1024; // 5 MB
const ALLOWED_MIME = new Set(['image/png', 'image/jpeg', 'image/webp', 'image/gif']);
@@ -116,7 +123,7 @@ app.post('/upload', async (c) => {
// GET /api/feedback/mine — 当前用户的反馈历史
app.get('/mine', async (c) => {
await ensureTable();
if (!c.get('user')?.preview) await ensureTable();
const user = (c as { get?: (k: string) => unknown }).get?.('user') as AuthUser | undefined;
if (!user?.userId) return c.json({ items: [] });
const [rows] = await pool.query<RowDataPacket[]>(
@@ -133,7 +140,7 @@ app.get('/mine', async (c) => {
// GET /api/feedback/list — 管理列表(仅 BI-ADMIN-FEEDBACK / 全量权限)
app.get('/list', async (c) => {
await ensureTable();
if (!c.get('user')?.preview) await ensureTable();
const user = (c as { get?: (k: string) => unknown }).get?.('user') as AuthUser | undefined;
if (!canManageFeedback(user?.roles)) {
return c.json({ ok: false, message: '无权限' }, 403);