接待客户统计页面的改造

This commit is contained in:
zhonghua.li
2026-02-08 19:13:07 +08:00
parent 705ee2dff7
commit bcf25432d9
17 changed files with 1690 additions and 353 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -46,6 +46,7 @@ if (!Math) {
"./pages-subpackage/ai_features/intent_level/intent_level.js";
"./pages-subpackage/ai_features/deal_attribution/deal_attribution.js";
"./pages-subpackage/ai_features/recording_duration/recording_duration.js";
"./pages-subpackage/ai_features/customer_count/customer_count.js";
"./pages-subpackage/ai_features/opening_rate/opening_rate.js";
"./pages-subpackage/ai_features/over_commitment/over_commitment.js";
"./pages-subpackage/ai_features/red_line_touch/red_line_touch.js";

View File

@@ -54,6 +54,7 @@
"ai_features/intent_level/intent_level",
"ai_features/deal_attribution/deal_attribution",
"ai_features/recording_duration/recording_duration",
"ai_features/customer_count/customer_count",
"ai_features/opening_rate/opening_rate",
"ai_features/over_commitment/over_commitment",
"ai_features/red_line_touch/red_line_touch"

View File

@@ -38,7 +38,6 @@ const pages = [
navigationStyle: "custom"
},
componentPlaceholder: {
CustomerCountPopup: "pages-subpackage/ai_features/customer_count/customer-count-popup",
QualityCoveragePopup: "pages-subpackage/ai_features/quality_coverage/quality-coverage-popup"
}
}
@@ -273,6 +272,12 @@ const subPackages = [
navigationStyle: "custom"
}
},
{
path: "ai_features/customer_count/customer_count",
style: {
navigationStyle: "custom"
}
},
{
path: "ai_features/opening_rate/opening_rate",
style: {

View File

@@ -0,0 +1,492 @@
"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 {
const windowInfo = common_vendor.wx$1.getWindowInfo();
return {
statusBarHeight: windowInfo.statusBarHeight || 20,
windowWidth: windowInfo.windowWidth,
windowHeight: windowInfo.windowHeight
};
} catch (e) {
common_vendor.index.__f__("warn", "at pages-subpackage/ai_features/customer_count/customer_count.vue:102", "[CustomerCount] Failed to use wx.getWindowInfo, fallback to getSystemInfoSync:", e);
}
}
try {
const systemInfo = common_vendor.index.getSystemInfoSync();
return {
statusBarHeight: systemInfo.statusBarHeight || 20,
windowWidth: systemInfo.windowWidth,
windowHeight: systemInfo.windowHeight
};
} catch (e) {
common_vendor.index.__f__("error", "at pages-subpackage/ai_features/customer_count/customer_count.vue:116", "[CustomerCount] Failed to get system info:", e);
return {
statusBarHeight: 20,
windowWidth: 375,
windowHeight: 667
};
}
}
const _sfc_main = {
data() {
const systemInfo = getSystemInfo();
const statusBarHeight = systemInfo.statusBarHeight;
const navbarHeight = 44;
const statusBarHeightRpx = statusBarHeight * 2;
const navbarHeightRpx = navbarHeight * 2;
const totalNavbarHeight = statusBarHeightRpx + navbarHeightRpx;
return {
statusBarHeight,
// 状态栏高度px
contentTop: totalNavbarHeight + "rpx",
// 内容区域距离顶部的距离
contentBottom: "0rpx",
// 内容区域距离底部的距离(默认值,会在 onReady 中更新)
timeRangeOptions: ["1个月", "3个月", "6个月"],
timeRangeIndex: 0,
// 默认选择1个月
showTimeRangeDropdown: false,
// 控制下拉菜单显示
totalCustomers: "0",
todayCustomers: "0",
dataList: [],
loading: false,
chartWidth: 0,
chartHeight: 300,
chartData: []
};
},
onLoad() {
this.loadData();
this.initChartSize();
},
onReady() {
this.$nextTick(() => {
const query = common_vendor.index.createSelectorQuery().in(this);
query.select(".nav-bar").boundingClientRect((data) => {
if (data && data.height) {
const actualHeight = data.height;
const actualHeightRpx = actualHeight * 2;
const statusBarHeightRpx = this.statusBarHeight * 2;
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/customer_count/customer_count.vue:174", "[CustomerCount] 使用实际导航栏高度:", actualHeight, "px =", actualHeightRpx, "rpx, 总高度:", totalHeight, "rpx, 调整后:", adjustedHeight, "rpx");
} else {
const systemInfo = getSystemInfo();
const statusBarHeight = systemInfo.statusBarHeight;
const navbarHeight = 44;
const statusBarHeightRpx = statusBarHeight * 2;
const navbarHeightRpx = navbarHeight * 2;
const totalNavbarHeight = statusBarHeightRpx + navbarHeightRpx;
const adjustedHeight = Math.max(totalNavbarHeight - 4, 0);
this.$set(this, "contentTop", adjustedHeight + "rpx");
}
}).exec();
const queryTabbar = common_vendor.index.createSelectorQuery().in(this);
queryTabbar.select(".tabbar").boundingClientRect((tabbarData) => {
if (tabbarData && tabbarData.height) {
const tabbarHeight = tabbarData.height;
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/customer_count/customer_count.vue:198", "[CustomerCount] 使用实际tabbar高度:", tabbarHeight, "px =", tabbarHeightRpx, "rpx, 调整后:", adjustedBottom, "rpx");
} else {
this.$set(this, "contentBottom", "0rpx");
}
}).exec();
setTimeout(() => {
const query2 = common_vendor.index.createSelectorQuery().in(this);
query2.select(".nav-bar").boundingClientRect((data) => {
if (data && data.height) {
const actualHeight = data.height;
const actualHeightRpx = actualHeight * 2;
const statusBarHeightRpx = this.statusBarHeight * 2;
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/customer_count/customer_count.vue:217", "[CustomerCount] 延迟更新导航栏高度:", actualHeight, "px =", actualHeightRpx, "rpx, 总高度:", totalHeight, "rpx, 调整后:", adjustedHeight, "rpx");
}
}).exec();
const queryTabbar2 = common_vendor.index.createSelectorQuery().in(this);
queryTabbar2.select(".tabbar").boundingClientRect((tabbarData) => {
if (tabbarData && tabbarData.height) {
const tabbarHeight = tabbarData.height;
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/customer_count/customer_count.vue:229", "[CustomerCount] 延迟更新tabbar高度:", tabbarHeight, "px =", tabbarHeightRpx, "rpx, 调整后:", adjustedBottom, "rpx");
}
}).exec();
}, 200);
});
},
methods: {
goBack() {
common_vendor.index.navigateBack();
},
toggleTimeRangeDropdown() {
this.showTimeRangeDropdown = !this.showTimeRangeDropdown;
},
closeTimeRangeDropdown() {
this.showTimeRangeDropdown = false;
},
selectTimeRange(index) {
this.timeRangeIndex = index;
this.showTimeRangeDropdown = false;
this.loadData();
},
onRefresh() {
this.loadData();
},
/**
* 获取当前登录用户信息
*/
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/customer_count/customer_count.vue:266", "获取用户信息失败:", e);
return { salesId: null, salesPhone: null };
}
},
/**
* 格式化客户数
*/
formatCustomerCount(count) {
if (!count || count === 0)
return "0";
return String(count);
},
/**
* 格式化日期
*/
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/customer-statistics/sales");
const url = queryString ? `${baseUrl}?${queryString}` : baseUrl;
common_vendor.index.__f__("log", "at pages-subpackage/ai_features/customer_count/customer_count.vue:347", "[CustomerCount] 请求参数:", queryParams);
common_vendor.index.__f__("log", "at pages-subpackage/ai_features/customer_count/customer_count.vue:348", "[CustomerCount] 请求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;
const isSuccess = result.success === true || result.code === 0 || result.code === 200;
if (!isSuccess) {
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/customer_count/customer_count.vue:383", "[CustomerCount] 返回数据:", statisticsList);
common_vendor.index.__f__("log", "at pages-subpackage/ai_features/customer_count/customer_count.vue:384", "[CustomerCount] 返回结果:", result);
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/customer_count/customer_count.vue:402", "[CustomerCount] 加载数据失败:", error);
common_vendor.index.showToast({
title: error.message || "加载失败,请重试",
icon: "none",
duration: 2e3
});
} finally {
this.loading = false;
}
},
/**
* 处理统计数据
*/
processStatisticsData(statisticsList) {
if (!statisticsList || statisticsList.length === 0) {
this.totalCustomers = "0";
this.todayCustomers = "0";
this.dataList = [];
return;
}
const firstItem = statisticsList[0];
const totalCustomerCount = firstItem.salesTotalCustomerCount || firstItem.salesCustomerCount || 0;
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;
});
const todayCustomerCount = todayItem ? todayItem.salesCustomerCount || 0 : 0;
const formattedList = statisticsList.map((item) => {
const customerCount = item.salesCustomerCount || 0;
const date = this.formatDate(item.statisticsDate);
let description = "";
if (item.dealershipName) {
description = `${item.dealershipName}`;
} else if (item.salesName) {
description = `${item.salesName}的接待`;
} else {
description = "客户接待统计";
}
return {
date,
description,
count: `${this.formatCustomerCount(customerCount)}`,
// 保存原始数据,方便后续使用
rawData: item
};
});
formattedList.sort((a, b) => {
if (a.date > b.date)
return -1;
if (a.date < b.date)
return 1;
return 0;
});
this.totalCustomers = this.formatCustomerCount(totalCustomerCount);
this.todayCustomers = this.formatCustomerCount(todayCustomerCount);
this.dataList = formattedList;
common_vendor.index.__f__("log", "at pages-subpackage/ai_features/customer_count/customer_count.vue:477", "[CustomerCount] 数据处理完成:", {
totalCustomers: this.totalCustomers,
todayCustomers: this.todayCustomers,
dataListCount: this.dataList.length,
statisticsListLength: statisticsList.length
});
this.prepareChartData(statisticsList);
},
/**
* 初始化图表尺寸
*/
initChartSize() {
const systemInfo = common_vendor.index.getSystemInfoSync();
const screenWidth = systemInfo.windowWidth || 375;
this.chartWidth = screenWidth - 60;
},
/**
* 准备图表数据
*/
prepareChartData(statisticsList) {
if (!statisticsList || statisticsList.length === 0) {
this.chartData = [];
return;
}
const sortedList = [...statisticsList].sort((a, b) => {
const dateA = new Date(a.statisticsDate);
const dateB = new Date(b.statisticsDate);
return dateA - dateB;
});
this.chartData = sortedList.map((item) => ({
date: item.statisticsDate,
count: item.salesCustomerCount || 0
}));
this.$nextTick(() => {
setTimeout(() => {
this.drawChart();
}, 100);
});
},
/**
* 绘制趋势图
*/
drawChart() {
if (!this.chartData || this.chartData.length === 0) {
return;
}
const ctx = common_vendor.index.createCanvasContext("trendChart", this);
const width = this.chartWidth;
const height = this.chartHeight;
const padding = {
top: 40,
right: 20,
bottom: 50,
left: 50
};
const chartWidth = width - padding.left - padding.right;
const chartHeight = height - padding.top - padding.bottom;
ctx.clearRect(0, 0, width, height);
const counts = this.chartData.map((item) => item.count);
const maxCount = Math.max(...counts, 1);
Math.min(...counts, 0);
const yMax = Math.ceil(maxCount / 10) * 10;
const yStep = yMax / 5;
ctx.setFillStyle("#666666");
ctx.setFontSize(10);
for (let i = 0; i <= 5; i++) {
const y = padding.top + chartHeight - chartHeight / 5 * i;
const value = Math.round(yStep * i);
ctx.fillText(value.toString(), 5, y + 4);
ctx.setStrokeStyle("#e0e0e0");
ctx.setLineWidth(1);
ctx.beginPath();
ctx.moveTo(padding.left, y);
ctx.lineTo(padding.left + chartWidth, y);
ctx.stroke();
}
const dataCount = this.chartData.length;
const xStep = chartWidth / Math.max(dataCount - 1, 1);
this.chartData.forEach((item, index) => {
const x = padding.left + xStep * index;
const date = new Date(item.date);
const month = date.getMonth() + 1;
const day = date.getDate();
const label = `${month}/${day}`;
ctx.setFillStyle("#666666");
ctx.setFontSize(10);
ctx.fillText(label, x - 15, height - padding.bottom + 20);
});
ctx.setStrokeStyle("#007aff");
ctx.setLineWidth(2);
ctx.beginPath();
this.chartData.forEach((item, index) => {
const x = padding.left + xStep * index;
const y = padding.top + chartHeight - item.count / yMax * chartHeight;
if (index === 0) {
ctx.moveTo(x, y);
} else {
ctx.lineTo(x, y);
}
});
ctx.stroke();
ctx.setFillStyle("#007aff");
this.chartData.forEach((item, index) => {
const x = padding.left + xStep * index;
const y = padding.top + chartHeight - item.count / yMax * chartHeight;
ctx.beginPath();
ctx.arc(x, y, 4, 0, 2 * Math.PI);
ctx.fill();
});
ctx.setStrokeStyle("#333333");
ctx.setLineWidth(1);
ctx.beginPath();
ctx.moveTo(padding.left, padding.top);
ctx.lineTo(padding.left, padding.top + chartHeight);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(padding.left, padding.top + chartHeight);
ctx.lineTo(padding.left + chartWidth, padding.top + chartHeight);
ctx.stroke();
ctx.draw();
}
}
};
if (!Array) {
const _easycom_uni_icons2 = common_vendor.resolveComponent("uni-icons");
_easycom_uni_icons2();
}
const _easycom_uni_icons = () => "../../../uni_modules/uni-icons/components/uni-icons/uni-icons.js";
if (!Math) {
_easycom_uni_icons();
}
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
return common_vendor.e({
a: common_vendor.o((...args) => $options.goBack && $options.goBack(...args)),
b: $data.statusBarHeight + "px",
c: common_vendor.t($data.timeRangeOptions[$data.timeRangeIndex]),
d: common_vendor.p({
type: $data.showTimeRangeDropdown ? "top" : "bottom",
size: "14",
color: "#999"
}),
e: $data.showTimeRangeDropdown
}, $data.showTimeRangeDropdown ? {
f: common_vendor.f($data.timeRangeOptions, (option, index, i0) => {
return {
a: common_vendor.t(option),
b: index,
c: $data.timeRangeIndex === index ? 1 : "",
d: common_vendor.o(($event) => $options.selectTimeRange(index), index)
};
})
} : {}, {
g: common_vendor.o((...args) => $options.toggleTimeRangeDropdown && $options.toggleTimeRangeDropdown(...args)),
h: common_vendor.p({
type: "refresh",
size: "18",
color: "#2A68FF"
}),
i: common_vendor.o((...args) => $options.onRefresh && $options.onRefresh(...args)),
j: $data.showTimeRangeDropdown
}, $data.showTimeRangeDropdown ? {
k: common_vendor.o((...args) => $options.closeTimeRangeDropdown && $options.closeTimeRangeDropdown(...args))
} : {}, {
l: common_vendor.t($data.totalCustomers),
m: common_vendor.t($data.todayCustomers),
n: $data.chartWidth + "px",
o: $data.chartHeight + "px",
p: common_vendor.f($data.dataList, (item, index, i0) => {
return {
a: common_vendor.t(item.date),
b: common_vendor.t(item.description),
c: common_vendor.t(item.count),
d: index
};
}),
q: $data.contentTop,
r: $data.contentBottom
});
}
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render], ["__scopeId", "data-v-e0c5faaf"]]);
wx.createPage(MiniProgramPage);
//# sourceMappingURL=../../../../.sourcemap/mp-weixin/pages-subpackage/ai_features/customer_count/customer_count.js.map

