3 Commits

Author SHA1 Message Date
RoaringFlame
770910439e Pre Merge pull request !319 from RoaringFlame/k8s-deployment 2025-03-06 03:10:08 +00:00
java-ch
660162038a 更新k8s配置 2024-01-11 15:41:28 +08:00
Heng Chen
50b538ec80 增加k8s部署文件 2023-04-06 00:00:28 +08:00
228 changed files with 4715 additions and 3898 deletions

View File

@@ -1,11 +1,11 @@
<p align="center"> <p align="center">
<img alt="logo" src="https://oscimg.oschina.net/oscnet/up-b99b286755aef70355a7084753f89cdb7c9.png"> <img alt="logo" src="https://oscimg.oschina.net/oscnet/up-b99b286755aef70355a7084753f89cdb7c9.png">
</p> </p>
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.6.7</h1> <h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.6.5</h1>
<h4 align="center">基于 Vue/Element UI 和 Spring Boot/Spring Cloud & Alibaba 前后端分离的分布式微服务架构</h4> <h4 align="center">基于 Vue/Element UI 和 Spring Boot/Spring Cloud & Alibaba 前后端分离的分布式微服务架构</h4>
<p align="center"> <p align="center">
<a href="https://gitee.com/y_project/RuoYi-Cloud/stargazers"><img src="https://gitee.com/y_project/RuoYi-Cloud/badge/star.svg?theme=dark"></a> <a href="https://gitee.com/y_project/RuoYi-Cloud/stargazers"><img src="https://gitee.com/y_project/RuoYi-Cloud/badge/star.svg?theme=dark"></a>
<a href="https://gitee.com/y_project/RuoYi-Cloud"><img src="https://img.shields.io/badge/RuoYi-v3.6.7-brightgreen.svg"></a> <a href="https://gitee.com/y_project/RuoYi-Cloud"><img src="https://img.shields.io/badge/RuoYi-v3.6.5-brightgreen.svg"></a>
<a href="https://gitee.com/y_project/RuoYi-Cloud/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a> <a href="https://gitee.com/y_project/RuoYi-Cloud/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a>
</p> </p>
@@ -126,4 +126,4 @@ com.ruoyi
## 若依微服务交流群 ## 若依微服务交流群
QQ群 [![加入QQ群](https://img.shields.io/badge/已满-42799195-blue.svg)](https://jq.qq.com/?_wv=1027&k=yqInfq0S) [![加入QQ群](https://img.shields.io/badge/已满-170157040-blue.svg)](https://jq.qq.com/?_wv=1027&k=Oy1mb3p8) [![加入QQ群](https://img.shields.io/badge/已满-130643120-blue.svg)](https://jq.qq.com/?_wv=1027&k=rvxkJtXK) [![加入QQ群](https://img.shields.io/badge/已满-225920371-blue.svg)](https://jq.qq.com/?_wv=1027&k=0Ck3PvTe) [![加入QQ群](https://img.shields.io/badge/已满-201705537-blue.svg)](https://jq.qq.com/?_wv=1027&k=FnHHP4TT) [![加入QQ群](https://img.shields.io/badge/已满-236543183-blue.svg)](https://jq.qq.com/?_wv=1027&k=qdT1Ojpz) [![加入QQ群](https://img.shields.io/badge/已满-213618602-blue.svg)](https://jq.qq.com/?_wv=1027&k=nw3OiyXs) [![加入QQ群](https://img.shields.io/badge/已满-148794840-blue.svg)](https://jq.qq.com/?_wv=1027&k=kiU5WDls) [![加入QQ群](https://img.shields.io/badge/已满-118752664-blue.svg)](https://jq.qq.com/?_wv=1027&k=MtBy6YfT) [![加入QQ群](https://img.shields.io/badge/已满-101038945-blue.svg)](https://jq.qq.com/?_wv=1027&k=FqImHgH2) [![加入QQ群](https://img.shields.io/badge/已满-128355254-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=G4jZ4EtdT50PhnMBudTnEwgonxkXOscJ&authKey=FkGHYfoTKlGE6wHdKdjH9bVoOgQjtLP9WM%2Fj7pqGY1msoqw9uxDiBo39E2mLgzYg&noverify=0&group_code=128355254) [![加入QQ群](https://img.shields.io/badge/已满-179219821-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=irnwcXhbLOQEv1g-TwGifjNTA_f4wZiA&authKey=4bpzEwhcUY%2FvsPDHvzYn6xfoS%2FtOArvZ%2BGXzfr7O0%2FEqLfkKA%2BuCDXlzHIFg8t93&noverify=0&group_code=179219821) [![加入QQ群](https://img.shields.io/badge/已满-158753145-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=lx1uEdEDuxeM7rUvF3qmlFdqKqdJ5Z-R&authKey=rgyPW9yhhh4IIURKVFa6NgP3qiqH04WAzrJ0trsgkr3pjzm6sKIOGyA58oOjoj%2FJ&noverify=0&group_code=158753145) [![加入QQ群](https://img.shields.io/badge/112869560-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=Kuaw0Xdlw2Nlgn6s8h9elzuquHGxGObD&authKey=cSrQcWQ%2BzQZAFFrwxaR%2BbzcumX4WRduZnd1O6JO1dlclQMiu%2BKwxAy8t2JfNp67V&noverify=0&group_code=112869560) 点击按钮入群。 QQ群 [![加入QQ群](https://img.shields.io/badge/已满-42799195-blue.svg)](https://jq.qq.com/?_wv=1027&k=yqInfq0S) [![加入QQ群](https://img.shields.io/badge/已满-170157040-blue.svg)](https://jq.qq.com/?_wv=1027&k=Oy1mb3p8) [![加入QQ群](https://img.shields.io/badge/已满-130643120-blue.svg)](https://jq.qq.com/?_wv=1027&k=rvxkJtXK) [![加入QQ群](https://img.shields.io/badge/已满-225920371-blue.svg)](https://jq.qq.com/?_wv=1027&k=0Ck3PvTe) [![加入QQ群](https://img.shields.io/badge/已满-201705537-blue.svg)](https://jq.qq.com/?_wv=1027&k=FnHHP4TT) [![加入QQ群](https://img.shields.io/badge/已满-236543183-blue.svg)](https://jq.qq.com/?_wv=1027&k=qdT1Ojpz) [![加入QQ群](https://img.shields.io/badge/已满-213618602-blue.svg)](https://jq.qq.com/?_wv=1027&k=nw3OiyXs) [![加入QQ群](https://img.shields.io/badge/已满-148794840-blue.svg)](https://jq.qq.com/?_wv=1027&k=kiU5WDls) [![加入QQ群](https://img.shields.io/badge/已满-118752664-blue.svg)](https://jq.qq.com/?_wv=1027&k=MtBy6YfT) [![加入QQ群](https://img.shields.io/badge/已满-101038945-blue.svg)](https://jq.qq.com/?_wv=1027&k=FqImHgH2) [![加入QQ群](https://img.shields.io/badge/已满-128355254-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=G4jZ4EtdT50PhnMBudTnEwgonxkXOscJ&authKey=FkGHYfoTKlGE6wHdKdjH9bVoOgQjtLP9WM%2Fj7pqGY1msoqw9uxDiBo39E2mLgzYg&noverify=0&group_code=128355254) [![加入QQ群](https://img.shields.io/badge/已满-179219821-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=irnwcXhbLOQEv1g-TwGifjNTA_f4wZiA&authKey=4bpzEwhcUY%2FvsPDHvzYn6xfoS%2FtOArvZ%2BGXzfr7O0%2FEqLfkKA%2BuCDXlzHIFg8t93&noverify=0&group_code=179219821) [![加入QQ群](https://img.shields.io/badge/158753145-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=lx1uEdEDuxeM7rUvF3qmlFdqKqdJ5Z-R&authKey=rgyPW9yhhh4IIURKVFa6NgP3qiqH04WAzrJ0trsgkr3pjzm6sKIOGyA58oOjoj%2FJ&noverify=0&group_code=158753145) 点击按钮入群。

54
deployment/README.md Normal file
View File

@@ -0,0 +1,54 @@
# Kubernates 部署Ruoyi-Cloud项目
本部署所用到的k8s配置均为简易版仅作为初步入门学习使用有不合理的地方还请见谅。
### 后期考虑功能:
* HPA自动扩缩容
* MySQL主从、Redis集群、服务集群
* ELK日志收集
## 容器分布
~~~
namespace
├── redis
│ └── redis // StatefulSet
├── kube-ruoyi
│ └── ruoyi-mysql // Deployment
│ └── ruoyi-nacos
│ └── ruoyi-nginx
│ └── ruoyi-sentinel
│ └── ruoyi-gateway
│ └── ruoyi-auth
│ └── ruoyi-system
│ └── ruoyi-gen
│ └── ruoyi-job
│ └── ruoyi-file
│ └── ruoyi-monitor
│ └── elasticsearch
│ └── skywalking
│ └── skywalking-ui
├── minio
│ └── minio
├── monitor-sa
│ └── node-exporter
│ └── prometheus-server
│ └── monitoring-grafana
~~~
## 部署顺序及要点
1. Redis
2. MySQL手动Dockerfile打包镜像初始化准备好的数据脚本。使用了Secret加密密码等配置。
3. Nacos, 配置好MODE=standalone使用configMap设置数据库。
4. Sentinel
5. Gateway本服务需要用Dockerfile打包镜像否则会报错。其他RuoYi服务可以直接使用spring-boot的image命令一键打包生成镜像[每个服务都有使用额外的SpringBoot配置文件bootstrap-k8s.yml加入到服务中同时在原配置文件中把active换成${SPRING_PROFILES_ACTIVE:dev}后再打包以读取deployment的env变量。启动服务前记得提前在nacos中克隆新增服务配置以把dev改成k8sdeployment中启动的环境是SPRING_PROFILES_ACTIVE=k8s修改好Redis地址redis.redis、MySQL地址(ruoyi-mysql)、Sentinel地址(ruoyi-sentinel)]
6. Nginx部署之前先打包好前端静态文件使用本地磁盘方式挂载到容器 (注我使用的是Window的DockerDesktop启动的K8s挂载磁盘路径必须带/run/desktop/mnt/host)修改好nginx配置ruoyi-gateway就可以启动启动后输入localhost:30080就可以访问前端项目
7. Auth
8. System配置好后就可以登录了
9. Gen
10. Job
11. File改成minio服务之后需要修改静态文件中读取文件的端口地址
12. Monitor需要修改前端静态文件中的Monitor端口地址
13. Minio挂载本地文件。修改ruoyi-file服务中@Primary注释改到MinioServer上以使用Minio服务记得修改nacos配置
14. Elasticsearch部署文件一并放入到了skywalking文件夹中
15. skywalking需要在Java服务中使用agent进行跟踪自制agent镜像然后使用initContainers方式挂载到同一个容器模板放到了agent-in-server文件
16. skywalking-ui

View File

@@ -0,0 +1,54 @@
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
name: minio
name: minio
namespace: minio
spec:
replicas: 1
selector:
matchLabels:
app: minio
template:
metadata:
labels:
app: minio
spec:
containers:
- name: minio
image: minio/minio
imagePullPolicy: Always
ports:
- containerPort: 9000
name: tcp
- containerPort: 9090
protocol: TCP
name: console
command:
- /bin/sh
- -c
- minio server /data --console-address ":9090"
env:
- name: MINIO_ACCESS_KEY
value: minioadmin
- name: MINIO_SECRET_KEY
value: minioadmin
readinessProbe:
failureThreshold: 3
httpGet:
path: /minio/health/ready
port: 9000
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 5
volumeMounts:
- mountPath: /data
name: minio-data
volumes:
- name: minio-data
hostPath:
path: /run/desktop/mnt/host/c/k8sVolume/minio/data
type: Directory

View File

@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: minio

View File

@@ -0,0 +1,20 @@
apiVersion: v1
kind: Service
metadata:
name: minio
namespace: minio
labels:
app: minio
spec:
type: NodePort
publishNotReadyAddresses: true
ports:
- port: 9000
name: tcp
targetPort: 9000
- port: 9090
name: console
targetPort: 9090
nodePort: 30090
selector:
app: minio

View File

@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: monitor-sa

View File

@@ -0,0 +1,63 @@
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: node-exporter
namespace: monitor-sa
labels:
name: node-exporter
spec:
selector:
matchLabels:
name: node-exporter
template:
metadata:
labels:
name: node-exporter
spec:
hostPID: true
hostIPC: true
hostNetwork: true # 共享宿主机网络和进程
containers:
- name: node-exporter
image: prom/node-exporter:v0.16.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9100 # 容器暴露端口为9100
resources:
requests:
cpu: 0.15
securityContext:
privileged: true # 开启特权模式
args:
- --path.procfs
- /host/proc
- --path.sysfs
- /host/sys
- --collector.filesystem.ignored-mount-points
- '"^/(sys|proc|dev|host|etc)($|/)"'
volumeMounts: # 挂载宿主机目录以收集宿主机信息
- name: dev
mountPath: /host/dev
- name: proc
mountPath: /host/proc
- name: sys
mountPath: /host/sys
- name: rootfs
mountPath: /rootfs
tolerations: # 定义容忍度使其可调度到默认有污点的master
- key: "node-role.kubernetes.io/master"
operator: "Exists"
effect: "NoSchedule"
volumes: # 定义存储卷
- name: proc
hostPath:
path: /proc
- name: dev
hostPath:
path: /dev
- name: sys
hostPath:
path: /sys
- name: rootfs
hostPath:
path: /

View File

@@ -0,0 +1,169 @@
apiVersion: v1
kind: ConfigMap #
metadata:
name: prometheus-config
namespace: kube-system
labels:
kubernetes.io/cluster-service: "true"
addonmanager.kubernetes.io/mode: EnsureExists
data:
prometheus.yml: |
rule_files:
- /etc/config/rules/*.rules
scrape_configs:
- job_name: prometheus
static_configs:
- targets:
- localhost:9090
- job_name: kubernetes-nodes
scrape_interval: 30s
static_configs:
- targets:
- 192.168.73.135:9100
- 192.168.73.138:9100
- 192.168.73.139:9100
- 192.168.73.140:9100
- job_name: kubernetes-apiservers
kubernetes_sd_configs:
- role: endpoints
relabel_configs:
- action: keep
regex: default;kubernetes;https
source_labels:
- __meta_kubernetes_namespace
- __meta_kubernetes_service_name
- __meta_kubernetes_endpoint_port_name
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
insecure_skip_verify: true
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
- job_name: kubernetes-nodes-kubelet
kubernetes_sd_configs:
- role: node
relabel_configs:
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
insecure_skip_verify: true
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
- job_name: kubernetes-nodes-cadvisor
kubernetes_sd_configs:
- role: node
relabel_configs:
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
- target_label: __metrics_path__
replacement: /metrics/cadvisor
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
insecure_skip_verify: true
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
- job_name: kubernetes-service-endpoints
kubernetes_sd_configs:
- role: endpoints
relabel_configs:
- action: keep
regex: true
source_labels:
- __meta_kubernetes_service_annotation_prometheus_io_scrape
- action: replace
regex: (https?)
source_labels:
- __meta_kubernetes_service_annotation_prometheus_io_scheme
target_label: __scheme__
- action: replace
regex: (.+)
source_labels:
- __meta_kubernetes_service_annotation_prometheus_io_path
target_label: __metrics_path__
- action: replace
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
source_labels:
- __address__
- __meta_kubernetes_service_annotation_prometheus_io_port
target_label: __address__
- action: labelmap
regex: __meta_kubernetes_service_label_(.+)
- action: replace
source_labels:
- __meta_kubernetes_namespace
target_label: kubernetes_namespace
- action: replace
source_labels:
- __meta_kubernetes_service_name
target_label: kubernetes_name
- job_name: kubernetes-services
kubernetes_sd_configs:
- role: service
metrics_path: /probe
params:
module:
- http_2xx
relabel_configs:
- action: keep
regex: true
source_labels:
- __meta_kubernetes_service_annotation_prometheus_io_probe
- source_labels:
- __address__
target_label: __param_target
- replacement: blackbox
target_label: __address__
- source_labels:
- __param_target
target_label: instance
- action: labelmap
regex: __meta_kubernetes_service_label_(.+)
- source_labels:
- __meta_kubernetes_namespace
target_label: kubernetes_namespace
- source_labels:
- __meta_kubernetes_service_name
target_label: kubernetes_name
- job_name: kubernetes-pods
kubernetes_sd_configs:
- role: pod
relabel_configs:
- action: keep
regex: true
source_labels:
- __meta_kubernetes_pod_annotation_prometheus_io_scrape
- action: replace
regex: (.+)
source_labels:
- __meta_kubernetes_pod_annotation_prometheus_io_path
target_label: __metrics_path__
- action: replace
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
source_labels:
- __address__
- __meta_kubernetes_pod_annotation_prometheus_io_port
target_label: __address__
- action: labelmap
regex: __meta_kubernetes_pod_label_(.+)
- action: replace
source_labels:
- __meta_kubernetes_namespace
target_label: kubernetes_namespace
- action: replace
source_labels:
- __meta_kubernetes_pod_name
target_label: kubernetes_pod_name
alerting:
alertmanagers:
- static_configs:
- targets: ["alertmanager:80"]

View File

@@ -0,0 +1 @@
存放sql目录下的所有脚本用于docker自动执行。

View File

@@ -0,0 +1,5 @@
# 基础镜像
FROM mysql:5.7
# 执行sql脚本
ADD ./db/*.sql /docker-entrypoint-initdb.d/

View File

@@ -0,0 +1,47 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: ruoyi-mysql #指定deployment的名字
namespace: kube-ruoyi
labels:
app: ruoyi-mysql-local
spec: #规约
replicas: 1 #pod的副本数量就是希望创建多少个pod的副本.可p选字段。它的默认值是1。
selector: #selector 字段定义 Deployment 如何查找要管理的 Pods。必须匹配 .spec.template.metadata.labels否则请求会被 API 拒绝。
matchLabels:
app: ruoyi-mysql-local
template: #Deployment Pod 模板;它和 Pod 的语法规则完全相同。 只是这里它是嵌套的,因此不需要 apiVersion 或 kind。
metadata:
labels:
app: ruoyi-mysql-local
spec: #pod模板规约
containers: #容器
- name: ruoyi-mysql #容器的名称
image: ruoyi/mysql:5.7 #容器使用的镜像
ports:
- containerPort: 3306
volumeMounts:
- name: mysql-local-data #pv的name
mountPath: /var/lib/mysql #MySQL容器的数据都是存在这个目录的要对这个目录做数据持久化
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom: # Read environment variables from kubernetes secrets
secretKeyRef:
name: ruoyi-mysql-secret
key: mysql-root-pass
- name: MYSQL_USER
valueFrom:
secretKeyRef:
name: ruoyi-mysql-secret
key: mysql-user
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: ruoyi-mysql-secret
key: mysql-password
volumes:
- name: mysql-local-data #pv的name
hostPath:
path: /run/desktop/mnt/host/c/k8sVolume/mysql/data
type: Directory
restartPolicy: Always #Deployment 中的 Pod 模板必须指定适当的标签和适当的重新启动策略。只有 .spec.template.spec.restartPolicy 等于 Always 才是被允许的,这也是在没有指定时的默认设置

View File

@@ -0,0 +1,29 @@
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-pv
namespace: kube-ruoyi
spec:
capacity:
storage: 3Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain # 手动删除
storageClassName: hostpath #表明这个pv所属的storageClass
hostPath:
path: /mnt/data #节点上卷的完整路径。必须是存在的路径不然容器无法创建deployment会报错可以是目录或块设备(磁盘、分区…)。
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pvc-local
namespace: kube-ruoyi
spec:
accessModes: #访问模式 申领在请求具有特定访问模式的存储时,使用与卷相同的访问模式约定。
- ReadWriteMany
volumeMode: Filesystem #卷模式
resources:
requests:
storage: 1Gi
storageClassName: hostpath # 此处须显式设置空字符串或指定值,否则会被设置为默认的 StorageClass

View File

@@ -0,0 +1,10 @@
apiVersion: v1
kind: Secret
metadata:
name: ruoyi-mysql-secret
namespace: kube-ruoyi
type: Opaque #base-64加密
data:
mysql-root-pass: cGFzc3dvcmQ=
mysql-user: YWRtaW4=
mysql-password: MTIzNDU2

View File

@@ -0,0 +1,12 @@
apiVersion: v1
kind: Service
metadata:
name: ruoyi-mysql
namespace: kube-ruoyi
spec:
ports:
- port: 3306
nodePort: 30060
selector:
app: ruoyi-mysql-local # 该 Service 会将所有具有标签 app: mysql-labels-app暴露到一个抽象的 Service 端口上targetPort容器接收流量的端口port可任意取值的抽象的 Service 端口,其他 Pod 通过该端口访问 Service
type: NodePort

View File

@@ -0,0 +1,31 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: ruoyi-nacos-config
namespace: kube-ruoyi
data:
application.properties: |
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://ruoyi-mysql:3306/ry-config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user=root
db.password=password
nacos.naming.empty-service.auto-clean=true
nacos.naming.empty-service.clean.initial-delay-ms=50000
nacos.naming.empty-service.clean.period-time-ms=30000
management.endpoints.web.exposure.include=*
management.metrics.export.elastic.enabled=false
management.metrics.export.influx.enabled=false
server.tomcat.accesslog.enabled=true
server.tomcat.accesslog.pattern=%h %l %u %t "%r" %s %b %D %{User-Agent}i %{Request-Source}i
server.tomcat.basedir=/home/ruoyi/nacos/tomcat/logs
nacos.security.ignore.urls=/,/error,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-ui/public/**,/v1/auth/**,/v1/console/health/**,/actuator/**,/v1/console/server/**
nacos.core.auth.system.type=nacos
nacos.core.auth.enabled=false
nacos.core.auth.plugin.nacos.token.expire.seconds=18000
nacos.core.auth.plugin.nacos.token.secret.key=SecretKey012345678901234567890123456789012345678901234567890123456789
nacos.core.auth.caching.enabled=true
nacos.core.auth.enable.userAgentAuthWhite=false
nacos.core.auth.server.identity.key=serverIdentity
nacos.core.auth.server.identity.value=security
nacos.istio.mcp.server.enabled=false

View File

@@ -0,0 +1,37 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: ruoyi-nacos
namespace: kube-ruoyi
spec:
replicas: 1
selector:
matchLabels:
app: ruoyi-nacos
template:
metadata:
labels:
app: ruoyi-nacos
spec:
containers:
- name: ruoyi-nacos
image: nacos/nacos-server
imagePullPolicy: Always
ports:
- containerPort: 8848
name: client
- containerPort: 9848
name: client-rpc
- containerPort: 9849
name: raft-rpc
env:
- name: MODE
value: standalone
volumeMounts:
- mountPath: /home/nacos/conf/application.properties
name: nacos-conf
subPath: application.properties
volumes:
- name: nacos-conf
configMap:
name: ruoyi-nacos-config

View File

@@ -0,0 +1,23 @@
apiVersion: v1
kind: Service
metadata:
name: ruoyi-nacos
namespace: kube-ruoyi
labels:
app: ruoyi-nacos
spec:
type: NodePort
publishNotReadyAddresses: true
ports:
- port: 8848
name: server
targetPort: 8848
nodePort: 30848
- port: 9848
name: client-rpc
targetPort: 9848
- port: 9849
name: raft-rpc
targetPort: 9849
selector:
app: ruoyi-nacos

View File

@@ -0,0 +1,37 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: ruoyi-nginx-config
namespace: kube-ruoyi
data:
nginx.conf: |
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root /home/ruoyi/projects/ruoyi-ui;
try_files $uri $uri/ /index.html;
index index.html index.htm;
}
location /prod-api/{
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://ruoyi-gateway:8080/;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}

View File

@@ -0,0 +1,53 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: ruoyi-nginx
namespace: kube-ruoyi
spec:
replicas: 1
selector:
matchLabels:
app: ruoyi-nginx
template:
metadata:
labels:
app: ruoyi-nginx
spec:
containers:
- name: ruoyi-nginx
image: nginx
imagePullPolicy: Always
ports:
- containerPort: 80
volumeMounts:
- mountPath: /etc/nginx/nginx.conf
name: nginx-conf
subPath: nginx.conf
- mountPath: /home/ruoyi/projects/ruoyi-ui
name: local-path #/usr/share/nginx/html 挂载到volumes中server+path
volumes:
- name: nginx-conf
configMap:
name: ruoyi-nginx-config
- name: local-path
hostPath:
path: /run/desktop/mnt/host/c/k8sVolume/dist
type: Directory
---
apiVersion: v1
kind: Service
metadata:
name: ruoyi-nginx
namespace: kube-ruoyi
labels:
name: ruoyi-nginx
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 30080
selector:
app: ruoyi-nginx

View File

@@ -0,0 +1,58 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: redis-config
namespace: redis
data:
redis.conf: |-
maxmemory 1000mb
maxmemory-policy allkeys-lru
protected-mode no
tcp-backlog 511
daemonize no
supervised no
dir /data
pidfile /data/redis_6379.pid
port 6379
loglevel notice
logfile ""
databases 16
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
replica-serve-stale-data yes
replica-read-only no
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
replica-priority 100
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
replica-lazy-flush no
appendonly no
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble yes
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
set-max-intset-entries 512
hll-sparse-max-bytes 3000
stream-node-max-bytes 4096
stream-node-max-entries 100
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit replica 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
dynamic-hz yes
aof-rewrite-incremental-fsync yes
rdb-save-incremental-fsync yes

View File

@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: redis

View File

@@ -0,0 +1,98 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
labels:
app: redis
namespace: redis
spec:
serviceName: redis
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
initContainers:
- name: config
image: redis:7.0.6
command: [ "sh", "-c" ]
args:
- |
cp /tmp/redis/redis.conf /etc/redis/redis.conf
echo "finding master..."
MASTER_FDQN=`hostname -f | sed -e 's/redis-[0-9]\./redis-0./'`
if [ "$(redis-cli -h sentinel -p 5000 ping)" != "PONG" ]; then
echo "master not found, defaulting to redis-0"
if [ "$(hostname)" = "redis-0" ]; then
echo "this is redis-0, not updating config..."
else
echo "updating redis.conf..."
echo "\nslaveof $MASTER_FDQN 6379" >> /etc/redis/redis.conf
fi
else
echo "sentinel found, finding master"
MASTER="$(redis-cli -h sentinel -p 5000 sentinel get-master-addr-by-name mymaster | grep -E '(^redis-\d{1,})|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})')"
echo "master found : $MASTER, updating redis.conf"
echo "slaveof $MASTER 6379" >> /etc/redis/redis.conf
fi
volumeMounts:
- name: redis-config
mountPath: /etc/redis/
- name: config
mountPath: /tmp/redis/
containers:
- name: redis
image: redis:7.0.6
command: [ "redis-server" ]
args: [ "/etc/redis/redis.conf" ]
ports:
- containerPort: 6379
name: redis
volumeMounts:
- name: data
mountPath: /data
- name: redis-config
mountPath: /etc/redis/
resources:
limits:
memory: 1100Mi
requests:
memory: 1100Mi
volumes:
- name: redis-config
emptyDir: { }
- name: config
configMap:
name: redis-config
volumeClaimTemplates:
- metadata:
name: data
spec:
storageClassName: hostpath
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 500Mi
---
apiVersion: v1 # API version
kind: Service # Type of the kubernetes resource
metadata:
name: redis # Name of the kubernetes resource
labels: # Labels that will be applied to this resource
app: redis
namespace: redis
spec:
selector:
app: redis # The service exposes Pods with label `app=redis`
ports:
- name: redis-port
port: 6379
nodePort: 30079
type: NodePort

View File

@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: kube-ruoyi

View File

@@ -0,0 +1,41 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: ruoyi-sentinel
namespace: kube-ruoyi
spec:
replicas: 1
selector:
matchLabels:
app: ruoyi-sentinel
template:
metadata:
labels:
app: ruoyi-sentinel
spec:
containers:
- name: ruoyi-sentinel
image: bladex/sentinel-dashboard
imagePullPolicy: Always
ports:
- containerPort: 8858
env: # Environment variables supplied to the Pod
- name: JAVA_TOOL_OPTIONS
value: "-Dserver.port=8858 -Dcsp.sentinel.dashboard.server=localhost:8858 -Dproject.name=sentinel-dashboard"
---
apiVersion: v1
kind: Service
metadata:
name: ruoyi-sentinel
namespace: kube-ruoyi
labels:
name: ruoyi-sentinel
spec:
type: NodePort
ports:
- port: 8858
targetPort: 8858
nodePort: 30858
selector:
app: ruoyi-sentinel

View File

@@ -0,0 +1,50 @@
apiVersion: apps/v1 # API version
kind: Deployment # Type of kubernetes resource
metadata:
name: ruoyi-auth # Name of the kubernetes resource
namespace: kube-ruoyi
labels: # Labels that will be applied to this resource
app: ruoyi-auth
spec:
replicas: 1 # No. of replicas/pods to run in this deployment
selector:
matchLabels: # The deployment applies to any pods matching the specified labels
app: ruoyi-auth
template: # Template for creating the pods in this deployment
metadata:
labels: # Labels that will be applied to each Pod in this deployment
app: ruoyi-auth
spec: # Spec for the containers that will be run in the Pods
containers:
- name: ruoyi-auth-server
image: ruoyi-auth:3.6.2
ports:
- name: http
containerPort: 9200 # The port that the container exposes
env: # Environment variables supplied to the Pod
- name: SPRING_PROFILES_ACTIVE
value: k8s
- name: SERVER_NAME
value: ruoyi-auth
- name: NACOS_SERVER
value: ruoyi-nacos # nacos svc name
- name: NACOS_PORT
value: "8848"
- name: NACOS_SHARED_CONFIGS
value: application-dev.yml
---
apiVersion: v1 # API version
kind: Service # Type of the kubernetes resource
metadata:
name: ruoyi-auth # Name of the kubernetes resource
labels: # Labels that will be applied to this resource
app: ruoyi-auth
namespace: kube-ruoyi
spec:
type: NodePort # The service will be exposed by opening a Port on each node and proxying it.
selector:
app: ruoyi-auth # The service exposes Pods with label `app=ruoyi-auth`
ports: # Forward incoming connections on port 9200 to the target port 9200
- name: http
port: 9200
targetPort: 9200

View File

@@ -0,0 +1,50 @@
apiVersion: apps/v1 # API version
kind: Deployment # Type of kubernetes resource
metadata:
name: ruoyi-gateway # Name of the kubernetes resource
namespace: kube-ruoyi
labels: # Labels that will be applied to this resource
app: ruoyi-gateway
spec:
replicas: 1 # No. of replicas/pods to run in this deployment
selector:
matchLabels: # The deployment applies to any pods matching the specified labels
app: ruoyi-gateway
template: # Template for creating the pods in this deployment
metadata:
labels: # Labels that will be applied to each Pod in this deployment
app: ruoyi-gateway
spec: # Spec for the containers that will be run in the Pods
containers:
- name: ruoyi-gateway-server
image: ruoyi-gateway:3.6.2
ports:
- name: http
containerPort: 8080 # The port that the container exposes
env: # Environment variables supplied to the Pod
- name: SPRING_PROFILES_ACTIVE
value: k8s
- name: SERVER_NAME
value: ruoyi-gateway
- name: NACOS_SERVER
value: ruoyi-nacos # nacos svc name
- name: NACOS_PORT
value: "8848"
- name: NACOS_SHARED_CONFIGS
value: application-dev.yml
---
apiVersion: v1 # API version
kind: Service # Type of the kubernetes resource
metadata:
name: ruoyi-gateway # Name of the kubernetes resource
labels: # Labels that will be applied to this resource
app: ruoyi-gateway
namespace: kube-ruoyi
spec:
type: NodePort # The service will be exposed by opening a Port on each node and proxying it.
selector:
app: ruoyi-gateway # The service exposes Pods with label `app=ruoyi-gateway`
ports: # Forward incoming connections on port 8080 to the target port 8080
- name: http
port: 8080
targetPort: 8080

View File

@@ -0,0 +1,50 @@
apiVersion: apps/v1 # API version
kind: Deployment # Type of kubernetes resource
metadata:
name: ruoyi-file # Name of the kubernetes resource
namespace: kube-ruoyi
labels: # Labels that will be applied to this resource
app: ruoyi-file
spec:
replicas: 1 # No. of replicas/pods to run in this deployment
selector:
matchLabels: # The deployment applies to any pods matching the specified labels
app: ruoyi-file
template: # Template for creating the pods in this deployment
metadata:
labels: # Labels that will be applied to each Pod in this deployment
app: ruoyi-file
spec: # Spec for the containers that will be run in the Pods
containers:
- name: ruoyi-file-server
image: ruoyi-modules-file:3.6.2
ports:
- name: http
containerPort: 9300 # The port that the container exposes
env: # Environment variables supplied to the Pod
- name: SPRING_PROFILES_ACTIVE
value: k8s
- name: SERVER_NAME
value: ruoyi-file
- name: NACOS_SERVER
value: ruoyi-nacos # nacos svc name
- name: NACOS_PORT
value: "8848"
- name: NACOS_SHARED_CONFIGS
value: application-dev.yml
---
apiVersion: v1 # API version
kind: Service # Type of the kubernetes resource
metadata:
name: ruoyi-file # Name of the kubernetes resource
labels: # Labels that will be applied to this resource
app: ruoyi-file
namespace: kube-ruoyi
spec:
type: NodePort # The service will be exposed by opening a Port on each node and proxying it.
selector:
app: ruoyi-file # The service exposes Pods with label `app=ruoyi-file`
ports: # Forward incoming connections on port 9300 to the target port 9300
- name: http
port: 9300
targetPort: 9300

View File

@@ -0,0 +1,50 @@
apiVersion: apps/v1 # API version
kind: Deployment # Type of kubernetes resource
metadata:
name: ruoyi-gen # Name of the kubernetes resource
namespace: kube-ruoyi
labels: # Labels that will be applied to this resource
app: ruoyi-gen
spec:
replicas: 1 # No. of replicas/pods to run in this deployment
selector:
matchLabels: # The deployment applies to any pods matching the specified labels
app: ruoyi-gen
template: # Template for creating the pods in this deployment
metadata:
labels: # Labels that will be applied to each Pod in this deployment
app: ruoyi-gen
spec: # Spec for the containers that will be run in the Pods
containers:
- name: ruoyi-gen-server
image: ruoyi-modules-gen:3.6.2
ports:
- name: http
containerPort: 9202 # The port that the container exposes
env: # Environment variables supplied to the Pod
- name: SPRING_PROFILES_ACTIVE
value: k8s
- name: SERVER_NAME
value: ruoyi-gen
- name: NACOS_SERVER
value: ruoyi-nacos # nacos svc name
- name: NACOS_PORT
value: "8848"
- name: NACOS_SHARED_CONFIGS
value: application-dev.yml
---
apiVersion: v1 # API version
kind: Service # Type of the kubernetes resource
metadata:
name: ruoyi-gen # Name of the kubernetes resource
labels: # Labels that will be applied to this resource
app: ruoyi-gen
namespace: kube-ruoyi
spec:
type: NodePort # The service will be exposed by opening a Port on each node and proxying it.
selector:
app: ruoyi-gen # The service exposes Pods with label `app=ruoyi-gen`
ports: # Forward incoming connections on port 9202 to the target port 9202
- name: http
port: 9202
targetPort: 9202

View File

@@ -0,0 +1,50 @@
apiVersion: apps/v1 # API version
kind: Deployment # Type of kubernetes resource
metadata:
name: ruoyi-job # Name of the kubernetes resource
namespace: kube-ruoyi
labels: # Labels that will be applied to this resource
app: ruoyi-job
spec:
replicas: 1 # No. of replicas/pods to run in this deployment
selector:
matchLabels: # The deployment applies to any pods matching the specified labels
app: ruoyi-job
template: # Template for creating the pods in this deployment
metadata:
labels: # Labels that will be applied to each Pod in this deployment
app: ruoyi-job
spec: # Spec for the containers that will be run in the Pods
containers:
- name: ruoyi-job-server
image: ruoyi-modules-job:3.6.2
ports:
- name: http
containerPort: 9203 # The port that the container exposes
env: # Environment variables supplied to the Pod
- name: SPRING_PROFILES_ACTIVE
value: k8s
- name: SERVER_NAME
value: ruoyi-job
- name: NACOS_SERVER
value: ruoyi-nacos # nacos svc name
- name: NACOS_PORT
value: "8848"
- name: NACOS_SHARED_CONFIGS
value: application-dev.yml
---
apiVersion: v1 # API version
kind: Service # Type of the kubernetes resource
metadata:
name: ruoyi-job # Name of the kubernetes resource
labels: # Labels that will be applied to this resource
app: ruoyi-job
namespace: kube-ruoyi
spec:
type: NodePort # The service will be exposed by opening a Port on each node and proxying it.
selector:
app: ruoyi-job # The service exposes Pods with label `app=ruoyi-job`
ports: # Forward incoming connections on port 9203 to the target port 9203
- name: http
port: 9203
targetPort: 9203

View File

@@ -0,0 +1,50 @@
apiVersion: apps/v1 # API version
kind: Deployment # Type of kubernetes resource
metadata:
name: ruoyi-system # Name of the kubernetes resource
namespace: kube-ruoyi
labels: # Labels that will be applied to this resource
app: ruoyi-system
spec:
replicas: 1 # No. of replicas/pods to run in this deployment
selector:
matchLabels: # The deployment applies to any pods matching the specified labels
app: ruoyi-system
template: # Template for creating the pods in this deployment
metadata:
labels: # Labels that will be applied to each Pod in this deployment
app: ruoyi-system
spec: # Spec for the containers that will be run in the Pods
containers:
- name: ruoyi-system-server
image: ruoyi-modules-system:3.6.2
ports:
- name: http
containerPort: 9201 # The port that the container exposes
env: # Environment variables supplied to the Pod
- name: SPRING_PROFILES_ACTIVE
value: k8s
- name: SERVER_NAME
value: ruoyi-system
- name: NACOS_SERVER
value: ruoyi-nacos # nacos svc name
- name: NACOS_PORT
value: "8848"
- name: NACOS_SHARED_CONFIGS
value: application-dev.yml
---
apiVersion: v1 # API version
kind: Service # Type of the kubernetes resource
metadata:
name: ruoyi-system # Name of the kubernetes resource
labels: # Labels that will be applied to this resource
app: ruoyi-system
namespace: kube-ruoyi
spec:
type: NodePort # The service will be exposed by opening a Port on each node and proxying it.
selector:
app: ruoyi-system # The service exposes Pods with label `app=ruoyi-system`
ports: # Forward incoming connections on port 9201 to the target port 9201
- name: http
port: 9201
targetPort: 9201

View File

@@ -0,0 +1,50 @@
apiVersion: apps/v1 # API version
kind: Deployment # Type of kubernetes resource
metadata:
name: ruoyi-monitor # Name of the kubernetes resource
namespace: kube-ruoyi
labels: # Labels that will be applied to this resource
app: ruoyi-monitor
spec:
replicas: 1 # No. of replicas/pods to run in this deployment
selector:
matchLabels: # The deployment applies to any pods matching the specified labels
app: ruoyi-monitor
template: # Template for creating the pods in this deployment
metadata:
labels: # Labels that will be applied to each Pod in this deployment
app: ruoyi-monitor
spec: # Spec for the containers that will be run in the Pods
containers:
- name: ruoyi-monitor-server
image: ruoyi-visual-monitor:3.6.2
ports:
- name: http
containerPort: 9100 # The port that the container exposes
env: # Environment variables supplied to the Pod
- name: SPRING_PROFILES_ACTIVE
value: k8s
- name: SERVER_NAME
value: ruoyi-monitor
- name: NACOS_SERVER
value: ruoyi-nacos # nacos svc name
- name: NACOS_PORT
value: "8848"
- name: NACOS_SHARED_CONFIGS
value: application-dev.yml
---
apiVersion: v1 # API version
kind: Service # Type of the kubernetes resource
metadata:
name: ruoyi-monitor # Name of the kubernetes resource
labels: # Labels that will be applied to this resource
app: ruoyi-monitor
namespace: kube-ruoyi
spec:
type: NodePort # The service will be exposed by opening a Port on each node and proxying it.
selector:
app: ruoyi-monitor # The service exposes Pods with label `app=ruoyi-monitor`
ports: # Forward incoming connections on port 9100 to the target port 9100
- name: http
port: 9100
targetPort: 9100

View File

@@ -0,0 +1,37 @@
# Tomcat
server:
port: 8080
# Spring
spring:
application:
# 应用名称
name: ${SERVER_NAME}
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: ${NACOS_SERVER}:${NACOS_PORT}
config:
# 配置中心地址
server-addr: ${NACOS_SERVER}:${NACOS_PORT}
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- ${NACOS_SHARED_CONFIGS}
sentinel:
# 取消控制台懒加载
eager: true
transport:
# 控制台地址
dashboard: 127.0.0.1:8718
# nacos配置持久化
datasource:
ds1:
nacos:
server-addr: ${NACOS_SERVER}:${NACOS_PORT}
dataId: sentinel-ruoyi-gateway
groupId: DEFAULT_GROUP
data-type: json
rule-type: gw-flow

View File

@@ -0,0 +1,15 @@
# 基础镜像
FROM openjdk:8-jre
# author
MAINTAINER ruoyi
# 挂载目录
VOLUME /home/ruoyi
# 创建目录
RUN mkdir -p /home/ruoyi
# 指定路径
WORKDIR /home/ruoyi
# 复制jar文件到路径
COPY ./jar/ruoyi-gateway.jar /home/ruoyi/ruoyi-gateway.jar
# 启动网关服务
ENTRYPOINT ["java","-jar","ruoyi-gateway.jar"]

View File

@@ -0,0 +1 @@
存放网关模块打包好的jar文件用于docker启动应用。

View File

@@ -0,0 +1,73 @@
apiVersion: apps/v1 # API version
kind: Deployment # Type of kubernetes resource
metadata:
name: ruoyi-system # Name of the kubernetes resource
namespace: kube-ruoyi
labels: # Labels that will be applied to this resource
app: ruoyi-system
spec:
replicas: 1 # No. of replicas/pods to run in this deployment
selector:
matchLabels: # The deployment applies to any pods matching the specified labels
app: ruoyi-system
template: # Template for creating the pods in this deployment
metadata:
labels: # Labels that will be applied to each Pod in this deployment
app: ruoyi-system
spec: # Spec for the containers that will be run in the Pods
containers:
- name: ruoyi-system-server
image: ruoyi-modules-system:3.6.2
ports:
- name: http
containerPort: 9201 # The port that the container exposes
env: # Environment variables supplied to the Pod
- name: SPRING_PROFILES_ACTIVE
value: k8s
- name: SERVER_NAME
value: ruoyi-system
- name: NACOS_SERVER
value: ruoyi-nacos # nacos svc name
- name: NACOS_PORT
value: "8848"
- name: NACOS_SHARED_CONFIGS
value: application-dev.yml
- name: JAVA_OPTS
value: -javaagent:/javaagent/skywalking-agent/skywalking-agent.jar -Dskywalking.agent.service_name=k8s::$(SERVER_NAME) -Dskywalking.collector.backend_service=skywalking:11800
volumeMounts:
- mountPath: /javaagent
name: agent-jar
volumes:
- emptyDir: { }
name: agent-jar
initContainers:
# 官网用脚本命令行+args的方式执行多条command语句
- command: ['sh']
args:
- "-c"
- |
cp -r /opt/skywalking-agent /javaagent
chown -R 65534:65534 /javaagent
/bin/chmod -R 777 /javaagent
image: skywalking-agent:8.14.0
imagePullPolicy: IfNotPresent
name: skywalking-agent
volumeMounts:
- mountPath: /javaagent
name: agent-jar
---
apiVersion: v1 # API version
kind: Service # Type of the kubernetes resource
metadata:
name: ruoyi-system # Name of the kubernetes resource
labels: # Labels that will be applied to this resource
app: ruoyi-system
namespace: kube-ruoyi
spec:
type: NodePort # The service will be exposed by opening a Port on each node and proxying it.
selector:
app: ruoyi-system # The service exposes Pods with label `app=ruoyi-system`
ports: # Forward incoming connections on port 9201 to the target port 9201
- name: http
port: 9201
targetPort: 9201

View File

@@ -0,0 +1,17 @@
## cat Dcokerfile
FROM docker.io/library/busybox:latest AS base
# 使用 ADD 下载 java-agent,你也可以使用其他下载命令,或者下载到本地,再 使用 COPY或者ADD 指令添加到 镜像里
ADD https://dlcdn.apache.org/skywalking/java-agent/9.0.0/apache-skywalking-java-agent-9.0.0.tgz /tmp/
RUN mkdir -p /opt \
&& tar -xzf /tmp/apache-skywalking-java-agent-9.0.0.tgz -C /opt/ \
&& rm -rf /tmp/*
#ADD skywalking-agent.tar.gz /opt/
RUN mkdir -p /javaagent
## java-agent 使用 方法
## https://skywalking.apache.org/docs/skywalking-java/next/en/setup/service-agent/java-agent/readme/
## java -javaagent:/opt/skywalking-agent/skywalking-agent.jar -jar yourApp.jar
## -javaagent:/opt/skywalking-agent/skywalking-agent.jar=agent.service_name=yourAppName,collector.backend_service=127.0.0.1:11800
## -javaagent:/opt/skywalking-agent/skywalking-agent.jar -Dskywalking.agent.service_name=yourAppName -Dskywalking.collector.backend_service=127.0.0.1:11800

View File

@@ -0,0 +1,44 @@
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
name: elasticsearch
name: elasticsearch
namespace: kube-ruoyi
spec:
replicas: 1
selector:
matchLabels:
app: elasticsearch
template:
metadata:
labels:
app: elasticsearch
spec:
containers:
- name: elasticsearch
image: elasticsearch:7.14.2
ports:
- containerPort: 9200
name: cluster-node
env:
- name: discovery.type
value: single-node
- name: TZ
value: Asia/Shanghai
- name: ES_JAVA_OPTS
value: -Xms512m -Xmx512m
---
apiVersion: v1
kind: Service
metadata:
name: elasticsearch
namespace: kube-ruoyi
spec:
ports:
- port: 9220 # 和auth-server的端口冲突了对外暴露换一个端口访问
targetPort: 9200
name: cluster-node
selector:
app: elasticsearch # 该 Service 会将所有具有标签 app: mysql-labels-app暴露到一个抽象的 Service 端口上targetPort容器接收流量的端口port可任意取值的抽象的 Service 端口,其他 Pod 通过该端口访问 Service
type: NodePort

View File

@@ -0,0 +1,50 @@
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
name: skywalking
name: skywalking
namespace: kube-ruoyi
spec:
replicas: 1
selector:
matchLabels:
app: skywalking
template:
metadata:
labels:
app: skywalking
spec:
containers:
- name: skywalking
image: apache/skywalking-oap-server
imagePullPolicy: Always
ports:
- containerPort: 11800
name: collector
- containerPort: 12800
name: oap
env:
- name: SW_STORAGE
value: elasticsearch
- name: TZ
value: Asia/Shanghai
- name: SW_STORAGE_ES_CLUSTER_NODES
value: elasticsearch:9220
---
apiVersion: v1
kind: Service
metadata:
name: skywalking
namespace: kube-ruoyi
spec:
ports:
- port: 11800
targetPort: 11800
name: collector
- port: 12800
targetPort: 12800
name: oap
selector:
app: skywalking # 该 Service 会将所有具有标签 app: mysql-labels-app暴露到一个抽象的 Service 端口上targetPort容器接收流量的端口port可任意取值的抽象的 Service 端口,其他 Pod 通过该端口访问 Service
type: NodePort

View File

@@ -0,0 +1,42 @@
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
name: skywalking-ui
name: skywalking-ui
namespace: kube-ruoyi
spec:
replicas: 1
selector:
matchLabels:
app: skywalking-ui
template:
metadata:
labels:
app: skywalking-ui
spec:
containers:
- name: skywalking-ui
image: apache/skywalking-ui
imagePullPolicy: Always
ports:
- containerPort: 8080
name: console
env:
- name: SW_OAP_ADDRESS
value: http://skywalking:12800
- name: TZ
value: Asia/Shanghai
---
apiVersion: v1
kind: Service
metadata:
name: skywalking-ui
namespace: kube-ruoyi
spec:
ports:
- port: 8080
nodePort: 30088
selector:
app: skywalking-ui # 该 Service 会将所有具有标签 app: mysql-labels-app暴露到一个抽象的 Service 端口上targetPort容器接收流量的端口port可任意取值的抽象的 Service 端口,其他 Pod 通过该端口访问 Service
type: NodePort

View File

@@ -9,8 +9,8 @@ usage() {
# copy sql # copy sql
echo "begin copy sql " echo "begin copy sql "
cp ../sql/ry_20250523.sql ./mysql/db cp ../sql/ry_20240629.sql ./mysql/db
cp ../sql/ry_config_20250902.sql ./mysql/db cp ../sql/ry_config_20250224.sql ./mysql/db
# copy html # copy html
echo "begin copy html " echo "begin copy html "

View File

@@ -29,7 +29,7 @@ http {
} }
# 避免actuator暴露 # 避免actuator暴露
if ($uri ~ "/actuator") { if ($request_uri ~ "/actuator") {
return 403; return 403;
} }

13
pom.xml
View File

@@ -6,14 +6,14 @@
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.6.7</version> <version>3.6.5</version>
<name>ruoyi</name> <name>ruoyi</name>
<url>http://www.ruoyi.vip</url> <url>http://www.ruoyi.vip</url>
<description>若依微服务系统</description> <description>若依微服务系统</description>
<properties> <properties>
<ruoyi.version>3.6.7</ruoyi.version> <ruoyi.version>3.6.5</ruoyi.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version> <java.version>1.8</java.version>
@@ -24,18 +24,19 @@
<tobato.version>1.27.2</tobato.version> <tobato.version>1.27.2</tobato.version>
<kaptcha.version>2.3.3</kaptcha.version> <kaptcha.version>2.3.3</kaptcha.version>
<pagehelper.boot.version>2.0.0</pagehelper.boot.version> <pagehelper.boot.version>2.0.0</pagehelper.boot.version>
<druid.version>1.2.27</druid.version> <druid.version>1.2.23</druid.version>
<dynamic-ds.version>4.3.1</dynamic-ds.version> <dynamic-ds.version>4.3.1</dynamic-ds.version>
<commons.io.version>2.21.0</commons.io.version> <commons.io.version>2.13.0</commons.io.version>
<velocity.version>2.3</velocity.version> <velocity.version>2.3</velocity.version>
<fastjson.version>2.0.60</fastjson.version> <fastjson.version>2.0.53</fastjson.version>
<jjwt.version>0.9.1</jjwt.version> <jjwt.version>0.9.1</jjwt.version>
<minio.version>8.2.2</minio.version> <minio.version>8.2.2</minio.version>
<poi.version>4.1.2</poi.version> <poi.version>4.1.2</poi.version>
<springdoc.version>1.6.9</springdoc.version> <springdoc.version>1.6.9</springdoc.version>
<transmittable-thread-local.version>2.14.4</transmittable-thread-local.version> <transmittable-thread-local.version>2.14.4</transmittable-thread-local.version>
<!-- override dependency version --> <!-- override dependency version -->
<tomcat.version>9.0.112</tomcat.version> <tomcat.version>9.0.98</tomcat.version>
<logback.version>1.2.13</logback.version> <logback.version>1.2.13</logback.version>
<spring-framework.version>5.3.39</spring-framework.version> <spring-framework.version>5.3.39</spring-framework.version>
</properties> </properties>

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.6.7</version> <version>3.6.5</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-api</artifactId> <artifactId>ruoyi-api</artifactId>
<version>3.6.7</version> <version>3.6.5</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -2,9 +2,7 @@ package com.ruoyi.system.api;
import org.springframework.cloud.openfeign.FeignClient; import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.core.constant.ServiceNameConstants; import com.ruoyi.common.core.constant.ServiceNameConstants;
@@ -28,13 +26,4 @@ public interface RemoteFileService
*/ */
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public R<SysFile> upload(@RequestPart(value = "file") MultipartFile file); public R<SysFile> upload(@RequestPart(value = "file") MultipartFile file);
/**
* 删除文件
*
* @param fileUrl 文件地址
* @return 结果
*/
@DeleteMapping(value = "/delete", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public R<Boolean> delete(@RequestParam("fileUrl") String fileUrl);
} }

View File

@@ -8,7 +8,6 @@ import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.core.annotation.Excel; import com.ruoyi.common.core.annotation.Excel;
import com.ruoyi.common.core.annotation.Excel.ColumnType; import com.ruoyi.common.core.annotation.Excel.ColumnType;
import com.ruoyi.common.core.annotation.Excel.Type; import com.ruoyi.common.core.annotation.Excel.Type;
import com.ruoyi.common.core.constant.UserConstants;
import com.ruoyi.common.core.annotation.Excels; import com.ruoyi.common.core.annotation.Excels;
import com.ruoyi.common.core.web.domain.BaseEntity; import com.ruoyi.common.core.web.domain.BaseEntity;
import com.ruoyi.common.core.xss.Xss; import com.ruoyi.common.core.xss.Xss;
@@ -56,8 +55,8 @@ public class SysUser extends BaseEntity
/** 密码 */ /** 密码 */
private String password; private String password;
/** 号状态0正常 1停用 */ /** 号状态0正常 1停用 */
@Excel(name = "号状态", readConverterExp = "0=正常,1=停用") @Excel(name = "号状态", readConverterExp = "0=正常,1=停用")
private String status; private String status;
/** 删除标志0代表存在 2代表删除 */ /** 删除标志0代表存在 2代表删除 */
@@ -71,9 +70,6 @@ public class SysUser extends BaseEntity
@Excel(name = "最后登录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT) @Excel(name = "最后登录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT)
private Date loginDate; private Date loginDate;
/** 密码最后更新时间 */
private Date pwdUpdateDate;
/** 部门对象 */ /** 部门对象 */
@Excels({ @Excels({
@Excel(name = "部门名称", targetAttr = "deptName", type = Type.EXPORT), @Excel(name = "部门名称", targetAttr = "deptName", type = Type.EXPORT),
@@ -115,7 +111,12 @@ public class SysUser extends BaseEntity
public boolean isAdmin() public boolean isAdmin()
{ {
return UserConstants.isAdmin(userId); return isAdmin(this.userId);
}
public static boolean isAdmin(Long userId)
{
return userId != null && 1L == userId;
} }
public Long getDeptId() public Long getDeptId()
@@ -246,16 +247,6 @@ public class SysUser extends BaseEntity
this.loginDate = loginDate; this.loginDate = loginDate;
} }
public Date getPwdUpdateDate()
{
return pwdUpdateDate;
}
public void setPwdUpdateDate(Date pwdUpdateDate)
{
this.pwdUpdateDate = pwdUpdateDate;
}
public SysDept getDept() public SysDept getDept()
{ {
return dept; return dept;
@@ -305,7 +296,6 @@ public class SysUser extends BaseEntity
{ {
this.roleId = roleId; this.roleId = roleId;
} }
@Override @Override
public String toString() { public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
@@ -322,7 +312,6 @@ public class SysUser extends BaseEntity
.append("delFlag", getDelFlag()) .append("delFlag", getDelFlag())
.append("loginIp", getLoginIp()) .append("loginIp", getLoginIp())
.append("loginDate", getLoginDate()) .append("loginDate", getLoginDate())
.append("pwdUpdateDate", getPwdUpdateDate())
.append("createBy", getCreateBy()) .append("createBy", getCreateBy())
.append("createTime", getCreateTime()) .append("createTime", getCreateTime())
.append("updateBy", getUpdateBy()) .append("updateBy", getUpdateBy())

View File

@@ -30,12 +30,6 @@ public class RemoteFileFallbackFactory implements FallbackFactory<RemoteFileServ
{ {
return R.fail("上传文件失败:" + throwable.getMessage()); return R.fail("上传文件失败:" + throwable.getMessage());
} }
@Override
public R<Boolean> delete(String fileUrl)
{
return R.fail("删除文件失败:" + throwable.getMessage());
}
}; };
} }
} }

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.6.7</version> <version>3.6.5</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -143,7 +143,6 @@ public class SysLoginService
SysUser sysUser = new SysUser(); SysUser sysUser = new SysUser();
sysUser.setUserName(username); sysUser.setUserName(username);
sysUser.setNickName(username); sysUser.setNickName(username);
sysUser.setPwdUpdateDate(DateUtils.getNowDate());
sysUser.setPassword(SecurityUtils.encryptPassword(password)); sysUser.setPassword(SecurityUtils.encryptPassword(password));
R<?> registerResult = remoteUserService.registerUserInfo(sysUser, SecurityConstants.INNER); R<?> registerResult = remoteUserService.registerUserInfo(sysUser, SecurityConstants.INNER);

