| | |
| | | private String name; |
| | | @TableField("MENU_ID") |
| | | private String menuId; // 关联的菜单ID |
| | | @TableField("MENU_PARENT_ID") |
| | | private String menuParentId; // 关联的菜单父ID |
| | | @TableField("STATUS") |
| | | private String status; |
| | | @TableField(value = "DEL_FLAG") |
| | |
| | | private String formJson; // 表单设计 JSON 字符串 |
| | | private String showColumn; // 字段显示配置 |
| | | private String actionsFunc; // 启用的操作项(增删改查) |
| | | private String menuParentId; |
| | | } |
| | |
| | | import org.ruoyi.system.domain.vo.SysMenuVo; |
| | | |
| | | import java.io.Serializable; |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * @author kanglujie |
| | |
| | | public class PageDesignerVo implements Serializable { |
| | | private Long id; // 修改时传入 |
| | | private String name; // 页面名称 |
| | | private String menuId; // 关联菜单 ID |
| | | private String parentId; // 关联菜单 ID |
| | | private String status; // 启用状态 |
| | | private String remark; // 备注 |
| | | private String formJson; // 表单设计 JSON 字符串 |
| | | private String showColumn; // 字段显示配置 |
| | | private String actionsFunc; // 启用的操作项(增删改查) |
| | | private SysMenuVo menu; // 创建人信息 |
| | | private SysMenuVo parent; // 创建人信息 |
| | | private String menuParentId; // 菜单父ID |
| | | private Date createTime; // 创建时间 |
| | | } |
| | |
| | | package org.ruoyi.pageDesigner.service.impl; |
| | | |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.amazonaws.util.json.Jackson; |
| | | import com.baomidou.mybatisplus.core.conditions.Wrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | |
| | | import org.ruoyi.pageDesigner.domain.PageDesignerVo; |
| | | import org.ruoyi.pageDesigner.mapper.PageDesignerMapper; |
| | | import org.ruoyi.pageDesigner.service.PageDesignerService; |
| | | import org.ruoyi.system.domain.SysMenu; |
| | | import org.ruoyi.system.mapper.SysMenuMapper; |
| | | import org.ruoyi.system.mapper.SysUserMapper; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.List; |
| | |
| | | public class PageDesignerServiceImpl extends ServiceImpl<PageDesignerMapper, PageDesigner> |
| | | implements PageDesignerService { |
| | | |
| | | private final ObjectMapper objectMapper; |
| | | private final SysMenuMapper menuMapper; |
| | | |
| | | @Override |
| | | public void add(PageDesignerDTO dto) { |
| | | SysMenu menu = new SysMenu(); |
| | | menu.setMenuName(dto.getName()); |
| | | menu.setParentId(Long.valueOf(dto.getMenuParentId())); |
| | | menu.setOrderNum(100); |
| | | menu.setPath("page"); |
| | | menu.setComponent("tool/template/index"); |
| | | menu.setIsFrame("1"); |
| | | menu.setIsCache("0"); |
| | | menu.setMenuType("C"); // C:目录, M:菜单, F:按钮 |
| | | menu.setVisible("0"); |
| | | menu.setStatus(dto.getStatus()); |
| | | menuMapper.insert(menu); |
| | | PageDesigner entity = convertToEntity(dto); |
| | | entity.setMenuId(menu.getMenuId().toString()); |
| | | this.save(entity); |
| | | JSONObject json = new JSONObject(); |
| | | json.put("pageId", entity.getId().toString()); |
| | | String jsonString = json.toJSONString(); |
| | | menu.setQueryParam(jsonString); |
| | | menuMapper.updateById(menu); |
| | | } |
| | | |
| | | @Override |
| | | public void updatePage(PageDesignerDTO dto) { |
| | | PageDesigner entity = convertToEntity(dto); |
| | | this.updateById(entity); |
| | | PageDesigner byId = this.getById(entity.getId()); |
| | | SysMenu menu = new SysMenu(); |
| | | menu.setMenuId(Long.valueOf(byId.getMenuId())); |
| | | menu.setStatus(entity.getStatus()); |
| | | menu.setParentId(Long.valueOf(entity.getMenuParentId())); |
| | | menuMapper.updateById(menu); |
| | | } |
| | | |
| | | @Override |
| | |
| | | |
| | | @Override |
| | | public void deleteByIds(List<Long> ids) { |
| | | this.removeByIds(ids); |
| | | List<PageDesigner> designers = this.listByIds(ids); |
| | | for (PageDesigner designer : designers) { |
| | | Long id = designer.getId(); |
| | | this.removeById(id); |
| | | |
| | | Long menuId = Long.valueOf(designer.getMenuId()); |
| | | if (menuId != null) { |
| | | menuMapper.deleteById(menuId); |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | private PageDesigner convertToEntity(PageDesignerDTO dto) { |
| | |
| | | entity.setFormJson(dto.getFormJson()); |
| | | entity.setShowColumn(dto.getShowColumn()); |
| | | entity.setActionsFunc(dto.getActionsFunc()); |
| | | entity.setMenuParentId(dto.getMenuParentId()); |
| | | return entity; |
| | | } |
| | | } |
| | |
| | | package org.ruoyi.pageDesigner.service.impl; |
| | | |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import com.baomidou.mybatisplus.core.conditions.Wrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.fasterxml.jackson.databind.ObjectMapper; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.ruoyi.common.core.constant.UserConstants; |
| | | import org.ruoyi.core.page.PageQuery; |
| | | import org.ruoyi.core.page.TableDataInfo; |
| | | import org.ruoyi.pageDesigner.domain.*; |
| | |
| | | private Wrapper<PageDesignerTemplate> buildQueryWrapper(PageDesignerTemplateDTO dto) { |
| | | //Map<String, Object> params = pageDesignerDTO.getParams(); |
| | | QueryWrapper<PageDesignerTemplate> wrapper = Wrappers.query(); |
| | | //wrapper.eq("del_flag", UserConstants.USER_NORMAL) |
| | | // .eq(ObjectUtil.isNotNull(pageDesignerDTO.getId()), "id", pageDesignerDTO.getId()) |
| | | wrapper.eq("del_flag", UserConstants.USER_NORMAL) |
| | | .eq(ObjectUtil.isNotNull(dto.getPageId()), "page_id", dto.getPageId()) |
| | | // .like(StringUtils.isNotBlank(pageDesignerDTO.getName()), "name", pageDesignerDTO.getName()) |
| | | // .eq(StringUtils.isNotBlank(pageDesignerDTO.getStatus()), "status", pageDesignerDTO.getStatus()) |
| | | // .between(params.get("beginTime") != null && params.get("endTime") != null, |
| | | // "create_time", params.get("beginTime"), params.get("endTime")) |
| | | //; |
| | | ; |
| | | return wrapper; |
| | | } |
| | | @Override |
| | |
| | | <id property="id" column="id"/> |
| | | <result property="name" column="name"/> |
| | | <result property="status" column="status"/> |
| | | <result property="createTime" column="create_time"/> |
| | | <result property="menuParentId" column="menu_parent_id"/> |
| | | <result property="remark" column="remark"/> |
| | | </resultMap> |
| | | |
| | | |
| | |
| | | select |
| | | id, |
| | | name, |
| | | status |
| | | status, |
| | | create_time, |
| | | menu_parent_id, |
| | | remark |
| | | from page_designer |
| | | ${ew.getCustomSqlSegment} |
| | | </select> |
| | |
| | | field: 'status', |
| | | slots: { |
| | | default: ({ row }) => { |
| | | return row.status === '1' ? '正常' : '停用'; |
| | | return row.status === '0' ? '正常' : '停用'; |
| | | }, |
| | | }, |
| | | }, |
| | |
| | | }, |
| | | { |
| | | component: 'TreeSelect', |
| | | fieldName: 'menuId', |
| | | fieldName: 'menuParentId', |
| | | label: '上级目录', |
| | | componentProps: { |
| | | allowClear: true, |
| | |
| | | label: '状态', |
| | | componentProps: { |
| | | options: [ |
| | | { label: '正常', value: '1' }, |
| | | { label: '停用', value: '0' }, |
| | | { label: '正常', value: '0' }, |
| | | { label: '停用', value: '1' }, |
| | | ], |
| | | }, |
| | | rules: 'selectRequired', |
| | |
| | | const modalVisible = ref(false); |
| | | const modalLoading = ref(false); |
| | | const currentEditId = ref<string | number>(''); // 当前编辑的ID |
| | | const fullMenuTree = ref([]); |
| | | |
| | | // 打开弹窗 |
| | | const open = async (params: ModalProps = { update: false }) => { |
| | |
| | | await setupPageSelect(); |
| | | |
| | | if (params.id) { |
| | | await formApi.setFieldValue('menuId', params.id); |
| | | await formApi.setFieldValue('menuParentId', params.id); |
| | | if (params.update) { |
| | | // 获取详情数据 |
| | | const record = await pageInfo(params.id); |
| | | console.log('编辑数据:', record); |
| | | |
| | | // 设置基础表单数据 |
| | | const menuParentId = String(record.menuParentId || record.parentId || ''); |
| | | await formApi.setValues({ |
| | | name: record.name, |
| | | menuId: record.menuId || record.parentId || params.id, // 优先使用menuId,其次parentId |
| | | menuParentId: menuParentId, // 用 menuParentId 字段 |
| | | status: record.status, |
| | | remark: record.remark, |
| | | actionsFunc: record.actionsFunc ? JSON.parse(record.actionsFunc) : ['add', 'edit', 'delete', 'query'] |
| | |
| | | // 恢复选中的字段 |
| | | if (record.showColumn) { |
| | | selectedFields.value = JSON.parse(record.showColumn); |
| | | console.log('恢复选中字段:', selectedFields.value); |
| | | } |
| | | } catch (e) { |
| | | console.error('加载表单设计数据失败:', e); |
| | |
| | | filteredList.forEach(item => { item.menuName = $t(item.menuName); }); |
| | | // 转为树结构 |
| | | const menuTree = listToTree(filteredList, { id: 'menuId', pid: 'parentId' }); |
| | | // 加根节点 |
| | | const fullMenuTree = [ |
| | | // 递归映射 menuId -> menuParentId |
| | | function mapMenuIdToParentId(list) { |
| | | return list.map(item => { |
| | | const newItem = { ...item, menuParentId: item.menuId }; |
| | | if (item.children) { |
| | | newItem.children = mapMenuIdToParentId(item.children); |
| | | } |
| | | return newItem; |
| | | }); |
| | | } |
| | | fullMenuTree.value = [ |
| | | { |
| | | menuId: 0, |
| | | menuParentId: 0, |
| | | menuName: $t('menu.root'), |
| | | children: menuTree, |
| | | children: mapMenuIdToParentId(menuTree), |
| | | }, |
| | | ]; |
| | | // 生成全路径名 |
| | | addFullName(fullMenuTree, 'menuName', ' / '); |
| | | addFullName(fullMenuTree.value, 'menuName', ' / '); |
| | | |
| | | formApi.updateSchema([ |
| | | { |
| | | componentProps: { |
| | | fieldNames: { |
| | | label: 'menuName', |
| | | value: 'menuId', |
| | | value: 'menuId', // 用 menuId |
| | | children: 'children' |
| | | }, |
| | | getPopupContainer, |
| | | listHeight: 300, |
| | | showSearch: true, |
| | | treeData: fullMenuTree, |
| | | treeData: fullMenuTree.value, |
| | | treeDefaultExpandAll: false, |
| | | treeDefaultExpandedKeys: [0], |
| | | treeLine: { showLeafIcon: false }, |
| | | treeNodeFilterProp: 'menuName', |
| | | treeNodeLabelProp: 'fullName', |
| | | }, |
| | | fieldName: 'menuId', |
| | | fieldName: 'menuParentId', // 用 menuParentId |
| | | }, |
| | | ]); |
| | | } |
| | |
| | | const syncAllFields = () => { |
| | | // 获取表单组件的规则描述 |
| | | const formDesc = designer.value?.getFormDescription?.(); |
| | | console.log('表单组件描述:', formDesc); |
| | | |
| | | if (!formDesc || !Array.isArray(formDesc)) { |
| | | message.warning('暂无设计数据'); |
| | |
| | | field: item.field |
| | | })); |
| | | |
| | | console.log('提取的字段:', allFields); |
| | | |
| | | if (allFields.length === 0) { |
| | | message.warning('未找到可用字段'); |
| | |
| | | |
| | | // 处理设计器变化 |
| | | const handleDesignerChange = () => { |
| | | console.log('设计器内容变化'); |
| | | nextTick(() => { |
| | | updateFieldOptions(); |
| | | }); |
| | |
| | | |
| | | // 当设计器内容变化时更新字段选项 |
| | | const updateFieldOptions = () => { |
| | | console.log('updateFieldOptions'); |
| | | console.log('designer.value', designer.value); |
| | | |
| | | // 获取表单组件的规则描述 |
| | | const formDesc = designer.value?.getFormDescription?.(); |
| | | if (!formDesc || !Array.isArray(formDesc)) return; |
| | |
| | | label: item.title, |
| | | value: item.field |
| | | })); |
| | | |
| | | console.log('更新后的字段选项:', fieldOptions.value); |
| | | }; |
| | | |
| | | // 监听设计器内容变化 |
| | |
| | | const safeDetail = { |
| | | id: detail.id, |
| | | name: detail.name, |
| | | menuId: detail.menuId, |
| | | menuParentId: detail.menuId, |
| | | status: detail.status, |
| | | remark: detail.remark, |
| | | formJson: detail.formJson, |
| | |
| | | ...formValues, |
| | | }; |
| | | if (pageId.value) { |
| | | queryParams.pageDesignId = pageId.value; |
| | | queryParams.pageId = pageId.value; |
| | | } |
| | | const resp = await templateList(queryParams); |
| | | // 处理每条 row 的 formData |
| | |
| | | // 如果有 pageId,传递给新增 |
| | | const params: any = { update: false }; |
| | | if (pageId.value) { |
| | | params.pageDesignId = pageId.value; |
| | | params.pageId = pageId.value; |
| | | } |
| | | // 动态传递formJson,先JSON.parse,保证是纯对象 |
| | | if (pageDesignDetail.value && pageDesignDetail.value.formJson) { |
| | |
| | | const params: any = { |
| | | id: record.id, |
| | | update: true, |
| | | pageDesignId: pageId.value, // 传递页面设计ID |
| | | pageId: pageId.value, // 传递页面设计ID |
| | | record: record // 传递完整的记录数据 |
| | | }; |
| | | |
| | |
| | | try { |
| | | const formJson = JSON.parse(pageDesignDetail.value.formJson); |
| | | params.formJson = formJson; |
| | | console.log('编辑时传递数据:', { record, formJson, pageDesignId: pageId.value }); |
| | | console.log('编辑时传递数据:', { record, formJson, pageId: pageId.value }); |
| | | } catch (error) { |
| | | console.error('解析 formJson 失败:', error); |
| | | params.formJson = undefined; |
| | |
| | | interface ModalProps { |
| | | id?: number | string; |
| | | update: boolean; |
| | | pageDesignId?: string | number; |
| | | pageId?: string | number; |
| | | formJson?: any; |
| | | } |
| | | |
| | |
| | | modalLoading.value = true; |
| | | isUpdate.value = params.update; |
| | | currentEditId.value = params.id || ''; |
| | | currentPageId.value = params.pageId || params.pageDesignId || ''; |
| | | currentPageId.value = params.pageId || ''; |
| | | |
| | | // 设置动态表单字段,始终移除所有submit按钮 |
| | | if (params.formJson) { |