feat: 企业权限上限与迁移脚本;管理端/超管概览与财务;双端小程序 tab/订单/历史/测评选择等同步
Made-with: Cursor
This commit is contained in:
@@ -47,8 +47,8 @@ App({
|
||||
// 超管配置的默认企业 ID(无 scene/eid 等入口参数时回落)
|
||||
defaultEnterpriseId: null,
|
||||
// API基础地址(开发时用本地,生产环境替换为实际域名)
|
||||
apiBase: 'https://mbtiapi.quwanzhi.com',
|
||||
//apiBase: 'http://mbti.com',
|
||||
//apiBase: 'https://mbtiapi.quwanzhi.com',
|
||||
apiBase: 'http://mbti.com',
|
||||
// VIP信息
|
||||
vipInfo: null,
|
||||
// 测试次数
|
||||
@@ -59,7 +59,9 @@ App({
|
||||
mbtiResult: null,
|
||||
discResult: null,
|
||||
pdpResult: null,
|
||||
aiResult: null
|
||||
aiResult: null,
|
||||
// 企业功能权限(超管在企业管理中配置):null=无限制(个人版),对象时按 key 控制
|
||||
enterprisePermissions: null
|
||||
},
|
||||
|
||||
onLaunch(launchOptions) {
|
||||
@@ -69,30 +71,85 @@ App({
|
||||
// 加载本地存储的数据
|
||||
this.loadStoredData()
|
||||
|
||||
// 静默登录获取openId
|
||||
this.silentLogin()
|
||||
|
||||
// 上报应用启动事件
|
||||
try {
|
||||
const analytics = require('./utils/analytics.js')
|
||||
analytics.reportAppLaunch(launchOptions)
|
||||
} catch (e) {}
|
||||
|
||||
// 预加载站点/小程序名称、维护模式与面相审核模式(camera/首页文案)
|
||||
this.getRuntimeConfig().then((cfg) => {
|
||||
if (cfg) {
|
||||
if (cfg.siteTitle) this.globalData.siteTitle = cfg.siteTitle
|
||||
if (cfg.maintenanceMode !== undefined) this.globalData.maintenanceMode = !!cfg.maintenanceMode
|
||||
if (typeof cfg.reviewMode === 'boolean') {
|
||||
this.globalData.reviewMode = cfg.reviewMode
|
||||
// 必须先完成静默登录再拉 runtime:否则无 token 时 enterprisePermissions 永远 null,清除缓存后必现「要二次刷新」
|
||||
this.silentLogin()
|
||||
.catch(() => {})
|
||||
.then(() => this.getRuntimeConfig())
|
||||
.then(() => {
|
||||
this._afterRuntimeSynced()
|
||||
})
|
||||
.catch(() => {})
|
||||
},
|
||||
|
||||
/**
|
||||
* runtime 写入 globalData 后,同步当前栈顶页面与 tabBar(避免首屏用旧 null 权限)
|
||||
*/
|
||||
_afterRuntimeSynced() {
|
||||
try {
|
||||
const pages = getCurrentPages()
|
||||
if (!pages || pages.length === 0) return
|
||||
const top = pages[pages.length - 1]
|
||||
if (!top) return
|
||||
const gd = this.globalData
|
||||
const ep = gd.enterprisePermissions
|
||||
const audit = !!(gd.reviewMode || gd.maintenanceMode)
|
||||
const permFace = !ep || ep.face !== false
|
||||
|
||||
if (typeof top.getTabBar === 'function') {
|
||||
const tb = top.getTabBar()
|
||||
if (tb && typeof tb.updateSelected === 'function') tb.updateSelected()
|
||||
}
|
||||
|
||||
const route = top.route || ''
|
||||
if (route === 'pages/index/index' && typeof top.setData === 'function') {
|
||||
top.setData({
|
||||
reviewMode: audit,
|
||||
permFace,
|
||||
siteTitle: audit ? String(gd.siteTitle || '神仙团队性格测试').replace(/AI/gi, '') : (gd.siteTitle || '神仙团队性格测试'),
|
||||
startButtonText: (audit || (ep && ep.face === false)) ? '开始性格测试' : ((gd.textConfig && gd.textConfig.startButtonText) || '拍摄'),
|
||||
aiAnalysisText: audit ? '分析' : ((gd.textConfig && gd.textConfig.aiAnalysisText) || '分析')
|
||||
})
|
||||
} else if (route === 'pages/profile/index' && typeof top.setData === 'function') {
|
||||
if (typeof top._syncPerms === 'function') top._syncPerms.call(top)
|
||||
top.setData({ reviewMode: audit })
|
||||
if (typeof top.getTabBar === 'function') {
|
||||
const tb = top.getTabBar()
|
||||
if (tb && typeof tb.updateSelected === 'function') tb.updateSelected()
|
||||
}
|
||||
if (cfg.defaultEnterpriseId != null && Number(cfg.defaultEnterpriseId) > 0) {
|
||||
this.globalData.defaultEnterpriseId = Number(cfg.defaultEnterpriseId)
|
||||
} else {
|
||||
this.globalData.defaultEnterpriseId = null
|
||||
} else if (route === 'pages/enterprise/index' && typeof top.setData === 'function') {
|
||||
const maintenanceMode = audit
|
||||
const pf = permFace
|
||||
top.setData({
|
||||
maintenanceMode,
|
||||
reviewMode: maintenanceMode,
|
||||
permFace: pf,
|
||||
siteTitle: gd.siteTitle || '神仙团队AI性格测试',
|
||||
startButtonEnterprise: (maintenanceMode || !pf) ? '开始性格测试' : ((gd.textConfig && gd.textConfig.startButtonEnterprise) || '开始面部测试'),
|
||||
aiAnalysisText: (gd.textConfig && gd.textConfig.aiAnalysisText) || '智能分析'
|
||||
})
|
||||
if (typeof top.getTabBar === 'function') {
|
||||
const tb = top.getTabBar()
|
||||
if (tb && typeof tb.updateSelected === 'function') tb.updateSelected()
|
||||
}
|
||||
} else if (route === 'pages/index/camera' && typeof top.setData === 'function') {
|
||||
top.setData({ reviewMode: audit })
|
||||
if (ep && ep.face === false) {
|
||||
wx.navigateTo({ url: '/pages/test-select/index' })
|
||||
}
|
||||
if (typeof top.getTabBar === 'function') {
|
||||
const tb = top.getTabBar()
|
||||
if (tb && typeof tb.updateSelected === 'function') tb.updateSelected()
|
||||
}
|
||||
}
|
||||
}).catch(() => {})
|
||||
} catch (e) {
|
||||
console.error('_afterRuntimeSynced', e)
|
||||
}
|
||||
},
|
||||
|
||||
onShow() {
|
||||
@@ -386,6 +443,7 @@ App({
|
||||
* @returns {Promise<{pricingType, pricing, aiProviderId, aiProviderName}>}
|
||||
*/
|
||||
getRuntimeConfig() {
|
||||
const reqId = (this._runtimeReqSeq = (this._runtimeReqSeq || 0) + 1)
|
||||
return new Promise((resolve, reject) => {
|
||||
const scope = this.globalData.appScope || 'personal'
|
||||
const base = this.globalData.apiBase.replace(/\/$/, '')
|
||||
@@ -396,6 +454,10 @@ App({
|
||||
method: 'GET',
|
||||
header: token ? { Authorization: 'Bearer ' + token } : {},
|
||||
success: (res) => {
|
||||
if (reqId !== this._runtimeReqSeq) {
|
||||
resolve(null)
|
||||
return
|
||||
}
|
||||
if (res.statusCode === 200 && res.data && res.data.code === 200) {
|
||||
const data = res.data.data || {}
|
||||
if (data.siteTitle) this.globalData.siteTitle = data.siteTitle
|
||||
@@ -411,6 +473,11 @@ App({
|
||||
} else {
|
||||
this.globalData.defaultEnterpriseId = null
|
||||
}
|
||||
if (data.enterprisePermissions && typeof data.enterprisePermissions === 'object') {
|
||||
this.globalData.enterprisePermissions = data.enterprisePermissions
|
||||
} else {
|
||||
this.globalData.enterprisePermissions = null
|
||||
}
|
||||
resolve(data)
|
||||
} else {
|
||||
reject(new Error(res.data && res.data.message ? res.data.message : '获取配置失败'))
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
Component({
|
||||
data: {
|
||||
selected: 0,
|
||||
/** 审核模式:为 true 时隐藏中间「拍摄」入口(与 globalData.reviewMode / maintenanceMode 一致) */
|
||||
/** 审核模式 */
|
||||
reviewMode: false,
|
||||
/** 为 true 时隐藏中间「拍摄」:审核模式 或 企业权限关闭 face */
|
||||
hideMiddleFab: false,
|
||||
list: [
|
||||
{ pagePath: '/pages/index/index', text: '首页', textKey: 'home', icon: 'home' },
|
||||
{ pagePath: '/pages/index/camera', text: '拍摄', textKey: 'camera', icon: 'camera' },
|
||||
@@ -30,18 +32,20 @@ Component({
|
||||
const url = currentPage.route
|
||||
const gd = getApp().globalData || {}
|
||||
const reviewMode = !!(gd.reviewMode || gd.maintenanceMode)
|
||||
const ep = gd.enterprisePermissions
|
||||
const hideMiddleFab = reviewMode || !!(ep && ep.face === false)
|
||||
let selected = 0
|
||||
if (url === 'pages/index/index' || url === 'pages/enterprise/index') {
|
||||
selected = 0
|
||||
} else if (url === 'pages/index/camera') {
|
||||
selected = 1
|
||||
selected = hideMiddleFab ? 0 : 1
|
||||
} else if (url === 'pages/profile/index') {
|
||||
selected = 2
|
||||
}
|
||||
this.setData({ selected, reviewMode })
|
||||
this.setData({ selected, reviewMode, hideMiddleFab })
|
||||
} catch (error) {
|
||||
console.error('updateSelected error:', error)
|
||||
this.setData({ selected: 0, reviewMode: false })
|
||||
this.setData({ selected: 0, reviewMode: false, hideMiddleFab: false })
|
||||
}
|
||||
},
|
||||
switchTab(e) {
|
||||
@@ -49,7 +53,8 @@ Component({
|
||||
let url = e.currentTarget.dataset.path
|
||||
|
||||
const gd = getApp().globalData || {}
|
||||
if (index === 1 && !!(gd.reviewMode || gd.maintenanceMode)) {
|
||||
const faceOff = !!(gd.enterprisePermissions && gd.enterprisePermissions.face === false)
|
||||
if (index === 1 && (!!(gd.reviewMode || gd.maintenanceMode) || faceOff)) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!-- 自定义 tabBar:顶部分割线 + 三栏;中间单独一列避免浮钮与左右叠层 -->
|
||||
<view class="tab-bar">
|
||||
<view class="tab-bar-line"></view>
|
||||
<view class="tab-bar-inner {{reviewMode ? 'tab-bar-inner--audit' : ''}}">
|
||||
<view class="tab-bar-inner {{hideMiddleFab ? 'tab-bar-inner--audit' : ''}}">
|
||||
<view
|
||||
class="tab-item {{selected === 0 ? 'active' : ''}}"
|
||||
data-index="0"
|
||||
@@ -13,7 +13,7 @@
|
||||
</view>
|
||||
|
||||
<!-- 中间列:非审核模式显示「拍摄」 -->
|
||||
<view class="tab-slot-middle" wx:if="{{!reviewMode}}">
|
||||
<view class="tab-slot-middle" wx:if="{{!hideMiddleFab}}">
|
||||
<view
|
||||
class="middle-fab {{selected === 1 ? 'active' : ''}}"
|
||||
data-index="1"
|
||||
|
||||
@@ -10,7 +10,9 @@ Page({
|
||||
siteTitle: '神仙团队AI性格测试',
|
||||
startButtonEnterprise: '开始面部测试',
|
||||
aiAnalysisText: '智能分析',
|
||||
maintenanceMode: false
|
||||
maintenanceMode: false,
|
||||
reviewMode: false,
|
||||
permFace: true
|
||||
},
|
||||
|
||||
onLoad(options) {
|
||||
@@ -62,13 +64,17 @@ Page({
|
||||
const navbarHeightRpx = statusBarHeightRpx + 88
|
||||
const gd = app.globalData
|
||||
const maintenanceMode = !!(gd.reviewMode || gd.maintenanceMode)
|
||||
const ep = gd.enterprisePermissions
|
||||
const pf = !ep || ep.face !== false
|
||||
this.setData({
|
||||
statusBarHeight: statusBarHeightRpx,
|
||||
navbarHeight: navbarHeightRpx,
|
||||
siteTitle: gd.siteTitle || '神仙团队AI性格测试',
|
||||
startButtonEnterprise: maintenanceMode ? '开始性格测试' : ((gd.textConfig && gd.textConfig.startButtonEnterprise) || '开始面部测试'),
|
||||
startButtonEnterprise: (maintenanceMode || !pf) ? '开始性格测试' : ((gd.textConfig && gd.textConfig.startButtonEnterprise) || '开始面部测试'),
|
||||
aiAnalysisText: (gd.textConfig && gd.textConfig.aiAnalysisText) || '智能分析',
|
||||
maintenanceMode
|
||||
maintenanceMode,
|
||||
reviewMode: maintenanceMode,
|
||||
permFace: pf
|
||||
})
|
||||
|
||||
// 未绑定企业的用户:扫码带 eid 或超管配置了默认企业时也允许使用企业版
|
||||
@@ -92,10 +98,14 @@ Page({
|
||||
if (cfg.reviewMode !== undefined || cfg.maintenanceMode !== undefined) {
|
||||
app.globalData.reviewMode = !!(cfg.reviewMode || cfg.maintenanceMode)
|
||||
}
|
||||
const ep2 = app.globalData.enterprisePermissions
|
||||
const pf2 = !ep2 || ep2.face !== false
|
||||
this.setData({
|
||||
startButtonEnterprise: maintenanceMode ? '开始性格测试' : (cfg.textConfig && cfg.textConfig.startButtonEnterprise || '开始面部测试'),
|
||||
startButtonEnterprise: (maintenanceMode || !pf2) ? '开始性格测试' : (cfg.textConfig && cfg.textConfig.startButtonEnterprise || '开始面部测试'),
|
||||
aiAnalysisText: (cfg.textConfig && cfg.textConfig.aiAnalysisText) || '智能分析',
|
||||
maintenanceMode
|
||||
maintenanceMode,
|
||||
reviewMode: maintenanceMode,
|
||||
permFace: pf2
|
||||
})
|
||||
}
|
||||
}).catch(() => {})
|
||||
@@ -120,10 +130,14 @@ Page({
|
||||
if (cfg.reviewMode !== undefined || cfg.maintenanceMode !== undefined) {
|
||||
app.globalData.reviewMode = !!(cfg.reviewMode || cfg.maintenanceMode)
|
||||
}
|
||||
const ep3 = app.globalData.enterprisePermissions
|
||||
const pf3 = !ep3 || ep3.face !== false
|
||||
this.setData({
|
||||
startButtonEnterprise: maintenanceMode ? '开始性格测试' : (cfg.textConfig && cfg.textConfig.startButtonEnterprise || '开始面部测试'),
|
||||
startButtonEnterprise: (maintenanceMode || !pf3) ? '开始性格测试' : (cfg.textConfig && cfg.textConfig.startButtonEnterprise || '开始面部测试'),
|
||||
aiAnalysisText: (cfg.textConfig && cfg.textConfig.aiAnalysisText) || '智能分析',
|
||||
maintenanceMode
|
||||
maintenanceMode,
|
||||
reviewMode: maintenanceMode,
|
||||
permFace: pf3
|
||||
})
|
||||
}
|
||||
if ((cfg && cfg.pricingType) !== 'enterprise' && !app.globalData.enterpriseIdFromScene && !(app.globalData.defaultEnterpriseId && Number(app.globalData.defaultEnterpriseId) > 0)) {
|
||||
@@ -157,18 +171,20 @@ Page({
|
||||
onShow() {
|
||||
if (typeof this.getTabBar === 'function' && this.getTabBar()) {
|
||||
const tabBar = this.getTabBar()
|
||||
const gd = getApp().globalData || {}
|
||||
const audit = !!(gd.reviewMode || gd.maintenanceMode)
|
||||
tabBar.setData({ selected: 0, reviewMode: audit })
|
||||
if (typeof tabBar.updateSelected === 'function') tabBar.updateSelected()
|
||||
}
|
||||
try { getApp().globalData.appScope = 'enterprise' } catch (e) {}
|
||||
const gd = getApp().globalData
|
||||
const maintenanceMode = !!(gd.reviewMode || gd.maintenanceMode)
|
||||
const ep4 = gd.enterprisePermissions
|
||||
const pf4 = !ep4 || ep4.face !== false
|
||||
this.setData({
|
||||
siteTitle: gd.siteTitle || '神仙团队AI性格测试',
|
||||
startButtonEnterprise: maintenanceMode ? '开始性格测试' : ((gd.textConfig && gd.textConfig.startButtonEnterprise) || '开始面部测试'),
|
||||
startButtonEnterprise: (maintenanceMode || !pf4) ? '开始性格测试' : ((gd.textConfig && gd.textConfig.startButtonEnterprise) || '开始面部测试'),
|
||||
aiAnalysisText: (gd.textConfig && gd.textConfig.aiAnalysisText) || '智能分析',
|
||||
maintenanceMode
|
||||
maintenanceMode,
|
||||
reviewMode: maintenanceMode,
|
||||
permFace: pf4
|
||||
})
|
||||
},
|
||||
|
||||
@@ -181,7 +197,8 @@ Page({
|
||||
|
||||
// 开始AI面部测试(先校验是否已上传简历,再跳转相机);审核模式下直接跳转 test-select
|
||||
startAITest() {
|
||||
if (this.data.maintenanceMode) {
|
||||
const ep = getApp().globalData.enterprisePermissions
|
||||
if (this.data.maintenanceMode || (ep && ep.face === false)) {
|
||||
wx.navigateTo({ url: '/pages/test-select/index' })
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,80 +1,80 @@
|
||||
<!--pages/enterprise/index.wxml - 企业版首页-->
|
||||
<view class="container" style="padding-top: {{navbarHeight}}px;">
|
||||
<!-- 自定义导航栏 -->
|
||||
<view class="custom-navbar" style="padding-top: {{statusBarHeight}}rpx;">
|
||||
<view class="navbar-content">
|
||||
<view class="switch-personal-btn" bindtap="switchToPersonal">
|
||||
<text class="personal-icon">👤</text>
|
||||
<text class="personal-text">个人版</text>
|
||||
</view>
|
||||
<view class="navbar-title">{{siteTitle || '神仙团队性格测试'}}</view>
|
||||
<view class="navbar-placeholder"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 背景装饰 -->
|
||||
<view class="bg-decoration bg-top-right"></view>
|
||||
<view class="bg-decoration bg-bottom-left"></view>
|
||||
|
||||
<view class="top-image-section">
|
||||
<view class="image-container">
|
||||
<view class="image-wrapper">
|
||||
<image class="main-image" src="/images/mbti-team-image.png" mode="aspectFit"></image>
|
||||
</view>
|
||||
<view class="float-tag tag-1" wx:if="{{!reviewMode}}">面相分析</view>
|
||||
<view class="float-tag tag-2" wx:if="{{!reviewMode}}">骨相分析</view>
|
||||
<view class="float-tag tag-3">性格测评</view>
|
||||
<view class="float-tag tag-1" wx:if="{{reviewMode}}">MBTI</view>
|
||||
<view class="float-tag tag-2" wx:if="{{reviewMode}}">DISC</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="process-section">
|
||||
<view class="section-title">测试流程</view>
|
||||
<view class="process-steps" wx:if="{{!reviewMode}}">
|
||||
<view class="step-item">
|
||||
<view class="step-circle active">1</view>
|
||||
<text class="step-label">STEP1</text>
|
||||
<text class="step-text">拍摄照片</text>
|
||||
</view>
|
||||
<view class="step-line"></view>
|
||||
<view class="step-item">
|
||||
<view class="step-circle">2</view>
|
||||
<text class="step-label">STEP2</text>
|
||||
<text class="step-text">{{aiAnalysisText || '分析'}}</text>
|
||||
</view>
|
||||
<view class="step-line"></view>
|
||||
<view class="step-item">
|
||||
<view class="step-circle">3</view>
|
||||
<text class="step-label">STEP3</text>
|
||||
<text class="step-text">生成报告</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="process-steps" wx:if="{{reviewMode}}">
|
||||
<view class="step-item">
|
||||
<view class="step-circle active">1</view>
|
||||
<text class="step-label">STEP1</text>
|
||||
<text class="step-text">选择测试</text>
|
||||
</view>
|
||||
<view class="step-line"></view>
|
||||
<view class="step-item">
|
||||
<view class="step-circle">2</view>
|
||||
<text class="step-label">STEP2</text>
|
||||
<text class="step-text">回答问题</text>
|
||||
</view>
|
||||
<view class="step-line"></view>
|
||||
<view class="step-item">
|
||||
<view class="step-circle">3</view>
|
||||
<text class="step-label">STEP3</text>
|
||||
<text class="step-text">查看结果</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="start-button" bindtap="startAITest">
|
||||
<text class="button-text">{{startButtonEnterprise || '开始性格测试'}}</text>
|
||||
</view>
|
||||
|
||||
<!-- 自定义底部导航 -->
|
||||
<custom-tab-bar />
|
||||
</view>
|
||||
<!--pages/enterprise/index.wxml - 企业版首页-->
|
||||
<view class="container" style="padding-top: {{navbarHeight}}px;">
|
||||
<!-- 自定义导航栏 -->
|
||||
<view class="custom-navbar" style="padding-top: {{statusBarHeight}}rpx;">
|
||||
<view class="navbar-content">
|
||||
<view class="switch-personal-btn" bindtap="switchToPersonal">
|
||||
<text class="personal-icon">👤</text>
|
||||
<text class="personal-text">个人版</text>
|
||||
</view>
|
||||
<view class="navbar-title">{{siteTitle || '神仙团队性格测试'}}</view>
|
||||
<view class="navbar-placeholder"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 背景装饰 -->
|
||||
<view class="bg-decoration bg-top-right"></view>
|
||||
<view class="bg-decoration bg-bottom-left"></view>
|
||||
|
||||
<view class="top-image-section">
|
||||
<view class="image-container">
|
||||
<view class="image-wrapper">
|
||||
<image class="main-image" src="/images/mbti-team-image.png" mode="aspectFit"></image>
|
||||
</view>
|
||||
<view class="float-tag tag-1" wx:if="{{!reviewMode && permFace}}">面相分析</view>
|
||||
<view class="float-tag tag-2" wx:if="{{!reviewMode && permFace}}">骨相分析</view>
|
||||
<view class="float-tag tag-3">性格测评</view>
|
||||
<view class="float-tag tag-1" wx:if="{{reviewMode}}">MBTI</view>
|
||||
<view class="float-tag tag-2" wx:if="{{reviewMode}}">DISC</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="process-section">
|
||||
<view class="section-title">测试流程</view>
|
||||
<view class="process-steps" wx:if="{{!reviewMode && permFace}}">
|
||||
<view class="step-item">
|
||||
<view class="step-circle active">1</view>
|
||||
<text class="step-label">STEP1</text>
|
||||
<text class="step-text">拍摄照片</text>
|
||||
</view>
|
||||
<view class="step-line"></view>
|
||||
<view class="step-item">
|
||||
<view class="step-circle">2</view>
|
||||
<text class="step-label">STEP2</text>
|
||||
<text class="step-text">{{aiAnalysisText || '分析'}}</text>
|
||||
</view>
|
||||
<view class="step-line"></view>
|
||||
<view class="step-item">
|
||||
<view class="step-circle">3</view>
|
||||
<text class="step-label">STEP3</text>
|
||||
<text class="step-text">生成报告</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="process-steps" wx:if="{{reviewMode || !permFace}}">
|
||||
<view class="step-item">
|
||||
<view class="step-circle active">1</view>
|
||||
<text class="step-label">STEP1</text>
|
||||
<text class="step-text">选择测试</text>
|
||||
</view>
|
||||
<view class="step-line"></view>
|
||||
<view class="step-item">
|
||||
<view class="step-circle">2</view>
|
||||
<text class="step-label">STEP2</text>
|
||||
<text class="step-text">回答问题</text>
|
||||
</view>
|
||||
<view class="step-line"></view>
|
||||
<view class="step-item">
|
||||
<view class="step-circle">3</view>
|
||||
<text class="step-label">STEP3</text>
|
||||
<text class="step-text">查看结果</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="start-button" bindtap="startAITest">
|
||||
<text class="button-text">{{startButtonEnterprise || '开始性格测试'}}</text>
|
||||
</view>
|
||||
|
||||
<!-- 自定义底部导航 -->
|
||||
<custom-tab-bar />
|
||||
</view>
|
||||
|
||||
@@ -8,9 +8,16 @@ Page({
|
||||
tabName: '',
|
||||
list: [],
|
||||
total: 0,
|
||||
page: 1,
|
||||
hasMore: false,
|
||||
loading: false,
|
||||
loadingMore: false,
|
||||
isEnterprise: false,
|
||||
reviewMode: false
|
||||
reviewMode: false,
|
||||
permMbti: true,
|
||||
permPdp: true,
|
||||
permDisc: true,
|
||||
permFace: true
|
||||
},
|
||||
|
||||
_checkIsEnterprise() {
|
||||
@@ -21,54 +28,111 @@ Page({
|
||||
return scope === 'enterprise' || !!enterpriseId
|
||||
},
|
||||
|
||||
_syncPermsAndTab() {
|
||||
const p = app.globalData.enterprisePermissions
|
||||
const permMbti = !p || p.mbti !== false
|
||||
const permPdp = !p || p.pdp !== false
|
||||
const permDisc = !p || p.disc !== false
|
||||
const permFace = !p || p.face !== false
|
||||
const reviewMode = !!app.globalData.reviewMode
|
||||
const names = { all: '', mbti: 'MBTI', pdp: 'PDP', disc: 'DISC', ai: '面相', resume: '简历' }
|
||||
let { activeTab } = this.data
|
||||
if (activeTab === 'mbti' && !permMbti) activeTab = 'all'
|
||||
if (activeTab === 'pdp' && !permPdp) activeTab = 'all'
|
||||
if (activeTab === 'disc' && !permDisc) activeTab = 'all'
|
||||
if (activeTab === 'ai' && (!permFace || reviewMode)) activeTab = 'all'
|
||||
this.setData({
|
||||
permMbti, permPdp, permDisc, permFace, reviewMode,
|
||||
activeTab,
|
||||
tabName: names[activeTab] || ''
|
||||
})
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
this.setData({ isEnterprise: this._checkIsEnterprise() })
|
||||
this._syncPermsAndTab()
|
||||
this.loadAll()
|
||||
},
|
||||
|
||||
onShow() {
|
||||
this.setData({ isEnterprise: this._checkIsEnterprise(), reviewMode: !!app.globalData.reviewMode })
|
||||
this.setData({ isEnterprise: this._checkIsEnterprise() })
|
||||
this._syncPermsAndTab()
|
||||
this.loadAll()
|
||||
if (typeof this.getTabBar === 'function' && this.getTabBar()) {
|
||||
this.getTabBar().setData({ selected: 1 })
|
||||
const tb = this.getTabBar()
|
||||
if (typeof tb.updateSelected === 'function') tb.updateSelected()
|
||||
}
|
||||
},
|
||||
|
||||
// 一次拉取全部历史(pageSize=500)
|
||||
/** 首屏/切换 Tab:接口默认 pageSize=10,更多走 loadMore */
|
||||
loadAll() {
|
||||
if (this.data.loading) return
|
||||
this.setData({ loading: true, list: [] })
|
||||
this.setData({ loading: true, list: [], page: 1, hasMore: false, loadingMore: false })
|
||||
this._fetchHistoryPage(1, false)
|
||||
},
|
||||
|
||||
/** 触底加载下一页 */
|
||||
loadMore() {
|
||||
if (!this.data.hasMore || this.data.loadingMore || this.data.loading) return
|
||||
const next = this.data.page + 1
|
||||
this.setData({ loadingMore: true })
|
||||
this._fetchHistoryPage(next, true)
|
||||
},
|
||||
|
||||
onReachBottom() {
|
||||
this.loadMore()
|
||||
},
|
||||
|
||||
_fetchHistoryPage(pageNum, append) {
|
||||
const token = app.globalData.token || wx.getStorageSync('token')
|
||||
const apiBase = app.globalData.apiBase
|
||||
const { activeTab } = this.data
|
||||
const typeParam = activeTab === 'all' ? '' : `&type=${activeTab}`
|
||||
|
||||
if (!token || !apiBase) {
|
||||
this.setData({ loading: false })
|
||||
this.setData({ loading: false, loadingMore: false })
|
||||
this.loadFromStorage()
|
||||
return
|
||||
}
|
||||
|
||||
wx.request({
|
||||
url: `${apiBase}/api/test/history?page=1&pageSize=500${typeParam}&scope=all`,
|
||||
url: `${apiBase}/api/test/history?page=${pageNum}&pageSize=10${typeParam}&scope=all`,
|
||||
method: 'GET',
|
||||
header: { Authorization: `Bearer ${token}` },
|
||||
success: (res) => {
|
||||
if (res.statusCode === 200 && res.data && res.data.data) {
|
||||
const payload = res.data.data
|
||||
const rawList = Array.isArray(payload) ? payload : (payload.list || [])
|
||||
const total = Array.isArray(payload) ? rawList.length : (payload.total || 0)
|
||||
const rawList = payload.list || []
|
||||
const formatted = this.formatList(rawList)
|
||||
this.setData({ list: formatted, total, loading: false })
|
||||
const total = typeof payload.total === 'number' ? payload.total : formatted.length
|
||||
const hasMore = !!payload.hasMore
|
||||
if (append) {
|
||||
this.setData({
|
||||
list: this.data.list.concat(formatted),
|
||||
total,
|
||||
hasMore,
|
||||
page: pageNum,
|
||||
loadingMore: false,
|
||||
loading: false
|
||||
})
|
||||
} else {
|
||||
this.setData({
|
||||
list: formatted,
|
||||
total,
|
||||
hasMore,
|
||||
page: pageNum,
|
||||
loading: false,
|
||||
loadingMore: false
|
||||
})
|
||||
}
|
||||
} else {
|
||||
this.setData({ loading: false })
|
||||
this.loadFromStorage()
|
||||
this.setData({ loading: false, loadingMore: false })
|
||||
if (!append) this.loadFromStorage()
|
||||
}
|
||||
},
|
||||
fail: () => {
|
||||
this.setData({ loading: false })
|
||||
this.loadFromStorage()
|
||||
this.setData({ loading: false, loadingMore: false })
|
||||
if (!append) this.loadFromStorage()
|
||||
}
|
||||
})
|
||||
},
|
||||
@@ -79,7 +143,8 @@ Page({
|
||||
|
||||
return rawList.map((item, idx) => {
|
||||
if (item.typeName) {
|
||||
return { ...item, enterpriseName: item.enterpriseName || '' }
|
||||
const t = String(item.testType || item.type || 'mbti').toLowerCase()
|
||||
return { ...item, type: t, enterpriseName: item.enterpriseName || '' }
|
||||
}
|
||||
const testType = (item.testType || item.type || 'mbti').toLowerCase()
|
||||
const ts = item.createdAt || item.testTime || item.timestamp
|
||||
@@ -97,16 +162,17 @@ Page({
|
||||
|
||||
// 本地缓存回退
|
||||
loadFromStorage() {
|
||||
const { permMbti, permPdp, permDisc, permFace, reviewMode } = this.data
|
||||
const mbtiResult = wx.getStorageSync('mbtiResult')
|
||||
const discResult = wx.getStorageSync('discResult')
|
||||
const pdpResult = wx.getStorageSync('pdpResult')
|
||||
const aiResult = wx.getStorageSync('aiResult')
|
||||
const list = []
|
||||
if (mbtiResult) list.push({ type: 'mbti', key: 'mbti', emoji: '🧠', typeName: 'MBTI性格测试', resultText: mbtiResult.mbtiType || '未知', testTime: this.formatTime(mbtiResult.timestamp), data: mbtiResult })
|
||||
if (pdpResult) list.push({ type: 'pdp', key: 'pdp', emoji: pdpResult.description?.emoji || '🦁', typeName: 'PDP行为偏好测试', resultText: pdpResult.description?.type || '未知', testTime: this.formatTime(pdpResult.timestamp || pdpResult.completedAt), data: pdpResult })
|
||||
if (discResult) list.push({ type: 'disc', key: 'disc', emoji: '📊', typeName: 'DISC性格测试', resultText: (discResult.dominantType || '未知') + '型', testTime: this.formatTime(discResult.timestamp || discResult.completedAt), data: discResult })
|
||||
if (aiResult && !app.globalData.reviewMode) list.push({ type: 'ai', key: 'ai', emoji: '👁️', typeName: '面相分析', resultText: aiResult.mbti || '未知', testTime: this.formatTime(aiResult.timestamp || aiResult.completedAt), data: aiResult })
|
||||
this.setData({ list, total: list.length, loading: false })
|
||||
if (mbtiResult && permMbti) list.push({ type: 'mbti', key: 'mbti', emoji: '🧠', typeName: 'MBTI性格测试', resultText: mbtiResult.mbtiType || '未知', testTime: this.formatTime(mbtiResult.timestamp), data: mbtiResult })
|
||||
if (pdpResult && permPdp) list.push({ type: 'pdp', key: 'pdp', emoji: pdpResult.description?.emoji || '🦁', typeName: 'PDP行为偏好测试', resultText: pdpResult.description?.type || '未知', testTime: this.formatTime(pdpResult.timestamp || pdpResult.completedAt), data: pdpResult })
|
||||
if (discResult && permDisc) list.push({ type: 'disc', key: 'disc', emoji: '📊', typeName: 'DISC性格测试', resultText: (discResult.dominantType || '未知') + '型', testTime: this.formatTime(discResult.timestamp || discResult.completedAt), data: discResult })
|
||||
if (aiResult && permFace && !reviewMode) list.push({ type: 'ai', key: 'ai', emoji: '👁️', typeName: '面相分析', resultText: aiResult.mbti || '未知', testTime: this.formatTime(aiResult.timestamp || aiResult.completedAt), data: aiResult })
|
||||
this.setData({ list, total: list.length, page: 1, hasMore: false, loading: false, loadingMore: false })
|
||||
},
|
||||
|
||||
changeTab(e) {
|
||||
|
||||
@@ -7,21 +7,18 @@
|
||||
<view class="tab-item {{activeTab === 'all' ? 'active' : ''}}" bindtap="changeTab" data-tab="all">
|
||||
<text class="tab-text">全部</text>
|
||||
</view>
|
||||
<view class="tab-item {{activeTab === 'mbti' ? 'active' : ''}}" bindtap="changeTab" data-tab="mbti">
|
||||
<view wx:if="{{permMbti}}" class="tab-item {{activeTab === 'mbti' ? 'active' : ''}}" bindtap="changeTab" data-tab="mbti">
|
||||
<text class="tab-text">MBTI</text>
|
||||
</view>
|
||||
<view class="tab-item {{activeTab === 'pdp' ? 'active' : ''}}" bindtap="changeTab" data-tab="pdp">
|
||||
<view wx:if="{{permPdp}}" class="tab-item {{activeTab === 'pdp' ? 'active' : ''}}" bindtap="changeTab" data-tab="pdp">
|
||||
<text class="tab-text">PDP</text>
|
||||
</view>
|
||||
<view class="tab-item {{activeTab === 'disc' ? 'active' : ''}}" bindtap="changeTab" data-tab="disc">
|
||||
<view wx:if="{{permDisc}}" class="tab-item {{activeTab === 'disc' ? 'active' : ''}}" bindtap="changeTab" data-tab="disc">
|
||||
<text class="tab-text">DISC</text>
|
||||
</view>
|
||||
<view wx:if="{{!reviewMode}}" class="tab-item {{activeTab === 'ai' ? 'active' : ''}}" bindtap="changeTab" data-tab="ai">
|
||||
<view wx:if="{{!reviewMode && permFace}}" class="tab-item {{activeTab === 'ai' ? 'active' : ''}}" bindtap="changeTab" data-tab="ai">
|
||||
<text class="tab-text">面相</text>
|
||||
</view>
|
||||
<view wx:if="{{isEnterprise}}" class="tab-item {{activeTab === 'resume' ? 'active' : ''}}" bindtap="changeTab" data-tab="resume">
|
||||
<text class="tab-text">简历</text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
@@ -57,11 +54,12 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载中 -->
|
||||
<view class="load-more-row" wx:if="{{loading}}">
|
||||
<text class="load-more-text">加载中...</text>
|
||||
<view class="load-more-row" wx:if="{{loadingMore}}">
|
||||
<text class="load-more-text">加载更多...</text>
|
||||
</view>
|
||||
<view wx:elif="{{hasMore && list.length > 0}}" class="load-more-row">
|
||||
<text class="load-more-text">上拉或继续滑动加载更多</text>
|
||||
</view>
|
||||
|
||||
<view wx:elif="{{list.length > 0}}" class="load-more-row">
|
||||
<text class="load-more-text no-more">共 {{total}} 条</text>
|
||||
</view>
|
||||
|
||||
@@ -72,16 +72,22 @@ Page({
|
||||
|
||||
onShow() {
|
||||
const rm = this._audit()
|
||||
const faceOff = !!(app.globalData.enterprisePermissions && app.globalData.enterprisePermissions.face === false)
|
||||
this.setData({ reviewMode: rm })
|
||||
|
||||
if (typeof this.getTabBar === 'function' && this.getTabBar()) {
|
||||
this.getTabBar().setData({ selected: 1, reviewMode: rm })
|
||||
const tb = this.getTabBar()
|
||||
if (typeof tb.updateSelected === 'function') tb.updateSelected()
|
||||
}
|
||||
|
||||
// 审核模式:只展示本页引导,不再强跳 navigateTo(失败时曾导致白屏且无拍摄区)
|
||||
if (rm) {
|
||||
return
|
||||
}
|
||||
if (faceOff) {
|
||||
wx.navigateTo({ url: '/pages/test-select/index' })
|
||||
return
|
||||
}
|
||||
|
||||
if (!ensureProfileCompleteAndRedirect()) {
|
||||
return
|
||||
|
||||
@@ -10,7 +10,8 @@ Page({
|
||||
siteTitle: '神仙团队性格测试',
|
||||
startButtonText: '开始性格测试',
|
||||
aiAnalysisText: '分析',
|
||||
reviewMode: true
|
||||
reviewMode: true,
|
||||
permFace: true
|
||||
},
|
||||
|
||||
onLoad(options) {
|
||||
@@ -25,6 +26,8 @@ Page({
|
||||
const userInfo = getApp().globalData.userInfo || wx.getStorageSync('userInfo') || {}
|
||||
const gd = getApp().globalData
|
||||
const rm0 = !!(gd.reviewMode || gd.maintenanceMode)
|
||||
const ep = gd.enterprisePermissions
|
||||
const pf = !ep || ep.face !== false
|
||||
this.setData({
|
||||
statusBarHeight: statusBarHeightRpx,
|
||||
navbarHeight: navbarHeightRpx,
|
||||
@@ -32,7 +35,8 @@ Page({
|
||||
siteTitle: rm0 ? (gd.siteTitle || '神仙团队性格测试').replace(/AI/gi, '') : (gd.siteTitle || '神仙团队性格测试'),
|
||||
startButtonText: rm0 ? '开始性格测试' : ((gd.textConfig && gd.textConfig.startButtonText) || '拍摄'),
|
||||
aiAnalysisText: rm0 ? '分析' : ((gd.textConfig && gd.textConfig.aiAnalysisText) || '分析'),
|
||||
reviewMode: rm0
|
||||
reviewMode: rm0,
|
||||
permFace: pf
|
||||
})
|
||||
// 预加载站点名称与文案配置
|
||||
app.getRuntimeConfig().then((cfg) => {
|
||||
@@ -53,7 +57,8 @@ Page({
|
||||
aiAnalysisText: rm ? '分析' : (cfg.textConfig.aiAnalysisText || '分析')
|
||||
})
|
||||
}
|
||||
this.setData({ reviewMode: rm })
|
||||
const ep2 = getApp().globalData.enterprisePermissions
|
||||
this.setData({ reviewMode: rm, permFace: !ep2 || ep2.face !== false })
|
||||
try {
|
||||
const tb = typeof this.getTabBar === 'function' ? this.getTabBar() : null
|
||||
if (tb && typeof tb.updateSelected === 'function') tb.updateSelected()
|
||||
@@ -97,9 +102,9 @@ Page({
|
||||
|
||||
onShow() {
|
||||
const gd0 = getApp().globalData || {}
|
||||
const audit = !!(gd0.reviewMode || gd0.maintenanceMode)
|
||||
if (typeof this.getTabBar === 'function' && this.getTabBar()) {
|
||||
this.getTabBar().setData({ selected: 0, reviewMode: audit })
|
||||
const tb = this.getTabBar()
|
||||
if (typeof tb.updateSelected === 'function') tb.updateSelected()
|
||||
}
|
||||
// 个人版首页:固定 scope=personal,并清除企业来源上下文
|
||||
try {
|
||||
@@ -108,11 +113,13 @@ Page({
|
||||
} catch (e) {}
|
||||
const g = getApp().globalData
|
||||
const rm = !!(g.reviewMode || g.maintenanceMode)
|
||||
const ep3 = g.enterprisePermissions
|
||||
this.setData({
|
||||
siteTitle: rm ? (g.siteTitle || '神仙团队性格测试').replace(/AI/gi, '') : (g.siteTitle || '神仙团队性格测试'),
|
||||
startButtonText: rm ? '开始性格测试' : ((g.textConfig && g.textConfig.startButtonText) || '拍摄'),
|
||||
startButtonText: (rm || (ep3 && ep3.face === false)) ? '开始性格测试' : ((g.textConfig && g.textConfig.startButtonText) || '拍摄'),
|
||||
aiAnalysisText: rm ? '分析' : ((g.textConfig && g.textConfig.aiAnalysisText) || '分析'),
|
||||
reviewMode: rm
|
||||
reviewMode: rm,
|
||||
permFace: !ep3 || ep3.face !== false
|
||||
})
|
||||
const userInfo = getApp().globalData.userInfo || wx.getStorageSync('userInfo') || {}
|
||||
this.setData({ showEnterpriseEntry: userInfo.hasEnterprise === true })
|
||||
@@ -138,7 +145,9 @@ Page({
|
||||
startCamera() {
|
||||
try { getApp().globalData.appScope = 'personal' } catch (e) {}
|
||||
const gd = getApp().globalData
|
||||
if (gd.reviewMode || gd.maintenanceMode) {
|
||||
const ep = gd.enterprisePermissions
|
||||
const faceOff = ep && ep.face === false
|
||||
if (gd.reviewMode || gd.maintenanceMode || faceOff) {
|
||||
wx.navigateTo({ url: '/pages/test-select/index' })
|
||||
return
|
||||
}
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
<image class="main-image" src="/images/mbti-team-image.png" mode="aspectFit"></image>
|
||||
</view>
|
||||
<!-- 审核模式:只显示性格测评标签 -->
|
||||
<view class="float-tag tag-1" wx:if="{{!reviewMode}}">面相分析</view>
|
||||
<view class="float-tag tag-2" wx:if="{{!reviewMode}}">骨相分析</view>
|
||||
<view class="float-tag tag-1" wx:if="{{!reviewMode && permFace}}">面相分析</view>
|
||||
<view class="float-tag tag-2" wx:if="{{!reviewMode && permFace}}">骨相分析</view>
|
||||
<view class="float-tag tag-3">性格测评</view>
|
||||
<view class="float-tag tag-1" wx:if="{{reviewMode}}">MBTI</view>
|
||||
<view class="float-tag tag-2" wx:if="{{reviewMode}}">DISC</view>
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
<view class="process-section">
|
||||
<view class="section-title">测试流程</view>
|
||||
<view class="process-steps" wx:if="{{!reviewMode}}">
|
||||
<view class="process-steps" wx:if="{{!reviewMode && permFace}}">
|
||||
<view class="step-item">
|
||||
<view class="step-circle active">1</view>
|
||||
<text class="step-label">STEP1</text>
|
||||
@@ -51,8 +51,8 @@
|
||||
<text class="step-text">生成报告</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 审核模式:纯问卷流程 -->
|
||||
<view class="process-steps" wx:if="{{reviewMode}}">
|
||||
<!-- 审核模式或 face 权限关闭:纯问卷流程 -->
|
||||
<view class="process-steps" wx:if="{{reviewMode || !permFace}}">
|
||||
<view class="step-item">
|
||||
<view class="step-circle active">1</view>
|
||||
<text class="step-label">STEP1</text>
|
||||
|
||||
@@ -35,7 +35,8 @@ Page({
|
||||
|
||||
onShow() {
|
||||
const audit = !!(app.globalData.reviewMode || app.globalData.maintenanceMode)
|
||||
if (audit) {
|
||||
const faceOff = !!(app.globalData.enterprisePermissions && app.globalData.enterprisePermissions.face === false)
|
||||
if (audit || faceOff) {
|
||||
wx.navigateTo({ url: '/pages/test-select/index' })
|
||||
return
|
||||
}
|
||||
@@ -43,7 +44,8 @@ Page({
|
||||
return
|
||||
}
|
||||
if (typeof this.getTabBar === 'function' && this.getTabBar()) {
|
||||
this.getTabBar().setData({ selected: 1, reviewMode: audit })
|
||||
const tb = this.getTabBar()
|
||||
if (typeof tb.updateSelected === 'function') tb.updateSelected()
|
||||
}
|
||||
this.setData({ needPhoneAuth: !hasPhone() })
|
||||
const tc = app.globalData.textConfig
|
||||
|
||||
@@ -40,25 +40,65 @@ Page({
|
||||
promoTotalEarned: '0.00',
|
||||
promoWithdrawable: '0.00',
|
||||
/** 是否有企业权限(绑定企业):有则显示「我的简历」 */
|
||||
hasEnterprise: false
|
||||
hasEnterprise: false,
|
||||
// 企业功能权限:默认全开(个人版 / 未配置时)
|
||||
permFace: true,
|
||||
permMbti: true,
|
||||
permPdp: true,
|
||||
permDisc: true,
|
||||
permDistribution: true,
|
||||
/** 最新测试横滑区:仅有已出结果的卡片时才显示,避免禁权或未测评占位 */
|
||||
showLatestTestCards: false,
|
||||
/** 用户卡片下性格标签:在「当前权限下无任何问卷结果」时显示灰色提示 */
|
||||
showEmptyPersonalityTags: true
|
||||
},
|
||||
|
||||
_computeShowLatestTestCards(d) {
|
||||
const rm = !!(d.reviewMode)
|
||||
if (d.permMbti && d.mbtiType) return true
|
||||
if (d.permPdp && d.pdpType) return true
|
||||
if (d.permDisc && d.discType) return true
|
||||
if (!rm && d.permFace && (d.gallupPreview || d.aiType)) return true
|
||||
return false
|
||||
},
|
||||
|
||||
_computeShowEmptyPersonalityTags(d) {
|
||||
return !((d.mbtiType && d.permMbti) || (d.discType && d.permDisc) || (d.pdpType && d.permPdp))
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
// 仅在 onLoad 执行一次,onShow 里的 runLoginThenLoad 会导致重复请求
|
||||
this.runLoginThenLoad()
|
||||
},
|
||||
_syncPerms(overrides = {}) {
|
||||
const p = app.globalData.enterprisePermissions
|
||||
const next = {
|
||||
permFace: !p || p.face !== false,
|
||||
permMbti: !p || p.mbti !== false,
|
||||
permPdp: !p || p.pdp !== false,
|
||||
permDisc: !p || p.disc !== false,
|
||||
permDistribution: !p || p.distribution !== false,
|
||||
...overrides
|
||||
}
|
||||
const d = { ...this.data, ...next }
|
||||
this.setData({
|
||||
...next,
|
||||
showLatestTestCards: this._computeShowLatestTestCards(d),
|
||||
showEmptyPersonalityTags: this._computeShowEmptyPersonalityTags(d)
|
||||
})
|
||||
},
|
||||
|
||||
onShow() {
|
||||
// 同步审核模式(与 runtime maintenanceMode / reviewMode 一致)
|
||||
const gd = app.globalData
|
||||
this.setData({ reviewMode: !!(gd.reviewMode || gd.maintenanceMode) })
|
||||
this._syncPerms({ reviewMode: !!(gd.reviewMode || gd.maintenanceMode) })
|
||||
// 如果是从其他页面返回,且已经登录,则只刷新数据而不重新执行登录流程
|
||||
if (this.data.hasLogin) {
|
||||
this.loadData()
|
||||
}
|
||||
|
||||
if (typeof this.getTabBar === 'function' && this.getTabBar()) {
|
||||
const audit = !!(gd.reviewMode || gd.maintenanceMode)
|
||||
this.getTabBar().setData({ selected: 2, reviewMode: audit })
|
||||
const tb = this.getTabBar()
|
||||
if (typeof tb.updateSelected === 'function') tb.updateSelected()
|
||||
}
|
||||
},
|
||||
|
||||
@@ -108,6 +148,9 @@ Page({
|
||||
},
|
||||
|
||||
loadData() {
|
||||
const gd = app.globalData
|
||||
this._syncPerms({ reviewMode: !!(gd.reviewMode || gd.maintenanceMode) })
|
||||
|
||||
const userInfo = app.globalData.userInfo || wx.getStorageSync('userInfo')
|
||||
const token = app.globalData.token || wx.getStorageSync('token')
|
||||
|
||||
@@ -164,7 +207,7 @@ Page({
|
||||
const discType = r.disc ? r.disc.resultText.replace(/型$/, '') : ''
|
||||
|
||||
const gallupPreview = (r.ai && r.ai.gallupPreview) ? String(r.ai.gallupPreview) : ''
|
||||
this.setData({
|
||||
const patch = {
|
||||
testCount: totalCount,
|
||||
hasResults: !!(r.mbti || r.disc || r.pdp || r.ai),
|
||||
mbtiType: r.mbti ? r.mbti.resultText : '',
|
||||
@@ -180,6 +223,12 @@ Page({
|
||||
discResultId: r.disc ? r.disc.id : null,
|
||||
pdpResultId: r.pdp ? r.pdp.id : null,
|
||||
aiResultId: r.ai ? r.ai.id : null,
|
||||
}
|
||||
const d = { ...this.data, ...patch }
|
||||
this.setData({
|
||||
...patch,
|
||||
showLatestTestCards: this._computeShowLatestTestCards(d),
|
||||
showEmptyPersonalityTags: this._computeShowEmptyPersonalityTags(d)
|
||||
})
|
||||
},
|
||||
fail: () => {
|
||||
@@ -234,7 +283,7 @@ Page({
|
||||
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
|
||||
}
|
||||
|
||||
this.setData({
|
||||
const patch = {
|
||||
testCount,
|
||||
hasResults: testCount > 0,
|
||||
mbtiType: mbtiResult ? getTypeOnly(mbtiResult, 'mbti') : '',
|
||||
@@ -250,6 +299,12 @@ Page({
|
||||
discResultId: null,
|
||||
pdpResultId: null,
|
||||
aiResultId: null,
|
||||
}
|
||||
const d = { ...this.data, ...patch }
|
||||
this.setData({
|
||||
...patch,
|
||||
showLatestTestCards: this._computeShowLatestTestCards(d),
|
||||
showEmptyPersonalityTags: this._computeShowEmptyPersonalityTags(d)
|
||||
})
|
||||
},
|
||||
|
||||
|
||||
@@ -49,16 +49,16 @@
|
||||
<!-- 类型标签 -->
|
||||
<scroll-view scroll-x class="tags-scroll">
|
||||
<view class="tags-row">
|
||||
<view class="tag tag-purple" wx:if="{{mbtiType}}">
|
||||
<view class="tag tag-purple" wx:if="{{mbtiType && permMbti}}">
|
||||
<text class="tag-text">{{mbtiType}}</text>
|
||||
</view>
|
||||
<view class="tag tag-blue" wx:if="{{discType}}">
|
||||
<view class="tag tag-blue" wx:if="{{discType && permDisc}}">
|
||||
<text class="tag-text">{{discType}}型</text>
|
||||
</view>
|
||||
<view class="tag tag-orange" wx:if="{{pdpType}}">
|
||||
<view class="tag tag-orange" wx:if="{{pdpType && permPdp}}">
|
||||
<text class="tag-text">{{pdpType}}</text>
|
||||
</view>
|
||||
<view class="tag tag-gray" wx:if="{{!mbtiType && !discType && !pdpType}}">
|
||||
<view class="tag tag-gray" wx:if="{{showEmptyPersonalityTags}}">
|
||||
<text class="tag-text">暂无测试记录</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -79,57 +79,57 @@
|
||||
<text class="depth-header-chevron">›</text>
|
||||
</view>
|
||||
</view>
|
||||
<scroll-view scroll-x class="cards-scroll cards-scroll--in-card" enhanced show-scrollbar="{{false}}">
|
||||
<scroll-view wx:if="{{showLatestTestCards}}" scroll-x class="cards-scroll cards-scroll--in-card" enhanced show-scrollbar="{{false}}">
|
||||
<view class="cards-row cards-row--in-card">
|
||||
<view class="result-card card-purple {{mbtiType ? '' : 'result-card--placeholder'}}" bindtap="viewMBTI">
|
||||
<view class="result-card card-purple" bindtap="viewMBTI" wx:if="{{permMbti && mbtiType}}">
|
||||
<view class="card-deco"></view>
|
||||
<view class="card-icon-wrap card-icon-purple">
|
||||
<text class="card-icon">🧠</text>
|
||||
</view>
|
||||
<text class="card-label">MBTI性格</text>
|
||||
<text class="card-value">{{mbtiType || '未测评'}}</text>
|
||||
<text class="card-time">{{mbtiType ? mbtiTime : '点击进入问卷'}}</text>
|
||||
<text class="card-value">{{mbtiType}}</text>
|
||||
<text class="card-time">{{mbtiTime}}</text>
|
||||
</view>
|
||||
<view class="result-card card-orange {{pdpType ? '' : 'result-card--placeholder'}}" bindtap="viewPDP">
|
||||
<view class="result-card card-orange" bindtap="viewPDP" wx:if="{{permPdp && pdpType}}">
|
||||
<view class="card-deco"></view>
|
||||
<view class="card-icon-wrap card-icon-orange">
|
||||
<text class="card-icon">🦁</text>
|
||||
</view>
|
||||
<text class="card-label">PDP行为</text>
|
||||
<text class="card-value">{{pdpType || '未测评'}}</text>
|
||||
<text class="card-time">{{pdpType ? pdpTime : '点击进入问卷'}}</text>
|
||||
<text class="card-value">{{pdpType}}</text>
|
||||
<text class="card-time">{{pdpTime}}</text>
|
||||
</view>
|
||||
<view class="result-card card-blue {{discType ? '' : 'result-card--placeholder'}}" bindtap="viewDISC">
|
||||
<view class="result-card card-blue" bindtap="viewDISC" wx:if="{{permDisc && discType}}">
|
||||
<view class="card-deco"></view>
|
||||
<view class="card-icon-wrap card-icon-blue">
|
||||
<text class="card-icon">📊</text>
|
||||
</view>
|
||||
<text class="card-label">DISC测评</text>
|
||||
<text class="card-value">{{discType ? discType + '型' : '未测评'}}</text>
|
||||
<text class="card-time">{{discType ? discTime : '点击进入问卷'}}</text>
|
||||
<text class="card-value">{{discType + '型'}}</text>
|
||||
<text class="card-time">{{discTime}}</text>
|
||||
</view>
|
||||
<view class="result-card card-teal {{(gallupPreview || aiType) ? '' : 'result-card--placeholder'}}" bindtap="viewGallup" wx:if="{{!reviewMode}}">
|
||||
<view class="result-card card-teal" bindtap="viewGallup" wx:if="{{!reviewMode && permFace && (gallupPreview || aiType)}}">
|
||||
<view class="card-deco"></view>
|
||||
<view class="card-icon-wrap card-icon-teal">
|
||||
<text class="card-icon">⭐</text>
|
||||
</view>
|
||||
<text class="card-label">盖洛普优势</text>
|
||||
<text class="card-value card-value--small">{{gallupPreview || (aiType ? '见面相报告' : '未测评')}}</text>
|
||||
<text class="card-time">{{gallupPreview ? aiTime : (aiType ? '已拍面相可查看' : '先完成面相拍摄')}}</text>
|
||||
<text class="card-value card-value--small">{{gallupPreview || '见面相报告'}}</text>
|
||||
<text class="card-time">{{aiTime}}</text>
|
||||
</view>
|
||||
<view class="result-card card-rose {{aiType ? '' : 'result-card--placeholder'}}" bindtap="viewAI" wx:if="{{!reviewMode}}">
|
||||
<view class="result-card card-rose" bindtap="viewAI" wx:if="{{!reviewMode && permFace && aiType}}">
|
||||
<view class="card-deco"></view>
|
||||
<view class="card-icon-wrap card-icon-rose">
|
||||
<text class="card-icon">👁️</text>
|
||||
</view>
|
||||
<text class="card-label">面相分析</text>
|
||||
<text class="card-value">{{aiType || '未测评'}}</text>
|
||||
<text class="card-time">{{aiType ? aiTime : '去拍摄分析'}}</text>
|
||||
<text class="card-value">{{aiType}}</text>
|
||||
<text class="card-time">{{aiTime}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="depth-empty-hint depth-empty-hint--compact">
|
||||
<text>灰色为未完成项,点击即可进入测评;右上方可查看全部历史。</text>
|
||||
<view wx:if="{{showLatestTestCards}}" class="depth-empty-hint depth-empty-hint--compact">
|
||||
<text>点击卡片查看详情;右上方可查看全部测试记录。</text>
|
||||
</view>
|
||||
<view class="depth-inner-divider"></view>
|
||||
<view class="menu-item menu-item--flat" bindtap="goToTestSelect">
|
||||
@@ -179,7 +179,7 @@
|
||||
</view>
|
||||
|
||||
<!-- 推广中心(与管理端开关、标题配置一致;卡片样式与其他区块统一) -->
|
||||
<view class="section px-section" wx:if="{{hasLogin && promoDistributionEnabled && !reviewMode}}">
|
||||
<view class="section px-section" wx:if="{{hasLogin && promoDistributionEnabled && !reviewMode && permDistribution}}">
|
||||
<view class="promo-card" bindtap="goToPromo">
|
||||
<view class="promo-header">
|
||||
<view class="promo-title-wrap">
|
||||
|
||||
@@ -1,21 +1,41 @@
|
||||
// pages/test-select/index.js - 人脸测试后的详情性格测试入口(MBTI / PDP / DISC)
|
||||
Page({
|
||||
data: {},
|
||||
|
||||
onLoad() {},
|
||||
|
||||
// 进入 MBTI 测试
|
||||
goMBTI() {
|
||||
wx.navigateTo({ url: '/pages/test/mbti' })
|
||||
},
|
||||
|
||||
// 进入 PDP 测试
|
||||
goPDP() {
|
||||
wx.navigateTo({ url: '/pages/test/pdp' })
|
||||
},
|
||||
|
||||
// 进入 DISC 测试
|
||||
goDISC() {
|
||||
wx.navigateTo({ url: '/pages/test/disc' })
|
||||
}
|
||||
})
|
||||
// pages/test-select/index.js
|
||||
const app = getApp()
|
||||
|
||||
Page({
|
||||
data: {
|
||||
permFace: true,
|
||||
permMbti: true,
|
||||
permPdp: true,
|
||||
permDisc: true
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
this._syncPerms()
|
||||
},
|
||||
|
||||
onShow() {
|
||||
this._syncPerms()
|
||||
},
|
||||
|
||||
_syncPerms() {
|
||||
const p = app.globalData.enterprisePermissions
|
||||
this.setData({
|
||||
permFace: !p || p.face !== false,
|
||||
permMbti: !p || p.mbti !== false,
|
||||
permPdp: !p || p.pdp !== false,
|
||||
permDisc: !p || p.disc !== false
|
||||
})
|
||||
},
|
||||
|
||||
goMBTI() {
|
||||
wx.navigateTo({ url: '/pages/test/mbti' })
|
||||
},
|
||||
|
||||
goPDP() {
|
||||
wx.navigateTo({ url: '/pages/test/pdp' })
|
||||
},
|
||||
|
||||
goDISC() {
|
||||
wx.navigateTo({ url: '/pages/test/disc' })
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,40 +1,40 @@
|
||||
<!--pages/test-select/index.wxml - 详细性格测试入口(MBTI / PDP / DISC)-->
|
||||
<view class="container">
|
||||
<view class="card intro-card">
|
||||
<text class="intro-title">选择一项详细性格测试</text>
|
||||
<text class="intro-desc">完成问卷即可获得对应维度的专业性格报告</text>
|
||||
</view>
|
||||
|
||||
<view class="card entry-card" bindtap="goMBTI">
|
||||
<view class="entry-icon-wrap mbti">
|
||||
<text class="entry-emoji">🧠</text>
|
||||
</view>
|
||||
<view class="entry-content">
|
||||
<text class="entry-name">MBTI 性格测试</text>
|
||||
<text class="entry-brief">16型人格 · 发现你的认知与决策风格</text>
|
||||
</view>
|
||||
<text class="entry-arrow">→</text>
|
||||
</view>
|
||||
|
||||
<view class="card entry-card" bindtap="goPDP">
|
||||
<view class="entry-icon-wrap pdp">
|
||||
<text class="entry-emoji">🦁</text>
|
||||
</view>
|
||||
<view class="entry-content">
|
||||
<text class="entry-name">PDP 行为偏好测试</text>
|
||||
<text class="entry-brief">老虎 / 孔雀 / 考拉 / 猫头鹰 · 行为风格</text>
|
||||
</view>
|
||||
<text class="entry-arrow">→</text>
|
||||
</view>
|
||||
|
||||
<view class="card entry-card" bindtap="goDISC">
|
||||
<view class="entry-icon-wrap disc">
|
||||
<text class="entry-emoji">📊</text>
|
||||
</view>
|
||||
<view class="entry-content">
|
||||
<text class="entry-name">DISC 性格测试</text>
|
||||
<text class="entry-brief">D/I/S/C 四维 · 沟通与行为倾向</text>
|
||||
</view>
|
||||
<text class="entry-arrow">→</text>
|
||||
</view>
|
||||
</view>
|
||||
<!--pages/test-select/index.wxml - 详细性格测试入口(MBTI / PDP / DISC)-->
|
||||
<view class="container">
|
||||
<view class="card intro-card">
|
||||
<text class="intro-title">选择一项详细性格测试</text>
|
||||
<text class="intro-desc">完成问卷即可获得对应维度的专业性格报告</text>
|
||||
</view>
|
||||
|
||||
<view class="card entry-card" bindtap="goMBTI" wx:if="{{permMbti}}">
|
||||
<view class="entry-icon-wrap mbti">
|
||||
<text class="entry-emoji">🧠</text>
|
||||
</view>
|
||||
<view class="entry-content">
|
||||
<text class="entry-name">MBTI 性格测试</text>
|
||||
<text class="entry-brief">16型人格 · 发现你的认知与决策风格</text>
|
||||
</view>
|
||||
<text class="entry-arrow">→</text>
|
||||
</view>
|
||||
|
||||
<view class="card entry-card" bindtap="goPDP" wx:if="{{permPdp}}">
|
||||
<view class="entry-icon-wrap pdp">
|
||||
<text class="entry-emoji">🦁</text>
|
||||
</view>
|
||||
<view class="entry-content">
|
||||
<text class="entry-name">PDP 行为偏好测试</text>
|
||||
<text class="entry-brief">老虎 / 孔雀 / 考拉 / 猫头鹰 · 行为风格</text>
|
||||
</view>
|
||||
<text class="entry-arrow">→</text>
|
||||
</view>
|
||||
|
||||
<view class="card entry-card" bindtap="goDISC" wx:if="{{permDisc}}">
|
||||
<view class="entry-icon-wrap disc">
|
||||
<text class="entry-emoji">📊</text>
|
||||
</view>
|
||||
<view class="entry-content">
|
||||
<text class="entry-name">DISC 性格测试</text>
|
||||
<text class="entry-brief">D/I/S/C 四维 · 沟通与行为倾向</text>
|
||||
</view>
|
||||
<text class="entry-arrow">→</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
Reference in New Issue
Block a user