View File

@@ -0,0 +1,22 @@
# Tomcat
server:
port: 9200
# Spring
spring:
application:
# 应用名称
name: ${SERVER_NAME}
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: ${NACOS_SERVER}:${NACOS_PORT}
config:
# 配置中心地址
server-addr: ${NACOS_SERVER}:${NACOS_PORT}
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- ${NACOS_SHARED_CONFIGS}

View File

@@ -9,7 +9,7 @@ spring:
name: ruoyi-auth name: ruoyi-auth
profiles: profiles:
# 环境配置 # 环境配置
active: dev active: ${SPRING_PROFILES_ACTIVE:dev}
cloud: cloud:
nacos: nacos:
discovery: discovery:

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.6.7</version> <version>3.6.5</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.7</version> <version>3.6.5</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -87,16 +87,6 @@ public class Constants
*/ */
public static final String LOGIN_FAIL = "Error"; public static final String LOGIN_FAIL = "Error";
/**
* 所有权限标识
*/
public static final String ALL_PERMISSION = "*:*:*";
/**
* 管理员角色权限标识
*/
public static final String SUPER_ADMIN = "admin";
/** /**
* 当前记录起始索引 * 当前记录起始索引
*/ */
@@ -130,7 +120,7 @@ public class Constants
/** /**
* 自动识别json对象白名单配置仅允许解析的包名范围越小越安全 * 自动识别json对象白名单配置仅允许解析的包名范围越小越安全
*/ */
public static final String[] JSON_WHITELIST_STR = { "com.ruoyi" }; public static final String[] JSON_WHITELIST_STR = { "org.springframework", "com.ruoyi" };
/** /**
* 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加) * 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加)

View File

@@ -80,9 +80,4 @@ public class UserConstants
public static final int PASSWORD_MIN_LENGTH = 5; public static final int PASSWORD_MIN_LENGTH = 5;
public static final int PASSWORD_MAX_LENGTH = 20; public static final int PASSWORD_MAX_LENGTH = 20;
public static boolean isAdmin(Long userId)
{
return userId != null && 1L == userId;
}
} }

View File

@@ -3,7 +3,7 @@ package com.ruoyi.common.core.exception.file;
import java.util.Arrays; import java.util.Arrays;
/** /**
* 文件上传无效扩展名异常类 * 文件上传异常类
* *
* @author ruoyi * @author ruoyi
*/ */

