Przeglądaj źródła

黑名单和拦截明细表

yuhongqi 19 godzin temu
rodzic
commit
c49515e6bb

+ 37 - 21
src/api/company/companyVoiceBlacklist.js

@@ -1,53 +1,69 @@
 import request from '@/utils/request'
 
-// 查询黑名单列表
+// 平台总后台:未选租户查主库平台级(11);选租户后通过 tenant-id 切租户库
 export function listCompanyVoiceBlacklist(query) {
   return request({
-    url: '/company/companyVoiceBlacklist/list',
+    url: '/admin/voice-blacklist/list',
     method: 'get',
     params: query
   })
 }
 
-// 查询黑名单详细
-export function getCompanyVoiceBlacklist(blacklistId) {
+export function getCompanyVoiceBlacklist(id, query) {
   return request({
-    url: '/company/companyVoiceBlacklist/' + blacklistId,
-    method: 'get'
+    url: '/admin/voice-blacklist/' + id,
+    method: 'get',
+    params: query || {}
   })
 }
 
-// 新增黑名单
-export function addCompanyVoiceBlacklist(data) {
+export function addCompanyVoiceBlacklist(data, query) {
   return request({
-    url: '/company/companyVoiceBlacklist',
+    url: '/admin/voice-blacklist',
     method: 'post',
-    data: data
+    data: data,
+    params: query || {}
   })
 }
 
-// 修改黑名单
-export function updateCompanyVoiceBlacklist(data) {
+export function updateCompanyVoiceBlacklist(data, query) {
   return request({
-    url: '/company/companyVoiceBlacklist',
+    url: '/admin/voice-blacklist',
     method: 'put',
-    data: data
+    data: data,
+    params: query || {}
   })
 }
 
-// 删除黑名单
-export function delCompanyVoiceBlacklist(blacklistId) {
+export function delCompanyVoiceBlacklist(ids, query) {
   return request({
-    url: '/company/companyVoiceBlacklist/' + blacklistId,
-    method: 'delete'
+    url: '/admin/voice-blacklist/' + ids,
+    method: 'delete',
+    params: query || {}
   })
 }
 
-// 导出黑名单
 export function exportCompanyVoiceBlacklist(query) {
   return request({
-    url: '/company/companyVoiceBlacklist/export',
+    url: '/admin/voice-blacklist/export',
     method: 'get',
     params: query
   })
-}
+}
+
+export function changeCompanyVoiceBlacklistStatus(data, query) {
+  return request({
+    url: '/admin/voice-blacklist/changeStatus',
+    method: 'put',
+    data: data,
+    params: query || {}
+  })
+}
+
+export function queryCompanyVoiceBlacklistPhone(id, query) {
+  return request({
+    url: '/admin/voice-blacklist/queryPhone/' + id,
+    method: 'get',
+    params: query || {}
+  })
+}

+ 34 - 0
src/api/company/companyVoiceBlacklistIntercept.js

@@ -0,0 +1,34 @@
+import request from '@/utils/request'
+
+// 平台总后台 -> fs-admin /admin/voice-blacklist-intercept(未选租户查主库,选租户切库)
+export function listCompanyVoiceBlacklistIntercept(query) {
+  return request({
+    url: '/admin/voice-blacklist-intercept/list',
+    method: 'get',
+    params: query
+  })
+}
+
+export function getCompanyVoiceBlacklistIntercept(id, query) {
+  return request({
+    url: '/admin/voice-blacklist-intercept/' + id,
+    method: 'get',
+    params: query || {}
+  })
+}
+
+export function exportCompanyVoiceBlacklistIntercept(query) {
+  return request({
+    url: '/admin/voice-blacklist-intercept/export',
+    method: 'get',
+    params: query
+  })
+}
+
+export function queryCompanyVoiceBlacklistInterceptPhone(id, query) {
+  return request({
+    url: '/admin/voice-blacklist-intercept/queryPhone/' + id,
+    method: 'get',
+    params: query || {}
+  })
+}

+ 50 - 51
src/api/company/companyVoiceRoboticCallBlacklist.js

@@ -1,70 +1,69 @@
 import request from '@/utils/request'
 
-// 查询外呼黑名单列表(admin专用,走 /admin/ 前缀,路由到 fs-admin 8004)
+// 未选租户查主库平台级;选租户后通过 tenant-id 切租户库
 export function listVoiceRoboticCallBlacklist(query) {
-    return request({
-        url: '/admin/voice-blacklist/list',
-        method: 'get',
-        params: query
-    })
+  return request({
+    url: '/admin/voice-blacklist/list',
+    method: 'get',
+    params: query
+  })
 }
 
-// 查询外呼黑名单详情
-export function getVoiceRoboticCallBlacklist(id) {
-    return request({
-        url: '/admin/voice-blacklist/' + id,
-        method: 'get'
-    })
+export function getVoiceRoboticCallBlacklist(id, query) {
+  return request({
+    url: '/admin/voice-blacklist/' + id,
+    method: 'get',
+    params: query || {}
+  })
 }
 
-// 新增外呼黑名单
-export function addVoiceRoboticCallBlacklist(data) {
-    return request({
-        url: '/admin/voice-blacklist',
-        method: 'post',
-        data: data
-    })
+export function addVoiceRoboticCallBlacklist(data, query) {
+  return request({
+    url: '/admin/voice-blacklist',
+    method: 'post',
+    data: data,
+    params: query || {}
+  })
 }
 
-// 修改外呼黑名单
-export function updateVoiceRoboticCallBlacklist(data) {
-    return request({
-        url: '/admin/voice-blacklist',
-        method: 'put',
-        data: data
-    })
+export function updateVoiceRoboticCallBlacklist(data, query) {
+  return request({
+    url: '/admin/voice-blacklist',
+    method: 'put',
+    data: data,
+    params: query || {}
+  })
 }
 
-// 删除外呼黑名单
-export function delVoiceRoboticCallBlacklist(id) {
-    return request({
-        url: '/admin/voice-blacklist/' + id,
-        method: 'delete'
-    })
+export function delVoiceRoboticCallBlacklist(ids, query) {
+  return request({
+    url: '/admin/voice-blacklist/' + ids,
+    method: 'delete',
+    params: query || {}
+  })
 }
 
-// 修改状态
-export function changeVoiceRoboticCallBlacklistStatus(data) {
-    return request({
-        url: '/admin/voice-blacklist/changeStatus',
-        method: 'put',
-        data: data
-    })
+export function changeVoiceRoboticCallBlacklistStatus(data, query) {
+  return request({
+    url: '/admin/voice-blacklist/changeStatus',
+    method: 'put',
+    data: data,
+    params: query || {}
+  })
 }
 
-// 查看解密手机号
-export function queryVoiceRoboticCallBlacklistPhone(blacklistId) {
-    return request({
-        url: '/admin/voice-blacklist/queryPhone/' + blacklistId,
-        method: 'get'
-    })
+export function queryVoiceRoboticCallBlacklistPhone(blacklistId, query) {
+  return request({
+    url: '/admin/voice-blacklist/queryPhone/' + blacklistId,
+    method: 'get',
+    params: query || {}
+  })
 }
 
-// 导出外呼黑名单
 export function exportVoiceRoboticCallBlacklist(query) {
-    return request({
-        url: '/admin/voice-blacklist/export',
-        method: 'get',
-        params: query
-    })
+  return request({
+    url: '/admin/voice-blacklist/export',
+    method: 'get',
+    params: query
+  })
 }

+ 160 - 69
src/views/admin/voiceBlacklist/index.vue

@@ -2,6 +2,13 @@
   <div class="app-container">
     <el-card shadow="never" class="mb16 filter-card">
       <el-form :model="queryParams" ref="queryForm" :inline="true" size="small">
+        <el-form-item label="租户">
+          <inline-tenant-selector
+            mode="admin"
+            :key="tenantSelectorKey"
+            @change="handleTenantChange"
+          />
+        </el-form-item>
         <el-form-item label="手机号" prop="phone">
           <el-input
             v-model="queryParams.phone"
@@ -10,19 +17,11 @@
             @keyup.enter.native="handleQuery"
           />
         </el-form-item>
-        <el-form-item label="租户名称" prop="companyName">
-          <el-input
-            v-model="queryParams.companyName"
-            placeholder="请输入租户名称"
-            clearable
-            @keyup.enter.native="handleQuery"
-          />
-        </el-form-item>
         <el-form-item label="黑名单级别" prop="businessType">
           <el-select v-model="queryParams.businessType" placeholder="请选择黑名单级别" clearable size="small" style="width: 160px">
-            <el-option label="平台封禁" value="11" />
-            <el-option label="租户级" value="12" />
-            <el-option label="线路级" value="13" />
+            <el-option v-if="!isTenantMode" label="平台封禁" value="11" />
+            <el-option v-if="isTenantMode" label="租户级" value="12" />
+            <el-option v-if="isTenantMode" label="线路级" value="13" />
           </el-select>
         </el-form-item>
         <el-form-item>
@@ -69,7 +68,14 @@
       <el-table-column type="selection" width="55" align="center" />
       <el-table-column label="手机号" align="center" prop="phone" min-width="200">
         <template slot-scope="scope">
-          <span>{{ scope.row.phone }}<el-button icon="el-icon-search" size="mini" @click="handlePhone(scope)" style="margin-left: 20px;" circle></el-button></span>
+          <span>{{ scope.row.phone || '-' }}</span>
+          <el-button
+            icon="el-icon-search"
+            size="mini"
+            circle
+            style="margin-left: 8px;"
+            @click="handlePhone(scope.row)"
+          />
         </template>
       </el-table-column>
       <el-table-column label="所属租户" align="center" prop="companyName" min-width="140" show-overflow-tooltip />
@@ -119,11 +125,21 @@
       @pagination="getList"
     />
 
-    <!-- 新增/编辑弹窗 -->
     <el-dialog :title="dialogTitle" :visible.sync="dialogOpen" width="500px" append-to-body>
       <el-form ref="editForm" :model="editForm" :rules="editRules" label-width="100px" size="small">
+        <el-form-item v-if="isTenantMode" label="黑名单级别" prop="businessType">
+          <el-select v-model="editForm.businessType" placeholder="请选择黑名单级别" style="width: 100%">
+            <el-option label="租户级" value="12" />
+            <el-option label="线路级" value="13" />
+          </el-select>
+        </el-form-item>
         <el-form-item label="手机号" prop="phone">
-          <el-input v-model="editForm.phone" placeholder="请输入手机号" maxlength="11" />
+          <el-input
+            v-model="editForm.phone"
+            :placeholder="editForm.blacklistId ? '不填写则不修改手机号' : '请输入手机号'"
+            maxlength="11"
+            clearable
+          />
         </el-form-item>
         <el-form-item label="状态" prop="status">
           <el-radio-group v-model="editForm.status">
@@ -154,9 +170,12 @@ import {
   queryVoiceRoboticCallBlacklistPhone,
   exportVoiceRoboticCallBlacklist
 } from '@/api/company/companyVoiceRoboticCallBlacklist'
+import { listCompanyOptions } from '@/api/admin/sysCompany'
+import InlineTenantSelector from '@/components/InlineTenantSelector'
 
 export default {
   name: 'AdminVoiceBlacklist',
+  components: { InlineTenantSelector },
   data() {
     return {
       loading: true,
@@ -164,59 +183,107 @@ export default {
       showSearch: true,
       total: 0,
       dataList: [],
-      // 选中数组
+      tenantOptions: [],
+      tenantSelectorKey: 0,
       ids: [],
-      // 非多个禁用
       multiple: true,
       queryParams: {
         pageNum: 1,
         pageSize: 10,
         phone: null,
-        companyName: null,
         businessType: null
       },
-      // 弹窗
       dialogOpen: false,
       dialogTitle: '',
       editForm: {
         blacklistId: null,
+        businessType: '11',
         phone: null,
         status: 1,
         remark: null
       },
       editRules: {
         phone: [
-          { required: true, message: '请输入手机号', trigger: 'blur' },
-          { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }
+          {
+            validator: (rule, value, callback) => {
+              if (!this.editForm.blacklistId && !value) {
+                callback(new Error('请输入手机号'))
+              } else if (value && !/^1[3-9]\d{9}$/.test(value)) {
+                callback(new Error('请输入正确的手机号'))
+              } else {
+                callback()
+              }
+            },
+            trigger: 'blur'
+          }
         ]
       }
     }
   },
+  computed: {
+    isTenantMode() {
+      return !!this.$tenantId
+    }
+  },
   created() {
+    this.loadTenantOptions()
     this.getList()
   },
   methods: {
+    loadTenantOptions() {
+      listCompanyOptions().then(response => {
+        this.tenantOptions = response.data || []
+      })
+    },
+    resolveTenantName(tenantId) {
+      if (tenantId == null) {
+        return '平台'
+      }
+      const tenant = this.tenantOptions.find(item => item.id === tenantId)
+      return tenant ? (tenant.tenantName || tenant.companyName || String(tenantId)) : String(tenantId)
+    },
+    mapRow(item) {
+      const companyName = this.isTenantMode
+        ? this.resolveTenantName(this.$tenantId)
+        : (item.companyId != null ? this.resolveTenantName(item.companyId) : '平台')
+      return {
+        ...item,
+        phone: item.targetValue,
+        blacklistId: item.id,
+        companyName
+      }
+    },
+    buildQueryParams() {
+      return this.$withTenant({
+        ...this.queryParams,
+        targetValue: this.queryParams.phone,
+        targetType: 1
+      })
+    },
     getList() {
       this.loading = true
-      listVoiceRoboticCallBlacklist({
-        ...this.queryParams,
-        targetValue: this.queryParams.phone
-      }).then(response => {
-        this.dataList = (response.rows || []).map(item => {
-          item.phone = item.targetValue
-          item.blacklistId = item.id
-          return item
-        })
-        this.total = response.total
+      listVoiceRoboticCallBlacklist(this.buildQueryParams()).then(response => {
+        this.dataList = (response.rows || []).map(item => this.mapRow(item))
+        this.total = response.total || 0
+        this.loading = false
+      }).catch(() => {
         this.loading = false
       })
     },
+    handleTenantChange() {
+      this.queryParams.pageNum = 1
+      this.queryParams.businessType = null
+      this.getList()
+    },
     handleQuery() {
       this.queryParams.pageNum = 1
       this.getList()
     },
     resetQuery() {
       this.resetForm('queryForm')
+      this.queryParams.businessType = null
+      this.$store.dispatch('tenant/setTenantId', null)
+      this.tenantSelectorKey++
       this.handleQuery()
     },
     handleSelectionChange(selection) {
@@ -225,74 +292,92 @@ export default {
     },
     handleAdd() {
       this.resetEditForm()
+      this.editForm.businessType = this.isTenantMode ? '12' : '11'
       this.dialogTitle = '新增黑名单'
       this.dialogOpen = true
     },
     handleUpdate(row) {
       this.resetEditForm()
       const id = row.blacklistId
-      getVoiceRoboticCallBlacklist(id).then(response => {
-        this.editForm = response.data
-        this.editForm.blacklistId = response.data.id
-        queryVoiceRoboticCallBlacklistPhone(id).then(res => {
-          this.editForm.phone = res.mobile
-        })
+      getVoiceRoboticCallBlacklist(id, this.$withTenant({})).then(response => {
+        const data = response.data || {}
+        this.editForm = {
+          blacklistId: data.id,
+          businessType: data.businessType || (this.isTenantMode ? '12' : '11'),
+          phone: null,
+          status: data.status != null ? data.status : 1,
+          remark: data.remark
+        }
         this.dialogTitle = '编辑黑名单'
         this.dialogOpen = true
       })
     },
     submitForm() {
-      this.$refs['editForm'].validate(valid => {
-        if (valid) {
-          const payload = {
-            ...this.editForm,
-            id: this.editForm.blacklistId,
-            targetValue: this.editForm.phone,
-            targetType: 1,
-            businessType: '11'
-          }
-          if (this.editForm.blacklistId) {
-            updateVoiceRoboticCallBlacklist(payload).then(response => {
-              this.$message.success('修改成功')
-              this.dialogOpen = false
-              this.getList()
-            })
-          } else {
-            addVoiceRoboticCallBlacklist(payload).then(response => {
-              this.$message.success('新增成功')
-              this.dialogOpen = false
-              this.getList()
-            })
-          }
+      this.$refs.editForm.validate(valid => {
+        if (!valid) {
+          return
+        }
+        const payload = {
+          id: this.editForm.blacklistId,
+          targetType: 1,
+          businessType: this.isTenantMode ? this.editForm.businessType : '11',
+          status: this.editForm.status,
+          remark: this.editForm.remark
+        }
+        if (this.editForm.phone) {
+          payload.targetValue = this.editForm.phone
+        } else if (!this.editForm.blacklistId) {
+          this.$message.error('手机号不能为空')
+          return
+        }
+        const tenantQuery = this.$withTenant({})
+        if (this.editForm.blacklistId) {
+          updateVoiceRoboticCallBlacklist(payload, tenantQuery).then(() => {
+            this.$message.success('修改成功')
+            this.dialogOpen = false
+            this.getList()
+          })
+        } else {
+          addVoiceRoboticCallBlacklist(payload, tenantQuery).then(() => {
+            this.$message.success('新增成功')
+            this.dialogOpen = false
+            this.getList()
+          })
         }
       })
     },
     handleDelete(row) {
-      const blacklistIds = row.blacklistId ? [row.blacklistId] : this.ids
+      const blacklistIds = row && row.blacklistId != null ? row.blacklistId : this.ids.join(',')
+      if (!blacklistIds) {
+        this.$message.warning('请选择要删除的数据')
+        return
+      }
       this.$confirm('是否确认删除选中的黑名单记录?', '警告', {
         confirmButtonText: '确定',
         cancelButtonText: '取消',
         type: 'warning'
       }).then(() => {
-        return delVoiceRoboticCallBlacklist(blacklistIds)
+        return delVoiceRoboticCallBlacklist(blacklistIds, this.$withTenant({}))
       }).then(() => {
         this.getList()
         this.$message.success('删除成功')
-      })
+      }).catch(() => {})
     },
     handleStatusChange(row) {
       changeVoiceRoboticCallBlacklistStatus({
         id: row.blacklistId,
         status: row.status
-      }).then(() => {
+      }, this.$withTenant({})).then(() => {
         this.$message.success('状态修改成功')
       }).catch(() => {
         row.status = row.status === 1 ? 0 : 1
       })
     },
     handleExport() {
-      const queryParams = { ...this.queryParams, targetValue: this.queryParams.phone }
-      this.$confirm('是否确认导出所有黑名单数据项?', '警告', {
+      const queryParams = this.buildQueryParams()
+      delete queryParams.pageNum
+      delete queryParams.pageSize
+      this.$confirm('是否确认导出当前筛选条件下的黑名单数据?', '警告', {
         confirmButtonText: '确定',
         cancelButtonText: '取消',
         type: 'warning'
@@ -306,21 +391,27 @@ export default {
         this.exportLoading = false
       })
     },
-    handlePhone(scope) {
-      queryVoiceRoboticCallBlacklistPhone(scope.row.blacklistId).then(res => {
-        scope.row.phone = res.mobile
+    handlePhone(row) {
+      queryVoiceRoboticCallBlacklistPhone(row.blacklistId, this.$withTenant({})).then(res => {
+        const mobile = (res && res.mobile) || (res && res.data && res.data.mobile)
+        if (mobile) {
+          this.$alert(mobile, '手机号', { confirmButtonText: '确定' })
+        } else {
+          this.$message.error((res && res.msg) || '获取手机号失败')
+        }
       })
     },
     resetEditForm() {
       this.editForm = {
         blacklistId: null,
+        businessType: this.isTenantMode ? '12' : '11',
         phone: null,
         status: 1,
         remark: null
       }
       this.$nextTick(() => {
-        if (this.$refs['editForm']) {
-          this.$refs['editForm'].clearValidate()
+        if (this.$refs.editForm) {
+          this.$refs.editForm.clearValidate()
         }
       })
     }

+ 304 - 156
src/views/company/companyVoiceBlacklist/index.vue

@@ -1,10 +1,30 @@
 <template>
   <div class="app-container">
-    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
-      <el-form-item label="手机号" prop="mobile">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="90px">
+      <el-form-item label="租户">
+        <inline-tenant-selector
+          mode="admin"
+          :key="tenantSelectorKey"
+          @change="handleTenantChange"
+        />
+      </el-form-item>
+      <el-form-item label="黑名单级别" prop="businessType">
+        <el-select
+          v-model="queryParams.businessType"
+          placeholder="请选择黑名单级别"
+          clearable
+          size="small"
+          style="width: 160px"
+        >
+          <el-option label="平台封禁" value="11" />
+          <el-option label="租户级" value="12" />
+          <el-option label="线路级" value="13" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="手机号" prop="targetValue">
         <el-input
-        style="width: 220px"
-          v-model="queryParams.mobile"
+          style="width: 220px"
+          v-model="queryParams.targetValue"
           placeholder="请输入手机号"
           clearable
           size="small"
@@ -12,13 +32,9 @@
         />
       </el-form-item>
       <el-form-item label="状态" prop="status">
-         <el-select style="width: 220px" v-model="queryParams.status" placeholder="请选择状态" clearable size="small">
-              <el-option
-                v-for="dict in statusOptions"
-                :key="dict.dictValue"
-                :label="dict.dictLabel"
-                :value="dict.dictValue"
-              />
+        <el-select style="width: 220px" v-model="queryParams.status" placeholder="请选择状态" clearable size="small">
+          <el-option label="生效" :value="1" />
+          <el-option label="失效" :value="0" />
         </el-select>
       </el-form-item>
       <el-form-item>
@@ -34,7 +50,7 @@
           icon="el-icon-plus"
           size="mini"
           @click="handleAdd"
-          v-hasPermi="['platform:companyVoiceBlacklist:add']"
+          v-hasPermi="['company:companyVoiceBlacklist:add']"
         >新增</el-button>
       </el-col>
       <el-col :span="1.5">
@@ -43,8 +59,8 @@
           icon="el-icon-edit"
           size="mini"
           :disabled="single"
-          @click="handleUpdate"
-          v-hasPermi="['platform:companyVoiceBlacklist:edit']"
+          @click="handleUpdate()"
+          v-hasPermi="['company:companyVoiceBlacklist:edit']"
         >修改</el-button>
       </el-col>
       <el-col :span="1.5">
@@ -53,8 +69,8 @@
           icon="el-icon-delete"
           size="mini"
           :disabled="multiple"
-          @click="handleDelete"
-          v-hasPermi="['platform:companyVoiceBlacklist:remove']"
+          @click="handleDelete()"
+          v-hasPermi="['company:companyVoiceBlacklist:remove']"
         >删除</el-button>
       </el-col>
       <el-col :span="1.5">
@@ -62,69 +78,110 @@
           type="warning"
           icon="el-icon-download"
           size="mini"
+          :loading="exportLoading"
           @click="handleExport"
-          v-hasPermi="['platform:companyVoiceBlacklist:export']"
+          v-hasPermi="['company:companyVoiceBlacklist:export']"
         >导出</el-button>
       </el-col>
-	  <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
 
-    <el-table  height="500" border v-loading="loading" :data="companyVoiceBlacklistList" @selection-change="handleSelectionChange">
+    <el-table
+      height="500"
+      border
+      v-loading="loading"
+      :data="companyVoiceBlacklistList"
+      @selection-change="handleSelectionChange"
+    >
       <el-table-column type="selection" width="55" align="center" />
-      <el-table-column label="ID" align="center" prop="blacklistId" />
-      <el-table-column label="手机号" align="center" prop="mobile" />
-      <el-table-column label="状态" align="center" prop="status" >
+      <el-table-column label="ID" align="center" prop="id" width="80" />
+      <el-table-column label="租户" align="center" prop="companyName" min-width="140" show-overflow-tooltip />
+      <el-table-column label="黑名单级别" align="center" prop="businessType" width="110">
         <template slot-scope="scope">
-              <el-tag prop="status" v-for="(item, index) in statusOptions"  :type="scope.row.status==1?'success':'danger'"  v-if="scope.row.status==item.dictValue">{{item.dictLabel}}</el-tag>
+          <span v-if="scope.row.businessType === '11'">平台封禁</span>
+          <span v-else-if="scope.row.businessType === '12'">租户级</span>
+          <span v-else-if="scope.row.businessType === '13'">线路级</span>
+          <span v-else>{{ scope.row.businessType || '-' }}</span>
         </template>
       </el-table-column>
-      <el-table-column label="创建时间" align="center" prop="createTime" />
-      <el-table-column label="更新时间" align="center" prop="updateTime" />
-      <el-table-column label="备注" align="center" prop="remark" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+      <el-table-column label="手机号" align="center" prop="targetValue" min-width="160" show-overflow-tooltip>
+        <template slot-scope="scope">
+          <span>{{ scope.row.targetValue || '-' }}</span>
+          <el-button
+            v-if="scope.row.targetType === 1 && scope.row.id"
+            type="text"
+            icon="el-icon-zoom-in"
+            size="mini"
+            style="margin-left: 8px"
+            @click="handlePhone(scope.row)"
+            v-hasPermi="['company:companyVoiceBlacklist:queryPhone']"
+          />
+        </template>
+      </el-table-column>
+      <el-table-column label="状态" align="center" prop="status" width="100">
+        <template slot-scope="scope">
+          <el-tag :type="scope.row.status === 1 ? 'success' : 'danger'" size="mini">
+            {{ scope.row.status === 1 ? '生效' : '失效' }}
+          </el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="创建人" align="center" prop="createBy" width="120" />
+      <el-table-column label="创建时间" align="center" prop="createTime" width="160" />
+      <el-table-column label="更新人" align="center" prop="updateBy" width="120" />
+      <el-table-column label="更新时间" align="center" prop="updateTime" width="160" />
+      <el-table-column label="备注" align="center" prop="remark" min-width="120" show-overflow-tooltip />
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="160">
         <template slot-scope="scope">
           <el-button
             size="mini"
             type="text"
             icon="el-icon-edit"
             @click="handleUpdate(scope.row)"
-            v-hasPermi="['platform:companyVoiceBlacklist:edit']"
+            v-hasPermi="['company:companyVoiceBlacklist:edit']"
           >修改</el-button>
           <el-button
             size="mini"
             type="text"
             icon="el-icon-delete"
             @click="handleDelete(scope.row)"
-            v-hasPermi="['platform:companyVoiceBlacklist:remove']"
+            v-hasPermi="['company:companyVoiceBlacklist:remove']"
           >删除</el-button>
         </template>
       </el-table-column>
     </el-table>
-    
+
     <pagination
-      v-show="total>0"
+      v-show="total > 0"
       :total="total"
       :page.sync="queryParams.pageNum"
       :limit.sync="queryParams.pageSize"
       @pagination="getList"
     />
 
-    <!-- 添加或修改黑名单对话框 -->
-    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
-      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
-        <el-form-item label="手机号" prop="mobile">
-          <el-input v-model="form.mobile" placeholder="请输入手机号" />
+    <el-dialog :title="title" :visible.sync="open" width="560px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="100px">
+        <el-form-item label="黑名单级别" prop="businessType">
+          <el-select v-model="form.businessType" placeholder="请选择黑名单级别" style="width: 100%">
+            <el-option v-if="!isTenantMode" label="平台封禁" value="11" />
+            <el-option v-if="isTenantMode" label="租户级" value="12" />
+            <el-option v-if="isTenantMode" label="线路级" value="13" />
+          </el-select>
         </el-form-item>
-        <!-- <el-form-item label="企业ID" prop="companyId">
-          <el-input v-model="form.companyId" placeholder="请输入企业ID" />
-        </el-form-item> -->
-        <el-form-item label="状态">
-           <el-radio-group v-model="form.status">
-            <el-radio v-for="dict in statusOptions" :label="dict.dictValue">{{dict.dictLabel}}</el-radio>
+        <el-form-item label="手机号" prop="targetValue">
+          <el-input
+            v-model="form.targetValue"
+            :placeholder="form.id ? '不填写则不修改手机号' : '请输入手机号'"
+            clearable
+          />
+        </el-form-item>
+        <el-form-item label="状态" prop="status">
+          <el-radio-group v-model="form.status">
+            <el-radio :label="1">生效</el-radio>
+            <el-radio :label="0">失效</el-radio>
           </el-radio-group>
         </el-form-item>
-        <el-form-item label="备注">
-            <el-input type="textarea" v-model="form.remark" placeholder="请输入备注" />
+        <el-form-item label="备注" prop="remark">
+          <el-input type="textarea" v-model="form.remark" placeholder="请输入备注" />
         </el-form-item>
       </el-form>
       <div slot="footer" class="dialog-footer">
@@ -136,167 +193,258 @@
 </template>
 
 <script>
-import { listCompanyVoiceBlacklist, getCompanyVoiceBlacklist, delCompanyVoiceBlacklist, addCompanyVoiceBlacklist, updateCompanyVoiceBlacklist, exportCompanyVoiceBlacklist } from "@/api/company/companyVoiceBlacklist";
+import {
+  listCompanyVoiceBlacklist,
+  getCompanyVoiceBlacklist,
+  delCompanyVoiceBlacklist,
+  addCompanyVoiceBlacklist,
+  updateCompanyVoiceBlacklist,
+  exportCompanyVoiceBlacklist,
+  queryCompanyVoiceBlacklistPhone
+} from '@/api/company/companyVoiceBlacklist'
+import { listCompanyOptions } from '@/api/admin/sysCompany'
+import InlineTenantSelector from '@/components/InlineTenantSelector'
 
 export default {
-  name: "CompanyVoiceBlacklist",
+  name: 'CompanyVoiceBlacklist',
+  components: { InlineTenantSelector },
   data() {
     return {
-      statusOptions:[],
-      // 遮罩层
+      tenantOptions: [],
+      tenantSelectorKey: 0,
       loading: true,
-      // 选中数组
+      exportLoading: false,
       ids: [],
-      // 非单个禁用
       single: true,
-      // 非多个禁用
       multiple: true,
-      // 显示搜索条件
       showSearch: true,
-      // 总条数
       total: 0,
-      // 黑名单表格数据
       companyVoiceBlacklistList: [],
-      // 弹出层标题
-      title: "",
-      // 是否显示弹出层
+      title: '',
       open: false,
-      // 查询参数
       queryParams: {
         pageNum: 1,
         pageSize: 10,
-        mobile: null,
-        companyId: null,
-        status: null,
+        businessType: null,
+        targetType: 1,
+        targetValue: null,
+        status: null
       },
-      // 表单参数
       form: {},
-      // 表单校验
       rules: {
-        mobile: [
-          { required: true, message: "手机号不能为空", trigger: "blur" }
-        ],
+        targetValue: [
+          {
+            validator: (rule, value, callback) => {
+              if (!this.form.id && !value) {
+                callback(new Error('手机号不能为空'))
+              } else {
+                callback()
+              }
+            },
+            trigger: 'blur'
+          }
+        ]
       }
-    };
+    }
+  },
+  computed: {
+    isTenantMode() {
+      return !!this.$tenantId
+    }
   },
   created() {
-    this.getDicts("sys_company_status").then((response) => {
-      this.statusOptions = response.data;
-    });
-    this.getList();
+    this.loadTenantOptions()
+    this.getList()
   },
   methods: {
-    /** 查询黑名单列表 */
+    loadTenantOptions() {
+      listCompanyOptions().then(response => {
+        this.tenantOptions = response.data || []
+      })
+    },
+    resolveTenantName(tenantId) {
+      if (tenantId == null) {
+        return this.isTenantMode ? this.resolveTenantName(this.$tenantId) : '平台'
+      }
+      const tenant = this.tenantOptions.find(item => item.id === tenantId)
+      return tenant ? (tenant.tenantName || tenant.companyName || String(tenantId)) : String(tenantId)
+    },
     getList() {
-      this.loading = true;
-      listCompanyVoiceBlacklist(this.queryParams).then(response => {
-        this.companyVoiceBlacklistList = response.rows;
-        this.total = response.total;
-        this.loading = false;
-      });
+      this.loading = true
+      listCompanyVoiceBlacklist(this.$withTenant({ ...this.queryParams })).then(response => {
+        const tenantName = this.isTenantMode ? this.resolveTenantName(this.$tenantId) : '平台'
+        this.companyVoiceBlacklistList = (response.rows || []).map(row => ({
+          ...row,
+          companyName: this.isTenantMode ? tenantName : (row.companyId != null ? this.resolveTenantName(row.companyId) : '平台')
+        }))
+        this.total = response.total || 0
+        this.loading = false
+      }).catch(() => {
+        this.loading = false
+      })
     },
-    // 取消按钮
     cancel() {
-      this.open = false;
-      this.reset();
+      this.open = false
+      this.reset()
     },
-    // 表单重置
     reset() {
       this.form = {
-        blacklistId: null,
-        mobile: null,
+        id: null,
         companyId: null,
-        status: "1",
-        remark: null,
-        createTime: null,
-        updateTime: null
-      };
-      this.resetForm("form");
+        businessType: this.isTenantMode ? '12' : '11',
+        targetType: 1,
+        targetValue: null,
+        status: 1,
+        remark: null
+      }
+      this.resetForm('form')
+    },
+    handleTenantChange() {
+      this.queryParams.pageNum = 1
+      this.queryParams.businessType = null
+      this.getList()
     },
-    /** 搜索按钮操作 */
     handleQuery() {
-      this.queryParams.pageNum = 1;
-      this.getList();
+      this.queryParams.pageNum = 1
+      this.getList()
     },
-    /** 重置按钮操作 */
     resetQuery() {
-      this.resetForm("queryForm");
-      this.handleQuery();
+      this.resetForm('queryForm')
+      this.queryParams.targetType = 1
+      this.queryParams.businessType = null
+      this.$store.dispatch('tenant/setTenantId', null)
+      this.tenantSelectorKey++
+      this.handleQuery()
     },
-    // 多选框选中数据
     handleSelectionChange(selection) {
-      this.ids = selection.map(item => item.blacklistId)
-      this.single = selection.length!==1
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length !== 1
       this.multiple = !selection.length
     },
-    /** 新增按钮操作 */
     handleAdd() {
-      this.reset();
-      this.open = true;
-      this.title = "添加黑名单";
+      this.reset()
+      this.form.businessType = this.isTenantMode ? '12' : '11'
+      this.open = true
+      this.title = '添加黑名单'
     },
-    /** 修改按钮操作 */
     handleUpdate(row) {
-      this.reset();
-      const blacklistId = row.blacklistId || this.ids
-      getCompanyVoiceBlacklist(blacklistId).then(response => {
-        this.form = response.data;
-        this.form.status = response.data.status.toString();
-        this.open = true;
-        this.title = "修改黑名单";
-      });
+      this.reset()
+      const id = row && row.id != null ? row.id : this.ids[0]
+      if (!id) {
+        this.msgWarning('请选择要修改的数据')
+        return
+      }
+      getCompanyVoiceBlacklist(id, this.$withTenant({})).then(response => {
+        const data = response.data || {}
+        this.form = {
+          id: data.id,
+          companyId: data.companyId,
+          businessType: data.businessType || '12',
+          targetType: data.targetType != null ? data.targetType : 1,
+          targetValue: null,
+          status: data.status != null ? data.status : 1,
+          remark: data.remark
+        }
+        this.open = true
+        this.title = '修改黑名单'
+      })
+    },
+    handleSubmitSuccess(msg) {
+      this.open = false
+      this.reset()
+      this.msgSuccess(msg)
+      this.getList()
     },
-    /** 提交按钮 */
     submitForm() {
-      this.$refs["form"].validate(valid => {
-        if (valid) {
-          if (this.form.blacklistId != null) {
-            updateCompanyVoiceBlacklist(this.form).then(response => {
-              if (response.code === 200) {
-                this.msgSuccess("修改成功");
-                this.open = false;
-                this.getList();
-              }
-            });
-          } else {
-            addCompanyVoiceBlacklist(this.form).then(response => {
-              if (response.code === 200) {
-                this.msgSuccess("新增成功");
-                this.open = false;
-                this.getList();
-              }
-            });
+      this.$refs.form.validate(valid => {
+        if (!valid) {
+          return
+        }
+        const payload = {
+          id: this.form.id,
+          companyId: this.form.companyId,
+          businessType: this.form.businessType || '12',
+          targetType: this.form.targetType != null ? this.form.targetType : 1,
+          status: this.form.status,
+          remark: this.form.remark
+        }
+        if (payload.businessType === '11') {
+          payload.companyId = null
+        }
+        if (this.form.targetValue) {
+          payload.targetValue = this.form.targetValue
+        }
+        if (payload.id != null) {
+          updateCompanyVoiceBlacklist(payload, this.$withTenant({})).then(res => {
+            if (!res || Number(res.code) === 200) {
+              this.handleSubmitSuccess((res && res.msg) || '修改成功')
+            } else {
+              this.msgError(res.msg || '修改失败')
+            }
+          })
+        } else {
+          if (!payload.targetValue) {
+            this.msgError('手机号不能为空')
+            return
           }
+          addCompanyVoiceBlacklist(payload, this.$withTenant({})).then(res => {
+            if (!res || Number(res.code) === 200) {
+              this.handleSubmitSuccess((res && res.msg) || '新增成功')
+            } else {
+              this.msgError(res.msg || '新增失败')
+            }
+          })
         }
-      });
+      })
     },
-    /** 删除按钮操作 */
     handleDelete(row) {
-      const blacklistIds = row.blacklistId || this.ids;
-      this.$confirm('是否确认删除黑名单编号为"' + blacklistIds + '"的数据项?', "警告", {
-          confirmButtonText: "确定",
-          cancelButtonText: "取消",
-          type: "warning"
-        }).then(function() {
-          return delCompanyVoiceBlacklist(blacklistIds);
-        }).then(() => {
-          this.getList();
-          this.msgSuccess("删除成功");
-        }).catch(function() {});
+      const ids = row && row.id != null ? row.id : this.ids.join(',')
+      if (!ids) {
+        this.msgWarning('请选择要删除的数据')
+        return
+      }
+      this.$confirm('是否确认删除黑名单编号为"' + ids + '"的数据项?', '警告', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        return delCompanyVoiceBlacklist(ids, this.$withTenant({}))
+      }).then(() => {
+        this.getList()
+        this.msgSuccess('删除成功')
+      }).catch(() => {})
     },
-    /** 导出按钮操作 */
     handleExport() {
-      const queryParams = this.queryParams;
-      this.$confirm('是否确认导出所有黑名单数据项?', "警告", {
-          confirmButtonText: "确定",
-          cancelButtonText: "取消",
-          type: "warning"
-        }).then(function() {
-          return exportCompanyVoiceBlacklist(queryParams);
-        }).then(response => {
-          this.download(response.msg);
-        }).catch(function() {});
+      this.$confirm('是否确认导出当前筛选条件下的黑名单数据?', '警告', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        this.exportLoading = true
+        const params = this.$withTenant({ ...this.queryParams })
+        delete params.pageNum
+        delete params.pageSize
+        return exportCompanyVoiceBlacklist(params)
+      }).then(response => {
+        this.download(response.msg)
+        this.exportLoading = false
+      }).catch(() => {
+        this.exportLoading = false
+      })
+    },
+    handlePhone(row) {
+      if (!row || !row.id) {
+        return
+      }
+      queryCompanyVoiceBlacklistPhone(row.id, this.$withTenant({})).then(res => {
+        const mobile = (res && res.mobile) || (res && res.data && res.data.mobile)
+        if (mobile) {
+          this.$alert(mobile, '手机号', { confirmButtonText: '确定' })
+        } else {
+          this.msgError((res && res.msg) || '获取手机号失败')
+        }
+      })
     }
   }
-};
+}
 </script>

+ 343 - 0
src/views/company/companyVoiceBlacklistIntercept/index.vue

@@ -0,0 +1,343 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="100px">
+      <el-form-item label="租户">
+        <inline-tenant-selector
+          mode="admin"
+          :key="tenantSelectorKey"
+          @change="handleTenantChange"
+        />
+      </el-form-item>
+      <el-form-item label="业务场景" prop="sceneCode">
+        <el-select v-model="queryParams.sceneCode" placeholder="请选择业务场景" clearable size="small" style="width: 160px">
+          <el-option label="外呼" value="CALL" />
+          <el-option label="短信" value="SMS" />
+          <el-option label="加微" value="ADD_WX" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="对象类型" prop="targetType">
+        <el-select v-model="queryParams.targetType" placeholder="请选择对象类型" clearable size="small" style="width: 160px">
+          <el-option label="手机号" :value="1" />
+          <el-option label="客户ID" :value="2" />
+          <el-option label="企微客户ID" :value="3" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="对象值" prop="targetValue">
+        <el-input
+          v-model="queryParams.targetValue"
+          placeholder="请输入手机号或对象值"
+          clearable
+          size="small"
+          style="width: 200px"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="黑名单ID" prop="blacklistId">
+        <el-input
+          v-model="queryParams.blacklistId"
+          placeholder="请输入黑名单ID"
+          clearable
+          size="small"
+          style="width: 140px"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="客户ID" prop="customerId">
+        <el-input
+          v-model="queryParams.customerId"
+          placeholder="请输入客户ID"
+          clearable
+          size="small"
+          style="width: 140px"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="外呼任务ID" prop="roboticId">
+        <el-input
+          v-model="queryParams.roboticId"
+          placeholder="请输入外呼任务ID"
+          clearable
+          size="small"
+          style="width: 140px"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="拦截时间">
+        <el-date-picker
+          v-model="dateRange"
+          size="small"
+          style="width: 240px"
+          value-format="yyyy-MM-dd"
+          type="daterange"
+          range-separator="-"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          icon="el-icon-download"
+          size="mini"
+          :loading="exportLoading"
+          @click="handleExport"
+          v-hasPermi="['company:companyVoiceBlacklistIntercept:export']"
+        >导出</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList" />
+    </el-row>
+
+    <el-table v-loading="loading" :data="list" border height="500">
+      <el-table-column label="ID" align="center" prop="id" width="80" />
+      <el-table-column label="租户" align="center" prop="companyName" min-width="140" show-overflow-tooltip />
+      <el-table-column label="业务场景" align="center" prop="sceneCode" width="100">
+        <template slot-scope="scope">
+          <span>{{ formatSceneCode(scope.row.sceneCode) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="黑名单ID" align="center" prop="blacklistId" width="100" />
+      <el-table-column label="对象类型" align="center" prop="targetType" width="110">
+        <template slot-scope="scope">
+          <span>{{ formatTargetType(scope.row.targetType) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="对象值" align="center" min-width="180">
+        <template slot-scope="scope">
+          <span>{{ scope.row.targetValue || '-' }}</span>
+          <el-button
+            v-if="canQueryPhone(scope.row)"
+            type="text"
+            icon="el-icon-zoom-in"
+            size="mini"
+            style="margin-left: 8px"
+            @click="handlePhone(scope.row)"
+            v-hasPermi="['company:companyVoiceBlacklistIntercept:queryPhone']"
+          />
+        </template>
+      </el-table-column>
+      <el-table-column label="拉黑原因" align="center" prop="blacklistReason" min-width="120" show-overflow-tooltip />
+      <el-table-column label="拦截说明" align="center" prop="interceptReason" min-width="140" show-overflow-tooltip />
+      <el-table-column label="客户ID" align="center" prop="customerId" width="100" />
+      <el-table-column label="被叫人ID" align="center" prop="calleeId" width="100" />
+      <el-table-column label="外呼任务ID" align="center" prop="roboticId" width="110" />
+      <el-table-column label="操作人ID" align="center" prop="companyUserId" width="100" />
+      <el-table-column label="业务ID" align="center" prop="bizId" min-width="120" show-overflow-tooltip />
+      <el-table-column label="请求IP" align="center" prop="requestIp" width="130" />
+      <el-table-column label="拦截时间" align="center" prop="createTime" width="160" />
+      <el-table-column label="备注" align="center" prop="remark" min-width="120" show-overflow-tooltip />
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="80">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-view"
+            @click="handleDetail(scope.row)"
+            v-hasPermi="['company:companyVoiceBlacklistIntercept:query']"
+          >详情</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total > 0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <el-dialog title="拦截明细详情" :visible.sync="detailOpen" width="640px" append-to-body>
+      <el-descriptions :column="2" border size="small">
+        <el-descriptions-item label="ID">{{ detail.id || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="租户">{{ detail.companyName || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="业务场景">{{ formatSceneCode(detail.sceneCode) }}</el-descriptions-item>
+        <el-descriptions-item label="黑名单ID">{{ detail.blacklistId || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="对象类型">{{ formatTargetType(detail.targetType) }}</el-descriptions-item>
+        <el-descriptions-item label="对象值">{{ detail.targetValue || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="拉黑原因" :span="2">{{ detail.blacklistReason || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="拦截说明" :span="2">{{ detail.interceptReason || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="客户ID">{{ detail.customerId || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="被叫人ID">{{ detail.calleeId || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="外呼任务ID">{{ detail.roboticId || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="操作人ID">{{ detail.companyUserId || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="业务ID">{{ detail.bizId || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="链路ID">{{ detail.bizTraceId || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="请求IP">{{ detail.requestIp || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="拦截时间">{{ detail.createTime || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="备注" :span="2">{{ detail.remark || '-' }}</el-descriptions-item>
+      </el-descriptions>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="detailOpen = false">关 闭</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import {
+  listCompanyVoiceBlacklistIntercept,
+  getCompanyVoiceBlacklistIntercept,
+  exportCompanyVoiceBlacklistIntercept,
+  queryCompanyVoiceBlacklistInterceptPhone
+} from '@/api/company/companyVoiceBlacklistIntercept'
+import { listCompanyOptions } from '@/api/admin/sysCompany'
+import InlineTenantSelector from '@/components/InlineTenantSelector'
+
+export default {
+  name: 'CompanyVoiceBlacklistIntercept',
+  components: { InlineTenantSelector },
+  data() {
+    return {
+      tenantOptions: [],
+      tenantSelectorKey: 0,
+      loading: true,
+      exportLoading: false,
+      showSearch: true,
+      total: 0,
+      list: [],
+      dateRange: [],
+      detailOpen: false,
+      detail: {},
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        sceneCode: null,
+        targetType: null,
+        targetValue: null,
+        blacklistId: null,
+        customerId: null,
+        roboticId: null,
+        beginTime: null,
+        endTime: null
+      }
+    }
+  },
+  computed: {
+    isTenantMode() {
+      return !!this.$tenantId
+    }
+  },
+  created() {
+    this.loadTenantOptions()
+    this.getList()
+  },
+  methods: {
+    loadTenantOptions() {
+      listCompanyOptions().then(response => {
+        this.tenantOptions = response.data || []
+      })
+    },
+    resolveTenantName(tenantId) {
+      if (tenantId == null) {
+        return '平台'
+      }
+      const tenant = this.tenantOptions.find(item => item.id === tenantId)
+      return tenant ? (tenant.tenantName || tenant.companyName || String(tenantId)) : String(tenantId)
+    },
+    formatSceneCode(code) {
+      const map = { CALL: '外呼', SMS: '短信', ADD_WX: '加微' }
+      return map[code] || code || '-'
+    },
+    formatTargetType(type) {
+      const map = { 1: '手机号', 2: '客户ID', 3: '企微客户ID' }
+      return map[type] || type || '-'
+    },
+    canQueryPhone(row) {
+      return row && row.id != null && Number(row.targetType) === 1
+    },
+    buildQueryParams() {
+      const params = { ...this.queryParams }
+      if (this.dateRange && this.dateRange.length === 2) {
+        params.beginTime = this.dateRange[0]
+        params.endTime = this.dateRange[1] + ' 23:59:59'
+      } else {
+        params.beginTime = null
+        params.endTime = null
+      }
+      return this.$withTenant(params)
+    },
+    mapRow(row) {
+      const companyName = this.isTenantMode
+        ? this.resolveTenantName(this.$tenantId)
+        : (row.companyId != null ? this.resolveTenantName(row.companyId) : '平台')
+      return { ...row, companyName }
+    },
+    getList() {
+      this.loading = true
+      listCompanyVoiceBlacklistIntercept(this.buildQueryParams()).then(response => {
+        this.list = (response.rows || []).map(row => this.mapRow(row))
+        this.total = response.total || 0
+        this.loading = false
+      }).catch(() => {
+        this.loading = false
+      })
+    },
+    handleTenantChange() {
+      this.queryParams.pageNum = 1
+      this.getList()
+    },
+    handleQuery() {
+      this.queryParams.pageNum = 1
+      this.getList()
+    },
+    resetQuery() {
+      this.dateRange = []
+      this.resetForm('queryForm')
+      this.queryParams.beginTime = null
+      this.queryParams.endTime = null
+      this.$store.dispatch('tenant/setTenantId', null)
+      this.tenantSelectorKey++
+      this.handleQuery()
+    },
+    handleDetail(row) {
+      if (!row || !row.id) return
+      getCompanyVoiceBlacklistIntercept(row.id, this.$withTenant({})).then(response => {
+        const data = response.data || {}
+        this.detail = {
+          ...data,
+          companyName: this.isTenantMode
+            ? this.resolveTenantName(this.$tenantId)
+            : this.resolveTenantName(data.companyId)
+        }
+        this.detailOpen = true
+      })
+    },
+    handleExport() {
+      this.$confirm('是否确认导出当前筛选条件下的拦截明细数据?', '警告', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        this.exportLoading = true
+        const data = this.buildQueryParams()
+        delete data.pageNum
+        delete data.pageSize
+        return exportCompanyVoiceBlacklistIntercept(data)
+      }).then(response => {
+        this.download(response.msg)
+        this.exportLoading = false
+      }).catch(() => {
+        this.exportLoading = false
+      })
+    },
+    handlePhone(row) {
+      if (!row || !row.id) return
+      queryCompanyVoiceBlacklistInterceptPhone(row.id, this.$withTenant({})).then(response => {
+        const mobile = (response && response.mobile) || (response && response.data && response.data.mobile)
+        if (mobile) {
+          this.$alert(mobile, '手机号', { confirmButtonText: '确定' })
+        } else {
+          this.msgError((response && response.msg) || '获取手机号失败')
+        }
+      })
+    }
+  }
+}
+</script>