| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293 |
- <template>
- <div class="app-container">
- <el-form :model="queryParams" ref="queryFormRef" :inline="true" :label-width="labelWidth">
- <el-form-item :label="t('common.userId')" prop="username">
- <el-input
- v-model="queryParams.userId"
- :placeholder="t('common.pleaseEnter') + t('common.userId')"
- clearable
- @keyup.enter="handleQuery"
- />
- </el-form-item>
- <el-form-item :label="t('common.userName')" prop="username">
- <el-input
- v-model="queryParams.username"
- :placeholder="t('common.pleaseEnter') + t('common.userName')"
- clearable
- @keyup.enter="handleQuery"
- />
- </el-form-item>
- <el-form-item>
- <el-button type="primary" icon="Search" @click="handleQuery">{{ t('common.search') }}</el-button>
- <el-button icon="Refresh" @click="resetQuery">{{ t('common.reset') }}</el-button>
- </el-form-item>
- </el-form>
- <el-row :gutter="10" class="mb8">
- <el-col :span="1.5">
- <el-button
- type="info"
- plain
- icon="Sort"
- @click="toggleExpandAll"
- >{{ t('common.expandCollapse') }}</el-button>
- </el-col>
- </el-row>
- <el-table
- v-if="refreshTable"
- v-loading="loading"
- :data="treeData"
- :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
- row-key="id"
- :default-expand-all="isExpandAll"
- >
- <el-table-column type="selection" width="55" align="center" />
- <el-table-column :label="t('common.userName')" prop="userName" width="200" show-overflow-tooltip>
- <template #default="{ row }">
- <span v-if="row.isParent" class="parent-user-name">{{ row.userName || row.userId || t('common.unknown') }}</span>
- <span v-else>{{ row.userName || '-' }}</span>
- </template>
- </el-table-column>
- <el-table-column :label="t('common.userId')" prop="userId" width="120" align="center"/>
- <el-table-column :label="t('call.phoneNumber')" prop="phoneNumber" align="center" />
- <el-table-column :label="t('call.callType')" prop="callType" align="center">
- <template #default="{ row }">
- <span v-if="!row.isParent">{{ callTypeText(row.callType) }}</span>
- </template>
- </el-table-column>
- <el-table-column :label="t('call.startTime')" prop="startTime" align="center" />
- <el-table-column :label="t('call.duration')" prop="duration" align="center" />
- <el-table-column :label="t('call.contactName')" prop="contactName" align="center" />
- <el-table-column :label="t('common.operation')" align="center" width="140" class-name="small-padding fixed-width">
- <template #default="{ row }">
- <el-tooltip :content="t('common.view')" placement="top" v-if="!row.isParent">
- <el-button link type="primary" icon="View" @click.stop="handleView(row)"></el-button>
- </el-tooltip>
- </template>
- </el-table-column>
- </el-table>
- <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
- <el-dialog :title="title" v-model="open" width="600px" append-to-body>
- <el-form ref="formRef" :model="form" :label-width="labelWidth">
- <el-form-item :label="t('common.userId')" prop="userId">
- <el-input v-model="form.userId" :placeholder="t('common.pleaseEnter') + t('common.userId')" />
- </el-form-item>
- <el-form-item :label="t('common.userName')" prop="userName">
- <el-input v-model="form.userName" />
- </el-form-item>
- <el-form-item :label="t('call.phoneNumber')" prop="phoneNumber">
- <el-input v-model="form.phoneNumber" :placeholder="t('call.pleaseEnterPhoneNumber')" />
- </el-form-item>
- <el-form-item :label="t('call.startTime')" prop="startTime">
- <el-input v-model="form.startTime" :placeholder="t('call.pleaseEnterStartTime')" />
- </el-form-item>
- <el-form-item :label="t('call.duration')" prop="duration">
- <el-input v-model="form.duration" :placeholder="t('call.pleaseEnterDuration')" />
- </el-form-item>
- <el-form-item :label="t('call.contactName')" prop="contactName">
- <el-input v-model="form.contactName" :placeholder="t('call.pleaseEnterContactName')" />
- </el-form-item>
- </el-form>
- <template #footer>
- <div class="dialog-footer">
- <el-button @click="cancel">{{ t('common.cancel') }}</el-button>
- </div>
- </template>
- </el-dialog>
- </div>
- </template>
- <script setup>
- import {ref, reactive, getCurrentInstance, onMounted, nextTick, computed} from 'vue'
- import {getCallPageList} from '@/api/system/call.js'
- import {useI18n} from '@/composables/useI18n'
- const { t, locale } = useI18n()
- // 根据语言动态设置label宽度
- const labelWidth = computed(() => {
- return locale.value === 'vi' ? '140px' : '80px'
- })
- const { proxy } = getCurrentInstance()
- const { sys_show_hide, sys_normal_disable } = proxy.useDict("sys_show_hide", "sys_normal_disable")
- const callList = ref([])
- const treeData = ref([])
- const total = ref(0)
- const title = ref("")
- const open = ref(false)
- const form = ref({})
- const formRef = ref()
- const loading = ref(true)
- const queryFormRef = ref()
- const isExpandAll = ref(false)
- const refreshTable = ref(true)
- const queryParams = reactive({
- pageNum: 1,
- pageSize: 10,
- username: null,
- userId:null,
- })
- // 将扁平数据转换为树形结构
- const convertToTree = (data) => {
- if (!data || !Array.isArray(data)) {
- return []
- }
- const treeMap = new Map()
- const result = []
-
- // 先按userName和userId分组
- data.forEach(item => {
- const key = `${item.userName || ''}_${item.userId || ''}`
- if (!treeMap.has(key)) {
- treeMap.set(key, {
- id: `parent_${key}`,
- userName: item.userName || item.userId || t('common.unknown'),
- userId: item.userId,
- isParent: true,
- children: []
- })
- }
- // 添加子节点
- treeMap.get(key).children.push({
- ...item,
- id: item.id || `child_${key}_${treeMap.get(key).children.length}`
- })
- })
-
- // 转换为数组
- treeMap.forEach(value => {
- result.push(value)
- })
-
- return result
- }
- onMounted(()=>{
- getList()
- })
- const callTypeText = (type) => {
- switch (type) {
- case 1:
- case '1':
- return t('call.incoming');
- case 2:
- case '2':
- return t('call.outgoing');
- case 3:
- case '3':
- return t('call.missed');
- case 5:
- case '5':
- return t('call.hangup');
- default:
- return type;
- }
- }
- // 表单重设
- const reset = () => {
- form.value = {
- id: null,
- phoneNumber: null,
- callType: null,
- startTime: null,
- duration: null,
- contactName: null,
- createTime: null,
- userId: null,
- userName:null,
- }
- if (formRef.value) {
- formRef.value.resetFields()
- }
- }
- /** 搜索按钮操作 */
- const handleQuery = () => {
- queryParams.pageNum = 1
- getList()
- }
- /** 重置按钮操作 */
- const resetQuery = () => {
- queryFormRef.value.resetFields()
- handleQuery()
- }
- const getList = () => {
- loading.value = true
- const params = {
- pageNum: queryParams.pageNum,
- pageSize: queryParams.pageSize,
- userName: queryParams.username,
- userId:queryParams.userId,
- }
- getCallPageList(params).then(response => {
- // 处理不同的API返回格式
- // response 可能是 { code: 200, msg: "操作成功", data: [...] } 或直接是数组
- let data = []
- let totalCount = 0
-
- if (Array.isArray(response)) {
- // 如果response直接是数组
- data = response
- totalCount = data.length
- } else if (Array.isArray(response.data)) {
- // 如果data是数组
- data = response.data
- totalCount = data.length
- } else if (response.data && Array.isArray(response.data.records)) {
- // 如果是分页格式 { records: [], total: ... }
- data = response.data.records
- totalCount = response.data.total || data.length
- }
-
- // 如果数据已经是树形结构(包含isParent和children),直接使用
- if (data.length > 0 && (data[0].isParent !== undefined || data[0].children !== undefined)) {
- treeData.value = data
- callList.value = data.flatMap(item => item.children || [])
- total.value = totalCount
- } else {
- // 否则转换为树形结构
- callList.value = data
- treeData.value = convertToTree(data)
- total.value = totalCount
- }
- loading.value = false
- }).catch((error) => {
- console.error('获取通话列表失败:', error)
- loading.value = false
- })
- }
- /** 查看按钮操作 */
- const handleView = (row) => {
- reset()
- form.value = {...row}
- open.value = true
- title.value = t('call.viewTitle')
- nextTick(() => {
- if (formRef.value) formRef.value.clearValidate && formRef.value.clearValidate()
- })
- }
- // 取消按钮
- const cancel = () => {
- open.value = false
- reset()
- }
- /** 展开/折叠操作 */
- const toggleExpandAll = () => {
- refreshTable.value = false
- isExpandAll.value = !isExpandAll.value
- nextTick(() => {
- refreshTable.value = true
- })
- }
- </script>
- <style scoped lang="scss">
- .parent-user-name {
- color: #409EFF;
- font-weight: 500;
- font-size: 14px;
- }
- </style>
|