View File

@@ -136,14 +136,6 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
return new Date(time); return new Date(time);
} }
/**
* 计算相差天数
*/
public static int differentDaysByMillisecond(Date date1, Date date2)
{
return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24)));
}
/** /**
* 计算时间差 * 计算时间差
* *

View File

@@ -114,20 +114,20 @@ public class FileUtils
} }
/** /**
* 校验文件路径合法性(安全性与扩展名) * 检查文件是否可下载
* *
* @param fileUrl 待校验的文件地址 * @param resource 需要下载的文件
* @return true 正常 false 非法 * @return true 正常 false 非法
*/ */
public static boolean validateFilePath(String fileUrl) public static boolean checkAllowDownload(String resource)
{ {
// 禁止目录上跳级别 // 禁止目录上跳级别
if (StringUtils.contains(fileUrl, "..")) if (StringUtils.contains(resource, ".."))
{ {
return false; return false;
} }
// 判断是否在允许下载的文件规则内 // 判断是否在允许下载的文件规则内
return ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(fileUrl)); return ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource));
} }
/** /**

View File

@@ -73,8 +73,6 @@ public class ExcelUtil<T>
{ {
private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class); private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class);
public static final String SEPARATOR = ",";
public static final String FORMULA_REGEX_STR = "=|-|\\+|@"; public static final String FORMULA_REGEX_STR = "=|-|\\+|@";
public static final String[] FORMULA_STR = { "=", "-", "+", "@" }; public static final String[] FORMULA_STR = { "=", "-", "+", "@" };
@@ -147,18 +145,23 @@ public class ExcelUtil<T>
/** /**
* 对象的子列表方法 * 对象的子列表方法
*/ */
private Map<String, Method> subMethods; private Method subMethod;
/** /**
* 对象的子列表属性 * 对象的子列表属性
*/ */
private Map<String, List<Field>> subFieldsMap; private List<Field> subFields;
/** /**
* 统计列表 * 统计列表
*/ */
private Map<Integer, Double> statistics = new HashMap<Integer, Double>(); private Map<Integer, Double> statistics = new HashMap<Integer, Double>();
/**
* 数字格式
*/
private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00");
/** /**
* 实体对象 * 实体对象
*/ */
@@ -225,10 +228,7 @@ public class ExcelUtil<T>
int titleLastCol = this.fields.size() - 1; int titleLastCol = this.fields.size() - 1;
if (isSubList()) if (isSubList())
{ {
for (List<Field> currentSubFields : subFieldsMap.values()) titleLastCol = titleLastCol + subFields.size() - 1;
{
titleLastCol = titleLastCol + currentSubFields.size() - 1;
}
} }
Row titleRow = sheet.createRow(rownum == 0 ? rownum++ : 0); Row titleRow = sheet.createRow(rownum == 0 ? rownum++ : 0);
titleRow.setHeightInPoints(30); titleRow.setHeightInPoints(30);
@@ -248,17 +248,16 @@ public class ExcelUtil<T>
{ {
Row subRow = sheet.createRow(rownum); Row subRow = sheet.createRow(rownum);
int column = 0; int column = 0;
int subFieldSize = subFields != null ? subFields.size() : 0;
for (Object[] objects : fields) for (Object[] objects : fields)
{ {
Field field = (Field) objects[0]; Field field = (Field) objects[0];
Excel attr = (Excel) objects[1]; Excel attr = (Excel) objects[1];
CellStyle cellStyle = styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor()));
if (Collection.class.isAssignableFrom(field.getType())) if (Collection.class.isAssignableFrom(field.getType()))
{ {
Cell cell = subRow.createCell(column); Cell cell = subRow.createCell(column);
cell.setCellValue(attr.name()); cell.setCellValue(attr.name());
cell.setCellStyle(cellStyle); cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));
int subFieldSize = subFieldsMap != null ? subFieldsMap.get(field.getName()).size() : 0;
if (subFieldSize > 1) if (subFieldSize > 1)
{ {
CellRangeAddress cellAddress = new CellRangeAddress(rownum, rownum, column, column + subFieldSize - 1); CellRangeAddress cellAddress = new CellRangeAddress(rownum, rownum, column, column + subFieldSize - 1);
@@ -270,7 +269,7 @@ public class ExcelUtil<T>
{ {
Cell cell = subRow.createCell(column++); Cell cell = subRow.createCell(column++);
cell.setCellValue(attr.name()); cell.setCellValue(attr.name());
cell.setCellStyle(cellStyle); cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));
} }
} }
rownum++; rownum++;
@@ -342,11 +341,7 @@ public class ExcelUtil<T>
Map<String, Integer> cellMap = new HashMap<String, Integer>(); Map<String, Integer> cellMap = new HashMap<String, Integer>();
// 获取表头 // 获取表头
Row heard = sheet.getRow(titleNum); Row heard = sheet.getRow(titleNum);
if (heard == null) for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++)
{
throw new UtilException("文件标题行为空请检查Excel文件格式");
}
for (int i = 0; i < heard.getLastCellNum(); i++)
{ {
Cell cell = heard.getCell(i); Cell cell = heard.getCell(i);
if (StringUtils.isNotNull(cell)) if (StringUtils.isNotNull(cell))
@@ -354,6 +349,10 @@ public class ExcelUtil<T>
String value = this.getCellValue(heard, i).toString(); String value = this.getCellValue(heard, i).toString();
cellMap.put(value, i); cellMap.put(value, i);
} }
else
{
cellMap.put(null, i);
}
} }
// 有数据时才处理 得到类的所有field. // 有数据时才处理 得到类的所有field.
List<Object[]> fields = this.getFields(); List<Object[]> fields = this.getFields();
@@ -391,7 +390,7 @@ public class ExcelUtil<T>
if (String.class == fieldType) if (String.class == fieldType)
{ {
String s = Convert.toStr(val); String s = Convert.toStr(val);
if (s.matches("^\\d+\\.0$")) if (StringUtils.endsWith(s, ".0"))
{ {
val = StringUtils.substringBefore(s, ".0"); val = StringUtils.substringBefore(s, ".0");
} }
@@ -566,8 +565,7 @@ public class ExcelUtil<T>
Excel excel = (Excel) os[1]; Excel excel = (Excel) os[1];
if (Collection.class.isAssignableFrom(field.getType())) if (Collection.class.isAssignableFrom(field.getType()))
{ {
List<Field> currentSubFields = subFieldsMap.get(field.getName()); for (Field subField : subFields)
for (Field subField : currentSubFields)
{ {
Excel subExcel = subField.getAnnotation(Excel.class); Excel subExcel = subField.getAnnotation(Excel.class);
this.createHeadCell(subExcel, row, column++); this.createHeadCell(subExcel, row, column++);
@@ -580,7 +578,7 @@ public class ExcelUtil<T>
} }
if (Type.EXPORT.equals(type)) if (Type.EXPORT.equals(type))
{ {
fillExcelData(index); fillExcelData(index, row);
addStatisticsRow(); addStatisticsRow();
} }
} }
@@ -590,9 +588,10 @@ public class ExcelUtil<T>
* 填充excel数据 * 填充excel数据
* *
* @param index 序号 * @param index 序号
* @param row 单元格行
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void fillExcelData(int index) public void fillExcelData(int index, Row row)
{ {
int startNo = index * sheetSize; int startNo = index * sheetSize;
int endNo = Math.min(startNo + sheetSize, list.size()); int endNo = Math.min(startNo + sheetSize, list.size());
@@ -600,7 +599,7 @@ public class ExcelUtil<T>
for (int i = startNo; i < endNo; i++) for (int i = startNo; i < endNo; i++)
{ {
Row row = sheet.createRow(currentRowNum); row = sheet.createRow(currentRowNum);
T vo = (T) list.get(i); T vo = (T) list.get(i);
int column = 0; int column = 0;
int maxSubListSize = getCurrentMaxSubListSize(vo); int maxSubListSize = getCurrentMaxSubListSize(vo);
@@ -613,7 +612,6 @@ public class ExcelUtil<T>
try try
{ {
Collection<?> subList = (Collection<?>) getTargetValue(vo, field, excel); Collection<?> subList = (Collection<?>) getTargetValue(vo, field, excel);
List<Field> currentSubFields = subFieldsMap.get(field.getName());
if (subList != null && !subList.isEmpty()) if (subList != null && !subList.isEmpty())
{ {
int subIndex = 0; int subIndex = 0;
@@ -626,15 +624,15 @@ public class ExcelUtil<T>
} }
int subColumn = column; int subColumn = column;
for (Field subField : currentSubFields) for (Field subField : subFields)
{ {
Excel subExcel = subField.getAnnotation(Excel.class); Excel subExcel = subField.getAnnotation(Excel.class);
addCell(subExcel, subRow, (T) subVo, subField, subColumn++); addCell(subExcel, subRow, (T) subVo, subField, subColumn++);
} }
subIndex++; subIndex++;
} }
column += subFields.size();
} }
column += currentSubFields.size();
} }
catch (Exception e) catch (Exception e)
{ {
@@ -726,7 +724,6 @@ public class ExcelUtil<T>
style = wb.createCellStyle(); style = wb.createCellStyle();
style.setAlignment(HorizontalAlignment.CENTER); style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER); style.setVerticalAlignment(VerticalAlignment.CENTER);
style.setDataFormat(dataFormat.getFormat("######0.00"));
Font totalFont = wb.createFont(); Font totalFont = wb.createFont();
totalFont.setFontName("Arial"); totalFont.setFontName("Arial");
totalFont.setFontHeightInPoints((short) 10); totalFont.setFontHeightInPoints((short) 10);
@@ -987,7 +984,7 @@ public class ExcelUtil<T>
{ {
// 创建cell // 创建cell
cell = row.createCell(column); cell = row.createCell(column);
if (isSubListValue(vo) && getListCellValue(vo) > 1 && attr.needMerge()) if (isSubListValue(vo) && getListCellValue(vo).size() > 1 && attr.needMerge())
{ {
if (subMergedLastRowNum >= subMergedFirstRowNum) if (subMergedLastRowNum >= subMergedFirstRowNum)
{ {
@@ -1003,7 +1000,7 @@ public class ExcelUtil<T>
String separator = attr.separator(); String separator = attr.separator();
if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value)) if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value))
{ {
cell.setCellStyle(createCellStyle(cell.getCellStyle(), dateFormat)); cell.getCellStyle().setDataFormat(this.wb.getCreationHelper().createDataFormat().getFormat(dateFormat));
cell.setCellValue(parseDateToStr(dateFormat, value)); cell.setCellValue(parseDateToStr(dateFormat, value));
} }
else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value)) else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value))
@@ -1033,21 +1030,6 @@ public class ExcelUtil<T>
return cell; return cell;
} }
/**
* 使用自定义格式,同时避免样式污染
*
* @param cellStyle 从此样式复制
* @param format 格式匹配的字符串
* @return 格式化后CellStyle对象
*/
private CellStyle createCellStyle(CellStyle cellStyle, String format)
{
CellStyle style = wb.createCellStyle();
style.cloneStyleFrom(cellStyle);
style.setDataFormat(wb.getCreationHelper().createDataFormat().getFormat(format));
return style;
}
/** /**
* 设置 POI XSSFSheet 单元格提示或选择框 * 设置 POI XSSFSheet 单元格提示或选择框
* *
@@ -1099,36 +1081,18 @@ public class ExcelUtil<T>
public void setXSSFValidationWithHidden(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow, int firstCol, int endCol) public void setXSSFValidationWithHidden(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow, int firstCol, int endCol)
{ {
String hideSheetName = "combo_" + firstCol + "_" + endCol; String hideSheetName = "combo_" + firstCol + "_" + endCol;
Sheet hideSheet = null; Sheet hideSheet = wb.createSheet(hideSheetName); // 用于存储 下拉菜单数据
String hideSheetDataName = hideSheetName + "_data"; for (int i = 0; i < textlist.length; i++)
Name name = wb.getName(hideSheetDataName);
if (name != null)
{ {
// 名称已存在尝试从名称的引用中找到sheet名称 hideSheet.createRow(i).createCell(0).setCellValue(textlist[i]);
String refersToFormula = name.getRefersToFormula();
if (StringUtils.isNotEmpty(refersToFormula) && refersToFormula.contains("!"))
{
String sheetNameFromFormula = refersToFormula.substring(0, refersToFormula.indexOf("!"));
hideSheet = wb.getSheet(sheetNameFromFormula);
}
} }
// 创建名称,可被其他单元格引用
if (hideSheet == null) Name name = wb.createName();
{ name.setNameName(hideSheetName + "_data");
hideSheet = wb.createSheet(hideSheetName); // 用于存储 下拉菜单数据 name.setRefersToFormula(hideSheetName + "!$A$1:$A$" + textlist.length);
for (int i = 0; i < textlist.length; i++)
{
hideSheet.createRow(i).createCell(0).setCellValue(textlist[i]);
}
// 创建名称,可被其他单元格引用
name = wb.createName();
name.setNameName(hideSheetDataName);
name.setRefersToFormula(hideSheetName + "!$A$1:$A$" + textlist.length);
}
DataValidationHelper helper = sheet.getDataValidationHelper(); DataValidationHelper helper = sheet.getDataValidationHelper();
// 加载下拉列表内容 // 加载下拉列表内容
DataValidationConstraint constraint = helper.createFormulaListConstraint(hideSheetDataName); DataValidationConstraint constraint = helper.createFormulaListConstraint(hideSheetName + "_data");
// 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列 // 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列
CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
// 数据有效性对象 // 数据有效性对象
@@ -1166,7 +1130,7 @@ public class ExcelUtil<T>
public static String convertByExp(String propertyValue, String converterExp, String separator) public static String convertByExp(String propertyValue, String converterExp, String separator)
{ {
StringBuilder propertyString = new StringBuilder(); StringBuilder propertyString = new StringBuilder();
String[] convertSource = converterExp.split(SEPARATOR); String[] convertSource = converterExp.split(",");
for (String item : convertSource) for (String item : convertSource)
{ {
String[] itemArray = item.split("="); String[] itemArray = item.split("=");
@@ -1203,7 +1167,7 @@ public class ExcelUtil<T>
public static String reverseByExp(String propertyValue, String converterExp, String separator) public static String reverseByExp(String propertyValue, String converterExp, String separator)
{ {
StringBuilder propertyString = new StringBuilder(); StringBuilder propertyString = new StringBuilder();
String[] convertSource = converterExp.split(SEPARATOR); String[] convertSource = converterExp.split(",");
for (String item : convertSource) for (String item : convertSource)
{ {
String[] itemArray = item.split("="); String[] itemArray = item.split("=");
@@ -1291,7 +1255,7 @@ public class ExcelUtil<T>
{ {
cell = row.createCell(key); cell = row.createCell(key);
cell.setCellStyle(styles.get("total")); cell.setCellStyle(styles.get("total"));
cell.setCellValue(statistics.get(key)); cell.setCellValue(DOUBLE_FORMAT.format(statistics.get(key)));
} }
statistics.clear(); statistics.clear();
} }
@@ -1366,8 +1330,6 @@ public class ExcelUtil<T>
{ {
List<Object[]> fields = new ArrayList<Object[]>(); List<Object[]> fields = new ArrayList<Object[]>();
List<Field> tempFields = new ArrayList<>(); List<Field> tempFields = new ArrayList<>();
subFieldsMap = new HashMap<>();
subMethods = new HashMap<>();
tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields())); tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));
tempFields.addAll(Arrays.asList(clazz.getDeclaredFields())); tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
if (StringUtils.isNotEmpty(includeFields)) if (StringUtils.isNotEmpty(includeFields))
@@ -1415,11 +1377,10 @@ public class ExcelUtil<T>
} }
if (Collection.class.isAssignableFrom(field.getType())) if (Collection.class.isAssignableFrom(field.getType()))
{ {
String fieldName = field.getName(); subMethod = getSubMethod(field.getName(), clazz);
subMethods.put(fieldName, getSubMethod(fieldName, clazz));
ParameterizedType pt = (ParameterizedType) field.getGenericType(); ParameterizedType pt = (ParameterizedType) field.getGenericType();
Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0]; Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];
subFieldsMap.put(fieldName, FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class)); this.subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class);
} }
} }
@@ -1488,8 +1449,7 @@ public class ExcelUtil<T>
{ {
this.sheet = wb.createSheet(); this.sheet = wb.createSheet();
this.createTitle(); this.createTitle();
int actualIndex = wb.getSheetIndex(this.sheet); wb.setSheetName(index, sheetName + index);
wb.setSheetName(actualIndex, sheetName + index);
} }
} }
@@ -1614,7 +1574,7 @@ public class ExcelUtil<T>
*/ */
public boolean isSubList() public boolean isSubList()
{ {
return !StringUtils.isEmpty(subFieldsMap); return StringUtils.isNotNull(subFields) && subFields.size() > 0;
} }
/** /**
@@ -1622,32 +1582,24 @@ public class ExcelUtil<T>
*/ */
public boolean isSubListValue(T vo) public boolean isSubListValue(T vo)
{ {
return !StringUtils.isEmpty(subFieldsMap) && getListCellValue(vo) > 0; return StringUtils.isNotNull(subFields) && subFields.size() > 0 && StringUtils.isNotNull(getListCellValue(vo)) && getListCellValue(vo).size() > 0;
} }
/** /**
* 获取集合的值 * 获取集合的值
*/ */
public int getListCellValue(Object obj) public Collection<?> getListCellValue(Object obj)
{ {
Collection<?> value; Object value;
int max = 0;
try try
{ {
for (String s : subMethods.keySet()) value = subMethod.invoke(obj, new Object[] {});
{
value = (Collection<?>) subMethods.get(s).invoke(obj);
if (value.size() > max)
{
max = value.size();
}
}
} }
catch (Exception e) catch (Exception e)
{ {
return 0; return new ArrayList<Object>();
} }
return max; return (Collection<?>) value;
} }
/** /**

View File

@@ -343,25 +343,25 @@ public final class UUID implements java.io.Serializable, Comparable<UUID>
final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36); final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36);
// time_low // time_low
builder.append(digits(mostSigBits >> 32, 8)); builder.append(digits(mostSigBits >> 32, 8));
if (!isSimple) if (false == isSimple)
{ {
builder.append('-'); builder.append('-');
} }
// time_mid // time_mid
builder.append(digits(mostSigBits >> 16, 4)); builder.append(digits(mostSigBits >> 16, 4));
if (!isSimple) if (false == isSimple)
{ {
builder.append('-'); builder.append('-');
} }
// time_high_and_version // time_high_and_version
builder.append(digits(mostSigBits, 4)); builder.append(digits(mostSigBits, 4));
if (!isSimple) if (false == isSimple)
{ {
builder.append('-'); builder.append('-');
} }
// variant_and_sequence // variant_and_sequence
builder.append(digits(leastSigBits >> 48, 4)); builder.append(digits(leastSigBits >> 48, 4));
if (!isSimple) if (false == isSimple)
{ {
builder.append('-'); builder.append('-');
} }

View File

@@ -7,17 +7,12 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.InitBinder;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
import com.ruoyi.common.core.constant.HttpStatus; import com.ruoyi.common.core.constant.HttpStatus;
import com.ruoyi.common.core.utils.DateUtils; import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.PageUtils; import com.ruoyi.common.core.utils.PageUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.sql.SqlUtil;
import com.ruoyi.common.core.web.domain.AjaxResult; import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.web.page.PageDomain;
import com.ruoyi.common.core.web.page.TableDataInfo; import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.common.core.web.page.TableSupport;
/** /**
* web层通用数据处理 * web层通用数据处理
@@ -53,19 +48,6 @@ public class BaseController
PageUtils.startPage(); PageUtils.startPage();
} }
/**
* 设置请求排序数据
*/
protected void startOrderBy()
{
PageDomain pageDomain = TableSupport.buildPageRequest();
if (StringUtils.isNotEmpty(pageDomain.getOrderBy()))
{
String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
PageHelper.orderBy(orderBy);
}
}
/** /**
* 清理分页的线程变量 * 清理分页的线程变量
*/ */

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.7</version> <version>3.6.5</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -94,7 +94,7 @@ public class DataScopeAspect
List<String> conditions = new ArrayList<String>(); List<String> conditions = new ArrayList<String>();
List<String> scopeCustomIds = new ArrayList<String>(); List<String> scopeCustomIds = new ArrayList<String>();
user.getRoles().forEach(role -> { user.getRoles().forEach(role -> {
if (DATA_SCOPE_CUSTOM.equals(role.getDataScope()) && StringUtils.equals(role.getStatus(), UserConstants.ROLE_NORMAL) && (StringUtils.isEmpty(permission) || StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))) if (DATA_SCOPE_CUSTOM.equals(role.getDataScope()) && StringUtils.equals(role.getStatus(), UserConstants.ROLE_NORMAL) && StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
{ {
scopeCustomIds.add(Convert.toStr(role.getRoleId())); scopeCustomIds.add(Convert.toStr(role.getRoleId()));
} }
@@ -107,7 +107,7 @@ public class DataScopeAspect
{ {
continue; continue;
} }
if (StringUtils.isNotEmpty(permission) && !StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission))) if (!StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
{ {
continue; continue;
} }

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.7</version> <version>3.6.5</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.7</version> <version>3.6.5</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -48,9 +48,6 @@ public class LogAspect
/** 计算操作消耗时间 */ /** 计算操作消耗时间 */
private static final ThreadLocal<Long> TIME_THREADLOCAL = new NamedThreadLocal<Long>("Cost Time"); private static final ThreadLocal<Long> TIME_THREADLOCAL = new NamedThreadLocal<Long>("Cost Time");
/** 参数最大长度限制 */
private static final int PARAM_MAX_LENGTH = 2000;
@Autowired @Autowired
private AsyncLogService asyncLogService; private AsyncLogService asyncLogService;
@@ -169,16 +166,16 @@ public class LogAspect
*/ */
private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog, String[] excludeParamNames) throws Exception private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog, String[] excludeParamNames) throws Exception
{ {
String requestMethod = operLog.getRequestMethod();
Map<?, ?> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest()); Map<?, ?> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest());
String requestMethod = operLog.getRequestMethod();
if (StringUtils.isEmpty(paramsMap) && StringUtils.equalsAny(requestMethod, HttpMethod.PUT.name(), HttpMethod.POST.name(), HttpMethod.DELETE.name())) if (StringUtils.isEmpty(paramsMap) && StringUtils.equalsAny(requestMethod, HttpMethod.PUT.name(), HttpMethod.POST.name(), HttpMethod.DELETE.name()))
{ {
String params = argsArrayToString(joinPoint.getArgs(), excludeParamNames); String params = argsArrayToString(joinPoint.getArgs(), excludeParamNames);
operLog.setOperParam(params); operLog.setOperParam(StringUtils.substring(params, 0, 2000));
} }
else else
{ {
operLog.setOperParam(StringUtils.substring(JSON.toJSONString(paramsMap, excludePropertyPreFilter(excludeParamNames)), 0, PARAM_MAX_LENGTH)); operLog.setOperParam(StringUtils.substring(JSON.toJSONString(paramsMap, excludePropertyPreFilter(excludeParamNames)), 0, 2000));
} }
} }
@@ -187,7 +184,7 @@ public class LogAspect
*/ */
private String argsArrayToString(Object[] paramsArray, String[] excludeParamNames) private String argsArrayToString(Object[] paramsArray, String[] excludeParamNames)
{ {
StringBuilder params = new StringBuilder(); String params = "";
if (paramsArray != null && paramsArray.length > 0) if (paramsArray != null && paramsArray.length > 0)
{ {
for (Object o : paramsArray) for (Object o : paramsArray)
@@ -197,20 +194,15 @@ public class LogAspect
try try
{ {
String jsonObj = JSON.toJSONString(o, excludePropertyPreFilter(excludeParamNames)); String jsonObj = JSON.toJSONString(o, excludePropertyPreFilter(excludeParamNames));
params.append(jsonObj).append(" "); params += jsonObj.toString() + " ";
if (params.length() >= PARAM_MAX_LENGTH)
{
return StringUtils.substring(params.toString(), 0, PARAM_MAX_LENGTH);
}
} }
catch (Exception e) catch (Exception e)
{ {
log.error("请求参数拼装异常 msg:{}, 参数:{}", e.getMessage(), paramsArray, e);
} }
} }
} }
} }
return params.toString(); return params.trim();
} }
/** /**

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.7</version> <version>3.6.5</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.7</version> <version>3.6.5</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.7</version> <version>3.6.5</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -56,8 +56,16 @@ public class PreAuthorizeAspect
// 注解鉴权 // 注解鉴权
MethodSignature signature = (MethodSignature) joinPoint.getSignature(); MethodSignature signature = (MethodSignature) joinPoint.getSignature();
checkMethodAnnotation(signature.getMethod()); checkMethodAnnotation(signature.getMethod());
// 执行原有逻辑 try
return joinPoint.proceed(); {
// 执行原有逻辑
Object obj = joinPoint.proceed();
return obj;
}
catch (Throwable e)
{
throw e;
}
} }
/** /**

View File

@@ -4,7 +4,6 @@ import javax.servlet.http.HttpServletRequest;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import com.ruoyi.common.core.constant.SecurityConstants; import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.constant.TokenConstants; import com.ruoyi.common.core.constant.TokenConstants;
import com.ruoyi.common.core.constant.UserConstants;
import com.ruoyi.common.core.context.SecurityContextHolder; import com.ruoyi.common.core.context.SecurityContextHolder;
import com.ruoyi.common.core.utils.ServletUtils; import com.ruoyi.common.core.utils.ServletUtils;
import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.StringUtils;
@@ -80,16 +79,6 @@ public class SecurityUtils
return token; return token;
} }
/**
* 是否为管理员
*
* @return 结果
*/
public static boolean isAdmin()
{
return isAdmin(getUserId());
}
/** /**
* 是否为管理员 * 是否为管理员
* *
@@ -98,7 +87,7 @@ public class SecurityUtils
*/ */
public static boolean isAdmin(Long userId) public static boolean isAdmin(Long userId)
{ {
return UserConstants.isAdmin(userId); return userId != null && 1L == userId;
} }
/** /**

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.7</version> <version>3.6.5</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@@ -17,10 +17,10 @@
<dependencies> <dependencies>
<!-- RuoYi Common Core --> <!-- RuoYi Common Security -->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-core</artifactId> <artifactId>ruoyi-common-security</artifactId>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@@ -8,10 +8,10 @@ import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer; import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.ruoyi.common.core.constant.UserConstants; import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.common.core.context.SecurityContextHolder;
import com.ruoyi.common.sensitive.annotation.Sensitive; import com.ruoyi.common.sensitive.annotation.Sensitive;
import com.ruoyi.common.sensitive.enums.DesensitizedType; import com.ruoyi.common.sensitive.enums.DesensitizedType;
import com.ruoyi.system.api.model.LoginUser;
/** /**
* 数据脱敏序列化过滤 * 数据脱敏序列化过滤
@@ -55,9 +55,9 @@ public class SensitiveJsonSerializer extends JsonSerializer<String> implements C
{ {
try try
{ {
Long userId = SecurityContextHolder.getUserId(); LoginUser securityUser = SecurityUtils.getLoginUser();
// 管理员不脱敏 // 管理员不脱敏
return !UserConstants.isAdmin(userId); return !securityUser.getSysUser().isAdmin();
} }
catch (Exception e) catch (Exception e)
{ {

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.7</version> <version>3.6.5</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.6.7</version> <version>3.6.5</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -0,0 +1,87 @@
package com.ruoyi.gateway.filter;
import java.util.Collections;
import java.util.List;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.OrderedGatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* 获取body请求数据解决流不能重复读取问题
*
* @author ruoyi
*/
@Component
public class CacheRequestFilter extends AbstractGatewayFilterFactory<CacheRequestFilter.Config>
{
public CacheRequestFilter()
{
super(Config.class);
}
@Override
public String name()
{
return "CacheRequestFilter";
}
@Override
public GatewayFilter apply(Config config)
{
CacheRequestGatewayFilter cacheRequestGatewayFilter = new CacheRequestGatewayFilter();
Integer order = config.getOrder();
if (order == null)
{
return cacheRequestGatewayFilter;
}
return new OrderedGatewayFilter(cacheRequestGatewayFilter, order);
}
public static class CacheRequestGatewayFilter implements GatewayFilter
{
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
{
// GET DELETE 不过滤
HttpMethod method = exchange.getRequest().getMethod();
if (method == null || method == HttpMethod.GET || method == HttpMethod.DELETE)
{
return chain.filter(exchange);
}
return ServerWebExchangeUtils.cacheRequestBodyAndRequest(exchange, (serverHttpRequest) -> {
if (serverHttpRequest == exchange.getRequest())
{
return chain.filter(exchange);
}
return chain.filter(exchange.mutate().request(serverHttpRequest).build());
});
}
}
@Override
public List<String> shortcutFieldOrder()
{
return Collections.singletonList("order");
}
static class Config
{
private Integer order;
public Integer getOrder()
{
return order;
}
public void setOrder(Integer order)
{
this.order = order;
}
}
}

