mirror of
https://github.com/jeecgboot/JeecgBoot.git
synced 2025-12-26 08:16:41 +08:00
Compare commits
21 Commits
526734c5a5
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 42087c0bf8 | |||
| 606edcc82f | |||
| 9082e986f1 | |||
| 40cd525bba | |||
| d6b6cf079e | |||
| 1b688e7cd2 | |||
| 58915a6410 | |||
| b67096dc54 | |||
| 67795493bd | |||
| e1c8f00bf2 | |||
| 17a81e89a5 | |||
| bcbf775756 | |||
| 462365890e | |||
| b686f9fbd1 | |||
| 872f84d006 | |||
| 26087172df | |||
| 281c3ff3c8 | |||
| 38d44c2487 | |||
| 8c88f8adf5 | |||
| adc191f03e | |||
| f6f2ef6316 |
@ -3,9 +3,6 @@ AIGC应用平台介绍
|
|||||||
|
|
||||||
一个全栈式 AI 开发平台,旨在帮助开发者快速构建和部署个性化的 AI 应用。
|
一个全栈式 AI 开发平台,旨在帮助开发者快速构建和部署个性化的 AI 应用。
|
||||||
|
|
||||||
> JDK说明:AI流程编排引擎暂时不支持jdk21,所以目前只能使用jdk8或者jdk17启动项目。
|
|
||||||
|
|
||||||
|
|
||||||
JeecgBoot平台的AIGC功能模块,是一套类似`Dify`的`AIGC应用开发平台`+`知识库问答`,是一款基于LLM大语言模型AI应用平台和 RAG 的知识库问答系统。
|
JeecgBoot平台的AIGC功能模块,是一套类似`Dify`的`AIGC应用开发平台`+`知识库问答`,是一款基于LLM大语言模型AI应用平台和 RAG 的知识库问答系统。
|
||||||
其直观的界面结合了 AI 流程编排、RAG 管道、知识库管理、模型管理、对接向量库、实时运行可观察等,让您可以快速从原型到生产,拥有AI服务能力。
|
其直观的界面结合了 AI 流程编排、RAG 管道、知识库管理、模型管理、对接向量库、实时运行可观察等,让您可以快速从原型到生产,拥有AI服务能力。
|
||||||
|
|
||||||
@ -109,6 +106,10 @@ JeecgBoot平台的AIGC功能模块,是一套类似`Dify`的`AIGC应用开发
|
|||||||
| ChatGTP | √ |
|
| ChatGTP | √ |
|
||||||
| Qwq | √ |
|
| Qwq | √ |
|
||||||
| 智库 | √ |
|
| 智库 | √ |
|
||||||
|
| claude | √ |
|
||||||
|
| vl模型 | √ |
|
||||||
|
| 千帆大模型 | √ |
|
||||||
|
| 通义千问 | √ |
|
||||||
| Ollama本地搭建大模型 | √ |
|
| Ollama本地搭建大模型 | √ |
|
||||||
| 等等。。 | √ |
|
| 等等。。 | √ |
|
||||||
|
|
||||||
|
|||||||
@ -1,126 +0,0 @@
|
|||||||
|
|
||||||
JeecgBoot低代码平台(商业版介绍)
|
|
||||||
===============
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
项目介绍
|
|
||||||
-----------------------------------
|
|
||||||
|
|
||||||
<h3 align="center">企业级AI低代码平台</h3>
|
|
||||||
|
|
||||||
|
|
||||||
JeecgBoot是一款集成AI应用的,基于BPM流程的低代码平台,旨在帮助企业快速实现低代码开发和构建个性化AI应用,支持MCP和插件,实现聊天式业务操作(如 “一句话创建用户”)!
|
|
||||||
|
|
||||||
前后端分离架构Ant Design&Vue3,SpringBoot,SpringCloud Alibaba,Mybatis-plus,Shiro。强大的代码生成器让前后端代码一键生成,无需写任何代码! 引领AI低代码开发模式: AI生成->OnlineCoding-> 代码生成-> 手工MERGE, 帮助Java项目解决80%的重复工作,让开发更多关注业务,提高效率、节省成本,同时又不失灵活性!低代码能力:Online表单、表单设计、流程设计、Online报表、大屏/仪表盘设计、报表设计; AI应用平台功能:AI知识库问答、AI模型管理、AI流程编排、AI聊天等,支持含ChatGPT、DeepSeek、Ollama等多种AI大模型
|
|
||||||
|
|
||||||
JeecgBoot 提供了一系列 `低代码能力`,实现`真正的零代码`在线开发:Online表单开发、Online报表、复杂报表设计、打印设计、在线图表设计、仪表盘设计、大屏设计、移动图表能力、表单设计器、在线设计流程、流程自动化配置、插件能力(可插拔)
|
|
||||||
|
|
||||||
`AI赋能低代码:` 目前提供了AI应用、AI模型管理、AI流程编排、AI对话助手,AI建表、AI写文章、AI知识库问答、AI字段建议等功能;支持各种AI大模型ChatGPT、DeepSeek、Ollama、智普、千问等.
|
|
||||||
|
|
||||||
`JEECG宗旨是:` 简单功能由OnlineCoding配置实现,做到`零代码开发`;复杂功能由代码生成器生成进行手工Merge 实现`低代码开发`,既保证了`智能`又兼顾`灵活`;实现了低代码开发的同时又支持灵活编码,解决了当前低代码产品普遍不灵活的弊端!
|
|
||||||
|
|
||||||
`JEECG业务流程:` 采用工作流来实现、扩展出任务接口,供开发编写业务逻辑,表单提供多种解决方案: 表单设计器、online配置表单、编码表单。同时实现了流程与表单的分离设计(松耦合)、并支持任务节点灵活配置,既保证了公司流程的保密性,又减少了开发人员的工作量。
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#### JeecgBoot商业版与同类产品区别
|
|
||||||
-----------------------------------
|
|
||||||
|
|
||||||
- 灵活性:jeecgboot基于开源技术栈,设计初考虑到可插拔性和集成灵活性,确保平台的智能性与灵活性,避免因平台过于庞大而导致的扩展困难。
|
|
||||||
- 流程管理:支持一个表单挂接多个流程,同时一个流程可以连接多个表单,增强了流程的灵活性和复杂性管理。
|
|
||||||
- 符合中国国情的流程:针对中国市场的特定需求,jeecgboot能够实现各种符合中国国情的业务流程。
|
|
||||||
- 强大的表单设计器:jeecgboot的表单设计器与敲敲云共享,具备高质量和智能化的特点,能够满足零代码应用的需求,业内同类产品中不多见。
|
|
||||||
- 报表功能:自主研发的报表工具,拥有独立知识产权,功能上比业内老牌产品如帆软更智能,操作简便。
|
|
||||||
- BI产品整合:提供大屏、仪表盘、门户等功能,完美解决这些需求,并支持移动面板的设计与渲染。
|
|
||||||
- 自主研发的模块:jeecgboot的所有模块均为自主研发,具有独立的知识产权。
|
|
||||||
- 颗粒度和功能细致:在功能细致度和颗粒度上,jeecgboot远超同类产品,尤其在零代码能力方面表现突出。
|
|
||||||
- 零代码应用管理:最新版支持与敲敲云的零代码应用管理能力的集成,使得jeecgboot既具备低代码,又具备零代码的应用能力,业内独一无二。
|
|
||||||
- 强大的代码生成器:作为开源代码生成器的先锋,jeecgboot在代码生成的智能化和在线低代码与代码生成的结合方面,优势明显。
|
|
||||||
- 精细化权限管理:提供行级和列级的数据权限控制,满足企业在ERP和OA领域对权限管理的严格需求。
|
|
||||||
- 多平台支持的APP:目前采用uniapp3实现,支持小程序、H5、App及鸿蒙、鸿蒙Next、Electron桌面应用等多种终端。
|
|
||||||
|
|
||||||
> 综上所述,jeecgboot不仅在功能上具备丰富性和灵活性,还在技术架构、权限管理和用户体验等方面展现出明显的优势,是一个综合性能强大的低代码平台。
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
商业版演示
|
|
||||||
-----------------------------------
|
|
||||||
|
|
||||||
JeecgBoot vs 敲敲云
|
|
||||||
> - JeecgBoot是低代码产品拥有系列低代码能力,比如流程设计、表单设计、大屏设计,代码生成器,适合半开发模式(开发+低代码结合),也可以集成零代码应用管理模块.
|
|
||||||
> - 敲敲云是零代码产品,完全不写代码,通过配置搭建业务系统,其在jeecgboot基础上研发而成,删除了online、代码生成、OA等需要编码功能,只保留应用管理功能和聊天、日程、文件三个OA组件.
|
|
||||||
|
|
||||||
|
|
||||||
- JeecgBoot低代码: https://boot3.jeecg.com
|
|
||||||
- 敲敲云零代码:https://app.qiaoqiaoyun.com
|
|
||||||
- APP演示(多端): http://jeecg.com/appIndex
|
|
||||||
|
|
||||||
|
|
||||||
### 流程视频介绍
|
|
||||||
|
|
||||||
[](https://www.bilibili.com/video/BV1Nk4y1o7Qc)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### 商业版功能简述
|
|
||||||
|
|
||||||
> 详细的功能介绍,[请联系官方](https://jeecg.com/vip)
|
|
||||||
|
|
||||||
```
|
|
||||||
│─更多商业功能
|
|
||||||
│ ├─流程设计器
|
|
||||||
│ ├─简流设计器(类钉钉版)
|
|
||||||
│ ├─门户设计(NEW)
|
|
||||||
│ ├─表单设计器
|
|
||||||
│ ├─大屏设计器
|
|
||||||
│ └─我的任务
|
|
||||||
│ └─历史流程
|
|
||||||
│ └─历史流程
|
|
||||||
│ └─流程实例管理
|
|
||||||
│ └─流程监听管理
|
|
||||||
│ └─流程表达式
|
|
||||||
│ └─我发起的流程
|
|
||||||
│ └─我的抄送
|
|
||||||
│ └─流程委派、抄送、跳转
|
|
||||||
│ └─OA办公组件
|
|
||||||
│ └─零代码应用管理(无需编码,在线搭建应用系统)
|
|
||||||
│ ├─积木报表企业版(含jimureport、jimubi)
|
|
||||||
│ ├─AI流程设计器源码
|
|
||||||
│ ├─Online全模块功能和源码
|
|
||||||
│ ├─AI写文章(CMS)
|
|
||||||
│ ├─AI表单字段建议(表单设计器)
|
|
||||||
│ ├─OA办公协同组件
|
|
||||||
│ ├─在线聊天功能
|
|
||||||
│ ├─设计表单移动适配
|
|
||||||
│ ├─设计表单支持外部填报
|
|
||||||
│ ├─设计表单AI字段建议
|
|
||||||
│ ├─设计表单视图功能(支持多种类型含日历、表格、看板、甘特图)
|
|
||||||
│ └─。。。
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
##### 流程设计
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
##### 表单设计器
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
|
[中文](./README.md) | English
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
15
README.md
15
README.md
@ -1,3 +1,4 @@
|
|||||||
|
中文 | [English](./README.en-US.md)
|
||||||
|
|
||||||
JeecgBoot AI低代码平台
|
JeecgBoot AI低代码平台
|
||||||
===============
|
===============
|
||||||
@ -232,20 +233,6 @@ JeecgBoot平台提供了一套完善的AI应用管理系统模块,是一套类
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
开源版与企业版区别?
|
|
||||||
-----------------------------------
|
|
||||||
|
|
||||||
- JeecgBoot开源版采用 [Apache-2.0 license](LICENSE) 协议附加补充条款:允许商用使用,不会造成侵权行为,允许基于本平台软件开展业务系统开发(但在任何情况下,您不得使用本软件开发可能被认为与本软件竞争的软件).
|
|
||||||
- 商业版与开源版主要区别在于商业版提供了技术支持 和 更多的企业级功能(例如:Online图表、流程监控、流程设计、流程审批、表单设计器、表单视图、积木报表企业版、OA办公、商业APP、零代码应用、Online模块源码等功能). [更多商业功能介绍,点击查看](README-Enterprise.md)
|
|
||||||
- JeecgBoot未来发展方向是:零代码平台的建设,也就是团队的另外一款产品 [敲敲云零代码](https://www.qiaoqiaoyun.com) ,无需编码即可通过拖拽快速搭建企业级应用,与JeecgBoot低代码平台形成互补,满足从简单业务到复杂系统的全场景开发需求,目前已经开源,[欢迎下载](https://qiaoqiaoyun.com/downloadCode)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Jeecg Boot 产品功能蓝图
|
### Jeecg Boot 产品功能蓝图
|
||||||

|

|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
JeecgBoot 低代码开发平台
|
JeecgBoot 低代码开发平台
|
||||||
===============
|
===============
|
||||||
|
|
||||||
|
|||||||
@ -3,9 +3,7 @@ package org.jeecg.common.system.util;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.jeecg.common.system.annotation.EnumDict;
|
import org.jeecg.common.system.annotation.EnumDict;
|
||||||
import org.jeecg.common.system.vo.DictModel;
|
import org.jeecg.common.system.vo.DictModel;
|
||||||
import org.jeecg.common.util.SpringContextUtils;
|
|
||||||
import org.jeecg.common.util.oConvertUtils;
|
import org.jeecg.common.util.oConvertUtils;
|
||||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||||
@ -13,6 +11,7 @@ import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
|
|||||||
import org.springframework.core.type.classreading.MetadataReader;
|
import org.springframework.core.type.classreading.MetadataReader;
|
||||||
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@ -183,10 +182,10 @@ public class ResourceUtil {
|
|||||||
for (DictModel dm : dictItemList) {
|
for (DictModel dm : dictItemList) {
|
||||||
String value = dm.getValue();
|
String value = dm.getValue();
|
||||||
if (keySet.contains(value)) {
|
if (keySet.contains(value)) {
|
||||||
List<DictModel> list = new ArrayList<>();
|
// 修复bug:获取或创建该dictCode对应的list,而不是每次都创建新的list
|
||||||
|
List<DictModel> list = map.computeIfAbsent(code, k -> new ArrayList<>());
|
||||||
list.add(new DictModel(value, dm.getText()));
|
list.add(new DictModel(value, dm.getText()));
|
||||||
map.put(code, list);
|
//break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,32 @@
|
|||||||
|
package org.jeecg.config.sign.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 签名校验注解
|
||||||
|
* 用于方法级别的签名验证,功能等同于yml中的jeecg.signUrls配置
|
||||||
|
* 参考DragSignatureAspect的设计思路,使用AOP切面实现
|
||||||
|
*
|
||||||
|
* @author GitHub Copilot
|
||||||
|
* @since 2025-12-15
|
||||||
|
*/
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface SignatureCheck {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否启用签名校验
|
||||||
|
* @return true-启用(默认), false-禁用
|
||||||
|
*/
|
||||||
|
boolean enabled() default true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 签名校验失败时的错误消息
|
||||||
|
* @return 错误消息
|
||||||
|
*/
|
||||||
|
String errorMessage() default "Sign签名校验失败!";
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,93 @@
|
|||||||
|
package org.jeecg.config.sign.aspect;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.aspectj.lang.JoinPoint;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
import org.aspectj.lang.annotation.Before;
|
||||||
|
import org.aspectj.lang.annotation.Pointcut;
|
||||||
|
import org.aspectj.lang.reflect.MethodSignature;
|
||||||
|
import org.jeecg.config.sign.annotation.SignatureCheck;
|
||||||
|
import org.jeecg.config.sign.interceptor.SignAuthInterceptor;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 基于AOP的签名验证切面
|
||||||
|
* 复用SignAuthInterceptor的成熟签名验证逻辑
|
||||||
|
*
|
||||||
|
* @author GitHub Copilot
|
||||||
|
* @since 2025-12-15
|
||||||
|
*/
|
||||||
|
@Aspect
|
||||||
|
@Slf4j
|
||||||
|
@Component("signatureCheckAspect")
|
||||||
|
public class SignatureCheckAspect {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 复用SignAuthInterceptor的签名验证逻辑
|
||||||
|
*/
|
||||||
|
private final SignAuthInterceptor signAuthInterceptor = new SignAuthInterceptor();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验签切点:拦截所有标记了@SignatureCheck注解的方法
|
||||||
|
*/
|
||||||
|
@Pointcut("@annotation(org.jeecg.config.sign.annotation.SignatureCheck)")
|
||||||
|
private void signatureCheckPointCut() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开始验签
|
||||||
|
*/
|
||||||
|
@Before("signatureCheckPointCut()")
|
||||||
|
public void doSignatureValidation(JoinPoint point) throws Exception {
|
||||||
|
// 获取方法上的注解
|
||||||
|
MethodSignature signature = (MethodSignature) point.getSignature();
|
||||||
|
Method method = signature.getMethod();
|
||||||
|
SignatureCheck signatureCheck = method.getAnnotation(SignatureCheck.class);
|
||||||
|
|
||||||
|
log.info("AOP签名验证: {}.{}", method.getDeclaringClass().getSimpleName(), method.getName());
|
||||||
|
|
||||||
|
// 如果注解被禁用,直接返回
|
||||||
|
if (!signatureCheck.enabled()) {
|
||||||
|
log.info("签名验证已禁用,跳过");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||||
|
if (attributes == null) {
|
||||||
|
log.error("无法获取请求上下文");
|
||||||
|
throw new IllegalArgumentException("无法获取请求上下文");
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpServletRequest request = attributes.getRequest();
|
||||||
|
log.info("X-SIGN: {}, X-TIMESTAMP: {}", request.getHeader("X-SIGN"), request.getHeader("X-TIMESTAMP"));
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 直接调用SignAuthInterceptor的验证逻辑
|
||||||
|
signAuthInterceptor.validateSignature(request);
|
||||||
|
log.info("AOP签名验证通过");
|
||||||
|
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// 使用注解中配置的错误消息,或者保留原始错误消息
|
||||||
|
String errorMessage = signatureCheck.errorMessage();
|
||||||
|
log.error("AOP签名验证失败: {}", e.getMessage());
|
||||||
|
|
||||||
|
if ("Sign签名校验失败!".equals(errorMessage)) {
|
||||||
|
// 如果是默认错误消息,使用原始的详细错误信息
|
||||||
|
throw e;
|
||||||
|
} else {
|
||||||
|
// 如果是自定义错误消息,使用自定义消息
|
||||||
|
throw new IllegalArgumentException(errorMessage, e);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 包装其他异常
|
||||||
|
String errorMessage = signatureCheck.errorMessage();
|
||||||
|
log.error("AOP签名验证异常: {}", e.getMessage());
|
||||||
|
throw new IllegalArgumentException(errorMessage, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,12 +1,10 @@
|
|||||||
package org.jeecg.config.sign.interceptor;
|
package org.jeecg.config.sign.interceptor;
|
||||||
|
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import com.alibaba.fastjson.JSON;
|
||||||
import java.util.SortedMap;
|
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.jeecg.common.api.vo.Result;
|
import org.jeecg.common.api.vo.Result;
|
||||||
import org.jeecg.common.constant.CommonConstant;
|
import org.jeecg.common.constant.CommonConstant;
|
||||||
import org.jeecg.common.util.DateUtils;
|
import org.jeecg.common.util.DateUtils;
|
||||||
@ -16,9 +14,8 @@ import org.jeecg.config.sign.util.HttpUtils;
|
|||||||
import org.jeecg.config.sign.util.SignUtil;
|
import org.jeecg.config.sign.util.SignUtil;
|
||||||
import org.springframework.web.servlet.HandlerInterceptor;
|
import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import java.io.PrintWriter;
|
||||||
|
import java.util.SortedMap;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 签名拦截器
|
* 签名拦截器
|
||||||
@ -33,23 +30,46 @@ public class SignAuthInterceptor implements HandlerInterceptor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||||
log.debug("Sign Interceptor request URI = " + request.getRequestURI());
|
log.info("签名拦截器 Interceptor request URI = " + request.getRequestURI());
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 调用验证逻辑
|
||||||
|
validateSignature(request);
|
||||||
|
return true;
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// 验证失败,返回错误响应
|
||||||
|
log.error("Sign 签名校验失败!{}", e.getMessage());
|
||||||
|
response.setCharacterEncoding("UTF-8");
|
||||||
|
response.setContentType("application/json; charset=utf-8");
|
||||||
|
PrintWriter out = response.getWriter();
|
||||||
|
Result<?> result = Result.error(e.getMessage());
|
||||||
|
out.print(JSON.toJSON(result));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 签名验证核心逻辑
|
||||||
|
* 提取出来供AOP切面复用
|
||||||
|
* @param request HTTP请求
|
||||||
|
* @throws IllegalArgumentException 验证失败时抛出异常
|
||||||
|
*/
|
||||||
|
public void validateSignature(HttpServletRequest request) throws IllegalArgumentException {
|
||||||
|
try {
|
||||||
|
log.debug("开始签名验证: {} {}", request.getMethod(), request.getRequestURI());
|
||||||
|
|
||||||
HttpServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper(request);
|
HttpServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper(request);
|
||||||
//获取全部参数(包括URL和body上的)
|
//获取全部参数(包括URL和body上的)
|
||||||
SortedMap<String, String> allParams = HttpUtils.getAllParams(requestWrapper);
|
SortedMap<String, String> allParams = HttpUtils.getAllParams(requestWrapper);
|
||||||
|
log.debug("提取参数: {}", allParams);
|
||||||
|
|
||||||
//对参数进行签名验证
|
//对参数进行签名验证
|
||||||
String headerSign = request.getHeader(CommonConstant.X_SIGN);
|
String headerSign = request.getHeader(CommonConstant.X_SIGN);
|
||||||
String xTimestamp = request.getHeader(CommonConstant.X_TIMESTAMP);
|
String xTimestamp = request.getHeader(CommonConstant.X_TIMESTAMP);
|
||||||
|
|
||||||
if(oConvertUtils.isEmpty(xTimestamp)){
|
if(oConvertUtils.isEmpty(xTimestamp)){
|
||||||
Result<?> result = Result.error("Sign签名校验失败,时间戳为空!");
|
log.error("Sign签名校验失败,时间戳为空!");
|
||||||
log.error("Sign 签名校验失败!Header xTimestamp 为空");
|
throw new IllegalArgumentException("Sign签名校验失败,请求参数不完整!");
|
||||||
//校验失败返回前端
|
|
||||||
response.setCharacterEncoding("UTF-8");
|
|
||||||
response.setContentType("application/json; charset=utf-8");
|
|
||||||
PrintWriter out = response.getWriter();
|
|
||||||
out.print(JSON.toJSON(result));
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//客户端时间
|
//客户端时间
|
||||||
@ -60,15 +80,24 @@ public class SignAuthInterceptor implements HandlerInterceptor {
|
|||||||
//1.校验签名时间(兼容X_TIMESTAMP的新老格式)
|
//1.校验签名时间(兼容X_TIMESTAMP的新老格式)
|
||||||
if (xTimestamp.length() == length) {
|
if (xTimestamp.length() == length) {
|
||||||
//a. X_TIMESTAMP格式是 yyyyMMddHHmmss (例子:20220308152143)
|
//a. X_TIMESTAMP格式是 yyyyMMddHHmmss (例子:20220308152143)
|
||||||
if ((DateUtils.getCurrentTimestamp() - clientTimestamp) > MAX_EXPIRE) {
|
long currentTimestamp = DateUtils.getCurrentTimestamp();
|
||||||
log.error("签名验证失败:X-TIMESTAMP已过期,注意系统时间和服务器时间是否有误差!");
|
long timeDiff = currentTimestamp - clientTimestamp;
|
||||||
throw new IllegalArgumentException("签名验证失败:X-TIMESTAMP已过期");
|
log.debug("时间戳验证(yyyyMMddHHmmss): 时间差{}秒", timeDiff);
|
||||||
|
|
||||||
|
if (timeDiff > MAX_EXPIRE) {
|
||||||
|
log.error("时间戳已过期: {}秒 > {}秒", timeDiff, MAX_EXPIRE);
|
||||||
|
throw new IllegalArgumentException("签名验证失败,请求时效性验证失败!");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//b. X_TIMESTAMP格式是 时间戳 (例子:1646552406000)
|
//b. X_TIMESTAMP格式是 时间戳 (例子:1646552406000)
|
||||||
if ((System.currentTimeMillis() - clientTimestamp) > (MAX_EXPIRE * length1000)) {
|
long currentTime = System.currentTimeMillis();
|
||||||
log.error("签名验证失败:X-TIMESTAMP已过期,注意系统时间和服务器时间是否有误差!");
|
long timeDiff = currentTime - clientTimestamp;
|
||||||
throw new IllegalArgumentException("签名验证失败:X-TIMESTAMP已过期");
|
long maxExpireMs = MAX_EXPIRE * length1000;
|
||||||
|
log.debug("时间戳验证(Unix): 时间差{}ms", timeDiff);
|
||||||
|
|
||||||
|
if (timeDiff > maxExpireMs) {
|
||||||
|
log.error("时间戳已过期: {}ms > {}ms", timeDiff, maxExpireMs);
|
||||||
|
throw new IllegalArgumentException("签名验证失败,请求时效性验证失败!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,19 +105,18 @@ public class SignAuthInterceptor implements HandlerInterceptor {
|
|||||||
boolean isSigned = SignUtil.verifySign(allParams,headerSign);
|
boolean isSigned = SignUtil.verifySign(allParams,headerSign);
|
||||||
|
|
||||||
if (isSigned) {
|
if (isSigned) {
|
||||||
log.debug("Sign 签名通过!Header Sign : {}",headerSign);
|
log.debug("签名验证通过");
|
||||||
return true;
|
|
||||||
} else {
|
} else {
|
||||||
log.debug("sign allParams: {}", allParams);
|
log.error("签名验证失败, 参数: {}", allParams);
|
||||||
log.error("request URI = " + request.getRequestURI());
|
throw new IllegalArgumentException("Sign签名校验失败!");
|
||||||
log.error("Sign 签名校验失败!Header Sign : {}",headerSign);
|
}
|
||||||
//校验失败返回前端
|
} catch (IllegalArgumentException e) {
|
||||||
response.setCharacterEncoding("UTF-8");
|
// 重新抛出签名验证异常
|
||||||
response.setContentType("application/json; charset=utf-8");
|
throw e;
|
||||||
PrintWriter out = response.getWriter();
|
} catch (Exception e) {
|
||||||
Result<?> result = Result.error("Sign签名校验失败!");
|
// 包装其他异常(如IOException)
|
||||||
out.print(JSON.toJSON(result));
|
log.error("签名验证异常: {}", e.getMessage());
|
||||||
return false;
|
throw new IllegalArgumentException("Sign签名校验失败:" + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -21,6 +21,7 @@ import org.jeecg.common.util.PasswordUtil;
|
|||||||
import org.jeecg.common.util.TokenUtils;
|
import org.jeecg.common.util.TokenUtils;
|
||||||
import org.jeecg.common.util.oConvertUtils;
|
import org.jeecg.common.util.oConvertUtils;
|
||||||
import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
|
import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
|
||||||
|
import org.jeecg.config.sign.annotation.SignatureCheck;
|
||||||
import org.jeecg.modules.base.service.BaseCommonService;
|
import org.jeecg.modules.base.service.BaseCommonService;
|
||||||
import org.jeecg.modules.system.entity.*;
|
import org.jeecg.modules.system.entity.*;
|
||||||
import org.jeecg.modules.system.service.ISysTenantPackService;
|
import org.jeecg.modules.system.service.ISysTenantPackService;
|
||||||
@ -260,6 +261,7 @@ public class SysTenantController {
|
|||||||
* @param id
|
* @param id
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
@SignatureCheck
|
||||||
@RequestMapping(value = "/queryById", method = RequestMethod.GET)
|
@RequestMapping(value = "/queryById", method = RequestMethod.GET)
|
||||||
public Result<SysTenant> queryById(@RequestParam(name="id",required=true) String id) {
|
public Result<SysTenant> queryById(@RequestParam(name="id",required=true) String id) {
|
||||||
Result<SysTenant> result = new Result<SysTenant>();
|
Result<SysTenant> result = new Result<SysTenant>();
|
||||||
@ -507,26 +509,26 @@ public class SysTenantController {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* 加入租户通过门牌号【低代码应用专用接口】
|
// * 加入租户通过门牌号【低代码应用专用接口】
|
||||||
* @param sysTenant
|
// * @param sysTenant
|
||||||
*/
|
// */
|
||||||
@PostMapping("/joinTenantByHouseNumber")
|
// @PostMapping("/joinTenantByHouseNumber")
|
||||||
public Result<Integer> joinTenantByHouseNumber(@RequestBody SysTenant sysTenant){
|
// public Result<Integer> joinTenantByHouseNumber(@RequestBody SysTenant sysTenant){
|
||||||
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
// LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
||||||
Integer tenantId = sysTenantService.joinTenantByHouseNumber(sysTenant, sysUser.getId());
|
// Integer tenantId = sysTenantService.joinTenantByHouseNumber(sysTenant, sysUser.getId());
|
||||||
Result<Integer> result = new Result<>();
|
// Result<Integer> result = new Result<>();
|
||||||
if(tenantId != 0){
|
// if(tenantId != 0){
|
||||||
result.setMessage("申请加入组织成功");
|
// result.setMessage("申请加入组织成功");
|
||||||
result.setSuccess(true);
|
// result.setSuccess(true);
|
||||||
result.setResult(tenantId);
|
// result.setResult(tenantId);
|
||||||
return result;
|
// return result;
|
||||||
}else{
|
// }else{
|
||||||
result.setMessage("该门牌号不存在");
|
// result.setMessage("该门牌号不存在");
|
||||||
result.setSuccess(false);
|
// result.setSuccess(false);
|
||||||
return result;
|
// return result;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分页获取租户用户数据(vue3用户租户页面)【低代码应用专用接口】
|
* 分页获取租户用户数据(vue3用户租户页面)【低代码应用专用接口】
|
||||||
@ -713,6 +715,7 @@ public class SysTenantController {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@PostMapping("/invitationUser")
|
@PostMapping("/invitationUser")
|
||||||
|
@RequiresPermissions("system:tenant:invitation:user")
|
||||||
public Result<String> invitationUser(@RequestParam(name="phone") String phone,
|
public Result<String> invitationUser(@RequestParam(name="phone") String phone,
|
||||||
@RequestParam(name="departId",defaultValue = "") String departId){
|
@RequestParam(name="departId",defaultValue = "") String departId){
|
||||||
return sysTenantService.invitationUser(phone,departId);
|
return sysTenantService.invitationUser(phone,departId);
|
||||||
@ -911,43 +914,43 @@ public class SysTenantController {
|
|||||||
return Result.ok(pageList);
|
return Result.ok(pageList);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* 同意或拒绝加入租户
|
// * 同意或拒绝加入租户
|
||||||
*/
|
// */
|
||||||
@PutMapping("/agreeOrRefuseJoinTenant")
|
// @PutMapping("/agreeOrRefuseJoinTenant")
|
||||||
public Result<String> agreeOrRefuseJoinTenant(@RequestParam("tenantId") Integer tenantId,
|
// public Result<String> agreeOrRefuseJoinTenant(@RequestParam("tenantId") Integer tenantId,
|
||||||
@RequestParam("status") String status){
|
// @RequestParam("status") String status){
|
||||||
//是否开启系统管理模块的多租户数据隔离【SAAS多租户模式】
|
// //是否开启系统管理模块的多租户数据隔离【SAAS多租户模式】
|
||||||
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
// LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
||||||
String userId = sysUser.getId();
|
// String userId = sysUser.getId();
|
||||||
SysTenant tenant = sysTenantService.getById(tenantId);
|
// SysTenant tenant = sysTenantService.getById(tenantId);
|
||||||
if(null == tenant){
|
// if(null == tenant){
|
||||||
return Result.error("不存在该组织");
|
// return Result.error("不存在该组织");
|
||||||
}
|
// }
|
||||||
SysUserTenant sysUserTenant = relationService.getUserTenantByTenantId(userId, tenantId);
|
// SysUserTenant sysUserTenant = relationService.getUserTenantByTenantId(userId, tenantId);
|
||||||
if (null == sysUserTenant) {
|
// if (null == sysUserTenant) {
|
||||||
return Result.error("该用户不存在该组织中,无权修改");
|
// return Result.error("该用户不存在该组织中,无权修改");
|
||||||
}
|
// }
|
||||||
String content = "";
|
// String content = "";
|
||||||
SysUser user = new SysUser();
|
// SysUser user = new SysUser();
|
||||||
user.setUsername(sysUserTenant.getCreateBy());
|
// user.setUsername(sysUserTenant.getCreateBy());
|
||||||
String realname = oConvertUtils.getString(sysUser.getRealname(),sysUser.getUsername());
|
// String realname = oConvertUtils.getString(sysUser.getRealname(),sysUser.getUsername());
|
||||||
//成功加入
|
// //成功加入
|
||||||
if(CommonConstant.USER_TENANT_NORMAL.equals(status)){
|
// if(CommonConstant.USER_TENANT_NORMAL.equals(status)){
|
||||||
//修改租户状态
|
// //修改租户状态
|
||||||
relationService.agreeJoinTenant(userId,tenantId);
|
// relationService.agreeJoinTenant(userId,tenantId);
|
||||||
content = content + realname + "已同意您发送的加入 " + tenant.getName() + " 的邀请";
|
// content = content + realname + "已同意您发送的加入 " + tenant.getName() + " 的邀请";
|
||||||
sysTenantService.sendMsgForAgreeAndRefuseJoin(user, content);
|
// sysTenantService.sendMsgForAgreeAndRefuseJoin(user, content);
|
||||||
return Result.OK("您已同意该组织的邀请");
|
// return Result.OK("您已同意该组织的邀请");
|
||||||
}else if(CommonConstant.USER_TENANT_REFUSE.equals(status)){
|
// }else if(CommonConstant.USER_TENANT_REFUSE.equals(status)){
|
||||||
//直接删除关系表即可
|
// //直接删除关系表即可
|
||||||
relationService.refuseJoinTenant(userId,tenantId);
|
// relationService.refuseJoinTenant(userId,tenantId);
|
||||||
content = content + realname + "拒绝了您发送的加入 " + tenant.getName() + " 的邀请";
|
// content = content + realname + "拒绝了您发送的加入 " + tenant.getName() + " 的邀请";
|
||||||
sysTenantService.sendMsgForAgreeAndRefuseJoin(user, content);
|
// sysTenantService.sendMsgForAgreeAndRefuseJoin(user, content);
|
||||||
return Result.OK("您已成功拒绝该组织的邀请");
|
// return Result.OK("您已成功拒绝该组织的邀请");
|
||||||
}
|
// }
|
||||||
return Result.error("类型不匹配,禁止修改数据");
|
// return Result.error("类型不匹配,禁止修改数据");
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 目前只给敲敲云租户下删除用户使用
|
* 目前只给敲敲云租户下删除用户使用
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
package org.jeecg.modules.system.controller;
|
package org.jeecg.modules.system.controller;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.apache.shiro.SecurityUtils;
|
import org.apache.shiro.SecurityUtils;
|
||||||
|
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
import org.jeecg.common.api.vo.Result;
|
import org.jeecg.common.api.vo.Result;
|
||||||
import org.jeecg.common.constant.CacheConstant;
|
import org.jeecg.common.constant.CacheConstant;
|
||||||
import org.jeecg.common.constant.CommonConstant;
|
import org.jeecg.common.constant.CommonConstant;
|
||||||
@ -20,7 +22,6 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -48,6 +49,7 @@ public class SysUserOnlineController {
|
|||||||
@Resource
|
@Resource
|
||||||
private BaseCommonService baseCommonService;
|
private BaseCommonService baseCommonService;
|
||||||
|
|
||||||
|
@RequiresPermissions("system:online:list")
|
||||||
@RequestMapping(value = "/list", method = RequestMethod.GET)
|
@RequestMapping(value = "/list", method = RequestMethod.GET)
|
||||||
public Result<Page<SysUserOnlineVO>> list(@RequestParam(name="username", required=false) String username,
|
public Result<Page<SysUserOnlineVO>> list(@RequestParam(name="username", required=false) String username,
|
||||||
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,@RequestParam(name="pageSize", defaultValue="10") Integer pageSize) {
|
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,@RequestParam(name="pageSize", defaultValue="10") Integer pageSize) {
|
||||||
@ -100,6 +102,7 @@ public class SysUserOnlineController {
|
|||||||
/**
|
/**
|
||||||
* 强退用户
|
* 强退用户
|
||||||
*/
|
*/
|
||||||
|
@RequiresPermissions("system:online:forceLogout")
|
||||||
@RequestMapping(value = "/forceLogout",method = RequestMethod.POST)
|
@RequestMapping(value = "/forceLogout",method = RequestMethod.POST)
|
||||||
public Result<Object> forceLogout(@RequestBody SysUserOnlineVO online) {
|
public Result<Object> forceLogout(@RequestBody SysUserOnlineVO online) {
|
||||||
//用户退出逻辑
|
//用户退出逻辑
|
||||||
|
|||||||
@ -371,11 +371,19 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
|
|||||||
if (isCustomDataSource) {
|
if (isCustomDataSource) {
|
||||||
DynamicDataSourceContextHolder.push(dataSource);
|
DynamicDataSourceContextHolder.push(dataSource);
|
||||||
}
|
}
|
||||||
List<DictModel> restData = sysDictMapper.queryTableDictByKeysAndFilterSql(table, text, code, filterSql, codeValues);
|
//update-begin---author:jarysun ---date:20251020 for:[issues/#9002]解决表字典查询出现异常之后,数据源不能恢复问题------------
|
||||||
|
List<DictModel> restData = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
restData = sysDictMapper.queryTableDictByKeysAndFilterSql(table, text, code, filterSql, codeValues);
|
||||||
|
} finally {
|
||||||
// 清理自定义的数据源
|
// 清理自定义的数据源
|
||||||
if (isCustomDataSource) {
|
if (isCustomDataSource) {
|
||||||
DynamicDataSourceContextHolder.clear();
|
DynamicDataSourceContextHolder.clear();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
//update-end---author:jarysun ---date:20251020 for:[issues/#9002]解决表字典查询出现异常之后,数据源不能恢复问题------------
|
||||||
|
|
||||||
return restData;
|
return restData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<#assign list_need_category=false>
|
<#assign list_need_category=false>
|
||||||
<#assign list_need_pca=false>
|
<#assign list_need_pca=false>
|
||||||
@ -33,7 +33,7 @@
|
|||||||
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
||||||
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle == 'button'>
|
<#if btn.buttonStyle == 'button'>
|
||||||
<a-button type="primary" @click="handle${btn.buttonCode?cap_first}" <#if btn.buttonIcon??> preIcon="ant-design:${btn.buttonIcon}" </#if>>${btn.buttonName}</a-button>
|
<a-button type="primary" @click="handle${btn.buttonCode?cap_first}" <#if btn.buttonIcon??> preIcon="ant-design:${btn.buttonIcon}" </#if>>${btn.buttonName}</a-button>
|
||||||
</#if>
|
</#if>
|
||||||
@ -303,7 +303,7 @@
|
|||||||
ifShow: !!record.bpmStatus && record.bpmStatus !== '1',
|
ifShow: !!record.bpmStatus && record.bpmStatus !== '1',
|
||||||
}
|
}
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle == 'link'>
|
<#if btn.buttonStyle == 'link'>
|
||||||
,{
|
,{
|
||||||
label: '${btn.buttonName}',
|
label: '${btn.buttonName}',
|
||||||
@ -339,7 +339,7 @@
|
|||||||
auth: '${entityPackage}:${tableName}:delete'
|
auth: '${entityPackage}:${tableName}:delete'
|
||||||
}
|
}
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle == 'link'>
|
<#if btn.buttonStyle == 'link'>
|
||||||
,{
|
,{
|
||||||
label: '${btn.buttonName}',
|
label: '${btn.buttonName}',
|
||||||
@ -378,7 +378,7 @@
|
|||||||
</#if>
|
</#if>
|
||||||
|
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle=='button'>
|
<#if btn.buttonStyle=='button'>
|
||||||
function handle${btn.buttonCode?cap_first}(){
|
function handle${btn.buttonCode?cap_first}(){
|
||||||
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
||||||
|
|||||||
@ -108,7 +108,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle=='form'>
|
<#if btn.buttonStyle=='form'>
|
||||||
function handle${btn.buttonCode?cap_first}(){
|
function handle${btn.buttonCode?cap_first}(){
|
||||||
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<#include "/common/utils.ftl">
|
<#include "/common/utils.ftl">
|
||||||
<template>
|
<template>
|
||||||
<div class="p-2">
|
<div class="p-2">
|
||||||
<#assign query_field_no=0>
|
<#assign query_field_no=0>
|
||||||
@ -110,7 +110,7 @@
|
|||||||
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
||||||
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle == 'button'>
|
<#if btn.buttonStyle == 'button'>
|
||||||
<a-button type="primary" @click="handle${btn.buttonCode?cap_first}" <#if btn.buttonIcon??> preIcon="ant-design:${btn.buttonIcon}" </#if>>${btn.buttonName}</a-button>
|
<a-button type="primary" @click="handle${btn.buttonCode?cap_first}" <#if btn.buttonIcon??> preIcon="ant-design:${btn.buttonIcon}" </#if>>${btn.buttonName}</a-button>
|
||||||
</#if>
|
</#if>
|
||||||
@ -368,7 +368,7 @@
|
|||||||
ifShow: !!record.bpmStatus && record.bpmStatus !== '1',
|
ifShow: !!record.bpmStatus && record.bpmStatus !== '1',
|
||||||
}
|
}
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle == 'link'>
|
<#if btn.buttonStyle == 'link'>
|
||||||
,{
|
,{
|
||||||
label: '${btn.buttonName}',
|
label: '${btn.buttonName}',
|
||||||
@ -404,7 +404,7 @@
|
|||||||
auth: '${entityPackage}:${tableName}:delete'
|
auth: '${entityPackage}:${tableName}:delete'
|
||||||
}
|
}
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle == 'link'>
|
<#if btn.buttonStyle == 'link'>
|
||||||
,{
|
,{
|
||||||
label: '${btn.buttonName}',
|
label: '${btn.buttonName}',
|
||||||
@ -484,7 +484,7 @@
|
|||||||
</#if>
|
</#if>
|
||||||
|
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle=='button'>
|
<#if btn.buttonStyle=='button'>
|
||||||
function handle${btn.buttonCode?cap_first}(){
|
function handle${btn.buttonCode?cap_first}(){
|
||||||
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
||||||
|
|||||||
@ -78,7 +78,7 @@
|
|||||||
visible.value = false;
|
visible.value = false;
|
||||||
}
|
}
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle=='form'>
|
<#if btn.buttonStyle=='form'>
|
||||||
function handle${btn.buttonCode?cap_first}(){
|
function handle${btn.buttonCode?cap_first}(){
|
||||||
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<#include "/common/utils.ftl">
|
<#include "/common/utils.ftl">
|
||||||
<#assign pidFieldName = "">
|
<#assign pidFieldName = "">
|
||||||
<#assign hasChildrenField = "">
|
<#assign hasChildrenField = "">
|
||||||
<#assign bpm_flag=false>
|
<#assign bpm_flag=false>
|
||||||
@ -38,7 +38,7 @@
|
|||||||
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
||||||
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle == 'button'>
|
<#if btn.buttonStyle == 'button'>
|
||||||
<a-button type="primary" @click="handle${btn.buttonCode?cap_first}" <#if btn.buttonIcon??> preIcon="${btn.buttonIcon}" </#if>>${btn.buttonName}</a-button>
|
<a-button type="primary" @click="handle${btn.buttonCode?cap_first}" <#if btn.buttonIcon??> preIcon="${btn.buttonIcon}" </#if>>${btn.buttonName}</a-button>
|
||||||
</#if>
|
</#if>
|
||||||
@ -447,7 +447,7 @@
|
|||||||
ifShow: !!record.bpmStatus && record.bpmStatus !== '1',
|
ifShow: !!record.bpmStatus && record.bpmStatus !== '1',
|
||||||
}
|
}
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle == 'link'>
|
<#if btn.buttonStyle == 'link'>
|
||||||
,{
|
,{
|
||||||
label: '${btn.buttonName}',
|
label: '${btn.buttonName}',
|
||||||
@ -483,7 +483,7 @@
|
|||||||
auth: '${entityPackage}:${tableName}:delete'
|
auth: '${entityPackage}:${tableName}:delete'
|
||||||
}
|
}
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle == 'link'>
|
<#if btn.buttonStyle == 'link'>
|
||||||
,{
|
,{
|
||||||
label: '${btn.buttonName}',
|
label: '${btn.buttonName}',
|
||||||
@ -544,7 +544,7 @@
|
|||||||
</#if>
|
</#if>
|
||||||
|
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle=='button'>
|
<#if btn.buttonStyle=='button'>
|
||||||
function handle${btn.buttonCode?cap_first}(){
|
function handle${btn.buttonCode?cap_first}(){
|
||||||
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<#include "/common/utils.ftl">
|
<#include "/common/utils.ftl">
|
||||||
<#assign pidFieldName = "">
|
<#assign pidFieldName = "">
|
||||||
<#assign hasChildrenField = "">
|
<#assign hasChildrenField = "">
|
||||||
<#list originalColumns as po>
|
<#list originalColumns as po>
|
||||||
@ -170,7 +170,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle=='form'>
|
<#if btn.buttonStyle=='form'>
|
||||||
function handle${btn.buttonCode?cap_first}(){
|
function handle${btn.buttonCode?cap_first}(){
|
||||||
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<#include "/common/utils.ftl">
|
<#include "/common/utils.ftl">
|
||||||
<template>
|
<template>
|
||||||
<div class="p-2">
|
<div class="p-2">
|
||||||
<#assign pidFieldName = "">
|
<#assign pidFieldName = "">
|
||||||
@ -120,7 +120,7 @@
|
|||||||
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
||||||
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle == 'button'>
|
<#if btn.buttonStyle == 'button'>
|
||||||
<a-button type="primary" @click="handle${btn.buttonCode?cap_first}" <#if btn.buttonIcon??> preIcon="ant-design:${btn.buttonIcon}" </#if>>${btn.buttonName}</a-button>
|
<a-button type="primary" @click="handle${btn.buttonCode?cap_first}" <#if btn.buttonIcon??> preIcon="ant-design:${btn.buttonIcon}" </#if>>${btn.buttonName}</a-button>
|
||||||
</#if>
|
</#if>
|
||||||
@ -518,7 +518,7 @@
|
|||||||
ifShow: !!record.bpmStatus && record.bpmStatus !== '1',
|
ifShow: !!record.bpmStatus && record.bpmStatus !== '1',
|
||||||
}
|
}
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle == 'link'>
|
<#if btn.buttonStyle == 'link'>
|
||||||
,{
|
,{
|
||||||
label: '${btn.buttonName}',
|
label: '${btn.buttonName}',
|
||||||
@ -559,7 +559,7 @@
|
|||||||
auth: '${entityPackage}:${tableName}:delete'
|
auth: '${entityPackage}:${tableName}:delete'
|
||||||
}
|
}
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle == 'link'>
|
<#if btn.buttonStyle == 'link'>
|
||||||
,{
|
,{
|
||||||
label: '${btn.buttonName}',
|
label: '${btn.buttonName}',
|
||||||
@ -597,7 +597,7 @@
|
|||||||
}
|
}
|
||||||
</#if>
|
</#if>
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle=='button'>
|
<#if btn.buttonStyle=='button'>
|
||||||
function handle${btn.buttonCode?cap_first}(){
|
function handle${btn.buttonCode?cap_first}(){
|
||||||
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="p-2 cgformErpList">
|
<div class="p-2 cgformErpList">
|
||||||
<#assign list_need_category=false>
|
<#assign list_need_category=false>
|
||||||
<#assign list_need_pca=false>
|
<#assign list_need_pca=false>
|
||||||
@ -33,7 +33,7 @@
|
|||||||
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
||||||
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle == 'button'>
|
<#if btn.buttonStyle == 'button'>
|
||||||
<a-button type="primary" @click="handle${btn.buttonCode?cap_first}" <#if btn.buttonIcon??> preIcon="ant-design:${btn.buttonIcon}" </#if>>${btn.buttonName}</a-button>
|
<a-button type="primary" @click="handle${btn.buttonCode?cap_first}" <#if btn.buttonIcon??> preIcon="ant-design:${btn.buttonIcon}" </#if>>${btn.buttonName}</a-button>
|
||||||
</#if>
|
</#if>
|
||||||
@ -350,7 +350,7 @@
|
|||||||
ifShow: !!record.bpmStatus && record.bpmStatus !== '1',
|
ifShow: !!record.bpmStatus && record.bpmStatus !== '1',
|
||||||
}
|
}
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle == 'link'>
|
<#if btn.buttonStyle == 'link'>
|
||||||
,{
|
,{
|
||||||
label: '${btn.buttonName}',
|
label: '${btn.buttonName}',
|
||||||
@ -385,7 +385,7 @@
|
|||||||
auth: '${entityPackage}:${tableName}:delete'
|
auth: '${entityPackage}:${tableName}:delete'
|
||||||
}
|
}
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle == 'link'>
|
<#if btn.buttonStyle == 'link'>
|
||||||
,{
|
,{
|
||||||
label: '${btn.buttonName}',
|
label: '${btn.buttonName}',
|
||||||
@ -444,7 +444,7 @@
|
|||||||
</#if>
|
</#if>
|
||||||
|
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle=='button'>
|
<#if btn.buttonStyle=='button'>
|
||||||
function handle${btn.buttonCode?cap_first}(){
|
function handle${btn.buttonCode?cap_first}(){
|
||||||
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
||||||
|
|||||||
@ -107,7 +107,7 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle=='form'>
|
<#if btn.buttonStyle=='form'>
|
||||||
function handle${btn.buttonCode?cap_first}(){
|
function handle${btn.buttonCode?cap_first}(){
|
||||||
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
||||||
|
|||||||
@ -114,7 +114,7 @@
|
|||||||
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
||||||
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle == 'button'>
|
<#if btn.buttonStyle == 'button'>
|
||||||
<a-button type="primary" @click="handle${btn.buttonCode?cap_first}" <#if btn.buttonIcon??> preIcon="ant-design:${btn.buttonIcon}" </#if>>${btn.buttonName}</a-button>
|
<a-button type="primary" @click="handle${btn.buttonCode?cap_first}" <#if btn.buttonIcon??> preIcon="ant-design:${btn.buttonIcon}" </#if>>${btn.buttonName}</a-button>
|
||||||
</#if>
|
</#if>
|
||||||
@ -390,7 +390,7 @@
|
|||||||
ifShow: !!record.bpmStatus && record.bpmStatus !== '1',
|
ifShow: !!record.bpmStatus && record.bpmStatus !== '1',
|
||||||
},
|
},
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle == 'link'>
|
<#if btn.buttonStyle == 'link'>
|
||||||
,{
|
,{
|
||||||
label: '${btn.buttonName}',
|
label: '${btn.buttonName}',
|
||||||
@ -427,7 +427,7 @@
|
|||||||
auth: '${entityPackage}:${tableName}:delete'
|
auth: '${entityPackage}:${tableName}:delete'
|
||||||
}
|
}
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle == 'link'>
|
<#if btn.buttonStyle == 'link'>
|
||||||
,{
|
,{
|
||||||
label: '${btn.buttonName}',
|
label: '${btn.buttonName}',
|
||||||
@ -465,7 +465,7 @@
|
|||||||
}
|
}
|
||||||
</#if>
|
</#if>
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle=='button'>
|
<#if btn.buttonStyle=='button'>
|
||||||
function handle${btn.buttonCode?cap_first}(){
|
function handle${btn.buttonCode?cap_first}(){
|
||||||
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
||||||
|
|||||||
@ -80,7 +80,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle=='form'>
|
<#if btn.buttonStyle=='form'>
|
||||||
function handle${btn.buttonCode?cap_first}(){
|
function handle${btn.buttonCode?cap_first}(){
|
||||||
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<#-- ** 引入全局工具方法 ** -->
|
<#-- ** 引入全局工具方法 ** -->
|
||||||
<#include "/common/utils.ftl">
|
<#include "/common/utils.ftl">
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
@ -45,7 +45,7 @@
|
|||||||
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
||||||
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle == 'button'>
|
<#if btn.buttonStyle == 'button'>
|
||||||
<a-button type="primary" @click="handle${btn.buttonCode?cap_first}" <#if btn.buttonIcon??> preIcon="${btn.buttonIcon}" </#if>>${btn.buttonName}</a-button>
|
<a-button type="primary" @click="handle${btn.buttonCode?cap_first}" <#if btn.buttonIcon??> preIcon="${btn.buttonIcon}" </#if>>${btn.buttonName}</a-button>
|
||||||
</#if>
|
</#if>
|
||||||
@ -355,7 +355,7 @@
|
|||||||
ifShow: !!record.bpmStatus && record.bpmStatus !== '1',
|
ifShow: !!record.bpmStatus && record.bpmStatus !== '1',
|
||||||
}
|
}
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle == 'link'>
|
<#if btn.buttonStyle == 'link'>
|
||||||
,{
|
,{
|
||||||
label: '${btn.buttonName}',
|
label: '${btn.buttonName}',
|
||||||
@ -391,7 +391,7 @@
|
|||||||
auth: '${entityPackage}:${tableName}:delete'
|
auth: '${entityPackage}:${tableName}:delete'
|
||||||
}
|
}
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle == 'link'>
|
<#if btn.buttonStyle == 'link'>
|
||||||
,{
|
,{
|
||||||
label: '${btn.buttonName}',
|
label: '${btn.buttonName}',
|
||||||
@ -450,7 +450,7 @@
|
|||||||
</#if>
|
</#if>
|
||||||
|
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle=='button'>
|
<#if btn.buttonStyle=='button'>
|
||||||
function handle${btn.buttonCode?cap_first}(){
|
function handle${btn.buttonCode?cap_first}(){
|
||||||
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<#include "/common/utils.ftl">
|
<#include "/common/utils.ftl">
|
||||||
<template>
|
<template>
|
||||||
<#assign buttonList=[]>
|
<#assign buttonList=[]>
|
||||||
<#if tableVo.extendParams?? && tableVo.extendParams.cgButtonList??>
|
<#if tableVo.extendParams?? && tableVo.extendParams.cgButtonList??>
|
||||||
@ -253,7 +253,7 @@
|
|||||||
</#list>
|
</#list>
|
||||||
};
|
};
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle=='form'>
|
<#if btn.buttonStyle=='form'>
|
||||||
function handle${btn.buttonCode?cap_first}(){
|
function handle${btn.buttonCode?cap_first}(){
|
||||||
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<#assign list_need_category=false>
|
<#assign list_need_category=false>
|
||||||
<#assign list_need_pca=false>
|
<#assign list_need_pca=false>
|
||||||
@ -32,7 +32,7 @@
|
|||||||
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
||||||
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle == 'button'>
|
<#if btn.buttonStyle == 'button'>
|
||||||
<a-button type="primary" @click="handle${btn.buttonCode?cap_first}" <#if btn.buttonIcon??> preIcon="${btn.buttonIcon}" </#if>>${btn.buttonName}</a-button>
|
<a-button type="primary" @click="handle${btn.buttonCode?cap_first}" <#if btn.buttonIcon??> preIcon="${btn.buttonIcon}" </#if>>${btn.buttonName}</a-button>
|
||||||
</#if>
|
</#if>
|
||||||
@ -330,7 +330,7 @@
|
|||||||
ifShow: !!record.bpmStatus && record.bpmStatus !== '1',
|
ifShow: !!record.bpmStatus && record.bpmStatus !== '1',
|
||||||
}
|
}
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle == 'link'>
|
<#if btn.buttonStyle == 'link'>
|
||||||
,{
|
,{
|
||||||
label: '${btn.buttonName}',
|
label: '${btn.buttonName}',
|
||||||
@ -366,7 +366,7 @@
|
|||||||
auth: '${entityPackage}:${tableName}:delete'
|
auth: '${entityPackage}:${tableName}:delete'
|
||||||
}
|
}
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle == 'link'>
|
<#if btn.buttonStyle == 'link'>
|
||||||
,{
|
,{
|
||||||
label: '${btn.buttonName}',
|
label: '${btn.buttonName}',
|
||||||
@ -425,7 +425,7 @@
|
|||||||
</#if>
|
</#if>
|
||||||
|
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle=='button'>
|
<#if btn.buttonStyle=='button'>
|
||||||
function handle${btn.buttonCode?cap_first}(){
|
function handle${btn.buttonCode?cap_first}(){
|
||||||
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<#include "/common/utils.ftl">
|
<#include "/common/utils.ftl">
|
||||||
<template>
|
<template>
|
||||||
<#assign buttonList=[]>
|
<#assign buttonList=[]>
|
||||||
<#if tableVo.extendParams?? && tableVo.extendParams.cgButtonList??>
|
<#if tableVo.extendParams?? && tableVo.extendParams.cgButtonList??>
|
||||||
@ -253,7 +253,7 @@
|
|||||||
</#list>
|
</#list>
|
||||||
};
|
};
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle=='form'>
|
<#if btn.buttonStyle=='form'>
|
||||||
function handle${btn.buttonCode?cap_first}(){
|
function handle${btn.buttonCode?cap_first}(){
|
||||||
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<#include "/common/utils.ftl">
|
<#include "/common/utils.ftl">
|
||||||
<template>
|
<template>
|
||||||
<div class="p-2">
|
<div class="p-2">
|
||||||
<#assign query_field_no=0>
|
<#assign query_field_no=0>
|
||||||
@ -113,7 +113,7 @@
|
|||||||
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
||||||
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle == 'button'>
|
<#if btn.buttonStyle == 'button'>
|
||||||
<a-button type="primary" @click="handle${btn.buttonCode?cap_first}" <#if btn.buttonIcon??> preIcon="${btn.buttonIcon}" </#if>>${btn.buttonName}</a-button>
|
<a-button type="primary" @click="handle${btn.buttonCode?cap_first}" <#if btn.buttonIcon??> preIcon="${btn.buttonIcon}" </#if>>${btn.buttonName}</a-button>
|
||||||
</#if>
|
</#if>
|
||||||
@ -364,7 +364,7 @@
|
|||||||
ifShow: !!record.bpmStatus && record.bpmStatus !== '1',
|
ifShow: !!record.bpmStatus && record.bpmStatus !== '1',
|
||||||
}
|
}
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle == 'link'>
|
<#if btn.buttonStyle == 'link'>
|
||||||
,{
|
,{
|
||||||
label: '${btn.buttonName}',
|
label: '${btn.buttonName}',
|
||||||
@ -401,7 +401,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle == 'link'>
|
<#if btn.buttonStyle == 'link'>
|
||||||
,{
|
,{
|
||||||
label: '${btn.buttonName}',
|
label: '${btn.buttonName}',
|
||||||
@ -441,7 +441,7 @@
|
|||||||
</#if>
|
</#if>
|
||||||
|
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle=='button'>
|
<#if btn.buttonStyle=='button'>
|
||||||
function handle${btn.buttonCode?cap_first}(){
|
function handle${btn.buttonCode?cap_first}(){
|
||||||
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<#include "/common/utils.ftl">
|
<#include "/common/utils.ftl">
|
||||||
<template>
|
<template>
|
||||||
<#assign buttonList=[]>
|
<#assign buttonList=[]>
|
||||||
<#if tableVo.extendParams?? && tableVo.extendParams.cgButtonList??>
|
<#if tableVo.extendParams?? && tableVo.extendParams.cgButtonList??>
|
||||||
@ -59,7 +59,7 @@
|
|||||||
closeModal();
|
closeModal();
|
||||||
}
|
}
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle=='form'>
|
<#if btn.buttonStyle=='form'>
|
||||||
function handle${btn.buttonCode?cap_first}(){
|
function handle${btn.buttonCode?cap_first}(){
|
||||||
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
||||||
@ -75,7 +75,7 @@
|
|||||||
handleSubmit,
|
handleSubmit,
|
||||||
submitSuccess,
|
submitSuccess,
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle=='form'>
|
<#if btn.buttonStyle=='form'>
|
||||||
handle${btn.buttonCode?cap_first},
|
handle${btn.buttonCode?cap_first},
|
||||||
</#if>
|
</#if>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<#assign list_need_category=false>
|
<#assign list_need_category=false>
|
||||||
<#assign list_need_pca=false>
|
<#assign list_need_pca=false>
|
||||||
@ -32,7 +32,7 @@
|
|||||||
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
<a-button type="primary" v-auth="'${entityPackage}:${tableName}:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
||||||
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
<j-upload-button type="primary" v-auth="'${entityPackage}:${tableName}:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle == 'button'>
|
<#if btn.buttonStyle == 'button'>
|
||||||
<a-button type="primary" @click="handle${btn.buttonCode?cap_first}" <#if btn.buttonIcon??> preIcon="${btn.buttonIcon}" </#if>>${btn.buttonName}</a-button>
|
<a-button type="primary" @click="handle${btn.buttonCode?cap_first}" <#if btn.buttonIcon??> preIcon="${btn.buttonIcon}" </#if>>${btn.buttonName}</a-button>
|
||||||
</#if>
|
</#if>
|
||||||
@ -329,7 +329,7 @@
|
|||||||
ifShow: !!record.bpmStatus && record.bpmStatus !== '1',
|
ifShow: !!record.bpmStatus && record.bpmStatus !== '1',
|
||||||
}
|
}
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle == 'link'>
|
<#if btn.buttonStyle == 'link'>
|
||||||
,{
|
,{
|
||||||
label: '${btn.buttonName}',
|
label: '${btn.buttonName}',
|
||||||
@ -365,7 +365,7 @@
|
|||||||
auth: '${entityPackage}:${tableName}:delete'
|
auth: '${entityPackage}:${tableName}:delete'
|
||||||
}
|
}
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle == 'link'>
|
<#if btn.buttonStyle == 'link'>
|
||||||
,{
|
,{
|
||||||
label: '${btn.buttonName}',
|
label: '${btn.buttonName}',
|
||||||
@ -424,7 +424,7 @@
|
|||||||
</#if>
|
</#if>
|
||||||
|
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle=='button'>
|
<#if btn.buttonStyle=='button'>
|
||||||
function handle${btn.buttonCode?cap_first}(){
|
function handle${btn.buttonCode?cap_first}(){
|
||||||
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<#include "/common/utils.ftl">
|
<#include "/common/utils.ftl">
|
||||||
<template>
|
<template>
|
||||||
<#assign buttonList=[]>
|
<#assign buttonList=[]>
|
||||||
<#if tableVo.extendParams?? && tableVo.extendParams.cgButtonList??>
|
<#if tableVo.extendParams?? && tableVo.extendParams.cgButtonList??>
|
||||||
@ -286,7 +286,7 @@
|
|||||||
</#list>
|
</#list>
|
||||||
};
|
};
|
||||||
<#if buttonList?size gt 0>
|
<#if buttonList?size gt 0>
|
||||||
<#list buttonList?filter(it -> it.orderNum?? && it.orderNum != null)?sort_by("orderNum") as btn>
|
<#list buttonList as btn>
|
||||||
<#if btn.buttonStyle=='form'>
|
<#if btn.buttonStyle=='form'>
|
||||||
function handle${btn.buttonCode?cap_first}(){
|
function handle${btn.buttonCode?cap_first}(){
|
||||||
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
createMessage.info('点击了${btn.buttonName}按钮,对应的业务逻辑需自行实现!');
|
||||||
|
|||||||
@ -0,0 +1,3 @@
|
|||||||
|
-- author:scott---date:20251212--for:在线用户接口权限配置
|
||||||
|
INSERT INTO `sys_permission` (`id`, `parent_id`, `name`, `url`, `component`, `is_route`, `component_name`, `redirect`, `menu_type`, `perms`, `perms_type`, `sort_no`, `always_show`, `icon`, `is_leaf`, `keep_alive`, `hidden`, `hide_tab`, `description`, `create_by`, `create_time`, `update_by`, `update_time`, `del_flag`, `rule_flag`, `status`, `internal_or_external`) VALUES ('1999406402585542657', '1594930803956920321', '在线用户列表接口', NULL, NULL, 0, NULL, NULL, 2, 'system:online:list', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-12-12 17:10:08', NULL, NULL, 0, 0, '1', 0);
|
||||||
|
INSERT INTO `sys_permission` (`id`, `parent_id`, `name`, `url`, `component`, `is_route`, `component_name`, `redirect`, `menu_type`, `perms`, `perms_type`, `sort_no`, `always_show`, `icon`, `is_leaf`, `keep_alive`, `hidden`, `hide_tab`, `description`, `create_by`, `create_time`, `update_by`, `update_time`, `del_flag`, `rule_flag`, `status`, `internal_or_external`) VALUES ('1999406500300242946', '1594930803956920321', '强制用户退出接口', NULL, NULL, 0, NULL, NULL, 2, 'system:online:forceLogout', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-12-12 17:10:32', NULL, NULL, 0, 0, '1', 0);
|
||||||
@ -132,6 +132,11 @@
|
|||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.platform</groupId>
|
||||||
|
<artifactId>junit-platform-launcher</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
<!-- Lombok -->
|
<!-- Lombok -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
|
|||||||
@ -38,7 +38,10 @@ export function usePagination(props: JVxeTableProps, methods: JVxeTableMethods)
|
|||||||
|
|
||||||
function handleShowSizeChange(current, pageSize) {
|
function handleShowSizeChange(current, pageSize) {
|
||||||
innerPagination.pageSize = pageSize;
|
innerPagination.pageSize = pageSize;
|
||||||
methods.trigger('pageChange', { current, pageSize });
|
// -update-begin--author:liaozhiyang---date:20251209---for:【issues/9169】切换页码时,pageChange事件加载了两次
|
||||||
|
// 因为 handleShowSizeChange先触发,紧接着会触发 handleChange,所以可以注释掉。
|
||||||
|
// methods.trigger('pageChange', { current, pageSize });
|
||||||
|
// -update-end--author:liaozhiyang---date:20251209---for:【issues/9169】切换页码时,pageChange事件加载了两次
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 渲染分页器 */
|
/** 渲染分页器 */
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
/**
|
/**
|
||||||
* @description: menu type
|
* @description: 默认四种菜单主题
|
||||||
*/
|
*/
|
||||||
export enum MenuTypeEnum {
|
export enum MenuTypeEnum {
|
||||||
// left menu
|
// 左侧边菜单导航风格
|
||||||
SIDEBAR = 'sidebar',
|
SIDEBAR = 'sidebar',
|
||||||
|
// 顶部栏导航风格
|
||||||
MIX_SIDEBAR = 'mix-sidebar',
|
|
||||||
// mixin menu
|
|
||||||
MIX = 'mix',
|
MIX = 'mix',
|
||||||
// top menu
|
// 侧边折叠导航风格
|
||||||
|
MIX_SIDEBAR = 'mix-sidebar',
|
||||||
|
//顶部混合导航风格
|
||||||
TOP_MENU = 'top-menu',
|
TOP_MENU = 'top-menu',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -132,8 +132,8 @@ export function useListPage(options: ListPageOptions) {
|
|||||||
for (const column of columns) {
|
for (const column of columns) {
|
||||||
if(!column.defaultHidden){
|
if(!column.defaultHidden){
|
||||||
let dataIndex = column?.dataIndex;
|
let dataIndex = column?.dataIndex;
|
||||||
if(column?.dataIndex!.toString().indexOf('_dictText')){
|
if(column?.dataIndex?.toString()?.indexOf('_dictText') !== -1){
|
||||||
dataIndex = column?.dataIndex!.toString().replace('_dictText','')
|
dataIndex = column?.dataIndex?.toString().replace('_dictText','')
|
||||||
}
|
}
|
||||||
exportFields.push(dataIndex);
|
exportFields.push(dataIndex);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -9,8 +9,7 @@ import { changeTheme } from '/@/logics/theme';
|
|||||||
import { updateDarkTheme } from '/@/logics/theme/dark';
|
import { updateDarkTheme } from '/@/logics/theme/dark';
|
||||||
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
|
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
|
||||||
import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum';
|
import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum';
|
||||||
import { HEADER_PRESET_BG_COLOR_LIST, SIDE_BAR_BG_COLOR_LIST } from '/@/settings/designSetting';
|
import { getConfigByMenuType } from '../../../utils/getConfigByMenuType';
|
||||||
import { getThemeColorByMenuType } from '/@/utils/getThemeColorByMenuType';
|
|
||||||
import { isObject } from '/@/utils/is';
|
import { isObject } from '/@/utils/is';
|
||||||
import { ThemeEnum } from '/@/enums/appEnum';
|
import { ThemeEnum } from '/@/enums/appEnum';
|
||||||
import { APP__THEME__COLOR } from '/@/enums/cacheEnum';
|
import { APP__THEME__COLOR } from '/@/enums/cacheEnum';
|
||||||
@ -27,10 +26,10 @@ export function layoutHandler(event: HandlerEnum, value: any) {
|
|||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const darkMode = appStore.getDarkMode === ThemeEnum.DARK;
|
const darkMode = appStore.getDarkMode === ThemeEnum.DARK;
|
||||||
// 根据菜单类型动态获取主题色
|
// 根据菜单类型动态获取主题色
|
||||||
const dynamicThemeColor = getThemeColorByMenuType(value.type);
|
const {themeColor: dynamicThemeColor, headerBgColor, sideBgColor } = getConfigByMenuType(value.type);
|
||||||
if (isHTopMenu) {
|
if (isHTopMenu) {
|
||||||
baseHandler(event, value);
|
baseHandler(event, value);
|
||||||
baseHandler(HandlerEnum.HEADER_THEME, HEADER_PRESET_BG_COLOR_LIST[4]);
|
baseHandler(HandlerEnum.HEADER_THEME, headerBgColor);
|
||||||
baseHandler(HandlerEnum.CHANGE_THEME_COLOR, dynamicThemeColor);
|
baseHandler(HandlerEnum.CHANGE_THEME_COLOR, dynamicThemeColor);
|
||||||
if (darkMode) {
|
if (darkMode) {
|
||||||
updateHeaderBgColor();
|
updateHeaderBgColor();
|
||||||
@ -39,8 +38,8 @@ export function layoutHandler(event: HandlerEnum, value: any) {
|
|||||||
baseHandler(HandlerEnum.TABS_THEME, tabsThemeOptions[1].value);
|
baseHandler(HandlerEnum.TABS_THEME, tabsThemeOptions[1].value);
|
||||||
} else if (isMixMenu) {
|
} else if (isMixMenu) {
|
||||||
baseHandler(event, value);
|
baseHandler(event, value);
|
||||||
baseHandler(HandlerEnum.HEADER_THEME, HEADER_PRESET_BG_COLOR_LIST[2]);
|
baseHandler(HandlerEnum.HEADER_THEME, headerBgColor);
|
||||||
baseHandler(HandlerEnum.MENU_THEME, SIDE_BAR_BG_COLOR_LIST[3]);
|
baseHandler(HandlerEnum.MENU_THEME, sideBgColor);
|
||||||
if (darkMode) {
|
if (darkMode) {
|
||||||
updateHeaderBgColor();
|
updateHeaderBgColor();
|
||||||
updateSidebarBgColor();
|
updateSidebarBgColor();
|
||||||
@ -51,8 +50,8 @@ export function layoutHandler(event: HandlerEnum, value: any) {
|
|||||||
} else if (isMixSidebarMenu) {
|
} else if (isMixSidebarMenu) {
|
||||||
baseHandler(event, value);
|
baseHandler(event, value);
|
||||||
baseHandler(HandlerEnum.CHANGE_THEME_COLOR, dynamicThemeColor);
|
baseHandler(HandlerEnum.CHANGE_THEME_COLOR, dynamicThemeColor);
|
||||||
baseHandler(HandlerEnum.HEADER_THEME, HEADER_PRESET_BG_COLOR_LIST[0]);
|
baseHandler(HandlerEnum.HEADER_THEME, headerBgColor);
|
||||||
baseHandler(HandlerEnum.MENU_THEME, SIDE_BAR_BG_COLOR_LIST[0]);
|
baseHandler(HandlerEnum.MENU_THEME, sideBgColor);
|
||||||
if (darkMode) {
|
if (darkMode) {
|
||||||
updateHeaderBgColor();
|
updateHeaderBgColor();
|
||||||
updateSidebarBgColor();
|
updateSidebarBgColor();
|
||||||
@ -60,8 +59,8 @@ export function layoutHandler(event: HandlerEnum, value: any) {
|
|||||||
baseHandler(HandlerEnum.TABS_THEME, tabsThemeOptions[1].value);
|
baseHandler(HandlerEnum.TABS_THEME, tabsThemeOptions[1].value);
|
||||||
} else {
|
} else {
|
||||||
baseHandler(event, value);
|
baseHandler(event, value);
|
||||||
baseHandler(HandlerEnum.HEADER_THEME, HEADER_PRESET_BG_COLOR_LIST[4]);
|
baseHandler(HandlerEnum.HEADER_THEME, headerBgColor);
|
||||||
baseHandler(HandlerEnum.MENU_THEME, SIDE_BAR_BG_COLOR_LIST[7]);
|
baseHandler(HandlerEnum.MENU_THEME, sideBgColor);
|
||||||
if (darkMode) {
|
if (darkMode) {
|
||||||
updateHeaderBgColor();
|
updateHeaderBgColor();
|
||||||
updateSidebarBgColor();
|
updateSidebarBgColor();
|
||||||
|
|||||||
@ -50,7 +50,9 @@ export function useTabDropdown(tabContentProps: TabContentProps, getIsTabs: Comp
|
|||||||
} else {
|
} else {
|
||||||
// 【TV360X-1039】当只有首页和另一个tab页时关闭左侧禁用
|
// 【TV360X-1039】当只有首页和另一个tab页时关闭左侧禁用
|
||||||
const validTabList = tabStore.getTabList.filter((item) => !item?.meta?.affix);
|
const validTabList = tabStore.getTabList.filter((item) => !item?.meta?.affix);
|
||||||
return validTabList[0].path === state.current?.path;
|
// update-begin--author:liaozhiyang---date:20251128---for:【issues/9098】tabs标签页关闭异常
|
||||||
|
return validTabList[0]?.path === state.current?.path;
|
||||||
|
// update-end--author:liaozhiyang---date:20251128---for:【issues/9098】tabs标签页关闭异常
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// Close other
|
// Close other
|
||||||
|
|||||||
@ -10,11 +10,14 @@ import {
|
|||||||
SessionTimeoutProcessingEnum,
|
SessionTimeoutProcessingEnum,
|
||||||
TabsThemeEnum,
|
TabsThemeEnum,
|
||||||
} from '/@/enums/appEnum';
|
} from '/@/enums/appEnum';
|
||||||
import { SIDE_BAR_BG_COLOR_LIST, HEADER_PRESET_BG_COLOR_LIST } from './designSetting';
|
|
||||||
import { darkMode } from '/@/settings/designSetting';
|
import { darkMode } from '/@/settings/designSetting';
|
||||||
import { getThemeColorByMenuType } from '/@/utils/getThemeColorByMenuType';
|
import { getConfigByMenuType } from '../utils/getConfigByMenuType';
|
||||||
|
// 修改此属性,实现默认的四个系统主题快速切换
|
||||||
const menuType = MenuTypeEnum.SIDEBAR;
|
const menuType = MenuTypeEnum.SIDEBAR;
|
||||||
|
|
||||||
|
// update-begin--author:liaozhiyang---date:20251201---for【QQYUN-14176】修改一个配置就能切换默认四个主题,不需要额外修改颜色等
|
||||||
|
const { themeColor, headerBgColor, sideBgColor, split, mode } = getConfigByMenuType(menuType);
|
||||||
|
// update-end--author:liaozhiyang---date:20251201---for【QQYUN-14176】修改一个配置就能切换默认四个主题,不需要额外修改颜色等
|
||||||
// ! 改动后需要清空浏览器缓存
|
// ! 改动后需要清空浏览器缓存
|
||||||
const setting: ProjectConfig = {
|
const setting: ProjectConfig = {
|
||||||
// 是否显示SettingButton
|
// 是否显示SettingButton
|
||||||
@ -43,7 +46,7 @@ const setting: ProjectConfig = {
|
|||||||
// SessionTimeoutProcessingEnum.PAGE_COVERAGE: 生成登录弹窗,覆盖当前页面
|
// SessionTimeoutProcessingEnum.PAGE_COVERAGE: 生成登录弹窗,覆盖当前页面
|
||||||
sessionTimeoutProcessing: SessionTimeoutProcessingEnum.ROUTE_JUMP,
|
sessionTimeoutProcessing: SessionTimeoutProcessingEnum.ROUTE_JUMP,
|
||||||
// 项目主题色 - 根据导航栏模式确定主题色动态设置
|
// 项目主题色 - 根据导航栏模式确定主题色动态设置
|
||||||
themeColor: getThemeColorByMenuType(menuType),
|
themeColor: themeColor,
|
||||||
// 项目主题模式
|
// 项目主题模式
|
||||||
themeMode: darkMode,
|
themeMode: darkMode,
|
||||||
|
|
||||||
@ -71,7 +74,7 @@ const setting: ProjectConfig = {
|
|||||||
// 头部配置
|
// 头部配置
|
||||||
headerSetting: {
|
headerSetting: {
|
||||||
// 背景色
|
// 背景色
|
||||||
bgColor: HEADER_PRESET_BG_COLOR_LIST[4],
|
bgColor: headerBgColor,
|
||||||
// 固定头部
|
// 固定头部
|
||||||
fixed: true,
|
fixed: true,
|
||||||
// 是否显示顶部
|
// 是否显示顶部
|
||||||
@ -93,7 +96,7 @@ const setting: ProjectConfig = {
|
|||||||
// 菜单配置
|
// 菜单配置
|
||||||
menuSetting: {
|
menuSetting: {
|
||||||
// 背景色
|
// 背景色
|
||||||
bgColor: SIDE_BAR_BG_COLOR_LIST[0],
|
bgColor: sideBgColor,
|
||||||
// 是否固定住左侧菜单
|
// 是否固定住左侧菜单
|
||||||
fixed: true,
|
fixed: true,
|
||||||
// 菜单折叠
|
// 菜单折叠
|
||||||
@ -110,15 +113,15 @@ const setting: ProjectConfig = {
|
|||||||
// 菜单宽度
|
// 菜单宽度
|
||||||
menuWidth: 210,
|
menuWidth: 210,
|
||||||
// 菜单模式
|
// 菜单模式
|
||||||
mode: MenuModeEnum.INLINE,
|
mode,
|
||||||
// 菜单类型
|
// 菜单类型
|
||||||
type: MenuTypeEnum.SIDEBAR,
|
type: menuType,
|
||||||
// 菜单主题
|
// 菜单主题
|
||||||
theme: ThemeEnum.DARK,
|
theme: ThemeEnum.LIGHT,
|
||||||
// 左侧导航栏文字颜色调整区分彩色和暗黑 (不对应配置)
|
// 左侧导航栏文字颜色调整区分彩色和暗黑 (不对应配置)
|
||||||
isThemeBright: false,
|
isThemeBright: false,
|
||||||
// 分割菜单
|
// 分割菜单
|
||||||
split: false,
|
split,
|
||||||
// 顶部菜单布局
|
// 顶部菜单布局
|
||||||
topMenuAlign: 'center',
|
topMenuAlign: 'center',
|
||||||
// 折叠触发器的位置
|
// 折叠触发器的位置
|
||||||
|
|||||||
@ -45,15 +45,17 @@ const render = {
|
|||||||
*/
|
*/
|
||||||
renderDict: (v, code, renderTag = false) => {
|
renderDict: (v, code, renderTag = false) => {
|
||||||
let text = '';
|
let text = '';
|
||||||
|
let color = '';
|
||||||
let array = getDictItemsByCode(code) || [];
|
let array = getDictItemsByCode(code) || [];
|
||||||
let obj = array.filter((item) => {
|
let obj = array.filter((item) => {
|
||||||
return item.value == v;
|
return item.value == v;
|
||||||
});
|
});
|
||||||
if (obj.length > 0) {
|
if (obj.length > 0) {
|
||||||
text = obj[0].text;
|
text = obj[0].text;
|
||||||
|
color = obj[0].color;
|
||||||
}
|
}
|
||||||
//【jeecgboot-vue3/issues/903】render.renderDict使用tag渲染报警告问题 #903
|
//【jeecgboot-vue3/issues/903】render.renderDict使用tag渲染报警告问题 #903
|
||||||
return isEmpty(text) || !renderTag ? h('span', text) : h(Tag, () => text);
|
return isEmpty(text) || !renderTag ? h('span', text) : h(Tag,{ color }, () => text);
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* 渲染图片
|
* 渲染图片
|
||||||
|
|||||||
49
jeecgboot-vue3/src/utils/getConfigByMenuType.ts
Normal file
49
jeecgboot-vue3/src/utils/getConfigByMenuType.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import { MenuTypeEnum, MenuModeEnum } from '/@/enums/menuEnum';
|
||||||
|
import { APP_PRESET_COLOR_LIST, HEADER_PRESET_BG_COLOR_LIST, SIDE_BAR_BG_COLOR_LIST } from '/@/settings/designSetting';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据菜单类型和模式获取对应的主题色
|
||||||
|
* @param menuType 菜单类型
|
||||||
|
*/
|
||||||
|
export function getConfigByMenuType(menuType: MenuTypeEnum): {
|
||||||
|
themeColor: string;
|
||||||
|
headerBgColor: string;
|
||||||
|
sideBgColor: string;
|
||||||
|
split: boolean;
|
||||||
|
mode: MenuModeEnum;
|
||||||
|
} {
|
||||||
|
let themeColor;
|
||||||
|
let headerBgColor;
|
||||||
|
let sideBgColor;
|
||||||
|
let split = false;
|
||||||
|
let mode: MenuModeEnum = MenuModeEnum.INLINE;
|
||||||
|
if (menuType === MenuTypeEnum.TOP_MENU) {
|
||||||
|
// 顶部栏导航
|
||||||
|
themeColor = APP_PRESET_COLOR_LIST[1];
|
||||||
|
headerBgColor = HEADER_PRESET_BG_COLOR_LIST[4];
|
||||||
|
mode = MenuModeEnum.HORIZONTAL;
|
||||||
|
} else if (menuType === MenuTypeEnum.MIX) {
|
||||||
|
// 顶部混合菜单模式
|
||||||
|
themeColor = APP_PRESET_COLOR_LIST[2];
|
||||||
|
headerBgColor = HEADER_PRESET_BG_COLOR_LIST[2];
|
||||||
|
sideBgColor = SIDE_BAR_BG_COLOR_LIST[3];
|
||||||
|
split = true;
|
||||||
|
} else if (menuType === MenuTypeEnum.MIX_SIDEBAR) {
|
||||||
|
// 侧边折叠导航模式
|
||||||
|
themeColor = APP_PRESET_COLOR_LIST[1];
|
||||||
|
headerBgColor = HEADER_PRESET_BG_COLOR_LIST[0];
|
||||||
|
sideBgColor = SIDE_BAR_BG_COLOR_LIST[0];
|
||||||
|
} else if (menuType === MenuTypeEnum.SIDEBAR) {
|
||||||
|
// 侧边栏导航
|
||||||
|
themeColor = APP_PRESET_COLOR_LIST[1];
|
||||||
|
headerBgColor = HEADER_PRESET_BG_COLOR_LIST[4];
|
||||||
|
sideBgColor = SIDE_BAR_BG_COLOR_LIST[7];
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
themeColor,
|
||||||
|
headerBgColor,
|
||||||
|
sideBgColor,
|
||||||
|
split,
|
||||||
|
mode,
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -1,23 +0,0 @@
|
|||||||
import { MenuTypeEnum } from '/@/enums/menuEnum';
|
|
||||||
import { APP_PRESET_COLOR_LIST } from '/@/settings/designSetting';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据菜单类型和模式获取对应的主题色
|
|
||||||
* @param menuType 菜单类型
|
|
||||||
*/
|
|
||||||
export function getThemeColorByMenuType(menuType: MenuTypeEnum): string {
|
|
||||||
if (menuType === MenuTypeEnum.TOP_MENU) {
|
|
||||||
// 顶部栏导航
|
|
||||||
return APP_PRESET_COLOR_LIST[1];
|
|
||||||
} else if (menuType === MenuTypeEnum.MIX) {
|
|
||||||
// 顶部混合菜单使用青绿色主题
|
|
||||||
return APP_PRESET_COLOR_LIST[2];
|
|
||||||
} else if (menuType === MenuTypeEnum.MIX_SIDEBAR) {
|
|
||||||
// 侧边折叠导航模式
|
|
||||||
return APP_PRESET_COLOR_LIST[1];
|
|
||||||
} else if (menuType === MenuTypeEnum.SIDEBAR) {
|
|
||||||
// 侧边栏导航
|
|
||||||
return APP_PRESET_COLOR_LIST[1];
|
|
||||||
}
|
|
||||||
return APP_PRESET_COLOR_LIST[1];
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user