Browse Source
1. 修复多个文件的多余BOM头字符问题 2. 重构年龄选择器的选中逻辑 3. 新增工具方法处理数字比较和包含判断 4. 完整实现健康问卷页面,包括分步答题、单选多选切换、其他输入、表单验证和提交功能 5. 更新接口文档,新增健康问卷相关API文档master
51 changed files with 348 additions and 86 deletions
@ -1,8 +1,181 @@ |
|||||||
const _app = getApp<IAppOption>(); |
const app = getApp<IAppOption>() |
||||||
|
|
||||||
|
interface IOption { |
||||||
|
key: string |
||||||
|
value: string |
||||||
|
} |
||||||
|
|
||||||
|
interface IQuestion { |
||||||
|
QuestionNo: number |
||||||
|
QuestionContent: string |
||||||
|
QuestionType: number |
||||||
|
HasOther: number |
||||||
|
Options: Record<string, string> |
||||||
|
Answer: number[] | number |
||||||
|
OtherText: string |
||||||
|
optionList: IOption[] |
||||||
|
} |
||||||
|
|
||||||
Page({ |
Page({ |
||||||
data: {}, |
data: { |
||||||
onLoad() {}, |
currentIndex: 0, |
||||||
}); |
questions: [] as IQuestion[], |
||||||
|
hasSubmitted: false, |
||||||
|
latestSubmitTime: '', |
||||||
|
isSubmitting: false, |
||||||
|
}, |
||||||
|
|
||||||
|
onLoad() { |
||||||
|
app.waitLogin().then(() => { |
||||||
|
this.getQuestionnaire() |
||||||
|
}) |
||||||
|
}, |
||||||
|
|
||||||
|
getQuestionnaire() { |
||||||
|
wx.ajax({ |
||||||
|
method: 'GET', |
||||||
|
url: '?r=igg4/health-question/get-patient-questionnaire', |
||||||
|
data: {}, |
||||||
|
}).then((res: any) => { |
||||||
|
const questions: IQuestion[] = (res.questions || []).map((q: any) => { |
||||||
|
const optionList: IOption[] = Object.entries(q.Options || {}).map(([key, value]) => ({ |
||||||
|
key, |
||||||
|
value: value as string, |
||||||
|
})) |
||||||
|
let Answer: number[] | number = q.QuestionType === 2 ? [] : 0 |
||||||
|
let OtherText = '' |
||||||
|
if (q.Answer !== undefined && q.Answer !== null) { |
||||||
|
Answer = q.Answer |
||||||
|
OtherText = q.OtherText || '' |
||||||
|
} |
||||||
|
return { |
||||||
|
QuestionNo: q.QuestionNo, |
||||||
|
QuestionContent: q.QuestionContent, |
||||||
|
QuestionType: q.QuestionType, |
||||||
|
HasOther: q.HasOther, |
||||||
|
Options: q.Options, |
||||||
|
Answer, |
||||||
|
OtherText, |
||||||
|
optionList, |
||||||
|
} |
||||||
|
}) |
||||||
|
this.setData({ |
||||||
|
questions, |
||||||
|
hasSubmitted: res.hasSubmitted || false, |
||||||
|
latestSubmitTime: res.latestSubmitTime || '', |
||||||
|
}) |
||||||
|
}) |
||||||
|
}, |
||||||
|
|
||||||
|
handleSelect(e: any) { |
||||||
|
const { key } = e.currentTarget.dataset |
||||||
|
const { currentIndex, questions } = this.data |
||||||
|
const question = questions[currentIndex] |
||||||
|
const numKey = Number(key) |
||||||
|
|
||||||
|
if (question.QuestionType === 2) { |
||||||
|
let answer = [...(question.Answer as number[])] |
||||||
|
const idx = answer.indexOf(numKey) |
||||||
|
if (idx > -1) { |
||||||
|
answer.splice(idx, 1) |
||||||
|
} else { |
||||||
|
answer.push(numKey) |
||||||
|
} |
||||||
|
this.setData({ |
||||||
|
[`questions[${currentIndex}].Answer`]: answer, |
||||||
|
}) |
||||||
|
} else { |
||||||
|
this.setData({ |
||||||
|
[`questions[${currentIndex}].Answer`]: numKey, |
||||||
|
}) |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
handleOtherInput(e: any) { |
||||||
|
const { currentIndex } = this.data |
||||||
|
this.setData({ |
||||||
|
[`questions[${currentIndex}].OtherText`]: e.detail.value, |
||||||
|
}) |
||||||
|
}, |
||||||
|
|
||||||
|
handlePrev() { |
||||||
|
const { currentIndex } = this.data |
||||||
|
if (currentIndex > 0) { |
||||||
|
this.setData({ |
||||||
|
currentIndex: currentIndex - 1, |
||||||
|
}) |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
handleNext() { |
||||||
|
const { currentIndex, questions } = this.data |
||||||
|
const question = questions[currentIndex] |
||||||
|
if (!this.validateQuestion(question)) return |
||||||
|
|
||||||
|
if (currentIndex < questions.length - 1) { |
||||||
|
this.setData({ |
||||||
|
currentIndex: currentIndex + 1, |
||||||
|
}) |
||||||
|
} else { |
||||||
|
this.handleSubmit() |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
validateQuestion(question: IQuestion): boolean { |
||||||
|
if (question.QuestionType === 2) { |
||||||
|
const answer = question.Answer as number[] |
||||||
|
if (!answer || !answer.length) { |
||||||
|
wx.showToast({ title: '请至少选择一项', icon: 'none' }) |
||||||
|
return false |
||||||
|
} |
||||||
|
if (answer.includes(99) && !question.OtherText.trim()) { |
||||||
|
wx.showToast({ title: '请填写其他内容', icon: 'none' }) |
||||||
|
return false |
||||||
|
} |
||||||
|
} else { |
||||||
|
const answer = question.Answer as number |
||||||
|
if (!answer) { |
||||||
|
wx.showToast({ title: '请选择一项', icon: 'none' }) |
||||||
|
return false |
||||||
|
} |
||||||
|
if (answer === 99 && !question.OtherText.trim()) { |
||||||
|
wx.showToast({ title: '请填写其他内容', icon: 'none' }) |
||||||
|
return false |
||||||
|
} |
||||||
|
} |
||||||
|
return true |
||||||
|
}, |
||||||
|
|
||||||
|
handleSubmit() { |
||||||
|
const { questions, isSubmitting } = this.data |
||||||
|
if (isSubmitting) return |
||||||
|
|
||||||
|
const answers = questions.map((q) => { |
||||||
|
const item: any = { |
||||||
|
questionNo: q.QuestionNo, |
||||||
|
answer: q.Answer, |
||||||
|
} |
||||||
|
if (q.HasOther === 1 && q.OtherText) { |
||||||
|
item.otherText = q.OtherText |
||||||
|
} |
||||||
|
return item |
||||||
|
}) |
||||||
|
|
||||||
export {} |
this.setData({ isSubmitting: true }) |
||||||
|
wx.ajax({ |
||||||
|
method: 'POST', |
||||||
|
url: '?r=igg4/health-question/submit-questionnaire', |
||||||
|
data: { answers }, |
||||||
|
loading: true, |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
wx.showToast({ title: '提交成功', icon: 'success' }) |
||||||
|
setTimeout(() => { |
||||||
|
wx.navigateBack() |
||||||
|
}, 1500) |
||||||
|
}) |
||||||
|
.finally(() => { |
||||||
|
this.setData({ isSubmitting: false }) |
||||||
|
}) |
||||||
|
}, |
||||||
|
}) |
||||||
|
|||||||
@ -1,22 +1,45 @@ |
|||||||
<view class="page" id="{{theme === 'DRUG' && 'drug-page'}}"> |
<wxs src="../../utils/tools.wxs" module="tools" /> |
||||||
<view class="page-header">您好!为了更好地了解您的病情,请您完成以下4个简单问题,便于医生评估您的近期状况:</view> |
<view class="page" id="{{theme === 'DRUG' && 'drug-page'}}"> |
||||||
|
<view class="page-header">您好!为了更好地了解您的病情,请您完成以下{{questions.length}}个简单问题,便于医生评估您的近期状况:</view> |
||||||
<view class="progress"> |
<view class="progress"> |
||||||
<view class="p-item"></view> |
<view |
||||||
<view class="p-item"></view> |
class="p-item {{index <= currentIndex && 'active'}}" |
||||||
<view class="p-item"></view> |
wx:for="{{questions}}" |
||||||
<view class="p-item"></view> |
wx:key="QuestionNo" |
||||||
|
></view> |
||||||
</view> |
</view> |
||||||
<view class="list-title">您目前被确诊受累的器官有哪些?(可多选)</view> |
|
||||||
<view class="list"> |
<block wx:for="{{questions}}" wx:key="QuestionNo" wx:for-item="question" wx:for-index="qIndex"> |
||||||
<view class="list-item"> |
<view class="question-section" wx:if="{{qIndex === currentIndex}}"> |
||||||
<checkbox class="check"> |
<view class="list-title">{{question.QuestionContent}}</view> |
||||||
<view class="content">泪腺 / 眼眶</view> |
<view class="list"> |
||||||
</checkbox> |
<view |
||||||
|
class="list-item {{(question.QuestionType === 2 && tools.include(item.key, question.Answer)) || (question.QuestionType === 1 && tools.eq(question.Answer, item.key)) ? 'active' : ''}}" |
||||||
|
wx:for="{{question.optionList}}" |
||||||
|
wx:key="key" |
||||||
|
bind:tap="handleSelect" |
||||||
|
data-key="{{item.key}}" |
||||||
|
> |
||||||
|
<view class="check-icon"> |
||||||
|
<view class="icon-inner"></view> |
||||||
|
</view> |
||||||
|
<view class="content">{{item.value}}</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="other-section" wx:if="{{question.HasOther === 1 && ((question.QuestionType === 2 && tools.include(99, question.Answer)) || (question.QuestionType === 1 && tools.eq(question.Answer, 99)))}}"> |
||||||
|
<textarea |
||||||
|
class="other-input" |
||||||
|
placeholder="请输入其他内容" |
||||||
|
value="{{question.OtherText}}" |
||||||
|
bindinput="handleOtherInput" |
||||||
|
maxlength="200" |
||||||
|
></textarea> |
||||||
|
</view> |
||||||
</view> |
</view> |
||||||
</view> |
</block> |
||||||
|
|
||||||
<view class="footer"> |
<view class="footer"> |
||||||
<view class="prev">上一步</view> |
<view class="prev" wx:if="{{currentIndex > 0}}" bind:tap="handlePrev">上一步</view> |
||||||
<view class="next" wx:if="{{true}}">继续</view> |
<view class="next" bind:tap="handleNext">{{currentIndex === questions.length - 1 ? '完成' : '继续'}}</view> |
||||||
<view class="next" wx:else>完成</view> |
|
||||||
</view> |
</view> |
||||||
</view> |
</view> |
||||||
|
|||||||
@ -1,12 +1,18 @@ |
|||||||
function include(value, arr) { |
function include(value, arr) { |
||||||
|
var numValue = parseInt(value) |
||||||
for (var i = 0; i < arr.length; i++) { |
for (var i = 0; i < arr.length; i++) { |
||||||
if (arr[i] === value) { |
if (arr[i] === numValue) { |
||||||
return true |
return true |
||||||
} |
} |
||||||
} |
} |
||||||
return false |
return false |
||||||
} |
} |
||||||
|
|
||||||
|
function eq(a, b) { |
||||||
|
return parseInt(a) === parseInt(b) |
||||||
|
} |
||||||
|
|
||||||
module.exports = { |
module.exports = { |
||||||
include: include, |
include: include, |
||||||
|
eq: eq, |
||||||
} |
} |
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Loading…
Reference in new issue