View File

@@ -0,0 +1,37 @@
# Tomcat
server:
port: 8080
# Spring
spring:
application:
# 应用名称
name: ${SERVER_NAME}
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: ${NACOS_SERVER}:${NACOS_PORT}
config:
# 配置中心地址
server-addr: ${NACOS_SERVER}:${NACOS_PORT}
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- ${NACOS_SHARED_CONFIGS}
sentinel:
# 取消控制台懒加载
eager: true
transport:
# 控制台地址
dashboard: 127.0.0.1:8718
# nacos配置持久化
datasource:
ds1:
nacos:
server-addr: ${NACOS_SERVER}:${NACOS_PORT}
dataId: sentinel-ruoyi-gateway
groupId: DEFAULT_GROUP
data-type: json
rule-type: gw-flow

View File

@@ -9,7 +9,7 @@ spring:
name: ruoyi-gateway name: ruoyi-gateway
profiles: profiles:
# 环境配置 # 环境配置
active: dev active: ${SPRING_PROFILES_ACTIVE:dev}
cloud: cloud:
nacos: nacos:
discovery: discovery:

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.6.7</version> <version>3.6.5</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-modules</artifactId> <artifactId>ruoyi-modules</artifactId>
<version>3.6.7</version> <version>3.6.5</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -1,46 +0,0 @@
package com.ruoyi.file.config;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.DispatcherType;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.ruoyi.file.filter.RefererFilter;
/**
* Filter配置
*
* @author ruoyi
*/
@Configuration
public class FilterConfig
{
/**
* 资源映射路径 前缀
*/
@Value("${file.prefix}")
public String localFilePrefix;
@Value("${referer.allowed-domains}")
private String allowedDomains;
@SuppressWarnings({"rawtypes", "unchecked"})
@Bean
@ConditionalOnProperty(value = "referer.enabled", havingValue = "true")
public FilterRegistrationBean refererFilterRegistration()
{
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setDispatcherTypes(DispatcherType.REQUEST);
registration.setFilter(new RefererFilter());
registration.addUrlPatterns(localFilePrefix + "/*");
registration.setName("refererFilter");
registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE);
Map<String, String> initParameters = new HashMap<String, String>();
initParameters.put("allowedDomains", allowedDomains);
registration.setInitParameters(initParameters);
return registration;
}
}

