Ver código fonte

feat: 对外接口配置功能

liujt 1 semana atrás
pai
commit
178345a2ca

+ 52 - 0
src/api/system/externalConfig/index.js

@@ -0,0 +1,52 @@
+import request from '@/utils/request';
+
+/**
+ * 分页查询
+ * @param params 查询条件
+ */
+export async function externalSystemConfigPage(params) {
+  const res = await request.get('/main/externalSystemConfig/list', {
+    params
+  });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+
+/**
+ * 详情
+ * @param params 查询条件
+ */
+export async function externalSystemConfigDetail(id) {
+  const res = await request.get(`/main/externalSystemConfig/getById/${id}`);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 修改
+ * @param params 更新参数
+ */
+export async function externalSystemConfigUpdate(params) {
+  const res = await request.put(`/main/externalSystemConfig/update`, params);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ *启用/禁用
+ * @param params 更新参数
+ */
+export async function externalSystemConfigEnableOrDisable(params) {
+  const res = await request.post(`/main/externalSystemConfig/enableOrDisable`, params);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}

+ 522 - 0
src/views/system/externalConfig/index.vue

@@ -0,0 +1,522 @@
+<template>
+  <div class="ele-body">
+    <el-card shadow="never" v-loading="loading">
+      <ele-split-layout
+        width="266px"
+        allow-collapse
+        :right-style="{ overflow: 'hidden' }"
+      >
+        <div>
+          <!-- 操作按钮 -->
+          <ele-toolbar class="ele-toolbar-actions">
+            <div style="margin: 5px 0">
+              <el-input
+                v-model="searchValue"
+                placeholder="请输入"
+                clearable
+                @keyup.enter.native="query"
+              />
+            </div>
+          </ele-toolbar>
+          <div class="ele-border-lighter sys-organization-list">
+            <div class="list-title">系统列表</div>
+            <div class="list-body">
+              <div
+                v-for="item in systemList"
+                :key="item.id"
+                class="list-item"
+                :class="{ active: current && current.id === item.id }"
+                @click="onNodeClick(item)"
+              >
+                <!-- <i class="el-icon-folder list-item-icon"></i> -->
+                <span class="list-item-text">{{ item.systemName }}  {{ item.systemVersion }}</span>
+              </div>
+            </div>
+          </div>
+        </div>
+        <template v-slot:content>
+          <div class="external-config-content">
+            <el-form
+              ref="form"
+              :model="form"
+              :rules="rules"
+              label-width="110px"
+              class="el-form-box external-config-form"
+            >
+              <!-- 基本信息 -->
+              <HeaderTitle title="基本信息"></HeaderTitle>
+              <el-row :gutter="20">
+                <el-col :span="8">
+                  <el-form-item label="系统名称:" prop="systemName">
+                    <el-input disabled v-model="form.systemName" placeholder="请输入" />
+                  </el-form-item>
+                </el-col>
+                <el-col :span="8">
+                  <el-form-item label="系统唯一编码:" prop="systemCode">
+                    <el-input disabled v-model="form.systemCode" placeholder="请输入" />
+                  </el-form-item>
+                </el-col>
+                <el-col :span="8">
+                  <el-form-item label="系统版本号:" prop="systemVersion">
+                    <el-input v-model="form.systemVersion" :disabled="!editable" placeholder="请输入" />
+                  </el-form-item>
+                </el-col>
+              </el-row>
+              <el-row :gutter="20">
+                <el-col :span="8">
+                  <el-form-item label="对接业务类型:" prop="directionType">
+                    <el-select
+                      v-model="form.directionType"
+                      :disabled="!editable"
+                      placeholder="请选择"
+                      style="width: 100%"
+                    >
+                      <el-option
+                        v-for="item in directionTypeOptions"
+                        :key="item.value"
+                        :label="item.label"
+                        :value="item.value"
+                      />
+                    </el-select>
+                  </el-form-item>
+                </el-col>
+                <el-col :span="8">
+                  <el-form-item label="接口生效状态:" prop="effectStatus">
+                    <el-select
+                      v-model="form.effectStatus"
+                      :disabled="!editable"
+                      placeholder="请选择"
+                      style="width: 100%"
+                    >
+                      <el-option
+                        v-for="item in effectStatusOptions"
+                        :key="item.value"
+                        :label="item.label"
+                        :value="item.value"
+                      />
+                    </el-select>
+                  </el-form-item>
+                </el-col>
+              </el-row>
+
+              <!-- 业务类型 -->
+              <HeaderTitle style="margin-top: 20px" title="业务类型" />
+              <el-row :gutter="20">
+                <!-- 推送业务 -->
+                <el-col :span="24">
+                  <div class="sub-title">推送</div>
+                  <el-checkbox-group v-model="form.pushSelected" :disabled="!editable" class="checkbox-block">
+                    <el-checkbox
+                      v-for="item in pushList"
+                      :key="item.code"
+                      :label="item.code"
+                    >{{ item.name }}</el-checkbox>
+                  </el-checkbox-group>
+                </el-col>
+                <!-- 回传业务 -->
+                <el-col :span="24" style="margin-top: 16px">
+                  <div class="sub-title">回传</div>
+                  <el-checkbox-group v-model="form.callbackSelected" :disabled="!editable" class="checkbox-block">
+                    <el-checkbox
+                      v-for="item in callbackList"
+                      :key="item.code"
+                      :label="item.code"
+                    >{{ item.name }}</el-checkbox>
+                  </el-checkbox-group>
+                </el-col>
+              </el-row>
+
+              <!-- 授权规则 -->
+              <HeaderTitle style="margin-top: 20px" title="授权规则" />
+              <el-row :gutter="20">
+                <el-col :span="24">
+                  <div class="rule-tip">
+                    勾选业务类型后,需本公司授权通过,接口才生效启用
+                  </div>
+                </el-col>
+              </el-row>
+            </el-form>
+
+            <!-- 操作按钮 -->
+            <div class="external-config-footer">
+              <template v-if="!editable">
+                <el-button type="primary" plain @click="editable = true">编辑</el-button>
+              </template>
+              <template v-else>
+                <el-button @click="cancelEdit">取消</el-button>
+                <el-button type="primary" :loading="saveLoading" @click="handleSave">保存配置</el-button>
+              </template>
+              <el-button v-if="!editable" :type="form.effectStatus == 0 ? 'success' : 'danger'" :loading="enableLoading" @click="handleEnable">{{form.effectStatus == 0 ? '启用接口' : '禁用接口'}}</el-button>
+              <!-- <el-button type="warning" @click="handleApplyAuth">申请授权</el-button> -->
+              <!-- <el-button type="danger" plain @click="handleDelete">删除</el-button> -->
+            </div>
+          </div>
+        </template>
+      </ele-split-layout>
+    </el-card>
+ 
+  </div>
+</template>
+
+<script>
+import { externalSystemConfigPage, externalSystemConfigDetail, externalSystemConfigUpdate, externalSystemConfigEnableOrDisable } from '@/api/system/externalConfig';
+
+
+  export default {
+    name: 'ExternalConfig',
+    components: { },
+    data() {
+      return {
+        // 加载状态
+        loading: false,
+        // 保存/启用按钮防抖锁
+        saveLoading: false,
+        enableLoading: false,
+        // 编辑模式(默认非编辑,右侧只读)
+        editable: false,
+        // 左侧系统列表(示例数据)
+        systemList: [],
+        // 选中数据
+        current: null,
+        // 是否显示表单弹窗
+        showEdit: false,
+        // 编辑回显数据
+        editData: null,
+        // 上级id
+        parentId: null,
+
+        // ========== 外部对接配置 ==========
+        // 对接业务类型
+        directionTypeOptions: [
+          { value: 'EX', label: '对外' },
+          { value: 'IN', label: '对内' }
+        ],
+        // 接口生效状态
+        effectStatusOptions: [
+          { value: 0, label: '未生效' },
+          { value: 1, label: '已生效' }
+        ],
+        // 推送业务子项(由详情 bizInterfaceList 中 buisType=PUSH 生成)
+        pushList: [],
+        // 回传业务子项(由详情 bizInterfaceList 中 buisType=PULL 生成)
+        callbackList: [],
+
+        // 表单数据
+        form: {
+          systemName: '',
+          systemCode: '',
+          systemVersion: '',
+          directionType: '',
+          effectStatus: '',
+          businessType: '',
+          pushSelected: [],
+          callbackSelected: []
+        },
+        searchValue: '',
+
+        // 校验规则
+        rules: {
+        //   systemName: [
+        //     { required: true, message: '请输入系统名称', trigger: 'blur' }
+        //   ],
+        //   systemCode: [
+        //     { required: true, message: '请输入系统唯一编码', trigger: 'blur' }
+        //   ],
+        //   systemVersion: [
+        //     { required: true, message: '请输入系统版本号', trigger: 'blur' }
+        //   ],
+        //   directionType: [
+        //     { required: true, message: '请选择对接业务类型', trigger: 'change' }
+        //   ]
+        }
+      };
+    },
+    created() {
+      this.query();
+    },
+    methods: {
+      /* 查询 */
+      query() {
+        this.loading = true;
+        externalSystemConfigPage({
+          systemName: this.searchValue
+        })
+          .then((res) => {
+            console.log(res);
+            this.loading = false;
+            this.systemList = res;
+            console.log(this.systemList);
+            // 默认选中第一条并显示详情
+            if (this.systemList && this.systemList.length) {
+              this.onNodeClick(this.systemList[0]);
+            }
+          })
+          .catch((e) => {
+            this.loading = false;
+            // this.$message.error(e.message);
+          });
+      },
+      /* 选择数据 */
+      onNodeClick(row) {
+        this.current = row;
+        // 切换系统时回到只读模式
+        this.editable = false;
+        this.getDetail(row.id);
+      },
+      /* 取消编辑,还原为只读并重新加载详情 */
+      cancelEdit() {
+        this.editable = false;
+        if (this.current) {
+          this.getDetail(this.current.id);
+        }
+      },
+      async getDetail(id) {
+        const detail = await externalSystemConfigDetail(id);
+        // 合并保留表单默认字段(如多选数组),避免接口未返回时丢失
+        this.form = { ...this.form, ...detail };
+
+        // 根据 buisType 分组业务接口列表:PUSH=推送,PULL=回传
+        const bizList = detail.bizInterfaceList || [];
+        const pushList = [];
+        const callbackList = [];
+        const pushSelected = [];
+        const callbackSelected = [];
+        bizList.forEach((item) => {
+          if (item.buisType === 'PUSH') {
+            pushList.push({
+              code: item.bizInterfaceCode,
+              name: item.bizInterfaceName
+            });
+            if (item.isChecked === 1) {
+              pushSelected.push(item.bizInterfaceCode);
+            }
+          } else if (item.buisType === 'PULL') {
+            callbackList.push({
+              code: item.bizInterfaceCode,
+              name: item.bizInterfaceName
+            });
+            if (item.isChecked === 1) {
+              callbackSelected.push(item.bizInterfaceCode);
+            }
+          }
+        });
+        this.pushList = pushList;
+        this.callbackList = callbackList;
+        this.form.pushSelected = pushSelected;
+        this.form.callbackSelected = callbackSelected;
+
+        console.log(this.form);
+      },
+      /* 显示编辑 */
+      openEdit(item) {
+        this.editData = item;
+        this.showEdit = true;
+      },
+      /* 删除 */
+      remove() {
+        this.$confirm('确定要删除选中的机构吗?', '提示', {
+          type: 'warning'
+        })
+          .then(() => {
+            const loading = this.$loading({ lock: true });
+            removeOrganization([this.current.id])
+              .then((msg) => {
+                loading.close();
+                this.$message.success(msg);
+                this.query();
+              })
+              .catch((e) => {
+                loading.close();
+                // this.$message.error(e.message);
+              });
+          })
+          .catch(() => {});
+      },
+
+      /* 保存配置 */
+      handleSave() {
+        if (this.saveLoading) {
+          return;
+        }
+        this.$refs.form.validate((valid) => {
+          if (!valid) {
+            this.$message.warning('有必填项未填,请检查');
+            return;
+          }
+          this.saveLoading = true;
+          // 保持接口返回格式,仅根据勾选状态更新 isChecked(勾选=1,未勾选=0)
+          const bizInterfaceList = (this.form.bizInterfaceList || []).map(
+            (item) => {
+              const checked =
+                (item.buisType === 'PUSH' &&
+                  this.form.pushSelected.includes(item.bizInterfaceCode)) ||
+                (item.buisType === 'PULL' &&
+                  this.form.callbackSelected.includes(item.bizInterfaceCode));
+              return { ...item, isChecked: checked ? 1 : 0 };
+            }
+          );
+          const submitData = { ...this.form, bizInterfaceList };
+          console.log('保存配置', submitData);
+          externalSystemConfigUpdate(submitData)
+            .then((res) => {
+              this.$message.success('保存配置成功');
+              this.editable = false;
+              this.query();
+            })
+            .finally(() => {
+              this.saveLoading = false;
+            });
+        });
+      },
+      /* 申请授权 */
+      handleApplyAuth() {
+        console.log('申请授权', this.form);
+        this.$message.info('申请授权');
+      },
+      /* 启用接口 */
+      handleEnable() {
+        if (this.enableLoading) {
+          return;
+        }
+        this.enableLoading = true;
+        console.log('启用接口', this.form);
+        externalSystemConfigEnableOrDisable({
+          id: this.form.id,
+          effectStatus: this.form.effectStatus == 0 ? 1 : 0
+        })
+          .then((res) => {
+            this.$message.success(this.form.effectStatus == 0 ? '接口已启用' : '接口已禁用');
+            this.query();
+          })
+          .finally(() => {
+            this.enableLoading = false;
+          });
+      },
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  .sys-organization-list {
+    height: calc(100vh - 264px);
+    box-sizing: border-box;
+    border-width: 1px;
+    border-style: solid;
+    overflow: hidden;
+    display: flex;
+    flex-direction: column;
+  }
+
+  .sys-organization-list .list-title {
+    flex-shrink: 0;
+    font-size: 14px;
+    font-weight: 600;
+    color: #303133;
+    padding: 12px 16px;
+    border-bottom: 1px solid #ebeef5;
+    background: #fafafa;
+  }
+
+  .sys-organization-list .list-body {
+    flex: 1;
+    overflow-y: auto;
+    padding: 8px;
+  }
+
+  .sys-organization-list .list-item {
+    display: flex;
+    align-items: center;
+    height: 38px;
+    padding: 0 12px;
+    border-radius: 4px;
+    cursor: pointer;
+    color: #606266;
+    transition: background-color 0.2s, color 0.2s;
+  }
+
+  .sys-organization-list .list-item:hover {
+    background: #ecf5ff;
+    color: #409eff;
+  }
+
+  .sys-organization-list .list-item.active {
+    background: #409eff;
+    color: #fff;
+  }
+
+  .sys-organization-list .list-item-icon {
+    margin-right: 8px;
+    font-size: 15px;
+  }
+
+  .sys-organization-list .list-item-text {
+    flex: 1;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+    font-size: 14px;
+  }
+
+  .external-config-content {
+    padding: 16px 20px;
+    height: 100%;
+    overflow-y: auto;
+    box-sizing: border-box;
+  }
+
+  .external-config-form {
+    :deep(.el-checkbox-group) {
+      display: flex;
+      flex-wrap: wrap;
+    }
+    :deep(.el-checkbox) {
+      margin-right: 24px;
+      margin-bottom: 8px;
+    }
+  }
+
+  .rule-tip {
+    color: #909399;
+    font-size: 13px;
+    padding: 6px 0 4px;
+  }
+
+  .sub-title {
+    font-size: 14px;
+    font-weight: 600;
+    color: #303133;
+    position: relative;
+    padding-left: 10px;
+    margin-bottom: 10px;
+
+    &::before {
+      content: '';
+      position: absolute;
+      left: 0;
+      top: 50%;
+      transform: translateY(-50%);
+      width: 3px;
+      height: 14px;
+      background: #409eff;
+      border-radius: 2px;
+    }
+  }
+
+  .checkbox-block {
+    display: flex;
+    flex-wrap: wrap;
+    padding-left: 10px;
+
+    :deep(.el-checkbox) {
+      margin-right: 24px;
+      margin-bottom: 8px;
+    }
+  }
+
+  .external-config-footer {
+    margin-top: 24px;
+    padding-top: 16px;
+    border-top: 1px solid #ebeef5;
+    text-align: left;
+  }
+</style>