lmx 3 天之前
父節點
當前提交
257c4db9ce
共有 2 個文件被更改,包括 307 次插入30 次删除
  1. 55 0
      src/api/admin/voiceSeat.js
  2. 252 30
      src/views/admin/voiceSeat/index.vue

+ 55 - 0
src/api/admin/voiceSeat.js

@@ -0,0 +1,55 @@
+import request from '@/utils/request'
+
+export function listVoiceSeat(query) {
+  return request({
+    url: '/admin/voiceSeat/list',
+    method: 'get',
+    params: query
+  })
+}
+
+export function getVoiceSeat(id) {
+  return request({
+    url: '/admin/voiceSeat/' + id,
+    method: 'get'
+  })
+}
+
+export function batchCreateVoiceSeat(data) {
+  return request({
+    url: '/admin/voiceSeat/batchCreate',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateVoiceSeatStatus(data) {
+  return request({
+    url: '/admin/voiceSeat/status',
+    method: 'put',
+    data: data
+  })
+}
+
+export function batchUpdateVoiceSeatStatus(data) {
+  return request({
+    url: '/admin/voiceSeat/batchStatus',
+    method: 'put',
+    data: data
+  })
+}
+
+export function delVoiceSeat(ids) {
+  return request({
+    url: '/admin/voiceSeat/' + ids,
+    method: 'delete'
+  })
+}
+
+export function exportVoiceSeat(query) {
+  return request({
+    url: '/admin/voiceSeat/export',
+    method: 'get',
+    params: query
+  })
+}

+ 252 - 30
src/views/admin/voiceSeat/index.vue

@@ -10,6 +10,20 @@
             @keyup.enter.native="handleQuery"
           />
         </el-form-item>
+        <el-form-item label="分机号码" prop="extensionNum">
+          <el-input
+            v-model="queryParams.extensionNum"
+            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">
+            <el-option label="可用" :value="1" />
+            <el-option label="停用" :value="0" />
+          </el-select>
+        </el-form-item>
         <el-form-item>
           <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
           <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@@ -18,6 +32,18 @@
     </el-card>
 
     <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleCreate">创建分机</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button type="success" plain icon="el-icon-open" size="mini" :disabled="!selectedRows.length" @click="handleBatchStatus(1)">批量启用</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button type="info" plain icon="el-icon-turn-off" size="mini" :disabled="!selectedRows.length" @click="handleBatchStatus(0)">批量停用</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="!selectedRows.length" @click="handleBatchDelete">批量删除</el-button>
+      </el-col>
       <el-col :span="1.5">
         <el-button
           type="warning"
@@ -28,22 +54,40 @@
           @click="handleExport"
         >导出</el-button>
       </el-col>
+      <el-col :span="1.5" v-if="selectedRows.length">
+        <span class="selected-tip">已选 {{ selectedRows.length }} 条</span>
+      </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
 
-    <el-table v-loading="loading" :data="dataList" border size="small" style="width:100%">
-      <el-table-column label="坐席ID" align="center" prop="callerId" width="80" />
-      <el-table-column label="所属租户" align="center" prop="companyName" min-width="140" show-overflow-tooltip />
-      <el-table-column label="坐席号码" align="center" prop="callerNumber" min-width="140" />
-      <el-table-column label="坐席名称" align="center" prop="callerName" min-width="120" show-overflow-tooltip />
-      <el-table-column label="状态" align="center" prop="status" width="100">
+    <el-table
+      v-loading="loading"
+      :data="dataList"
+      border
+      size="small"
+      class="voice-seat-table"
+      style="width:100%"
+      @selection-change="handleSelectionChange"
+    >
+      <el-table-column type="selection" width="45" align="center" />
+      <el-table-column label="ID" align="center" prop="id" width="70" />
+      <el-table-column label="所属租户" align="center" prop="tenantName" min-width="120" show-overflow-tooltip />
+      <el-table-column label="分机号码" align="center" prop="extensionNum" width="110" />
+      <el-table-column label="绑定标识" align="center" prop="userCode" min-width="130" show-overflow-tooltip />
+      <el-table-column label="状态" align="center" prop="status" width="130" class-name="status-column">
         <template slot-scope="scope">
-          <el-tag v-if="scope.row.status === 0 || scope.row.status === '0'" type="danger">禁用</el-tag>
-          <el-tag v-else type="success">启用</el-tag>
+          <el-switch
+            v-model="scope.row.status"
+            :active-value="1"
+            :inactive-value="0"
+            active-text="可用"
+            inactive-text="停用"
+            @change="handleStatusChange(scope.row)"
+          />
         </template>
       </el-table-column>
-      <el-table-column label="绑定时间" align="center" prop="bindTime" width="160" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="120">
+      <el-table-column label="创建时间" align="center" prop="createTime" width="155" />
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="90">
         <template slot-scope="scope">
           <el-button
             size="mini"
@@ -63,39 +107,85 @@
       @pagination="getList"
     />
 
+    <!-- 创建分机弹窗 -->
+    <el-dialog title="创建租户分机" :visible.sync="createOpen" width="480px" append-to-body @close="resetCreateForm">
+      <el-form ref="createForm" :model="createForm" :rules="createRules" label-width="100px" size="small">
+        <el-form-item label="租户" prop="tenantId">
+          <el-select
+            v-model="createForm.tenantId"
+            placeholder="输入租户名称搜索"
+            clearable
+            filterable
+            remote
+            reserve-keyword
+            :remote-method="searchTenants"
+            :loading="tenantSearchLoading"
+            style="width:100%"
+          >
+            <el-option
+              v-for="item in tenantOptions"
+              :key="item.tenantId"
+              :label="formatTenantOption(item)"
+              :value="item.tenantId"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="生成数量" prop="createNum">
+          <el-input-number v-model="createForm.createNum" :min="1" :max="500" controls-position="right" style="width:100%" />
+        </el-form-item>
+        <el-form-item label="分机密码" prop="password">
+          <el-input v-model="createForm.password" placeholder="默认 123456" maxlength="32" show-password />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="createOpen = false">取 消</el-button>
+        <el-button type="primary" :loading="createLoading" @click="submitCreate">确 定</el-button>
+      </div>
+    </el-dialog>
+
     <!-- 详情弹窗 -->
-    <el-dialog title="坐席详情" :visible.sync="detailOpen" width="600px" append-to-body>
+    <el-dialog title="分机详情" :visible.sync="detailOpen" width="600px" append-to-body>
       <el-form :model="detailForm" label-width="100px" size="small">
         <el-row :gutter="20">
           <el-col :span="12">
-            <el-form-item label="坐席ID">
-              <span>{{ detailForm.callerId }}</span>
+            <el-form-item label="ID">
+              <span>{{ detailForm.id }}</span>
             </el-form-item>
           </el-col>
           <el-col :span="12">
             <el-form-item label="所属租户">
-              <span>{{ detailForm.companyName }}</span>
+              <span>{{ detailForm.tenantName }}</span>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="分机号码">
+              <span>{{ detailForm.extensionNum }}</span>
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item label="坐席号码">
-              <span>{{ detailForm.callerNumber }}</span>
+            <el-form-item label="分机密码">
+              <span>{{ detailForm.extensionPass || '-' }}</span>
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item label="坐席名称">
-              <span>{{ detailForm.callerName }}</span>
+            <el-form-item label="流水编号">
+              <span>{{ detailForm.extId || '-' }}</span>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="绑定标识">
+              <span>{{ detailForm.userCode || '-' }}</span>
             </el-form-item>
           </el-col>
           <el-col :span="12">
             <el-form-item label="状态">
-              <el-tag v-if="detailForm.status === 0 || detailForm.status === '0'" type="danger">禁用</el-tag>
-              <el-tag v-else type="success">启用</el-tag>
+              <el-tag v-if="detailForm.status === 0 || detailForm.status === '0'" type="danger">用</el-tag>
+              <el-tag v-else type="success">用</el-tag>
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item label="绑定时间">
-              <span>{{ detailForm.bindTime }}</span>
+            <el-form-item label="创建时间">
+              <span>{{ detailForm.createTime || '-' }}</span>
             </el-form-item>
           </el-col>
           <el-col :span="24">
@@ -110,7 +200,16 @@
 </template>
 
 <script>
-import { listCompanyVoiceCaller, getCompanyVoiceCaller, exportCompanyVoiceCaller } from '@/api/company/companyVoiceCaller'
+import {
+  listVoiceSeat,
+  getVoiceSeat,
+  batchCreateVoiceSeat,
+  updateVoiceSeatStatus,
+  batchUpdateVoiceSeatStatus,
+  delVoiceSeat,
+  exportVoiceSeat
+} from '@/api/admin/voiceSeat'
+import { listAdminTenantList } from '@/api/admin/sysCompany'
 
 export default {
   name: 'AdminVoiceSeat',
@@ -118,13 +217,29 @@ export default {
     return {
       loading: true,
       exportLoading: false,
+      createLoading: false,
+      tenantSearchLoading: false,
       showSearch: true,
       total: 0,
       dataList: [],
+      selectedRows: [],
+      tenantOptions: [],
       queryParams: {
         pageNum: 1,
         pageSize: 10,
-        companyName: null
+        companyName: null,
+        extensionNum: null,
+        status: null
+      },
+      createOpen: false,
+      createForm: {
+        tenantId: null,
+        createNum: 1,
+        password: '123456'
+      },
+      createRules: {
+        tenantId: [{ required: true, message: '请选择租户', trigger: 'change' }],
+        createNum: [{ required: true, message: '请输入生成数量', trigger: 'blur' }]
       },
       detailOpen: false,
       detailForm: {}
@@ -136,9 +251,11 @@ export default {
   methods: {
     getList() {
       this.loading = true
-      listCompanyVoiceCaller(this.queryParams).then(response => {
-        this.dataList = response.rows
-        this.total = response.total
+      listVoiceSeat(this.queryParams).then(response => {
+        this.dataList = response.rows || []
+        this.total = response.total || 0
+        this.loading = false
+      }).catch(() => {
         this.loading = false
       })
     },
@@ -150,15 +267,105 @@ export default {
       this.resetForm('queryForm')
       this.handleQuery()
     },
+    handleSelectionChange(selection) {
+      this.selectedRows = selection
+    },
+    formatTenantOption(item) {
+      const name = item.companyName || item.tenantName || ''
+      const code = item.tenantCode ? ` (${item.tenantCode})` : ''
+      return name + code
+    },
+    searchTenants(query) {
+      this.tenantSearchLoading = true
+      listAdminTenantList({
+        pageNum: 1,
+        pageSize: 20,
+        tenantName: query || undefined,
+        status: 1
+      }).then(res => {
+        const rows = res.rows || res.data || []
+        this.tenantOptions = rows.map(item => ({
+          tenantId: item.companyId || item.id,
+          companyName: item.companyName || item.tenantName,
+          tenantCode: item.tenantCode
+        }))
+        this.tenantSearchLoading = false
+      }).catch(() => {
+        this.tenantSearchLoading = false
+      })
+    },
+    handleCreate() {
+      this.createOpen = true
+      this.searchTenants('')
+    },
+    resetCreateForm() {
+      this.createForm = {
+        tenantId: null,
+        createNum: 1,
+        password: '123456'
+      }
+      if (this.$refs.createForm) {
+        this.$refs.createForm.resetFields()
+      }
+    },
+    submitCreate() {
+      this.$refs.createForm.validate(valid => {
+        if (!valid) return
+        this.createLoading = true
+        batchCreateVoiceSeat(this.createForm).then(res => {
+          this.msgSuccess(res.msg || '创建成功')
+          this.createOpen = false
+          this.getList()
+        }).finally(() => {
+          this.createLoading = false
+        })
+      })
+    },
     handleDetail(row) {
-      getCompanyVoiceCaller(row.callerId).then(response => {
-        this.detailForm = response.data
+      getVoiceSeat(row.id).then(response => {
+        this.detailForm = response.data || {}
         this.detailOpen = true
       })
     },
+    handleStatusChange(row) {
+      const text = row.status === 1 ? '启用' : '停用'
+      const prevStatus = row.status === 1 ? 0 : 1
+      this.$confirm('确认要' + text + '分机 "' + row.extensionNum + '" 吗?', '提示', {
+        type: 'warning'
+      }).then(() => {
+        return updateVoiceSeatStatus({ id: row.id, status: row.status })
+      }).then(() => {
+        this.msgSuccess(text + '成功')
+      }).catch(() => {
+        row.status = prevStatus
+      })
+    },
+    handleBatchStatus(status) {
+      const ids = this.selectedRows.map(item => item.id)
+      const text = status === 1 ? '启用' : '停用'
+      this.$confirm('确认要批量' + text + '选中的 ' + ids.length + ' 条分机吗?', '提示', {
+        type: 'warning'
+      }).then(() => {
+        return batchUpdateVoiceSeatStatus({ ids, status })
+      }).then(() => {
+        this.msgSuccess('批量' + text + '成功')
+        this.getList()
+      }).catch(() => {})
+    },
+    handleBatchDelete() {
+      const ids = this.selectedRows.map(item => item.id)
+      this.$confirm('确认要删除选中的 ' + ids.length + ' 条分机吗?', '提示', {
+        type: 'warning'
+      }).then(() => {
+        return delVoiceSeat(ids.join(','))
+      }).then(() => {
+        this.msgSuccess('删除成功')
+        this.getList()
+      }).catch(() => {})
+    },
     handleExport() {
       this.exportLoading = true
-      exportCompanyVoiceCaller(this.queryParams).then(response => {
+      exportVoiceSeat(this.queryParams).then(response => {
         this.download(response.msg)
         this.exportLoading = false
       }).catch(() => {
@@ -173,4 +380,19 @@ export default {
 .mb8 { margin-bottom: 8px; }
 .mb16 { margin-bottom: 16px; }
 .filter-card { padding-bottom: 0; }
+.selected-tip {
+  display: inline-block;
+  line-height: 28px;
+  font-size: 13px;
+  color: #909399;
+}
+.voice-seat-table >>> .status-column .cell {
+  overflow: visible;
+  white-space: nowrap;
+  padding-left: 6px;
+  padding-right: 6px;
+}
+.voice-seat-table >>> .status-column .el-switch {
+  vertical-align: middle;
+}
 </style>