Procházet zdrojové kódy

黑名单和黑名单拦截明细

yuhongqi před 5 dny
rodič
revize
b4e07da5d2

+ 26 - 7
src/api/company/companyVoiceBlacklist.js

@@ -1,6 +1,6 @@
 import request from '@/utils/request'
 
-// 查询黑名单管理列表
+// 租户总后台 → fs-admin-saas /company/companyVoiceBlacklist(租户级12 + 线路级13)
 export function listApi(query) {
   return request({
     url: '/company/companyVoiceBlacklist/list',
@@ -9,7 +9,6 @@ export function listApi(query) {
   })
 }
 
-// 查询黑名单管理详细
 export function getApi(id) {
   return request({
     url: '/company/companyVoiceBlacklist/' + id,
@@ -17,7 +16,6 @@ export function getApi(id) {
   })
 }
 
-// 新增黑名单管理
 export function addApi(data) {
   return request({
     url: '/company/companyVoiceBlacklist',
@@ -26,7 +24,6 @@ export function addApi(data) {
   })
 }
 
-// 修改黑名单管理
 export function updateApi(data) {
   return request({
     url: '/company/companyVoiceBlacklist',
@@ -35,10 +32,32 @@ export function updateApi(data) {
   })
 }
 
-// 删除黑名单管理
-export function delApi(id) {
+export function delApi(ids) {
   return request({
-    url: '/company/companyVoiceBlacklist/' + id,
+    url: '/company/companyVoiceBlacklist/' + ids,
     method: 'delete'
   })
 }
+
+export function exportApi(data) {
+  return request({
+    url: '/company/companyVoiceBlacklist/export',
+    method: 'post',
+    data: data
+  })
+}
+
+export function changeStatusApi(data) {
+  return request({
+    url: '/company/companyVoiceBlacklist/changeStatus',
+    method: 'put',
+    data: data
+  })
+}
+
+export function queryPhoneApi(id) {
+  return request({
+    url: '/company/companyVoiceBlacklist/queryPhone/' + id,
+    method: 'get'
+  })
+}

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

@@ -0,0 +1,32 @@
+import request from '@/utils/request'
+
+// 租户总后台 -> fs-admin-saas /company/companyVoiceBlacklistIntercept
+export function listApi(query) {
+  return request({
+    url: '/company/companyVoiceBlacklistIntercept/list',
+    method: 'get',
+    params: query
+  })
+}
+
+export function getApi(id) {
+  return request({
+    url: '/company/companyVoiceBlacklistIntercept/' + id,
+    method: 'get'
+  })
+}
+
+export function exportApi(data) {
+  return request({
+    url: '/company/companyVoiceBlacklistIntercept/export',
+    method: 'post',
+    data: data
+  })
+}
+
+export function queryPhoneApi(id) {
+  return request({
+    url: '/company/companyVoiceBlacklistIntercept/queryPhone/' + id,
+    method: 'get'
+  })
+}

+ 356 - 29
src/views/company/companyVoiceBlacklist/index.vue

@@ -1,59 +1,235 @@
 <template>
   <div class="app-container">
-    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="100px">
-      <el-form-item label="关键词" prop="keyword">
-        <el-input v-model="queryParams.keyword" placeholder="请输入关键词" clearable size="small"
-          @keyup.enter.native="handleQuery" />
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="90px">
+<!--      <el-form-item label="黑名单级别" prop="businessType">-->
+<!--        <el-select-->
+<!--          v-model="queryParams.businessType"-->
+<!--          placeholder="全部(租户级+线路级)"-->
+<!--          clearable-->
+<!--          size="small"-->
+<!--          style="width: 180px"-->
+<!--        >-->
+<!--          <el-option label="租户级" value="12" />-->
+<!--          <el-option label="线路级" value="13" />-->
+<!--        </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="状态" prop="status">
+        <el-select v-model="queryParams.status" placeholder="请选择状态" clearable size="small" style="width: 140px">
+          <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>
       </el-form-item>
     </el-form>
+
     <el-row :gutter="10" class="mb8">
-      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['company:companyVoiceBlacklist:add']"
+        >新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate()"
+          v-hasPermi="['company:companyVoiceBlacklist:edit']"
+        >修改</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete()"
+          v-hasPermi="['company:companyVoiceBlacklist:remove']"
+        >删除</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          icon="el-icon-download"
+          size="mini"
+          :loading="exportLoading"
+          @click="handleExport"
+          v-hasPermi="['company:companyVoiceBlacklist:export']"
+        >导出</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList" />
     </el-row>
-    <el-table v-loading="loading" :data="list">
+
+    <el-table v-loading="loading" :data="list" border height="500" @selection-change="handleSelectionChange">
       <el-table-column type="selection" width="50" align="center" />
       <el-table-column label="ID" align="center" prop="id" width="80" />
-      <el-table-column label="黑名单号码" align="center" prop="phone" width="140" />
-      <el-table-column label="黑名单类型" align="center" prop="blacklistType" width="120" />
-      <el-table-column label="原因" align="center" prop="reason" />
-      <el-table-column label="状态" align="center" prop="status" width="80">
+<!--      <el-table-column label="黑名单级别" align="center" prop="businessType" width="100">-->
+<!--        <template slot-scope="scope">-->
+<!--          <span v-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" min-width="180">
         <template slot-scope="scope">
-          <el-tag :type="scope.row.status==='0'?'success':'danger'" size="small">{{ scope.row.status==='0'?'启用':'停用' }}</el-tag>
+          <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:companyVoiceBlacklist:queryPhone']"
+          />
         </template>
       </el-table-column>
+      <el-table-column label="拉黑原因" align="center" prop="reason" min-width="120" show-overflow-tooltip />
+      <el-table-column label="状态" align="center" prop="status" width="90">
+        <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="remark" min-width="120" show-overflow-tooltip />
+      <el-table-column label="创建人" align="center" prop="createBy" width="100" />
       <el-table-column label="创建时间" align="center" prop="createTime" width="160" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
+      <el-table-column label="更新人" align="center" prop="updateBy" width="100" />
+      <el-table-column label="更新时间" align="center" prop="updateTime" width="160" />
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="150">
         <template slot-scope="scope">
-          <el-button size="mini" type="text" icon="el-icon-view" @click="handleDetail(scope.row)"
-            v-hasPermi="['company:companyVoiceBlacklist:query']">详情</el-button>
-          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
-            v-hasPermi="['company:companyVoiceBlacklist:remove']">删除</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['company:companyVoiceBlacklist:edit']"
+          >修改</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['company:companyVoiceBlacklist:remove']"
+          >删除</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" />
+
+    <pagination
+      v-show="total > 0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <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 label="租户级" value="12" />-->
+<!--            <el-option label="线路级" value="13" />-->
+<!--          </el-select>-->
+<!--        </el-form-item>-->
+        <el-form-item label="手机号" prop="targetValue">
+          <el-input
+            v-model="form.targetValue"
+            :placeholder="form.id ? '不填写则不修改手机号' : '请输入手机号'"
+            clearable
+          />
+        </el-form-item>
+        <el-form-item label="拉黑原因" prop="reason">
+          <el-input v-model="form.reason" type="textarea" :rows="2" placeholder="请输入拉黑原因" />
+        </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="备注" prop="remark">
+          <el-input v-model="form.remark" type="textarea" :rows="2" placeholder="请输入备注" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
-import { listApi, delApi } from '@/api/company/companyVoiceBlacklist'
+import {
+  listApi,
+  getApi,
+  addApi,
+  updateApi,
+  delApi,
+  exportApi,
+  queryPhoneApi
+} from '@/api/company/companyVoiceBlacklist'
 
 export default {
   name: 'CompanyVoiceBlacklist',
   data() {
     return {
       loading: true,
+      exportLoading: false,
       showSearch: true,
       total: 0,
       list: [],
+      ids: [],
+      single: true,
+      multiple: true,
+      title: '',
+      open: false,
       queryParams: {
         pageNum: 1,
         pageSize: 10,
-        keyword: null
+        businessType: null,
+        targetType: 1,
+        targetValue: null,
+        status: null
+      },
+      form: {},
+      rules: {
+        // businessType: [
+        //   { required: true, message: '请选择黑名单级别', trigger: 'change' }
+        // ],
+        targetValue: [
+          {
+            validator: (rule, value, callback) => {
+              if (!this.isEditForm() && !this.normalizeTargetValue(value)) {
+                callback(new Error('手机号不能为空'))
+              } else {
+                callback()
+              }
+            },
+            trigger: ['blur', 'change']
+          }
+        ]
       }
     }
   },
@@ -61,13 +237,37 @@ export default {
     this.getList()
   },
   methods: {
+    isEditForm() {
+      return this.form.id !== undefined && this.form.id !== null && this.form.id !== ''
+    },
+    normalizeTargetValue(value) {
+      if (value == null) return ''
+      return String(value).trim()
+    },
+    canQueryPhone(row) {
+      return row && row.id != null && Number(row.targetType) !== 2 && Number(row.targetType) !== 3
+    },
     getList() {
       this.loading = true
       listApi(this.queryParams).then(res => {
-        this.list = res.rows || (res.data && res.data.list) || []
-        this.total = res.total || (res.data && res.data.total) || 0
+        this.list = res.rows || []
+        this.total = res.total || 0
+        this.loading = false
+      }).catch(() => {
         this.loading = false
-      }).catch(() => { this.loading = false })
+      })
+    },
+    reset() {
+      this.form = {
+        id: null,
+        businessType: '12',
+        targetType: 1,
+        targetValue: null,
+        reason: null,
+        status: 1,
+        remark: null
+      }
+      this.resetForm('form')
     },
     handleQuery() {
       this.queryParams.pageNum = 1
@@ -75,18 +275,145 @@ export default {
     },
     resetQuery() {
       this.resetForm('queryForm')
+      this.queryParams.targetType = 1
       this.handleQuery()
     },
-    handleDetail(row) {
-      this.$message.info('详情功能开发中')
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length !== 1
+      this.multiple = !selection.length
+    },
+    handleAdd() {
+      this.reset()
+      this.open = true
+      this.title = '新增黑名单'
+    },
+    handleUpdate(row) {
+      this.reset()
+      const id = row && row.id != null ? row.id : this.ids[0]
+      if (!id) {
+        this.$message.warning('请选择要修改的数据')
+        return
+      }
+      getApi(id).then(res => {
+        const data = res.data || {}
+        this.form = {
+          id: data.id,
+          businessType: data.businessType || '12',
+          targetType: 1,
+          targetValue: null,
+          reason: data.reason,
+          status: data.status != null ? data.status : 1,
+          remark: data.remark
+        }
+        this.open = true
+        this.title = '修改黑名单'
+      })
+    },
+    cancel() {
+      this.open = false
+      this.reset()
+    },
+    handleSubmitSuccess(msg) {
+      this.msgSuccess(msg || '操作成功')
+      this.open = false
+      this.reset()
+      this.getList()
+    },
+    handleSubmitError(response) {
+      const msg = (response && response.msg) || '操作失败'
+      this.msgError(msg)
+    },
+    submitForm() {
+      this.$refs.form.validate(valid => {
+        if (!valid) return
+        const payload = {
+          id: this.form.id,
+          businessType: this.form.businessType,
+          targetType: 1,
+          status: this.form.status,
+          reason: this.form.reason,
+          remark: this.form.remark
+        }
+        const targetValue = this.normalizeTargetValue(this.form.targetValue)
+        if (this.isEditForm()) {
+          if (targetValue) {
+            payload.targetValue = targetValue
+          } else {
+            delete payload.targetValue
+          }
+          updateApi(payload).then(response => {
+            if (response && response.code === 200) {
+              this.handleSubmitSuccess(response.msg)
+            } else {
+              this.handleSubmitError(response)
+            }
+          }).catch(() => {})
+        } else {
+          if (!targetValue) {
+            this.msgError('手机号不能为空')
+            return
+          }
+          payload.targetValue = targetValue
+          addApi(payload).then(response => {
+            if (response && response.code === 200) {
+              this.handleSubmitSuccess(response.msg)
+            } else {
+              this.handleSubmitError(response)
+            }
+          }).catch(() => {})
+        }
+      })
     },
     handleDelete(row) {
-      this.$modal.confirm('是否确认删除?').then(() => {
-        return delApi(row.id)
+      const ids = row && row.id != null ? row.id : this.ids.join(',')
+      if (!ids) {
+        this.$message.warning('请选择要删除的数据')
+        return
+      }
+      this.$confirm('是否确认删除黑名单编号为"' + ids + '"的数据项?', '警告', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
       }).then(() => {
-        this.getList()
-        this.$modal.msgSuccess('删除成功')
+        return delApi(ids)
+      }).then(response => {
+        if (response && response.code === 200) {
+          this.getList()
+          this.msgSuccess(response.msg || '删除成功')
+        } else {
+          this.msgError((response && response.msg) || '删除失败')
+        }
       }).catch(() => {})
+    },
+    handleExport() {
+      this.$confirm('是否确认导出当前筛选条件下的黑名单数据?', '警告', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        this.exportLoading = true
+        const data = { ...this.queryParams }
+        delete data.pageNum
+        delete data.pageSize
+        return exportApi(data)
+      }).then(res => {
+        this.download(res.msg)
+        this.exportLoading = false
+      }).catch(() => {
+        this.exportLoading = false
+      })
+    },
+    handlePhone(row) {
+      if (!row || !row.id) return
+      queryPhoneApi(row.id).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) || '获取手机号失败')
+        }
+      })
     }
   }
 }

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