View File

@@ -3,12 +3,10 @@ package com.ruoyi.file.controller;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.file.FileUtils; import com.ruoyi.common.core.utils.file.FileUtils;
import com.ruoyi.file.service.ISysFileService; import com.ruoyi.file.service.ISysFileService;
import com.ruoyi.system.api.domain.SysFile; import com.ruoyi.system.api.domain.SysFile;
@@ -47,26 +45,4 @@ public class SysFileController
return R.fail(e.getMessage()); return R.fail(e.getMessage());
} }
} }
}
/**
* 文件删除请求
*/
@DeleteMapping("delete")
public R<Boolean> delete(String fileUrl)
{
try
{
if (!FileUtils.validateFilePath(fileUrl))
{
throw new Exception(StringUtils.format("资源文件({})非法,不允许删除。 ", fileUrl));
}
sysFileService.deleteFile(fileUrl);
return R.ok();
}
catch (Exception e)
{
log.error("删除文件失败", e);
return R.fail(e.getMessage());
}
}
}

View File

@@ -1,77 +0,0 @@
package com.ruoyi.file.filter;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 防盗链过滤器
*
* @author ruoyi
*/
public class RefererFilter implements Filter
{
/**
* 允许的域名列表
*/
public List<String> allowedDomains;
@Override
public void init(FilterConfig filterConfig) throws ServletException
{
String domains = filterConfig.getInitParameter("allowedDomains");
this.allowedDomains = Arrays.asList(domains.split(","));
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
String referer = req.getHeader("Referer");
// 如果Referer为空拒绝访问
if (referer == null || referer.isEmpty())
{
resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Access denied: Referer header is required");
return;
}
// 检查Referer是否在允许的域名列表中
boolean allowed = false;
for (String domain : allowedDomains)
{
if (referer.contains(domain))
{
allowed = true;
break;
}
}
// 根据检查结果决定是否放行
if (allowed)
{
chain.doFilter(request, response);
}
else
{
resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Access denied: Referer '" + referer + "' is not allowed");
}
}
@Override
public void destroy()
{
}
}