View File

@@ -0,0 +1,6 @@
{
"navigationStyle": "custom",
"usingComponents": {
"uni-icons": "../../../uni_modules/uni-icons/components/uni-icons/uni-icons"
}
}

View File

@@ -0,0 +1 @@
<view class="feature-page data-v-e0c5faaf"><view class="page-header data-v-e0c5faaf" style="{{'padding-top:' + b}}"><view class="nav-bar data-v-e0c5faaf"><view class="nav-left data-v-e0c5faaf" bindtap="{{a}}"><text class="back-icon data-v-e0c5faaf">←</text></view><text class="nav-title data-v-e0c5faaf">接待客户数统计</text></view></view><scroll-view class="content-scroll data-v-e0c5faaf" scroll-y="true" style="{{'top:' + q + ';' + ('bottom:' + r)}}"><view class="search-toolbar data-v-e0c5faaf"><view class="toolbar-picker-wrapper data-v-e0c5faaf" bindtap="{{g}}"><view class="toolbar-picker-view data-v-e0c5faaf"><text class="toolbar-picker-text data-v-e0c5faaf">{{c}}</text><uni-icons wx:if="{{d}}" class="data-v-e0c5faaf" u-i="e0c5faaf-0" bind:__l="__l" u-p="{{d}}"></uni-icons></view><view wx:if="{{e}}" class="time-range-dropdown data-v-e0c5faaf"><view wx:for="{{f}}" wx:for-item="option" wx:key="b" class="{{['dropdown-item', 'data-v-e0c5faaf', option.c && 'dropdown-item-active']}}" catchtap="{{option.d}}"><text class="data-v-e0c5faaf">{{option.a}}</text></view></view></view><view class="toolbar-actions data-v-e0c5faaf"><view class="toolbar-btn toolbar-btn--refresh data-v-e0c5faaf" bindtap="{{i}}"><uni-icons wx:if="{{h}}" class="data-v-e0c5faaf" u-i="e0c5faaf-1" bind:__l="__l" u-p="{{h}}"></uni-icons><text class="data-v-e0c5faaf">刷新</text></view></view></view><view wx:if="{{j}}" class="dropdown-mask data-v-e0c5faaf" bindtap="{{k}}"></view><view class="stats-card data-v-e0c5faaf"><view class="stat-item data-v-e0c5faaf"><text class="stat-value data-v-e0c5faaf">{{l}}</text><text class="stat-label data-v-e0c5faaf">累计接待客户</text></view><view class="stat-item data-v-e0c5faaf"><text class="stat-value data-v-e0c5faaf">{{m}}</text><text class="stat-label data-v-e0c5faaf">今日接待客户</text></view></view><view class="chart-section data-v-e0c5faaf"><text class="section-title data-v-e0c5faaf">客户数趋势图</text><view class="chart-container data-v-e0c5faaf"><canvas canvas-id="trendChart" id="trendChart" class="chart-canvas data-v-e0c5faaf" style="{{'width:' + n + ';' + ('height:' + o)}}"></canvas></view></view><view class="data-list data-v-e0c5faaf"><text class="section-title data-v-e0c5faaf">详细数据</text><view wx:for="{{p}}" wx:for-item="item" wx:key="d" class="list-item data-v-e0c5faaf"><view class="item-left data-v-e0c5faaf"><text class="item-date data-v-e0c5faaf">{{item.a}}</text><text class="item-desc data-v-e0c5faaf">{{item.b}}</text></view><view class="item-right data-v-e0c5faaf"><text class="item-count data-v-e0c5faaf">{{item.c}}</text></view></view></view></scroll-view></view>

