Files
FruitServer/sql/data-phase1.sql
T
Vicky d67d9daf8c feat: 08 数据看板落地(总览 + 转码看板,只读)
为什么:
1) 前面几块把用户、内容、播放、交易、媒资的数据都落库了,运营需要一个地方一次看完,
   否则每个指标都要去查库或翻后台列表。
2) 看板最容易出的问题是"数字看起来对但口径不清",所以每个指标都在代码注释和
   docs/api-phase1.md 里写死口径(时间范围、统计维度),前端 tooltip 直接复用。
3) 取不到数据源的指标(DAU、CDN 流量成本、商店订单金额)一律返回 null 并在 notes 里
   说明缺什么、怎么补 —— 不用 0 冒充,避免运营拿假数字做判断。
4) 站在接入层做只读聚合而不是新建模块:它跨六个域取数,建模块只会把依赖再摊开一层,
   而它只读不写,放在 admin-api 改动面最小。
2026-10-15 13:03:58 +08:00

141 lines
7.9 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- FruitShorts 短剧服务 · 第一阶段增量数据(PostgreSQL 18)
--
-- 只放「代码已经实现、需要权限点才能调通」的数据。
-- 菜单(sys_menu)暂时不加:前端页面还没做,加了会出现指向不存在组件的动态路由,
-- 等 fruitshorts-web 的 App 用户管理页落地后再补菜单与角色菜单绑定。
--
-- 幂等:可重复执行。
-- 先对齐 IDENTITY 序列:历史种子数据用了显式 ID,序列没有前移,
-- 不对齐的话下面的插入会从 1 开始而撞主键。
DO $$
DECLARE
t text;
seq text;
maxid bigint;
BEGIN
FOREACH t IN ARRAY ARRAY['sys_permission','sys_menu','sys_role_permission','sys_role_menu',
'product','app_user','app_user_credential','orders','wallet'] LOOP
seq := pg_get_serial_sequence(t, 'id');
IF seq IS NULL THEN
CONTINUE;
END IF;
EXECUTE format('SELECT COALESCE(MAX(id), 0) FROM %I', t) INTO maxid;
IF maxid > 0 THEN
PERFORM setval(seq, maxid);
END IF;
END LOOP;
END $$;
INSERT INTO sys_permission (code, name, group_name, type, sort) VALUES
('app-user:list', '查看 App 用户', '用户管理', 'BUTTON', 101),
('app-user:update', '处置 App 用户', '用户管理', 'BUTTON', 102)
ON CONFLICT (code) DO NOTHING;
INSERT INTO sys_permission (code, name, group_name, type, sort) VALUES
('download:list', '查看下载授权', '用户管理', 'BUTTON', 103),
('download:revoke', '吊销下载授权', '用户管理', 'BUTTON', 104)
ON CONFLICT (code) DO NOTHING;
INSERT INTO sys_permission (code, name, group_name, type, sort) VALUES
('comment:list', '查看评论', '内容治理', 'BUTTON', 111),
('comment:audit', '审核评论', '内容治理', 'BUTTON', 112),
('report:list', '查看举报', '内容治理', 'BUTTON', 113),
('report:handle', '处理举报', '内容治理', 'BUTTON', 114),
('sensitive-word:list', '查看敏感词', '内容治理', 'BUTTON', 115),
('sensitive-word:update','维护敏感词', '内容治理', 'BUTTON', 116)
ON CONFLICT (code) DO NOTHING;
INSERT INTO sys_permission (code, name, group_name, type, sort) VALUES
('order:list', '查看订单', '订单与权益', 'BUTTON', 121),
('order:update', '补发/退款', '订单与权益', 'BUTTON', 122),
('entitlement:list', '查看权益', '订单与权益', 'BUTTON', 123),
('entitlement:update', '补发/回收权益', '订单与权益', 'BUTTON', 124),
('wallet:update', '人工补币', '订单与权益', 'BUTTON', 125),
('reconcile:run', '手动对账', '订单与权益', 'BUTTON', 126)
ON CONFLICT (code) DO NOTHING;
INSERT INTO sys_permission (code, name, group_name, type, sort) VALUES
('creator:list', '查看创作者', '创作者管理', 'BUTTON', 131),
('creator:audit', '创作者入驻审核','创作者管理', 'BUTTON', 132),
('submission:list', '查看内容提交', '创作者管理', 'BUTTON', 133),
('submission:audit', '内容提交审核', '创作者管理', 'BUTTON', 134),
('price:update', '配置分集价格', '内容管理', 'BUTTON', 135)
ON CONFLICT (code) DO NOTHING;
-- 看板权限:菜单在 3-4 补页面时一起加,避免菜单指向不存在的组件
INSERT INTO sys_permission (code, name, group_name, type, sort) VALUES
('dashboard:view', '查看运营大盘', '数据看板', 'BUTTON', 141)
ON CONFLICT (code) DO NOTHING;
-- 超管默认拥有全部权限点
INSERT INTO sys_role_permission (role_id, permission_id)
SELECT r.id, p.id
FROM sys_role r
CROSS JOIN sys_permission p
WHERE r.code = 'super_admin'
AND p.code IN ('app-user:list', 'app-user:update', 'download:list', 'download:revoke',
'comment:list', 'comment:audit', 'report:list', 'report:handle',
'sensitive-word:list', 'sensitive-word:update',
'order:list', 'order:update', 'entitlement:list', 'entitlement:update',
'wallet:update', 'reconcile:run',
'creator:list', 'creator:audit', 'submission:list', 'submission:audit',
'price:update', 'dashboard:view')
ON CONFLICT DO NOTHING;
-- ---------- 菜单:创作者管理 ----------
-- component 指向 src/views/creator/ 下的页面,前端按这个字符串动态加载。
INSERT INTO sys_menu (id, parent_id, title, route_path, route_name, component, redirect, icon,
permission_code, type, always_show, affix, sort) VALUES
(17, 0, '创作者管理', '/creator', 'CreatorCenter', '#', '/creator/creators', 'ep:user-filled', 'creator:list', 'CATALOG', 1, 0, 5),
(18, 17, '创作者入驻', 'creators', 'creators', 'views/creator/CreatorAuditView', '', '', 'creator:list', 'MENU', 0, 0, 1),
(19, 17, '内容审核', 'submissions', 'submissions', 'views/creator/SubmissionAuditView', '', '', 'submission:list', 'MENU', 0, 0, 2)
ON CONFLICT (id) DO UPDATE SET parent_id = EXCLUDED.parent_id, title = EXCLUDED.title,
route_path = EXCLUDED.route_path, route_name = EXCLUDED.route_name, component = EXCLUDED.component,
redirect = EXCLUDED.redirect, icon = EXCLUDED.icon, permission_code = EXCLUDED.permission_code,
type = EXCLUDED.type, always_show = EXCLUDED.always_show, affix = EXCLUDED.affix, sort = EXCLUDED.sort;
INSERT INTO sys_role_menu (role_id, menu_id)
SELECT r.id, m.id
FROM sys_role r
CROSS JOIN sys_menu m
WHERE r.code = 'super_admin'
AND m.id IN (17, 18, 19)
ON CONFLICT DO NOTHING;
-- 第一阶段新增的白名单数据(当前阶段都是免费内容,先把演示商品占位好)
INSERT INTO product (code, name, type, platform, store_product_id, coin_amount, bonus_coin,
price_amount, currency, region_codes, sort, status)
SELECT 'coin_100', '100 金币', 'COIN_PACK', 'ALL', '', 100, 0, 0.99, 'USD', 'ID', 1, 1
WHERE NOT EXISTS (SELECT 1 FROM product WHERE code = 'coin_100');
INSERT INTO product (code, name, type, platform, store_product_id, coin_amount, bonus_coin,
price_amount, currency, region_codes, sort, status)
SELECT 'coin_550', '550 金币', 'COIN_PACK', 'ALL', '', 500, 50, 4.99, 'USD', 'ID', 2, 1
WHERE NOT EXISTS (SELECT 1 FROM product WHERE code = 'coin_550');
INSERT INTO product (code, name, type, platform, store_product_id, coin_amount, bonus_coin,
price_amount, currency, region_codes, sort, status)
SELECT 'coin_1200', '1200 金币', 'COIN_PACK', 'ALL', '', 1000, 200, 9.99, 'USD', 'ID', 3, 1
WHERE NOT EXISTS (SELECT 1 FROM product WHERE code = 'coin_1200');
-- ---------- 菜单:用户管理 ----------
-- C 端用户与后台管理员是两套账号体系,单独挂一个一级目录,避免和管理员列表混淆。
-- component 指向 src/views/userManagement/AppUsersView.vue,前端按这个字符串动态加载。
INSERT INTO sys_menu (id, parent_id, title, route_path, route_name, component, redirect, icon,
permission_code, type, always_show, affix, sort) VALUES
(15, 0, '用户管理', '/user', 'UserCenter', '#', '/user/app-users', 'ep:user', 'app-user:list', 'CATALOG', 1, 0, 4),
(16, 15, 'App 用户', 'app-users', 'app-users', 'views/userManagement/AppUsersView', '', '', 'app-user:list', 'MENU', 0, 0, 1)
ON CONFLICT (id) DO UPDATE SET parent_id = EXCLUDED.parent_id, title = EXCLUDED.title,
route_path = EXCLUDED.route_path, route_name = EXCLUDED.route_name, component = EXCLUDED.component,
redirect = EXCLUDED.redirect, icon = EXCLUDED.icon, permission_code = EXCLUDED.permission_code,
type = EXCLUDED.type, always_show = EXCLUDED.always_show, affix = EXCLUDED.affix, sort = EXCLUDED.sort;
INSERT INTO sys_role_menu (role_id, menu_id)
SELECT r.id, m.id
FROM sys_role r
CROSS JOIN sys_menu m
WHERE r.code = 'super_admin'
AND m.id IN (15, 16)
ON CONFLICT DO NOTHING;