View File

@@ -1,11 +1,11 @@
package com.ruoyi.file.service; package com.ruoyi.file.service;
import java.io.InputStream; import java.io.InputStream;
import com.alibaba.nacos.common.utils.IoUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.alibaba.nacos.common.utils.IoUtils;
import com.github.tobato.fastdfs.domain.fdfs.StorePath; import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient; import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.ruoyi.common.core.utils.file.FileTypeUtils; import com.ruoyi.common.core.utils.file.FileTypeUtils;
@@ -53,24 +53,4 @@ public class FastDfsSysFileServiceImpl implements ISysFileService
IoUtils.closeQuietly(inputStream); IoUtils.closeQuietly(inputStream);
} }
} }
/**
* FastDFS文件删除接口
*
* @param fileUrl 文件访问URL
* @throws Exception
*/
@Override
public void deleteFile(String fileUrl) throws Exception
{
try
{
StorePath storePath = StorePath.parseFromUrl(fileUrl);
storageClient.deleteFile(storePath.getGroup(), storePath.getPath());
}
catch (Exception e)
{
throw new RuntimeException("FastDfs Failed to delete file: ", e);
}
}
} }

View File

@@ -17,12 +17,4 @@ public interface ISysFileService
* @throws Exception * @throws Exception
*/ */
public String uploadFile(MultipartFile file) throws Exception; public String uploadFile(MultipartFile file) throws Exception;
/**
* 文件删除接口
*
* @param fileUrl 文件访问URL
* @throws Exception
*/
public void deleteFile(String fileUrl) throws Exception;
} }

View File

@@ -4,8 +4,6 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.file.FileUtils;
import com.ruoyi.file.utils.FileUploadUtils; import com.ruoyi.file.utils.FileUploadUtils;
/** /**
@@ -49,17 +47,4 @@ public class LocalSysFileServiceImpl implements ISysFileService
String url = domain + localFilePrefix + name; String url = domain + localFilePrefix + name;
return url; return url;
} }
/**
* 本地文件删除接口
*
* @param fileUrl 文件访问URL
* @throws Exception
*/
@Override
public void deleteFile(String fileUrl) throws Exception
{
String localFile = StringUtils.substringAfter(fileUrl, localFilePrefix);
FileUtils.deleteFile(localFilePath + localFile);
}
} }

View File

@@ -5,12 +5,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.alibaba.nacos.common.utils.IoUtils; import com.alibaba.nacos.common.utils.IoUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.file.config.MinioConfig; import com.ruoyi.file.config.MinioConfig;
import com.ruoyi.file.utils.FileUploadUtils; import com.ruoyi.file.utils.FileUploadUtils;
import io.minio.MinioClient; import io.minio.MinioClient;
import io.minio.PutObjectArgs; import io.minio.PutObjectArgs;
import io.minio.RemoveObjectArgs;
/** /**
* Minio 文件存储 * Minio 文件存储
@@ -59,24 +57,4 @@ public class MinioSysFileServiceImpl implements ISysFileService
IoUtils.closeQuietly(inputStream); IoUtils.closeQuietly(inputStream);
} }
} }
/**
* Minio文件删除接口
*
* @param fileUrl 文件访问URL
* @throws Exception
*/
@Override
public void deleteFile(String fileUrl) throws Exception
{
try
{
String minioFile = StringUtils.substringAfter(fileUrl, minioConfig.getBucketName());
client.removeObject(RemoveObjectArgs.builder().bucket(minioConfig.getBucketName()).object(minioFile).build());
}
catch (Exception e)
{
throw new RuntimeException("Minio Failed to delete file", e);
}
}
} }

View File

@@ -0,0 +1,23 @@
# Tomcat
server:
port: 9300
# Spring
spring:
application:
# 应用名称
name: ${SERVER_NAME}
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: ${NACOS_SERVER}:${NACOS_PORT}
config:
# 配置中心地址
server-addr: ${NACOS_SERVER}:${NACOS_PORT}
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- ${NACOS_SHARED_CONFIGS}

View File

@@ -9,7 +9,7 @@ spring:
name: ruoyi-file name: ruoyi-file
profiles: profiles:
# 环境配置 # 环境配置
active: dev active: ${SPRING_PROFILES_ACTIVE:dev}
cloud: cloud:
nacos: nacos:
discovery: discovery:

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-modules</artifactId> <artifactId>ruoyi-modules</artifactId>
<version>3.6.7</version> <version>3.6.5</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -57,7 +57,7 @@ public class GenController extends BaseController
} }
/** /**
* 获取代码生成信息 * 修改代码生成业务
*/ */
@RequiresPermissions("tool:gen:query") @RequiresPermissions("tool:gen:query")
@GetMapping(value = "/{tableId}") @GetMapping(value = "/{tableId}")

View File

@@ -0,0 +1,23 @@
# Tomcat
server:
port: 9202
# Spring
spring:
application:
# 应用名称
name: ${SERVER_NAME}
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: ${NACOS_SERVER}:${NACOS_PORT}
config:
# 配置中心地址
server-addr: ${NACOS_SERVER}:${NACOS_PORT}
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- ${NACOS_SHARED_CONFIGS}

View File

@@ -9,7 +9,7 @@ spring:
name: ruoyi-gen name: ruoyi-gen
profiles: profiles:
# 环境配置 # 环境配置
active: dev active: ${SPRING_PROFILES_ACTIVE:dev}
cloud: cloud:
nacos: nacos:
discovery: discovery:

View File

