From 38a626b58763f903f5580d49854a420681925092 Mon Sep 17 00:00:00 2001 From: 康鲁杰 <60095866+KangLujie@users.noreply.github.com> Date: 星期二, 24 六月 2025 18:06:15 +0800 Subject: [PATCH] 创建公共模版 --- ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/domain/PageDesignerVo.java | 1 ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/service/impl/PageDesignerTemplateServiceImpl.java | 87 ++++ ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/domain/PageDesignerDTO.java | 3 ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/mapper/PageDesignerTemplateMapper.java | 20 + ruoyi-ui/apps/web-antd/src/views/tool/template/template-drawer.vue | 224 +++++++++++ ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/controller/PageDesignerTemplateController.java | 70 +++ ruoyi-modules/sc-page-designer/src/main/resources/mapper/PageDesignerMapper.xml | 0 ruoyi-modules/sc-page-designer/src/main/resources/mapper/PageDesignerTemplateMapper.xml | 27 + ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/domain/PageDesignerTemplateVo.java | 19 + ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/domain/PageDesignerTemplate.java | 28 + ruoyi-ui/apps/web-antd/src/api/tool/template/model.d.ts | 14 ruoyi-ui/apps/web-antd/src/api/tool/template/index.ts | 45 ++ ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/service/impl/PageDesignerServiceImpl.java | 16 ruoyi-ui/apps/web-antd/src/views/tool/template/data.tsx | 86 ++++ ruoyi-ui/apps/web-antd/src/views/tool/template/index.vue | 404 +++++++++++++++++++++ ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/domain/PageDesignerTemplateDTO.java | 22 + ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/service/PageDesignerTemplateService.java | 27 + 17 files changed, 1,081 insertions(+), 12 deletions(-) diff --git a/ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/controller/PageDesignerTemplateController.java b/ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/controller/PageDesignerTemplateController.java new file mode 100644 index 0000000..5af3c15 --- /dev/null +++ b/ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/controller/PageDesignerTemplateController.java @@ -0,0 +1,70 @@ +package org.ruoyi.pageDesigner.controller; + +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.ruoyi.common.core.domain.R; +import org.ruoyi.common.web.core.BaseController; +import org.ruoyi.core.page.PageQuery; +import org.ruoyi.core.page.TableDataInfo; +import org.ruoyi.pageDesigner.domain.*; +import org.ruoyi.pageDesigner.service.PageDesignerTemplateService; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @author kanglujie + * @date 2025-06-23 14:41:24 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/page-designer-template") +public class PageDesignerTemplateController extends BaseController { + + private final PageDesignerTemplateService service; + + /** + * 鑾峰彇椤甸潰璁捐鍒楄〃 + */ + @GetMapping("/list") + public TableDataInfo<PageDesignerTemplateVo> list(PageDesignerTemplateDTO dto, PageQuery pageQuery) { + return service.selectPagelistAll(dto, pageQuery); + } + + /** + * 鑾峰彇椤甸潰璁捐璇︽儏 + */ + @GetMapping("/{id}") + public R<PageDesignerTemplate> getInfo(@PathVariable Long id) { + return R.ok(service.getDetail(id)); + } + + /** + * 鏂板椤甸潰璁捐 + */ + @PostMapping + public R<Void> add(@Valid @RequestBody PageDesignerTemplateDTO dto) { + service.add(dto); + return R.ok("鏂板鎴愬姛"); + } + + /** + * 淇敼椤甸潰璁捐 + */ + @PutMapping + public R<Void> update(@Valid @RequestBody PageDesignerTemplateDTO dto) { + service.updatePage(dto); + return R.ok("淇敼鎴愬姛"); + } + + /** + * 鍒犻櫎椤甸潰璁捐 + */ + @DeleteMapping + public R<Void> remove(@RequestBody List<Long> ids) { + service.deleteByIds(ids); + return R.ok("鍒犻櫎鎴愬姛"); + } +} diff --git a/ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/domain/PageDesignerDTO.java b/ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/domain/PageDesignerDTO.java index 977f6fb..7224b38 100644 --- a/ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/domain/PageDesignerDTO.java +++ b/ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/domain/PageDesignerDTO.java @@ -5,9 +5,6 @@ import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import org.ruoyi.core.domain.BaseEntity; -import org.ruoyi.system.domain.SysUser; - -import java.util.List; /** * @author kanglujie diff --git a/ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/domain/PageDesignerTemplate.java b/ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/domain/PageDesignerTemplate.java new file mode 100644 index 0000000..338c97a --- /dev/null +++ b/ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/domain/PageDesignerTemplate.java @@ -0,0 +1,28 @@ +package org.ruoyi.pageDesigner.domain; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.ruoyi.core.domain.BaseEntity; + +/** + * @author kanglujie + * @date 2025-06-23 17:24:05 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("PAGE_DESIGNER_TEMPLATE") +public class PageDesignerTemplate extends BaseEntity { + @TableId(value = "ID") + private Long id; + @TableField(value = "PAGE_ID") + private Long pageId; + @TableField("FORM_DATA") + private String formData; + @TableField(value = "DEL_FLAG") + @TableLogic + private String delFlag; +} diff --git a/ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/domain/PageDesignerTemplateDTO.java b/ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/domain/PageDesignerTemplateDTO.java new file mode 100644 index 0000000..f2be0b8 --- /dev/null +++ b/ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/domain/PageDesignerTemplateDTO.java @@ -0,0 +1,22 @@ +package org.ruoyi.pageDesigner.domain; + +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import org.ruoyi.core.domain.BaseEntity; + +/** + * @author kanglujie + * @date 2025-06-23 17:23:35 + */ +@Data +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +@AutoMapper(target = PageDesignerTemplate.class, reverseConvertGenerate = false) +public class PageDesignerTemplateDTO extends BaseEntity { + private Long id; + private Long pageId; + private String formData; + private String delFlag; +} diff --git a/ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/domain/PageDesignerTemplateVo.java b/ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/domain/PageDesignerTemplateVo.java new file mode 100644 index 0000000..9974206 --- /dev/null +++ b/ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/domain/PageDesignerTemplateVo.java @@ -0,0 +1,19 @@ +package org.ruoyi.pageDesigner.domain; + +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author kanglujie + * @date 2025-06-23 17:23:35 + */ +@Data +@AutoMapper(target = PageDesignerTemplate.class) +public class PageDesignerTemplateVo implements Serializable { + private Long id; + private Long pageId; + private String formData; + private String delFlag; +} diff --git a/ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/domain/PageDesignerVo.java b/ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/domain/PageDesignerVo.java index 3b98968..54bb8fa 100644 --- a/ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/domain/PageDesignerVo.java +++ b/ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/domain/PageDesignerVo.java @@ -2,7 +2,6 @@ import io.github.linpeilie.annotations.AutoMapper; import lombok.Data; -import org.ruoyi.core.domain.BaseEntity; import org.ruoyi.system.domain.vo.SysMenuVo; import java.io.Serializable; diff --git a/ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/mapper/PageDesignerTemplateMapper.java b/ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/mapper/PageDesignerTemplateMapper.java new file mode 100644 index 0000000..c0a54d1 --- /dev/null +++ b/ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/mapper/PageDesignerTemplateMapper.java @@ -0,0 +1,20 @@ +package org.ruoyi.pageDesigner.mapper; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.ruoyi.pageDesigner.domain.PageDesignerTemplate; +import org.ruoyi.pageDesigner.domain.PageDesignerTemplateVo; + +/** + * @author kanglujie + * @date 2025-06-23 17:34:48 + */ +@Mapper +public interface PageDesignerTemplateMapper extends BaseMapper<PageDesignerTemplate> { + Page<PageDesignerTemplateVo> selectPagelistAll(@Param("page") Page<PageDesignerTemplate> page, @Param(Constants.WRAPPER) Wrapper<PageDesignerTemplate> queryWrapper); + +} diff --git a/ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/service/PageDesignerTemplateService.java b/ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/service/PageDesignerTemplateService.java new file mode 100644 index 0000000..a0e2bdb --- /dev/null +++ b/ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/service/PageDesignerTemplateService.java @@ -0,0 +1,27 @@ +package org.ruoyi.pageDesigner.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import org.ruoyi.core.page.PageQuery; +import org.ruoyi.core.page.TableDataInfo; +import org.ruoyi.pageDesigner.domain.*; + +import java.util.List; + +/** + * @author kanglujie + * @date 2025-06-23 17:35:56 + */ +public interface PageDesignerTemplateService extends IService<PageDesignerTemplate> { + + void add(PageDesignerTemplateDTO dto); + + void updatePage(PageDesignerTemplateDTO dto); + + List<PageDesignerTemplate> listAll(String keyword); + + PageDesignerTemplate getDetail(Long id); + + void deleteByIds(List<Long> ids); + + TableDataInfo<PageDesignerTemplateVo> selectPagelistAll(PageDesignerTemplateDTO dto, PageQuery pageQuery); +} diff --git a/ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/service/impl/PageDesignerServiceImpl.java b/ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/service/impl/PageDesignerServiceImpl.java index b8e42d8..e42337c 100644 --- a/ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/service/impl/PageDesignerServiceImpl.java +++ b/ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/service/impl/PageDesignerServiceImpl.java @@ -54,15 +54,15 @@ return TableDataInfo.build(page); } private Wrapper<PageDesigner> buildQueryWrapper(PageDesignerDTO pageDesignerDTO) { - //Map<String, Object> params = pageDesignerDTO.getParams(); + Map<String, Object> params = pageDesignerDTO.getParams(); QueryWrapper<PageDesigner> wrapper = Wrappers.query(); - //wrapper.eq("del_flag", UserConstants.USER_NORMAL) - // .eq(ObjectUtil.isNotNull(pageDesignerDTO.getId()), "id", pageDesignerDTO.getId()) - // .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")) - //; + wrapper.eq("del_flag", UserConstants.USER_NORMAL) + .eq(ObjectUtil.isNotNull(pageDesignerDTO.getId()), "id", pageDesignerDTO.getId()) + .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 diff --git a/ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/service/impl/PageDesignerTemplateServiceImpl.java b/ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/service/impl/PageDesignerTemplateServiceImpl.java new file mode 100644 index 0000000..4901a54 --- /dev/null +++ b/ruoyi-modules/sc-page-designer/src/main/java/org/ruoyi/pageDesigner/service/impl/PageDesignerTemplateServiceImpl.java @@ -0,0 +1,87 @@ +package org.ruoyi.pageDesigner.service.impl; + +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.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.RequiredArgsConstructor; +import org.ruoyi.core.page.PageQuery; +import org.ruoyi.core.page.TableDataInfo; +import org.ruoyi.pageDesigner.domain.*; +import org.ruoyi.pageDesigner.mapper.PageDesignerMapper; +import org.ruoyi.pageDesigner.mapper.PageDesignerTemplateMapper; +import org.ruoyi.pageDesigner.service.PageDesignerService; +import org.ruoyi.pageDesigner.service.PageDesignerTemplateService; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author kanglujie + * @date 2025-06-23 17:36:29 + */ +@Service +@RequiredArgsConstructor +public class PageDesignerTemplateServiceImpl extends ServiceImpl<PageDesignerTemplateMapper, PageDesignerTemplate> + implements PageDesignerTemplateService { + + private final ObjectMapper objectMapper; + + @Override + public void add(PageDesignerTemplateDTO dto) { + PageDesignerTemplate entity = convertToEntity(dto); + this.save(entity); + } + + @Override + public void updatePage(PageDesignerTemplateDTO dto) { + PageDesignerTemplate entity = convertToEntity(dto); + this.updateById(entity); + } + + @Override + public TableDataInfo<PageDesignerTemplateVo> selectPagelistAll(PageDesignerTemplateDTO dto, PageQuery pageQuery) { + Page<PageDesignerTemplateVo> page = baseMapper.selectPagelistAll(pageQuery.build(), this.buildQueryWrapper(dto)); + return TableDataInfo.build(page); + } + 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()) + // .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 + public List<PageDesignerTemplate> listAll(String keyword) { + LambdaQueryWrapper<PageDesignerTemplate> wrapper = new LambdaQueryWrapper<>(); + wrapper.like(keyword != null, PageDesignerTemplate::getPageId, keyword); + return this.list(wrapper); + } + + @Override + public PageDesignerTemplate getDetail(Long id) { + return this.getById(id); + } + + @Override + public void deleteByIds(List<Long> ids) { + this.removeByIds(ids); + } + + private PageDesignerTemplate convertToEntity(PageDesignerTemplateDTO dto) { + PageDesignerTemplate entity = new PageDesignerTemplate(); + entity.setId(dto.getId()); + entity.setFormData(dto.getFormData()); + entity.setDelFlag(dto.getDelFlag()); + entity.setPageId(dto.getPageId()); + return entity; + } +} diff --git a/ruoyi-modules/sc-page-designer/src/main/resources/mapper/SysUserMapper.xml b/ruoyi-modules/sc-page-designer/src/main/resources/mapper/PageDesignerMapper.xml similarity index 100% rename from ruoyi-modules/sc-page-designer/src/main/resources/mapper/SysUserMapper.xml rename to ruoyi-modules/sc-page-designer/src/main/resources/mapper/PageDesignerMapper.xml diff --git a/ruoyi-modules/sc-page-designer/src/main/resources/mapper/PageDesignerTemplateMapper.xml b/ruoyi-modules/sc-page-designer/src/main/resources/mapper/PageDesignerTemplateMapper.xml new file mode 100644 index 0000000..8c23389 --- /dev/null +++ b/ruoyi-modules/sc-page-designer/src/main/resources/mapper/PageDesignerTemplateMapper.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE mapper + PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> +<mapper namespace="org.ruoyi.pageDesigner.mapper.PageDesignerTemplateMapper"> + + <!-- 缁撴灉鏄犲皠 --> + <resultMap type="org.ruoyi.pageDesigner.domain.PageDesignerTemplateVo" id="PageDesignerTemplateResult"> + <id property="id" column="id"/> + <result property="pageId" column="page_id"/> + <result property="formData" column="form_data"/> + <result property="delFlag" column="del_flag"/> + </resultMap> + + <select id="selectPagelistAll" resultMap="PageDesignerTemplateResult"> + SELECT + id, + page_id, + form_data, + del_flag + FROM page_designer_template + <where> + ${ew.sqlSegment} + </where> + </select> + +</mapper> diff --git a/ruoyi-ui/apps/web-antd/src/api/tool/template/index.ts b/ruoyi-ui/apps/web-antd/src/api/tool/template/index.ts new file mode 100644 index 0000000..0b91788 --- /dev/null +++ b/ruoyi-ui/apps/web-antd/src/api/tool/template/index.ts @@ -0,0 +1,45 @@ +import { requestClient } from '#/api/request'; +import type { Template } from './model'; + +enum Api { + templateAdd = '/page-designer-template', + templateUpdate = '/page-designer-template', + templateList = '/page-designer-template/list', + templateInfo = '/page-designer-template', + templateRemove = '/page-designer-template', +} + +/** + * 鏂板椤甸潰璁捐 + */ +export function templateAdd(data: any) { + return requestClient.post(Api.templateAdd, data); +} + +/** + * 淇敼椤甸潰璁捐 + */ +export function templateUpdate(data: any) { + return requestClient.put(Api.templateUpdate, data); +} + +/** + * 鑾峰彇椤甸潰璁捐鍒楄〃 + */ +export function templateList(params?: any) { + return requestClient.get(Api.templateList, { params }); +} + +/** + * 鑾峰彇椤甸潰璁捐璇︽儏 + */ +export function templateInfo(id: string | number) { + return requestClient.get(`${Api.templateInfo}/${id}`); +} + +/** + * 鍒犻櫎椤甸潰璁捐 + */ +export function templateRemove(ids: string[] | number[]) { + return requestClient.delete(Api.templateRemove, { data: ids }); +} \ No newline at end of file diff --git a/ruoyi-ui/apps/web-antd/src/api/tool/template/model.d.ts b/ruoyi-ui/apps/web-antd/src/api/tool/template/model.d.ts new file mode 100644 index 0000000..ab9d827 --- /dev/null +++ b/ruoyi-ui/apps/web-antd/src/api/tool/template/model.d.ts @@ -0,0 +1,14 @@ +export interface Template { + id?: string | number; // 涓婚敭 + formData: string; // 妯$増鍚嶇О + pageDesignId: string | number; // 鍏宠仈鐨勯〉闈㈣璁D + createTime?: string; // 鍒涘缓鏃堕棿 + updateTime?: string; // 鏇存柊鏃堕棿 + pageDesign?: { // 鍏宠仈鐨勯〉闈㈣璁′俊鎭� + id: string | number; + name: string; + formJson?: string; + showColumn?: string; + actionsFunc?: string; + } | null; +} \ No newline at end of file diff --git a/ruoyi-ui/apps/web-antd/src/views/tool/template/data.tsx b/ruoyi-ui/apps/web-antd/src/views/tool/template/data.tsx new file mode 100644 index 0000000..62d35c1 --- /dev/null +++ b/ruoyi-ui/apps/web-antd/src/views/tool/template/data.tsx @@ -0,0 +1,86 @@ +import type { FormSchemaGetter } from '#/adapter/form'; +import type { VxeGridProps } from '#/adapter/vxe-table'; + +export const querySchema: FormSchemaGetter = () => [ + { + component: 'Input', + fieldName: 'name', + label: '妯$増鍚嶇О', + }, + { + component: 'Select', + componentProps: { + options: [ + { label: '姝e父', value: '1' }, + { label: '鍋滅敤', value: '0' }, + ], + }, + fieldName: 'status', + label: '妯$増鐘舵��', + }, +]; + +export const columns = [ + { + title: '濮撳悕', + dataIndex: 'name', + auth: 'test', // 鏍规嵁鏉冮檺鎺у埗鏄惁鏄剧ず: 鏃犳潈闄愶紝涓嶆樉绀� + } +]; + +export const drawerSchema = () => [ + { + component: 'Input', + fieldName: 'name', + label: '妯$増鍚嶇О', + rules: 'required', + }, + { + component: 'Select', + fieldName: 'pageDesignId', + label: '椤甸潰璁捐', + componentProps: { + allowClear: true, + showSearch: true, + filterOption: (input: string, option: any) => { + return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0; + }, + }, + rules: 'selectRequired', + }, + { + component: 'Select', + fieldName: 'templateType', + label: '妯$増绫诲瀷', + componentProps: { + options: [ + { label: '鍒楄〃椤�', value: 'list' }, + { label: '琛ㄥ崟椤�', value: 'form' }, + { label: '璇︽儏椤�', value: 'detail' }, + { label: '浠〃鏉�', value: 'dashboard' }, + ], + }, + rules: 'selectRequired', + }, + { + component: 'Select', + fieldName: 'status', + label: '鐘舵��', + componentProps: { + options: [ + { label: '姝e父', value: '1' }, + { label: '鍋滅敤', value: '0' }, + ], + }, + rules: 'selectRequired', + }, + { + component: 'Input', + fieldName: 'remark', + label: '澶囨敞', + componentProps: { + type: 'textarea', + rows: 2, + }, + }, +]; \ No newline at end of file diff --git a/ruoyi-ui/apps/web-antd/src/views/tool/template/index.vue b/ruoyi-ui/apps/web-antd/src/views/tool/template/index.vue new file mode 100644 index 0000000..d198eaa --- /dev/null +++ b/ruoyi-ui/apps/web-antd/src/views/tool/template/index.vue @@ -0,0 +1,404 @@ +<template> + <Page v-if="isAdmin" :auto-content-height="true"> + <BasicTable + :key="tableKey" + :table-title="pageDesignDetail?.name || '妯℃澘鍒楄〃'" + :grid-options="gridOptions" + > + <template #toolbar-tools> + <Space> + <a-button v-if="showAction('add')" type="primary" @click="handleAdd">鏂板</a-button> + </Space> + </template> + <template #action="{ row }"> + <Space> + <ghost-button v-if="showAction('edit')" @click="handleEdit(row)">缂栬緫</ghost-button> + <Popconfirm v-if="showAction('delete')" :get-popup-container="getVxePopupContainer" placement="left" title="纭鍒犻櫎锛�" @confirm="handleDelete(row)"> + <ghost-button danger @click.stop="">鍒犻櫎</ghost-button> + </Popconfirm> + </Space> + </template> + </BasicTable> + <TemplateDrawer ref="templateModalRef" @reload="tableApi.query()" /> + </Page> + <Fallback v-else description="鎮ㄦ病鏈夐〉闈㈢殑璁块棶鏉冮檺" status="403" /> +</template> + +<script setup lang="ts"> +import type { VbenFormProps } from '@vben/common-ui'; +import type { VxeGridProps } from '#/adapter/vxe-table'; +import { computed, ref, onMounted, watch } from 'vue'; +import { useRoute, useRouter } from 'vue-router'; +import { useAccess } from '@vben/access'; +import { Fallback, Page } from '@vben/common-ui'; +import { getVxePopupContainer } from '@vben/utils'; +import { Popconfirm, Space, Spin as ASpin } from 'ant-design-vue'; +import { useVbenVxeGrid } from '#/adapter/vxe-table'; +import { columns as baseColumns, querySchema } from './data'; +import TemplateDrawer from './template-drawer.vue'; +import { templateList, templateRemove } from '#/api/tool/template'; +import { pageInfo } from '#/api/tool/page-designer'; + +const route = useRoute(); +const router = useRouter(); +const pageId = ref<string | number>(''); +const pageDesignDetail = ref<any>(null); // 椤甸潰璁捐璇︽儏 +const loading = ref(true); // 鍔犺浇涓� + +// 鍔ㄦ�乧olumns +const dynamicColumns = ref([ + { field: 'id', title: 'ID', width: 100 }, + { field: 'formData', title: '琛ㄥ崟鏁版嵁', minWidth: 160 }, + { field: 'action', title: '鎿嶄綔', width: 160, slots: { default: 'action' } } +]); + +// 鐢ㄤ簬琛ㄦ牸閲嶆柊娓叉煋鐨� key +const tableKey = ref(0); + +// 鏇存柊鍔ㄦ�佸垪鐨勫嚱鏁� +function updateDynamicColumns() { + if (!pageDesignDetail.value || !pageDesignDetail.value.showColumn || !pageDesignDetail.value.formJson) { + console.log('浣跨敤榛樿鍒�'); + return; + } + + try { + const showFields = JSON.parse(pageDesignDetail.value.showColumn); + const formFields = JSON.parse(pageDesignDetail.value.formJson); + const cols = showFields.map(field => { + const fieldDef = formFields.find(f => f.field === field); + return { + field: field, + title: fieldDef ? fieldDef.title : field, + minWidth: 120, + align: 'center', + }; + }); + + cols.push({ + field: 'action', + title: '鎿嶄綔', + width: 160, + slots: { default: 'action' }, + }); + + dynamicColumns.value = cols; + gridOptions.value = { ...gridOptions.value, columns: cols }; + tableKey.value++; + } catch (error) { + const fallbackCols = [ + { field: 'id', title: 'ID', width: 100 }, + { field: 'formData', title: '琛ㄥ崟鏁版嵁', minWidth: 160 }, + { field: 'action', title: '鎿嶄綔', width: 160, slots: { default: 'action' } } + ]; + dynamicColumns.value = fallbackCols; + gridOptions.value = { ...gridOptions.value, columns: fallbackCols }; + tableKey.value++; + } +} + + +// 鍔ㄦ�佹寜閽� +function showAction(action: string) { + if (!pageDesignDetail.value || !pageDesignDetail.value.actionsFunc) { + return true; + } + + try { + const actions = JSON.parse(pageDesignDetail.value.actionsFunc); + if (!Array.isArray(actions)) { + console.warn('actionsFunc 涓嶆槸鏁扮粍鏍煎紡:', pageDesignDetail.value.actionsFunc); + return true; + } + + return actions.includes(action); + } catch (error) { + console.error('瑙f瀽 actionsFunc 澶辫触:', error); + return true; + } +} + +// 鑾峰彇 pageId锛屽吋瀹� meta銆乸arams銆乹uery +function getPageId() { + const pageId = ( + (route.meta && (route.meta as any).pageId) || + route.params.pageId || + route.query.pageId || + '' + ); + + // 纭繚杩斿洖鐨勬槸瀛楃涓叉垨鏁板瓧 + return pageId ? String(pageId) : ''; +} + +onMounted(() => { + const initialPageId = getPageId(); + console.log('鑾峰彇鍒扮殑 pageId:', initialPageId); + + if (initialPageId) { + pageId.value = initialPageId; + handlePageIdChange(); + } else { + loading.value = false; + } +}); + +// 鐩戝惉璺敱鍙樺寲锛岃嚜鍔ㄦ洿鏂� pageId +watch( + () => [route.meta.pageId, route.params.pageId, route.query.pageId], + (newValues, oldValues) => { + // 鍙湁褰撳�肩湡姝e彉鍖栨椂鎵嶅鐞� + if (JSON.stringify(newValues) !== JSON.stringify(oldValues)) { + const newPageId = getPageId(); + console.log('璺敱鍙樺寲鍚� pageId:', newPageId); + + // 鍙湁褰� pageId 鐪熸鍙樺寲鏃舵墠鏇存柊 + if (newPageId !== pageId.value) { + pageId.value = newPageId; + handlePageIdChange(); + tableApi.query(); + } + } + }, + { deep: true } +); + +// pageId鍙樺寲鏃惰嚜鍔ㄨ幏鍙栭〉闈㈣璁¤鎯� +async function handlePageIdChange() { + loading.value = true; + console.log(`[handlePageIdChange] 寮�濮嬪鐞� pageId: ${pageId.value}`); + try { + if (pageId.value) { + const detail = await pageInfo(pageId.value); + console.log('[handlePageIdChange] 鑾峰彇鍒扮殑椤甸潰璁捐璇︽儏 (detail):', JSON.parse(JSON.stringify(detail))); + + // 澶勭悊鏁版嵁锛岄伩鍏嶅惊鐜紩鐢� + const safeDetail = { + id: detail.id, + name: detail.name, + menuId: detail.menuId, + status: detail.status, + remark: detail.remark, + formJson: detail.formJson, + showColumn: detail.showColumn, + actionsFunc: detail.actionsFunc, + createTime: detail.createTime, + updateTime: detail.updateTime, + createBy: detail.createBy, + updateBy: detail.updateBy, + createDept: detail.createDept + }; + + pageDesignDetail.value = safeDetail; + console.log('[handlePageIdChange] 璁剧疆鐨� pageDesignDetail.value:', JSON.parse(JSON.stringify(pageDesignDetail.value))); + updateDynamicColumns(); + } else { + pageDesignDetail.value = null; + updateDynamicColumns(); + } + } catch (error) { + console.error('[handlePageIdChange] 鑾峰彇椤甸潰璁捐璇︽儏澶辫触:', error); + pageDesignDetail.value = null; + updateDynamicColumns(); + } finally { + loading.value = false; + } +} + +const formOptions: VbenFormProps = { + commonConfig: { + labelWidth: 80, + componentProps: { + allowClear: true, + }, + }, + schema: querySchema(), + wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4', +}; + +const gridOptions = ref<VxeGridProps>({ + columns: dynamicColumns.value, + height: 'auto', + keepSource: true, + pagerConfig: { + enabled: true, + }, + proxyConfig: { + ajax: { + query: async ({ page }, formValues = {}) => { + try { + console.log('鏌ヨ鍙傛暟:', { page, formValues }); + const queryParams = { + pageNum: page.currentPage, + pageSize: page.pageSize, + ...formValues, + }; + if (pageId.value) { + queryParams.pageDesignId = pageId.value; + } + const resp = await templateList(queryParams); + // 澶勭悊姣忔潯 row 鐨� formData + const rows = (resp.rows || []).map(row => { + let formData = {}; + try { + if (row.formData) { + formData = JSON.parse(row.formData); + console.log('瑙f瀽鍚庣殑 formData:', formData); + // 鍒犻櫎鍘熷鐨� formData 瀛楁锛屽洜涓烘垜浠凡缁忓睍寮�瀹冪殑鍐呭 + const { formData: _, ...restRow } = row; + // 杩斿洖灞曞紑鍚庣殑鏁版嵁 + return { + ...restRow, + ...formData + }; + } + } catch (e) { + console.error('瑙f瀽 formData 澶辫触:', e); + } + return row; + }); + console.log('澶勭悊鍚庣殑 rows:', rows); + return { + rows, + total: resp.total || 0, + }; + } catch (error) { + console.error('鏌ヨ妯℃澘鍒楄〃澶辫触:', error); + return { + rows: [], + total: 0, + }; + } + }, + }, + }, + rowConfig: { + keyField: 'id', + }, + id: 'tool-template-index', + columnConfig: { resizable: true }, +}); + +const [BasicTable, tableApi] = useVbenVxeGrid({ + formOptions, + gridOptions: computed(() => ({ + ...gridOptions.value, + columns: dynamicColumns.value + })), +}); + +const templateModalRef = ref(); +const generateModalRef = ref(); + +function handleAdd() { + // 濡傛灉鏈� pageId锛屼紶閫掔粰鏂板 + const params: any = { update: false }; + if (pageId.value) { + params.pageDesignId = pageId.value; + } + // 鍔ㄦ�佷紶閫抐ormJson锛屽厛JSON.parse锛屼繚璇佹槸绾璞� + if (pageDesignDetail.value && pageDesignDetail.value.formJson) { + try { + const formJson = JSON.parse(pageDesignDetail.value.formJson); + params.formJson = formJson; + console.log('浼犻�掑姩鎬佽〃鍗曞瓧娈�:', formJson); + } catch (error) { + console.error('瑙f瀽 formJson 澶辫触:', error); + params.formJson = undefined; + } + } + templateModalRef.value.open(params); +} + +function handleEdit(record) { + // 缂栬緫鏃朵篃浼犻�抐ormJson锛屽厛JSON.parse锛屼繚璇佹槸绾璞� + const params: any = { + id: record.id, + update: true, + pageDesignId: pageId.value, // 浼犻�掗〉闈㈣璁D + record: record // 浼犻�掑畬鏁寸殑璁板綍鏁版嵁 + }; + + if (pageDesignDetail.value && pageDesignDetail.value.formJson) { + try { + const formJson = JSON.parse(pageDesignDetail.value.formJson); + params.formJson = formJson; + console.log('缂栬緫鏃朵紶閫掓暟鎹�:', { record, formJson, pageDesignId: pageId.value }); + } catch (error) { + console.error('瑙f瀽 formJson 澶辫触:', error); + params.formJson = undefined; + } + } + templateModalRef.value.open(params); +} + +async function handleDelete(row: any) { + try { + await templateRemove([row.id]); + await tableApi.query(); + } catch (error) { + console.error('鍒犻櫎妯℃澘澶辫触:', error); + } +} + +function handleGenerate(row) { + try { + generateModalRef.value.open(row); + } catch (error) { + console.error('鎵撳紑鐢熸垚椤甸潰澶辫触:', error); + } +} + +function handlePreview(row) { + try { + // 鎵撳紑棰勮绐楀彛 + const url = `/tool/template/preview/${row.id}`; + window.open(url, '_blank'); + } catch (error) { + console.error('鎵撳紑棰勮澶辫触:', error); + } +} + +const { hasAccessByRoles } = useAccess(); +const isAdmin = computed(() => { + try { + return hasAccessByRoles(['admin', 'superadmin']); + } catch (error) { + console.error('妫�鏌ユ潈闄愬け璐�:', error); + return false; + } +}); + +const isReady = computed(() => { + try { + // 绠�鍖栧垽鏂�昏緫锛屽噺灏戜笉蹇呰鐨勮绠� + return !!(pageDesignDetail.value && !loading.value); + } catch (error) { + console.error('妫�鏌ラ〉闈㈠噯澶囩姸鎬佸け璐�:', error); + return false; + } +}); +</script> + +<style scoped> +.template-page { + background: #f5f6fa; + padding: 16px; + min-height: 100vh; + height: 100vh; + overflow: hidden; +} + +/* 纭繚琛ㄦ牸瀹瑰櫒楂樺害绋冲畾 */ +:deep(.vxe-table--main-wrapper) { + height: 600px !important; +} + +/* 纭繚鍒嗛〉鍣ㄤ綅缃浐瀹� */ +:deep(.vxe-pager) { + position: sticky; + bottom: 0; + background: white; + z-index: 10; +} +</style> \ No newline at end of file diff --git a/ruoyi-ui/apps/web-antd/src/views/tool/template/template-drawer.vue b/ruoyi-ui/apps/web-antd/src/views/tool/template/template-drawer.vue new file mode 100644 index 0000000..da11342 --- /dev/null +++ b/ruoyi-ui/apps/web-antd/src/views/tool/template/template-drawer.vue @@ -0,0 +1,224 @@ +<script setup lang="ts"> +import { computed, ref, watch, nextTick } from 'vue'; +import { Modal, message, FormItem } from 'ant-design-vue'; +import { $t } from '@vben/locales'; +import { templateAdd, templateUpdate, templateInfo } from '#/api/tool/template'; +import { pageList } from '#/api/tool/page-designer'; +import formCreate from '@form-create/element-ui'; + +interface ModalProps { + id?: number | string; + update: boolean; + pageDesignId?: string | number; + formJson?: any; +} + +const emit = defineEmits<{ reload: [] }>(); + +const isUpdate = ref(false); +const title = computed(() => { + return isUpdate.value ? $t('pages.common.edit') : $t('pages.common.add'); +}); + +const modalVisible = ref(false); +const modalLoading = ref(false); +const currentEditId = ref<string | number>(''); +const dynamicFormRef = ref(); +const dynamicFormRule = ref([]); +const dynamicFormOption = ref({ + submitBtn: false, + resetBtn: false +}); +const showOkBtn = ref(true); +const currentPageId = ref(''); +const formApi = ref(); + +// 鍒ゆ柇鏄惁鏈夋彁浜ゆ寜閽� +type RuleItem = { type?: string }; +const hasSubmitBtn = (rules: any[] = []) => { + return rules.some((item: RuleItem) => item.type === 'submit'); +}; +// 鏇村交搴曠殑閫掑綊绉婚櫎鎵�鏈� submit 鎸夐挳锛屾敮鎸� children銆乥ody銆乧olumns銆乴ist銆乷ptions銆乼abs 绛夊鍣� +function removeSubmitBtn(rules = []) { + return rules + .filter(item => item.type !== 'submit') + .map(item => { + if (item.children) item.children = removeSubmitBtn(item.children); + if (item.body) item.body = removeSubmitBtn(item.body); + if (item.columns) item.columns = item.columns.map(col => ({ + ...col, + list: removeSubmitBtn(col.list || []) + })); + if (item.list) item.list = removeSubmitBtn(item.list); + if (item.options && Array.isArray(item.options)) item.options = removeSubmitBtn(item.options); + if (item.tabs) item.tabs = item.tabs.map(tab => ({ + ...tab, + list: removeSubmitBtn(tab.list || []) + })); + return item; + }); +} + +// 鎵撳紑寮圭獥 +const open = async (params: ModalProps = { update: false }) => { + try { + console.log('鎵撳紑寮圭獥锛屽弬鏁�:', params); + modalVisible.value = true; + modalLoading.value = true; + isUpdate.value = params.update; + currentEditId.value = params.id || ''; + currentPageId.value = params.pageId || params.pageDesignId || ''; + + // 璁剧疆鍔ㄦ�佽〃鍗曞瓧娈碉紝濮嬬粓绉婚櫎鎵�鏈塻ubmit鎸夐挳 + if (params.formJson) { + console.log('璁剧疆鍔ㄦ�佽〃鍗曡鍒�:', params.formJson); + dynamicFormRule.value = removeSubmitBtn(params.formJson); + showOkBtn.value = true; // 濮嬬粓鏄剧ず纭畾鎸夐挳 + } else { + dynamicFormRule.value = []; + showOkBtn.value = true; + } + + // 缂栬緫妯″紡 + if (params.id && params.update) { + console.log('缂栬緫妯″紡锛岃幏鍙栬鎯呮暟鎹�'); + try { + // 鑾峰彇璇︽儏鏁版嵁 + const record = await templateInfo(params.id); + console.log('鑾峰彇鍒扮殑璁板綍鏁版嵁:', record); + + // 璁剧疆鍔ㄦ�佽〃鍗曟暟鎹� + if (record.formData) { + try { + const dynamicData = JSON.parse(record.formData); + console.log('瑙f瀽鍚庣殑琛ㄥ崟鏁版嵁:', dynamicData); + + await nextTick(); + if (formApi.value) { + console.log('鍑嗗璁剧疆琛ㄥ崟鏁版嵁鍒扮粍浠�'); + // 浣跨敤 form-create 鐨� API 璁剧疆鍊� + Object.keys(dynamicData).forEach(key => { + formApi.value.setValue(key, dynamicData[key]); + }); + console.log('琛ㄥ崟鏁版嵁璁剧疆瀹屾垚'); + } else { + console.warn('琛ㄥ崟API鏈氨缁�'); + message.error('琛ㄥ崟鏈氨缁紝璇烽噸璇�'); + } + } catch (error) { + console.error('瑙f瀽鍔ㄦ�佸瓧娈垫暟鎹け璐�:', error); + message.error('鍔犺浇琛ㄥ崟鏁版嵁澶辫触'); + } + } else { + console.log('璁板綍涓病鏈� formData 鏁版嵁'); + } + } catch (error) { + console.error('澶勭悊琛ㄥ崟鏁版嵁澶辫触:', error); + message.error('鍔犺浇琛ㄥ崟鏁版嵁澶辫触锛岃閲嶈瘯'); + } + } else { + // 鏂板鏃堕噸缃暟鎹� + console.log('鏂板妯″紡锛岄噸缃〃鍗�'); + await nextTick(); + if (formApi.value) { + formApi.value.resetFields && formApi.value.resetFields(); + } + } + } catch (error) { + console.error('鎵撳紑寮圭獥澶辫触:', error); + message.error('鍔犺浇鏁版嵁澶辫触'); + } finally { + modalLoading.value = false; + } +}; + +const close = () => { + modalVisible.value = false; +}; + +defineExpose({ open, close }); + +function onFormMounted(api) { + formApi.value = api; +} + +// handleOk 鍙礋璐hЕ鍙戣〃鍗� submit +async function handleOk() { + await nextTick(); + console.log('handleOk formApi:', formApi.value); + if (!dynamicFormRule.value || dynamicFormRule.value.length === 0) { + message.error('琛ㄥ崟瑙勫垯鏈姞杞斤紝鏃犳硶鎻愪氦'); + return; + } + if (!formApi.value) { + message.error('琛ㄥ崟鏈覆鏌撳畬鎴愶紝璇风◢鍚庨噸璇�'); + return; + } + try { + modalLoading.value = true; + const valid = await formApi.value.validate(); + if (!valid) { + modalLoading.value = false; + return; + } + const formData = formApi.value.formData(); + await onFormSubmit(formData); + } catch (error) { + console.error('淇濆瓨澶辫触:', error); + message.error('淇濆瓨澶辫触'); + modalLoading.value = false; + } +} + +// form-create 鐨� submit 浜嬩欢澶勭悊 +async function onFormSubmit(dynamicData: any) { + try { + modalLoading.value = true; + // 鏋勫缓淇濆瓨鏁版嵁 + const finalData = { + pageId: currentPageId.value, + formData: Object.keys(dynamicData).length > 0 ? JSON.stringify(dynamicData) : undefined + }; + if (isUpdate.value) { + finalData.id = currentEditId.value; + } + console.log(finalData) + await (isUpdate.value ? templateUpdate(finalData) : templateAdd(finalData)); + emit('reload'); + close(); + message.success('淇濆瓨鎴愬姛'); + } catch (error) { + console.error('淇濆瓨澶辫触:', error); + message.error('淇濆瓨澶辫触'); + } finally { + modalLoading.value = false; + } +} + +function handleCancel() { + close(); +} +</script> + +<template> + <a-modal + v-model:open="modalVisible" + :title="title" + :width="'80vw'" + :confirm-loading="modalLoading" + @ok="handleOk" + @cancel="handleCancel" + :bodyStyle="{ padding: '24px', minHeight: '60vh' }" + destroyOnClose + :ok-button-props="{ style: showOkBtn ? {} : { display: 'none' } }" + > + <!-- 鍔ㄦ�佽〃鍗曞尯鍩� --> + <form-create + ref="dynamicFormRef" + :rule="dynamicFormRule" + :option="dynamicFormOption" + @submit="onFormSubmit" + @mounted="onFormMounted" + /> + </a-modal> +</template> \ No newline at end of file -- Gitblit v1.9.3