Parcourir la source

AppConfig.vue 中采用分步表单方式添加 AppConfig

reghao il y a 1 jour
Parent
commit
91770a48d6

+ 1 - 1
src/api/devops.js

@@ -266,7 +266,7 @@ export function getAppBindDomain(appId) {
 }
 
 export function addAppConfig(formData) {
-  return postForm(devopsApi.getAppConfigList, formData)
+  return post(devopsApi.getAppConfigList, formData)
 }
 
 export function copyAppConfig(formData) {

+ 154 - 130
src/views/devops/app/AppConfig.vue

@@ -39,10 +39,6 @@
         height="480"
         style="width: 100%"
       >
-        <el-table-column
-          prop="appName"
-          label="应用名"
-        />
         <el-table-column
           prop="appId"
           label="应用 ID"
@@ -52,8 +48,8 @@
           label="分支"
         />
         <el-table-column
-          prop="bindPorts"
-          label="监听端口"
+          prop="httpPort"
+          label="HTTP 端口"
         />
         <el-table-column
           prop="totalDeployNodes"
@@ -202,17 +198,14 @@
           <el-form-item label="应用 ID" style="width: 70%; padding-right: 2px">
             <el-input v-model="editForm.appId" style="width: 70%; padding-right: 2px" readonly />
           </el-form-item>
-          <el-form-item label="应用名" style="width: 70%; padding-right: 2px">
-            <el-input v-model="editForm.appName" style="width: 70%; padding-right: 2px" />
-          </el-form-item>
           <el-form-item label="应用仓库" style="width: 70%; padding-right: 2px">
             <el-input v-model="editForm.appRepo" style="width: 70%; padding-right: 2px" readonly />
           </el-form-item>
           <el-form-item label="仓库分支" style="width: 70%; padding-right: 2px">
             <el-input v-model="editForm.repoBranch" style="width: 70%; padding-right: 2px" />
           </el-form-item>
-          <el-form-item label="监听端口" style="width: 70%; padding-right: 2px">
-            <el-input v-model="editForm.bindPorts" style="width: 70%; padding-right: 2px" />
+          <el-form-item label="HTTP 端口" style="width: 70%; padding-right: 2px">
+            <el-input v-model="editForm.httpPort" style="width: 70%; padding-right: 2px" />
           </el-form-item>
           <el-form-item label="仓库认证">
             <el-select v-model="editForm.repoAuthConfig" placeholder="选择仓库认证">
@@ -264,20 +257,14 @@
           <el-form-item label="应用 ID" style="width: 70%; padding-right: 2px">
             <el-input v-model="appConfigDetail.appId" style="width: 70%; padding-right: 2px" readonly />
           </el-form-item>
-          <el-form-item label="应用名" style="width: 70%; padding-right: 2px">
-            <el-input v-model="appConfigDetail.appName" style="width: 70%; padding-right: 2px" readonly />
-          </el-form-item>
           <el-form-item label="应用仓库" style="width: 70%; padding-right: 2px">
             <el-input v-model="appConfigDetail.appRepo" style="width: 70%; padding-right: 2px" readonly />
           </el-form-item>
           <el-form-item label="仓库分支" style="width: 70%; padding-right: 2px">
             <el-input v-model="appConfigDetail.repoBranch" style="width: 70%; padding-right: 2px" readonly />
           </el-form-item>
-          <el-form-item label="应用路径" style="width: 70%; padding-right: 2px">
-            <el-input v-model="appConfigDetail.appRootPath" style="width: 70%; padding-right: 2px" readonly />
-          </el-form-item>
-          <el-form-item label="监听端口" style="width: 70%; padding-right: 2px">
-            <el-input v-model="appConfigDetail.bindPorts" style="width: 70%; padding-right: 2px" readonly />
+          <el-form-item label="HTTP 端口" style="width: 70%; padding-right: 2px">
+            <el-input v-model="appConfigDetail.httpPort" style="width: 70%; padding-right: 2px" readonly />
           </el-form-item>
           <el-form-item label="仓库认证">
             <el-input v-model="appConfigDetail.repoAuthConfig" style="width: 70%; padding-right: 2px" readonly />
@@ -301,82 +288,67 @@
       center
     >
       <template>
-        <el-form :model="addForm" label-width="80px">
-          <el-form-item label="应用类型">
-            <el-select v-model="addForm.appType" placeholder="选择类型">
-              <el-option
-                v-for="(item, index) in appTypeList"
-                :key="index"
-                :label="item.label"
-                :value="item.value"
-              />
-            </el-select>
-          </el-form-item>
-          <el-form-item label="所属环境">
-            <el-select v-model="addForm.env" placeholder="选择环境">
-              <el-option
-                v-for="(item, index) in envList"
-                :key="index"
-                :label="item.label"
-                :value="item.value"
-              />
-            </el-select>
-          </el-form-item>
-          <el-form-item label="应用 ID" style="width: 70%; padding-right: 2px">
-            <el-input v-model="addForm.appId" style="width: 70%; padding-right: 2px" />
-          </el-form-item>
-          <el-form-item label="应用名" style="width: 70%; padding-right: 2px">
-            <el-input v-model="addForm.appName" style="width: 70%; padding-right: 2px" />
-          </el-form-item>
-          <el-form-item label="应用仓库" style="width: 70%; padding-right: 2px">
-            <el-input v-model="addForm.appRepo" style="width: 70%; padding-right: 2px" />
-          </el-form-item>
-          <el-form-item label="仓库分支" style="width: 70%; padding-right: 2px">
-            <el-input v-model="addForm.repoBranch" style="width: 70%; padding-right: 2px" />
-          </el-form-item>
-          <el-form-item label="应用路径" style="width: 70%; padding-right: 2px">
-            <el-input v-model="addForm.appRootPath" style="width: 70%; padding-right: 2px" />
-          </el-form-item>
-          <el-form-item label="监听端口" style="width: 70%; padding-right: 2px">
-            <el-input v-model="addForm.bindPorts" style="width: 70%; padding-right: 2px" />
-          </el-form-item>
-          <el-form-item label="仓库认证">
-            <el-select v-model="addForm.repoAuthConfig" placeholder="选择仓库认证">
-              <el-option
-                v-for="(item, index) in repoAuthList"
-                :key="index"
-                :label="item.label"
-                :value="item.label"
-              />
-            </el-select>
-          </el-form-item>
-          <el-form-item label="编译工具">
-            <el-select v-model="addForm.compilerConfig" placeholder="选择编译工具">
-              <el-option
-                v-for="(item, index) in compilerList"
-                :key="index"
-                :label="item.label"
-                :value="item.label"
-              />
-            </el-select>
-          </el-form-item>
-          <el-form-item label="打包工具">
-            <el-select v-model="addForm.packerConfig" placeholder="选择打包工具">
-              <el-option
-                v-for="(item, index) in packerList"
-                :key="index"
-                :label="item.label"
-                :value="item.label"
-              />
-            </el-select>
-          </el-form-item>
-          <el-form-item label="Dockerfile" style="width: 70%; padding-right: 2px">
-            <el-input v-model="addForm.dockerfile" type="textarea" :rows="10" style="width: 70%; padding-right: 2px" />
-          </el-form-item>
-          <el-form-item>
-            <el-button type="primary" @click="onAdd">确定</el-button>
-          </el-form-item>
-        </el-form>
+        <div class="app-config-container">
+          <el-steps :active="active" finish-status="success" simple style="margin-bottom: 20px">
+            <el-step title="基础信息"></el-step>
+            <el-step title="构建环境"></el-step>
+            <el-step title="详细配置"></el-step>
+          </el-steps>
+
+          <el-form :model="appForm" :rules="appFormRules" ref="appFormRef" label-width="120px">
+            <div v-show="active === 0">
+              <el-form-item label="应用仓库" prop="appRepo">
+                <el-input v-model="appForm.appRepo" placeholder="e.g. user-service"></el-input>
+              </el-form-item>
+              <el-form-item label="仓库分支" prop="repoBranch">
+                <el-input v-model="appForm.repoBranch"></el-input>
+              </el-form-item>
+              <el-form-item label="仓库认证" prop="repoAuthConfigId">
+                <el-select v-model="appForm.repoAuthConfigId" placeholder="选择认证">
+                  <el-option v-for="item in repoAuthList" :key="item.value" :label="item.label" :value="item.value"></el-option>
+                </el-select>
+              </el-form-item>
+            </div>
+
+            <div v-show="active === 1">
+              <el-form-item label="应用类型" prop="appType">
+                <el-select v-model="appForm.appType" placeholder="选择应用类型">
+                  <el-option v-for="item in appTypeList" :key="item.value" :label="item.label" :value="item.value"></el-option>
+                </el-select>
+              </el-form-item>
+              <el-form-item label="环境" prop="env">
+                <el-radio-group v-model="appForm.env">
+                  <el-radio v-for="item in envList" :key="item.value" :label="item.label" :value="item.value"></el-radio>
+                </el-radio-group>
+              </el-form-item>
+              <el-form-item label="编译器配置" prop="compilerConfigId">
+                <el-select v-model="appForm.compilerConfigId">
+                  <el-option v-for="item in compilerList" :key="item.value" :label="item.label" :value="item.value"></el-option>
+                </el-select>
+              </el-form-item>
+              <el-form-item label="打包配置" prop="packerConfigId">
+                <el-select v-model="appForm.packerConfigId">
+                  <el-option v-for="item in packerList" :key="item.value" :label="item.label" :value="item.value"></el-option>
+                </el-select>
+              </el-form-item>
+            </div>
+
+            <div v-show="active === 2">
+              <el-form-item label="HTTP 端口" prop="httpPort">
+                <el-input v-model="appForm.httpPort" placeholder="8080"></el-input>
+              </el-form-item>
+              <el-form-item label="Dockerfile" prop="dockerfile">
+                <el-input type="textarea" :rows="8" v-model="appForm.dockerfile" placeholder="FROM ..."></el-input>
+              </el-form-item>
+            </div>
+
+            <div class="footer-btns" style="text-align: center; margin-top: 20px">
+              <el-button v-if="active > 0" @click="prev">上一步</el-button>
+              <el-button v-if="active < 2" type="primary" @click="next">下一步</el-button>
+              <el-button v-if="active === 2" type="success" @click="submit">提交配置</el-button>
+            </div>
+          </el-form>
+        </div>
       </template>
     </el-dialog>
     <el-dialog
@@ -394,10 +366,6 @@
           height="480"
           style="width: 100%"
         >
-          <el-table-column
-            prop="appName"
-            label="应用名"
-          />
           <el-table-column
             prop="machineIpv4"
             label="机器地址"
@@ -528,6 +496,29 @@ export default {
       totalSize: 0,
       dataList: [],
       // **********************************************************************
+      active: 0,
+      appForm: {
+        appRepo: '',
+        repoBranch: '',
+        env: '',
+        appType: '',
+        repoAuthConfigId: null,
+        compilerConfigId: null,
+        packerConfigId: null,
+        dockerfile: '',
+        appId: '',
+      },
+      appFormRules: {
+        appRepo: [{ required: true, message: '代码仓库不能为空', trigger: 'blur' }],
+        repoBranch: [{ required: true, message: '仓库分支不能为空', trigger: 'blur' }],
+        'repoAuthConfigId': [{ required: true, message: '请选择仓库认证', trigger: 'blur' }],
+        appType: [{ required: true, message: '应用类型不能为空', trigger: 'blur' }],
+        env: [{ required: true, message: '应用环境不能为空', trigger: 'blur' }],
+        'compilerConfigId': [{ required: true, message: '请选择编译器', trigger: 'blur' }],
+        'packerConfigId': [{ required: true, message: '请选择打包配置', trigger: 'blur' }],
+        dockerfile: [{ required: true, message: '请填写 Dockerfile', trigger: 'blur' }],
+      },
+      // **********************************************************************
       showBindDomainDialog: false,
       domainList: [],
       showElInput: false,
@@ -544,11 +535,9 @@ export default {
         appType: null,
         env: null,
         appId: null,
-        appName: null,
         appRepo: null,
         repoBranch: null,
-        appRootPath: null,
-        bindPorts: null,
+        httpPort: null,
         repoAuthConfig: null,
         compilerConfig: null,
         packerConfig: null,
@@ -566,7 +555,6 @@ export default {
       showEditDialog: false,
       editForm: {
         appId: null,
-        appName: null,
         repoBranch: null,
         repoAuthConfig: null,
         compilerConfig: null,
@@ -744,7 +732,6 @@ export default {
     onEdit() {
       const formData = new FormData()
       formData.append('appId', this.editForm.appId)
-      formData.append('appName', this.editForm.appName)
       formData.append('repoBranch', this.editForm.repoBranch)
       formData.append('repoAuthConfig', this.editForm.repoAuthConfig)
       formData.append('compilerConfig', this.editForm.compilerConfig)
@@ -788,31 +775,68 @@ export default {
         this.$message.error(error.message)
       })
     },
-    onAdd() {
-      const formData = new FormData()
-      formData.append('appId', this.addForm.appId)
-      formData.append('appName', this.addForm.appName)
-      formData.append('appType', this.addForm.appType)
-      formData.append('env', this.addForm.env)
-      formData.append('appRepo', this.addForm.appRepo)
-      formData.append('repoBranch', this.addForm.repoBranch)
-      formData.append('appRootPath', this.addForm.appRootPath)
-      formData.append('bindPorts', this.addForm.bindPorts)
-      formData.append('repoAuthConfig', this.addForm.repoAuthConfig)
-      formData.append('compilerConfig', this.addForm.compilerConfig)
-      formData.append('packerConfig', this.addForm.packerConfig)
-      formData.append('dockerfile', this.addForm.dockerfile)
-      addAppConfig(formData).then(resp => {
-        if (resp.code === 0) {
-          this.getData()
-        } else {
-          this.$message.info(resp.msg)
+    // ****************************************************************************************************************
+    // 添加 AppConfig
+    // ****************************************************************************************************************
+    async next() {
+      const fieldsForSteps = [
+        ['appRepo', 'repoBranch', 'repoAuthConfigId'],
+        ['appType', 'env', 'compilerConfigId', 'packerConfigId'],
+        ['dockerfile']
+      ];
+
+      const currentFields = fieldsForSteps[this.active];
+
+      // 1. 手动封装校验逻辑,确保所有字段校验完才继续
+      try {
+        const validations = currentFields.map(field => {
+          return new Promise((resolve, reject) => {
+            this.$refs.appFormRef.validateField(field, (errorMessage) => {
+              if (errorMessage) {
+                reject(errorMessage);
+              } else {
+                resolve();
+              }
+            });
+          });
+        });
+
+        await Promise.all(validations);
+
+        // 2. 只有全部成功才会走到这里
+        if (this.active < 2) {
+          this.active++;
         }
-      }).catch(error => {
-        this.$message.error(error.message)
-      }).finally(() => {
-        this.showAddDialog = false
-      })
+      } catch (error) {
+        this.$message.error('校验未通过:', error);
+        // 校验失败,保持在当前页
+      }
+    },
+    prev() {
+      if (this.active > 0) this.active--;
+    },
+    submit() {
+      this.$refs.appFormRef.validate((valid) => {
+        if (valid) {
+          addAppConfig(this.appForm).then(resp => {
+            console.log('提交数据:', this.form);
+            this.$message.success('配置已保存');
+            if (resp.code === 0) {
+              this.active = 0;
+              this.$refs.appFormRef.resetFields();
+              this.appForm.repoAuthConfig = { id: null };
+              this.appForm.compilerConfig = { id: null };
+              this.getData()
+            } else {
+              this.$message.info(resp.msg)
+            }
+          }).catch(error => {
+            this.$message.error(error.message)
+          }).finally(() => {
+            this.showAddDialog = false
+          })
+        }
+      });
     },
     onSelectChange() {
       this.currentPage = 1
@@ -824,7 +848,7 @@ export default {
       this.getData()
     },
     handleDelete(index, row) {
-      this.$confirm('确定要删除 ' + row.appName + '?', '提示', {
+      this.$confirm('确定要删除 ' + row.appId + '?', '提示', {
         confirmButtonText: '确定',
         cancelButtonText: '取消',
         type: 'warning'
@@ -920,7 +944,7 @@ export default {
       })
     },
     handleDeleteDeployConfig(index, row) {
-      this.$confirm('确定要删除 ' + row.appName + '?', '提示', {
+      this.$confirm('确定要删除 ' + row.appId + '?', '提示', {
         confirmButtonText: '确定',
         cancelButtonText: '取消',
         type: 'warning'

+ 1 - 5
src/views/devops/app/AppStat.vue

@@ -39,11 +39,7 @@
         style="width: 100%"
       >
         <el-table-column
-          prop="appName"
-          label="应用"
-        />
-        <el-table-column
-          prop="bindPorts"
+          prop="httpPort"
           label="监听端口"
         />
         <el-table-column

+ 4 - 4
src/views/devops/app/BuildDeploy.vue

@@ -30,7 +30,7 @@
           />
         </el-select>
         <el-input
-          v-model="queryInfo.appName"
+          v-model="queryInfo.appId"
           style="margin :5px; width: 20%"
           clearable
           placeholder="输入应用名(回车搜索)"
@@ -69,7 +69,7 @@
           label="分支"
         />
         <el-table-column
-          prop="bindPorts"
+          prop="httpPort"
           label="监听端口"
         />
         <el-table-column
@@ -630,7 +630,7 @@ export default {
       queryInfo: {
         env: 'test',
         appType: '',
-        appName: '',
+        appId: '',
         pn: 1
       },
       // 屏幕宽度, 为了控制分页条的大小
@@ -946,7 +946,7 @@ export default {
       this.getData()
     },
     onRefresh() {
-      this.queryInfo.appName = ''
+      this.queryInfo.appId = ''
       this.getData()
     },
     onSelectChange() {