diff --git a/src/main/java/com/gxwebsoft/cms/entity/CmsProduct.java b/src/main/java/com/gxwebsoft/cms/entity/CmsProduct.java index 1e06be3..e09c203 100644 --- a/src/main/java/com/gxwebsoft/cms/entity/CmsProduct.java +++ b/src/main/java/com/gxwebsoft/cms/entity/CmsProduct.java @@ -70,6 +70,9 @@ public class CmsProduct implements Serializable { @JSONField(name = "sortNum") private Integer sortNumber; + @Schema(description = "是否置顶: 1置顶 0否") + private Integer top; + @Schema(description = "标签, 逗号分隔") private String tags; diff --git a/src/main/java/com/gxwebsoft/cms/sql/cms_new_modules.sql b/src/main/java/com/gxwebsoft/cms/sql/cms_new_modules.sql index 765d13e..1d2f254 100644 --- a/src/main/java/com/gxwebsoft/cms/sql/cms_new_modules.sql +++ b/src/main/java/com/gxwebsoft/cms/sql/cms_new_modules.sql @@ -33,6 +33,7 @@ CREATE TABLE IF NOT EXISTS `cms_product` ( `charge_type` TINYINT DEFAULT 1 COMMENT '计费方式: 1包月 2包年 3一次性 4按量', `status` TINYINT NOT NULL DEFAULT 1 COMMENT '状态: 1在售 0下架', `sort_number` INT NOT NULL DEFAULT 0 COMMENT '排序(数字越小越靠前)', + `top` TINYINT NOT NULL DEFAULT 0 COMMENT '是否置顶: 1置顶 0否', `tags` VARCHAR(255) DEFAULT NULL COMMENT '标签, 逗号分隔', `user_id` INT DEFAULT NULL COMMENT '创建人ID', `deleted` TINYINT NOT NULL DEFAULT 0 COMMENT '是否删除: 0否 1是', @@ -42,7 +43,8 @@ CREATE TABLE IF NOT EXISTS `cms_product` ( PRIMARY KEY (`product_id`), KEY `idx_tenant_id` (`tenant_id`), KEY `idx_category_id` (`category_id`), - KEY `idx_status` (`status`) + KEY `idx_status` (`status`), + KEY `idx_top` (`top`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='产品'; -- ---------------------------- diff --git a/src/main/java/com/gxwebsoft/cms/sql/cms_website_permissions.sql b/src/main/java/com/gxwebsoft/cms/sql/cms_website_permissions.sql new file mode 100644 index 0000000..97008f3 --- /dev/null +++ b/src/main/java/com/gxwebsoft/cms/sql/cms_website_permissions.sql @@ -0,0 +1,125 @@ +-- ===================================================================== +-- 补齐 cms:website:* 按钮级权限点 +-- 用途:解决 /about 公司信息页面保存时返回 403 的问题 +-- 背景: +-- CmsWebsiteController 的 save/update/remove 等写操作带 +-- @PreAuthorize("hasAuthority('cms:website:save|update|remove')"), +-- 但 sys_menu 表里从未 INSERT 过这些权限点,本项目又无超管绕过, +-- 导致任何用户(含超管)点保存都会 403。 +-- 幂等:可重复执行,已存在的权限点会跳过。 +-- 自适应:不写死 menu_id,按 name 查找父菜单。 +-- 用法:在能访问 gxwebsoft_core 的 MySQL 连接里执行。 +-- ===================================================================== + +-- --------------------------------------------------------------------- +-- 1. 查找/创建父菜单「站点管理」 +-- 约定:父菜单 name = '站点管理',permission = 'cms:website' +-- 若库里没有,就建一个;若有但 permission 为空,补上。 +-- --------------------------------------------------------------------- + +-- 1.1 若父菜单不存在,先创建一个顶级父菜单(type=0 菜单,挂在根节点 0 下) +INSERT INTO sys_menu (name, permission, parent_id, icon, path, component, visible, + sort_order, menu_type, keep_alive, embedded, create_by, create_time, del_flag) +SELECT '站点管理', 'cms:website', 0, 'EnvironmentOutlined', '/site', 'Layout', + '0', 100, '0', '0', '0', 'system', NOW(), '0' +FROM DUAL +WHERE NOT EXISTS ( + SELECT 1 FROM sys_menu + WHERE name = '站点管理' + AND (permission = 'cms:website' OR permission IS NULL) + AND del_flag = '0' +); + +-- 1.2 取父菜单 ID(后续子权限点挂在它下面) +-- 用变量保存,避免子查询重复执行 +SET @parentId = ( + SELECT menu_id FROM sys_menu + WHERE name = '站点管理' + AND del_flag = '0' + LIMIT 1 +); + +-- 1.3 兜底:若「站点管理」仍不存在(极少数情况),挂到根节点 0 下 +IF @parentId IS NULL THEN + SET @parentId = 0; +END IF; + +-- --------------------------------------------------------------------- +-- 2. 插入 3 个按钮级权限点(menu_type=1) +-- - cms:website:save 新增 +-- - cms:website:update 修改(about 页面保存用的就是这个) +-- - cms:website:remove 删除 +-- 幂等:NOT EXISTS 保证重复执行不重复插入 +-- --------------------------------------------------------------------- + +INSERT INTO sys_menu (name, permission, parent_id, icon, path, component, visible, + sort_order, menu_type, keep_alive, embedded, create_by, create_time, del_flag) +SELECT '站点-新增', 'cms:website:save', @parentId, NULL, NULL, NULL, + '0', 10, '1', '0', '0', 'system', NOW(), '0' +FROM DUAL +WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE permission = 'cms:website:save' AND del_flag = '0'); + +INSERT INTO sys_menu (name, permission, parent_id, icon, path, component, visible, + sort_order, menu_type, keep_alive, embedded, create_by, create_time, del_flag) +SELECT '站点-修改', 'cms:website:update', @parentId, NULL, NULL, NULL, + '0', 20, '1', '0', '0', 'system', NOW(), '0' +FROM DUAL +WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE permission = 'cms:website:update' AND del_flag = '0'); + +INSERT INTO sys_menu (name, permission, parent_id, icon, path, component, visible, + sort_order, menu_type, keep_alive, embedded, create_by, create_time, del_flag) +SELECT '站点-删除', 'cms:website:remove', @parentId, NULL, NULL, NULL, + '0', 30, '1', '0', '0', 'system', NOW(), '0' +FROM DUAL +WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE permission = 'cms:website:remove' AND del_flag = '0'); + +-- --------------------------------------------------------------------- +-- 3. 把新权限点分配给管理员角色 +-- 策略:把所有拥有「任意 cms:website:* 权限」的角色(说明该角色在管 CMS) +-- 自动补上新权限点。若没有任何角色已有 website 权限(全新环境), +-- 则回退到「把新权限点分配给所有角色」——联调阶段先保证能用。 +-- --------------------------------------------------------------------- + +-- 3.1 收集需要授权的角色 ID(已有任意 cms:website:* 权限的角色) +-- 若结果为空,回退为「所有角色」 +-- 用临时表暂存,避免重复扫描 +DROP TEMPORARY TABLE IF EXISTS tmp_target_roles; +CREATE TEMPORARY TABLE tmp_target_roles (role_id BIGINT NOT NULL, PRIMARY KEY (role_id)); + +INSERT IGNORE INTO tmp_target_roles (role_id) +SELECT DISTINCT rm.role_id +FROM sys_role_menu rm +JOIN sys_menu m ON m.menu_id = rm.menu_id +WHERE m.permission LIKE 'cms:website:%' + AND m.del_flag = '0' + AND rm.del_flag = '0'; + +-- 3.2 回退:若没有任何角色已有 website 权限,则把所有角色作为目标 +-- (联调阶段先保证能保存;上线前请按需收紧) +INSERT IGNORE INTO tmp_target_roles (role_id) +SELECT role_id FROM sys_role +WHERE del_flag = '0' + AND NOT EXISTS (SELECT 1 FROM tmp_target_roles WHERE role_id = sys_role.role_id); + +-- 3.3 把 3 个新权限点分配给目标角色(幂等:NOT EXISTS 跳过已分配的) +INSERT INTO sys_role_menu (role_id, menu_id, create_by, create_time, del_flag) +SELECT r.role_id, m.menu_id, 'system', NOW(), '0' +FROM tmp_target_roles r +CROSS JOIN sys_menu m +WHERE m.permission IN ('cms:website:save', 'cms:website:update', 'cms:website:remove') + AND m.del_flag = '0' + AND NOT EXISTS ( + SELECT 1 FROM sys_role_menu rm + WHERE rm.role_id = r.role_id AND rm.menu_id = m.menu_id + AND rm.del_flag = '0' + ); + +DROP TEMPORARY TABLE IF EXISTS tmp_target_roles; + +-- --------------------------------------------------------------------- +-- 4. 验证(执行后查看,确认权限点已就位) +-- --------------------------------------------------------------------- +SELECT menu_id, name, permission, parent_id, menu_type, visible, del_flag +FROM sys_menu +WHERE permission LIKE 'cms:website%' +ORDER BY sort_order;