- 自定义 tabBar:AI 入口图标与样式,相关页面与审核门控调整 - API:MpTabbar、出站推送 Hook、后台设置与迁移 SQL(含 FAB 居中排序) - 管理端:推送 Hook 面板、出站推送调试工具与生产环境注释说明 Made-with: Cursor
258 lines
7.9 KiB
JavaScript
258 lines
7.9 KiB
JavaScript
// pages/index/camera.js - 拍照页,拍完后上传到服务器再跳转结果页
|
||
const app = getApp()
|
||
const { ensureProfileCompleteAndRedirect } = require('../../utils/phoneAuth.js')
|
||
|
||
Page({
|
||
data: {
|
||
photos: [],
|
||
photoIndex: 0,
|
||
guideTexts: ['请正对镜头', '请向左转45°', '请向右转45°'],
|
||
guideText: '请正对镜头',
|
||
uploading: false,
|
||
aiAnalysisText: '分析',
|
||
reviewMode: true
|
||
},
|
||
|
||
_audit() {
|
||
return !!(app.globalData.reviewMode || app.globalData.maintenanceMode)
|
||
},
|
||
|
||
onLoad(options) {
|
||
try {
|
||
require('../../utils/thirdPartyContext.js').ingestThirdPartyOnPageLoad(options || {}, app)
|
||
} catch (e) {}
|
||
this.setData({ reviewMode: this._audit() })
|
||
const tc = app.globalData.textConfig
|
||
if (tc && tc.aiAnalysisText) {
|
||
this.setData({ aiAnalysisText: tc.aiAnalysisText })
|
||
}
|
||
app.getRuntimeConfig().then((cfg) => {
|
||
if (cfg) {
|
||
if (cfg.reviewMode !== undefined) app.globalData.reviewMode = !!cfg.reviewMode
|
||
else if (cfg.maintenanceMode !== undefined) app.globalData.reviewMode = !!cfg.maintenanceMode
|
||
if (cfg.maintenanceMode !== undefined) app.globalData.maintenanceMode = !!cfg.maintenanceMode
|
||
try {
|
||
require('../../utils/miniprogramAuditGate.js').applyAuditUiOverride(app)
|
||
} catch (e) {}
|
||
if (cfg.textConfig) {
|
||
app.globalData.textConfig = cfg.textConfig
|
||
this.setData({
|
||
aiAnalysisText: cfg.textConfig.aiAnalysisText || '分析',
|
||
reviewMode: this._audit()
|
||
})
|
||
try {
|
||
const tb = typeof this.getTabBar === 'function' ? this.getTabBar() : null
|
||
if (tb && typeof tb.updateSelected === 'function') tb.updateSelected()
|
||
} catch (e) {}
|
||
return
|
||
}
|
||
}
|
||
this.setData({ reviewMode: this._audit() })
|
||
}).catch(() => {
|
||
this.setData({ reviewMode: this._audit() })
|
||
})
|
||
},
|
||
|
||
/** 非审核模式且相机在页上时再创建上下文 */
|
||
onReady() {
|
||
if (!this._audit()) {
|
||
this.initCameraContext()
|
||
}
|
||
},
|
||
|
||
goToQuestionnaire() {
|
||
wx.navigateTo({ url: '/pages/test-select/index' })
|
||
},
|
||
|
||
initCameraContext() {
|
||
try {
|
||
if (typeof wx.createCameraContext === 'function') {
|
||
this.cameraContext = wx.createCameraContext()
|
||
}
|
||
} catch (e) {
|
||
console.error('initCameraContext', e)
|
||
this.cameraContext = null
|
||
}
|
||
},
|
||
|
||
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()) {
|
||
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
|
||
}
|
||
|
||
if (this.data.photos.length < 3) {
|
||
this.initCameraContext()
|
||
}
|
||
|
||
this.setData({ needPhoneAuth: !hasPhone() })
|
||
const tc = app.globalData.textConfig
|
||
if (tc && tc.aiAnalysisText) {
|
||
this.setData({ aiAnalysisText: tc.aiAnalysisText })
|
||
}
|
||
},
|
||
|
||
// 拍照
|
||
takePhoto() {
|
||
if (this.data.photos.length >= 3) {
|
||
wx.showToast({ title: '已拍满3张', icon: 'none' })
|
||
return
|
||
}
|
||
|
||
if (!this.cameraContext) {
|
||
this.initCameraContext()
|
||
}
|
||
if (!this.cameraContext || typeof this.cameraContext.takePhoto !== 'function') {
|
||
wx.showToast({ title: '相机未就绪,请稍候再试', icon: 'none' })
|
||
return
|
||
}
|
||
|
||
this.cameraContext.takePhoto({
|
||
quality: 'high',
|
||
success: (res) => {
|
||
try { require('../../utils/analytics').track('take_photo', { index: this.data.photos.length + 1 }) } catch (e) {}
|
||
const photos = [...this.data.photos, res.tempImagePath]
|
||
const photoIndex = photos.length
|
||
const guideText = this.data.guideTexts[photoIndex] || '拍摄完成'
|
||
|
||
this.setData({
|
||
photos,
|
||
photoIndex,
|
||
guideText
|
||
})
|
||
|
||
if (photos.length === 3) {
|
||
wx.showToast({ title: '拍摄完成', icon: 'success' })
|
||
}
|
||
},
|
||
fail: (err) => {
|
||
const msg = (err && (err.errMsg || err.message)) ? String(err.errMsg || err.message) : ''
|
||
if (msg.indexOf('auth deny') >= 0 || msg.indexOf('authorize') >= 0) {
|
||
wx.showModal({
|
||
title: '需要相机权限',
|
||
content: '请在设置中允许使用摄像头',
|
||
confirmText: '去设置',
|
||
success: (r) => { if (r.confirm) wx.openSetting() }
|
||
})
|
||
} else {
|
||
wx.showToast({ title: '拍照失败,请重试', icon: 'none' })
|
||
}
|
||
console.error('拍照失败:', err)
|
||
}
|
||
})
|
||
},
|
||
|
||
// 重新拍摄全部照片
|
||
retakeAll() {
|
||
wx.showModal({
|
||
title: '重新拍摄',
|
||
content: '确定要重新拍摄所有照片吗?',
|
||
confirmText: '确定',
|
||
cancelText: '取消',
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
this.setData({
|
||
photos: [],
|
||
photoIndex: 0,
|
||
guideText: '请正对镜头'
|
||
})
|
||
wx.showToast({ title: '已清空,请重新拍摄', icon: 'success' })
|
||
setTimeout(() => this.initCameraContext(), 200)
|
||
}
|
||
}
|
||
})
|
||
},
|
||
|
||
// 完成拍照:先上传 3 张图到服务器,拿到 URL 后再跳转结果页
|
||
completeCapture() {
|
||
const photos = this.data.photos
|
||
if (!photos || photos.length === 0) {
|
||
wx.showToast({ title: '请先拍摄照片', icon: 'none' })
|
||
return
|
||
}
|
||
this.setData({ uploading: true })
|
||
wx.showLoading({ title: '上传中...', mask: true })
|
||
const apiBase = (app.globalData && app.globalData.apiBase) ? app.globalData.apiBase.replace(/\/$/, '') : ''
|
||
const token = (app.globalData && app.globalData.token) || wx.getStorageSync('token') || ''
|
||
const uploadUrl = apiBase + '/api/upload/image'
|
||
|
||
const uploadOne = (path) => {
|
||
return new Promise((resolve, reject) => {
|
||
wx.uploadFile({
|
||
url: uploadUrl,
|
||
filePath: path,
|
||
name: 'file',
|
||
header: token ? { Authorization: 'Bearer ' + token } : {},
|
||
success: (res) => {
|
||
try {
|
||
const data = JSON.parse(res.data)
|
||
if (data.code === 200 && data.data && data.data.url) {
|
||
resolve(data.data.url)
|
||
} else {
|
||
reject(new Error(data.message || '上传失败'))
|
||
}
|
||
} catch (e) {
|
||
reject(new Error('解析上传结果失败'))
|
||
}
|
||
},
|
||
fail: (err) => reject(err)
|
||
})
|
||
})
|
||
}
|
||
|
||
Promise.all(photos.map(uploadOne))
|
||
.then((urls) => {
|
||
wx.hideLoading()
|
||
wx.setStorageSync('aiPhotos', urls)
|
||
this.setData({ uploading: false })
|
||
try { require('../../utils/analytics').track('photo_upload_success', { count: urls.length }) } catch (e) {}
|
||
wx.navigateTo({ url: '/pages/index/result' })
|
||
})
|
||
.catch((err) => {
|
||
wx.hideLoading()
|
||
this.setData({ uploading: false })
|
||
try { require('../../utils/analytics').track('photo_upload_fail', { error: (err && err.message) || '' }) } catch (e) {}
|
||
wx.showToast({ title: err.message || '上传失败', icon: 'none' })
|
||
})
|
||
},
|
||
|
||
// 从相册选择:跳转到上传页(三角度上传),不改变当前 scope/企业上下文
|
||
goToUpload() {
|
||
wx.navigateTo({
|
||
url: '/pages/index/upload'
|
||
})
|
||
},
|
||
|
||
// 相机错误
|
||
onCameraError(e) {
|
||
console.error('相机错误:', e)
|
||
wx.showModal({
|
||
title: '相机权限',
|
||
content: '请允许使用相机权限以进行性格分析',
|
||
confirmText: '去设置',
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
wx.openSetting()
|
||
}
|
||
}
|
||
})
|
||
}
|
||
})
|