LT32820A 2 місяців тому
батько
коміт
8777b961a4

+ 44 - 22
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/AppmanageServiceImpl.java

@@ -1,10 +1,13 @@
 package org.jeecg.modules.system.service.impl;
 
 import cn.hutool.system.UserInfo;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import org.apache.shiro.SecurityUtils;
+import org.jeecg.common.constant.CommonConstant;
 import org.jeecg.common.system.vo.LoginUser;
 import org.jeecg.common.util.RedisUtil;
+import org.jeecg.modules.base.service.BaseCommonService;
 import org.jeecg.modules.system.controller.SysUserController;
 import org.jeecg.modules.system.entity.*;
 import org.jeecg.modules.system.entity.AppmanageEntity.*;
@@ -29,6 +32,8 @@ import java.util.stream.Collectors;
 @Service
 public class AppmanageServiceImpl implements AppmanageService {
 
+    @Autowired
+    private BaseCommonService baseCommonService;
 
     // 操作用户与角色关系的(授予角色,撤销角色)
     @Autowired
@@ -145,8 +150,10 @@ public class AppmanageServiceImpl implements AppmanageService {
         SysPermission sysPermission = new SysPermission();
         // 设置菜单名称即为应用名称
         sysPermission.setName(appBaseInfo.getName());
-        // 设置菜单权限编码
-        sysPermission.setPerms("sys:appmanage:enter:"+sysPermission.getName());
+        // 设置菜单所属应用
+        sysPermission.setAppId(appid);
+//        // 设置菜单权限编码
+//        sysPermission.setPerms("sys:appmanage:enter:"+sysPermission.getName());
         // 设置菜单路径
         sysPermission.setUrl(appBaseInfo.getMenuInfo());
         // 设置组件(即 菜单路径去掉第一个 "/")
@@ -183,46 +190,59 @@ public class AppmanageServiceImpl implements AppmanageService {
     }
 
     /**
-     * 删除应用信息
+     * 删除应用信息 - 将会删除属于该应用的角色信息、菜单信息
      * @param ids 应用id集合
      * @return
      */
+    @Transactional
     @Override
     public Boolean deleteAppInfo(String[] ids) {
         // 需先判断用户是否拥有所删除的应用信息的权限(平台管理员-应用管理员)
         // 获取当前登录用户信息
         LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
-        QueryWrapper<AppBaseInfo> baseInfoPOQueryWrapper = new QueryWrapper<>();
+
         // 查询当前应用的应用管理员信息
         if (ids.length == 1){  // 删除单条信息时
+            QueryWrapper<AppBaseInfo> baseInfoPOQueryWrapper = new QueryWrapper<>();
             baseInfoPOQueryWrapper.select("admin").in("id", ids[0]);
             AppBaseInfo appBaseInfo = baseInfoMapper.selectOne(baseInfoPOQueryWrapper);
             if (!appBaseInfo.getAdmin().equals(loginUser.getId())) return false;
         }else {  //  批量删除应用信息时,如果有一个应用不是当前登录用户所创建,则返回false
             for (String id : ids) {
+                // 不能删除基础平台的应用信息
+                if (id.equals("0")) return false;
                 AppBaseInfo appBaseInfo = baseInfoMapper.selectById(id);
                 if (!appBaseInfo.getAdmin().equals(loginUser.getId())) return false;
-            }
-        }
-        for (String id : ids) {
-            // 不能删除基础平台的应用信息
-            if (id.equals("0")) return false;
-
-            // 删除所属该应用的基础信息、环境信息、文档信息、用户信息
-            baseInfoMapper.deleteById(id);
-            envInfoMapper.delete(new QueryWrapper<AppEnvInfo>().eq("appid", id));
-            docInfoMapper.delete(new QueryWrapper<AppDocInfo>().eq("appid", id));
-            userInfoMapper.delete(new QueryWrapper<AppUserInfo>().eq("appid", id));
 
-            // 删除该应用下所创建的菜单
-//            List<SysPermission> sysPermissions = sysPermissionService(loginUser.getUsername());
-//            String permissionsid = sysPermissions.stream().filter(permission -> permission.getAppId().equals(id)).findFirst().get().getId();
-//            sysPermissionService.deletePermission(permissionsid);
-
-            // 删除该应用下所创建的角色信息
-//            sysRoleService.listRoleIdsByAppId()
+                // 删除所属该应用的基础信息、环境信息、文档信息、用户信息
+                baseInfoMapper.deleteById(id);
+                envInfoMapper.delete(new QueryWrapper<AppEnvInfo>().eq("appid", id));
+                docInfoMapper.delete(new QueryWrapper<AppDocInfo>().eq("appid", id));
+                // 简易注册下的应用信息不具备用户、菜单、权限等信息,所有不需要删除
+                if (appBaseInfo.getAddType().equals("easy")) return true ;
+                userInfoMapper.delete(new QueryWrapper<AppUserInfo>().eq("appid", id));
+
+                // 删除该应用下所创建的菜单
+                // 查询该应用的一级菜单
+                LambdaQueryWrapper<SysPermission> query = new LambdaQueryWrapper<SysPermission>();
+                query.eq(SysPermission::getMenuType,CommonConstant.MENU_TYPE_0);
+                query.eq(SysPermission::getDelFlag, CommonConstant.DEL_FLAG_0);
+                query.eq(SysPermission::getAppId, id);
+                List<SysPermission> list = sysPermissionService.list(query);
+                for (SysPermission sysPermission : list){
+                    sysPermissionService.deletePermission(sysPermission.getId());
+                }
 
+                // 删除该应用下所创建的角色信息
+                String[] Approleids = sysRoleService.listRoleIdsByAppId(id);
+                if (Approleids!=null){
+                    boolean tag = sysRoleService.deleteBatchRole(Approleids);
+                    if (!tag) return false;
+                }
+            }
         }
+        // 记录日志
+        baseCommonService.addLog("删除应用信息:id"+Arrays.toString(ids), CommonConstant.LOG_TYPE_2, 3 );
         return true;
     }
 
@@ -657,4 +677,6 @@ public class AppmanageServiceImpl implements AppmanageService {
         }
         return roleNameInfo;
     }
