boss 21 ore fa
parent
commit
2ced6d8cf5

+ 9 - 0
src/api/admin/sysCompany.js

@@ -52,6 +52,15 @@ export function addCompany(data) {
   })
 }
 
+// 更新租户信息
+export function updateTenant(data) {
+  return request({
+    url: '/admin/company',
+    method: 'put',
+    data: data
+  })
+}
+
 // 租户充値/扣款
 export function rechargeCompany(companyId, data) {
   return request({

+ 1 - 1
src/layout/AdminLayout.vue

@@ -171,7 +171,7 @@ export default {
         .map(group => ({
           title: (group.meta && group.meta.title) || group.name || '',
           icon: (group.meta && group.meta.icon) || '',
-          children: this.buildSidebarItems(group.children, '/admin/' + (group.path || ''))
+          children: this.buildSidebarItems(group.children, group.path ? '/admin/' + group.path : '/admin')
         }))
     },
     // 是否处于数据看板页面

+ 3 - 2
src/store/modules/permission.js

@@ -99,9 +99,10 @@ function filterChildren(childrenMap, lastRouter = false) {
   var children = []
   childrenMap.forEach((el, index) => {
     if (el.children && el.children.length) {
-      if (el.component === 'ParentView') {
+      // ParentView 或空component(无实体页面的分组菜单)都需要展平
+      if (el.component === 'ParentView' || !el.component) {
         el.children.forEach(c => {
-          c.path = el.path + '/' + c.path
+          c.path = (el.path ? el.path + '/' : '') + c.path
           if (c.children && c.children.length) {
             children = children.concat(filterChildren(c.children, c))
             return

+ 4 - 4
src/views/admin/dashboard/index.vue

@@ -64,10 +64,10 @@ export default {
         { label: '总充值金额', value: '¥0.00', icon: 'el-icon-bank-card', color: '#06b6d4', gradient: 'linear-gradient(135deg, #06b6d4, #22d3ee)' }
       ],
       quickLinks: [
-        { title: '代理管理', path: '/admin/proxy-mgmt/proxy', icon: 'el-icon-user', color: '#3b82f6' },
-        { title: '租户管理', path: '/admin/tenant-mgmt/company', icon: 'el-icon-office-building', color: '#10b981' },
-        { title: 'AI模型配置', path: '/admin/ai-mgmt/aiModel', icon: 'el-icon-cpu', color: '#8b5cf6' },
-        { title: '消费记录', path: '/admin/finance/consumeRecord', icon: 'el-icon-coin', color: '#f59e0b' }
+        { title: '代理管理', path: '/admin/proxy', icon: 'el-icon-user', color: '#3b82f6' },
+        { title: '租户管理', path: '/admin/company', icon: 'el-icon-office-building', color: '#10b981' },
+        { title: 'AI模型配置', path: '/admin/aiModel', icon: 'el-icon-cpu', color: '#8b5cf6' },
+        { title: '消费记录', path: '/admin/consumeRecord', icon: 'el-icon-coin', color: '#f59e0b' }
       ]
     }
   },

+ 124 - 66
src/views/admin/sysCompany/index.vue

@@ -3,8 +3,8 @@
     <!-- ===== 搜索栏 ===== -->
     <el-card shadow="never" class="mb16 filter-card">
     <el-form :model="queryParams" ref="queryForm" :inline="true" size="small">
-      <el-form-item label="租户名称" prop="companyName">
-        <el-input v-model="queryParams.companyName" placeholder="租户编码/名称" clearable @keyup.enter.native="handleQuery" />
+      <el-form-item label="租户名称" prop="tenantName">
+        <el-input v-model="queryParams.tenantName" placeholder="租户编码/名称" clearable @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item label="状态" prop="status">
         <el-select v-model="queryParams.status" placeholder="全部" clearable style="width:120px">
@@ -31,8 +31,8 @@
 
     <!-- ===== 租户列表 ===== -->
     <el-table border v-loading="loading" :data="companyList" size="small" style="width:100%">
-      <el-table-column label="租户编码" prop="companyId" min-width="80" align="center" />
-      <el-table-column label="租户名称" prop="companyName" min-width="120" />
+      <el-table-column label="租户编码" prop="tenantCode" min-width="80" align="center" />
+      <el-table-column label="租户名称" prop="tenantName" min-width="120" />
       <el-table-column label="联系人" prop="contactName" min-width="80" align="center" />
       <el-table-column label="联系电话" prop="contactPhone" min-width="110" align="center" />
       <el-table-column label="余额" align="center" min-width="100">
@@ -42,7 +42,7 @@
       </el-table-column>
       <el-table-column label="已消费总额" align="center" min-width="100">
         <template slot-scope="scope">
-          <span>{{ scope.row.totalCost ? '¥' + Number(scope.row.totalCost).toFixed(2) : '¥0.00' }}</span>
+          <span>{{ scope.row.totalConsumption ? '¥' + Number(scope.row.totalConsumption).toFixed(2) : '¥0.00' }}</span>
         </template>
       </el-table-column>
       <el-table-column label="开通账户数" align="center" prop="accountCount" min-width="90" />
@@ -52,7 +52,6 @@
       <el-table-column label="企微用户数" align="center" prop="qwUserCount" min-width="90" />
       <el-table-column label="过期时间" align="center" prop="expireTime" min-width="100" />
       <el-table-column label="归属代理" align="center" prop="proxyName" min-width="90" />
-      <el-table-column label="备注" prop="remark" min-width="100" show-overflow-tooltip />
       <el-table-column label="状态" align="center" min-width="70">
         <template slot-scope="scope">
           <el-tag v-if="scope.row.status == 1" type="success" size="mini">正常</el-tag>
@@ -85,33 +84,58 @@
 
     <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
 
-    <!-- ===== 租户详情弹窗 ===== -->
-    <el-dialog title="租户详情" :visible.sync="viewOpen" width="640px" append-to-body>
-      <el-descriptions :column="2" border size="small">
-        <el-descriptions-item label="租户ID">{{ viewForm.companyId }}</el-descriptions-item>
-        <el-descriptions-item label="租户名称">{{ viewForm.companyName }}</el-descriptions-item>
-        <el-descriptions-item label="租户简称">{{ viewForm.companyShortName || '-' }}</el-descriptions-item>
-        <el-descriptions-item label="联系人">{{ viewForm.contactName || '-' }}</el-descriptions-item>
-        <el-descriptions-item label="联系电话">{{ viewForm.contactPhone || '-' }}</el-descriptions-item>
-        <el-descriptions-item label="邮箱">{{ viewForm.email || '-' }}</el-descriptions-item>
-        <el-descriptions-item label="地址" :span="2">{{ viewForm.address || '-' }}</el-descriptions-item>
-        <el-descriptions-item label="创建时间">{{ viewForm.createTime }}</el-descriptions-item>
-        <el-descriptions-item label="过期时间">{{ viewForm.expireTime || '-' }}</el-descriptions-item>
-        <el-descriptions-item label="租户余额">
-          <span style="color:#1890ff;font-weight:bold">¥{{ viewForm.balance || '0.00' }}</span>
-        </el-descriptions-item>
-        <el-descriptions-item label="已消费总额">¥{{ viewForm.totalCost || '0.00' }}</el-descriptions-item>
-        <el-descriptions-item label="开通账户数">{{ viewForm.accountCount || 0 }}</el-descriptions-item>
-        <el-descriptions-item label="绑定企微账号数">{{ viewForm.qwAccountCount || 0 }}</el-descriptions-item>
-        <el-descriptions-item label="绑定个微账号数">{{ viewForm.wxAccountCount || 0 }}</el-descriptions-item>
-        <el-descriptions-item label="客户数">{{ viewForm.customerCount || 0 }}</el-descriptions-item>
-        <el-descriptions-item label="企微用户数">{{ viewForm.qwUserCount || 0 }}</el-descriptions-item>
-        <el-descriptions-item label="归属代理">{{ viewForm.proxyName || '-' }}</el-descriptions-item>
-        <el-descriptions-item label="租户状态">
-          <el-tag v-if="viewForm.status == 1" type="success" size="mini">正常</el-tag>
-          <el-tag v-else type="danger" size="mini">禁用</el-tag>
-        </el-descriptions-item>
-      </el-descriptions>
+    <!-- ===== 编辑租户弹窗 ===== -->
+    <el-dialog title="编辑租户" :visible.sync="viewOpen" width="680px" append-to-body destroy-on-close>
+      <el-form ref="editForm" :model="viewForm" :rules="editRules" label-width="100px" size="small">
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="租户ID">
+              <span>{{ viewForm.id }}</span>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="租户编码">
+              <span>{{ viewForm.tenantCode || '-' }}</span>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="租户名称" prop="tenantName">
+              <el-input v-model="viewForm.tenantName" placeholder="请输入租户名称" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="联系人" prop="contactName">
+              <el-input v-model="viewForm.contactName" placeholder="请输入联系人" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="联系电话" prop="contactPhone">
+              <el-input v-model="viewForm.contactPhone" placeholder="请输入联系电话" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="过期时间" prop="expireTime">
+              <el-date-picker v-model="viewForm.expireTime" type="date" value-format="yyyy-MM-dd" placeholder="选择过期时间" style="width:100%" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="租户余额">
+              <span style="color:#1890ff;font-weight:bold">¥{{ viewForm.balance || '0.00' }}</span>
+              <span style="color:#999;font-size:12px;margin-left:8px">(通过充值/扣款调整)</span>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="租户状态">
+              <el-switch v-model="viewForm.statusBool" active-text="正常" inactive-text="禁用"
+                :active-value="1" :inactive-value="0" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+      <div slot="footer">
+        <el-button @click="viewOpen = false">取 消</el-button>
+        <el-button type="primary" :loading="editSubmitting" @click="submitEdit">保 存</el-button>
+      </div>
     </el-dialog>
 
     <!-- ===== 新增租户弹窗 ===== -->
@@ -119,18 +143,18 @@
       <el-form ref="addForm" :model="addDialog.form" :rules="addDialog.rules" label-width="100px" size="small">
         <el-row :gutter="20">
           <el-col :span="12">
-            <el-form-item label="企业名称" prop="companyName">
-              <el-input v-model="addDialog.form.companyName" placeholder="请输入企业名称" />
+            <el-form-item label="企业名称" prop="tenantName">
+              <el-input v-model="addDialog.form.tenantName" placeholder="请输入企业名称" />
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item label="联系电话" prop="companyMobile">
-              <el-input v-model="addDialog.form.companyMobile" placeholder="请输入联系电话" />
+            <el-form-item label="联系电话" prop="contactPhone">
+              <el-input v-model="addDialog.form.contactPhone" placeholder="请输入联系电话" />
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item label="联系人" prop="linkName">
-              <el-input v-model="addDialog.form.linkName" placeholder="请输入联系人" />
+            <el-form-item label="联系人" prop="contactName">
+              <el-input v-model="addDialog.form.contactName" placeholder="请输入联系人" />
             </el-form-item>
           </el-col>
           <el-col :span="12">
@@ -154,8 +178,8 @@
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item label="到期时间" prop="limitTime">
-              <el-date-picker v-model="addDialog.form.limitTime" type="date" value-format="yyyy-MM-dd" placeholder="选择到期时间" style="width:100%" />
+            <el-form-item label="到期时间" prop="expireTime">
+              <el-date-picker v-model="addDialog.form.expireTime" type="date" value-format="yyyy-MM-dd" placeholder="选择到期时间" style="width:100%" />
             </el-form-item>
           </el-col>
           <el-col :span="12">
@@ -233,7 +257,7 @@
 </template>
 
 <script>
-import { listAllCompanies, getCompanyInfo, addCompany, disableCompany, enableCompany, rechargeCompany, exportCompany, getTenantMenuTree, editTenantMenu } from '@/api/admin/sysCompany'
+import { listAllCompanies, getCompanyInfo, addCompany, updateTenant, disableCompany, enableCompany, rechargeCompany, exportCompany, getTenantMenuTree, editTenantMenu } from '@/api/admin/sysCompany'
 
 export default {
   name: 'SysCompanyAdmin',
@@ -251,30 +275,35 @@ export default {
       queryParams: {
         pageNum: 1,
         pageSize: 10,
-        companyName: null,
+        tenantName: null,
         status: null
       },
       // 详情弹窗
       viewOpen: false,
       viewForm: {},
+      editSubmitting: false,
+      editRules: {
+        tenantName: [{ required: true, message: '请输入租户名称', trigger: 'blur' }],
+        contactPhone: [{ required: true, message: '请输入联系电话', trigger: 'blur' }]
+      },
       // 新增租户弹窗
       addDialog: {
         visible: false,
         submitting: false,
         form: {
-          companyName: '',
-          companyMobile: '',
-          linkName: '',
+          tenantName: '',
+          contactPhone: '',
+          contactName: '',
           userName: '',
           password: '',
           manager: '',
           startTime: null,
-          limitTime: null,
+          expireTime: null,
           status: 1
         },
         rules: {
-          companyName: [{ required: true, message: '请输入企业名称', trigger: 'blur' }],
-          companyMobile: [{ required: true, message: '请输入联系电话', trigger: 'blur' }],
+          tenantName: [{ required: true, message: '请输入企业名称', trigger: 'blur' }],
+          contactPhone: [{ required: true, message: '请输入联系电话', trigger: 'blur' }],
           userName: [{ required: true, message: '请输入管理员账号', trigger: 'blur' }],
           password: [{ required: true, message: '请输入密码', trigger: 'blur' }]
         }
@@ -325,14 +354,14 @@ export default {
     /** 新增租户 */
     handleAdd() {
       this.addDialog.form = {
-        companyName: '',
-        companyMobile: '',
-        linkName: '',
+        tenantName: '',
+        contactPhone: '',
+        contactName: '',
         userName: '',
         password: '',
         manager: '',
         startTime: null,
-        limitTime: null,
+        expireTime: null,
         status: 1
       }
       this.addDialog.visible = true
@@ -356,24 +385,53 @@ export default {
         })
       })
     },
-    /** 查看详情/编辑 */
+    /** 编辑租户 */
     handleView(row) {
-      getCompanyInfo(row.companyId).then(response => {
+      getCompanyInfo(row.id).then(response => {
         this.viewForm = response.data
+        // 为 el-switch 提供 number 类型的 status
+        this.$set(this.viewForm, 'statusBool', this.viewForm.status)
         this.viewOpen = true
+        this.$nextTick(() => {
+          if (this.$refs.editForm) this.$refs.editForm.clearValidate()
+        })
+      })
+    },
+    /** 提交编辑租户 */
+    submitEdit() {
+      this.$refs['editForm'].validate(valid => {
+        if (!valid) return
+        this.editSubmitting = true
+        const data = {
+          id: this.viewForm.id,
+          tenantName: this.viewForm.tenantName,
+          contactName: this.viewForm.contactName,
+          contactPhone: this.viewForm.contactPhone,
+          expireTime: this.viewForm.expireTime,
+          status: this.viewForm.statusBool
+        }
+        updateTenant(data).then(() => {
+          this.$message.success('保存成功')
+          this.viewOpen = false
+          this.getList()
+        }).catch(() => {
+          this.$message.error('保存失败,请重试')
+        }).finally(() => {
+          this.editSubmitting = false
+        })
       })
     },
     /** 充值/扣款 */
     handleRecharge(row) {
       this.rechargeForm = {
-        companyId: row.companyId,
-        companyName: row.companyName,
+        companyId: row.id,
+        companyName: row.tenantName,
         currentBalance: row.balance || 0,
         operateType: 'recharge',
         amount: null,
         remark: ''
       }
-      this.rechargeTitle = `充值/扣款 - ${row.companyName}`
+      this.rechargeTitle = `充值/扣款 - ${row.tenantName}`
       this.rechargeOpen = true
     },
     submitRecharge() {
@@ -395,10 +453,10 @@ export default {
     },
     /** 禁用租户 */
     handleDisable(row) {
-      this.$confirm('确定禁用租户 [' + row.companyName + '] 吗?', '提示', {
+      this.$confirm('确定禁用租户 [' + row.tenantName + '] 吗?', '提示', {
         confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning'
       }).then(() => {
-        disableCompany(row.companyId).then(() => {
+        disableCompany(row.id).then(() => {
           this.$message.success('禁用成功')
           this.getList()
         })
@@ -406,10 +464,10 @@ export default {
     },
     /** 启用租户 */
     handleEnable(row) {
-      this.$confirm('确定启用租户 [' + row.companyName + '] 吗?', '提示', {
+      this.$confirm('确定启用租户 [' + row.tenantName + '] 吗?', '提示', {
         confirmButtonText: '确定', cancelButtonText: '取消', type: 'info'
       }).then(() => {
-        enableCompany(row.companyId).then(() => {
+        enableCompany(row.id).then(() => {
           this.$message.success('启用成功')
           this.getList()
         })
@@ -426,17 +484,17 @@ export default {
     handleEditMenu(row, flag) {
       this.menuDialog = {
         visible: true,
-        title: (flag === 'sys' ? '编辑管理端菜单 - ' : '编辑销售菜单 - ') + row.companyName,
+        title: (flag === 'sys' ? '编辑管理端菜单 - ' : '编辑销售菜单 - ') + row.tenantName,
         flag: flag,
-        companyId: row.companyId,
-        companyName: row.companyName,
+        companyId: row.id,
+        companyName: row.tenantName,
         treeData: [],
         checkedKeys: [],
         allMenuIds: [],
         loading: true,
         submitting: false
       }
-      getTenantMenuTree(row.companyId, flag).then(res => {
+      getTenantMenuTree(row.id, flag).then(res => {
         if (res.code === 200) {
           const menus = res.menus || []
           this.menuDialog.treeData = menus

+ 5 - 5
vue.config.js

@@ -49,9 +49,9 @@ module.exports = {
           '^/watch-api': '' // 将 /watch-api 替换为空
         }
       },
-      // 以下路径前缀代理到 fs-admin(8004) - 需要admin token验证的桥接接口
+      // 以下路径前缀代理到 fs-admin(8003) - 需要admin token验证的桥接接口
       [process.env.VUE_APP_BASE_API + '/company/companyOperLog']: {
-        target: 'http://localhost:8004',
+        target: 'http://localhost:8003',
         changeOrigin: true,
         pathRewrite: {
           ['^' + process.env.VUE_APP_BASE_API]: ''
@@ -130,7 +130,7 @@ module.exports = {
         }
       },
       [process.env.VUE_APP_BASE_API + '/workflow/lobster']: {
-        target: 'http://localhost:8004',
+        target: 'http://localhost:8003',
         changeOrigin: true,
         pathRewrite: {
           ['^' + process.env.VUE_APP_BASE_API]: ''
@@ -144,9 +144,9 @@ module.exports = {
         }
       },
       // detail: https://cli.vuejs.org/config/#devserver-proxy
-      // 默认所有其他请求代理到 fs-admin(8004) - 平台管理端
+      // 默认所有其他请求代理到 fs-admin(8003) - 平台管理端
       [process.env.VUE_APP_BASE_API]: {
-        target: `http://localhost:8004`,
+        target: `http://localhost:8003`,
         changeOrigin: true,
         pathRewrite: {
           ['^' + process.env.VUE_APP_BASE_API]: ''