diff --git a/App.vue b/App.vue
index b3681a8..74adac4 100644
--- a/App.vue
+++ b/App.vue
@@ -98,6 +98,10 @@
const isStudent = roles.includes('speaking_training_students');
const isAdmin = roles.includes('admin');
const isMeetingAdmin = roles.includes('meeting_admin');
+ const isAdminFurniture = roles.includes('admin_furniture');
+
+ // 检查是否有任何角色名等于 "furniture" 字符串(精确匹配)
+ const hasFurnitureRole = roles.includes('furniture');
// 会议相关的tab标签
const meetingTabLabels = ['总结和统计'];
@@ -107,23 +111,36 @@
const otherHidden = ['作业', '教务', '语音', '表达'];
// tabBar 顺序(根据 pages.json 中的 tabBar.list 顺序)
- // 0: 接待, 1: 客户, 2: 团队, 3: 销冠, 4: 工作台, 5: 我的(ucenter)
- // 6: 总结和统计
- const meetingTabIndices = [6]; // 会议相关tab的索引位置
+ // 0: 接待, 1: 客户, 2: 团队
+ // 3: 总结和统计, 4: 接待(furniture_reception), 5: 开始接待(common_begin_reception), 6: 客户(furniture_customer), 7: 销冠(furniture_top_sales), 8: 我的(ucenter)
+ const meetingTabIndices = [3]; // 会议相关tab的索引位置
+ const furnitureTabIndices = [4, 6, 7]; // 家具相关tab的索引位置(接待、客户、销冠)
+ const ucenterIndex = 8; // "我的"(ucenter)的索引位置
const shouldShow = (label, index) => {
- // 任何角色都应该能看到"我的"(ucenter)
+ // 任何角色都应该能看到"我的"(ucenter,索引8)
if (label === '我的') {
return true;
}
+ // admin_furniture 和 furniture 角色:显示 furniture_reception, furniture_customer, furniture_top_sales 和 ucenter
+ if (isAdminFurniture || hasFurnitureRole) {
+ // 显示家具相关的tab(索引4, 6, 7)和"我的"(索引8)
+ return furnitureTabIndices.includes(index) || index === ucenterIndex;
+ }
+
+ // 隐藏"接待"和"客户"这两个tab(索引0和1)
+ if (label === '接待' || label === '客户') {
+ return false;
+ }
+
// meeting_admin 角色:显示会议相关的tab和"我的"
if (isMeetingAdmin) {
return meetingTabIndices.includes(index);
}
- // 非 meeting_admin 角色:隐藏所有会议相关的tab
- if (meetingTabIndices.includes(index)) {
+ // 非 meeting_admin 角色:隐藏所有会议相关的tab和家具相关的tab
+ if (meetingTabIndices.includes(index) || furnitureTabIndices.includes(index)) {
return false;
}
diff --git a/custom-tab-bar/index.vue b/custom-tab-bar/index.vue
index 17864d3..3b1b281 100644
--- a/custom-tab-bar/index.vue
+++ b/custom-tab-bar/index.vue
@@ -42,20 +42,21 @@ export default {
iconPath: '/static/tabbar/team.png',
selectedIconPath: '/static/tabbar/team_active.png',
},
- {
- key: 'champion',
- text: '销冠',
- pagePath: '/pages/champion/champion',
- iconPath: '/static/tabbar/insight.png',
- selectedIconPath: '/static/tabbar/insight_active.png',
- },
- {
- key: 'workspace',
- text: '工作台',
- pagePath: '/pages/workspace/workspace',
- iconPath: '/static/tabbar/workspace.png',
- selectedIconPath: '/static/tabbar/workspace_active.png',
- },
+ // 已从导航中移除,但保留代码
+ // {
+ // key: 'champion',
+ // text: '销冠',
+ // pagePath: '/pages/champion/champion',
+ // iconPath: '/static/tabbar/insight.png',
+ // selectedIconPath: '/static/tabbar/insight_active.png',
+ // },
+ // {
+ // key: 'workspace',
+ // text: '工作台',
+ // pagePath: '/pages/workspace/workspace',
+ // iconPath: '/static/tabbar/workspace.png',
+ // selectedIconPath: '/static/tabbar/workspace_active.png',
+ // },
{
key: 'ucenter',
text: '我的',
@@ -77,6 +78,13 @@ export default {
iconPath: '/static/tabbar/reception.png',
selectedIconPath: '/static/tabbar/reception_active.png',
},
+ {
+ key: 'common_begin_reception',
+ text: '开始接待',
+ pagePath: '/pages/furniture_reception/common_begin_reception',
+ iconPath: '/static/tabbar/reception.png',
+ selectedIconPath: '/static/tabbar/reception_active.png',
+ },
{
key: 'furniture_customer',
text: '客户',
@@ -97,7 +105,37 @@ export default {
computed: {
visibleTabs() {
const allowedKeys = this.getAllowedKeys();
- return this.allTabs.filter((t) => allowedKeys.includes(t.key));
+ console.log('[TabBar][visibleTabs] STEP1 - getAllowedKeys returned:', JSON.stringify(allowedKeys));
+
+ // 创建 key 到 tab 的映射
+ const tabMap = {};
+ this.allTabs.forEach(tab => {
+ tabMap[tab.key] = tab;
+ });
+
+ // 强制将 ucenter 移到最后一个位置:先收集所有非 ucenter 的 keys,然后添加 ucenter
+ const otherKeys = [];
+ let hasUcenter = false;
+ allowedKeys.forEach(key => {
+ if (key !== 'ucenter') {
+ otherKeys.push(key);
+ } else {
+ hasUcenter = true;
+ }
+ });
+ console.log('[TabBar][visibleTabs] STEP2 - after filtering, otherKeys:', JSON.stringify(otherKeys), 'hasUcenter:', hasUcenter);
+
+ // 如果有 ucenter,将其添加到最后一个位置
+ const finalKeys = hasUcenter ? [...otherKeys, 'ucenter'] : otherKeys;
+ console.log('[TabBar][visibleTabs] STEP3 - finalKeys after moving ucenter to end:', JSON.stringify(finalKeys));
+
+ // 按照排序后的 keys 顺序返回 tabs
+ const result = finalKeys
+ .filter(key => tabMap[key])
+ .map(key => tabMap[key]);
+
+ console.log('[TabBar][visibleTabs] STEP4 - final result keys:', result.map(t => t.key), 'texts:', result.map(t => t.text));
+ return result;
},
},
created() {
@@ -219,11 +257,16 @@ export default {
// 会议相关的tab key列表
const meetingTabKeys = ['meeting_summary'];
+ // 已从导航中移除的tab key列表(代码保留但不显示)
+ const removedTabKeys = ['champion', 'workspace'];
- // admin_furniture 角色:只显示家具相关的tab和ucenter
- if (isAdminFurniture) {
+ // 检查是否有任何角色名等于 "furniture" 字符串(精确匹配)
+ const hasFurnitureRole = roles.includes('furniture');
+
+ // admin_furniture 和 furniture 角色:显示 furniture_reception, furniture_customer, furniture_top_sales 和 ucenter(相同顺序)
+ if (isAdminFurniture || hasFurnitureRole) {
const furnitureTabs = ['furniture_reception', 'furniture_customer', 'furniture_top_sales', 'ucenter'];
- console.log('[TabBar][allowed] admin_furniture ->', furnitureTabs);
+ console.log('[TabBar][allowed] furniture/admin_furniture role ->', furnitureTabs, 'roles:', roles);
return furnitureTabs;
}
@@ -236,10 +279,10 @@ export default {
// 非 meeting_admin 角色:排除所有会议相关的tab
if (isAdmin) {
- // admin 角色:显示所有tab(包括 ucenter),但排除会议相关的tab和家具相关的tab
+ // admin 角色:显示所有tab(包括 ucenter),但排除会议相关的tab、家具相关的tab、以及reception和customer
const all = this.allTabs
.map((t) => t.key)
- .filter((key) => !meetingTabKeys.includes(key) && !['furniture_reception', 'furniture_customer', 'furniture_top_sales'].includes(key));
+ .filter((key) => !meetingTabKeys.includes(key) && !['furniture_reception', 'common_begin_reception', 'furniture_customer', 'furniture_top_sales', 'reception', 'customer', ...removedTabKeys].includes(key));
// 确保 ucenter 被包含(用于"我的"页面)
console.log('[TabBar][allowed] admin ->', all, 'includes ucenter:', all.includes('ucenter'));
return all;
@@ -256,10 +299,10 @@ export default {
return studentTabs;
}
- // 其他角色:隐藏作业/教务/语音/表达,同时排除会议相关的tab和家具相关的tab,但确保包含ucenter
+ // 其他角色:隐藏作业/教务/语音/表达,同时排除会议相关的tab、家具相关的tab、以及reception和customer,但确保包含ucenter
const otherTabs = this.allTabs
.map((t) => t.key)
- .filter((key) => !['homework', 'edu', 'voice', 'expression', 'furniture_reception', 'furniture_customer', 'furniture_top_sales', ...meetingTabKeys].includes(key));
+ .filter((key) => !['homework', 'edu', 'voice', 'expression', 'furniture_reception', 'common_begin_reception', 'furniture_customer', 'furniture_top_sales', 'reception', 'customer', ...meetingTabKeys, ...removedTabKeys].includes(key));
// 确保 ucenter 被包含(任何角色都应该能看到"我的")
if (!otherTabs.includes('ucenter')) {
otherTabs.push('ucenter');
@@ -270,8 +313,8 @@ export default {
// #ifdef H5
toggleNativeTabs() {
// H5 平台自定义 tabbar 不生效,直接根据角色显隐原生 tabbar 项
- // 当前位置顺序:接待、客户、团队、销冠、工作台、我的、总结和统计、家具接待、家具客户、家具销冠
- const ORDER = ['reception', 'customer', 'team', 'champion', 'workspace', 'ucenter', 'meeting_summary', 'furniture_reception', 'furniture_customer', 'furniture_top_sales'];
+ // 当前位置顺序(根据 pages.json 中的 tabBar.list 顺序):接待、客户、团队、总结和统计、家具接待、开始接待、家具客户、家具销冠、我的
+ const ORDER = ['reception', 'customer', 'team', 'meeting_summary', 'furniture_reception', 'common_begin_reception', 'furniture_customer', 'furniture_top_sales', 'ucenter'];
const allowed = this.getAllowedKeys();
// 限制重试次数,防止渲染时机未就绪
this._h5TabRetries = (this._h5TabRetries || 0) + 1;
diff --git a/pages.json b/pages.json
index d49264a..41a6584 100644
--- a/pages.json
+++ b/pages.json
@@ -124,6 +124,12 @@
"navigationStyle": "custom"
}
},
+ {
+ "path": "pages/furniture_reception/common_begin_reception",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ },
{
"path": "pages/furniture_customer/furniture_customer",
"style": {
@@ -379,21 +385,6 @@
"iconPath": "static/tabbar/team.png",
"selectedIconPath": "static/tabbar/team_active.png",
"text": "团队"
- }, {
- "pagePath": "pages/champion/champion",
- "iconPath": "static/tabbar/insight.png",
- "selectedIconPath": "static/tabbar/insight_active.png",
- "text": "销冠"
- }, {
- "pagePath": "pages/workspace/workspace",
- "iconPath": "static/tabbar/workspace.png",
- "selectedIconPath": "static/tabbar/workspace_active.png",
- "text": "工作台"
- }, {
- "pagePath": "pages/ucenter/ucenter",
- "iconPath": "static/tabbar/me.png",
- "selectedIconPath": "static/tabbar/me_active.png",
- "text": "我的"
}, {
"pagePath": "pages/meeting_summary/meeting_summary",
"iconPath": "static/tabbar/insight.png",
@@ -404,6 +395,11 @@
"iconPath": "static/tabbar/reception.png",
"selectedIconPath": "static/tabbar/reception_active.png",
"text": "接待"
+ }, {
+ "pagePath": "pages/furniture_reception/common_begin_reception",
+ "iconPath": "static/tabbar/reception.png",
+ "selectedIconPath": "static/tabbar/reception_active.png",
+ "text": "开始接待"
}, {
"pagePath": "pages/furniture_customer/furniture_customer",
"iconPath": "static/tabbar/customer.png",
@@ -414,6 +410,11 @@
"iconPath": "static/tabbar/insight.png",
"selectedIconPath": "static/tabbar/insight_active.png",
"text": "销冠"
+ }, {
+ "pagePath": "pages/ucenter/ucenter",
+ "iconPath": "static/tabbar/me.png",
+ "selectedIconPath": "static/tabbar/me_active.png",
+ "text": "我的"
}]
},
"uniIdRouter": {
diff --git a/pages/speaking_training_edu/components/DeviceTab.vue b/pages/speaking_training_edu/components/DeviceTab.vue
index 307dbbb..45a0d41 100644
--- a/pages/speaking_training_edu/components/DeviceTab.vue
+++ b/pages/speaking_training_edu/components/DeviceTab.vue
@@ -1,463 +1,71 @@
-
-
-
- {{ filteredDeviceList.length }}台
-
-
-
-
-
- 状态
- {{ statusOptions[statusIndex] }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 刷新
-
+
+
+
+
+
+ 查看设备列表
+
-
-
-
-
-
-
- 家长电话
- {{ item.salesPhone || '-' }}
-
-
- 所属门店
- {{ item.dealershipName || '-' }}
-
-
- 创建时间
- {{ item.createTime || '-' }}
-
-
-
-
-
-
- 暂无设备记录
-
-
-
-
- 加载中...
- 没有更多了
-
-
+
+
+
diff --git a/pages/speaking_training_edu/speaking_training_edu.vue b/pages/speaking_training_edu/speaking_training_edu.vue
index cf01666..c821967 100644
--- a/pages/speaking_training_edu/speaking_training_edu.vue
+++ b/pages/speaking_training_edu/speaking_training_edu.vue
@@ -48,27 +48,7 @@ export default {
HomeworkTab,
},
onShow() {
- // 非教务老师角色,禁止停留在教务页,自动跳回接待
- try {
- // 从登录成功时缓存的后端响应中读取角色名称
- const roleName = uni.getStorageSync('backend-role-name') || '';
- const hasEduRole = roleName === 'speaking_training_teacher';
-
- if (!hasEduRole) {
- uni.showToast({
- title: '当前账号无教务权限',
- icon: 'none',
- duration: 1500,
- });
- setTimeout(() => {
- uni.switchTab({
- url: '/pages/reception/reception',
- });
- }, 800);
- }
- } catch (e) {
- console.warn('检查教务权限失败:', e);
- }
+ // 所有登录人都可以访问,已移除权限限制
},
data() {
return {
diff --git a/pages/ucenter/components/DeviceBindPopup.vue b/pages/ucenter/components/DeviceBindPopup.vue
new file mode 100644
index 0000000..ced51dd
--- /dev/null
+++ b/pages/ucenter/components/DeviceBindPopup.vue
@@ -0,0 +1,187 @@
+
+
+
+ 设备绑定
+
+ 设备编号
+
+
+
+ 家长电话
+
+
+
+ 所属门店
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/ucenter/components/DeviceListPopup.vue b/pages/ucenter/components/DeviceListPopup.vue
new file mode 100644
index 0000000..46fba63
--- /dev/null
+++ b/pages/ucenter/components/DeviceListPopup.vue
@@ -0,0 +1,519 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/ucenter/ucenter.vue b/pages/ucenter/ucenter.vue
index 3eccc06..89f12dc 100644
--- a/pages/ucenter/ucenter.vue
+++ b/pages/ucenter/ucenter.vue
@@ -35,7 +35,19 @@
- {{item.text}}
+
+ 设备总数
+ {{totalDevices}}
+
+
+ 人员总数
+ {{totalSales}}
+
+
+ 项目总数
+ {{totalProjects}}
+
+ {{item.text}}
@@ -51,6 +63,12 @@
+
+
+
+
+
+
@@ -93,8 +111,14 @@
store,
mutations
} from '@/uni_modules/uni-id-pages/common/store.js'
- import { put } from '@/common/request.js'
+ import { put, get } from '@/common/request.js'
+ import DeviceBindPopup from './components/DeviceBindPopup.vue'
+ import DeviceListPopup from './components/DeviceListPopup.vue'
export default {
+ components: {
+ DeviceBindPopup,
+ DeviceListPopup
+ },
// #ifdef APP
onBackPress({from}) {
if(from=='backbutton'){
@@ -109,17 +133,20 @@
return {
tenantId: '',
loginUserInfo: {},
+ totalDevices: 0,
+ totalSales: 0,
+ totalProjects: 0,
gridList: [{
- "text": this.$t('mine.showText'),
- "icon": "chat"
+ "text": "设备总数",
+ "icon": "gear"
},
{
- "text": this.$t('mine.showText'),
- "icon": "cloud-upload"
+ "text": "人员总数",
+ "icon": "person-filled"
},
{
- "text": this.$t('mine.showText'),
- "icon": "contact"
+ "text": "项目总数",
+ "icon": "list"
},
{
"text": '修改密码',
@@ -142,25 +169,13 @@
},
// #endif
{
- "title": this.$t('mine.signIn'),
- "to": '/pages/reception/reception',
+ "title": "设备绑定",
+ "event": 'openDeviceBind',
"icon": "compose"
},
- // #ifdef APP-PLUS
{
- "title": this.$t('mine.toEvaluate'),
- "event": 'gotoMarket',
- "icon": "star"
- },
- //#endif
- {
- "title":this.$t('mine.readArticles'),
- "to": '/pages/customer/customer',
- "icon": "flag"
- },
- {
- "title": this.$t('mine.myScore'),
- "to": '/pages/team/team',
+ "title": "设备列表",
+ "event": 'openDeviceList',
"icon": "paperplane"
}
// #ifdef APP
@@ -172,10 +187,6 @@
// #endif
],
[{
- "title": this.$t('mine.feedback'),
- "to": '/pages/champion/champion',
- "icon": "help"
- }, {
"title": this.$t('mine.settings'),
"to": '/pages/ucenter/settings/settings',
"icon": "gear"
@@ -216,6 +227,12 @@
onShow() {
// 每次显示页面时更新租户信息和登录人信息
this.loadUserInfo()
+ // 加载设备统计信息
+ this.loadDeviceStatistics()
+ // 加载销售(人员)统计信息
+ this.loadSalesStatistics()
+ // 加载项目统计信息
+ this.loadProjectStatistics()
},
computed: {
userInfo() {
@@ -254,6 +271,60 @@
console.error('加载用户信息失败:', e)
}
},
+ /**
+ * 加载设备统计信息
+ */
+ async loadDeviceStatistics() {
+ try {
+ const res = await get('/api/deviceManagement/statistics')
+
+ if (res.statusCode === 200 && res.data && res.data.success) {
+ this.totalDevices = res.data.data?.totalDevices || 0
+ } else {
+ console.error('获取设备统计信息失败:', res.data?.message || '未知错误')
+ this.totalDevices = 0
+ }
+ } catch (e) {
+ console.error('获取设备统计信息异常:', e)
+ this.totalDevices = 0
+ }
+ },
+ /**
+ * 加载销售(人员)统计信息
+ */
+ async loadSalesStatistics() {
+ try {
+ const res = await get('/api/salesManagement/statistics')
+
+ if (res.statusCode === 200 && res.data && res.data.success) {
+ this.totalSales = res.data.data?.totalSales || 0
+ } else {
+ console.error('获取销售统计信息失败:', res.data?.message || '未知错误')
+ this.totalSales = 0
+ }
+ } catch (e) {
+ console.error('获取销售统计信息异常:', e)
+ this.totalSales = 0
+ }
+ },
+ /**
+ * 加载项目统计信息
+ */
+ async loadProjectStatistics() {
+ try {
+ const res = await get('/api/projectManagement/statistics')
+
+ if (res.statusCode === 200 && res.data && res.data.success) {
+ this.totalProjects = res.data.data?.totalProjects || 0
+ } else {
+ console.error('获取项目统计信息失败:', res.data?.message || '未知错误')
+ this.totalProjects = 0
+ }
+ } catch (e) {
+ console.error('获取项目统计信息异常:', e)
+ this.totalProjects = 0
+ }
+ },
toSettings() {
uni.navigateTo({
url: "/pages/ucenter/settings/settings"
@@ -447,6 +518,29 @@
})
// #endif
},
+ /**
+ * 打开设备绑定弹窗
+ */
+ openDeviceBind() {
+ if (this.$refs.deviceBindPopup) {
+ this.$refs.deviceBindPopup.open()
+ }
+ },
+ /**
+ * 设备绑定成功回调
+ */
+ onDeviceBindSuccess() {
+ // 刷新设备统计信息
+ this.loadDeviceStatistics()
+ },
+ /**
+ * 打开设备列表弹窗
+ */
+ openDeviceList() {
+ if (this.$refs.deviceListPopup) {
+ this.$refs.deviceListPopup.open()
+ }
+ },
/**
* 打开修改密码弹窗
*/
@@ -678,6 +772,27 @@
align-items: center;
}
+ .device-text-wrapper {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ }
+
+ .device-label {
+ font-size: 14px;
+ color: #817f82;
+ line-height: 20px;
+ margin-bottom: 2px;
+ }
+
+ .device-count {
+ font-size: 18px;
+ font-weight: bold;
+ color: #007AFF;
+ line-height: 22px;
+ }
+
/*修改边线粗细示例*/
/* #ifndef APP-NVUE */