@@ -283,9 +283,9 @@
</template> </template>
<script> <script>
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}" import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}";
import Treeselect from "@riophae/vue-treeselect" import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css" import "@riophae/vue-treeselect/dist/vue-treeselect.css";
export default { export default {
name: "${BusinessName}", name: "${BusinessName}",
@@ -346,18 +346,18 @@ export default {
#end #end
#end #end
} }
} };
}, },
created() { created() {
this.getList() this.getList();
}, },
methods: { methods: {
/** 查询${functionName}列表 */ /** 查询${functionName}列表 */
getList() { getList() {
this.loading = true this.loading = true;
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
this.queryParams.params = {} this.queryParams.params = {};
#break #break
#end #end
#end #end
@@ -365,40 +365,40 @@ export default {
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
if (null != this.daterange${AttrName} && '' != this.daterange${AttrName}) { if (null != this.daterange${AttrName} && '' != this.daterange${AttrName}) {
this.queryParams.params["begin${AttrName}"] = this.daterange${AttrName}[0] this.queryParams.params["begin${AttrName}"] = this.daterange${AttrName}[0];
this.queryParams.params["end${AttrName}"] = this.daterange${AttrName}[1] this.queryParams.params["end${AttrName}"] = this.daterange${AttrName}[1];
} }
#end #end
#end #end
list${BusinessName}(this.queryParams).then(response => { list${BusinessName}(this.queryParams).then(response => {
this.${businessName}List = this.handleTree(response.data, "${treeCode}", "${treeParentCode}") this.${businessName}List = this.handleTree(response.data, "${treeCode}", "${treeParentCode}");
this.loading = false this.loading = false;
}) });
}, },
/** 转换${functionName}数据结构 */ /** 转换${functionName}数据结构 */
normalizer(node) { normalizer(node) {
if (node.children && !node.children.length) { if (node.children && !node.children.length) {
delete node.children delete node.children;
} }
return { return {
id: node.${treeCode}, id: node.${treeCode},
label: node.${treeName}, label: node.${treeName},
children: node.children children: node.children
} };
}, },
/** 查询${functionName}下拉树结构 */ /** 查询${functionName}下拉树结构 */
getTreeselect() { getTreeselect() {
list${BusinessName}().then(response => { list${BusinessName}().then(response => {
this.${businessName}Options = [] this.${businessName}Options = [];
const data = { ${treeCode}: 0, ${treeName}: '顶级节点', children: [] } const data = { ${treeCode}: 0, ${treeName}: '顶级节点', children: [] };
data.children = this.handleTree(response.data, "${treeCode}", "${treeParentCode}") data.children = this.handleTree(response.data, "${treeCode}", "${treeParentCode}");
this.${businessName}Options.push(data) this.${businessName}Options.push(data);
}) });
}, },
// 取消按钮 // 取消按钮
cancel() { cancel() {
this.open = false this.open = false;
this.reset() this.reset();
}, },
// 表单重置 // 表单重置
reset() { reset() {
@@ -410,61 +410,61 @@ export default {
$column.javaField: null#if($foreach.count != $columns.size()),#end $column.javaField: null#if($foreach.count != $columns.size()),#end
#end #end
#end #end
} };
this.resetForm("form") this.resetForm("form");
}, },
/** 搜索按钮操作 */ /** 搜索按钮操作 */
handleQuery() { handleQuery() {
this.getList() this.getList();
}, },
/** 重置按钮操作 */ /** 重置按钮操作 */
resetQuery() { resetQuery() {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
this.daterange${AttrName} = [] this.daterange${AttrName} = [];
#end #end
#end #end
this.resetForm("queryForm") this.resetForm("queryForm");
this.handleQuery() this.handleQuery();
}, },
/** 新增按钮操作 */ /** 新增按钮操作 */
handleAdd(row) { handleAdd(row) {
this.reset() this.reset();
this.getTreeselect() this.getTreeselect();
if (row != null && row.${treeCode}) { if (row != null && row.${treeCode}) {
this.form.${treeParentCode} = row.${treeCode} this.form.${treeParentCode} = row.${treeCode};
} else { } else {
this.form.${treeParentCode} = 0 this.form.${treeParentCode} = 0;
} }
this.open = true this.open = true;
this.title = "添加${functionName}" this.title = "添加${functionName}";
}, },
/** 展开/折叠操作 */ /** 展开/折叠操作 */
toggleExpandAll() { toggleExpandAll() {
this.refreshTable = false this.refreshTable = false;
this.isExpandAll = !this.isExpandAll this.isExpandAll = !this.isExpandAll;
this.$nextTick(() => { this.$nextTick(() => {
this.refreshTable = true this.refreshTable = true;
}) });
}, },
/** 修改按钮操作 */ /** 修改按钮操作 */
handleUpdate(row) { handleUpdate(row) {
this.reset() this.reset();
this.getTreeselect() this.getTreeselect();
if (row != null) { if (row != null) {
this.form.${treeParentCode} = row.${treeParentCode} this.form.${treeParentCode} = row.${treeParentCode};
} }
get${BusinessName}(row.${pkColumn.javaField}).then(response => { get${BusinessName}(row.${pkColumn.javaField}).then(response => {
this.form = response.data this.form = response.data;
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "checkbox") #if($column.htmlType == "checkbox")
this.form.$column.javaField = this.form.${column.javaField}.split(",") this.form.$column.javaField = this.form.${column.javaField}.split(",");
#end #end
#end #end
this.open = true this.open = true;
this.title = "修改${functionName}" this.title = "修改${functionName}";
}) });
}, },
/** 提交按钮 */ /** 提交按钮 */
submitForm() { submitForm() {
@@ -472,34 +472,34 @@ export default {
if (valid) { if (valid) {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "checkbox") #if($column.htmlType == "checkbox")
this.form.$column.javaField = this.form.${column.javaField}.join(",") this.form.$column.javaField = this.form.${column.javaField}.join(",");
#end #end
#end #end
if (this.form.${pkColumn.javaField} != null) { if (this.form.${pkColumn.javaField} != null) {
update${BusinessName}(this.form).then(response => { update${BusinessName}(this.form).then(response => {
this.#[[$modal]]#.msgSuccess("修改成功") this.#[[$modal]]#.msgSuccess("修改成功");
this.open = false this.open = false;
this.getList() this.getList();
}) });
} else { } else {
add${BusinessName}(this.form).then(response => { add${BusinessName}(this.form).then(response => {
this.#[[$modal]]#.msgSuccess("新增成功") this.#[[$modal]]#.msgSuccess("新增成功");
this.open = false this.open = false;
this.getList() this.getList();
}) });
} }
} }
}) });
}, },
/** 删除按钮操作 */ /** 删除按钮操作 */
handleDelete(row) { handleDelete(row) {
this.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + row.${pkColumn.javaField} + '"的数据项?').then(function() { this.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + row.${pkColumn.javaField} + '"的数据项?').then(function() {
return del${BusinessName}(row.${pkColumn.javaField}) return del${BusinessName}(row.${pkColumn.javaField});
}).then(() => { }).then(() => {
this.getList() this.getList();
this.#[[$modal]]#.msgSuccess("删除成功") this.#[[$modal]]#.msgSuccess("删除成功");
}).catch(() => {}) }).catch(() => {});
} }
} }
} };
</script> </script>

View File

@@ -353,7 +353,7 @@
</template> </template>
<script> <script>
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}" import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}";
export default { export default {
name: "${BusinessName}", name: "${BusinessName}",
@@ -423,18 +423,18 @@ export default {
#end #end
#end #end
} }
} };
}, },
created() { created() {
this.getList() this.getList();
}, },
methods: { methods: {
/** 查询${functionName}列表 */ /** 查询${functionName}列表 */
getList() { getList() {
this.loading = true this.loading = true;
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
this.queryParams.params = {} this.queryParams.params = {};
#break #break
#end #end
#end #end
@@ -442,21 +442,21 @@ export default {
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
if (null != this.daterange${AttrName} && '' != this.daterange${AttrName}) { if (null != this.daterange${AttrName} && '' != this.daterange${AttrName}) {
this.queryParams.params["begin${AttrName}"] = this.daterange${AttrName}[0] this.queryParams.params["begin${AttrName}"] = this.daterange${AttrName}[0];
this.queryParams.params["end${AttrName}"] = this.daterange${AttrName}[1] this.queryParams.params["end${AttrName}"] = this.daterange${AttrName}[1];
} }
#end #end
#end #end
list${BusinessName}(this.queryParams).then(response => { list${BusinessName}(this.queryParams).then(response => {
this.${businessName}List = response.rows this.${businessName}List = response.rows;
this.total = response.total this.total = response.total;
this.loading = false this.loading = false;
}) });
}, },
// 取消按钮 // 取消按钮
cancel() { cancel() {
this.open = false this.open = false;
this.reset() this.reset();
}, },
// 表单重置 // 表单重置
reset() { reset() {
@@ -468,27 +468,27 @@ export default {
$column.javaField: null#if($foreach.count != $columns.size()),#end $column.javaField: null#if($foreach.count != $columns.size()),#end
#end #end
#end #end
} };
#if($table.sub) #if($table.sub)
this.${subclassName}List = [] this.${subclassName}List = [];
#end #end
this.resetForm("form") this.resetForm("form");
}, },
/** 搜索按钮操作 */ /** 搜索按钮操作 */
handleQuery() { handleQuery() {
this.queryParams.pageNum = 1 this.queryParams.pageNum = 1;
this.getList() this.getList();
}, },
/** 重置按钮操作 */ /** 重置按钮操作 */
resetQuery() { resetQuery() {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
this.daterange${AttrName} = [] this.daterange${AttrName} = [];
#end #end
#end #end
this.resetForm("queryForm") this.resetForm("queryForm");
this.handleQuery() this.handleQuery();
}, },
// 多选框选中数据 // 多选框选中数据
handleSelectionChange(selection) { handleSelectionChange(selection) {
@@ -498,27 +498,27 @@ export default {
}, },
/** 新增按钮操作 */ /** 新增按钮操作 */
handleAdd() { handleAdd() {
this.reset() this.reset();
this.open = true this.open = true;
this.title = "添加${functionName}" this.title = "添加${functionName}";
}, },
/** 修改按钮操作 */ /** 修改按钮操作 */
handleUpdate(row) { handleUpdate(row) {
this.reset() this.reset();
const ${pkColumn.javaField} = row.${pkColumn.javaField} || this.ids const ${pkColumn.javaField} = row.${pkColumn.javaField} || this.ids
get${BusinessName}(${pkColumn.javaField}).then(response => { get${BusinessName}(${pkColumn.javaField}).then(response => {
this.form = response.data this.form = response.data;
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "checkbox") #if($column.htmlType == "checkbox")
this.form.$column.javaField = this.form.${column.javaField}.split(",") this.form.$column.javaField = this.form.${column.javaField}.split(",");
#end #end
#end #end
#if($table.sub) #if($table.sub)
this.${subclassName}List = response.data.${subclassName}List this.${subclassName}List = response.data.${subclassName}List;
#end #end
this.open = true this.open = true;
this.title = "修改${functionName}" this.title = "修改${functionName}";
}) });
}, },
/** 提交按钮 */ /** 提交按钮 */
submitForm() { submitForm() {
@@ -526,64 +526,64 @@ export default {
if (valid) { if (valid) {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "checkbox") #if($column.htmlType == "checkbox")
this.form.$column.javaField = this.form.${column.javaField}.join(",") this.form.$column.javaField = this.form.${column.javaField}.join(",");
#end #end
#end #end
#if($table.sub) #if($table.sub)
this.form.${subclassName}List = this.${subclassName}List this.form.${subclassName}List = this.${subclassName}List;
#end #end
if (this.form.${pkColumn.javaField} != null) { if (this.form.${pkColumn.javaField} != null) {
update${BusinessName}(this.form).then(response => { update${BusinessName}(this.form).then(response => {
this.#[[$modal]]#.msgSuccess("修改成功") this.#[[$modal]]#.msgSuccess("修改成功");
this.open = false this.open = false;
this.getList() this.getList();
}) });
} else { } else {
add${BusinessName}(this.form).then(response => { add${BusinessName}(this.form).then(response => {
this.#[[$modal]]#.msgSuccess("新增成功") this.#[[$modal]]#.msgSuccess("新增成功");
this.open = false this.open = false;
this.getList() this.getList();
}) });
} }
} }
}) });
}, },
/** 删除按钮操作 */ /** 删除按钮操作 */
handleDelete(row) { handleDelete(row) {
const ${pkColumn.javaField}s = row.${pkColumn.javaField} || this.ids const ${pkColumn.javaField}s = row.${pkColumn.javaField} || this.ids;
this.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + ${pkColumn.javaField}s + '"的数据项?').then(function() { this.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + ${pkColumn.javaField}s + '"的数据项?').then(function() {
return del${BusinessName}(${pkColumn.javaField}s) return del${BusinessName}(${pkColumn.javaField}s);
}).then(() => { }).then(() => {
this.getList() this.getList();
this.#[[$modal]]#.msgSuccess("删除成功") this.#[[$modal]]#.msgSuccess("删除成功");
}).catch(() => {}) }).catch(() => {});
}, },
#if($table.sub) #if($table.sub)
/** ${subTable.functionName}序号 */ /** ${subTable.functionName}序号 */
row${subClassName}Index({ row, rowIndex }) { row${subClassName}Index({ row, rowIndex }) {
row.index = rowIndex + 1 row.index = rowIndex + 1;
}, },
/** ${subTable.functionName}添加按钮操作 */ /** ${subTable.functionName}添加按钮操作 */
handleAdd${subClassName}() { handleAdd${subClassName}() {
let obj = {} let obj = {};
#foreach($column in $subTable.columns) #foreach($column in $subTable.columns)
#if($column.pk || $column.javaField == ${subTableFkclassName}) #if($column.pk || $column.javaField == ${subTableFkclassName})
#elseif($column.list && "" != $javaField) #elseif($column.list && "" != $javaField)
obj.$column.javaField = "" obj.$column.javaField = "";
#end #end
#end #end
this.${subclassName}List.push(obj) this.${subclassName}List.push(obj);
}, },
/** ${subTable.functionName}删除按钮操作 */ /** ${subTable.functionName}删除按钮操作 */
handleDelete${subClassName}() { handleDelete${subClassName}() {
if (this.checked${subClassName}.length == 0) { if (this.checked${subClassName}.length == 0) {
this.#[[$modal]]#.msgError("请先选择要删除的${subTable.functionName}数据") this.#[[$modal]]#.msgError("请先选择要删除的${subTable.functionName}数据");
} else { } else {
const ${subclassName}List = this.${subclassName}List const ${subclassName}List = this.${subclassName}List;
const checked${subClassName} = this.checked${subClassName} const checked${subClassName} = this.checked${subClassName};
this.${subclassName}List = ${subclassName}List.filter(function(item) { this.${subclassName}List = ${subclassName}List.filter(function(item) {
return checked${subClassName}.indexOf(item.index) == -1 return checked${subClassName}.indexOf(item.index) == -1
}) });
} }
}, },
/** 复选框选中数据 */ /** 复选框选中数据 */
@@ -598,5 +598,5 @@ export default {
}, `${businessName}_#[[${new Date().getTime()}]]#.xlsx`) }, `${businessName}_#[[${new Date().getTime()}]]#.xlsx`)
} }
} }
} };
</script> </script>

View File

