Merge remote-tracking branch 'origin/main'
# Conflicts:
# ruoyi-modules/pom.xml
| | |
| | | <artifactId>ruoyi-chat</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.ruoyi</groupId> |
| | | <artifactId>sc-services</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.ruoyi</groupId> |
| | | <artifactId>sc-page-designer</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.ruoyi</groupId> |
| | | <artifactId>ruoyi-knowledge-api</artifactId> |
| | |
| | | |
| | | <dependency> |
| | | <groupId>org.ruoyi</groupId> |
| | | <artifactId>sc-services</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.ruoyi</groupId> |
| | | <artifactId>sc-page-designer</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.ruoyi</groupId> |
| | | <artifactId>ruoyi-generator</artifactId> |
| | | </dependency> |
| | | |
| | |
| | | package org.ruoyi.domain; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import lombok.Data; |
| | |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @TableName("chat_session") |
| | | @TableName("CHAT_SESSION") |
| | | public class ChatSession extends BaseEntity { |
| | | |
| | | @Serial |
| | |
| | | /** |
| | | * ä¸»é® |
| | | */ |
| | | @TableId(value = "id") |
| | | @TableId(value = "ID") |
| | | private Long id; |
| | | |
| | | /** |
| | | * ç¨æ·id |
| | | * ç¨æ·ID |
| | | */ |
| | | @TableField("USER_ID") |
| | | private Long userId; |
| | | |
| | | /** |
| | | * ä¼è¯æ é¢ |
| | | */ |
| | | @TableField("SESSION_TITLE") |
| | | private String sessionTitle; |
| | | |
| | | /** |
| | | * ä¼è¯å
容 |
| | | */ |
| | | @TableField("SESSION_CONTENT") |
| | | private String sessionContent; |
| | | |
| | | /** |
| | | * 夿³¨ |
| | | */ |
| | | @TableField("REMARK") |
| | | private String remark; |
| | | |
| | | |
| | | } |
| | |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @TableName("knowledge_info") |
| | | @TableName("KNOWLEDGE_INFO") |
| | | public class KnowledgeInfo extends BaseEntity { |
| | | |
| | | @Serial |
| | |
| | | * 主é®ID |
| | | */ |
| | | @TableId(value = "ID") |
| | | @TableField("ID") |
| | | private Long id; |
| | | |
| | | /** |
| | |
| | | <module>ruoyi-system</module> |
| | | <module>ruoyi-generator</module> |
| | | <module>ruoyi-flowable</module> |
| | | <module>sc-services</module> |
| | | <module>sc-page-designer</module> |
| | | </modules> |
| | | |
| | | <properties> |
| | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void removeKnowledge(String id) { |
| | | Map<String,Object> map = new HashMap<>(); |
| | | KnowledgeInfo knowledgeInfo = baseMapper.selectById(id); |
| | | KnowledgeInfo knowledgeInfo = baseMapper.selectOne(new LambdaQueryWrapper<KnowledgeInfo>() |
| | | .eq(KnowledgeInfo::getKid, id)); |
| | | check(knowledgeInfo); |
| | | map.put("kid",knowledgeInfo.getKid()); |
| | | // å é¤åéæ°æ® |
| | |
| | | return R.ok(trees); |
| | | } |
| | | |
| | | /** |
| | | * è·åé¨é¨ä¸çææç¨æ·ä¿¡æ¯ |
| | | */ |
| | | @SaCheckPermission("system:user:list") |
| | | @GetMapping("/list/dept/{deptId}") |
| | | public R<List<SysUserVo>> listByDeptId(@PathVariable Long deptId) { |
| | | List<SysUserVo> sysUserVos = userService.selectUserList(new SysUserBo()); |
| | | return R.ok(sysUserVos.stream() |
| | | .filter(user -> deptId.equals(user.getDeptId())) |
| | | .collect(Collectors.toList())); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project xmlns="http://maven.apache.org/POM/4.0.0" |
| | | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| | | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | <parent> |
| | | <groupId>org.ruoyi</groupId> |
| | | <artifactId>ruoyi-modules</artifactId> |
| | | <version>${revision}</version> |
| | | <relativePath>../pom.xml</relativePath> |
| | | </parent> |
| | | <artifactId>sc-page-designer</artifactId> |
| | | <description> |
| | | school-ai页é¢è®¾è®¡å¨æ¨¡å |
| | | </description> |
| | | |
| | | <dependencies> |
| | | <!-- éç¨å·¥å
·--> |
| | | <dependency> |
| | | <groupId>org.ruoyi</groupId> |
| | | <artifactId>ruoyi-common-core</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.ruoyi</groupId> |
| | | <artifactId>ruoyi-system-api</artifactId> |
| | | </dependency> |
| | | </dependencies> |
| | | </project> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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.PageDesigner; |
| | | import org.ruoyi.pageDesigner.domain.PageDesignerDTO; |
| | | import org.ruoyi.pageDesigner.domain.PageDesignerVo; |
| | | import org.ruoyi.pageDesigner.service.PageDesignerService; |
| | | 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") |
| | | public class PageDesignerController extends BaseController { |
| | | |
| | | private final PageDesignerService pageDesignerService; |
| | | |
| | | /** |
| | | * è·å页é¢è®¾è®¡å表 |
| | | */ |
| | | @GetMapping("/list") |
| | | public TableDataInfo<PageDesignerVo> list(PageDesignerDTO pageDesignerDTO, PageQuery pageQuery) { |
| | | return pageDesignerService.selectPagelistAll(pageDesignerDTO, pageQuery); |
| | | } |
| | | |
| | | /** |
| | | * è·å页é¢è®¾è®¡è¯¦æ
|
| | | */ |
| | | @GetMapping("/{id}") |
| | | public R<PageDesigner> getInfo(@PathVariable Long id) { |
| | | return R.ok(pageDesignerService.getDetail(id)); |
| | | } |
| | | |
| | | /** |
| | | * æ°å¢é¡µé¢è®¾è®¡ |
| | | */ |
| | | @PostMapping |
| | | public R<Void> add(@Valid @RequestBody PageDesignerDTO dto) { |
| | | pageDesignerService.add(dto); |
| | | return R.ok("æ°å¢æå"); |
| | | } |
| | | |
| | | /** |
| | | * ä¿®æ¹é¡µé¢è®¾è®¡ |
| | | */ |
| | | @PutMapping |
| | | public R<Void> update(@Valid @RequestBody PageDesignerDTO dto) { |
| | | pageDesignerService.updatePage(dto); |
| | | return R.ok("ä¿®æ¹æå"); |
| | | } |
| | | |
| | | /** |
| | | * å é¤é¡µé¢è®¾è®¡ |
| | | */ |
| | | @DeleteMapping |
| | | public R<Void> remove(@RequestBody List<Long> ids) { |
| | | pageDesignerService.deleteByIds(ids); |
| | | return R.ok("å 餿å"); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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("å 餿å"); |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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") |
| | | public class PageDesigner extends BaseEntity { |
| | | @TableId(value = "ID") |
| | | private Long id; |
| | | @TableField("NAME") |
| | | 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") |
| | | @TableLogic |
| | | private String delFlag; |
| | | @TableField("REMARK") |
| | | private String remark; |
| | | @TableField("FORM_JSON") |
| | | private String formJson; |
| | | @TableField("SHOW_COLUMN") |
| | | private String showColumn; // å¯ä»¥å° selectedFields åå¨ä¸º JSON å符串 |
| | | @TableField("ACTIONS_FUNC") |
| | | private String actionsFunc; // å¯ä»¥å° enableActions åå¨ä¸º JSON å符串 |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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 = PageDesigner.class, reverseConvertGenerate = false) |
| | | public class PageDesignerDTO extends BaseEntity { |
| | | private Long id; // ä¿®æ¹æ¶ä¼ å
¥ |
| | | private String name; // 页é¢åç§° |
| | | private String menuId; // å
³èèå ID |
| | | private String status; // å¯ç¨ç¶æ |
| | | private String remark; // 夿³¨ |
| | | private String formJson; // 表å设计 JSON å符串 |
| | | private String showColumn; // åæ®µæ¾ç¤ºé
ç½® |
| | | private String actionsFunc; // å¯ç¨çæä½é¡¹ï¼å¢å æ¹æ¥ï¼ |
| | | private String menuParentId; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.ruoyi.pageDesigner.domain; |
| | | |
| | | import io.github.linpeilie.annotations.AutoMapper; |
| | | import lombok.Data; |
| | | import org.ruoyi.system.domain.vo.SysMenuVo; |
| | | |
| | | import java.io.Serializable; |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * @author kanglujie |
| | | * @date 2025-06-23 17:23:35 |
| | | */ |
| | | @Data |
| | | @AutoMapper(target = PageDesigner.class) |
| | | public class PageDesignerVo implements Serializable { |
| | | private Long id; // ä¿®æ¹æ¶ä¼ å
¥ |
| | | private String name; // 页é¢åç§° |
| | | private String status; // å¯ç¨ç¶æ |
| | | private String remark; // 夿³¨ |
| | | private String menuParentId; // èåç¶ID |
| | | private Date createTime; // å建æ¶é´ |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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.PageDesigner; |
| | | import org.ruoyi.pageDesigner.domain.PageDesignerVo; |
| | | |
| | | /** |
| | | * @author kanglujie |
| | | * @date 2025-06-23 17:34:48 |
| | | */ |
| | | @Mapper |
| | | public interface PageDesignerMapper extends BaseMapper<PageDesigner> { |
| | | Page<PageDesignerVo> selectPagelistAll(@Param("page") Page<PageDesigner> page, @Param(Constants.WRAPPER) Wrapper<PageDesigner> queryWrapper); |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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); |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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.PageDesigner; |
| | | import org.ruoyi.pageDesigner.domain.PageDesignerDTO; |
| | | import org.ruoyi.pageDesigner.domain.PageDesignerVo; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author kanglujie |
| | | * @date 2025-06-23 17:35:56 |
| | | */ |
| | | public interface PageDesignerService extends IService<PageDesigner> { |
| | | |
| | | void add(PageDesignerDTO dto); |
| | | |
| | | void updatePage(PageDesignerDTO dto); |
| | | |
| | | List<PageDesigner> listAll(String keyword); |
| | | |
| | | PageDesigner getDetail(Long id); |
| | | |
| | | void deleteByIds(List<Long> ids); |
| | | |
| | | TableDataInfo<PageDesignerVo> selectPagelistAll(PageDesignerDTO pageDesignerDTO, PageQuery pageQuery); |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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); |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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 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.common.core.constant.UserConstants; |
| | | import org.ruoyi.common.core.utils.StreamUtils; |
| | | import org.ruoyi.common.core.utils.StringUtils; |
| | | import org.ruoyi.core.page.PageQuery; |
| | | import org.ruoyi.core.page.TableDataInfo; |
| | | import org.ruoyi.helper.DataBaseHelper; |
| | | import org.ruoyi.pageDesigner.domain.PageDesigner; |
| | | import org.ruoyi.pageDesigner.domain.PageDesignerDTO; |
| | | 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; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * @author kanglujie |
| | | * @date 2025-06-23 17:36:29 |
| | | */ |
| | | @Service |
| | | @RequiredArgsConstructor |
| | | public class PageDesignerServiceImpl extends ServiceImpl<PageDesignerMapper, PageDesigner> |
| | | implements PageDesignerService { |
| | | |
| | | 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(999); |
| | | 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); |
| | | menu.setPath(String.valueOf(entity.getId())); |
| | | 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 |
| | | public TableDataInfo<PageDesignerVo> selectPagelistAll(PageDesignerDTO pageDesignerDTO, PageQuery pageQuery) { |
| | | Page<PageDesignerVo> page = baseMapper.selectPagelistAll(pageQuery.build(), this.buildQueryWrapper(pageDesignerDTO)); |
| | | return TableDataInfo.build(page); |
| | | } |
| | | private Wrapper<PageDesigner> buildQueryWrapper(PageDesignerDTO pageDesignerDTO) { |
| | | 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")) |
| | | ; |
| | | return wrapper; |
| | | } |
| | | @Override |
| | | public List<PageDesigner> listAll(String keyword) { |
| | | LambdaQueryWrapper<PageDesigner> wrapper = new LambdaQueryWrapper<>(); |
| | | wrapper.like(keyword != null, PageDesigner::getName, keyword); |
| | | return this.list(wrapper); |
| | | } |
| | | |
| | | @Override |
| | | public PageDesigner getDetail(Long id) { |
| | | return this.getById(id); |
| | | } |
| | | |
| | | @Override |
| | | public void deleteByIds(List<Long> 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) { |
| | | PageDesigner entity = new PageDesigner(); |
| | | entity.setId(dto.getId()); |
| | | entity.setName(dto.getName()); |
| | | entity.setMenuId(dto.getMenuId()); |
| | | entity.setStatus(dto.getStatus()); |
| | | entity.setRemark(dto.getRemark()); |
| | | 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.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.common.core.constant.UserConstants; |
| | | 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(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 |
| | | 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; |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <?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.PageDesignerMapper"> |
| | | |
| | | <!-- å¤ç»æåµå¥èªå¨æ å°é另䏿¯ä¸ªå®ä½ç主é®id å¦åæ å°ä¼å¤±è´¥ --> |
| | | <resultMap type="org.ruoyi.pageDesigner.domain.PageDesignerVo" id="PageDesignerResult"> |
| | | <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="selectPagelistAll" resultMap="PageDesignerResult"> |
| | | select |
| | | id, |
| | | name, |
| | | status, |
| | | create_time, |
| | | menu_parent_id, |
| | | remark |
| | | from page_designer |
| | | ${ew.getCustomSqlSegment} |
| | | </select> |
| | | |
| | | |
| | | |
| | | |
| | | </mapper> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <?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> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project xmlns="http://maven.apache.org/POM/4.0.0" |
| | | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| | | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | <parent> |
| | | <groupId>org.ruoyi</groupId> |
| | | <artifactId>ruoyi-modules</artifactId> |
| | | <version>${revision}</version> |
| | | <relativePath>../pom.xml</relativePath> |
| | | </parent> |
| | | <artifactId>sc-services</artifactId> |
| | | <description> |
| | | school-aiä¸å¡æ¨¡å |
| | | </description> |
| | | |
| | | <dependencies> |
| | | <!-- éç¨å·¥å
·--> |
| | | <dependency> |
| | | <groupId>org.ruoyi</groupId> |
| | | <artifactId>ruoyi-common-core</artifactId> |
| | | </dependency> |
| | | </dependencies> |
| | | </project> |
| | |
| | | "@vben/utils": "workspace:*", |
| | | "@vueuse/core": "catalog:", |
| | | "ant-design-vue": "catalog:", |
| | | "axios": "^1.10.0", |
| | | "bpmn-js": "^18.6.2", |
| | | "cropperjs": "^1.6.2", |
| | | "crypto-js": "^4.2.0", |
| | | "dayjs": "catalog:", |
| | | "diagram-js": "^15.3.0", |
| | | "echarts": "^5.5.1", |
| | | "element-plus": "^2.10.2", |
| | | "jsencrypt": "^3.3.2", |
| | | "lodash-es": "^4.17.21", |
| | | "pinia": "catalog:", |
| | | "qs": "^6.13.1", |
| | | "tinymce": "^7.3.0", |
| | | "unplugin-vue-components": "^0.27.3", |
| | | "vue": "catalog:", |
¶Ô±ÈÐÂÎļþ |
| | |
| | | import { requestClient } from '#/api/request'; |
| | | import type { |
| | | PageDesigner |
| | | } from './model'; |
| | | |
| | | enum Api { |
| | | pageAdd = '/page-designer', |
| | | pageUpdate = '/page-designer', |
| | | pageList = '/page-designer/list', |
| | | pageInfo = '/page-designer', |
| | | pageRemove = '/page-designer', |
| | | } |
| | | |
| | | /** |
| | | * æ°å¢é¡µé¢è®¾è®¡ |
| | | */ |
| | | export function pageAdd(data: any) { |
| | | return requestClient.post(Api.pageAdd, data); |
| | | } |
| | | |
| | | /** |
| | | * ä¿®æ¹é¡µé¢è®¾è®¡ |
| | | */ |
| | | export function pageUpdate(data: any) { |
| | | return requestClient.put(Api.pageUpdate, data); |
| | | } |
| | | |
| | | /** |
| | | * è·å页é¢è®¾è®¡å表 |
| | | */ |
| | | export function pageList(params?: any) { |
| | | return requestClient.get<{ |
| | | total: number; |
| | | rows: PageDesigner[]; |
| | | code: number; |
| | | msg: string; |
| | | }>(Api.pageList, { params }); |
| | | } |
| | | |
| | | /** |
| | | * è·å页é¢è®¾è®¡è¯¦æ
|
| | | */ |
| | | export function pageInfo(id: string | number) { |
| | | return requestClient.get<PageDesigner>(`${Api.pageInfo}/${id}`); |
| | | } |
| | | |
| | | /** |
| | | * å é¤é¡µé¢è®¾è®¡ |
| | | */ |
| | | export function pageRemove(ids: string[] | number[]) { |
| | | return requestClient.delete(Api.pageRemove, { data: ids }); |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | export interface PageDesigner { |
| | | id?: string | number; // 主é®ï¼ç¼è¾æ¶ç¨ |
| | | name: string; // 页é¢åç§° |
| | | menuId: string | number | null; // ä¸çº§ç®å½ï¼èåIDï¼ |
| | | parentId: string | number | null; // ç¶çº§ID |
| | | status: string; // ç¶æ |
| | | remark?: string | null; // 夿³¨ |
| | | formJson?: string | null; // 表å设计JSON |
| | | showColumn?: string | null; // æ¾ç¤ºå段(JSONå符串) |
| | | actionsFunc?: string | null; // å¯ç¨åè½(JSONå符串) |
| | | createTime?: string; // å建æ¶é´ |
| | | updateTime?: string; // æ´æ°æ¶é´ |
| | | menu?: { // å
³èçèåä¿¡æ¯ |
| | | menuId: number; |
| | | menuName: string; |
| | | } | null; |
| | | parent?: { // å
³èçç¶çº§ä¿¡æ¯ |
| | | id: string | number; |
| | | name: string; |
| | | } | null; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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 }); |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | export interface Template { |
| | | id?: string | number; // ä¸»é® |
| | | formData: string; // 模çåç§° |
| | | pageDesignId: string | number; // å
³èç页é¢è®¾è®¡ID |
| | | createTime?: string; // å建æ¶é´ |
| | | updateTime?: string; // æ´æ°æ¶é´ |
| | | pageDesign?: { // å
³èç页é¢è®¾è®¡ä¿¡æ¯ |
| | | id: string | number; |
| | | name: string; |
| | | formJson?: string; |
| | | showColumn?: string; |
| | | actionsFunc?: string; |
| | | } | null; |
| | | } |
| | |
| | | import { router } from './router'; |
| | | import formCreate from '@form-create/element-ui'; |
| | | import FcDesigner from '@form-create/designer'; |
| | | import Antd from 'ant-design-vue'; |
| | | import 'ant-design-vue/dist/reset.css'; |
| | | async function bootstrap(namespace: string) { |
| | | |
| | | // åå§åç»ä»¶éé
å¨ |
| | | await initComponentAdapter(); |
| | | |
| | |
| | | app.use(ElementPlus); |
| | | app.use(formCreate); |
| | | app.use(FcDesigner); |
| | | app.use(Antd); |
| | | // å¨ææ´æ°æ é¢ |
| | | watchEffect(() => { |
| | | if (preferences.app.dynamicTitle) { |
¶Ô±ÈÐÂÎļþ |
| | |
| | | import type { VxeGridProps } from 'src/adapter/vxe-table'; |
| | | import type { FormSchemaGetter } from "src/adapter/form"; |
| | | |
| | | |
| | | export const querySchema: FormSchemaGetter = () => [ |
| | | { |
| | | component: 'Input', |
| | | fieldName: 'roleName', |
| | | label: 'åç§°', |
| | | }, |
| | | |
| | | { |
| | | component: 'Select', |
| | | fieldName: 'roleSort', |
| | | label: 'å建人', |
| | | }, |
| | | { |
| | | component: 'RangePicker', |
| | | fieldName: 'createTime', |
| | | label: 'å建æ¶é´', |
| | | }, |
| | | ]; |
| | | export const columns: VxeGridProps['columns'] = [ |
| | | { type: 'checkbox', width: 60 }, |
| | | { |
| | | title: 'åç§°', |
| | | field: 'roleName', |
| | | }, |
| | | { |
| | | title: 'å建人', |
| | | field: 'roleSort', |
| | | }, |
| | | { |
| | | title: 'å建æ¶é´', |
| | | field: 'createTime', |
| | | }, |
| | | { |
| | | field: 'action', |
| | | fixed: 'right', |
| | | slots: { default: 'action' }, |
| | | title: 'æä½', |
| | | width: 180, |
| | | }, |
| | | ]; |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <Page :auto-content-height="true"> |
| | | <BasicTable table-title="å·¥ä½èæ ¸ææ å表"> |
| | | <template #toolbar-tools> |
| | | <Space> |
| | | <a-button |
| | | v-access:code="['system:role:export']" |
| | | @click="handleDownloadExcel" |
| | | style="margin-right: 10px" |
| | | > |
| | | {{ $t('pages.common.export') }} |
| | | </a-button> |
| | | <a-button |
| | | type="primary" |
| | | v-access:code="['system:role:add']" |
| | | @click="handleAdd" |
| | | > |
| | | {{ $t('pages.common.add') }} |
| | | </a-button> |
| | | </Space> |
| | | </template> |
| | | </BasicTable> |
| | | </Page> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import type { VxeGridProps } from "#/adapter/vxe-table"; |
| | | import { useVbenVxeGrid, vxeCheckboxChecked } from '#/adapter/vxe-table'; |
| | | import type { VbenFormProps } from '@vben/common-ui'; |
| | | import type { roleList} from "#/api/system/role"; |
| | | import { columns, querySchema } from './data'; |
| | | import { Page, useVbenDrawer, useVbenModal } from '@vben/common-ui'; |
| | | 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', |
| | | // æ¥æéæ©æ ¼å¼å |
| | | fieldMappingTime: [ |
| | | [ |
| | | 'createTime', |
| | | ['params[beginTime]', 'params[endTime]'], |
| | | ['YYYY-MM-DD 00:00:00', 'YYYY-MM-DD 23:59:59'], |
| | | ], |
| | | ], |
| | | }; |
| | | const gridOptions: VxeGridProps = { |
| | | checkboxConfig: { |
| | | // é«äº® |
| | | highlight: true, |
| | | // 翻页æ¶ä¿çéä¸ç¶æ |
| | | reserve: true, |
| | | // ç¹å»è¡éä¸ |
| | | // trigger: 'row', |
| | | checkMethod: ({ row }) => row.roleId !== 1, |
| | | }, |
| | | columns, |
| | | height: 'auto', |
| | | keepSource: true, |
| | | pagerConfig: {}, |
| | | proxyConfig: { |
| | | ajax: { |
| | | query: async ({ page }, formValues = {}) => { |
| | | return await roleList({ |
| | | pageNum: page.currentPage, |
| | | pageSize: page.pageSize, |
| | | ...formValues, |
| | | }); |
| | | }, |
| | | }, |
| | | }, |
| | | rowConfig: { |
| | | keyField: 'roleId', |
| | | }, |
| | | id: 'system-role-index', |
| | | }; |
| | | const [BasicTable,tableApi] = useVbenVxeGrid({ |
| | | formOptions, |
| | | gridOptions, |
| | | }); |
| | | const handleAdd = () => { |
| | | console.log('æ°å¢') |
| | | } |
| | | const handleDownloadExcel = () => { |
| | | console.log('导åº') |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | |
| | | |
| | | <script> |
| | | import {modelInfo} from "#/api/system/model/index.js"; |
| | | import {pick} from "lodash-es"; |
| | | import {useVbenModal} from "@vben/common-ui"; |
| | | import {ref, computed} from "vue"; |
| | | import { $t } from '@vben/locales'; |
| | | const defaultValues = { |
| | | id: undefined, |
| | | name: undefined, |
| | | } |
| | | |
| | | const isUpdate = ref(false); |
| | | const title = computed(() => { |
| | | return isUpdate.value ? $t('ç¼è¾') : $t('æ°å¢'); |
| | | }); |
| | | const { validate, validateInfos, resetFields } = Form.useForm( |
| | | formData, |
| | | formRules, |
| | | ); |
| | | const [BasicModal, modalApi] = useVbenModal({ |
| | | class: 'w-[550px]', |
| | | fullscreenButton: false, |
| | | closeOnClickModal: false, |
| | | onClosed: handleCancel, |
| | | onConfirm: handleConfirm, |
| | | onOpenChange: async (isOpen) => { |
| | | if (!isOpen) { |
| | | return null; |
| | | } |
| | | modalApi.modalLoading(true); |
| | | |
| | | const { id } = modalApi.getData() as { id?: number | string }; |
| | | isUpdate.value = !!id; |
| | | |
| | | if (isUpdate.value && id) { |
| | | const record = await modelInfo(id); |
| | | // åªèµå¼åå¨çåæ®µ |
| | | const filterRecord = pick(record, Object.keys(defaultValues)); |
| | | formData.value = filterRecord; |
| | | } |
| | | |
| | | modalApi.modalLoading(false); |
| | | }, |
| | | }); |
| | | |
| | | |
| | | </script> |
| | | <template> |
| | | <BasicModal :title="title"> |
| | | <Form :label-col="{ span: 4 }"> |
| | | <FormItem label="åç§°" v-bind="validateInfos.name"> |
| | | <Input |
| | | v-model:value="formData.name" |
| | | :placeholder="$t('ui.formRules.required')" |
| | | /> |
| | | </FormItem> |
| | | </Form> |
| | | </BasicModal> |
| | | </template> |
| | | <style scoped> |
| | | |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="process-definition-container"> |
| | | <a-card title="æµç¨å®ä¹å表" :bordered="false"> |
| | | <div class="table-actions"> |
| | | <a-button type="primary" @click="showCreateModal">æ°å¢æµç¨å¾</a-button> |
| | | </div> |
| | | <a-table |
| | | :columns="columns" |
| | | :data-source="definitions" |
| | | :row-key="record => record.id" |
| | | :pagination="pagination" |
| | | :loading="loading" |
| | | @change="handleTableChange" |
| | | > |
| | | <template #bodyCell="{ column, record }"> |
| | | <template v-if="column.key === 'action'"> |
| | | <a-space> |
| | | <a-button type="link" @click="showDiagram(record)">æ¥ç</a-button> |
| | | <a-button type="link" @click="editDiagram(record)">ä¿®æ¹</a-button> |
| | | <a-button type="link" danger @click="deleteDefinition(record)">å é¤</a-button> |
| | | </a-space> |
| | | </template> |
| | | </template> |
| | | </a-table> |
| | | </a-card> |
| | | |
| | | <!-- æµç¨å¾æ¥çæ¨¡ææ¡ --> |
| | | <a-modal |
| | | v-model:visible="diagramVisible" |
| | | title="æµç¨å¾æ¥ç" |
| | | width="80%" |
| | | :footer="null" |
| | | @cancel="handleDiagramCancel" |
| | | > |
| | | <div style="text-align: center"> |
| | | <img |
| | | v-if="currentDiagramUrl" |
| | | :src="currentDiagramUrl" |
| | | alt="æµç¨å¾" |
| | | style="max-width: 100%" |
| | | /> |
| | | <a-skeleton v-else active /> |
| | | </div> |
| | | </a-modal> |
| | | |
| | | <!-- æµç¨å¾ç¼è¾æ¨¡ææ¡ --> |
| | | <a-modal |
| | | v-model:visible="editorVisible" |
| | | :title="editorTitle" |
| | | width="90%" |
| | | :maskClosable="false" |
| | | :okText="'ä¿å'" |
| | | :cancelText="'åæ¶'" |
| | | :confirmLoading="editorSaving" |
| | | @ok="handleEditorOk" |
| | | @cancel="handleEditorCancel" |
| | | :destroyOnClose="true" |
| | | :afterClose="handleEditorAfterClose" |
| | | :style="{ top: '20px' }" |
| | | :bodyStyle="{ |
| | | padding: '0', |
| | | height: 'calc(100vh - 100px)', |
| | | overflow: 'hidden', |
| | | display: 'flex', |
| | | flexDirection: 'column' |
| | | }" |
| | | > |
| | | <div class="editor-container"> |
| | | <div v-if="isCreateMode" class="create-form"> |
| | | <a-form layout="vertical"> |
| | | <a-form-item label="æµç¨åç§°" required> |
| | | <a-input v-model:value="newProcess.name" placeholder="请è¾å
¥æµç¨åç§°" /> |
| | | </a-form-item> |
| | | <a-form-item label="æµç¨Key" required> |
| | | <a-input v-model:value="newProcess.key" placeholder="请è¾å
¥æµç¨Key" /> |
| | | </a-form-item> |
| | | <a-form-item label="æµç¨æè¿°"> |
| | | <a-textarea v-model:value="newProcess.description" placeholder="请è¾å
¥æµç¨æè¿°" /> |
| | | </a-form-item> |
| | | </a-form> |
| | | </div> |
| | | <div class="bpmn-editor" ref="bpmnEditor"></div> |
| | | </div> |
| | | </a-modal> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted, nextTick } from 'vue' |
| | | import { message, Modal } from 'ant-design-vue' |
| | | import BpmnModeler from 'bpmn-js/lib/Modeler' |
| | | import 'bpmn-js/dist/assets/diagram-js.css' |
| | | import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css' |
| | | import 'bpmn-js/dist/assets/bpmn-js.css' |
| | | |
| | | // è¡¨æ ¼åå®ä¹ |
| | | const columns = [ |
| | | { |
| | | title: 'ID', |
| | | dataIndex: 'id', |
| | | key: 'id', |
| | | ellipsis: true |
| | | }, |
| | | { |
| | | title: 'åç§°', |
| | | dataIndex: 'name', |
| | | key: 'name' |
| | | }, |
| | | { |
| | | title: 'Key', |
| | | dataIndex: 'key', |
| | | key: 'key' |
| | | }, |
| | | { |
| | | title: 'æä½', |
| | | key: 'action', |
| | | } |
| | | ] |
| | | |
| | | // æ°æ®ç¶æ |
| | | const definitions = ref([]) |
| | | const loading = ref(false) |
| | | const pagination = ref({ |
| | | current: 1, |
| | | pageSize: 10, |
| | | total: 0, |
| | | showSizeChanger: true, |
| | | pageSizeOptions: ['10', '20', '50'] |
| | | }) |
| | | |
| | | // æµç¨å¾æ¥çç¸å
³ç¶æ |
| | | const diagramVisible = ref(false) |
| | | const currentDiagramUrl = ref('') |
| | | const currentProcessDefinition = ref(null) |
| | | |
| | | // æµç¨å¾ç¼è¾ç¸å
³ç¶æ |
| | | const editorVisible = ref(false) |
| | | const editorSaving = ref(false) |
| | | const editorTitle = ref('æµç¨å¾ç¼è¾') |
| | | const bpmnModeler = ref(null) |
| | | const bpmnEditor = ref(null) |
| | | const isCreateMode = ref(false) |
| | | const newProcess = ref({ |
| | | name: '', |
| | | key: '', |
| | | description: '' |
| | | }) |
| | | |
| | | // è·åæµç¨å®ä¹å表 |
| | | const fetchProcessDefinitions = async (params = {}) => { |
| | | loading.value = true |
| | | try { |
| | | // æ¨¡ææ°æ® |
| | | const mockData = [ |
| | | { id: '1', name: 'è¯·åæµç¨', key: 'leaveProcess'}, |
| | | { id: '2', name: 'æ¥éæµç¨', key: 'expenseProcess'}, |
| | | { id: '3', name: 'éè´æµç¨', key: 'purchaseProcess' } |
| | | ] |
| | | // 模æå页 |
| | | const start = (params.page - 1) * params.size |
| | | const end = start + params.size |
| | | definitions.value = mockData.slice(start, end) |
| | | pagination.value.total = mockData.length |
| | | } catch (error) { |
| | | message.error('å è½½æµç¨å®ä¹å¤±è´¥:'+ error.message) |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | |
| | | // è¡¨æ ¼å页/æåºååå¤ç |
| | | const handleTableChange = (pag, filters, sorter) => { |
| | | const params = { |
| | | page: pag.current, |
| | | size: pag.pageSize |
| | | } |
| | | |
| | | if (sorter.field) { |
| | | params.sort = sorter.field |
| | | params.order = sorter.order === 'ascend' ? 'asc' : 'desc' |
| | | } |
| | | |
| | | fetchProcessDefinitions(params) |
| | | } |
| | | |
| | | // æ¾ç¤ºæµç¨å¾ |
| | | const showDiagram = (record) => { |
| | | currentProcessDefinition.value = record |
| | | currentDiagramUrl.value = `https://via.placeholder.com/800x600?text=æµç¨å¾+${record.id}` |
| | | diagramVisible.value = true |
| | | } |
| | | |
| | | // 鿝BPMNç¼è¾å¨ |
| | | const destroyBpmnEditor = () => { |
| | | if (bpmnModeler.value) { |
| | | bpmnModeler.value.destroy() |
| | | bpmnModeler.value = null |
| | | } |
| | | } |
| | | |
| | | // åå§åBPMNç¼è¾å¨ |
| | | const initBpmnEditor = async (xml) => { |
| | | await nextTick() |
| | | |
| | | // å
鿝æ§çç¼è¾å¨ |
| | | destroyBpmnEditor() |
| | | |
| | | try { |
| | | // å建æ°çç¼è¾å¨å®ä¾ |
| | | bpmnModeler.value = new BpmnModeler({ |
| | | container: bpmnEditor.value, |
| | | }) |
| | | |
| | | // å è½½XMLæé»è®¤æµç¨å¾ |
| | | const diagram = xml || ` |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <bpmn:definitions |
| | | xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" |
| | | xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" |
| | | xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" |
| | | xmlns:di="http://www.omg.org/spec/DD/20100524/DI" |
| | | id="Definitions_1" |
| | | targetNamespace="http://bpmn.io/schema/bpmn"> |
| | | <bpmn:process id="Process_1" isExecutable="false"> |
| | | <bpmn:startEvent id="StartEvent_1" /> |
| | | </bpmn:process> |
| | | <bpmndi:BPMNDiagram id="BPMNDiagram_1"> |
| | | <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1"> |
| | | <bpmndi:BPMNShape id="StartEvent_1_di" bpmnElement="StartEvent_1"> |
| | | <dc:Bounds x="173" y="102" width="36" height="36" /> |
| | | </bpmndi:BPMNShape> |
| | | </bpmndi:BPMNPlane> |
| | | </bpmndi:BPMNDiagram> |
| | | </bpmn:definitions> |
| | | ` |
| | | |
| | | await bpmnModeler.value.importXML(diagram) |
| | | } catch (err) { |
| | | console.error('Error rendering diagram', err) |
| | | message.error('åå§åæµç¨å¾ç¼è¾å¨å¤±è´¥: ' + err.message) |
| | | } |
| | | } |
| | | |
| | | // æ¾ç¤ºåå»ºæ°æµç¨æ¨¡ææ¡ |
| | | const showCreateModal = () => { |
| | | isCreateMode.value = true |
| | | editorTitle.value = 'åå»ºæ°æµç¨å¾' |
| | | editorVisible.value = true |
| | | |
| | | // é置表å |
| | | newProcess.value = { |
| | | name: '', |
| | | key: '', |
| | | description: '' |
| | | } |
| | | |
| | | // åå§åç¼è¾å¨ |
| | | initBpmnEditor() |
| | | } |
| | | |
| | | // ç¼è¾æµç¨å¾ |
| | | const editDiagram = async (record) => { |
| | | isCreateMode.value = false |
| | | currentProcessDefinition.value = record |
| | | editorTitle.value = `ç¼è¾æµç¨ - ${record.name}` |
| | | editorVisible.value = true |
| | | |
| | | // 模æå è½½æµç¨å®ä¹XML |
| | | const mockXml = ` |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <bpmn:definitions |
| | | xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" |
| | | xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" |
| | | xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" |
| | | xmlns:di="http://www.omg.org/spec/DD/20100524/DI" |
| | | id="Definitions_1" |
| | | targetNamespace="http://bpmn.io/schema/bpmn"> |
| | | <bpmn:process id="${record.id}" name="${record.name}" isExecutable="true"> |
| | | <bpmn:startEvent id="StartEvent_1" name="å¼å§" /> |
| | | <bpmn:userTask id="UserTask_1" name="æäº¤ç³è¯·" /> |
| | | <bpmn:sequenceFlow id="Flow_1" sourceRef="StartEvent_1" targetRef="UserTask_1" /> |
| | | <bpmn:endEvent id="EndEvent_1" name="ç»æ" /> |
| | | <bpmn:sequenceFlow id="Flow_2" sourceRef="UserTask_1" targetRef="EndEvent_1" /> |
| | | </bpmn:process> |
| | | <bpmndi:BPMNDiagram id="BPMNDiagram_1"> |
| | | <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="${record.id}"> |
| | | <bpmndi:BPMNShape id="StartEvent_1_di" bpmnElement="StartEvent_1"> |
| | | <dc:Bounds x="173" y="102" width="36" height="36" /> |
| | | </bpmndi:BPMNShape> |
| | | <bpmndi:BPMNShape id="UserTask_1_di" bpmnElement="UserTask_1"> |
| | | <dc:Bounds x="280" y="80" width="100" height="80" /> |
| | | </bpmndi:BPMNShape> |
| | | <bpmndi:BPMNShape id="EndEvent_1_di" bpmnElement="EndEvent_1"> |
| | | <dc:Bounds x="450" y="102" width="36" height="36" /> |
| | | </bpmndi:BPMNShape> |
| | | <bpmndi:BPMNEdge id="Flow_1_di" bpmnElement="Flow_1"> |
| | | <di:waypoint x="209" y="120" /> |
| | | <di:waypoint x="280" y="120" /> |
| | | </bpmndi:BPMNEdge> |
| | | <bpmndi:BPMNEdge id="Flow_2_di" bpmnElement="Flow_2"> |
| | | <di:waypoint x="380" y="120" /> |
| | | <di:waypoint x="450" y="120" /> |
| | | </bpmndi:BPMNEdge> |
| | | </bpmndi:BPMNPlane> |
| | | </bpmndi:BPMNDiagram> |
| | | </bpmn:definitions> |
| | | ` |
| | | |
| | | // åå§åç¼è¾å¨å¹¶å è½½XML |
| | | initBpmnEditor(mockXml) |
| | | } |
| | | |
| | | // ä¿åæµç¨å¾ä¿®æ¹ |
| | | const handleEditorOk = async () => { |
| | | editorSaving.value = true |
| | | |
| | | try { |
| | | if (isCreateMode.value) { |
| | | // éªè¯è¡¨å |
| | | if (!newProcess.value.name || !newProcess.value.key) { |
| | | message.error('è¯·å¡«åæµç¨åç§°åKey') |
| | | return |
| | | } |
| | | |
| | | // è·åXML |
| | | const { xml } = await bpmnModeler.value.saveXML({ format: true }) |
| | | console.log('æ°æµç¨XML:', xml) |
| | | |
| | | // 模æåå»ºæ°æµç¨ |
| | | await new Promise(resolve => setTimeout(resolve, 1000)) |
| | | |
| | | // æ·»å å°å表 |
| | | const newId = Math.max(...definitions.value.map(d => parseInt(d.id))) + 1 |
| | | definitions.value.unshift({ |
| | | id: newId.toString(), |
| | | name: newProcess.value.name, |
| | | key: newProcess.value.key, |
| | | version: 1 |
| | | }) |
| | | |
| | | message.success('æ°æµç¨å建æå') |
| | | } else { |
| | | // è·åä¿®æ¹åçXML |
| | | const { xml } = await bpmnModeler.value.saveXML({ format: true }) |
| | | console.log('ä¿®æ¹åçXML:', xml) |
| | | |
| | | // 模æä¿å |
| | | await new Promise(resolve => setTimeout(resolve, 1000)) |
| | | |
| | | message.success('æµç¨å¾ä¿åæå') |
| | | } |
| | | |
| | | editorVisible.value = false |
| | | } catch (error) { |
| | | console.error('Error saving BPMN diagram', error) |
| | | message.error('æä½å¤±è´¥: ' + error.message) |
| | | } finally { |
| | | editorSaving.value = false |
| | | } |
| | | } |
| | | |
| | | // å 餿µç¨å®ä¹ |
| | | const deleteDefinition = (record) => { |
| | | Modal.confirm({ |
| | | title: '确认å 餿µç¨?', |
| | | content: `ç¡®å®è¦å 餿µç¨ "${record.name}" åï¼æ¤æä½ä¸å¯æ¢å¤ã`, |
| | | okText: '确认', |
| | | okType: 'danger', |
| | | cancelText: 'åæ¶', |
| | | onOk() { |
| | | // 模æå é¤ |
| | | definitions.value = definitions.value.filter(item => item.id !== record.id) |
| | | message.success('æµç¨å 餿å') |
| | | } |
| | | }) |
| | | } |
| | | |
| | | // æ¨¡ææ¡å
³é忏
ç |
| | | const handleEditorAfterClose = () => { |
| | | destroyBpmnEditor() |
| | | } |
| | | |
| | | const handleEditorCancel = () => { |
| | | editorVisible.value = false |
| | | } |
| | | |
| | | const handleDiagramCancel = () => { |
| | | diagramVisible.value = false |
| | | } |
| | | |
| | | // åå§åå è½½æ°æ® |
| | | onMounted(() => { |
| | | const params = { |
| | | page: 1, |
| | | size: 10 |
| | | } |
| | | fetchProcessDefinitions(params) |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .process-definition-container { |
| | | padding: 20px; |
| | | background: #fff; |
| | | } |
| | | |
| | | .table-actions { |
| | | margin-bottom: 16px; |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | } |
| | | |
| | | .editor-container { |
| | | height: 600px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | .bpmn-editor { |
| | | flex: 1; |
| | | border: 1px solid #d9d9d9; |
| | | border-radius: 2px; |
| | | margin-top: 16px; |
| | | min-height: 500px; /* ç¡®ä¿ç¼è¾å¨æè¶³å¤é«åº¦ */ |
| | | } |
| | | |
| | | .create-form { |
| | | padding: 16px; |
| | | background: #fafafa; |
| | | border-radius: 2px; |
| | | border: 1px solid #d9d9d9; |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | /* éèBPMNæ°´å° */ |
| | | .bpmn-editor :deep(.bjs-powered-by) { |
| | | display: none !important; |
| | | } |
| | | .editor-container { |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | height: 100%; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .bpmn-editor { |
| | | flex: 1; |
| | | min-height: 0; /* éè¦ï¼å
许flex容卿¶ç¼© */ |
| | | border: 1px solid #d9d9d9; |
| | | border-radius: 2px; |
| | | margin-top: 16px; |
| | | } |
| | | |
| | | .create-form { |
| | | padding: 16px; |
| | | background: #fafafa; |
| | | border-radius: 2px; |
| | | border: 1px solid #d9d9d9; |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | /* éèBPMNæ°´å° */ |
| | | .bpmn-editor :deep(.bjs-powered-by) { |
| | | display: none !important; |
| | | } |
| | | |
| | | /* ç¡®ä¿BPMNå·¥å
·æ å¯è§ */ |
| | | .bpmn-editor :deep(.djs-palette) { |
| | | top: 20px; |
| | | left: 20px; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <fc-designer ref="designer" /> |
| | | <fc-designer ref="designer" :config="config" @save="handleSave" /> |
| | | </template> |
| | | |
| | | <script setup> |
| | |
| | | const loadJson = (json) => { |
| | | designer.value.setJson(json); |
| | | }; |
| | | const config = ref({ |
| | | showSaveBtn: true, |
| | | showPreviewBtn: true, |
| | | }); |
| | | function handleSave(data) { |
| | | //ä¿å设计è§å |
| | | console.log(data); |
| | | } |
| | | </script> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | import type { FormSchemaGetter } from '#/adapter/form'; |
| | | import type { VxeGridProps } from '#/adapter/vxe-table'; |
| | | import { h } from 'vue'; |
| | | import { FolderIcon, VbenIcon } from '@vben/icons'; |
| | | |
| | | export const querySchema: FormSchemaGetter = () => [ |
| | | { |
| | | component: 'Input', |
| | | fieldName: 'name', |
| | | label: '页é¢åç§°', |
| | | }, |
| | | { |
| | | component: 'Select', |
| | | componentProps: { |
| | | options: [ |
| | | { label: 'æ£å¸¸', value: '0' }, |
| | | { label: 'åç¨', value: '1' }, |
| | | ], |
| | | }, |
| | | fieldName: 'status', |
| | | label: '页é¢ç¶æ', |
| | | }, |
| | | ]; |
| | | |
| | | export const columns: VxeGridProps['columns'] = [ |
| | | { |
| | | title: '页é¢åç§°', |
| | | field: 'name', |
| | | }, |
| | | { |
| | | title: 'ä¸çº§ç®å½', |
| | | field: 'menuParentName', |
| | | |
| | | }, |
| | | { |
| | | title: 'ç¶æ', |
| | | field: 'status', |
| | | slots: { |
| | | default: ({ row }) => { |
| | | return row.status === '0' ? 'æ£å¸¸' : 'åç¨'; |
| | | }, |
| | | }, |
| | | }, |
| | | { |
| | | title: 'å建æ¶é´', |
| | | field: 'createTime', |
| | | }, |
| | | { |
| | | field: 'action', |
| | | fixed: 'right', |
| | | slots: { default: 'action' }, |
| | | title: 'æä½', |
| | | }, |
| | | ]; |
| | | |
| | | export const drawerSchema = () => [ |
| | | { |
| | | component: 'Input', |
| | | fieldName: 'name', |
| | | label: '页é¢åç§°', |
| | | rules: 'required', |
| | | }, |
| | | { |
| | | component: 'TreeSelect', |
| | | fieldName: 'menuParentId', |
| | | label: 'ä¸çº§ç®å½', |
| | | componentProps: { |
| | | allowClear: true, |
| | | showSearch: true, |
| | | }, |
| | | rules: 'selectRequired', |
| | | }, |
| | | { |
| | | component: 'Select', |
| | | fieldName: 'status', |
| | | label: 'ç¶æ', |
| | | componentProps: { |
| | | options: [ |
| | | { label: 'æ£å¸¸', value: '0' }, |
| | | { label: 'åç¨', value: '1' }, |
| | | ], |
| | | }, |
| | | rules: 'selectRequired', |
| | | }, |
| | | { |
| | | component: 'CheckboxGroup', |
| | | fieldName: 'actionsFunc', |
| | | label: 'å¯ç¨åè½', |
| | | defaultValue: ['add', 'edit', 'delete', 'query'], |
| | | componentProps: { |
| | | options: [ |
| | | { label: 'æ°å¢', value: 'add' }, |
| | | { label: 'ç¼è¾', value: 'edit' }, |
| | | { label: 'å é¤', value: 'delete' }, |
| | | { label: 'æ¥è¯¢', value: 'query' }, |
| | | ], |
| | | }, |
| | | rules: 'required', |
| | | }, |
| | | { |
| | | component: 'Input', |
| | | fieldName: 'remark', |
| | | label: '夿³¨', |
| | | componentProps: { |
| | | type: 'textarea', |
| | | rows: 2, |
| | | }, |
| | | }, |
| | | ]; |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <Page v-if="isAdmin" :auto-content-height="true"> |
| | | <BasicTable table-title="页é¢è®¾è®¡å¨" > |
| | | <template #toolbar-tools> |
| | | <Space> |
| | | <a-button type="primary" @click="handleAdd">æ°å¢</a-button> |
| | | </Space> |
| | | </template> |
| | | <template #action="{ row }"> |
| | | <Space> |
| | | <ghost-button @click="handleEdit(row)">ç¼è¾</ghost-button> |
| | | <Popconfirm :get-popup-container="getVxePopupContainer" placement="left" title="确认å é¤ï¼" @confirm="handleDelete(row)"> |
| | | <ghost-button danger @click.stop="">å é¤</ghost-button> |
| | | </Popconfirm> |
| | | </Space> |
| | | </template> |
| | | </BasicTable> |
| | | <PageDrawer ref="pageModalRef" @reload="tableApi.query()" :menu-array="menuArray" /> |
| | | </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 } from 'vue'; |
| | | import { useAccess } from '@vben/access'; |
| | | import { Fallback, Page, useVbenDrawer } from '@vben/common-ui'; |
| | | import { eachTree, getVxePopupContainer } from '@vben/utils'; |
| | | import { Popconfirm, Space } from 'ant-design-vue'; |
| | | import { useVbenVxeGrid } from '#/adapter/vxe-table'; |
| | | import { columns, querySchema } from './data'; |
| | | import PageDrawer from './page-drawer.vue'; |
| | | import FcDesigner from '@form-create/designer'; |
| | | import { pageList, pageRemove } from '#/api/tool/page-designer'; |
| | | import { menuList } from '../../../api/system/menu'; |
| | | import { listToTree} from '@vben/utils'; |
| | | // ç§»é¤mockæ°æ® |
| | | // const pageList = async (params: any) => { ... }; |
| | | // const pageRemove = async (ids: number[]) => {}; |
| | | const menuArray = ref([]); |
| | | const processedMenuTree = ref([]); |
| | | onMounted(async () => { |
| | | try { |
| | | // è·ååå§èåæ°æ® |
| | | const rawMenuData = await menuList(); |
| | | menuArray.value = rawMenuData; |
| | | |
| | | // å¤çèåæ°æ® |
| | | processMenuData(); |
| | | } catch (error) { |
| | | console.error('è·åèåæ°æ®å¤±è´¥:', error); |
| | | } |
| | | }); |
| | | // å¤çèåæ°æ®ç彿° |
| | | const processMenuData = () => { |
| | | if (!menuArray.value || menuArray.value.length === 0) return; |
| | | |
| | | // 1. è¿æ»¤ææé®ç±»å(F)åèåç±»å(C) |
| | | const filteredList = menuArray.value.filter(item => |
| | | item.menuType !== 'F' && item.menuType !== 'C' |
| | | ); |
| | | |
| | | // 2. 转æ¢ä¸ºæ å½¢ç»æ |
| | | const treeData = listToTree(filteredList, { |
| | | id: 'menuId', |
| | | pid: 'parentId' |
| | | }); |
| | | |
| | | // 3. æ·»å æ ¹èç¹ |
| | | processedMenuTree.value = [ |
| | | { |
| | | menuId: 0, |
| | | parentId: 0, |
| | | menuName: 'æ ¹ç®å½', |
| | | children: treeData |
| | | } |
| | | ]; |
| | | }; |
| | | 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 getFullMenuPath = (id: number) => { |
| | | if (!processedMenuTree.value || processedMenuTree.value.length === 0) return ''; |
| | | |
| | | // é彿¥æ¾èåè·¯å¾ |
| | | const findPath = (tree, currentId, path = []): string[] | null => { |
| | | for (const item of tree) { |
| | | if (item.menuId === currentId) { |
| | | return [...path, item.menuName]; |
| | | } |
| | | if (item.children && item.children.length > 0) { |
| | | const found = findPath(item.children, currentId, [...path, item.menuName]); |
| | | if (found) return found; |
| | | } |
| | | } |
| | | return null; |
| | | }; |
| | | |
| | | const path = findPath(processedMenuTree.value, id); |
| | | return path ? path.join(' / ') : 'æ ¹ç®å½'; |
| | | }; |
| | | const gridOptions: VxeGridProps = { |
| | | columns, |
| | | height: 'auto', |
| | | keepSource: true, |
| | | pagerConfig: { |
| | | enabled: true, |
| | | }, |
| | | proxyConfig: { |
| | | ajax: { |
| | | query: async ({ page }, formValues = {}) => { |
| | | const resp = await pageList({ |
| | | pageNum: page.currentPage, |
| | | pageSize: page.pageSize, |
| | | ...formValues, |
| | | }); |
| | | |
| | | // å¤çè¿åæ°æ®ï¼æ·»å menuParentName |
| | | const processedRows = resp.rows.map(row => { |
| | | return { |
| | | ...row, |
| | | menuParentName: getFullMenuPath(row.menuParentId) || 'æ ¹ç®å½' |
| | | }; |
| | | }); |
| | | return { |
| | | rows: processedRows, // 使ç¨å¤çåçæ°æ® |
| | | total: resp.total, |
| | | }; |
| | | }, |
| | | }, |
| | | }, |
| | | rowConfig: { |
| | | keyField: 'id', |
| | | }, |
| | | id: 'tool-page-designer-index', |
| | | columnConfig: { resizable: true }, |
| | | }; |
| | | |
| | | const [BasicTable, tableApi] = useVbenVxeGrid({ |
| | | formOptions, |
| | | gridOptions, |
| | | }); |
| | | |
| | | const designer = ref(); |
| | | const pageModalRef = ref(); |
| | | |
| | | function getFormJson() { |
| | | // è·åè®¾è®¡ç»æ |
| | | const json = designer.value.getRule(); |
| | | // ä½ å¯ä»¥å° json åå°å端 |
| | | } |
| | | |
| | | function setFormJson(json) { |
| | | // å 载已æè®¾è®¡ |
| | | designer.value.setRule(json); |
| | | } |
| | | |
| | | function handleAdd() { |
| | | pageModalRef.value.open({ update: false }); |
| | | } |
| | | |
| | | function handleEdit(record) { |
| | | pageModalRef.value.open({ id: record.id, update: true }); |
| | | } |
| | | |
| | | async function handleDelete(row: any) { |
| | | await pageRemove([row.id]); |
| | | await tableApi.query(); |
| | | } |
| | | |
| | | function handleSubAdd(row) { |
| | | pageModalRef.value.open({ id: row.id, update: false }); |
| | | } |
| | | |
| | | const { hasAccessByRoles } = useAccess(); |
| | | const isAdmin = computed(() => { |
| | | return hasAccessByRoles(['admin', 'superadmin']); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .designer-page { |
| | | background: #f5f6fa; |
| | | padding: 16px; |
| | | min-height: 100vh; |
| | | } |
| | | .designer-query-form { |
| | | background: #fff; |
| | | padding: 16px 16px 0 16px; |
| | | border-radius: 6px; |
| | | margin-bottom: 12px; |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | align-items: center; |
| | | } |
| | | .designer-toolbar { |
| | | background: #fff; |
| | | padding: 12px 16px; |
| | | border-radius: 6px; |
| | | margin-bottom: 12px; |
| | | display: flex; |
| | | gap: 8px; |
| | | } |
| | | .designer-table { |
| | | background: #fff; |
| | | border-radius: 6px; |
| | | padding: 0 0 16px 0; |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <script setup lang="ts"> |
| | | import { computed, ref, watch, nextTick, onMounted } from 'vue'; |
| | | import { Modal, message, FormItem } from 'ant-design-vue'; |
| | | import { $t } from '@vben/locales'; |
| | | import { useVbenForm } from '#/adapter/form'; |
| | | import { drawerSchema } from './data'; |
| | | import FcDesigner from '@form-create/designer'; |
| | | |
| | | import { listToTree, addFullName, getPopupContainer } from '@vben/utils'; |
| | | import { pageAdd, pageUpdate, pageInfo } from '#/api/tool/page-designer'; |
| | | |
| | | interface ModalProps { |
| | | id?: number | string; |
| | | update: boolean; |
| | | } |
| | | |
| | | |
| | | const emit = defineEmits<{ reload: [] }>(); |
| | | |
| | | const isUpdate = ref(false); |
| | | const title = computed(() => { |
| | | return isUpdate.value ? $t('pages.common.edit') : $t('pages.common.add'); |
| | | }); |
| | | |
| | | const [BasicForm, formApi] = useVbenForm({ |
| | | commonConfig: { |
| | | componentProps: { |
| | | class: 'w-full', |
| | | }, |
| | | formItemClass: 'col-span-1', |
| | | labelWidth: 90, |
| | | }, |
| | | schema: drawerSchema(), |
| | | showDefaultActions: false, |
| | | wrapperClass: 'grid-cols-5', |
| | | }); |
| | | |
| | | const designer = ref(); |
| | | const selectedFields = ref([]); // å¤éæ¡éä¸çåæ®µkey |
| | | const fieldOptions = ref([]); // è®¾è®¡åºææå段 |
| | | const modalVisible = ref(false); |
| | | const modalLoading = ref(false); |
| | | const currentEditId = ref<string | number>(''); // å½åç¼è¾çID |
| | | const fullMenuTree = ref([]); |
| | | const props=defineProps({ |
| | | menuArray: { |
| | | type: Array, |
| | | required: true, |
| | | default: () => [] |
| | | } |
| | | }); |
| | | // æå¼å¼¹çª |
| | | const open = async (params: ModalProps = { update: false }) => { |
| | | try { |
| | | |
| | | modalVisible.value = true; |
| | | modalLoading.value = true; |
| | | isUpdate.value = params.update; |
| | | currentEditId.value = params.id || ''; // ä¿åå½åç¼è¾çID |
| | | await setupPageSelect(); |
| | | |
| | | if (params.id) { |
| | | await formApi.setFieldValue('menuParentId', params.id); |
| | | if (params.update) { |
| | | // è·å详æ
æ°æ® |
| | | const record = await pageInfo(params.id); |
| | | |
| | | // 设置åºç¡è¡¨åæ°æ® |
| | | const menuParentId = String(record.menuParentId || record.parentId || ''); |
| | | await formApi.setValues({ |
| | | name: record.name, |
| | | menuParentId: menuParentId, // ç¨ menuParentId åæ®µ |
| | | status: record.status, |
| | | remark: record.remark, |
| | | actionsFunc: record.actionsFunc ? JSON.parse(record.actionsFunc) : ['add', 'edit', 'delete', 'query'] |
| | | }); |
| | | |
| | | // å 载表åè®¾è®¡æ°æ® |
| | | if (record.formJson) { |
| | | try { |
| | | const formRule = JSON.parse(record.formJson); |
| | | console.log('设计å¨è§å:', formRule); |
| | | designer.value.setRule(formRule); |
| | | |
| | | // æ´æ°å段é项 |
| | | await nextTick(); |
| | | updateFieldOptions(); |
| | | |
| | | // æ¢å¤éä¸çåæ®µ |
| | | if (record.showColumn) { |
| | | selectedFields.value = JSON.parse(record.showColumn); |
| | | } |
| | | } catch (e) { |
| | | console.error('å 载表åè®¾è®¡æ°æ®å¤±è´¥:', e); |
| | | message.error('å 载表åè®¾è®¡æ°æ®å¤±è´¥'); |
| | | } |
| | | } |
| | | } |
| | | } else { |
| | | // æ°å¢æ¶éç½®æ°æ® |
| | | designer.value?.setRule([]); |
| | | selectedFields.value = []; |
| | | await formApi.resetForm(); |
| | | } |
| | | } catch (error) { |
| | | console.error('æå¼å¼¹çªå¤±è´¥:', error); |
| | | message.error('å è½½æ°æ®å¤±è´¥'); |
| | | } finally { |
| | | modalLoading.value = false; |
| | | } |
| | | }; |
| | | const close = () => { |
| | | modalVisible.value = false; |
| | | }; |
| | | |
| | | defineExpose({ open, close }); |
| | | |
| | | async function setupPageSelect() { |
| | | // è·åèåæ°æ® |
| | | if (!props.menuArray || props.menuArray.length === 0) { |
| | | await nextTick(); // çå¾
å¯è½ç弿¥å è½½ |
| | | if (!props.menuArray || props.menuArray.length === 0) { |
| | | console.warn('menuArray is empty'); |
| | | return; |
| | | } |
| | | } |
| | | // è¿æ»¤ææé®ç±»å |
| | | const filteredList = props.menuArray.filter(item => item.menuType !== 'F' && item.menuType !== 'C'); |
| | | // æ¯æi18n |
| | | filteredList.forEach(item => { item.menuName = $t(item.menuName); }); |
| | | // 转为æ ç»æ |
| | | const menuTree = listToTree(filteredList, { id: 'menuId', pid: 'parentId' }); |
| | | // é彿 å° 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: mapMenuIdToParentId(menuTree), |
| | | }, |
| | | ]; |
| | | // çæå
¨è·¯å¾å |
| | | addFullName(fullMenuTree.value, 'menuName', ' / '); |
| | | |
| | | formApi.updateSchema([ |
| | | { |
| | | componentProps: { |
| | | fieldNames: { |
| | | label: 'menuName', |
| | | value: 'menuId', // ç¨ menuId |
| | | children: 'children' |
| | | }, |
| | | getPopupContainer, |
| | | listHeight: 300, |
| | | showSearch: true, |
| | | treeData: fullMenuTree.value, |
| | | treeDefaultExpandAll: false, |
| | | treeDefaultExpandedKeys: [0], |
| | | treeLine: { showLeafIcon: false }, |
| | | treeNodeFilterProp: 'menuName', |
| | | treeNodeLabelProp: 'fullName', |
| | | }, |
| | | fieldName: 'menuParentId', // ç¨ menuParentId |
| | | }, |
| | | ]); |
| | | } |
| | | |
| | | |
| | | // 忥ææå段å°éä¸ç¶æ |
| | | const syncAllFields = () => { |
| | | // è·å表åç»ä»¶çè§åæè¿° |
| | | const formDesc = designer.value?.getFormDescription?.(); |
| | | |
| | | if (!formDesc || !Array.isArray(formDesc)) { |
| | | message.warning('ææ è®¾è®¡æ°æ®'); |
| | | return; |
| | | } |
| | | |
| | | // æååæ®µä¿¡æ¯ |
| | | const allFields = formDesc |
| | | .filter(item => item && item.field && item.title) |
| | | .map(item => ({ |
| | | title: item.title, |
| | | field: item.field |
| | | })); |
| | | |
| | | |
| | | if (allFields.length === 0) { |
| | | message.warning('æªæ¾å°å¯ç¨å段'); |
| | | return; |
| | | } |
| | | |
| | | // æ´æ°å段é项 |
| | | fieldOptions.value = allFields.map(item => ({ |
| | | label: item.title, |
| | | value: item.field |
| | | })); |
| | | |
| | | // é䏿æå段 |
| | | selectedFields.value = allFields.map(item => item.field); |
| | | message.success(`已忥 ${allFields.length} ä¸ªåæ®µ`); |
| | | }; |
| | | |
| | | // å¤ç设计å¨åå |
| | | const handleDesignerChange = () => { |
| | | nextTick(() => { |
| | | updateFieldOptions(); |
| | | }); |
| | | }; |
| | | |
| | | // å½è®¾è®¡å¨å
容ååæ¶æ´æ°å段é项 |
| | | const updateFieldOptions = () => { |
| | | // è·å表åç»ä»¶çè§åæè¿° |
| | | const formDesc = designer.value?.getFormDescription?.(); |
| | | if (!formDesc || !Array.isArray(formDesc)) return; |
| | | |
| | | const fields = formDesc |
| | | .filter(item => item && item.field && item.title) |
| | | .map(item => ({ |
| | | title: item.title, |
| | | field: item.field |
| | | })); |
| | | |
| | | fieldOptions.value = fields.map(item => ({ |
| | | label: item.title, |
| | | value: item.field |
| | | })); |
| | | }; |
| | | |
| | | // çå¬è®¾è®¡å¨å
容åå |
| | | watch(() => modalVisible.value, (val) => { |
| | | if (val) { |
| | | nextTick(() => updateFieldOptions()); |
| | | } |
| | | }); |
| | | |
| | | async function handleOk() { |
| | | try { |
| | | modalLoading.value = true; |
| | | const { valid } = await formApi.validate(); |
| | | if (!valid) { |
| | | return; |
| | | } |
| | | const data = await formApi.getValues(); |
| | | |
| | | // 妿æ¯ç¼è¾æ¨¡å¼ï¼æ·»å idåæ®µ |
| | | if (isUpdate.value) { |
| | | data.id = currentEditId.value; |
| | | } |
| | | |
| | | // è·å表å设计 JSON |
| | | data.formJson = designer.value.getJson(); |
| | | // æ·»å éä¸çåæ®µ |
| | | data.showColumn = JSON.stringify(selectedFields.value); |
| | | // 转æ¢å¯ç¨åè½ä¸ºJSONå符串 |
| | | data.actionsFunc = JSON.stringify(data.actionsFunc); |
| | | |
| | | // 忥䏿¬¡å段å¤é |
| | | updateFieldOptions(); |
| | | await (isUpdate.value ? pageUpdate(data) : pageAdd(data)); |
| | | emit('reload'); |
| | | close(); |
| | | message.success('ä¿åæå'); |
| | | } catch (error) { |
| | | console.error(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 |
| | | wrapClassName="page-designer-modal" |
| | | > |
| | | <template #closeIcon> |
| | | <span></span> |
| | | </template> |
| | | <BasicForm /> |
| | | <div style="margin-top: 16px;"> |
| | | <FcDesigner |
| | | ref="designer" |
| | | @update="handleDesignerChange" |
| | | @change="handleDesignerChange" |
| | | @add-rule="handleDesignerChange" |
| | | @remove-rule="handleDesignerChange" |
| | | |
| | | /> |
| | | <div style="margin-top: 8px; display: flex; justify-content: flex-end;"> |
| | | <a-button type="primary" ghost @click="syncAllFields"> |
| | | åæ¥è®¾è®¡åæ®µå°è¡¨æ ¼ |
| | | </a-button> |
| | | </div> |
| | | </div> |
| | | <FormItem label="è¡¨æ ¼åæ®µ" style="margin-top: 24px;"> |
| | | <a-checkbox-group |
| | | v-model:value="selectedFields" |
| | | :options="fieldOptions" |
| | | style="width:100%;display:flex;flex-wrap:wrap;gap:8px" |
| | | /> |
| | | </FormItem> |
| | | <template #empty> |
| | | <div style="padding: 32px 0; color: #999; text-align: center;"> |
| | | ææ æ°æ® |
| | | </div> |
| | | </template> |
| | | </a-modal> |
| | | </template> |
| | | |
| | | <style scoped> |
| | | .page-designer-modal .ant-modal { |
| | | max-width: 1200px; |
| | | } |
| | | |
| | | |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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: 'æ£å¸¸', 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: 'æ£å¸¸', value: '1' }, |
| | | { label: 'åç¨', value: '0' }, |
| | | ], |
| | | }, |
| | | rules: 'selectRequired', |
| | | }, |
| | | { |
| | | component: 'Input', |
| | | fieldName: 'remark', |
| | | label: '夿³¨', |
| | | componentProps: { |
| | | type: 'textarea', |
| | | rows: 2, |
| | | }, |
| | | }, |
| | | ]; |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <Page v-if="isAdmin && pageId" :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="æªæå® pageIdï¼æ æ³è®¿é®æ¤é¡µé¢" 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); // å è½½ä¸ |
| | | |
| | | // 卿columns |
| | | 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('è§£æ actionsFunc 失败:', error); |
| | | return true; |
| | | } |
| | | } |
| | | |
| | | // è·å pageIdï¼åªç¨ params |
| | | function getPageId() { |
| | | const segments = window.location.pathname.split('/'); |
| | | return segments[segments.length - 1] || ''; |
| | | } |
| | | |
| | | 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) => { |
| | | // åªæå½å¼çæ£ååæ¶æå¤ç |
| | | 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, |
| | | menuParentId: 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.pageId = 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('è§£æåç formData:', formData); |
| | | // å é¤åå§ç formData åæ®µï¼å 为æä»¬å·²ç»å±å¼å®çå
容 |
| | | const { formData: _, ...restRow } = row; |
| | | // è¿åå±å¼åçæ°æ® |
| | | return { |
| | | ...restRow, |
| | | ...formData |
| | | }; |
| | | } |
| | | } catch (e) { |
| | | console.error('è§£æ 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.pageId = pageId.value; |
| | | } |
| | | // å¨æä¼ éformJsonï¼å
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('è§£æ formJson 失败:', error); |
| | | params.formJson = undefined; |
| | | } |
| | | } |
| | | templateModalRef.value.open(params); |
| | | } |
| | | |
| | | function handleEdit(record) { |
| | | // ç¼è¾æ¶ä¹ä¼ éformJsonï¼å
JSON.parseï¼ä¿è¯æ¯çº¯å¯¹è±¡ |
| | | const params: any = { |
| | | id: record.id, |
| | | update: true, |
| | | pageId: pageId.value, // ä¼ é页é¢è®¾è®¡ID |
| | | record: record // ä¼ é宿´çè®°å½æ°æ® |
| | | }; |
| | | |
| | | if (pageDesignDetail.value && pageDesignDetail.value.formJson) { |
| | | try { |
| | | const formJson = JSON.parse(pageDesignDetail.value.formJson); |
| | | params.formJson = formJson; |
| | | console.log('ç¼è¾æ¶ä¼ éæ°æ®:', { record, formJson, pageId: pageId.value }); |
| | | } catch (error) { |
| | | console.error('è§£æ 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> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <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; |
| | | pageId?: 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ãbodyãcolumnsãlistãoptionsãtabs çå®¹å¨ |
| | | 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 || ''; |
| | | |
| | | // è®¾ç½®å¨æè¡¨ååæ®µï¼å§ç»ç§»é¤ææsubmitæé® |
| | | 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('è§£æåçè¡¨åæ°æ®:', 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('è§£æå¨æåæ®µæ°æ®å¤±è´¥:', 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 åªè´è´£è§¦å表å 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> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div>å·¥ä½ä¸å</div> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: "index" |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div>æçå·¥ä½</div> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: "index" |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div>å·¥ä½ç»è®¡</div> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: "index" |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | |
| | | </style> |