+
+
 }

+ 6 - 1
jeecgboot-vue3/src/views/appmanage/AppBaseInfo.api.ts

@@ -30,8 +30,13 @@ enum Api {
     getAppuserids = '/sys/applicationInfo/getAppuserids',
     isInfoUser = '/sys/applicationInfo/isInfoUser',
     isAppAdminOrDevOrOpe = '/sys/applicationInfo/isAppAdminOrDevOrOpe',
-    isAppAdmin = '/sys/applicationInfo/isAppAdmin'
+    isAppAdmin = '/sys/applicationInfo/isAppAdmin',
+    checkMenuInfoisExist = '/sys/permission/checkPermDuplication'
 }
+export const checkMenuInfoisExist=(params)=>{
+    return defHttp.get({url: Api.checkMenuInfoisExist+"?url="+params+"&alwaysShow="+false},  { errorMessageMode: false, successMessageMode: false })
+}
+
 export const isAppAdmin=()=>{
   return defHttp.get({url: Api.isAppAdmin})
 }

+ 10 - 7
jeecgboot-vue3/src/views/appmanage/AppInfoList.vue

@@ -65,7 +65,8 @@
         <div style="height: 50vh" v-if="isLoading"></div>
       </a-spin>
         <div v-show="!isLoading">
-          <FormStepPage v-if="modalVisible" ref="addForm" @closeModal="closeModal" :addType="addType" :addFormDraftData="addFormDraftData"/>
+          <FormStepPage v-if="modalVisible" ref="addForm" @closeModal="closeModal" :addType="addType"
+                        :addFormDraftData="addFormDraftData" test="123"/>
         </div>
     </a-modal>
 
@@ -230,7 +231,7 @@ import BaseInfoFrom from '@/views/appmanage/addForm/Step1.vue'
 import EnvInfoFrom from '@/views/appmanage/addForm/Step2.vue'
 import DocInfoFrom from '@/views/appmanage/addForm/Step3.vue'
 import UserInfoFrom from '@/views/appmanage/addForm/Step4.vue'
