录音时长统调整后端接口
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
import envConfig from '@/common/env.js'
|
||||
|
||||
const API_TARGETS = {
|
||||
local: 'http://localhost:8090/',
|
||||
local: 'http://localhost:8091/',
|
||||
prod: 'https://api.huayang-star.com/'
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
* apiEnv 可选:'local' | 'prod'
|
||||
*/
|
||||
export default {
|
||||
apiEnv: 'prod'
|
||||
apiEnv: 'local'
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
"port" : 8081,
|
||||
"proxy" : {
|
||||
"^/api" : {
|
||||
"target" : "http://localhost:8090",
|
||||
"target" : "http://localhost:8091",
|
||||
"changeOrigin" : true,
|
||||
"secure" : false
|
||||
}
|
||||
|
||||
@@ -79,6 +79,9 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { post } from '@/common/request.js'
|
||||
import { getApiUrl } from '@/common/config.js'
|
||||
|
||||
// 获取系统信息的辅助函数
|
||||
function getSystemInfo() {
|
||||
// #ifdef MP-WEIXIN
|
||||
@@ -133,17 +136,16 @@ export default {
|
||||
timeRangeOptions: ['1个月', '3个月', '6个月'],
|
||||
timeRangeIndex: 0, // 默认选择1个月
|
||||
showTimeRangeDropdown: false, // 控制下拉菜单显示
|
||||
totalDuration: '125.5 小时',
|
||||
todayDuration: '8.2 小时',
|
||||
dataList: [
|
||||
{ date: '2024-02-07', description: '客户咨询录音', duration: '2.5 小时' },
|
||||
{ date: '2024-02-06', description: '销售洽谈录音', duration: '3.2 小时' },
|
||||
{ date: '2024-02-05', description: '培训录音', duration: '1.8 小时' },
|
||||
{ date: '2024-02-04', description: '会议录音', duration: '4.1 小时' },
|
||||
{ date: '2024-02-03', description: '客户反馈录音', duration: '2.9 小时' }
|
||||
]
|
||||
totalDuration: '0 小时',
|
||||
todayDuration: '0 小时',
|
||||
dataList: [],
|
||||
loading: false
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
// 页面加载时获取数据
|
||||
this.loadData();
|
||||
},
|
||||
onReady() {
|
||||
// 页面渲染完成后,查询实际导航栏高度并更新位置
|
||||
this.$nextTick(() => {
|
||||
@@ -240,19 +242,235 @@ export default {
|
||||
onRefresh() {
|
||||
// 刷新数据
|
||||
this.loadData();
|
||||
uni.showToast({
|
||||
title: '刷新成功',
|
||||
icon: 'success',
|
||||
duration: 1500
|
||||
});
|
||||
},
|
||||
loadData() {
|
||||
// 根据 timeRangeIndex 加载对应时间范围的数据
|
||||
// 0 -> 1个月, 1 -> 3个月, 2 -> 6个月
|
||||
const months = this.timeRangeIndex === 0 ? 1 : (this.timeRangeIndex === 1 ? 3 : 6);
|
||||
console.log(`加载最近${months}个月的数据`);
|
||||
// TODO: 这里可以调用API加载数据
|
||||
// 示例:调用接口获取数据
|
||||
/**
|
||||
* 获取当前登录用户信息
|
||||
*/
|
||||
getCurrentUserInfo() {
|
||||
try {
|
||||
const loginResponse = uni.getStorageSync('backend-login-response') || {};
|
||||
return {
|
||||
salesId: loginResponse.userId ? String(loginResponse.userId) : null,
|
||||
salesPhone: loginResponse.phone || null
|
||||
};
|
||||
} catch (e) {
|
||||
console.error('获取用户信息失败:', e);
|
||||
return { salesId: null, salesPhone: null };
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 格式化时长(分钟转小时)
|
||||
*/
|
||||
formatDuration(minutes) {
|
||||
if (!minutes || minutes === 0) return '0 小时';
|
||||
const hours = (minutes / 60).toFixed(1);
|
||||
return `${hours} 小时`;
|
||||
},
|
||||
/**
|
||||
* 格式化日期
|
||||
*/
|
||||
formatDate(dateStr) {
|
||||
if (!dateStr) return '';
|
||||
try {
|
||||
const date = new Date(dateStr);
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
return `${year}-${month}-${day}`;
|
||||
} catch (e) {
|
||||
return dateStr;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 加载统计数据
|
||||
*/
|
||||
async loadData() {
|
||||
// 防止重复请求
|
||||
if (this.loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.loading = true;
|
||||
|
||||
try {
|
||||
// 获取当前用户信息
|
||||
const userInfo = this.getCurrentUserInfo();
|
||||
const { salesId, salesPhone } = userInfo;
|
||||
|
||||
// 验证:至少需要提供一个查询条件
|
||||
if (!salesId && !salesPhone) {
|
||||
uni.showToast({
|
||||
title: '无法获取用户信息',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
this.loading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// 根据 timeRangeIndex 确定 dateRangeType
|
||||
// 0 -> 1个月(1), 1 -> 3个月(2), 2 -> 6个月(3)
|
||||
const dateRangeType = this.timeRangeIndex + 1;
|
||||
|
||||
// 构建查询参数(后端使用 @RequestParam,参数需要作为 URL 查询参数传递)
|
||||
const queryParams = {
|
||||
dateRangeType: dateRangeType
|
||||
};
|
||||
|
||||
// 添加销售人员ID或电话号码(至少提供一个)
|
||||
if (salesId) {
|
||||
queryParams.salesId = salesId;
|
||||
}
|
||||
if (salesPhone) {
|
||||
queryParams.salesPhone = salesPhone;
|
||||
}
|
||||
|
||||
// 将参数转换为 URL 查询字符串
|
||||
const queryString = Object.keys(queryParams)
|
||||
.filter(key => queryParams[key] !== null && queryParams[key] !== undefined && queryParams[key] !== '')
|
||||
.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(queryParams[key])}`)
|
||||
.join('&');
|
||||
|
||||
// 构建完整URL
|
||||
const baseUrl = getApiUrl('/api/audio-statistics/sales');
|
||||
const url = queryString ? `${baseUrl}?${queryString}` : baseUrl;
|
||||
|
||||
console.log('[RecordingDuration] 请求参数:', queryParams);
|
||||
console.log('[RecordingDuration] 请求URL:', url);
|
||||
|
||||
// 显示加载提示
|
||||
uni.showLoading({
|
||||
title: '加载中...',
|
||||
mask: true
|
||||
});
|
||||
|
||||
// 发送POST请求(参数已在URL的query string中,data为空)
|
||||
const res = await post(url, {});
|
||||
|
||||
uni.hideLoading();
|
||||
|
||||
// 处理响应
|
||||
if (res.statusCode === 200 && res.data) {
|
||||
const result = res.data;
|
||||
|
||||
// 检查返回结果(根据项目中的返回结构)
|
||||
if (!result.success) {
|
||||
const errorMsg = result.msg || result.message || '查询失败';
|
||||
uni.showToast({
|
||||
title: errorMsg,
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
this.loading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取统计数据列表
|
||||
const statisticsList = result.data || [];
|
||||
|
||||
console.log('[RecordingDuration] 返回数据:', statisticsList);
|
||||
|
||||
// 处理统计数据
|
||||
this.processStatisticsData(statisticsList);
|
||||
|
||||
// 刷新成功后显示提示
|
||||
uni.showToast({
|
||||
title: '刷新成功',
|
||||
icon: 'success',
|
||||
duration: 1500
|
||||
});
|
||||
|
||||
} else {
|
||||
throw new Error('请求失败,状态码: ' + res.statusCode);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
uni.hideLoading();
|
||||
console.error('[RecordingDuration] 加载数据失败:', error);
|
||||
uni.showToast({
|
||||
title: error.message || '加载失败,请重试',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 处理统计数据
|
||||
*/
|
||||
processStatisticsData(statisticsList) {
|
||||
if (!statisticsList || statisticsList.length === 0) {
|
||||
// 没有数据时重置显示
|
||||
this.totalDuration = '0 小时';
|
||||
this.todayDuration = '0 小时';
|
||||
this.dataList = [];
|
||||
return;
|
||||
}
|
||||
|
||||
// 计算总录音时长和总录音数量
|
||||
let totalDurationMinutes = 0;
|
||||
let totalRecordingCount = 0;
|
||||
|
||||
// 构建数据列表
|
||||
const formattedList = statisticsList.map(item => {
|
||||
// 累计总时长(使用销售人员录音总时长)
|
||||
const salesDuration = item.salesTotalDuration || 0;
|
||||
totalDurationMinutes += salesDuration;
|
||||
totalRecordingCount += (item.salesRecordingCount || 0);
|
||||
|
||||
// 格式化日期
|
||||
const date = this.formatDate(item.statisticsDate);
|
||||
|
||||
// 构建描述信息
|
||||
let description = '';
|
||||
if (item.salesName) {
|
||||
description = `${item.salesName}的录音`;
|
||||
} else if (item.dealershipName) {
|
||||
description = `${item.dealershipName}的录音`;
|
||||
} else {
|
||||
description = '录音统计';
|
||||
}
|
||||
|
||||
return {
|
||||
date: date,
|
||||
description: description,
|
||||
duration: this.formatDuration(salesDuration),
|
||||
// 保存原始数据,方便后续使用
|
||||
rawData: item
|
||||
};
|
||||
});
|
||||
|
||||
// 按日期倒序排列(最新的在前)
|
||||
formattedList.sort((a, b) => {
|
||||
if (a.date > b.date) return -1;
|
||||
if (a.date < b.date) return 1;
|
||||
return 0;
|
||||
});
|
||||
|
||||
// 更新页面数据
|
||||
this.totalDuration = this.formatDuration(totalDurationMinutes);
|
||||
this.dataList = formattedList;
|
||||
|
||||
// 计算今日录音时长(从统计数据中查找今天的记录)
|
||||
const today = new Date();
|
||||
const todayStr = this.formatDate(today.toISOString());
|
||||
const todayItem = statisticsList.find(item => {
|
||||
const itemDate = this.formatDate(item.statisticsDate);
|
||||
return itemDate === todayStr;
|
||||
});
|
||||
|
||||
if (todayItem) {
|
||||
this.todayDuration = this.formatDuration(todayItem.salesTotalDuration || 0);
|
||||
} else {
|
||||
this.todayDuration = '0 小时';
|
||||
}
|
||||
|
||||
console.log('[RecordingDuration] 数据处理完成:', {
|
||||
totalDuration: this.totalDuration,
|
||||
todayDuration: this.todayDuration,
|
||||
dataListCount: this.dataList.length
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"file":"config.js","sources":["common/config.js"],"sourcesContent":["/**\r\n * API 配置\r\n * 统一管理后端接口地址,并根据环境自动切换\r\n */\r\n\r\nimport envConfig from '@/common/env.js'\r\n\r\nconst API_TARGETS = {\r\n\tlocal: 'http://localhost:8090/',\r\n\tprod: 'https://api.huayang-star.com/'\r\n}\r\n\r\nconst ENV_ALIAS = {\r\n\tdevelopment: 'local',\r\n\tproduction: 'prod',\r\n\tlocal: 'local',\r\n\tprod: 'prod'\r\n}\r\n\r\nfunction normalizeBaseUrl(url) {\r\n\treturn url.endsWith('/') ? url : `${url}/`\r\n}\r\n\r\nfunction resolveApiEnv() {\r\n\t// 优先读取 env.js 配置文件\r\n\tconst fileEnv = envConfig?.apiEnv\r\n\tif (fileEnv) {\r\n\t\tconst mapped = ENV_ALIAS[fileEnv.toLowerCase()]\r\n\t\tif (mapped) {\r\n\t\t\t// #ifdef APP-PLUS || H5 || MP-ALIPAY\r\n\t\t\tconsole.log('[API Config] 使用 env.js 配置:', fileEnv, '=>', mapped)\r\n\t\t\t// #endif\r\n\t\t\treturn mapped\r\n\t\t}\r\n\t}\r\n\r\n\t// 其次读取环境变量\r\n\tconst runtimeEnv =\r\n\t\ttypeof process !== 'undefined' && process?.env\r\n\t\t\t? process.env.UNI_APP_API_ENV || process.env.NODE_ENV\r\n\t\t\t: ''\r\n\tconst aliasKey = runtimeEnv ? runtimeEnv.toLowerCase() : ''\r\n\tconst env = ENV_ALIAS[aliasKey] || 'prod'\r\n\t// #ifdef APP-PLUS || H5 || MP-ALIPAY\r\n\tconsole.log('[API Config] 使用环境变量:', runtimeEnv, '=>', env)\r\n\t// #endif\r\n\treturn env\r\n}\r\n\r\nconst API_ENV = resolveApiEnv()\r\n\r\n// API 基础地址(根据当前环境自动判定)\r\nexport const API_BASE_URL = normalizeBaseUrl(API_TARGETS[API_ENV] || API_TARGETS.prod)\r\n\r\n// 输出当前配置信息(便于调试)\r\n// #ifdef APP-PLUS || H5 || MP-ALIPAY\r\nconsole.log('[API Config] 当前环境:', API_ENV)\r\nconsole.log('[API Config] API_BASE_URL:', API_BASE_URL)\r\n// #endif\r\n\r\n// 当前 API 环境(local / prod)\r\nexport function getApiEnv() {\r\n\treturn API_ENV\r\n}\r\n\r\n// 导出完整的 API URL 构建函数\r\n// H5环境下:local / prod 均直接使用完整URL,避免依赖本地代理\r\n// 其他环境使用完整URL\r\nexport function getApiUrl(path = '') {\r\n\tconst apiPath = path.startsWith('/') ? path : `/${path}`\r\n\t// #ifdef H5\r\n\t// H5环境下,local / prod 都返回完整URL,确保 prod 时直接请求远程服务器\r\n\tconst fullPath = apiPath.startsWith('/') ? apiPath.slice(1) : apiPath\r\n\tconst fullUrl = `${API_BASE_URL}${fullPath}`\r\n\t// #ifdef APP-PLUS || H5 || MP-ALIPAY\r\n\tconsole.log(`[API Config] H5环境(${API_ENV})直接使用完整URL:`, fullUrl)\r\n\t// #endif\r\n\treturn fullUrl\r\n\t// #endif\r\n\t// #ifndef H5\r\n\t// 其他环境使用完整URL\r\n\tconst fullPath = apiPath.startsWith('/') ? apiPath.slice(1) : apiPath\r\n\tconst fullUrl = `${API_BASE_URL}${fullPath}`\r\n\t// #ifdef APP-PLUS || H5 || MP-ALIPAY\r\n\tconsole.log('[API Config] 非H5环境使用完整URL:', fullUrl)\r\n\t// #endif\r\n\treturn fullUrl\r\n\t// #endif\r\n}\r\n"],"names":["envConfig"],"mappings":";;AAOA,MAAM,cAAc;AAAA,EACnB,OAAO;AAAA,EACP,MAAM;AACP;AAEA,MAAM,YAAY;AAAA,EACjB,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,MAAM;AACP;AAEA,SAAS,iBAAiB,KAAK;AAC9B,SAAO,IAAI,SAAS,GAAG,IAAI,MAAM,GAAG,GAAG;AACxC;AAEA,SAAS,gBAAgB;;AAExB,QAAM,WAAUA,gBAAW,cAAXA,mBAAW;AACd;AACZ,UAAM,SAAS,UAAU,QAAQ,YAAa,CAAA;AAC9C,QAAI,QAAQ;AAIJ,aAAA;AAAA,IACR;AAAA,EACD;AAGM,QAAA,aACL,OAAO,YAAY,gBAAe,mCAAS,OACxC,QAAQ,IAAI,mBAAmB,gBAC/B;AACJ,QAAM,WAAW,aAAa,WAAW,YAAA,IAAgB;AACnD,QAAA,MAAM,UAAU,QAAQ,KAAK;AAI5B,SAAA;AACR;AAEA,MAAM,UAAU,cAAc;AAGvB,MAAM,eAAe,iBAAiB,YAAY,OAAO,KAAK,YAAY,IAAI;AAS9E,SAAS,YAAY;AACpB,SAAA;AACR;AAKgB,SAAA,UAAU,OAAO,IAAI;AACpC,QAAM,UAAU,KAAK,WAAW,GAAG,IAAI,OAAO,IAAI,IAAI;AAYhD,QAAA,WAAW,QAAQ,WAAW,GAAG,IAAI,QAAQ,MAAM,CAAC,IAAI;AAC9D,QAAM,UAAU,GAAG,YAAY,GAAG,QAAQ;AAInC,SAAA;AAER;;;"}
|
||||
{"version":3,"file":"config.js","sources":["common/config.js"],"sourcesContent":["/**\r\n * API 配置\r\n * 统一管理后端接口地址,并根据环境自动切换\r\n */\r\n\r\nimport envConfig from '@/common/env.js'\r\n\r\nconst API_TARGETS = {\r\n\tlocal: 'http://localhost:8091/',\r\n\tprod: 'https://api.huayang-star.com/'\r\n}\r\n\r\nconst ENV_ALIAS = {\r\n\tdevelopment: 'local',\r\n\tproduction: 'prod',\r\n\tlocal: 'local',\r\n\tprod: 'prod'\r\n}\r\n\r\nfunction normalizeBaseUrl(url) {\r\n\treturn url.endsWith('/') ? url : `${url}/`\r\n}\r\n\r\nfunction resolveApiEnv() {\r\n\t// 优先读取 env.js 配置文件\r\n\tconst fileEnv = envConfig?.apiEnv\r\n\tif (fileEnv) {\r\n\t\tconst mapped = ENV_ALIAS[fileEnv.toLowerCase()]\r\n\t\tif (mapped) {\r\n\t\t\t// #ifdef APP-PLUS || H5 || MP-ALIPAY\r\n\t\t\tconsole.log('[API Config] 使用 env.js 配置:', fileEnv, '=>', mapped)\r\n\t\t\t// #endif\r\n\t\t\treturn mapped\r\n\t\t}\r\n\t}\r\n\r\n\t// 其次读取环境变量\r\n\tconst runtimeEnv =\r\n\t\ttypeof process !== 'undefined' && process?.env\r\n\t\t\t? process.env.UNI_APP_API_ENV || process.env.NODE_ENV\r\n\t\t\t: ''\r\n\tconst aliasKey = runtimeEnv ? runtimeEnv.toLowerCase() : ''\r\n\tconst env = ENV_ALIAS[aliasKey] || 'prod'\r\n\t// #ifdef APP-PLUS || H5 || MP-ALIPAY\r\n\tconsole.log('[API Config] 使用环境变量:', runtimeEnv, '=>', env)\r\n\t// #endif\r\n\treturn env\r\n}\r\n\r\nconst API_ENV = resolveApiEnv()\r\n\r\n// API 基础地址(根据当前环境自动判定)\r\nexport const API_BASE_URL = normalizeBaseUrl(API_TARGETS[API_ENV] || API_TARGETS.prod)\r\n\r\n// 输出当前配置信息(便于调试)\r\n// #ifdef APP-PLUS || H5 || MP-ALIPAY\r\nconsole.log('[API Config] 当前环境:', API_ENV)\r\nconsole.log('[API Config] API_BASE_URL:', API_BASE_URL)\r\n// #endif\r\n\r\n// 当前 API 环境(local / prod)\r\nexport function getApiEnv() {\r\n\treturn API_ENV\r\n}\r\n\r\n// 导出完整的 API URL 构建函数\r\n// H5环境下:local / prod 均直接使用完整URL,避免依赖本地代理\r\n// 其他环境使用完整URL\r\nexport function getApiUrl(path = '') {\r\n\tconst apiPath = path.startsWith('/') ? path : `/${path}`\r\n\t// #ifdef H5\r\n\t// H5环境下,local / prod 都返回完整URL,确保 prod 时直接请求远程服务器\r\n\tconst fullPath = apiPath.startsWith('/') ? apiPath.slice(1) : apiPath\r\n\tconst fullUrl = `${API_BASE_URL}${fullPath}`\r\n\t// #ifdef APP-PLUS || H5 || MP-ALIPAY\r\n\tconsole.log(`[API Config] H5环境(${API_ENV})直接使用完整URL:`, fullUrl)\r\n\t// #endif\r\n\treturn fullUrl\r\n\t// #endif\r\n\t// #ifndef H5\r\n\t// 其他环境使用完整URL\r\n\tconst fullPath = apiPath.startsWith('/') ? apiPath.slice(1) : apiPath\r\n\tconst fullUrl = `${API_BASE_URL}${fullPath}`\r\n\t// #ifdef APP-PLUS || H5 || MP-ALIPAY\r\n\tconsole.log('[API Config] 非H5环境使用完整URL:', fullUrl)\r\n\t// #endif\r\n\treturn fullUrl\r\n\t// #endif\r\n}\r\n"],"names":["envConfig"],"mappings":";;AAOA,MAAM,cAAc;AAAA,EACnB,OAAO;AAAA,EACP,MAAM;AACP;AAEA,MAAM,YAAY;AAAA,EACjB,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,MAAM;AACP;AAEA,SAAS,iBAAiB,KAAK;AAC9B,SAAO,IAAI,SAAS,GAAG,IAAI,MAAM,GAAG,GAAG;AACxC;AAEA,SAAS,gBAAgB;;AAExB,QAAM,WAAUA,gBAAW,cAAXA,mBAAW;AACd;AACZ,UAAM,SAAS,UAAU,QAAQ,YAAa,CAAA;AAC9C,QAAI,QAAQ;AAIJ,aAAA;AAAA,IACR;AAAA,EACD;AAGM,QAAA,aACL,OAAO,YAAY,gBAAe,mCAAS,OACxC,QAAQ,IAAI,mBAAmB,gBAC/B;AACJ,QAAM,WAAW,aAAa,WAAW,YAAA,IAAgB;AACnD,QAAA,MAAM,UAAU,QAAQ,KAAK;AAI5B,SAAA;AACR;AAEA,MAAM,UAAU,cAAc;AAGvB,MAAM,eAAe,iBAAiB,YAAY,OAAO,KAAK,YAAY,IAAI;AAS9E,SAAS,YAAY;AACpB,SAAA;AACR;AAKgB,SAAA,UAAU,OAAO,IAAI;AACpC,QAAM,UAAU,KAAK,WAAW,GAAG,IAAI,OAAO,IAAI,IAAI;AAYhD,QAAA,WAAW,QAAQ,WAAW,GAAG,IAAI,QAAQ,MAAM,CAAC,IAAI;AAC9D,QAAM,UAAU,GAAG,YAAY,GAAG,QAAQ;AAInC,SAAA;AAER;;;"}
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"file":"env.js","sources":["common/env.js"],"sourcesContent":["/**\r\n * 环境配置文件\r\n * apiEnv 可选:'local' | 'prod'\r\n */\r\nexport default {\r\n\tapiEnv: 'prod'\r\n}\r\n\r\n"],"names":[],"mappings":";AAIA,MAAe,YAAA;AAAA,EACd,QAAQ;AACT;;"}
|
||||
{"version":3,"file":"env.js","sources":["common/env.js"],"sourcesContent":["/**\r\n * 环境配置文件\r\n * apiEnv 可选:'local' | 'prod'\r\n */\r\nexport default {\r\n\tapiEnv: 'local'\r\n}\r\n\r\n"],"names":[],"mappings":";AAIA,MAAe,YAAA;AAAA,EACd,QAAQ;AACT;;"}
|
||||
File diff suppressed because one or more lines are too long
@@ -1,7 +1,7 @@
|
||||
"use strict";
|
||||
const common_env = require("./env.js");
|
||||
const API_TARGETS = {
|
||||
local: "http://localhost:8090/",
|
||||
local: "http://localhost:8091/",
|
||||
prod: "https://api.huayang-star.com/"
|
||||
};
|
||||
const ENV_ALIAS = {
|
||||
|
||||
2
unpackage/dist/dev/mp-weixin/common/env.js
vendored
2
unpackage/dist/dev/mp-weixin/common/env.js
vendored
@@ -1,6 +1,6 @@
|
||||
"use strict";
|
||||
const envConfig = {
|
||||
apiEnv: "prod"
|
||||
apiEnv: "local"
|
||||
};
|
||||
exports.envConfig = envConfig;
|
||||
//# sourceMappingURL=../../.sourcemap/mp-weixin/common/env.js.map
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
"use strict";
|
||||
const common_vendor = require("../../../common/vendor.js");
|
||||
const common_request = require("../../../common/request.js");
|
||||
const common_config = require("../../../common/config.js");
|
||||
function getSystemInfo() {
|
||||
if (typeof common_vendor.wx$1 !== "undefined" && common_vendor.wx$1.getWindowInfo) {
|
||||
try {
|
||||
@@ -10,7 +12,7 @@ function getSystemInfo() {
|
||||
windowHeight: windowInfo.windowHeight
|
||||
};
|
||||
} catch (e) {
|
||||
common_vendor.index.__f__("warn", "at pages-subpackage/ai_features/recording_duration/recording_duration.vue:95", "[RecordingDuration] Failed to use wx.getWindowInfo, fallback to getSystemInfoSync:", e);
|
||||
common_vendor.index.__f__("warn", "at pages-subpackage/ai_features/recording_duration/recording_duration.vue:98", "[RecordingDuration] Failed to use wx.getWindowInfo, fallback to getSystemInfoSync:", e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
@@ -21,7 +23,7 @@ function getSystemInfo() {
|
||||
windowHeight: systemInfo.windowHeight
|
||||
};
|
||||
} catch (e) {
|
||||
common_vendor.index.__f__("error", "at pages-subpackage/ai_features/recording_duration/recording_duration.vue:109", "[RecordingDuration] Failed to get system info:", e);
|
||||
common_vendor.index.__f__("error", "at pages-subpackage/ai_features/recording_duration/recording_duration.vue:112", "[RecordingDuration] Failed to get system info:", e);
|
||||
return {
|
||||
statusBarHeight: 20,
|
||||
windowWidth: 375,
|
||||
@@ -49,17 +51,15 @@ const _sfc_main = {
|
||||
// 默认选择1个月
|
||||
showTimeRangeDropdown: false,
|
||||
// 控制下拉菜单显示
|
||||
totalDuration: "125.5 小时",
|
||||
todayDuration: "8.2 小时",
|
||||
dataList: [
|
||||
{ date: "2024-02-07", description: "客户咨询录音", duration: "2.5 小时" },
|
||||
{ date: "2024-02-06", description: "销售洽谈录音", duration: "3.2 小时" },
|
||||
{ date: "2024-02-05", description: "培训录音", duration: "1.8 小时" },
|
||||
{ date: "2024-02-04", description: "会议录音", duration: "4.1 小时" },
|
||||
{ date: "2024-02-03", description: "客户反馈录音", duration: "2.9 小时" }
|
||||
]
|
||||
totalDuration: "0 小时",
|
||||
todayDuration: "0 小时",
|
||||
dataList: [],
|
||||
loading: false
|
||||
};
|
||||
},
|
||||
onLoad() {
|
||||
this.loadData();
|
||||
},
|
||||
onReady() {
|
||||
this.$nextTick(() => {
|
||||
const query = common_vendor.index.createSelectorQuery().in(this);
|
||||
@@ -71,7 +71,7 @@ const _sfc_main = {
|
||||
const totalHeight = statusBarHeightRpx + actualHeightRpx;
|
||||
const adjustedHeight = Math.max(totalHeight - 4, 0);
|
||||
this.$set(this, "contentTop", adjustedHeight + "rpx");
|
||||
common_vendor.index.__f__("log", "at pages-subpackage/ai_features/recording_duration/recording_duration.vue:163", "[RecordingDuration] 使用实际导航栏高度:", actualHeight, "px =", actualHeightRpx, "rpx, 总高度:", totalHeight, "rpx, 调整后:", adjustedHeight, "rpx");
|
||||
common_vendor.index.__f__("log", "at pages-subpackage/ai_features/recording_duration/recording_duration.vue:165", "[RecordingDuration] 使用实际导航栏高度:", actualHeight, "px =", actualHeightRpx, "rpx, 总高度:", totalHeight, "rpx, 调整后:", adjustedHeight, "rpx");
|
||||
} else {
|
||||
const systemInfo = getSystemInfo();
|
||||
const statusBarHeight = systemInfo.statusBarHeight;
|
||||
@@ -90,7 +90,7 @@ const _sfc_main = {
|
||||
const tabbarHeightRpx = tabbarHeight * 2;
|
||||
const adjustedBottom = Math.max(tabbarHeightRpx - 4, 0);
|
||||
this.$set(this, "contentBottom", adjustedBottom + "rpx");
|
||||
common_vendor.index.__f__("log", "at pages-subpackage/ai_features/recording_duration/recording_duration.vue:187", "[RecordingDuration] 使用实际tabbar高度:", tabbarHeight, "px =", tabbarHeightRpx, "rpx, 调整后:", adjustedBottom, "rpx");
|
||||
common_vendor.index.__f__("log", "at pages-subpackage/ai_features/recording_duration/recording_duration.vue:189", "[RecordingDuration] 使用实际tabbar高度:", tabbarHeight, "px =", tabbarHeightRpx, "rpx, 调整后:", adjustedBottom, "rpx");
|
||||
} else {
|
||||
this.$set(this, "contentBottom", "0rpx");
|
||||
}
|
||||
@@ -105,7 +105,7 @@ const _sfc_main = {
|
||||
const totalHeight = statusBarHeightRpx + actualHeightRpx;
|
||||
const adjustedHeight = Math.max(totalHeight - 4, 0);
|
||||
this.$set(this, "contentTop", adjustedHeight + "rpx");
|
||||
common_vendor.index.__f__("log", "at pages-subpackage/ai_features/recording_duration/recording_duration.vue:206", "[RecordingDuration] 延迟更新导航栏高度:", actualHeight, "px =", actualHeightRpx, "rpx, 总高度:", totalHeight, "rpx, 调整后:", adjustedHeight, "rpx");
|
||||
common_vendor.index.__f__("log", "at pages-subpackage/ai_features/recording_duration/recording_duration.vue:208", "[RecordingDuration] 延迟更新导航栏高度:", actualHeight, "px =", actualHeightRpx, "rpx, 总高度:", totalHeight, "rpx, 调整后:", adjustedHeight, "rpx");
|
||||
}
|
||||
}).exec();
|
||||
const queryTabbar2 = common_vendor.index.createSelectorQuery().in(this);
|
||||
@@ -115,7 +115,7 @@ const _sfc_main = {
|
||||
const tabbarHeightRpx = tabbarHeight * 2;
|
||||
const adjustedBottom = Math.max(tabbarHeightRpx - 4, 0);
|
||||
this.$set(this, "contentBottom", adjustedBottom + "rpx");
|
||||
common_vendor.index.__f__("log", "at pages-subpackage/ai_features/recording_duration/recording_duration.vue:218", "[RecordingDuration] 延迟更新tabbar高度:", tabbarHeight, "px =", tabbarHeightRpx, "rpx, 调整后:", adjustedBottom, "rpx");
|
||||
common_vendor.index.__f__("log", "at pages-subpackage/ai_features/recording_duration/recording_duration.vue:220", "[RecordingDuration] 延迟更新tabbar高度:", tabbarHeight, "px =", tabbarHeightRpx, "rpx, 调整后:", adjustedBottom, "rpx");
|
||||
}
|
||||
}).exec();
|
||||
}, 200);
|
||||
@@ -138,15 +138,181 @@ const _sfc_main = {
|
||||
},
|
||||
onRefresh() {
|
||||
this.loadData();
|
||||
common_vendor.index.showToast({
|
||||
title: "刷新成功",
|
||||
icon: "success",
|
||||
duration: 1500
|
||||
});
|
||||
},
|
||||
loadData() {
|
||||
const months = this.timeRangeIndex === 0 ? 1 : this.timeRangeIndex === 1 ? 3 : 6;
|
||||
common_vendor.index.__f__("log", "at pages-subpackage/ai_features/recording_duration/recording_duration.vue:253", `加载最近${months}个月的数据`);
|
||||
/**
|
||||
* 获取当前登录用户信息
|
||||
*/
|
||||
getCurrentUserInfo() {
|
||||
try {
|
||||
const loginResponse = common_vendor.index.getStorageSync("backend-login-response") || {};
|
||||
return {
|
||||
salesId: loginResponse.userId ? String(loginResponse.userId) : null,
|
||||
salesPhone: loginResponse.phone || null
|
||||
};
|
||||
} catch (e) {
|
||||
common_vendor.index.__f__("error", "at pages-subpackage/ai_features/recording_duration/recording_duration.vue:257", "获取用户信息失败:", e);
|
||||
return { salesId: null, salesPhone: null };
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 格式化时长(分钟转小时)
|
||||
*/
|
||||
formatDuration(minutes) {
|
||||
if (!minutes || minutes === 0)
|
||||
return "0 小时";
|
||||
const hours = (minutes / 60).toFixed(1);
|
||||
return `${hours} 小时`;
|
||||
},
|
||||
/**
|
||||
* 格式化日期
|
||||
*/
|
||||
formatDate(dateStr) {
|
||||
if (!dateStr)
|
||||
return "";
|
||||
try {
|
||||
const date = new Date(dateStr);
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, "0");
|
||||
const day = String(date.getDate()).padStart(2, "0");
|
||||
return `${year}-${month}-${day}`;
|
||||
} catch (e) {
|
||||
return dateStr;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 加载统计数据
|
||||
*/
|
||||
async loadData() {
|
||||
if (this.loading) {
|
||||
return;
|
||||
}
|
||||
this.loading = true;
|
||||
try {
|
||||
const userInfo = this.getCurrentUserInfo();
|
||||
const { salesId, salesPhone } = userInfo;
|
||||
if (!salesId && !salesPhone) {
|
||||
common_vendor.index.showToast({
|
||||
title: "无法获取用户信息",
|
||||
icon: "none",
|
||||
duration: 2e3
|
||||
});
|
||||
this.loading = false;
|
||||
return;
|
||||
}
|
||||
const dateRangeType = this.timeRangeIndex + 1;
|
||||
const queryParams = {
|
||||
dateRangeType
|
||||
};
|
||||
if (salesId) {
|
||||
queryParams.salesId = salesId;
|
||||
}
|
||||
if (salesPhone) {
|
||||
queryParams.salesPhone = salesPhone;
|
||||
}
|
||||
const queryString = Object.keys(queryParams).filter((key) => queryParams[key] !== null && queryParams[key] !== void 0 && queryParams[key] !== "").map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(queryParams[key])}`).join("&");
|
||||
const baseUrl = common_config.getApiUrl("/api/audio-statistics/sales");
|
||||
const url = queryString ? `${baseUrl}?${queryString}` : baseUrl;
|
||||
common_vendor.index.__f__("log", "at pages-subpackage/ai_features/recording_duration/recording_duration.vue:338", "[RecordingDuration] 请求参数:", queryParams);
|
||||
common_vendor.index.__f__("log", "at pages-subpackage/ai_features/recording_duration/recording_duration.vue:339", "[RecordingDuration] 请求URL:", url);
|
||||
common_vendor.index.showLoading({
|
||||
title: "加载中...",
|
||||
mask: true
|
||||
});
|
||||
const res = await common_request.post(url, {});
|
||||
common_vendor.index.hideLoading();
|
||||
if (res.statusCode === 200 && res.data) {
|
||||
const result = res.data;
|
||||
if (!result.success) {
|
||||
const errorMsg = result.msg || result.message || "查询失败";
|
||||
common_vendor.index.showToast({
|
||||
title: errorMsg,
|
||||
icon: "none",
|
||||
duration: 2e3
|
||||
});
|
||||
this.loading = false;
|
||||
return;
|
||||
}
|
||||
const statisticsList = result.data || [];
|
||||
common_vendor.index.__f__("log", "at pages-subpackage/ai_features/recording_duration/recording_duration.vue:371", "[RecordingDuration] 返回数据:", statisticsList);
|
||||
this.processStatisticsData(statisticsList);
|
||||
common_vendor.index.showToast({
|
||||
title: "刷新成功",
|
||||
icon: "success",
|
||||
duration: 1500
|
||||
});
|
||||
} else {
|
||||
throw new Error("请求失败,状态码: " + res.statusCode);
|
||||
}
|
||||
} catch (error) {
|
||||
common_vendor.index.hideLoading();
|
||||
common_vendor.index.__f__("error", "at pages-subpackage/ai_features/recording_duration/recording_duration.vue:389", "[RecordingDuration] 加载数据失败:", error);
|
||||
common_vendor.index.showToast({
|
||||
title: error.message || "加载失败,请重试",
|
||||
icon: "none",
|
||||
duration: 2e3
|
||||
});
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 处理统计数据
|
||||
*/
|
||||
processStatisticsData(statisticsList) {
|
||||
if (!statisticsList || statisticsList.length === 0) {
|
||||
this.totalDuration = "0 小时";
|
||||
this.todayDuration = "0 小时";
|
||||
this.dataList = [];
|
||||
return;
|
||||
}
|
||||
let totalDurationMinutes = 0;
|
||||
let totalRecordingCount = 0;
|
||||
const formattedList = statisticsList.map((item) => {
|
||||
const salesDuration = item.salesTotalDuration || 0;
|
||||
totalDurationMinutes += salesDuration;
|
||||
totalRecordingCount += item.salesRecordingCount || 0;
|
||||
const date = this.formatDate(item.statisticsDate);
|
||||
let description = "";
|
||||
if (item.salesName) {
|
||||
description = `${item.salesName}的录音`;
|
||||
} else if (item.dealershipName) {
|
||||
description = `${item.dealershipName}的录音`;
|
||||
} else {
|
||||
description = "录音统计";
|
||||
}
|
||||
return {
|
||||
date,
|
||||
description,
|
||||
duration: this.formatDuration(salesDuration),
|
||||
// 保存原始数据,方便后续使用
|
||||
rawData: item
|
||||
};
|
||||
});
|
||||
formattedList.sort((a, b) => {
|
||||
if (a.date > b.date)
|
||||
return -1;
|
||||
if (a.date < b.date)
|
||||
return 1;
|
||||
return 0;
|
||||
});
|
||||
this.totalDuration = this.formatDuration(totalDurationMinutes);
|
||||
this.dataList = formattedList;
|
||||
const today = /* @__PURE__ */ new Date();
|
||||
const todayStr = this.formatDate(today.toISOString());
|
||||
const todayItem = statisticsList.find((item) => {
|
||||
const itemDate = this.formatDate(item.statisticsDate);
|
||||
return itemDate === todayStr;
|
||||
});
|
||||
if (todayItem) {
|
||||
this.todayDuration = this.formatDuration(todayItem.salesTotalDuration || 0);
|
||||
} else {
|
||||
this.todayDuration = "0 小时";
|
||||
}
|
||||
common_vendor.index.__f__("log", "at pages-subpackage/ai_features/recording_duration/recording_duration.vue:469", "[RecordingDuration] 数据处理完成:", {
|
||||
totalDuration: this.totalDuration,
|
||||
todayDuration: this.todayDuration,
|
||||
dataListCount: this.dataList.length
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user