View File

@@ -0,0 +1,234 @@
.feature-page.data-v-e0c5faaf {
min-height: 100vh;
background: #f8f9fa;
}
.page-header.data-v-e0c5faaf {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 999;
background: #ffffff;
border-bottom: 1rpx solid #e9ecef;
}
.nav-bar.data-v-e0c5faaf {
display: flex;
align-items: center;
height: 88rpx;
padding: 0 30rpx;
}
.nav-left.data-v-e0c5faaf {
width: 60rpx;
height: 60rpx;
display: flex;
align-items: center;
justify-content: center;
margin-right: 20rpx;
}
.back-icon.data-v-e0c5faaf {
font-size: 36rpx;
color: #333333;
}
.nav-title.data-v-e0c5faaf {
flex: 1;
text-align: center;
font-size: 32rpx;
font-weight: bold;
color: #333333;
}
.content-scroll.data-v-e0c5faaf {
position: absolute;
left: 0;
right: 0;
top: 0; /* 先从顶部开始,通过内联样式动态设置 */
bottom: 0; /* 先从底部开始,通过内联样式动态设置 */
/* top和bottom值通过内联样式动态设置覆盖上面的默认值 */
padding: 0 !important;
margin: 0 !important;
box-sizing: border-box;
}
.search-toolbar.data-v-e0c5faaf {
display: flex;
flex-wrap: nowrap;
align-items: center;
gap: 8rpx;
padding: 12rpx 30rpx;
margin: 20rpx 30rpx;
background-color: #F8F8FA;
border-radius: 8rpx;
border: 1rpx solid #EFEFF2;
}
.toolbar-picker-wrapper.data-v-e0c5faaf {
position: relative;
flex: 1;
min-width: 120rpx;
max-width: 200rpx;
flex-shrink: 1;
z-index: 100;
}
.toolbar-picker-view.data-v-e0c5faaf {
height: 56rpx;
line-height: 56rpx;
background-color: #F5F6FA;
border-radius: 8rpx;
padding: 0 12rpx;
display: flex;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
}
.toolbar-picker-text.data-v-e0c5faaf {
font-size: 24rpx;
color: #333;
flex: 1;
}
.time-range-dropdown.data-v-e0c5faaf {
position: absolute;
top: calc(100% + 8rpx);
left: 0;
right: 0;
background-color: #FFFFFF;
border-radius: 8rpx;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.12);
z-index: 101;
overflow: hidden;
border: 1rpx solid #EFEFF2;
}
.dropdown-item.data-v-e0c5faaf {
padding: 20rpx 24rpx;
border-bottom: 1rpx solid #F3F4F6;
transition: background-color 0.2s ease;
}
.dropdown-item.data-v-e0c5faaf:last-child {
border-bottom: none;
}
.dropdown-item.data-v-e0c5faaf:active {
background-color: #F9FAFB;
}
.dropdown-item text.data-v-e0c5faaf {
font-size: 24rpx;
color: #333;
}
.dropdown-item-active.data-v-e0c5faaf {
background-color: #F0F7FF;
}
.dropdown-item-active text.data-v-e0c5faaf {
color: #2A68FF;
font-weight: 500;
}
.dropdown-mask.data-v-e0c5faaf {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: transparent;
z-index: 99;
}
.toolbar-actions.data-v-e0c5faaf {
display: flex;
align-items: center;
margin-left: auto;
flex-shrink: 0;
}
.toolbar-btn.data-v-e0c5faaf {
padding: 0 12rpx;
height: 56rpx;
min-width: 56rpx;
color: #2A68FF;
display: flex;
align-items: center;
justify-content: center;
gap: 4rpx;
font-size: 24rpx;
font-weight: 400;
}
.toolbar-btn text.data-v-e0c5faaf {
color: #2A68FF;
}
.stats-card.data-v-e0c5faaf {
display: flex;
margin: 20rpx 30rpx;
background: #ffffff;
border-radius: 16rpx;
padding: 40rpx 30rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}
.stat-item.data-v-e0c5faaf {
flex: 1;
text-align: center;
}
.stat-item.data-v-e0c5faaf:not(:last-child) {
border-right: 1rpx solid #e9ecef;
}
.stat-value.data-v-e0c5faaf {
display: block;
font-size: 48rpx;
font-weight: bold;
color: #007aff;
margin-bottom: 10rpx;
}
.stat-label.data-v-e0c5faaf {
display: block;
font-size: 24rpx;
color: #666666;
}
.chart-section.data-v-e0c5faaf, .data-list.data-v-e0c5faaf {
margin: 20rpx 30rpx;
background: #ffffff;
border-radius: 16rpx;
overflow: hidden;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}
.section-title.data-v-e0c5faaf {
display: block;
font-size: 32rpx;
font-weight: bold;
color: #333333;
padding: 30rpx;
border-bottom: 1rpx solid #e9ecef;
}
.chart-container.data-v-e0c5faaf {
padding: 30rpx;
display: flex;
justify-content: center;
align-items: center;
}
.chart-canvas.data-v-e0c5faaf {
display: block;
}
.list-item.data-v-e0c5faaf {
display: flex;
align-items: center;
justify-content: space-between;
padding: 30rpx;
border-bottom: 1rpx solid #f0f0f0;
}
.list-item.data-v-e0c5faaf:last-child {
border-bottom: none;
}
.item-left.data-v-e0c5faaf {
flex: 1;
}
.item-date.data-v-e0c5faaf {
display: block;
font-size: 28rpx;
font-weight: bold;
color: #333333;
margin-bottom: 8rpx;
}
.item-desc.data-v-e0c5faaf {
display: block;
font-size: 24rpx;
color: #666666;
}
.item-right.data-v-e0c5faaf {
text-align: right;
}
.item-count.data-v-e0c5faaf {
display: block;
font-size: 28rpx;
font-weight: bold;
color: #007aff;
}