@@ -271,26 +271,26 @@
</template> </template>
<script setup name="${BusinessName}"> <script setup name="${BusinessName}">
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}" import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}";
const { proxy } = getCurrentInstance() const { proxy } = getCurrentInstance();
#if(${dicts} != '') #if(${dicts} != '')
#set($dictsNoSymbol=$dicts.replace("'", "")) #set($dictsNoSymbol=$dicts.replace("'", ""))
const { ${dictsNoSymbol} } = proxy.useDict(${dicts}) const { ${dictsNoSymbol} } = proxy.useDict(${dicts});
#end #end
const ${businessName}List = ref([]) const ${businessName}List = ref([]);
const ${businessName}Options = ref([]) const ${businessName}Options = ref([]);
const open = ref(false) const open = ref(false);
const loading = ref(true) const loading = ref(true);
const showSearch = ref(true) const showSearch = ref(true);
const title = ref("") const title = ref("");
const isExpandAll = ref(true) const isExpandAll = ref(true);
const refreshTable = ref(true) const refreshTable = ref(true);
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
const daterange${AttrName} = ref([]) const daterange${AttrName} = ref([]);
#end #end
#end #end
@@ -318,48 +318,48 @@ const data = reactive({
#end #end
#end #end
} }
}) });
const { queryParams, form, rules } = toRefs(data) const { queryParams, form, rules } = toRefs(data);
/** 查询${functionName}列表 */ /** 查询${functionName}列表 */
function getList() { function getList() {
loading.value = true loading.value = true;
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
queryParams.value.params = {} queryParams.value.params = {};
#break #break
#end #end
#end #end
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
if (null != daterange${AttrName}.value && '' != daterange${AttrName}.value) { if (null != daterange${AttrName} && '' != daterange${AttrName}) {
queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0] queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0];
queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1] queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1];
} }
#end #end
#end #end
list${BusinessName}(queryParams.value).then(response => { list${BusinessName}(queryParams.value).then(response => {
${businessName}List.value = proxy.handleTree(response.data, "${treeCode}", "${treeParentCode}") ${businessName}List.value = proxy.handleTree(response.data, "${treeCode}", "${treeParentCode}");
loading.value = false loading.value = false;
}) });
} }
/** 查询${functionName}下拉树结构 */ /** 查询${functionName}下拉树结构 */
function getTreeselect() { function getTreeselect() {
list${BusinessName}().then(response => { list${BusinessName}().then(response => {
${businessName}Options.value = [] ${businessName}Options.value = [];
const data = { ${treeCode}: 0, ${treeName}: '顶级节点', children: [] } const data = { ${treeCode}: 0, ${treeName}: '顶级节点', children: [] };
data.children = proxy.handleTree(response.data, "${treeCode}", "${treeParentCode}") data.children = proxy.handleTree(response.data, "${treeCode}", "${treeParentCode}");
${businessName}Options.value.push(data) ${businessName}Options.value.push(data);
}) });
} }
// 取消按钮 // 取消按钮
function cancel() { function cancel() {
open.value = false open.value = false;
reset() reset();
} }
// 表单重置 // 表单重置
@@ -372,13 +372,13 @@ function reset() {
$column.javaField: null#if($foreach.count != $columns.size()),#end $column.javaField: null#if($foreach.count != $columns.size()),#end
#end #end
#end #end
} };
proxy.resetForm("${businessName}Ref") proxy.resetForm("${businessName}Ref");
} }
/** 搜索按钮操作 */ /** 搜索按钮操作 */
function handleQuery() { function handleQuery() {
getList() getList();
} }
/** 重置按钮操作 */ /** 重置按钮操作 */
@@ -386,52 +386,52 @@ function resetQuery() {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
daterange${AttrName}.value = [] daterange${AttrName}.value = [];
#end #end
#end #end
proxy.resetForm("queryRef") proxy.resetForm("queryRef");
handleQuery() handleQuery();
} }
/** 新增按钮操作 */ /** 新增按钮操作 */
function handleAdd(row) { function handleAdd(row) {
reset() reset();
getTreeselect() getTreeselect();
if (row != null && row.${treeCode}) { if (row != null && row.${treeCode}) {
form.value.${treeParentCode} = row.${treeCode} form.value.${treeParentCode} = row.${treeCode};
} else { } else {
form.value.${treeParentCode} = 0 form.value.${treeParentCode} = 0;
} }
open.value = true open.value = true;
title.value = "添加${functionName}" title.value = "添加${functionName}";
} }
/** 展开/折叠操作 */ /** 展开/折叠操作 */
function toggleExpandAll() { function toggleExpandAll() {
refreshTable.value = false refreshTable.value = false;
isExpandAll.value = !isExpandAll.value isExpandAll.value = !isExpandAll.value;
nextTick(() => { nextTick(() => {
refreshTable.value = true refreshTable.value = true;
}) });
} }
/** 修改按钮操作 */ /** 修改按钮操作 */
async function handleUpdate(row) { async function handleUpdate(row) {
reset() reset();
await getTreeselect() await getTreeselect();
if (row != null) { if (row != null) {
form.value.${treeParentCode} = row.${treeParentCode} form.value.${treeParentCode} = row.${treeParentCode};
} }
get${BusinessName}(row.${pkColumn.javaField}).then(response => { get${BusinessName}(row.${pkColumn.javaField}).then(response => {
form.value = response.data form.value = response.data;
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "checkbox") #if($column.htmlType == "checkbox")
form.value.$column.javaField = form.value.${column.javaField}.split(",") form.value.$column.javaField = form.value.${column.javaField}.split(",");
#end #end
#end #end
open.value = true open.value = true;
title.value = "修改${functionName}" title.value = "修改${functionName}";
}) });
} }
/** 提交按钮 */ /** 提交按钮 */
@@ -440,35 +440,35 @@ function submitForm() {
if (valid) { if (valid) {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "checkbox") #if($column.htmlType == "checkbox")
form.value.$column.javaField = form.value.${column.javaField}.join(",") form.value.$column.javaField = form.value.${column.javaField}.join(",");
#end #end
#end #end
if (form.value.${pkColumn.javaField} != null) { if (form.value.${pkColumn.javaField} != null) {
update${BusinessName}(form.value).then(response => { update${BusinessName}(form.value).then(response => {
proxy.#[[$modal]]#.msgSuccess("修改成功") proxy.#[[$modal]]#.msgSuccess("修改成功");
open.value = false open.value = false;
getList() getList();
}) });
} else { } else {
add${BusinessName}(form.value).then(response => { add${BusinessName}(form.value).then(response => {
proxy.#[[$modal]]#.msgSuccess("新增成功") proxy.#[[$modal]]#.msgSuccess("新增成功");
open.value = false open.value = false;
getList() getList();
}) });
} }
} }
}) });
} }
/** 删除按钮操作 */ /** 删除按钮操作 */
function handleDelete(row) { function handleDelete(row) {
proxy.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + row.${pkColumn.javaField} + '"的数据项?').then(function() { proxy.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + row.${pkColumn.javaField} + '"的数据项?').then(function() {
return del${BusinessName}(row.${pkColumn.javaField}) return del${BusinessName}(row.${pkColumn.javaField});
}).then(() => { }).then(() => {
getList() getList();
proxy.#[[$modal]]#.msgSuccess("删除成功") proxy.#[[$modal]]#.msgSuccess("删除成功");
}).catch(() => {}) }).catch(() => {});
} }
getList() getList();
</script> </script>

View File

@@ -343,33 +343,33 @@
</template> </template>
<script setup name="${BusinessName}"> <script setup name="${BusinessName}">
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}" import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}";
const { proxy } = getCurrentInstance() const { proxy } = getCurrentInstance();
#if(${dicts} != '') #if(${dicts} != '')
#set($dictsNoSymbol=$dicts.replace("'", "")) #set($dictsNoSymbol=$dicts.replace("'", ""))
const { ${dictsNoSymbol} } = proxy.useDict(${dicts}) const { ${dictsNoSymbol} } = proxy.useDict(${dicts});
#end #end
const ${businessName}List = ref([]) const ${businessName}List = ref([]);
#if($table.sub) #if($table.sub)
const ${subclassName}List = ref([]) const ${subclassName}List = ref([]);
#end #end
const open = ref(false) const open = ref(false);
const loading = ref(true) const loading = ref(true);
const showSearch = ref(true) const showSearch = ref(true);
const ids = ref([]) const ids = ref([]);
#if($table.sub) #if($table.sub)
const checked${subClassName} = ref([]) const checked${subClassName} = ref([]);
#end #end
const single = ref(true) const single = ref(true);
const multiple = ref(true) const multiple = ref(true);
const total = ref(0) const total = ref(0);
const title = ref("") const title = ref("");
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
const daterange${AttrName} = ref([]) const daterange${AttrName} = ref([]);
#end #end
#end #end
@@ -399,39 +399,39 @@ const data = reactive({
#end #end
#end #end
} }
}) });
const { queryParams, form, rules } = toRefs(data) const { queryParams, form, rules } = toRefs(data);
/** 查询${functionName}列表 */ /** 查询${functionName}列表 */
function getList() { function getList() {
loading.value = true loading.value = true;
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
queryParams.value.params = {} queryParams.value.params = {};
#break #break
#end #end
#end #end
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
if (null != daterange${AttrName}.value && '' != daterange${AttrName}.value) { if (null != daterange${AttrName} && '' != daterange${AttrName}) {
queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0] queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0];
queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1] queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1];
} }
#end #end
#end #end
list${BusinessName}(queryParams.value).then(response => { list${BusinessName}(queryParams.value).then(response => {
${businessName}List.value = response.rows ${businessName}List.value = response.rows;
total.value = response.total total.value = response.total;
loading.value = false loading.value = false;
}) });
} }
// 取消按钮 // 取消按钮
function cancel() { function cancel() {
open.value = false open.value = false;
reset() reset();
} }
// 表单重置 // 表单重置
@@ -444,17 +444,17 @@ function reset() {
$column.javaField: null#if($foreach.count != $columns.size()),#end $column.javaField: null#if($foreach.count != $columns.size()),#end
#end #end
#end #end
} };
#if($table.sub) #if($table.sub)
${subclassName}List.value = [] ${subclassName}List.value = [];
#end #end
proxy.resetForm("${businessName}Ref") proxy.resetForm("${businessName}Ref");
} }
/** 搜索按钮操作 */ /** 搜索按钮操作 */
function handleQuery() { function handleQuery() {
queryParams.value.pageNum = 1 queryParams.value.pageNum = 1;
getList() getList();
} }
/** 重置按钮操作 */ /** 重置按钮操作 */
@@ -462,44 +462,44 @@ function resetQuery() {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN") #if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
daterange${AttrName}.value = [] daterange${AttrName}.value = [];
#end #end
#end #end
proxy.resetForm("queryRef") proxy.resetForm("queryRef");
handleQuery() handleQuery();
} }
// 多选框选中数据 // 多选框选中数据
function handleSelectionChange(selection) { function handleSelectionChange(selection) {
ids.value = selection.map(item => item.${pkColumn.javaField}) ids.value = selection.map(item => item.${pkColumn.javaField});
single.value = selection.length != 1 single.value = selection.length != 1;
multiple.value = !selection.length multiple.value = !selection.length;
} }
/** 新增按钮操作 */ /** 新增按钮操作 */
function handleAdd() { function handleAdd() {
reset() reset();
open.value = true open.value = true;
title.value = "添加${functionName}" title.value = "添加${functionName}";
} }
/** 修改按钮操作 */ /** 修改按钮操作 */
function handleUpdate(row) { function handleUpdate(row) {
reset() reset();
const _${pkColumn.javaField} = row.${pkColumn.javaField} || ids.value const _${pkColumn.javaField} = row.${pkColumn.javaField} || ids.value
get${BusinessName}(_${pkColumn.javaField}).then(response => { get${BusinessName}(_${pkColumn.javaField}).then(response => {
form.value = response.data form.value = response.data;
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "checkbox") #if($column.htmlType == "checkbox")
form.value.$column.javaField = form.value.${column.javaField}.split(",") form.value.$column.javaField = form.value.${column.javaField}.split(",");
#end #end
#end #end
#if($table.sub) #if($table.sub)
${subclassName}List.value = response.data.${subclassName}List ${subclassName}List.value = response.data.${subclassName}List;
#end #end
open.value = true open.value = true;
title.value = "修改${functionName}" title.value = "修改${functionName}";
}) });
} }
/** 提交按钮 */ /** 提交按钮 */
@@ -508,68 +508,68 @@ function submitForm() {
if (valid) { if (valid) {
#foreach ($column in $columns) #foreach ($column in $columns)
#if($column.htmlType == "checkbox") #if($column.htmlType == "checkbox")
form.value.$column.javaField = form.value.${column.javaField}.join(",") form.value.$column.javaField = form.value.${column.javaField}.join(",");
#end #end
#end #end
#if($table.sub) #if($table.sub)
form.value.${subclassName}List = ${subclassName}List.value form.value.${subclassName}List = ${subclassName}List.value;
#end #end
if (form.value.${pkColumn.javaField} != null) { if (form.value.${pkColumn.javaField} != null) {
update${BusinessName}(form.value).then(response => { update${BusinessName}(form.value).then(response => {
proxy.#[[$modal]]#.msgSuccess("修改成功") proxy.#[[$modal]]#.msgSuccess("修改成功");
open.value = false open.value = false;
getList() getList();
}) });
} else { } else {
add${BusinessName}(form.value).then(response => { add${BusinessName}(form.value).then(response => {
proxy.#[[$modal]]#.msgSuccess("新增成功") proxy.#[[$modal]]#.msgSuccess("新增成功");
open.value = false open.value = false;
getList() getList();
}) });
} }
} }
}) });
} }
/** 删除按钮操作 */ /** 删除按钮操作 */
function handleDelete(row) { function handleDelete(row) {
const _${pkColumn.javaField}s = row.${pkColumn.javaField} || ids.value const _${pkColumn.javaField}s = row.${pkColumn.javaField} || ids.value;
proxy.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + _${pkColumn.javaField}s + '"的数据项?').then(function() { proxy.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + _${pkColumn.javaField}s + '"的数据项?').then(function() {
return del${BusinessName}(_${pkColumn.javaField}s) return del${BusinessName}(_${pkColumn.javaField}s);
}).then(() => { }).then(() => {
getList() getList();
proxy.#[[$modal]]#.msgSuccess("删除成功") proxy.#[[$modal]]#.msgSuccess("删除成功");
}).catch(() => {}) }).catch(() => {});
} }
#if($table.sub) #if($table.sub)
/** ${subTable.functionName}序号 */ /** ${subTable.functionName}序号 */
function row${subClassName}Index({ row, rowIndex }) { function row${subClassName}Index({ row, rowIndex }) {
row.index = rowIndex + 1 row.index = rowIndex + 1;
} }
/** ${subTable.functionName}添加按钮操作 */ /** ${subTable.functionName}添加按钮操作 */
function handleAdd${subClassName}() { function handleAdd${subClassName}() {
let obj = {} let obj = {};
#foreach($column in $subTable.columns) #foreach($column in $subTable.columns)
#if($column.pk || $column.javaField == ${subTableFkclassName}) #if($column.pk || $column.javaField == ${subTableFkclassName})
#elseif($column.list && "" != $javaField) #elseif($column.list && "" != $javaField)
obj.$column.javaField = "" obj.$column.javaField = "";
#end #end
#end #end
${subclassName}List.value.push(obj) ${subclassName}List.value.push(obj);
} }
/** ${subTable.functionName}删除按钮操作 */ /** ${subTable.functionName}删除按钮操作 */
function handleDelete${subClassName}() { function handleDelete${subClassName}() {
if (checked${subClassName}.value.length == 0) { if (checked${subClassName}.value.length == 0) {
proxy.#[[$modal]]#.msgError("请先选择要删除的${subTable.functionName}数据") proxy.#[[$modal]]#.msgError("请先选择要删除的${subTable.functionName}数据");
} else { } else {
const ${subclassName}s = ${subclassName}List.value const ${subclassName}s = ${subclassName}List.value;
const checked${subClassName}s = checked${subClassName}.value const checked${subClassName}s = checked${subClassName}.value;
${subclassName}List.value = ${subclassName}s.filter(function(item) { ${subclassName}List.value = ${subclassName}s.filter(function(item) {
return checked${subClassName}s.indexOf(item.index) == -1 return checked${subClassName}s.indexOf(item.index) == -1
}) });
} }
} }
@@ -586,5 +586,5 @@ function handleExport() {
}, `${businessName}_#[[${new Date().getTime()}]]#.xlsx`) }, `${businessName}_#[[${new Date().getTime()}]]#.xlsx`)
} }
getList() getList();
</script> </script>

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-modules</artifactId> <artifactId>ruoyi-modules</artifactId>
<version>3.6.7</version> <version>3.6.5</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -178,7 +178,7 @@ public class SysJobController extends BaseController
@RequiresPermissions("monitor:job:remove") @RequiresPermissions("monitor:job:remove")
@Log(title = "定时任务", businessType = BusinessType.DELETE) @Log(title = "定时任务", businessType = BusinessType.DELETE)
@DeleteMapping("/{jobIds}") @DeleteMapping("/{jobIds}")
public AjaxResult remove(@PathVariable Long[] jobIds) throws SchedulerException public AjaxResult remove(@PathVariable Long[] jobIds) throws SchedulerException, TaskException
{ {
jobService.deleteJobByIds(jobIds); jobService.deleteJobByIds(jobIds);
return success(); return success();

View File

@@ -3,6 +3,7 @@ package com.ruoyi.job.util;
import java.util.Date; import java.util.Date;
import org.quartz.Job; import org.quartz.Job;
import org.quartz.JobExecutionContext; import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.ruoyi.common.core.constant.ScheduleConstants; import com.ruoyi.common.core.constant.ScheduleConstants;
@@ -29,7 +30,7 @@ public abstract class AbstractQuartzJob implements Job
private static ThreadLocal<Date> threadLocal = new ThreadLocal<>(); private static ThreadLocal<Date> threadLocal = new ThreadLocal<>();
@Override @Override
public void execute(JobExecutionContext context) public void execute(JobExecutionContext context) throws JobExecutionException
{ {
SysJob sysJob = new SysJob(); SysJob sysJob = new SysJob();
BeanUtils.copyBeanProp(sysJob, context.getMergedJobDataMap().get(ScheduleConstants.TASK_PROPERTIES)); BeanUtils.copyBeanProp(sysJob, context.getMergedJobDataMap().get(ScheduleConstants.TASK_PROPERTIES));

Some files were not shown because too many files have changed in this diff Show More