3 Incheckningar a168affa4c ... 62998953b8

Upphovsman SHA1 Meddelande Datum
  wuwenyi 62998953b8 Merge branch 'feature/approve-by-self' 6 dagar sedan
  wuwenyi 98ec7e5318 refactor: nginx从前端剥离,单独部署 6 dagar sedan
  wuwenyi 51185a68b0 feat: 支持流程审批角色分配给自己 1 vecka sedan

+ 0 - 11
docker-compose.yml

@@ -8,17 +8,6 @@ services:
     networks:
       - qqflow-network
 
-  nginx:
-    build: ./gateway
-    container_name: qqflow-gateway-test
-    restart: always
-    ports:
-      - "3000:80"
-    networks:
-      - qqflow-network
-    depends_on:
-      - frontend
-
 networks:
   qqflow-network:
     external: true

+ 0 - 6
gateway/Dockerfile

@@ -1,6 +0,0 @@
-FROM nginx:1.27-alpine
-COPY nginx.conf.template /etc/nginx/conf.d/default.conf.template
-COPY docker-entrypoint.sh /
-RUN chmod +x /docker-entrypoint.sh
-ENTRYPOINT ["/docker-entrypoint.sh"]
-CMD ["nginx", "-g", "daemon off;"]

+ 0 - 11
gateway/docker-entrypoint.sh

@@ -1,11 +0,0 @@
-#!/bin/sh
-set -e
-
-# 默认值:测试环境用 docker-compose 内的 service name
-BACKEND_HOST=${BACKEND_HOST:-backend}
-
-echo "[nginx] BACKEND_HOST=${BACKEND_HOST}"
-
-sed "s|\${BACKEND_HOST}|${BACKEND_HOST}|g" /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf
-
-exec "$@"

+ 0 - 44
gateway/nginx.conf.template

@@ -1,44 +0,0 @@
-server {
-    listen       80;
-    server_name  localhost;
-
-    client_max_body_size 50M;
-
-    # 后端 API 代理
-    location /api/ {
-        proxy_pass http://${BACKEND_HOST}:8080/;
-        proxy_set_header Host $host;
-        proxy_set_header X-Real-IP $remote_addr;
-        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
-        proxy_set_header X-Forwarded-Proto $scheme;
-    }
-
-    # 文件上传/下载代理
-    location /uploads/ {
-        proxy_pass http://${BACKEND_HOST}:8080/uploads/;
-        proxy_set_header Host $host;
-        proxy_set_header X-Real-IP $remote_addr;
-        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
-        proxy_set_header X-Forwarded-Proto $scheme;
-    }
-
-    # 域名验证文件(WW_verify_xxx.txt / MP_verify_xxx.txt 等),转发到后端 static 目录
-    location ~ "^/([A-Z]{2,}_verify_.*\.txt)$" {
-        proxy_pass http://${BACKEND_HOST}:8080/$1;
-        proxy_set_header Host $host;
-        proxy_set_header X-Real-IP $remote_addr;
-        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
-        proxy_set_header X-Forwarded-Proto $scheme;
-    }
-
-    # 前端静态资源 + SPA fallback
-    location / {
-        proxy_pass http://frontend:80;
-        proxy_set_header Host $host;
-        proxy_set_header X-Real-IP $remote_addr;
-        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
-        proxy_set_header X-Forwarded-Proto $scheme;
-        proxy_intercept_errors on;
-        error_page 404 = /index.html;
-    }
-}

+ 13 - 2
src/views/flow/designer/DesignerPropertyPanel.vue

@@ -9,12 +9,23 @@
         <el-input v-model="nodeName" @blur="updateNodeName" />
       </el-form-item>
       <template v-if="selectedNode.type === 'approval-node'">