View File

@@ -10,7 +10,7 @@ function getSystemInfo() {
windowHeight: windowInfo.windowHeight
};
} catch (e) {
common_vendor.index.__f__("warn", "at pages/ai_analysis/ai_analysis.vue:144", "[AIAnalysis] Failed to use wx.getWindowInfo, fallback to getSystemInfoSync:", e);
common_vendor.index.__f__("warn", "at pages/ai_analysis/ai_analysis.vue:138", "[AIAnalysis] Failed to use wx.getWindowInfo, fallback to getSystemInfoSync:", e);
}
}
try {
@@ -21,7 +21,7 @@ function getSystemInfo() {
windowHeight: systemInfo.windowHeight
};
} catch (e) {
common_vendor.index.__f__("error", "at pages/ai_analysis/ai_analysis.vue:158", "[AIAnalysis] Failed to get system info:", e);
common_vendor.index.__f__("error", "at pages/ai_analysis/ai_analysis.vue:152", "[AIAnalysis] Failed to get system info:", e);
return {
statusBarHeight: 20,
windowWidth: 375,
@@ -44,16 +44,12 @@ const _sfc_main = {
// 内容区域距离顶部的距离
contentBottom: "96rpx",
// 内容区域距离底部的距离(默认值,会在 onReady 中更新)
showCustomerCount: false,
// 是否显示接待客户数弹出框
showQualityCoverage: false,
// 是否显示质检覆盖率弹出框
subpackageLoaded: false,
// 子包是否已加载
popupsInitialized: false,
// 弹出框组件是否已初始化
openCustomerCountTrigger: 0,
// 打开接待客户数弹出框的触发器
openQualityCoverageTrigger: 0
// 打开质检覆盖率弹出框的触发器
};
@@ -78,7 +74,7 @@ const _sfc_main = {
this.$nextTick(() => {
setTimeout(() => {
this.popupsInitialized = true;
common_vendor.index.__f__("log", "at pages/ai_analysis/ai_analysis.vue:231", "[AIAnalysis] Popup components ready (using v-show)");
common_vendor.index.__f__("log", "at pages/ai_analysis/ai_analysis.vue:223", "[AIAnalysis] Popup components ready (using v-show)");
}, 500);
});
},
@@ -99,7 +95,7 @@ const _sfc_main = {
const actualHeightRpx = actualHeight * 2;
const adjustedHeight = Math.max(actualHeightRpx - 4, 0);
this.$set(this, "contentTop", adjustedHeight + "rpx");
common_vendor.index.__f__("log", "at pages/ai_analysis/ai_analysis.vue:258", "[AIAnalysis] 使用实际导航栏高度:", actualHeight, "px =", actualHeightRpx, "rpx, 调整后:", adjustedHeight, "rpx");
common_vendor.index.__f__("log", "at pages/ai_analysis/ai_analysis.vue:250", "[AIAnalysis] 使用实际导航栏高度:", actualHeight, "px =", actualHeightRpx, "rpx, 调整后:", adjustedHeight, "rpx");
} else {
const systemInfo = getSystemInfo();
const statusBarHeight = systemInfo.statusBarHeight;
@@ -118,7 +114,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/ai_analysis/ai_analysis.vue:282", "[AIAnalysis] 使用实际tabbar高度:", tabbarHeight, "px =", tabbarHeightRpx, "rpx, 调整后:", adjustedBottom, "rpx");
common_vendor.index.__f__("log", "at pages/ai_analysis/ai_analysis.vue:274", "[AIAnalysis] 使用实际tabbar高度:", tabbarHeight, "px =", tabbarHeightRpx, "rpx, 调整后:", adjustedBottom, "rpx");
} else {
this.$set(this, "contentBottom", "96rpx");
}
@@ -131,7 +127,7 @@ const _sfc_main = {
const actualHeightRpx = actualHeight * 2;
const adjustedHeight = Math.max(actualHeightRpx - 4, 0);
this.$set(this, "contentTop", adjustedHeight + "rpx");
common_vendor.index.__f__("log", "at pages/ai_analysis/ai_analysis.vue:300", "[AIAnalysis] 延迟更新导航栏高度:", actualHeight, "px =", actualHeightRpx, "rpx, 调整后:", adjustedHeight, "rpx");
common_vendor.index.__f__("log", "at pages/ai_analysis/ai_analysis.vue:292", "[AIAnalysis] 延迟更新导航栏高度:", actualHeight, "px =", actualHeightRpx, "rpx, 调整后:", adjustedHeight, "rpx");
}
}).exec();
const queryTabbar2 = common_vendor.index.createSelectorQuery().in(this);
@@ -141,7 +137,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/ai_analysis/ai_analysis.vue:312", "[AIAnalysis] 延迟更新tabbar高度:", tabbarHeight, "px =", tabbarHeightRpx, "rpx, 调整后:", adjustedBottom, "rpx");
common_vendor.index.__f__("log", "at pages/ai_analysis/ai_analysis.vue:304", "[AIAnalysis] 延迟更新tabbar高度:", tabbarHeight, "px =", tabbarHeightRpx, "rpx, 调整后:", adjustedBottom, "rpx");
}
}).exec();
}, 200);
@@ -154,30 +150,19 @@ const _sfc_main = {
common_vendor.wx$1.loadSubpackage({
name: "pages-subpackage",
success: () => {
common_vendor.index.__f__("log", "at pages/ai_analysis/ai_analysis.vue:327", "[AIAnalysis] Subpackage loaded successfully");
common_vendor.index.__f__("log", "at pages/ai_analysis/ai_analysis.vue:319", "[AIAnalysis] Subpackage loaded successfully");
this.subpackageLoaded = true;
},
fail: (err) => {
common_vendor.index.__f__("error", "at pages/ai_analysis/ai_analysis.vue:331", "[AIAnalysis] Failed to load subpackage:", err);
common_vendor.index.__f__("error", "at pages/ai_analysis/ai_analysis.vue:323", "[AIAnalysis] Failed to load subpackage:", err);
this.subpackageLoaded = true;
}
});
} else {
common_vendor.index.__f__("log", "at pages/ai_analysis/ai_analysis.vue:338", "[AIAnalysis] loadSubpackage API not available, assuming subpackage will load automatically");
common_vendor.index.__f__("log", "at pages/ai_analysis/ai_analysis.vue:330", "[AIAnalysis] loadSubpackage API not available, assuming subpackage will load automatically");
this.subpackageLoaded = true;
}
},
// 显示接待客户数弹出框
showCustomerCountPopup() {
this.showCustomerCount = true;
this.$nextTick(() => {
this.openCustomerCountTrigger++;
});
},
// 接待客户数弹出框关闭事件
onCustomerCountPopupClose() {
this.showCustomerCount = false;
},
// 显示质检覆盖率弹出框
showQualityCoveragePopup() {
this.showQualityCoverage = true;
@@ -204,12 +189,12 @@ const _sfc_main = {
goBack() {
const pages = getCurrentPages();
if (pages.length <= 1) {
common_vendor.index.__f__("log", "at pages/ai_analysis/ai_analysis.vue:393", "[AIAnalysis][goBack] 当前是第一个页面,无法返回");
common_vendor.index.__f__("log", "at pages/ai_analysis/ai_analysis.vue:371", "[AIAnalysis][goBack] 当前是第一个页面,无法返回");
return;
}
common_vendor.index.navigateBack({
fail: (err) => {
common_vendor.index.__f__("error", "at pages/ai_analysis/ai_analysis.vue:398", "[AIAnalysis][goBack] 返回失败:", err);
common_vendor.index.__f__("error", "at pages/ai_analysis/ai_analysis.vue:376", "[AIAnalysis][goBack] 返回失败:", err);
}
});
},
@@ -218,7 +203,7 @@ const _sfc_main = {
common_vendor.index.navigateTo({
url: `/${pagePath}`,
fail: (err) => {
common_vendor.index.__f__("error", "at pages/ai_analysis/ai_analysis.vue:407", "导航失败:", err);
common_vendor.index.__f__("error", "at pages/ai_analysis/ai_analysis.vue:385", "导航失败:", err);
common_vendor.index.showToast({
title: "页面跳转失败",
icon: "none"
@@ -230,9 +215,8 @@ const _sfc_main = {
};
if (!Array) {
const _easycom_uni_nav_bar2 = common_vendor.resolveComponent("uni-nav-bar");
const _component_CustomerCountPopup = common_vendor.resolveComponent("CustomerCountPopup");
const _component_QualityCoveragePopup = common_vendor.resolveComponent("QualityCoveragePopup");
(_easycom_uni_nav_bar2 + _component_CustomerCountPopup + _component_QualityCoveragePopup)();
(_easycom_uni_nav_bar2 + _component_QualityCoveragePopup)();
}
const _easycom_uni_nav_bar = () => "../../uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.js";
if (!Math) {
@@ -250,7 +234,7 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
backgroundColor: "#FFFFFF"
}),
c: common_vendor.o(($event) => $options.navigateToPage("recording_duration")),
d: common_vendor.o((...args) => $options.showCustomerCountPopup && $options.showCustomerCountPopup(...args)),
d: common_vendor.o(($event) => $options.navigateToPage("customer_count")),
e: common_vendor.o((...args) => $options.showQualityCoveragePopup && $options.showQualityCoveragePopup(...args)),
f: common_vendor.o(($event) => $options.navigateToPage("speech_rating")),
g: common_vendor.o(($event) => $options.navigateToPage("intent_level")),
@@ -260,17 +244,10 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
k: common_vendor.o(($event) => $options.navigateToPage("red_line_touch")),
l: $options.computedContentTop || $data.contentTop,
m: $data.contentBottom || "96rpx",
n: $data.showCustomerCount
}, $data.showCustomerCount ? {
o: common_vendor.o($options.onCustomerCountPopupClose),
p: common_vendor.p({
["open-trigger"]: $data.openCustomerCountTrigger
})
} : {}, {
q: $data.showQualityCoverage
n: $data.showQualityCoverage
}, $data.showQualityCoverage ? {
r: common_vendor.o($options.onQualityCoveragePopupClose),
s: common_vendor.p({
o: common_vendor.o($options.onQualityCoveragePopupClose),
p: common_vendor.p({
["open-trigger"]: $data.openQualityCoverageTrigger
})
} : {});

View File

@@ -1 +1 @@
<view class="page data-v-8462a2f1"><uni-nav-bar wx:if="{{b}}" class="data-v-8462a2f1" bindclickLeft="{{a}}" u-i="8462a2f1-0" bind:__l="__l" u-p="{{b}}"></uni-nav-bar><view class="content data-v-8462a2f1"><scroll-view class="content-scroll data-v-8462a2f1" scroll-y="true" style="{{'top:' + l + ';' + ('bottom:' + m)}}"><view class="category-section two-column data-v-8462a2f1"><view class="category-header data-v-8462a2f1"><text class="category-icon data-v-8462a2f1">📊</text><text class="category-title data-v-8462a2f1">录音和接待统计</text></view><view class="function-grid data-v-8462a2f1"><view class="function-item data-v-8462a2f1" bindtap="{{c}}"><view class="function-icon data-v-8462a2f1">⏱️</view><text class="function-name data-v-8462a2f1">录音时长</text><text class="function-desc data-v-8462a2f1">统计录音总时长</text></view><view class="function-item data-v-8462a2f1" bindtap="{{d}}"><view class="function-icon data-v-8462a2f1">👥</view><text class="function-name data-v-8462a2f1">接待客户数</text><text class="function-desc data-v-8462a2f1">统计接待客户数量</text></view></view></view><view class="category-section two-column data-v-8462a2f1"><view class="category-header data-v-8462a2f1"><text class="category-icon data-v-8462a2f1">✅</text><text class="category-title data-v-8462a2f1">质量管控</text></view><view class="function-grid data-v-8462a2f1"><view class="function-item data-v-8462a2f1" bindtap="{{e}}"><view class="function-icon data-v-8462a2f1">📊</view><text class="function-name data-v-8462a2f1">质检覆盖率</text><text class="function-desc data-v-8462a2f1">质检录音覆盖统计</text></view><view class="function-item data-v-8462a2f1" bindtap="{{f}}"><view class="function-icon data-v-8462a2f1">🗣️</view><text class="function-name data-v-8462a2f1">员工话术评分</text><text class="function-desc data-v-8462a2f1">员工沟通质量评分</text></view></view></view><view class="category-section sales-analysis data-v-8462a2f1"><view class="category-header data-v-8462a2f1"><text class="category-icon data-v-8462a2f1">📈</text><text class="category-title data-v-8462a2f1">销售分析</text></view><view class="function-grid data-v-8462a2f1"><view class="function-item full-row-item data-v-8462a2f1" bindtap="{{g}}"><view class="function-icon data-v-8462a2f1">🎯</view><text class="function-name data-v-8462a2f1">客户意向分级</text><text class="function-desc data-v-8462a2f1">客户购买意向分析</text></view><view class="function-item full-row-item data-v-8462a2f1" bindtap="{{h}}"><view class="function-icon data-v-8462a2f1">💰</view><text class="function-name data-v-8462a2f1">成交归因</text><text class="function-desc data-v-8462a2f1">成交成功因素分析</text></view><view class="function-item full-row-item new-line-item data-v-8462a2f1" bindtap="{{i}}"><view class="function-icon data-v-8462a2f1">🚪</view><text class="function-name data-v-8462a2f1">开口率</text><text class="function-desc data-v-8462a2f1">客户主动开口统计</text></view></view></view><view class="category-section two-column data-v-8462a2f1"><view class="category-header data-v-8462a2f1"><text class="category-icon data-v-8462a2f1">⚠️</text><text class="category-title data-v-8462a2f1">风险监控</text></view><view class="function-grid data-v-8462a2f1"><view class="function-item data-v-8462a2f1" bindtap="{{j}}"><view class="function-icon data-v-8462a2f1">🚨</view><text class="function-name data-v-8462a2f1">过度承诺统计</text><text class="function-desc data-v-8462a2f1">监控过度承诺情况</text></view><view class="function-item data-v-8462a2f1" bindtap="{{k}}"><view class="function-icon data-v-8462a2f1">🔴</view><text class="function-name data-v-8462a2f1">触及红线统计</text><text class="function-desc data-v-8462a2f1">违规行为监控统计</text></view></view></view></scroll-view></view><customer-count-popup wx:if="{{n}}" class="data-v-8462a2f1" bindclose="{{o}}" u-i="8462a2f1-1" bind:__l="__l" u-p="{{p}}"/><quality-coverage-popup wx:if="{{q}}" class="data-v-8462a2f1" bindclose="{{r}}" u-i="8462a2f1-2" bind:__l="__l" u-p="{{s}}"/></view>
<view class="page data-v-8462a2f1"><uni-nav-bar wx:if="{{b}}" class="data-v-8462a2f1" bindclickLeft="{{a}}" u-i="8462a2f1-0" bind:__l="__l" u-p="{{b}}"></uni-nav-bar><view class="content data-v-8462a2f1"><scroll-view class="content-scroll data-v-8462a2f1" scroll-y="true" style="{{'top:' + l + ';' + ('bottom:' + m)}}"><view class="category-section two-column data-v-8462a2f1"><view class="category-header data-v-8462a2f1"><text class="category-icon data-v-8462a2f1">📊</text><text class="category-title data-v-8462a2f1">录音和接待统计</text></view><view class="function-grid data-v-8462a2f1"><view class="function-item data-v-8462a2f1" bindtap="{{c}}"><view class="function-icon data-v-8462a2f1">⏱️</view><text class="function-name data-v-8462a2f1">录音时长</text><text class="function-desc data-v-8462a2f1">统计录音总时长</text></view><view class="function-item data-v-8462a2f1" bindtap="{{d}}"><view class="function-icon data-v-8462a2f1">👥</view><text class="function-name data-v-8462a2f1">接待客户数</text><text class="function-desc data-v-8462a2f1">统计接待客户数量</text></view></view></view><view class="category-section two-column data-v-8462a2f1"><view class="category-header data-v-8462a2f1"><text class="category-icon data-v-8462a2f1">✅</text><text class="category-title data-v-8462a2f1">质量管控</text></view><view class="function-grid data-v-8462a2f1"><view class="function-item data-v-8462a2f1" bindtap="{{e}}"><view class="function-icon data-v-8462a2f1">📊</view><text class="function-name data-v-8462a2f1">质检覆盖率</text><text class="function-desc data-v-8462a2f1">质检录音覆盖统计</text></view><view class="function-item data-v-8462a2f1" bindtap="{{f}}"><view class="function-icon data-v-8462a2f1">🗣️</view><text class="function-name data-v-8462a2f1">员工话术评分</text><text class="function-desc data-v-8462a2f1">员工沟通质量评分</text></view></view></view><view class="category-section sales-analysis data-v-8462a2f1"><view class="category-header data-v-8462a2f1"><text class="category-icon data-v-8462a2f1">📈</text><text class="category-title data-v-8462a2f1">销售分析</text></view><view class="function-grid data-v-8462a2f1"><view class="function-item full-row-item data-v-8462a2f1" bindtap="{{g}}"><view class="function-icon data-v-8462a2f1">🎯</view><text class="function-name data-v-8462a2f1">客户意向分级</text><text class="function-desc data-v-8462a2f1">客户购买意向分析</text></view><view class="function-item full-row-item data-v-8462a2f1" bindtap="{{h}}"><view class="function-icon data-v-8462a2f1">💰</view><text class="function-name data-v-8462a2f1">成交归因</text><text class="function-desc data-v-8462a2f1">成交成功因素分析</text></view><view class="function-item full-row-item new-line-item data-v-8462a2f1" bindtap="{{i}}"><view class="function-icon data-v-8462a2f1">🚪</view><text class="function-name data-v-8462a2f1">开口率</text><text class="function-desc data-v-8462a2f1">客户主动开口统计</text></view></view></view><view class="category-section two-column data-v-8462a2f1"><view class="category-header data-v-8462a2f1"><text class="category-icon data-v-8462a2f1">⚠️</text><text class="category-title data-v-8462a2f1">风险监控</text></view><view class="function-grid data-v-8462a2f1"><view class="function-item data-v-8462a2f1" bindtap="{{j}}"><view class="function-icon data-v-8462a2f1">🚨</view><text class="function-name data-v-8462a2f1">过度承诺统计</text><text class="function-desc data-v-8462a2f1">监控过度承诺情况</text></view><view class="function-item data-v-8462a2f1" bindtap="{{k}}"><view class="function-icon data-v-8462a2f1">🔴</view><text class="function-name data-v-8462a2f1">触及红线统计</text><text class="function-desc data-v-8462a2f1">违规行为监控统计</text></view></view></view></scroll-view></view><quality-coverage-popup wx:if="{{n}}" class="data-v-8462a2f1" bindclose="{{o}}" u-i="8462a2f1-1" bind:__l="__l" u-p="{{p}}"/></view>