客户管理功能调整, 音频模型调整
This commit is contained in:
@@ -88,6 +88,12 @@ WantedBy=multi-user.target
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 门店录音统计相关接口
|
||||
// 机构录音统计相关接口
|
||||
export function generateStatistics(date) {
|
||||
return request({
|
||||
url: '/api/audio-statistics/generate',
|
||||
@@ -80,3 +80,12 @@ export function generateTempUrl(fileName, expiresInSeconds = 603800) {
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 语音转文本(ASR)接口
|
||||
export function speechToText(data) {
|
||||
return request({
|
||||
url: '/tts/log/speech-to-text',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
@@ -10,9 +10,9 @@ export function getCustomerList(params) {
|
||||
size: params.size || 10,
|
||||
customerName: params.customerName,
|
||||
contact: params.contact,
|
||||
salesName: params.salesName,
|
||||
dealershipId: params.dealershipId,
|
||||
projectId: params.projectId,
|
||||
salesId: params.salesId,
|
||||
createTimeStart: params.createTimeStart,
|
||||
createTimeEnd: params.createTimeEnd,
|
||||
infoCard: params.infoCard
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 获取门店列表
|
||||
// 获取机构列表
|
||||
export function getDealershipList(params) {
|
||||
return request({
|
||||
url: '/dealership/list',
|
||||
method: 'get',
|
||||
params: {
|
||||
current: params?.current || 1,
|
||||
size: params?.size || 1000, // 获取所有门店
|
||||
size: params?.size || 1000, // 获取所有机构
|
||||
...params
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 根据ID查询门店
|
||||
// 根据ID查询机构
|
||||
export function getDealershipById(id) {
|
||||
return request({
|
||||
url: `/dealership/get/${id}`,
|
||||
@@ -21,7 +21,7 @@ export function getDealershipById(id) {
|
||||
})
|
||||
}
|
||||
|
||||
// 添加门店
|
||||
// 添加机构
|
||||
export function addDealership(data) {
|
||||
return request({
|
||||
url: '/dealership/add',
|
||||
@@ -30,7 +30,7 @@ export function addDealership(data) {
|
||||
})
|
||||
}
|
||||
|
||||
// 更新门店
|
||||
// 更新机构
|
||||
export function updateDealership(data) {
|
||||
return request({
|
||||
url: '/dealership/update',
|
||||
@@ -39,7 +39,7 @@ export function updateDealership(data) {
|
||||
})
|
||||
}
|
||||
|
||||
// 删除门店
|
||||
// 删除机构
|
||||
export function deleteDealership(id) {
|
||||
return request({
|
||||
url: `/dealership/delete/${id}`,
|
||||
|
||||
@@ -76,7 +76,7 @@ export function getDeviceStatistics() {
|
||||
})
|
||||
}
|
||||
|
||||
// 批量分配设备到门店
|
||||
// 批量分配设备到机构
|
||||
export function batchAssignDevicesToStore(data) {
|
||||
return request({
|
||||
url: '/deviceManagement/batchAssignToStore',
|
||||
|
||||
@@ -26,6 +26,10 @@
|
||||
<el-input v-model="searchForm.creatorPhone" placeholder="请输入创建人电话" clearable style="width: 150px;" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="音频名称">
|
||||
<el-input v-model="searchForm.audioName" placeholder="请输入音频名称" clearable style="width: 150px;" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="开始时间">
|
||||
<el-date-picker
|
||||
v-model="searchForm.startTime"
|
||||
@@ -89,7 +93,7 @@
|
||||
style="width: 100%"
|
||||
@sort-change="handleSortChange"
|
||||
>
|
||||
<el-table-column prop="id" label="ID" width="80" sortable="custom" />
|
||||
<el-table-column prop="id" label="ID" width="160" sortable="custom" />
|
||||
<el-table-column prop="status" label="状态" width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-tag
|
||||
@@ -100,12 +104,16 @@
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="audioName" label="音频名称" width="150" show-overflow-tooltip />
|
||||
<el-table-column prop="creatorName" label="创建人姓名" width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="creatorPhone" label="创建人电话" width="130" show-overflow-tooltip />
|
||||
<el-table-column prop="model" label="模型" width="200" show-overflow-tooltip />
|
||||
<el-table-column prop="voice" label="声音" width="150" show-overflow-tooltip />
|
||||
<el-table-column prop="inputText" label="输入文本" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column prop="audioName" label="音频名称" width="150" />
|
||||
<el-table-column prop="creatorName" label="创建人姓名" width="120" />
|
||||
<el-table-column prop="creatorPhone" label="创建人电话" width="130" />
|
||||
<el-table-column prop="model" label="模型" width="200" />
|
||||
<el-table-column prop="voice" label="声音" width="150" />
|
||||
<el-table-column prop="inputText" label="输入文本" min-width="200">
|
||||
<template slot-scope="scope">
|
||||
<span style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: inline-block; max-width: 200px; word-break: keep-all; word-wrap: normal;">{{ scope.row.inputText }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="audioSizeBytes" label="文件大小" width="100">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.audioSizeBytes ? formatFileSize(scope.row.audioSizeBytes) : '-' }}
|
||||
@@ -118,7 +126,7 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="processingTimeMs" label="处理时间(ms)" width="120" />
|
||||
<el-table-column prop="updateTime" label="修改时间" width="160" sortable="custom" />
|
||||
<el-table-column label="操作" width="200" fixed="right">
|
||||
<el-table-column label="操作" width="280" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="small" @click="handleViewDetail(scope.row)">
|
||||
详情
|
||||
@@ -140,6 +148,15 @@
|
||||
>
|
||||
生成播放
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="scope.row.audioName"
|
||||
type="text"
|
||||
size="small"
|
||||
:loading="scope.row.asrLoading"
|
||||
@click="handleSpeechToText(scope.row)"
|
||||
>
|
||||
音频转文字
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="scope.row.status === 'FAILED'"
|
||||
type="text"
|
||||
@@ -168,46 +185,104 @@
|
||||
|
||||
<!-- 详情对话框 -->
|
||||
<el-dialog
|
||||
title="TTS请求详情"
|
||||
title="音频详情"
|
||||
:visible.sync="detailDialogVisible"
|
||||
width="800px"
|
||||
width="900px"
|
||||
:close-on-click-modal="false"
|
||||
class="detail-dialog"
|
||||
>
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="ID">{{ currentRow.id }}</el-descriptions-item>
|
||||
<el-descriptions-item label="状态">
|
||||
<el-tag :type="getStatusType(currentRow.status)">
|
||||
<div class="detail-content">
|
||||
<!-- 基本信息卡片 -->
|
||||
<el-card class="detail-card" shadow="never">
|
||||
<div slot="header" class="card-header">
|
||||
<i class="el-icon-document" />
|
||||
<span>基本信息</span>
|
||||
</div>
|
||||
<div class="detail-grid">
|
||||
<div class="detail-item">
|
||||
<label>ID:</label>
|
||||
<span class="detail-value">{{ currentRow.id || '-' }}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<label>状态:</label>
|
||||
<el-tag :type="getStatusType(currentRow.status)" size="small">
|
||||
{{ getStatusText(currentRow.status) }}
|
||||
</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="创建人姓名">{{ currentRow.creatorName || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="创建人电话">{{ currentRow.creatorPhone || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="模型">{{ currentRow.model }}</el-descriptions-item>
|
||||
<el-descriptions-item label="声音">{{ currentRow.voice }}</el-descriptions-item>
|
||||
<el-descriptions-item label="音频名称">{{ currentRow.audioName || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="文件大小">{{ formatFileSize(currentRow.audioSizeBytes) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="时长">{{ currentRow.duration ? currentRow.duration.toFixed(2) + '秒' : '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="处理时间">{{ currentRow.processingTimeMs }}ms</el-descriptions-item>
|
||||
<el-descriptions-item label="修改时间">{{ currentRow.updateTime }}</el-descriptions-item>
|
||||
<el-descriptions-item :span="2" label="输入文本">
|
||||
<div style="max-height: 100px; overflow-y: auto;">
|
||||
{{ currentRow.inputText }}
|
||||
</div>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item v-if="currentRow.errorMessage" :span="2" label="错误信息">
|
||||
<div style="color: #f56c6c;">{{ currentRow.errorMessage }}</div>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<div class="detail-item">
|
||||
<label>创建人:</label>
|
||||
<span class="detail-value">{{ currentRow.creatorName || '-' }}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<label>联系电话:</label>
|
||||
<span class="detail-value">{{ currentRow.creatorPhone || '-' }}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<label>模型:</label>
|
||||
<span class="detail-value">{{ currentRow.model || '-' }}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<label>音色:</label>
|
||||
<span class="detail-value">{{ currentRow.voice || '-' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 音频信息卡片 -->
|
||||
<el-card class="detail-card" shadow="never">
|
||||
<div slot="header" class="card-header">
|
||||
<i class="el-icon-headset" />
|
||||
<span>音频信息</span>
|
||||
</div>
|
||||
<div class="detail-grid">
|
||||
<div class="detail-item">
|
||||
<label>音频名称:</label>
|
||||
<span class="detail-value">{{ currentRow.audioName || '-' }}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<label>文件大小:</label>
|
||||
<span class="detail-value">{{ formatFileSize(currentRow.audioSizeBytes) }}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<label>音频时长:</label>
|
||||
<span class="detail-value">{{ currentRow.duration ? currentRow.duration.toFixed(2) + '秒' : '-' }}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<label>处理时间:</label>
|
||||
<span class="detail-value">{{ currentRow.processingTimeMs ? currentRow.processingTimeMs + 'ms' : '-' }}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<label>修改时间:</label>
|
||||
<span class="detail-value">{{ currentRow.updateTime || '-' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 文本内容卡片 -->
|
||||
<el-card class="detail-card" shadow="never">
|
||||
<div slot="header" class="card-header">
|
||||
<i class="el-icon-edit-outline" />
|
||||
<span>输入文本</span>
|
||||
</div>
|
||||
<div class="text-content">
|
||||
{{ currentRow.inputText || '无' }}
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 错误信息卡片(仅在有错误时显示) -->
|
||||
<el-card v-if="currentRow.errorMessage" class="detail-card error-card" shadow="never">
|
||||
<div slot="header" class="card-header error-header">
|
||||
<i class="el-icon-warning" />
|
||||
<span>错误信息</span>
|
||||
</div>
|
||||
<div class="error-content">
|
||||
{{ currentRow.errorMessage }}
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="detailDialogVisible = false">关闭</el-button>
|
||||
<el-button
|
||||
v-if="currentRow.shortUrl"
|
||||
type="primary"
|
||||
@click="handlePlayAudio(currentRow.shortUrl)"
|
||||
>
|
||||
播放音频
|
||||
</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
@@ -273,6 +348,41 @@
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 音频播放器弹窗 -->
|
||||
<el-dialog
|
||||
title="音频播放"
|
||||
:visible.sync="audioPlayerVisible"
|
||||
width="500px"
|
||||
:close-on-click-modal="false"
|
||||
@close="handleCloseAudioPlayer"
|
||||
>
|
||||
<div class="audio-player-container">
|
||||
<audio
|
||||
ref="audioPlayer"
|
||||
:src="currentAudioUrl"
|
||||
controls
|
||||
preload="metadata"
|
||||
style="width: 100%;"
|
||||
@loadstart="handleAudioLoadStart"
|
||||
@canplay="handleAudioCanPlay"
|
||||
@error="handleAudioError"
|
||||
>
|
||||
您的浏览器不支持音频播放。
|
||||
</audio>
|
||||
<div v-if="audioLoading" class="audio-loading">
|
||||
<i class="el-icon-loading" />
|
||||
音频加载中...
|
||||
</div>
|
||||
<div v-if="audioError" class="audio-error">
|
||||
<i class="el-icon-warning" />
|
||||
{{ audioError }}
|
||||
</div>
|
||||
</div>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="handleCloseAudioPlayer">关闭</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 音频生成对话框 -->
|
||||
<el-dialog
|
||||
title="音频生成"
|
||||
@@ -348,9 +458,11 @@
|
||||
v-model="generateForm.inputText"
|
||||
type="textarea"
|
||||
:rows="8"
|
||||
placeholder="请输入要转换为语音的文本"
|
||||
placeholder="请输入要转换为语音的文本..."
|
||||
maxlength="1000"
|
||||
show-word-limit
|
||||
resize="vertical"
|
||||
style="font-size: 14px; line-height: 1.5;"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
@@ -448,7 +560,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getTtsRequestLogs, generateTtsAudio, generateTempUrl } from '@/api/audio-statistics'
|
||||
import { getTtsRequestLogs, generateTtsAudio, generateTempUrl, speechToText } from '@/api/audio-statistics'
|
||||
import { mapGetters } from 'vuex'
|
||||
|
||||
export default {
|
||||
@@ -462,6 +574,7 @@ export default {
|
||||
model: '',
|
||||
creatorName: '',
|
||||
creatorPhone: '',
|
||||
audioName: '',
|
||||
startTime: '',
|
||||
endTime: ''
|
||||
},
|
||||
@@ -474,6 +587,11 @@ export default {
|
||||
sortOrder: '',
|
||||
detailDialogVisible: false,
|
||||
currentRow: {},
|
||||
// 音频播放器相关
|
||||
audioPlayerVisible: false,
|
||||
currentAudioUrl: '',
|
||||
audioLoading: false,
|
||||
audioError: '',
|
||||
// 上传音频对话框相关
|
||||
uploadDialogVisible: false,
|
||||
uploadLoading: false,
|
||||
@@ -612,6 +730,7 @@ export default {
|
||||
model: '',
|
||||
creatorName: '',
|
||||
creatorPhone: '',
|
||||
audioName: '',
|
||||
startTime: '',
|
||||
endTime: ''
|
||||
}
|
||||
@@ -653,7 +772,10 @@ export default {
|
||||
// 播放音频
|
||||
handlePlayAudio(audioUrl) {
|
||||
if (audioUrl) {
|
||||
window.open(audioUrl, '_blank')
|
||||
this.currentAudioUrl = audioUrl
|
||||
this.audioPlayerVisible = true
|
||||
this.audioLoading = true
|
||||
this.audioError = ''
|
||||
} else {
|
||||
this.$message.warning('音频文件不存在')
|
||||
}
|
||||
@@ -674,6 +796,40 @@ export default {
|
||||
})
|
||||
},
|
||||
|
||||
// 音频开始加载
|
||||
handleAudioLoadStart() {
|
||||
this.audioLoading = true
|
||||
this.audioError = ''
|
||||
},
|
||||
|
||||
// 音频可以播放
|
||||
handleAudioCanPlay() {
|
||||
this.audioLoading = false
|
||||
this.audioError = ''
|
||||
},
|
||||
|
||||
// 音频加载错误
|
||||
handleAudioError(event) {
|
||||
this.audioLoading = false
|
||||
this.audioError = '音频加载失败,请检查网络连接或音频文件是否有效'
|
||||
console.error('音频加载错误:', event)
|
||||
},
|
||||
|
||||
// 关闭音频播放器
|
||||
handleCloseAudioPlayer() {
|
||||
// 停止音频播放
|
||||
if (this.$refs.audioPlayer) {
|
||||
this.$refs.audioPlayer.pause()
|
||||
this.$refs.audioPlayer.currentTime = 0
|
||||
}
|
||||
// 关闭弹窗
|
||||
this.audioPlayerVisible = false
|
||||
// 重置状态
|
||||
this.currentAudioUrl = ''
|
||||
this.audioLoading = false
|
||||
this.audioError = ''
|
||||
},
|
||||
|
||||
// 获取状态类型
|
||||
getStatusType(status) {
|
||||
const statusMap = {
|
||||
@@ -988,6 +1144,64 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
// 音频转文字
|
||||
async handleSpeechToText(row) {
|
||||
if (!row || !row.audioName) {
|
||||
this.$message.error('缺少音频文件名,无法转文字')
|
||||
return
|
||||
}
|
||||
if (row.asrLoading) return
|
||||
this.$set(row, 'asrLoading', true)
|
||||
try {
|
||||
let audioUrl = row.shortUrl
|
||||
// 若还没有可访问的短链,先生成临时URL
|
||||
if (!audioUrl) {
|
||||
const expiresInSeconds = 604800
|
||||
const tempRes = await generateTempUrl(row.audioName, expiresInSeconds)
|
||||
if (tempRes && (tempRes.success || tempRes.code === 20000) && (tempRes.tempUrl || tempRes.data?.tempUrl)) {
|
||||
audioUrl = tempRes.tempUrl || tempRes.data.tempUrl
|
||||
this.$set(row, 'shortUrl', audioUrl)
|
||||
} else {
|
||||
this.$message.error(tempRes?.message || '无法生成音频访问链接')
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 组装与后端 AsrRequest 匹配的请求体
|
||||
const payload = {
|
||||
id: row.id, // 添加ID字段传递给后端
|
||||
audioUrl,
|
||||
model: 'paraformer-v2',
|
||||
format: 'wav',
|
||||
sampleRate: 16000,
|
||||
enablePunctuation: true,
|
||||
enableNumberConversion: true,
|
||||
enableSpeakerDiarization: false,
|
||||
speakerCount: 1,
|
||||
creatorName: row.creatorName || this.name || '',
|
||||
creatorPhone: row.creatorPhone || this.phone || '',
|
||||
audioName: row.audioName
|
||||
}
|
||||
|
||||
const res = await speechToText(payload, row.id)
|
||||
// 兼容 axios 响应包装
|
||||
const ok = res && (res.success === true || res.code === 20000 || res.code === 200)
|
||||
const text = (res && (res.data?.text || res.text || res.result || res.data)) || ''
|
||||
if (ok) {
|
||||
this.$alert(text || '未识别到有效文本', '转写结果', {
|
||||
confirmButtonText: '确定'
|
||||
})
|
||||
} else {
|
||||
this.$message.error(res?.message || '语音转文本失败')
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('ASR失败:', e)
|
||||
this.$message.error('语音转文本失败: ' + (e.message || '未知错误'))
|
||||
} finally {
|
||||
this.$set(row, 'asrLoading', false)
|
||||
}
|
||||
},
|
||||
|
||||
// 确认生成音频
|
||||
async handleConfirmGenerate() {
|
||||
this.$refs.generateForm.validate(async(valid) => {
|
||||
@@ -1052,4 +1266,229 @@ export default {
|
||||
.dialog-footer {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* 优化文本输入框样式 */
|
||||
.el-textarea__inner {
|
||||
font-size: 14px !important;
|
||||
line-height: 1.6 !important;
|
||||
padding: 12px 15px !important;
|
||||
border-radius: 6px !important;
|
||||
border: 1px solid #dcdfe6 !important;
|
||||
transition: all 0.3s ease !important;
|
||||
resize: vertical !important;
|
||||
min-height: 120px !important;
|
||||
}
|
||||
|
||||
.el-textarea__inner:focus {
|
||||
border-color: #409eff !important;
|
||||
box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.1) !important;
|
||||
}
|
||||
|
||||
.el-textarea__inner::placeholder {
|
||||
color: #c0c4cc !important;
|
||||
font-size: 13px !important;
|
||||
line-height: 1.5 !important;
|
||||
white-space: nowrap !important;
|
||||
overflow: hidden !important;
|
||||
text-overflow: ellipsis !important;
|
||||
}
|
||||
|
||||
/* 优化字数统计显示 */
|
||||
.el-input__count {
|
||||
background: rgba(255, 255, 255, 0.9) !important;
|
||||
color: #909399 !important;
|
||||
font-size: 12px !important;
|
||||
padding: 2px 6px !important;
|
||||
border-radius: 4px !important;
|
||||
}
|
||||
|
||||
/* 优化表格单元格样式,防止换行 */
|
||||
.el-table .cell {
|
||||
white-space: nowrap !important;
|
||||
overflow: hidden !important;
|
||||
text-overflow: ellipsis !important;
|
||||
word-break: keep-all !important;
|
||||
word-wrap: normal !important;
|
||||
}
|
||||
|
||||
/* 特别针对输入文本列,强制不换行 */
|
||||
.el-table tbody tr td:nth-child(8) .cell {
|
||||
white-space: nowrap !important;
|
||||
overflow: hidden !important;
|
||||
text-overflow: ellipsis !important;
|
||||
max-width: 200px !important;
|
||||
word-break: keep-all !important;
|
||||
word-wrap: normal !important;
|
||||
}
|
||||
|
||||
/* 确保所有表格单元格都不换行 */
|
||||
.el-table td .cell {
|
||||
white-space: nowrap !important;
|
||||
overflow: hidden !important;
|
||||
text-overflow: ellipsis !important;
|
||||
word-break: keep-all !important;
|
||||
word-wrap: normal !important;
|
||||
}
|
||||
|
||||
/* 针对输入文本列的具体样式优化 */
|
||||
.el-table-column[prop="inputText"] .cell {
|
||||
white-space: nowrap !important;
|
||||
overflow: hidden !important;
|
||||
text-overflow: ellipsis !important;
|
||||
word-break: keep-all !important;
|
||||
word-wrap: normal !important;
|
||||
display: inline-block !important;
|
||||
max-width: 200px !important;
|
||||
}
|
||||
|
||||
/* 音频播放器样式 */
|
||||
.audio-player-container {
|
||||
text-align: center;
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
.audio-loading {
|
||||
margin-top: 10px;
|
||||
color: #409eff;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.audio-loading i {
|
||||
margin-right: 5px;
|
||||
animation: rotating 2s linear infinite;
|
||||
}
|
||||
|
||||
.audio-error {
|
||||
margin-top: 10px;
|
||||
color: #f56c6c;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.audio-error i {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
@keyframes rotating {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
/* 详情对话框样式优化 */
|
||||
.detail-dialog .el-dialog__body {
|
||||
padding: 20px;
|
||||
max-height: 70vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.detail-content {
|
||||
max-height: 60vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.detail-card {
|
||||
margin-bottom: 20px;
|
||||
border: 1px solid #e4e7ed;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.detail-card:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.card-header i {
|
||||
margin-right: 8px;
|
||||
color: #409eff;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.error-header {
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.error-header i {
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.detail-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.detail-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-height: 36px;
|
||||
padding: 8px 12px;
|
||||
background: #fafafa;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #e4e7ed;
|
||||
}
|
||||
|
||||
.detail-item label {
|
||||
font-weight: 600;
|
||||
color: #606266;
|
||||
min-width: 80px;
|
||||
margin-right: 12px;
|
||||
flex-shrink: 0;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.detail-value {
|
||||
color: #303133;
|
||||
word-break: break-all;
|
||||
flex: 1;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.text-content {
|
||||
background: #f8f9fa;
|
||||
border: 1px solid #e4e7ed;
|
||||
border-radius: 6px;
|
||||
padding: 16px;
|
||||
line-height: 1.6;
|
||||
color: #303133;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
min-height: 80px;
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.error-content {
|
||||
background: #fef0f0;
|
||||
border: 1px solid #fbc4c4;
|
||||
border-radius: 6px;
|
||||
padding: 16px;
|
||||
color: #f56c6c;
|
||||
line-height: 1.6;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.error-card {
|
||||
border-color: #fbc4c4;
|
||||
}
|
||||
|
||||
.dialog-footer {
|
||||
text-align: right;
|
||||
padding-top: 20px;
|
||||
border-top: 1px solid #e4e7ed;
|
||||
}
|
||||
|
||||
.dialog-footer .el-button {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<h2>门店录音统计管理</h2>
|
||||
<h2>机构录音统计管理</h2>
|
||||
|
||||
<!-- 操作区域 -->
|
||||
<el-card style="margin-bottom: 20px;">
|
||||
@@ -102,13 +102,13 @@
|
||||
stripe
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column prop="dealershipName" label="门店名称" width="150" />
|
||||
<el-table-column prop="dealershipTotalDuration" label="门店录音总时长" width="150">
|
||||
<el-table-column prop="dealershipName" label="机构名称" width="150" />
|
||||
<el-table-column prop="dealershipTotalDuration" label="机构录音总时长" width="150">
|
||||
<template slot-scope="scope">
|
||||
{{ formatDuration(scope.row.dealershipTotalDuration) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="dealershipAvgDuration" label="门店录音平均时长" width="150">
|
||||
<el-table-column prop="dealershipAvgDuration" label="机构录音平均时长" width="150">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.dealershipAvgDuration }}秒
|
||||
</template>
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
<el-card class="filter-container" shadow="never">
|
||||
<el-form ref="queryForm" :model="queryParams" :inline="true" label-width="100px">
|
||||
<!-- 第一行 -->
|
||||
<el-form-item label="选择门店">
|
||||
<el-select v-model="queryParams.dealershipId" placeholder="请选择所属门店" clearable>
|
||||
<el-form-item label="选择机构">
|
||||
<el-select v-model="queryParams.dealershipId" placeholder="请选择所属机构" clearable>
|
||||
<el-option
|
||||
v-for="item in dealershipOptions"
|
||||
:key="item.value"
|
||||
@@ -167,7 +167,7 @@
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="所属门店" prop="dealershipName" min-width="150" />
|
||||
<el-table-column label="所属机构" prop="dealershipName" min-width="150" />
|
||||
<el-table-column label="所属项目" prop="projectName" min-width="150" />
|
||||
<el-table-column label="话术模型" prop="speechModel" min-width="120" />
|
||||
<el-table-column label="上传状态" prop="uploadStatus" min-width="100">
|
||||
@@ -377,7 +377,7 @@
|
||||
{{ audioForm.intentionLevel }}
|
||||
</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="所属门店">{{ audioForm.dealershipName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="所属机构">{{ audioForm.dealershipName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="所属项目">{{ audioForm.projectName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="话术模型">{{ audioForm.speechModel }}</el-descriptions-item>
|
||||
<el-descriptions-item label="上传状态">
|
||||
@@ -419,8 +419,8 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="所属门店" prop="dealershipId">
|
||||
<el-select v-model="audioForm.dealershipId" placeholder="请选择所属门店" style="width: 100%">
|
||||
<el-form-item label="所属机构" prop="dealershipId">
|
||||
<el-select v-model="audioForm.dealershipId" placeholder="请选择所属机构" style="width: 100%">
|
||||
<el-option
|
||||
v-for="item in dealershipOptions"
|
||||
:key="item.value"
|
||||
@@ -1039,7 +1039,7 @@ export default {
|
||||
{ required: true, message: '请选择销售', trigger: 'change' }
|
||||
]
|
||||
},
|
||||
// 门店选项
|
||||
// 机构选项
|
||||
dealershipOptions: [],
|
||||
// 项目选项
|
||||
projectOptions: [],
|
||||
@@ -1109,10 +1109,10 @@ export default {
|
||||
// 直接设置销售电话查询条件
|
||||
this.queryParams.salesPhone = salesPhone
|
||||
|
||||
// 如果有分支机构名称,设置到门店选择中
|
||||
// 如果有分支机构名称,设置到机构选择中
|
||||
if (dealershipName) {
|
||||
// 这里需要根据分支机构名称找到对应的ID
|
||||
// 暂时先设置一个标识,等门店选项加载完成后再处理
|
||||
// 暂时先设置一个标识,等机构选项加载完成后再处理
|
||||
this.pendingDealershipName = dealershipName
|
||||
}
|
||||
|
||||
@@ -1188,13 +1188,13 @@ export default {
|
||||
this.pendingDealershipName = ''
|
||||
},
|
||||
|
||||
// 获取门店选项
|
||||
// 获取机构选项
|
||||
getDealershipOptions() {
|
||||
getDealershipList({ size: 1000 }).then(response => {
|
||||
console.log('门店选项 1111111111111111111:', response)
|
||||
console.log('机构选项 1111111111111111111:', response)
|
||||
if (response.code === 20000) {
|
||||
const data = response.data.records || response.data.data || response.data || []
|
||||
console.log('门店选项 22222222222:', data)
|
||||
console.log('机构选项 22222222222:', data)
|
||||
this.dealershipOptions = data.map(item => ({
|
||||
value: item.id,
|
||||
label: item.dealershipName || item.name
|
||||
@@ -1212,10 +1212,10 @@ export default {
|
||||
this.getList()
|
||||
}
|
||||
} else {
|
||||
console.error('获取门店选项失败:', response.message)
|
||||
console.error('获取机构选项失败:', response.message)
|
||||
}
|
||||
}).catch(error => {
|
||||
console.error('获取门店选项错误:', error)
|
||||
console.error('获取机构选项错误:', error)
|
||||
// 开发环境使用模拟数据
|
||||
this.dealershipOptions = [
|
||||
{ value: '1', label: '销售演示-上汽' },
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<!-- 查询条件区域 -->
|
||||
<el-card class="filter-container" shadow="never">
|
||||
<el-form ref="queryForm" :model="queryParams" :inline="true" label-width="100px">
|
||||
<el-form-item label="选择门店">
|
||||
<el-select v-model="queryParams.dealershipId" placeholder="请选择所属门店" clearable>
|
||||
<el-form-item label="选择机构">
|
||||
<el-select v-model="queryParams.dealershipId" placeholder="请选择所属机构" clearable>
|
||||
<el-option
|
||||
v-for="item in dealershipOptions"
|
||||
:key="item.value"
|
||||
@@ -15,14 +15,12 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="所属销售">
|
||||
<el-select v-model="queryParams.salesId" placeholder="请选择销售" clearable>
|
||||
<el-option
|
||||
v-for="item in salesOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
<el-input
|
||||
v-model="queryParams.salesName"
|
||||
placeholder="请输入销售姓名(默认当前用户)"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="客户姓名">
|
||||
@@ -105,10 +103,15 @@
|
||||
<el-table-column label="序号" type="index" width="50" />
|
||||
<el-table-column label="客户姓名" prop="customerName" min-width="120" />
|
||||
<el-table-column label="联系方式" prop="contact" min-width="150" />
|
||||
<el-table-column label="所属门店" prop="dealershipName" min-width="150" />
|
||||
<el-table-column label="所属机构" prop="dealershipName" min-width="150" />
|
||||
<el-table-column label="所属销售" prop="salesName" min-width="150" />
|
||||
<el-table-column label="录音条数" prop="recordingCount" sortable min-width="100" />
|
||||
<el-table-column label="意向车型" prop="intendedModel" min-width="120" />
|
||||
<el-table-column label="修改时间" prop="updateTime" min-width="150">
|
||||
<template slot-scope="scope">
|
||||
{{ formatTime(scope.row.updateTime) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="200" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="small" @click="handleViewDetails(scope.row)">查看详情</el-button>
|
||||
@@ -145,7 +148,7 @@
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="info-item">
|
||||
<label>所属门店:</label>
|
||||
<label>所属机构:</label>
|
||||
<span>{{ customer.dealershipName }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
@@ -160,6 +163,10 @@
|
||||
<label>意向车型:</label>
|
||||
<span>{{ customer.intendedModel || '-' }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<label>修改时间:</label>
|
||||
<span>{{ formatTime(customer.updateTime) || '-' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<el-button type="text" size="small" @click="handleViewDetails(customer)">查看详情</el-button>
|
||||
@@ -196,8 +203,8 @@
|
||||
<el-form-item label="联系方式" prop="contact">
|
||||
<el-input v-model="customerForm.contact" placeholder="请输入联系方式" />
|
||||
</el-form-item>
|
||||
<el-form-item label="所属门店" prop="dealershipId">
|
||||
<el-select v-model="customerForm.dealershipId" placeholder="请选择所属门店" style="width: 100%">
|
||||
<el-form-item label="所属机构" prop="dealershipId">
|
||||
<el-select v-model="customerForm.dealershipId" placeholder="请选择所属机构" style="width: 100%">
|
||||
<el-option
|
||||
v-for="item in dealershipOptions"
|
||||
:key="item.value"
|
||||
@@ -258,7 +265,7 @@
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">
|
||||
<label>所属门店:</label>
|
||||
<label>所属机构:</label>
|
||||
<span>{{ currentCustomer.dealershipName }}</span>
|
||||
</div>
|
||||
</el-col>
|
||||
@@ -287,13 +294,13 @@
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">
|
||||
<label>创建时间:</label>
|
||||
<span>{{ currentCustomer.createTime }}</span>
|
||||
<span>{{ formatTime(currentCustomer.createTime) }}</span>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">
|
||||
<label>更新时间:</label>
|
||||
<span>{{ currentCustomer.updateTime }}</span>
|
||||
<span>{{ formatTime(currentCustomer.updateTime) }}</span>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -354,7 +361,7 @@ export default {
|
||||
customerRules: {
|
||||
customerName: [{ required: true, message: '请输入客户姓名', trigger: 'blur' }],
|
||||
contact: [{ required: true, message: '请输入联系方式', trigger: 'blur' }],
|
||||
dealershipId: [{ required: true, message: '请选择所属门店', trigger: 'change' }],
|
||||
dealershipId: [{ required: true, message: '请选择所属机构', trigger: 'change' }],
|
||||
salesId: [{ required: true, message: '请选择所属销售', trigger: 'change' }]
|
||||
},
|
||||
// 查询参数
|
||||
@@ -364,20 +371,25 @@ export default {
|
||||
customerName: '',
|
||||
contact: '',
|
||||
dealershipId: '',
|
||||
projectId: '',
|
||||
salesId: '',
|
||||
salesName: '',
|
||||
createTimeRange: [],
|
||||
infoCard: ''
|
||||
},
|
||||
// 门店选项
|
||||
// 机构选项
|
||||
dealershipOptions: [],
|
||||
// 项目选项
|
||||
projectOptions: [],
|
||||
// 销售选项
|
||||
salesOptions: []
|
||||
salesOptions: [],
|
||||
// 当前用户信息
|
||||
currentUser: {
|
||||
name: '',
|
||||
phone: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getCurrentUser()
|
||||
this.getList()
|
||||
this.getDealershipOptions()
|
||||
this.getProjectOptions()
|
||||
@@ -403,6 +415,9 @@ export default {
|
||||
}
|
||||
})
|
||||
|
||||
console.log('发送给后端的查询参数:', params)
|
||||
console.log('原始queryParams:', this.queryParams)
|
||||
|
||||
getCustomerList(params).then(response => {
|
||||
console.log('API响应:', response)
|
||||
if (response.code === 20000) {
|
||||
@@ -421,7 +436,7 @@ export default {
|
||||
})
|
||||
},
|
||||
|
||||
// 获取门店选项
|
||||
// 获取机构选项
|
||||
getDealershipOptions() {
|
||||
getDealershipList({ size: 1000 }).then(response => {
|
||||
if (response && response.code === 20000) {
|
||||
@@ -430,10 +445,10 @@ export default {
|
||||
label: item.dealershipName
|
||||
}))
|
||||
} else {
|
||||
this.$message.error(response?.message || '获取门店列表失败')
|
||||
this.$message.error(response?.message || '获取机构列表失败')
|
||||
}
|
||||
}).catch(error => {
|
||||
console.error('获取门店列表失败:', error)
|
||||
console.error('获取机构列表失败:', error)
|
||||
// 开发环境使用模拟数据
|
||||
this.dealershipOptions = [
|
||||
{ value: '1', label: '销售演示-上汽' },
|
||||
@@ -504,8 +519,7 @@ export default {
|
||||
customerName: '',
|
||||
contact: '',
|
||||
dealershipId: '',
|
||||
projectId: '',
|
||||
salesId: '',
|
||||
salesName: this.currentUser.name,
|
||||
createTimeRange: [],
|
||||
infoCard: ''
|
||||
}
|
||||
@@ -682,6 +696,8 @@ export default {
|
||||
}
|
||||
})
|
||||
|
||||
console.log('导出时发送给后端的查询参数:', params)
|
||||
|
||||
exportCustomerFlow(params).then(response => {
|
||||
// 创建下载链接
|
||||
const blob = new Blob([response], { type: 'application/vnd.ms-excel' })
|
||||
@@ -701,6 +717,39 @@ export default {
|
||||
handleViewDetails(row) {
|
||||
this.currentCustomer = row
|
||||
this.detailVisible = true
|
||||
},
|
||||
|
||||
// 获取当前用户信息
|
||||
getCurrentUser() {
|
||||
// 从Vuex store中获取当前用户信息
|
||||
const userName = this.$store.getters.name || ''
|
||||
|
||||
this.currentUser.name = userName || '当前用户'
|
||||
|
||||
// 设置默认查询条件
|
||||
this.queryParams.salesName = this.currentUser.name
|
||||
},
|
||||
|
||||
// 格式化时间显示
|
||||
formatTime(timeStr) {
|
||||
if (!timeStr) return '-'
|
||||
|
||||
try {
|
||||
const date = new Date(timeStr)
|
||||
if (isNaN(date.getTime())) return timeStr
|
||||
|
||||
const year = date.getFullYear()
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(date.getDate()).padStart(2, '0')
|
||||
const hours = String(date.getHours()).padStart(2, '0')
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0')
|
||||
const seconds = String(date.getSeconds()).padStart(2, '0')
|
||||
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
|
||||
} catch (error) {
|
||||
console.error('时间格式化错误:', error)
|
||||
return timeStr
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
<el-col :span="12">
|
||||
<el-card class="chart-card" shadow="never">
|
||||
<div slot="header">
|
||||
<span>门店录音数量</span>
|
||||
<span>机构录音数量</span>
|
||||
</div>
|
||||
<div class="chart-container">
|
||||
<div ref="dealershipChart" style="height: 300px;" />
|
||||
@@ -312,7 +312,7 @@ export default {
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: ['上汽门店', '奔驰门店', '比亚迪门店', 'DCC门店']
|
||||
data: ['上汽机构', '奔驰机构', '比亚迪机构', 'DCC机构']
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value'
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<!-- 查询条件区域 -->
|
||||
<el-card class="filter-container" shadow="never">
|
||||
<el-form ref="queryForm" :model="queryParams" :inline="true" label-width="100px">
|
||||
<el-form-item label="选择门店">
|
||||
<el-select v-model="queryParams.dealershipId" placeholder="请选择所属门店" clearable>
|
||||
<el-form-item label="选择机构">
|
||||
<el-select v-model="queryParams.dealershipId" placeholder="请选择所属机构" clearable>
|
||||
<el-option
|
||||
v-for="item in dealershipOptions"
|
||||
:key="item.value"
|
||||
@@ -50,7 +50,7 @@
|
||||
|
||||
<!-- 操作按钮区域 -->
|
||||
<el-card class="action-container" shadow="never">
|
||||
<el-button type="primary" @click="handleBatchAssign">批量分配设备到门店</el-button>
|
||||
<el-button type="primary" @click="handleBatchAssign">批量分配设备到机构</el-button>
|
||||
</el-card>
|
||||
|
||||
<!-- 数据表格区域 -->
|
||||
@@ -64,7 +64,7 @@
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column label="序号" type="index" width="50" />
|
||||
<el-table-column label="设备编号" prop="deviceCode" sortable min-width="180" />
|
||||
<el-table-column label="所属门店" prop="dealershipName" sortable min-width="120" />
|
||||
<el-table-column label="所属机构" prop="dealershipName" sortable min-width="120" />
|
||||
<el-table-column label="设备信息(最近一次)" min-width="300">
|
||||
<template slot-scope="scope">
|
||||
<div class="device-info">
|
||||
@@ -120,8 +120,8 @@
|
||||
<el-form-item label="设备编号" prop="deviceCode">
|
||||
<el-input v-model="deviceForm.deviceCode" placeholder="请输入设备编号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="所属门店" prop="dealershipId">
|
||||
<el-select v-model="deviceForm.dealershipId" placeholder="请选择所属门店" style="width: 100%">
|
||||
<el-form-item label="所属机构" prop="dealershipId">
|
||||
<el-select v-model="deviceForm.dealershipId" placeholder="请选择所属机构" style="width: 100%">
|
||||
<el-option
|
||||
v-for="item in dealershipOptions"
|
||||
:key="item.value"
|
||||
@@ -163,15 +163,15 @@
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 批量分配设备到门店对话框 -->
|
||||
<!-- 批量分配设备到机构对话框 -->
|
||||
<el-dialog
|
||||
title="批量分配设备到门店"
|
||||
title="批量分配设备到机构"
|
||||
:visible.sync="batchAssignVisible"
|
||||
width="500px"
|
||||
>
|
||||
<el-form ref="batchAssignForm" :model="batchAssignForm" :rules="batchAssignRules" label-width="100px">
|
||||
<el-form-item label="选择门店" prop="dealershipId">
|
||||
<el-select v-model="batchAssignForm.dealershipId" placeholder="请选择门店" style="width: 100%">
|
||||
<el-form-item label="选择机构" prop="dealershipId">
|
||||
<el-select v-model="batchAssignForm.dealershipId" placeholder="请选择机构" style="width: 100%">
|
||||
<el-option
|
||||
v-for="item in dealershipOptions"
|
||||
:key="item.value"
|
||||
@@ -252,7 +252,7 @@ export default {
|
||||
{ required: true, message: '请输入设备编号', trigger: 'blur' }
|
||||
],
|
||||
dealershipId: [
|
||||
{ required: true, message: '请选择所属门店', trigger: 'change' }
|
||||
{ required: true, message: '请选择所属机构', trigger: 'change' }
|
||||
],
|
||||
bindStatus: [
|
||||
{ required: true, message: '请选择绑定状态', trigger: 'change' }
|
||||
@@ -260,10 +260,10 @@ export default {
|
||||
},
|
||||
batchAssignRules: {
|
||||
dealershipId: [
|
||||
{ required: true, message: '请选择门店', trigger: 'change' }
|
||||
{ required: true, message: '请选择机构', trigger: 'change' }
|
||||
]
|
||||
},
|
||||
// 门店选项
|
||||
// 机构选项
|
||||
dealershipOptions: [],
|
||||
// 用户选项
|
||||
userOptions: [],
|
||||
@@ -278,7 +278,7 @@ export default {
|
||||
this.getProjectOptions()
|
||||
},
|
||||
methods: {
|
||||
// 获取门店选项
|
||||
// 获取机构选项
|
||||
getDealershipOptions() {
|
||||
getDealershipList({ size: 1000 }).then(response => {
|
||||
if (response && response.code === 20000) {
|
||||
@@ -287,10 +287,10 @@ export default {
|
||||
label: item.dealershipName
|
||||
}))
|
||||
} else {
|
||||
this.$message.error(response?.message || '获取门店列表失败')
|
||||
this.$message.error(response?.message || '获取机构列表失败')
|
||||
}
|
||||
}).catch(error => {
|
||||
console.error('获取门店列表失败:', error)
|
||||
console.error('获取机构列表失败:', error)
|
||||
// 开发环境使用模拟数据
|
||||
this.dealershipOptions = [
|
||||
{ value: '1', label: 'DCC演示' },
|
||||
@@ -435,7 +435,7 @@ export default {
|
||||
this.getList()
|
||||
},
|
||||
|
||||
// 批量分配设备到门店
|
||||
// 批量分配设备到机构
|
||||
handleBatchAssign() {
|
||||
if (this.selectedIds.length === 0) {
|
||||
this.$message.warning('请先选择要分配的设备')
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<!-- 查询条件区域 -->
|
||||
<el-card class="filter-container" shadow="never">
|
||||
<el-form ref="queryForm" :model="queryParams" :inline="true" label-width="100px">
|
||||
<el-form-item label="选择门店">
|
||||
<el-select v-model="queryParams.dealershipId" placeholder="请选择所属门店" clearable>
|
||||
<el-form-item label="选择机构">
|
||||
<el-select v-model="queryParams.dealershipId" placeholder="请选择所属机构" clearable>
|
||||
<el-option
|
||||
v-for="item in storeOptions"
|
||||
:key="item.value"
|
||||
@@ -62,7 +62,7 @@
|
||||
>
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column label="序号" type="index" width="50" />
|
||||
<el-table-column label="所属门店" prop="dealershipName" min-width="150" />
|
||||
<el-table-column label="所属机构" prop="dealershipName" min-width="150" />
|
||||
<el-table-column label="项目名称" prop="projectName" min-width="150" />
|
||||
<el-table-column label="话术版本" prop="scriptVersion" min-width="100" />
|
||||
<el-table-column label="话术发布时间" prop="scriptPublishTime" sortable min-width="150">
|
||||
@@ -118,8 +118,8 @@
|
||||
@close="handleDialogClose"
|
||||
>
|
||||
<el-form ref="projectForm" :model="projectForm" :rules="projectRules" label-width="100px">
|
||||
<el-form-item label="所属门店" prop="dealershipId">
|
||||
<el-select v-model="projectForm.dealershipId" placeholder="请选择所属门店" style="width: 100%">
|
||||
<el-form-item label="所属机构" prop="dealershipId">
|
||||
<el-select v-model="projectForm.dealershipId" placeholder="请选择所属机构" style="width: 100%">
|
||||
<el-option
|
||||
v-for="item in storeOptions"
|
||||
:key="item.value"
|
||||
@@ -191,7 +191,7 @@ export default {
|
||||
// 表单验证规则
|
||||
projectRules: {
|
||||
dealershipId: [
|
||||
{ required: true, message: '请选择所属门店', trigger: 'change' }
|
||||
{ required: true, message: '请选择所属机构', trigger: 'change' }
|
||||
],
|
||||
projectName: [
|
||||
{ required: true, message: '请输入项目名称', trigger: 'blur' }
|
||||
@@ -200,7 +200,7 @@ export default {
|
||||
{ required: true, message: '请选择项目状态', trigger: 'change' }
|
||||
]
|
||||
},
|
||||
// 门店选项
|
||||
// 机构选项
|
||||
storeOptions: []
|
||||
}
|
||||
},
|
||||
@@ -215,7 +215,7 @@ export default {
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
this.getDealershipList() // 获取门店列表
|
||||
this.getDealershipList() // 获取机构列表
|
||||
},
|
||||
methods: {
|
||||
// 获取列表数据
|
||||
@@ -485,29 +485,29 @@ export default {
|
||||
this.$refs.projectForm.resetFields()
|
||||
},
|
||||
|
||||
// 获取门店列表
|
||||
// 获取机构列表
|
||||
getDealershipList() {
|
||||
getDealershipList().then(response => {
|
||||
console.log('门店列表响应:', response) // 调试日志
|
||||
console.log('机构列表响应:', response) // 调试日志
|
||||
if (response && response.code === 20000) {
|
||||
console.log('门店列表响应 response.data :', response.data) // 调试日志
|
||||
console.log('机构列表响应 response.data :', response.data) // 调试日志
|
||||
this.storeOptions = response.data.map(item => ({
|
||||
value: item.id,
|
||||
label: item.dealershipName
|
||||
}))
|
||||
console.log('门店选项(按修改时间倒序):', this.storeOptions)
|
||||
console.log('机构选项(按修改时间倒序):', this.storeOptions)
|
||||
} else {
|
||||
this.$message.error(response?.message || '获取门店列表失败')
|
||||
this.$message.error(response?.message || '获取机构列表失败')
|
||||
}
|
||||
}).catch(error => {
|
||||
console.error('获取门店列表失败:', error)
|
||||
console.error('获取机构列表失败:', error)
|
||||
// 开发环境使用模拟数据
|
||||
this.storeOptions = [
|
||||
{ value: 'DEAL001', label: '销售演示-奔驰' },
|
||||
{ value: 'DEAL002', label: '销售演示-上汽' },
|
||||
{ value: 'DEAL003', label: '销售演示-比亚迪' }
|
||||
]
|
||||
console.log('使用模拟门店数据:', this.storeOptions)
|
||||
console.log('使用模拟机构数据:', this.storeOptions)
|
||||
})
|
||||
},
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="所属门店">
|
||||
<el-select v-model="queryParams.dealershipId" placeholder="请选择门店" clearable>
|
||||
<el-form-item label="所属机构">
|
||||
<el-select v-model="queryParams.dealershipId" placeholder="请选择机构" clearable>
|
||||
<el-option
|
||||
v-for="item in dealershipOptions"
|
||||
:key="item.value"
|
||||
@@ -103,7 +103,7 @@
|
||||
>
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column label="序号" type="index" width="50" />
|
||||
<el-table-column label="所属门店" prop="dealershipName" min-width="150" />
|
||||
<el-table-column label="所属机构" prop="dealershipName" min-width="150" />
|
||||
<el-table-column label="视频名称" prop="videoName" min-width="200" />
|
||||
<el-table-column label="所属销售" prop="salesName" min-width="150" />
|
||||
<el-table-column label="客户姓名" prop="customerName" min-width="120" />
|
||||
@@ -141,8 +141,8 @@
|
||||
<el-form-item label="视频名称" prop="videoName">
|
||||
<el-input v-model="videoForm.videoName" placeholder="请输入视频名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="所属门店" prop="dealershipId">
|
||||
<el-select v-model="videoForm.dealershipId" placeholder="请选择所属门店" style="width: 100%">
|
||||
<el-form-item label="所属机构" prop="dealershipId">
|
||||
<el-select v-model="videoForm.dealershipId" placeholder="请选择所属机构" style="width: 100%">
|
||||
<el-option
|
||||
v-for="item in dealershipOptions"
|
||||
:key="item.value"
|
||||
@@ -211,7 +211,7 @@
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="detail-item">
|
||||
<label>所属门店:</label>
|
||||
<label>所属机构:</label>
|
||||
<span>{{ currentVideo.dealershipName }}</span>
|
||||
</div>
|
||||
</el-col>
|
||||
@@ -328,7 +328,7 @@ export default {
|
||||
{ required: true, message: '请输入视频名称', trigger: 'blur' }
|
||||
],
|
||||
dealershipId: [
|
||||
{ required: true, message: '请选择所属门店', trigger: 'change' }
|
||||
{ required: true, message: '请选择所属机构', trigger: 'change' }
|
||||
],
|
||||
salesId: [
|
||||
{ required: true, message: '请选择所属销售', trigger: 'change' }
|
||||
@@ -343,7 +343,7 @@ export default {
|
||||
{ required: true, message: '请输入视频时长', trigger: 'blur' }
|
||||
]
|
||||
},
|
||||
// 门店选项
|
||||
// 机构选项
|
||||
dealershipOptions: [],
|
||||
// 销售选项
|
||||
salesOptions: []
|
||||
@@ -429,7 +429,7 @@ export default {
|
||||
})
|
||||
},
|
||||
|
||||
// 获取门店选项
|
||||
// 获取机构选项
|
||||
getDealershipOptions() {
|
||||
getDealershipList({ size: 1000 }).then(response => {
|
||||
if (response.code === 20000) {
|
||||
@@ -439,10 +439,10 @@ export default {
|
||||
label: item.dealershipName || item.name
|
||||
}))
|
||||
} else {
|
||||
console.error('获取门店选项失败:', response.message)
|
||||
console.error('获取机构选项失败:', response.message)
|
||||
}
|
||||
}).catch(error => {
|
||||
console.error('获取门店选项错误:', error)
|
||||
console.error('获取机构选项错误:', error)
|
||||
// 开发环境使用模拟数据
|
||||
this.dealershipOptions = [
|
||||
{ value: '1', label: '销售演示-上汽' },
|
||||
|
||||
Reference in New Issue
Block a user