| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753 |
- var tcm = require('../../../../utils/tcm.js')
- var compliance = require('../../../../utils/compliance.js')
- var EXAMPLE_IMAGES = {
- tongue: 'https://cfohow.hiwavo.com/fohow-app/xcx/tcm/sheup.png',
- tongueBottom: 'https://cfohow.hiwavo.com/fohow-app/xcx/tcm/shedown.png',
- face: 'https://cfohow.hiwavo.com/fohow-app/xcx/tcm/face.png'
- }
- var USER_OPTION_LABELS = {
- country: {
- china: '中国',
- russia: '俄罗斯',
- kazakhstan: '哈萨克斯坦',
- mongolia: '蒙古',
- japan: '日本',
- korea: '韩国',
- usa: '美国',
- uk: '英国',
- germany: '德国',
- france: '法国',
- other: '其他'
- },
- race: {
- asian: '亚裔',
- caucasian: '白人',
- african: '非裔',
- hispanic: '拉丁裔',
- mixed: '混血',
- other: '其他'
- },
- occupation: {
- sedentary_office: '久坐办公(文员/行政/财务等)',
- it_programmer: 'IT/程序员',
- driver: '司机(出租车/货运/公交等)',
- teacher: '教师/培训师',
- medical_staff: '健康护理人员',
- service_industry: '服务行业(餐饮/零售/酒店等)',
- heavy_labor: '重体力劳动(建筑/搬运/制造等)',
- outdoor_worker: '户外工作者(农业/快递/外卖等)',
- student: '学生',
- homemaker: '家庭主妇/夫',
- retired: '退休人员',
- other: '其他'
- }
- }
- Page({
- data: {
- currentStep: 0,
- loadingUsers: true,
- loadingTips: true,
- loadingQuestions: false,
- submitting: false,
- showUserPopup: false,
- showExamplePopup: false,
- exampleTitle: '',
- exampleImage: '',
- currentUser: null,
- scaleUsers: [],
- photoTipsTitle: '拍摄注意事项',
- photoTips: [
- '自然光或均匀灯光下拍摄,避免逆光、偏暗与强曝光。',
- '保持镜头稳定,对焦清晰,确保舌面纹理可见。',
- '舌下与面部照片请正对镜头,避免大角度侧拍。'
- ],
- uploadCards: [
- {
- key: 'tongue',
- title: '舌面',
- desc: '请伸出舌头,拍摄舌面正面照,需清晰展示舌面颜色和纹理',
- required: true,
- localPath: '',
- url: '',
- uploading: false
- },
- {
- key: 'tongueBottom',
- title: '舌下',
- desc: '请翘起舌头,拍摄舌底照片,需清晰展示舌下纹理',
- required: true,
- localPath: '',
- url: '',
- uploading: false
- },
- {
- key: 'face',
- title: '面部',
- desc: '请正对镜头拍摄面部照片,需清晰展示面部整体状态',
- required: true,
- localPath: '',
- url: '',
- uploading: false
- },
- {
- key: 'body',
- title: '全身',
- desc: '请拍摄全身正面照片,用于辅助体态与整体状态分析,可选上传',
- required: false,
- localPath: '',
- url: '',
- uploading: false
- }
- ],
- questionList: [],
- extraNote: ''
- },
- onLoad: function () {
- this.loadBaseData()
- },
- onShow: function () {
- if (wx.getStorageSync('tcmUserChanged')) {
- wx.removeStorageSync('tcmUserChanged')
- this.loadUsers()
- }
- },
- onUnload: function () {
- wx.removeStorageSync('tcmEditScaleUser')
- },
- loadBaseData: function () {
- this.loadUsers()
- this.loadPhotoTips()
- },
- loadUsers: function () {
- var that = this
- that.setData({
- loadingUsers: true
- })
- tcm.getScaleUsers().then(function (list) {
- var scaleUsers = that.decorateScaleUsers(Array.isArray(list) ? list : [])
- var currentUser = null
- if (scaleUsers.length > 0) {
- currentUser = scaleUsers[0]
- for (var i = 0; i < scaleUsers.length; i++) {
- if (scaleUsers[i].isDefault === true || scaleUsers[i].isDefault === 1) {
- currentUser = scaleUsers[i]
- break
- }
- if (!currentUser && scaleUsers[i].active === true) {
- currentUser = scaleUsers[i]
- }
- }
- }
- that.setData({
- scaleUsers: scaleUsers,
- currentUser: currentUser,
- loadingUsers: false
- })
- }).catch(function () {
- that.setData({
- scaleUsers: [],
- currentUser: null,
- loadingUsers: false
- })
- wx.showToast({
- title: '用户列表加载失败',
- icon: 'none'
- })
- })
- },
- loadPhotoTips: function () {
- var that = this
- tcm.getPhotoTips().then(function (data) {
- if (!data) {
- return
- }
- that.setData({
- photoTipsTitle: data.title || '拍摄注意事项',
- photoTips: data.tips && data.tips.length ? data.tips : that.data.photoTips,
- loadingTips: false
- })
- }).catch(function () {
- that.setData({
- loadingTips: false
- })
- })
- },
- decorateScaleUsers: function (list) {
- var nextList = []
- for (var i = 0; i < list.length; i++) {
- nextList.push(this.decorateScaleUser(list[i]))
- }
- return nextList
- },
- decorateScaleUser: function (user) {
- if (!user) {
- return user
- }
- var detailTags = []
- if (user.country) {
- detailTags.push(this.getUserOptionLabel('country', user.country))
- }
- if (user.race) {
- detailTags.push(this.getUserOptionLabel('race', user.race))
- }
- if (user.occupation) {
- detailTags.push(this.getUserOptionLabel('occupation', user.occupation))
- }
- user.detailTags = detailTags
- return user
- },
- getUserOptionLabel: function (group, value) {
- if (!value || !USER_OPTION_LABELS[group]) {
- return ''
- }
- return USER_OPTION_LABELS[group][value] || value
- },
- openUserPopup: function () {
- this.setData({
- showUserPopup: true
- })
- },
- closeUserPopup: function () {
- this.setData({
- showUserPopup: false
- })
- },
- selectUser: function (e) {
- var user = this.decorateScaleUser(e.currentTarget.dataset.user)
- this.setData({
- currentUser: user,
- showUserPopup: false
- })
- if (user && user.ID) {
- tcm.setDefaultScaleUser(user.ID)
- }
- },
- goUserForm: function () {
- this.closeUserPopup()
- wx.navigateTo({
- url: '/packageWellness/pages/tcm/user-form/user-form'
- })
- },
- editUser: function (e) {
- var user = e.currentTarget.dataset.user
- wx.setStorageSync('tcmEditScaleUser', user)
- this.closeUserPopup()
- wx.navigateTo({
- url: '/packageWellness/pages/tcm/user-form/user-form?mode=edit'
- })
- },
- deleteUser: function (e) {
- var that = this
- var user = e.currentTarget.dataset.user
- if (!user || !user.ID) {
- return
- }
- wx.showModal({
- title: '删除成员',
- content: '确认删除“' + user.nickName + '”吗?删除后该成员的康养评估入口将不可用。',
- confirmColor: '#e35b4e',
- success: function (res) {
- if (!res.confirm) {
- return
- }
- tcm.deleteScaleUser(user.ID).then(function () {
- wx.showToast({
- title: '删除成功',
- icon: 'success'
- })
- if (that.data.currentUser && that.data.currentUser.ID === user.ID) {
- that.setData({
- currentUser: null
- })
- }
- that.loadUsers()
- that.closeUserPopup()
- }).catch(function (err) {
- wx.showToast({
- title: err && err.message ? err.message : '删除失败',
- icon: 'none'
- })
- })
- }
- })
- },
- viewRecords: function () {
- if (!this.data.currentUser || !this.data.currentUser.ID) {
- wx.showToast({
- title: '请先选择成员',
- icon: 'none'
- })
- return
- }
- wx.navigateTo({
- url: '/packageWellness/pages/tcm/report/report?scaleUserId=' + this.data.currentUser.ID
- })
- },
- chooseImageSource: function (e) {
- var kind = e.currentTarget.dataset.kind
- var that = this
- wx.showActionSheet({
- itemList: ['拍照', '从相册选择'],
- success: function (res) {
- var sourceType = res.tapIndex === 0 ? ['camera'] : ['album']
- wx.chooseImage({
- count: 1,
- sizeType: ['compressed'],
- sourceType: sourceType,
- success: function (chooseRes) {
- var tempPath = chooseRes.tempFilePaths[0]
- that.uploadImage(kind, tempPath)
- }
- })
- }
- })
- },
- uploadImage: function (kind, tempPath) {
- var that = this
- var cards = this.data.uploadCards.slice()
- var cardIndex = this.findUploadCardIndex(kind)
- if (cardIndex < 0) {
- return
- }
- cards[cardIndex].localPath = tempPath
- cards[cardIndex].uploading = true
- cards[cardIndex].url = ''
- that.setData({
- uploadCards: cards
- })
- tcm.uploadObservationImage(tempPath, kind).then(function (data) {
- var nextCards = that.data.uploadCards.slice()
- nextCards[cardIndex].uploading = false
- nextCards[cardIndex].url = data.url || data.urlOss || ''
- that.setData({
- uploadCards: nextCards
- })
- wx.showToast({
- title: '上传成功',
- icon: 'success'
- })
- }).catch(function (err) {
- var failCards = that.data.uploadCards.slice()
- failCards[cardIndex].uploading = false
- failCards[cardIndex].localPath = ''
- failCards[cardIndex].url = ''
- that.setData({
- uploadCards: failCards
- })
- wx.showToast({
- title: err && err.message ? err.message : '上传失败',
- icon: 'none',
- duration: 3000
- })
- })
- },
- findUploadCardIndex: function (kind) {
- var cards = this.data.uploadCards
- for (var i = 0; i < cards.length; i++) {
- if (cards[i].key === kind) {
- return i
- }
- }
- return -1
- },
- openExample: function (e) {
- var kind = e.currentTarget.dataset.kind
- var title = e.currentTarget.dataset.title
- this.setData({
- showExamplePopup: true,
- exampleTitle: title,
- exampleImage: EXAMPLE_IMAGES[kind] || ''
- })
- },
- closeExample: function () {
- this.setData({
- showExamplePopup: false
- })
- },
- noop: function () {},
- previewCurrentImage: function (e) {
- var src = e.currentTarget.dataset.src
- if (!src) {
- return
- }
- wx.previewImage({
- current: src,
- urls: [src]
- })
- },
- goBackStep: function () {
- if (this.data.currentStep === 1) {
- this.setData({
- currentStep: 0
- })
- return
- }
- wx.navigateBack()
- },
- goQuestionsStep: function () {
- if (!this.data.currentUser || !this.data.currentUser.ID) {
- wx.showToast({
- title: '请先选择成员',
- icon: 'none'
- })
- return
- }
- var missing = []
- for (var i = 0; i < this.data.uploadCards.length; i++) {
- if (this.data.uploadCards[i].required && !this.data.uploadCards[i].url) {
- missing.push(this.data.uploadCards[i].title)
- }
- }
- if (missing.length) {
- wx.showToast({
- title: '请先上传' + missing.join('、'),
- icon: 'none'
- })
- return
- }
- this.setData({
- currentStep: 1
- })
- if (!this.data.questionList.length) {
- this.loadQuestions()
- }
- },
- loadQuestions: function () {
- var that = this
- that.setData({
- loadingQuestions: true
- })
- tcm.getQuestions().then(function (questions) {
- var list = Array.isArray(questions) ? questions : []
- var nextList = []
- for (var i = 0; i < list.length; i++) {
- var item = list[i]
- nextList.push({
- key: item.key || '',
- title: compliance.sanitizeText(item.title || ''),
- hint: compliance.sanitizeText(item.hint || ''),
- required: item.required === true,
- multiSelect: item.multiSelect === true,
- exclusivePairs: item.exclusivePairs || [],
- showCustomInput: false,
- customText: '',
- options: (item.options || []).map(function (opt) {
- return {
- value: opt.value || '',
- label: compliance.sanitizeText(opt.label || ''),
- isCustom: opt.isCustom === true,
- placeholder: compliance.sanitizeText(opt.placeholder || ''),
- description: compliance.sanitizeText(opt.description || ''),
- isExclusive: opt.isExclusive === true,
- selected: false,
- disabled: false
- }
- })
- })
- }
- that.setData({
- questionList: nextList,
- loadingQuestions: false
- })
- }).catch(function () {
- that.setData({
- loadingQuestions: false
- })
- wx.showToast({
- title: '健康问答题目加载失败',
- icon: 'none'
- })
- })
- },
- toggleOption: function (e) {
- var qIndex = e.currentTarget.dataset.qindex
- var oIndex = e.currentTarget.dataset.oindex
- var list = this.data.questionList.slice()
- var question = JSON.parse(JSON.stringify(list[qIndex]))
- var option = question.options[oIndex]
- if (option.disabled) {
- return
- }
- if (option.isCustom) {
- question.showCustomInput = !question.showCustomInput
- option.selected = question.showCustomInput
- if (!question.showCustomInput) {
- question.customText = ''
- }
- } else if (option.isExclusive) {
- var shouldSelectExclusive = !option.selected
- for (var i = 0; i < question.options.length; i++) {
- if (!question.options[i].isCustom) {
- question.options[i].selected = false
- }
- }
- option.selected = shouldSelectExclusive
- question.showCustomInput = false
- question.customText = ''
- for (var a = 0; a < question.options.length; a++) {
- if (question.options[a].isCustom) {
- question.options[a].selected = false
- }
- }
- } else {
- for (var b = 0; b < question.options.length; b++) {
- if (question.options[b].isExclusive) {
- question.options[b].selected = false
- }
- }
- if (!question.multiSelect) {
- for (var c = 0; c < question.options.length; c++) {
- if (!question.options[c].isCustom) {
- question.options[c].selected = false
- }
- }
- option.selected = true
- } else {
- option.selected = !option.selected
- }
- if (option.selected) {
- for (var d = 0; d < question.options.length; d++) {
- if (!question.options[d].selected || question.options[d].value === option.value) {
- continue
- }
- if (this.isMutuallyExclusive(question, option.value, question.options[d].value)) {
- question.options[d].selected = false
- }
- }
- }
- }
- question = this.refreshQuestionDisabledState(question)
- list[qIndex] = question
- this.setData({
- questionList: list
- })
- },
- refreshQuestionDisabledState: function (question) {
- var selectedValues = []
- for (var i = 0; i < question.options.length; i++) {
- question.options[i].disabled = false
- if (question.options[i].selected && !question.options[i].isCustom) {
- selectedValues.push(question.options[i].value)
- }
- }
- for (var j = 0; j < selectedValues.length; j++) {
- var selectedValue = selectedValues[j]
- var selectedOption = null
- for (var m = 0; m < question.options.length; m++) {
- if (question.options[m].value === selectedValue) {
- selectedOption = question.options[m]
- break
- }
- }
- if (selectedOption && selectedOption.isExclusive) {
- for (var n = 0; n < question.options.length; n++) {
- if (!question.options[n].isCustom && question.options[n].value !== selectedValue) {
- question.options[n].disabled = true
- }
- }
- }
- for (var p = 0; p < question.options.length; p++) {
- if (question.options[p].selected || question.options[p].isCustom) {
- continue
- }
- if (this.isMutuallyExclusive(question, selectedValue, question.options[p].value)) {
- question.options[p].disabled = true
- }
- }
- }
- return question
- },
- isMutuallyExclusive: function (question, value1, value2) {
- var pairs = question.exclusivePairs || []
- for (var i = 0; i < pairs.length; i++) {
- if (pairs[i].length < 2) {
- continue
- }
- if ((pairs[i][0] === value1 && pairs[i][1] === value2) ||
- (pairs[i][0] === value2 && pairs[i][1] === value1)) {
- return true
- }
- }
- return false
- },
- updateCustomText: function (e) {
- var qIndex = e.currentTarget.dataset.qindex
- var list = this.data.questionList.slice()
- list[qIndex].customText = e.detail.value
- this.setData({
- questionList: list
- })
- },
- updateExtraNote: function (e) {
- this.setData({
- extraNote: e.detail.value
- })
- },
- getQuestionAnswerText: function (question) {
- var texts = []
- for (var i = 0; i < question.options.length; i++) {
- if (question.options[i].selected && !question.options[i].isCustom) {
- texts.push(question.options[i].label)
- }
- }
- if (question.customText) {
- texts.push(question.customText)
- }
- return texts.join(',')
- },
- submitExam: function () {
- var that = this
- if (that.data.submitting) {
- return
- }
- for (var i = 0; i < that.data.questionList.length; i++) {
- var question = that.data.questionList[i]
- var answerText = that.getQuestionAnswerText(question)
- if (question.required && !answerText) {
- wx.showToast({
- title: '请完成' + question.title,
- icon: 'none'
- })
- return
- }
- }
- wx.showModal({
- title: 'AI 健康评估知情同意',
- content: '本功能使用人工智能技术对舌象、面部与健康问答信息进行分析,结果仅供健康参考,不构成专业建议。',
- confirmText: '继续提交',
- confirmColor: '#eab86a',
- success: function (res) {
- if (res.confirm) {
- that.doSubmitExam()
- }
- }
- })
- },
- doSubmitExam: function () {
- var that = this
- var questionAnswers = {}
- var customAnswers = {}
- var observationImages = {}
- for (var i = 0; i < that.data.uploadCards.length; i++) {
- if (that.data.uploadCards[i].url) {
- observationImages[that.data.uploadCards[i].key] = [that.data.uploadCards[i].url]
- }
- }
- for (var j = 0; j < that.data.questionList.length; j++) {
- var question = that.data.questionList[j]
- var selectedValues = []
- for (var k = 0; k < question.options.length; k++) {
- if (question.options[k].selected && !question.options[k].isCustom) {
- selectedValues.push(question.options[k].value)
- }
- }
- if (selectedValues.length) {
- questionAnswers[question.key] = selectedValues
- }
- if (question.customText) {
- customAnswers[question.key] = compliance.sanitizeText(question.customText)
- }
- }
- that.setData({
- submitting: true
- })
- tcm.submitExam({
- scaleUserId: that.data.currentUser.ID,
- language: tcm.getLanguageCode(),
- questionAnswers: questionAnswers,
- customAnswers: customAnswers,
- observationImages: observationImages,
- extraNote: compliance.sanitizeText(that.data.extraNote || ''),
- additionalText: ''
- }).then(function (data) {
- wx.showToast({
- title: '提交成功',
- icon: 'success'
- })
- that.setData({
- submitting: false
- })
- setTimeout(function () {
- wx.redirectTo({
- url: '/packageWellness/pages/tcm/report/report?examId=' + data.examId
- })
- }, 400)
- }).catch(function (err) {
- that.setData({
- submitting: false
- })
- wx.showToast({
- title: err && err.message ? err.message : '提交失败,请重试',
- icon: 'none',
- duration: 3000
- })
- })
- }
- })
|