-        <el-form-item label="审批员工">
+        <el-form-item label="审批对象类型">
+          <el-select
+            v-model="nodeProps.assigneeType"
+            placeholder="请选择审批对象类型"
+            style="width: 100%"
+            @change="nodeProps.assigneeValue = ''"
+          >
+            <el-option label="审批角色" value="ROLE" />
+            <el-option label="发起人自己" value="SELF" />
+          </el-select>
+        </el-form-item>
+        <el-form-item v-if="nodeProps.assigneeType === 'ROLE'" label="审批角色">
           <el-select
             v-model="nodeProps.assigneeValue"
             filterable
             clearable
-            placeholder="请选择审批角色中的成员"
+            placeholder="请选择审批角色"
             style="width: 100%"
           >
             <el-option

+ 16 - 7
src/views/flow/designer/useFlowDesigner.ts

@@ -41,6 +41,7 @@ export function useFlowDesigner(lfContainer: Ref<HTMLDivElement | undefined>) {
     approveMode: 'or',
     timeoutHours: undefined as number | undefined,
     timeoutAction: 'remind',
+    approveTimeField: '',
     ccUsers: '',
   })
 
@@ -138,7 +139,7 @@ export function useFlowDesigner(lfContainer: Ref<HTMLDivElement | undefined>) {
       // 只保存当前节点类型相关的属性,避免不同类型节点属性互相污染
       const props: Record<string, any> = JSON.parse(JSON.stringify(defaultProps))
       if (type === 'approval-node') {
-        props.assigneeType = 'ROLE'
+        props.assigneeType = nodeProps.assigneeType ?? 'ROLE'
         props.assigneeValue = nodeProps.assigneeValue ?? ''
         props.approveMode = nodeProps.approveMode ?? 'or'
         props.timeoutHours = nodeProps.timeoutHours
@@ -158,14 +159,21 @@ export function useFlowDesigner(lfContainer: Ref<HTMLDivElement | undefined>) {
     Object.assign(nodeProps, getDefaultProps(data.type))
     // 兼容旧格式:approver + approveType -> 新格式
     if (data.type === 'approval-node') {
-      const assigneeType = 'ROLE'
+      const supportedTypes = ['ROLE', 'SELF']
+      let assigneeType = cloned.assigneeType ?? 'ROLE'
       let assigneeValue = cloned.assigneeValue ?? ''
       const approveMode = cloned.approveMode ?? cloned.approveType ?? 'or'
-      if (!cloned.assigneeValue && cloned.approver) {
+      if (!cloned.assigneeType && !cloned.assigneeValue && cloned.approver) {
+        assigneeType = 'ROLE'
         assigneeValue = cloned.approver
       }
-      // 旧数据中的 USER/SELF/LEADER 不再支持,统一清空让用户重新选择员工角色
-      if (cloned.assigneeType && cloned.assigneeType !== 'ROLE') {
+      // 当前设计器只支持 ROLE / SELF,其它旧类型降级为 ROLE 并清空值
+      if (!supportedTypes.includes(assigneeType)) {
+        assigneeType = 'ROLE'
+        assigneeValue = ''
+      }
+      // SELF 不需要审批角色值
+      if (assigneeType === 'SELF') {
         assigneeValue = ''
       }
       nodeProps.assigneeType = assigneeType
@@ -591,12 +599,13 @@ export function useFlowDesigner(lfContainer: Ref<HTMLDivElement | undefined>) {
     if (startNodes.length === 0) return '流程图缺少开始节点'
     if (endNodes.length === 0) return '流程图缺少结束节点'
     if (startNodes.length > 1) return '流程图只能有一个开始节点'
-    // 检查审批节点是否选择了审批角色
+    // 检查审批节点是否配置了审批对象
     for (const node of nodes) {
       if (node.type === 'approval-node' || node.type === 'approval') {
         const props = node.properties || {}
+        const assigneeType = props.assigneeType ?? 'ROLE'
         const assigneeValue = props.assigneeValue || props.approver
-        if (!assigneeValue) {
+        if (assigneeType === 'ROLE' && !assigneeValue) {
           return `审批节点 "${node.text || node.name}" 未选择审批角色`
         }
       }