@@ -0,0 +1,293 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="100px">
+      <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="primary" 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="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:query']"
+          />
+        </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="业务场景">{{ 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="对象值" :span="2">{{ 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 {
+  listApi,
+  getApi,
+  exportApi,
+  queryPhoneApi
+} from '@/api/company/companyVoiceBlacklistIntercept'
+
+export default {
+  name: 'CompanyVoiceBlacklistIntercept',
+  data() {
+    return {
+      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
+      }
+    }
+  },
+  created() {
+    this.getList()
+  },
+  methods: {
+    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 params
+    },
+    getList() {
+      this.loading = true
+      listApi(this.buildQueryParams()).then(res => {
+        this.list = res.rows || []
+        this.total = res.total || 0
+        this.loading = false
+      }).catch(() => {
+        this.loading = false
+      })
+    },
+    handleQuery() {
+      this.queryParams.pageNum = 1
+      this.getList()
+    },
+    resetQuery() {
+      this.dateRange = []
+      this.resetForm('queryForm')
+      this.queryParams.beginTime = null
+      this.queryParams.endTime = null
+      this.handleQuery()
+    },
+    handleDetail(row) {
+      if (!row || !row.id) return
+      getApi(row.id).then(res => {
+        this.detail = res.data || {}
+        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 exportApi(data)
+      }).then(res => {
+        this.download(res.msg)
+        this.exportLoading = false
+      }).catch(() => {
+        this.exportLoading = false
+      })
+    },
+    handlePhone(row) {
+      if (!row || !row.id) return
+      queryPhoneApi(row.id).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>