feat: 管理端聚合页、小程序/抖音埋点与统计、飞书线索 webhook、API 迁移与路由

- admin:OrdersHub/UsersHub、Commerce/Ops/Enterprise Hub、MpAnalytics、Feishu/小程序配置面板、鉴权存储
- api:Analytics、DataMigration、FeishuLeadWebhook、mp 事件迁移 SQL
- 微信/抖音小程序:analytics 上报与相关页面调整
- 开发文档与 scripts 补充

Made-with: Cursor
This commit is contained in:
卡若
2026-03-27 17:18:25 +08:00
parent 9601b6955b
commit aca2e263bb
188 changed files with 41937 additions and 27625 deletions

View File

@@ -2,33 +2,23 @@
Component({
data: {
selected: 0,
reviewMode: false,
list: [
{ pagePath: '/pages/index/index', text: '首页', textKey: 'home', icon: 'home' },
{ pagePath: '/pages/index/camera', text: '查看报告', textKey: 'camera', icon: 'camera' },
{ pagePath: '/pages/index/camera', text: '拍摄', textKey: 'camera', icon: 'camera' },
{ pagePath: '/pages/profile/index', text: '我的', textKey: 'profile', icon: 'user' }
]
},
lifetimes: {
attached() {
this.updateSelected()
this.checkReviewMode()
}
},
pageLifetimes: {
show() {
this.updateSelected()
this.checkReviewMode()
}
},
methods: {
checkReviewMode() {
try {
const app = getApp()
const rm = !!(app && app.globalData && app.globalData.reviewMode)
this.setData({ reviewMode: rm })
} catch (e) {}
},
updateSelected() {
try {
const pages = getCurrentPages()
@@ -66,13 +56,6 @@ Component({
} catch (e) {}
}
// 审核模式:中间按钮跳转到测试选择页而非相机
if (index === 1 && this.data.reviewMode) {
wx.navigateTo({ url: '/pages/test-select/index' })
this.setData({ selected: index })
return
}
wx.switchTab({ url })
this.setData({ selected: index })
}

View File

@@ -1,4 +1,4 @@
<!-- 自定义 tabBar顶部分割线 + 三栏中间浮起圆钮 -->
<!-- 自定义 tabBar顶部分割线 + 三栏中间单独一列避免浮钮与左右叠层 -->
<view class="tab-bar">
<view class="tab-bar-line"></view>
<view class="tab-bar-inner">
@@ -11,30 +11,22 @@
<image class="tab-icon" src="{{selected === 0 ? '/images/home-active.png' : '/images/home.png'}}" mode="aspectFit" />
<text class="tab-text">首页</text>
</view>
<!-- 审核模式:中间按钮显示"测试"文字 -->
<view
wx:if="{{reviewMode}}"
class="tab-item {{selected === 1 ? 'active' : ''}}"
data-index="1"
data-path="/pages/test-select/index"
bindtap="switchTab"
>
<image class="tab-icon" src="{{selected === 1 ? '/images/home-active.png' : '/images/home.png'}}" mode="aspectFit" />
<text class="tab-text">测试</text>
</view>
<!-- 正常模式:中间浮起拍照按钮 -->
<view
wx:else
class="tab-item-center {{selected === 1 ? 'active' : ''}}"
data-index="1"
data-path="/pages/index/camera"
bindtap="switchTab"
>
<view class="center-circle">
<image class="center-icon" src="{{selected === 1 ? '/images/camera-active.png' : '/images/camera.png'}}" mode="aspectFit" />
<!-- 中间列:与审核态无关,固定「拍摄」+ 始终进 camera -->
<view class="tab-slot-middle">
<view
class="middle-fab {{selected === 1 ? 'active' : ''}}"
data-index="1"
data-path="/pages/index/camera"
bindtap="switchTab"
>
<view class="center-circle">
<image class="center-icon" src="{{selected === 1 ? '/images/camera-active.png' : '/images/camera.png'}}" mode="aspectFit" />
</view>
<text class="tab-text tab-text-fab">拍摄</text>
</view>
<view class="center-text-placeholder"></view>
</view>
<view
class="tab-item {{selected === 2 ? 'active' : ''}}"
data-index="2"

View File

@@ -1,104 +1,116 @@
/* 自定义 tabBar白底、顶部分割线、中间浮起圆钮 */
.tab-bar {
position: fixed;
left: 0;
right: 0;
bottom: 0;
background: #ffffff;
padding-bottom: env(safe-area-inset-bottom);
z-index: 9999;
}
.tab-bar-line {
height: 1rpx;
background: #e5e7eb;
width: 100%;
}
.tab-bar-inner {
display: flex;
align-items: flex-end;
justify-content: space-around;
height: 100rpx;
padding: 0 20rpx 8rpx;
position: relative;
}
.tab-item {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-end;
padding-bottom: 8rpx;
}
.tab-icon {
width: 48rpx;
height: 48rpx;
margin-bottom: 4rpx;
}
.tab-text {
font-size: 20rpx;
color: #999999;
}
.tab-item.active .tab-text {
color: #7c3aed;
}
/* 中间项:浮起彩色圆钮 + 相机图标 */
.tab-item-center {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-end;
margin-top: -56rpx;
padding-bottom: 8rpx;
}
.center-circle {
width: 96rpx;
height: 96rpx;
min-width: 96rpx;
min-height: 96rpx;
border-radius: 50%;
background: linear-gradient(135deg, #7c3aed 0%, #a78bfa 100%);
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 4rpx;
box-shadow: 0 4rpx 20rpx rgba(124, 58, 237, 0.4);
border: 4rpx solid #ffffff;
flex-shrink: 0;
overflow: hidden;
}
.tab-item-center.active .center-circle {
background: linear-gradient(135deg, #6d28d9 0%, #7c3aed 100%);
box-shadow: 0 4rpx 20rpx rgba(124, 58, 237, 0.6);
}
.center-icon {
width: 44rpx;
height: 44rpx;
}
/* 占位:与「首页」「我的」文字等高,保证中间圆钮与两侧图标对齐 */
.center-text-placeholder {
height: 24rpx;
width: 1rpx;
visibility: hidden;
}
.tab-item-center .center-text {
color: #7c3aed;
font-size: 20rpx;
font-weight: 600;
}
.tab-item-center.active .center-text {
color: #6d28d9;
}
/* 自定义 tabBar白底、顶部分割线、中间浮起圆钮 */
.tab-bar {
position: fixed;
left: 0;
right: 0;
bottom: 0;
background: #ffffff;
padding-bottom: env(safe-area-inset-bottom);
z-index: 9999;
}
.tab-bar-line {
height: 1rpx;
background: #e5e7eb;
width: 100%;
}
.tab-bar-inner {
display: flex;
align-items: flex-end;
justify-content: space-between;
min-height: 120rpx;
padding: 12rpx 12rpx 10rpx;
position: relative;
box-sizing: border-box;
}
.tab-item {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-end;
padding-bottom: 4rpx;
z-index: 1;
}
.tab-icon {
width: 48rpx;
height: 48rpx;
margin-bottom: 4rpx;
}
.tab-text {
font-size: 20rpx;
color: #999999;
}
.tab-item.active .tab-text {
color: #7c3aed;
}
/* 中间列:独立层叠上下文,浮钮不盖住左右 tab */
.tab-slot-middle {
flex: 1;
min-width: 0;
position: relative;
z-index: 4;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-end;
padding-bottom: 4rpx;
}
/* 浮钮:略上移即可,避免压住首页主按钮 */
.middle-fab {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-end;
width: 100%;
transform: translateY(-10rpx);
margin-bottom: -6rpx;
}
.center-circle {
width: 84rpx;
height: 84rpx;
min-width: 84rpx;
min-height: 84rpx;
border-radius: 50%;
background: linear-gradient(135deg, #7c3aed 0%, #a78bfa 100%);
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 6rpx;
box-shadow: 0 4rpx 20rpx rgba(124, 58, 237, 0.4);
border: 4rpx solid #ffffff;
flex-shrink: 0;
overflow: hidden;
}
.middle-fab.active .center-circle {
background: linear-gradient(135deg, #6d28d9 0%, #7c3aed 100%);
box-shadow: 0 4rpx 20rpx rgba(124, 58, 237, 0.6);
}
.center-icon {
width: 40rpx;
height: 40rpx;
}
.tab-text-fab {
font-size: 18rpx;
color: #999999;
line-height: 1.25;
text-align: center;
max-width: 168rpx;
}
.middle-fab.active .tab-text-fab {
color: #7c3aed;
font-weight: 600;
}