-import { message } from 'ant-design-vue';
+import { message, Modal } from 'ant-design-vue';
 import Description from '@/components/Description/src/Description.vue'
 import { useDescription } from '/@/components/Description';
 import {menuInfoisshow} from "@/views/appmanage/addForm/data";
@@ -258,14 +259,13 @@ const addFormDraftData = ref({
   base: {},
   env:{},
   doc:{},
-  user:{},
+  userInfo:{},
   current: 0
 })  // 添加表单草稿数据,存储添加至一半时关闭表单且已填入的数据
+const draftUserInfo = ref()
 
 type Key = string | number;
 
-
-
 interface FormState {
   appname: string;
   apptype: string;
@@ -322,6 +322,7 @@ export default defineComponent({
 
   async created() {
     console.log("创建完成啦啦啦")
+    // 清除草稿数据缓存
     columns.value = listColumns2
     const isInfoDeptUser = await isInfoUser()
     isInfoDeptUserTag.value = isInfoDeptUser
@@ -361,6 +362,7 @@ export default defineComponent({
         case 'isAdd':
           console.log("主页面关闭添加表单事件")
           addFormDraftData.value = value.data
+          console.log("关闭注册对话框时存储的草稿数据")
           console.dir(addFormDraftData)
           modalVisible.value = false;
           break;
@@ -590,11 +592,11 @@ export default defineComponent({
     handleAdd(isaddType) {
       isLoading.value = true
       let time = isaddType === 'full'? 1500:1000
-      console.log("time:"+time)
       addType.value = isaddType
+      console.log("点击注册时查看草稿数据")
+      console.dir(addFormDraftData)
       menuInfoisshow.value = isaddType === 'full';
       setTimeout(function (){
-        console.log("step1变成false了")
         isLoading.value = false
       },time)
       modalVisible.value = true;
@@ -602,6 +604,7 @@ export default defineComponent({
   },
 
   setup() {
+
     const [descriPtionregister] = useDescription({
       schema: Appdescschema,
     });

+ 12 - 9
jeecgboot-vue3/src/views/appmanage/addForm/Step2.vue

@@ -337,19 +337,22 @@
           delids.value = []
         })
       },
-    },
 
-    emits: ['next', 'prev', 'closeModal'],
-    setup(_, { emit }) {
-      async function customResetFunc() {
+      async customResetFunc() {
         console.log("上一页")
-        emit('prev');
+        this.assmblyData()
+        this.$emit('prev',envData);
       }
-
-      return {
-        customResetFunc
-      };
     },
+    //
+    // emits: ['next', 'prev', 'closeModal'],
+    // setup(_, { emit }) {
+    //
+    //
+    //   return {
+    //
+    //   };
+    // },
   });
 </script>
 <style lang="less" scoped>

+ 67 - 84
jeecgboot-vue3/src/views/appmanage/addForm/Step4.vue

@@ -38,23 +38,41 @@
       <div class="appUserOperateitem">
         <a-button @click="clearConditionAndData">重 置</a-button>
       </div>
-      <div class="appUserOperateitem" style="margin-left: 15%">
+      <div>
+      <!-- 作为编辑页面时显示   -->
+      <a-button type="primary"
+                :disabled="adduserCount===0"
+                @click="removeUserInfo('edit')"
+                v-if="!tag"  v-show="!uncheckTag">移 除</a-button>
+      </div>
+      <!-- 作为编辑页面时显示  -->
+      <div class="appUserOperateitem" style="margin-left: 10%">
+        <span v-if="!tag" style="padding-right: 5%; white-space: nowrap"> <b>新增用户:{{(newlyUserData as any).length}}</b> </span>
         <a-button type="primary" :disabled="uncheckTag" @click="handleOpen" v-if="!uncheckTag&&!tag">添加用户</a-button>
         <AppUserSelectByDepModal ref="addNewUser" :rowKey="rowKey" v-if="!uncheckTag&&!tag"
                                  :appid="appid" :appuserids="appUserids" @register="regModal"
                                  @getSelectResult="setValue" v-bind="getBindValue"/>
-      </div>
+        <a-popconfirm
+            title="你确定要移除全部信息吗?"
+            ok-text="是"
+            cancel-text="否"
+            @confirm="removeAllUserInfo('editForm_newlyUserData')"
+            @cancel="cancel">
+          <a-button v-if="!tag" style="padding-right: 10%" v-show="(newlyUserData as any).length>0">全部移除</a-button>
+        </a-popconfirm>
 
-      <div class="appUserOperateitem">
         <!-- 作为添加页面时显示  -->
-        <a-button type="primary" :disabled="adduserCount===0"
-                  @click="removeUserInfo('add')"
-                  v-if="tag" >添 加</a-button>
-        <!-- 作为编辑页面时显示   -->
-        <a-button type="primary"
-                  :disabled="adduserCount===0"
-                  @click="removeUserInfo('edit')"
-                  v-if="!tag"  v-show="!uncheckTag">移 除</a-button>
+        <span v-if="tag" style="padding-right: 5%; white-space: nowrap"><b>已添加应用用户:{{(addForm_newlyUserData as any).length}}</b></span>
+        <a-button  v-if="tag" type="primary" :disabled="adduserCount===0" @click="removeUserInfo('add')">添 加</a-button>
+        <a-popconfirm
+            title="你确定要移除全部信息吗?"
+            ok-text="是"
+            cancel-text="否"
+            @confirm="removeAllUserInfo('addForm_newlyUserData')"
+            @cancel="cancel">
+        <a-button v-if="tag" style="padding-right: 10%" v-show="(addForm_newlyUserData as any).length>0">全部移除</a-button>
+        </a-popconfirm>
+
       </div>
     </div>
 
@@ -69,13 +87,8 @@
           <a-table :row-selection="rowSelection" :columns="columns"
                    :data-source="data" v-show="!uncheckTag||tag" size="small"
                     class="userTableClass" :pagination="pagination" @change="handleTableChange">
-            <template #bodyCell="{ column, record }">
-              <template v-if="column.dataIndex === 'editform_action'">
-                <a-button type="link" @click="openPermissionModal">授 权</a-button>
-                <a-modal :open="permissionTag">
-                  <AppPermissionTree  app-list=""/>
-                </a-modal>
-              </template>
+            <template #title>
+              <b>平台用户</b>
             </template>
           </a-table>
         </div>
@@ -86,11 +99,11 @@
         <div class="table_right" v-if="tag">
           <!-- 新增用户列表 -->
           <div class="table_top">
-            <div style="margin-bottom: 5px">
-              <b>已添加应用用户:{{(addForm_newlyUserData as any).length}}</b>
-              <a-button style="margin-left: 40%" v-show="(addForm_newlyUserData as any).length>0">全部移除</a-button>
-            </div>
-            <a-table :columns="addForm_newlyUsercolumns" :data-source="addForm_newlyUserData" :scroll="{y: 500}" :pagination="false" size="small">
+            <a-table :columns="addForm_newlyUsercolumns" :data-source="addForm_newlyUserData" :scroll="{y: 500}"
+                     :pagination="false" size="small" class="rightuserTableClass">
+              <template #title>
+                <b>将要加入该应用的用户</b>
+              </template>
               <template #bodyCell="{ column, record }">
                 <template v-if="column.dataIndex === 'action'">
                   <a-button type="link" @click="recoverNewlyOneUserInfo(record.key, 'add')">移 出</a-button>
@@ -104,10 +117,6 @@
         <div class="table_right" v-if="!tag&&!uncheckTag">
           <!-- 新增用户列表 -->
           <div class="table_top">
-            <div style="margin-bottom: 5px">
-              <span> <b>新增用户:{{(newlyUserData as any).length}}</b> </span>
-              <a-button style="margin-left: 40%" v-show="(newlyUserData as any).length>0">全部移除</a-button>
-            </div>
             <a-table :columns="newlyUsercolumns" :data-source="newlyUserData"
                      :scroll="{y: 230}" :pagination="false" size="small"
                       class="rightuserTableClass">
@@ -128,7 +137,14 @@
                       class="rightuserTableClass">
               <template #title>
                 <b>移除用户:{{(removeUserData as any).length}}</b>
+                <a-popconfirm
+                    title="你确定要移除全部信息吗?"
+                    ok-text="是"
+                    cancel-text="否"
+                    @confirm="removeAllUserInfo('editForm_removeUserData')"
+                    @cancel="cancel">
                 <a-button style="margin-left: 40%" v-show="(removeUserData as any).length>0">全部移除</a-button>
+                </a-popconfirm>
               </template>
               <template #bodyCell="{ column, record }">
                 <template v-if="column.dataIndex === 'action'">
@@ -157,17 +173,9 @@
       <a-button v-if="tag" type="primary" @click="addCheck">
         提交审核
       </a-button>
-<!--      <a-popconfirm-->
-<!--        v-if="removeUserData.length>0"-->
-<!--        title="注意!移除用户将同时移除该用户在该应用下的所有权限,是否继续?"-->
-<!--        ok-text="是"-->
-<!--        cancel-text="否"-->
-<!--        @confirm=""-->
-<!--        @cancel="">-->
         <a-button v-if="!tag&&isEdit" type="primary" @click="save" :disabled="uncheckTag">
           保 存
         </a-button>
-<!--      </a-popconfirm>-->
     </div>
 
     <!-- 提交审核事件二次确认 -->
@@ -365,48 +373,6 @@ export default defineComponent({
       await this.queryAppUserMethod(1)
     },
 
-    // 作为添加表单时使用,根据表单一所选用户的角色,将用户加入新增用户列表及授予相应的角色
-    async step1Tostep4DataRelationDeal(step1FormData){
-      console.log("表单四拿到表单一数据")
-      console.dir(step1FormData)
-      let step1userData = []
-      // 将右列表用户数据添加至
-      if (step1FormData.admin!=undefined) step1userData.push(step1FormData.admin)
-      if (step1FormData.businessUser!=undefined) step1userData.push(step1FormData.businessUser)
-      if (step1FormData.developUser!=undefined) step1userData.push(step1FormData.developUser)
-      if (step1FormData.operationUser!=undefined) step1userData.push(step1FormData.operationUser)
-      if (step1FormData.requirementUser!=undefined) step1userData.push(step1FormData.requirementUser)
-      const params = {
-        userids: step1userData
-      }
-      await queryAppUser(params).then(res=>{
-        console.log("表单四查询表单一填写的用户数据")
-        console.dir(res)
-        // 根据表单一所选用户,初始化表单四添加用户列表数据
-        addForm_newlyUserData.value.length = 0
-        res.userinfos.forEach(item=>{
-          const itemObj = {
-            key: item.id,
-            name: item.realname,
-            username: item.username,
-            sex: item.sex,
-            depart: item.dept.deptName,
-            roles: ''
-          }
-          addForm_newlyUserData.value.push(itemObj)
-        })
-      })
-      selectedRowKeys.value = step1userData
-      userData.value = step1userData
-      addForm_newlyUserData.value.forEach( item =>{
-        if (item.key === step1FormData.admin) item.roles = '应用管理员'
-        if (item.key === step1FormData.businessUser) item.roles = '业务对接人'
-        if (item.key === step1FormData.developUser) item.roles = '开发负责人'
-        if (item.key === step1FormData.operationUser) item.roles = '运维负责人'
-        if (item.key === step1FormData.requirementUser) item.roles = '需求对接人'
-      })
-    },
-
     transformTreeData(data) {
       return data.map(item => {
         const transformedItem = {
@@ -422,19 +388,19 @@ export default defineComponent({
     },
 
     // 初始化表单样式,判断是添加表单还是编辑表单
-    async initUserInfo(value, step1Values){
+    async initUserInfo(value){
       // 获取部门信息
       console.log("先看看这个value吧")
+      console.dir(value)
       const deptInfo = await queryTreeList()
       treeData.value = this.transformTreeData(deptInfo);
       tag.value = this.formType === 'isAdd'
       if (tag.value){                             // 作为添加表单的初始化
         console.log("表单四:作为添加表单的初始化")
         // 由于分页限制了data的大小,故需自己去查询表单一所添加的用户的信息
-        await this.step1Tostep4DataRelationDeal(step1Values)
+        // if (step1Values!=undefined) await this.step1Tostep4DataRelationDeal(step1Values)
         // 将左用户信息栏角色列去除
         columns.value = userTableSchemas.filter(item => item.dataIndex !== 'roles');// 应用用户表列配置
-        console.dir(value)
         try {
           if (value.value!==undefined) addForm_newlyUserData.value = value
         }catch (e){
@@ -455,7 +421,18 @@ export default defineComponent({
       modalVisible.value=false
     },
 
-    // 移除用户信息
+    // 全部移除 新增(添加)用户信息
+    removeAllUserInfo(tag){
+      console.log("执行了全部移除:"+tag)
+      // 全部移除新增表单将要加入该应用的用户列表数据
+      if (tag==='addForm_newlyUserData') addForm_newlyUserData.value.length = 0
+      if (tag==='editForm_newlyUserData') newlyUserData.value.length = 0
+      if (tag==='editForm_removeUserData') removeUserData.value.length = 0
+      this.queryAppUserMethod(this.pagination.current)
+    },
+
+
+    // 移除右列表信息
     removeUserInfo(isType){
       console.log("移除用户信息执行了");
       console.dir(userData);
@@ -469,6 +446,7 @@ export default defineComponent({
           isType==='edit'? removeUserData.value.push(dataObject) : addForm_newlyUserData.value.push(dataObject)
         }
       })
+      this.clearConditionAndData()
       console.dir(addForm_newlyUsercolumns)
       selectedRowKeys.value = []
       this.adduserCount = 0
@@ -532,7 +510,7 @@ export default defineComponent({
       if (this.formType === 'isAdd'){  // 处于添加表单下的关闭事件,需收集表单已填数据进行存储
         console.log("表单四添加状态下关闭")
         const obj = {
-          data: addForm_newlyUserData,
+          data: addForm_newlyUserData.value,
           info: 'user',
           type: 'isAdd'
         }
@@ -591,6 +569,9 @@ export default defineComponent({
   },
 
   setup(props, { emit }) {
+    const cancel = (e: MouseEvent) => {
+      message.error('取消移除');
+    };
 
     watch(deptInfovalue, () => {
       realnameSearchvalue.value = ''
@@ -711,7 +692,8 @@ export default defineComponent({
       setValue,
       getBindValue,
       deptInfovalue,
-      searchValue
+      searchValue,
+      cancel
     };
   },
 });
@@ -752,6 +734,7 @@ export default defineComponent({
   align-items: center; /* 垂直居中对齐 */
   justify-content: center; /* 水平居中对齐 */
   margin-right: 10px; /* 为每个 .item 添加右边距 */
+  gap: 10px;
 }
 
 .item:last-child {
@@ -792,7 +775,7 @@ export default defineComponent({
 }
 
 .userTableClass{
-  border-right: 1px solid #d9d9d9;
+  border: 1px solid #d9d9d9;
 }
 
 .rightuserTableClass{

+ 55 - 0
jeecgboot-vue3/src/views/appmanage/addForm/data.tsx

@@ -1,9 +1,23 @@
 import { FormSchema } from '/@/components/Form';
 import {ref} from "vue";
+import {checkPermDuplication} from "@/views/system/menu/menu/menu.api";
+import {ComponentTypes} from "@/views/system/menu/menu/menu.data";
+import {checkMenuInfoisExist} from "@/views/appmanage/AppBaseInfo.api";
 
 
 export const menuInfoisshow = ref(false)
 
+
+export const checkMenuInfo = async (_rule, value, callback) => {
+  console.log("菜单value:" + value)
+  const res = await checkMenuInfoisExist(value)
+  if (res === '该值可用!') {
+    callback(); // 校验通过
+  } else {
+    callback(new Error(res)); // 校验失败
+  }
+};
+
 export const step1Schemas: FormSchema[] = [
   {
     field: 'name',
@@ -100,6 +114,11 @@ export const step1Schemas: FormSchema[] = [
     component: 'Input',
     label: '菜单信息',
     required: true,
+    ifShow: ({ values }) => !(values.component === ComponentTypes.IFrame && values.internalOrExternal),
+    rules:[{required: true, validator: checkMenuInfo, trigger: 'blur'}],
+    // dynamicRules: ({ model, schema, values }) => {
+    //   return checkPermDuplication(model, schema, values.menuType !== 2);
+    // },
     show: ()=>{
       return menuInfoisshow.value
     },
@@ -120,8 +139,38 @@ export const step1Schemas: FormSchema[] = [
     component: 'Input',
     show: false,
   },
+  {
+    field: 'alwaysShow',
+    label: '',
+    component: 'Switch',
+    defaultValue: false,
+    show: false
+  },
 ];
 
+
+const isValidIp = (_rule, value, callback) => {
+  if (!value) {
+    return callback(new Error('请输入 IP 地址'));
+  }
+  if (!isValidIpAddress(value)) {
+    return callback(new Error('请输入正确的 IP 地址格式'));
+  }
+  callback();
+};
+
+const isValidIpAddress = (ip) => {
+  const regex = /^(\d{1,3}\.){3}\d{1,3}$/;
+  const parts = ip.split('.');
+  if (parts.length !== 4) return false;
+  for (let part of parts) {
+    if (isNaN(part) || part < 0 || part > 255) {
+      return false;
+    }
+  }
+  return regex.test(ip);
+};
+
 export const step2Schemas: FormSchema[] = [
   {
     field: 'env',
@@ -156,6 +205,7 @@ export const step2Schemas: FormSchema[] = [
     field: 'leadingIp',
     component: 'Input',
     required: true,
+    rules:[{ required: true, validator: isValidIp, trigger: 'blur' }],
     label: '前端部署IP',
     colProps: {
       span: 8,
@@ -165,6 +215,7 @@ export const step2Schemas: FormSchema[] = [
     field: 'backendIp',
     component: 'Input',
     label: '后端部署IP',
+    rules:[{ required: true, validator: isValidIp, trigger: 'blur' }],
     colProps: {
       span: 8,
     },
@@ -266,6 +317,7 @@ export const step2_1Schemas: FormSchema[] = [
     component: 'Input',
     required: true,
     label: '前端部署IP',
+    rules:[{ required: true, validator: isValidIp, trigger: 'blur' }],
     colProps: {
       span: 8,
     },
@@ -274,6 +326,7 @@ export const step2_1Schemas: FormSchema[] = [
     field: 'backendIp',
     component: 'Input',
     label: '后端部署IP',
+    rules:[{ required: true, validator: isValidIp, trigger: 'blur' }],
     colProps: {
       span: 8,
     },
@@ -376,6 +429,7 @@ export const step2_2Schemas: FormSchema[] = [
     component: 'Input',
     required: true,
     label: '前端部署IP',
+    rules:[{ required: true, validator: isValidIp, trigger: 'blur' }],
     colProps: {
       span: 8,
     },
@@ -384,6 +438,7 @@ export const step2_2Schemas: FormSchema[] = [
     field: 'backendIp',
     component: 'Input',
     label: '后端部署IP',
+    rules:[{ required: true, validator: isValidIp, trigger: 'blur' }],
     colProps: {
       span: 8,
     },

+ 30 - 15
jeecgboot-vue3/src/views/appmanage/addForm/index.vue

@@ -9,21 +9,21 @@
     </div>
     <div class="mt-5">
       <Step1 ref="step1" @next="handleStep1Next" v-show="current === 0"  @closeModal="closeModal" formType="isAdd" :addType="addType"/>
-      <Step2 ref="step2" @prev="handleStepPrev" formType="isAdd" @next="handleStep2Next" v-show="current === 1" v-if="initSetp2" @closeModal="closeModal"/>
+      <Step2 ref="step2" @prev="handleStepPrev" formType="isAdd" @next="handleStep2Next" v-show="current === 1" @closeModal="closeModal"/>
       <Step3 ref="step3" v-show="current === 2" @prev="handleStepPrev" @next="handleStep3Next" @closeModal="closeModal" formType="isAdd"/>
       <Step4 ref="userManage" v-show="current === 3" formType="isAdd" @prev="handleStepPrev" @redo="handleRedo" @add="handAdd" @closeModal="closeModal"/>
     </div>
 </template>
 <script lang="ts">
-  import { defineComponent, ref, reactive, toRefs } from 'vue';
+import {defineComponent, ref, reactive, toRefs, toRaw} from 'vue';
   import Step1 from './Step1.vue';
   import Step2 from './Step2.vue';
   import Step3 from './Step3.vue';
   import Step4 from './Step4.vue';
   import { PageWrapper } from '/@/components/Page';
   import { Steps } from 'ant-design-vue';
-  import { saveOrUpdate } from  "../AppBaseInfo.api"
-  import {any, string} from "vue-types";
+  import {saveOrUpdate } from  "../AppBaseInfo.api"
+import {any, array, string} from "vue-types";
 
   const current = ref(0);
   const tag = ref(true)
@@ -56,7 +56,9 @@
           addType: string,
           current: number
         }>
-      }
+      },
+      test: any,
+      // draftUserInfo: any
     },
     components: {
       Step1,
@@ -69,8 +71,16 @@
     },
     mounted() {
       console.log("分步表单挂载完成事件:"+this.addType);
+      console.log(this.test)
       console.dir(this.addFormDraftData);
-      tag.value = this.addType === 'full'
+
+      tag.value = this.addType === 'full';
+      (appInfoData.appBaseInfoDTO as any) = this.addFormDraftData?.appBaseInfoDTO
+      appInfoData.appEnvInfoDTO = this.addFormDraftData?.appEnvInfoDTO
+      appInfoData.appDocInfoDTO = this.addFormDraftData?.appDocInfoDTO
+      appInfoData.userInfo = this.addFormDraftData?.userInfo
+      appInfoData.current = this.addFormDraftData?.current
+      appInfoData.addType = this.addType
       this.$nextTick(() => {
         if (this.$refs.step1) {
           (this.$refs.step1 as any).getData11(this.addFormDraftData?.appBaseInfoDTO);
@@ -85,6 +95,11 @@
           if (this.$refs.step3) {
             (this.$refs.step3 as any).initDocForm(this.addFormDraftData?.appDocInfoDTO);
           }
+          if (this.$refs.userManage) {
+            console.log("分步主页面调用表单四的初始化方法:");
+            console.dir(this.addFormDraftData?.userInfo);
+            (this.$refs.userManage as any).initUserInfo(this.addFormDraftData?.userInfo, this.addFormDraftData?.appBaseInfoDTO);
+          }
         });
       }else { // 简易添加
         current.value = 0
@@ -94,24 +109,21 @@
 
     methods:{
       handleStep3Next(step3Values: any) {
-        console.log("打开第四页")
         current.value++;
         state.initSetp4 = true;
         console.log(step3Values);
         appInfoData.appDocInfoDTO = step3Values;
       },
 
-      handleStep1Next(step1Values: any) {
+      async handleStep1Next(step1Values: any) {
+        // 检查菜单路径是否已存在
+        console.log("表单一点击下一步")
         current.value++;
         state.initSetp2 = true;
-        console.log(step1Values);
-        appInfoData.appBaseInfoDTO = step1Values;
+        appInfoData.appBaseInfoDTO = step1Values
         this.$nextTick(() => {
-          if (this.$refs.userManage) {
-            (this.$refs.userManage as any).initUserInfo(this.addFormDraftData?.userInfo, step1Values);
-          }
           if(this.$refs.step2){
-            (this.$refs.step2 as any).initEnvFrom(this.addFormDraftData?.appEnvInfoDTO)
+            (this.$refs.step2 as any).initEnvFrom(this.appInfoData.appEnvInfoDTO)
           }
         })
 
@@ -121,8 +133,11 @@
     emits: ['closeModal','submit'],
     setup(_, { emit }) {
 
-      function handleStepPrev() {
+      function handleStepPrev(step2Values: any) {
         current.value--;
+        console.log("表单二点击上一步")
+        console.dir(step2Values)
+        appInfoData.appEnvInfoDTO = step2Values;
       }
 
       function handleStep2Next(step2Values: any) {

+ 2 - 2
jeecgboot-vue3/src/views/appmanage/components/data.tsx

@@ -51,8 +51,8 @@ export const addForm_newlyuserTableSchemas = [
         width: 150
     },
     {
-      title: '角色',
-      dataIndex: 'roles',
+      title: '部门',
+      dataIndex: 'depart',
       width: 150
     },
     {