feat: 诊所问题优化
This commit is contained in:
@@ -115,21 +115,30 @@
|
||||
v-else-if="showQuestionButtons && currentQuestion && !isSubmitting && !showWaiting && answerMode === 'multi'"
|
||||
class="action-footer multi-footer safe-area-inset-bottom"
|
||||
>
|
||||
<!-- 多选适用症:点选 toggling,确认后再提交 -->
|
||||
<!-- 多选适用症:点选 toggling,确认后再提交;选「其他」可填自定义症状 -->
|
||||
<view class="multi-options">
|
||||
<button
|
||||
v-for="(answer, index) in currentQuestionAnswers"
|
||||
:key="index"
|
||||
:class="['multi-option-btn', { selected: !!multiSelectedMap[index] }]"
|
||||
hover-class="none"
|
||||
:class="['multi-option-btn', { selected: !!multiSelectedFlag[index] }]"
|
||||
@click="toggleMultiAnswer(index)"
|
||||
>
|
||||
{{ answer }}
|
||||
</button>
|
||||
</view>
|
||||
<input
|
||||
v-if="multiHasOtherSelected"
|
||||
class="multi-other-input"
|
||||
v-model="multiOtherText"
|
||||
placeholder="请填写具体症状"
|
||||
:maxlength="100"
|
||||
/>
|
||||
<!-- 不用原生 disabled,避免微信小程序卡死无法点击;未达标时 toast -->
|
||||
<button
|
||||
class="action-btn yes-btn confirm-btn"
|
||||
:disabled="multiSelectedCount === 0"
|
||||
:class="{ disabled: multiSelectedCount === 0 }"
|
||||
hover-class="none"
|
||||
:class="{ disabled: !multiConfirmEnabled }"
|
||||
@click="confirmMultiAnswer"
|
||||
>
|
||||
确认
|
||||
@@ -142,8 +151,9 @@
|
||||
<button
|
||||
v-for="(answer, index) in currentQuestionAnswers"
|
||||
:key="index"
|
||||
hover-class="none"
|
||||
:class="['action-btn', answerButtonClass(answer, index)]"
|
||||
@click="$emit('answer', answer)"
|
||||
@click="emitSingleAnswer(answer)"
|
||||
>
|
||||
{{ answer }}
|
||||
</button>
|
||||
@@ -259,17 +269,25 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
/** 多选模式下已选中的选项下标映射,避免模板里写 indexOf */
|
||||
multiSelectedMap: {},
|
||||
/** 多选已选下标列表(整表替换,微信小程序下比 object+$set 更稳) */
|
||||
multiSelectedIndexes: [],
|
||||
/** 选「其他」时的自定义症状文案 */
|
||||
multiOtherText: '',
|
||||
/** 防双击:emit 后立刻锁,题目切换解锁 */
|
||||
answeringLock: false,
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
// 题目切换时清空多选,避免上一题选中态残留
|
||||
currentQuestion() {
|
||||
this.multiSelectedMap = {};
|
||||
this.multiSelectedIndexes = [];
|
||||
this.multiOtherText = '';
|
||||
this.answeringLock = false;
|
||||
},
|
||||
answerMode() {
|
||||
this.multiSelectedMap = {};
|
||||
this.multiSelectedIndexes = [];
|
||||
this.multiOtherText = '';
|
||||
this.answeringLock = false;
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
@@ -281,8 +299,37 @@ export default {
|
||||
this.$emit('update:showAgreement', val)
|
||||
},
|
||||
},
|
||||
/** 供模板判断选中,避免 :class 里写 indexOf */
|
||||
multiSelectedFlag() {
|
||||
const map = {};
|
||||
const list = this.multiSelectedIndexes || [];
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
map[list[i]] = true;
|
||||
}
|
||||
return map;
|
||||
},
|
||||
multiSelectedCount() {
|
||||
return Object.keys(this.multiSelectedMap).filter((k) => this.multiSelectedMap[k]).length;
|
||||
return (this.multiSelectedIndexes || []).length;
|
||||
},
|
||||
/** 是否选中了「其他」选项 */
|
||||
multiHasOtherSelected() {
|
||||
const answers = this.currentQuestionAnswers || [];
|
||||
const list = this.multiSelectedIndexes || [];
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
const idx = list[i];
|
||||
if (answers[idx] === '其他') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
/** 多选确认是否可提交:至少选一项;选了其他则自定义文案非空 */
|
||||
multiConfirmEnabled() {
|
||||
if (this.multiSelectedCount === 0) return false;
|
||||
if (this.multiHasOtherSelected) {
|
||||
return !!(this.multiOtherText && String(this.multiOtherText).trim());
|
||||
}
|
||||
return true;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
@@ -306,27 +353,54 @@ export default {
|
||||
if (index === 0) return 'yes-btn'
|
||||
return 'no-btn'
|
||||
},
|
||||
/** 单选:点一下即提交,防双击重复 emit */
|
||||
emitSingleAnswer(answer) {
|
||||
if (this.answeringLock || this.isSubmitting) return;
|
||||
this.answeringLock = true;
|
||||
this.$emit('answer', answer);
|
||||
},
|
||||
/** 多选:切换某个适用症的选中状态 */
|
||||
toggleMultiAnswer(index) {
|
||||
if (this.multiSelectedMap[index]) {
|
||||
this.$delete(this.multiSelectedMap, index);
|
||||
if (this.answeringLock || this.isSubmitting) return;
|
||||
const list = this.multiSelectedIndexes || [];
|
||||
const pos = list.indexOf(index);
|
||||
if (pos === -1) {
|
||||
this.multiSelectedIndexes = list.concat([index]);
|
||||
} else {
|
||||
this.$set(this.multiSelectedMap, index, true);
|
||||
this.multiSelectedIndexes = list.filter((i) => i !== index);
|
||||
if (this.currentQuestionAnswers[index] === '其他') {
|
||||
this.multiOtherText = '';
|
||||
}
|
||||
}
|
||||
},
|
||||
/** 多选确认:把选中标签用顿号拼接后交给父组件 */
|
||||
/**
|
||||
* 多选确认:选中标签用顿号拼接;「其他」替换为自定义填写内容
|
||||
*/
|
||||
confirmMultiAnswer() {
|
||||
const indexes = Object.keys(this.multiSelectedMap)
|
||||
.filter((k) => this.multiSelectedMap[k])
|
||||
.map((k) => Number(k))
|
||||
.sort((a, b) => a - b);
|
||||
if (this.answeringLock || this.isSubmitting) return;
|
||||
if (!this.multiConfirmEnabled) {
|
||||
if (this.multiSelectedCount === 0) {
|
||||
uni.showToast({ title: '请至少选择一项', icon: 'none' });
|
||||
} else if (this.multiHasOtherSelected) {
|
||||
uni.showToast({ title: '请填写具体症状', icon: 'none' });
|
||||
}
|
||||
return;
|
||||
}
|
||||
const indexes = (this.multiSelectedIndexes || []).slice().sort((a, b) => a - b);
|
||||
if (!indexes.length) return;
|
||||
const otherText = (this.multiOtherText || '').trim();
|
||||
const labels = indexes
|
||||
.map((i) => this.currentQuestionAnswers[i])
|
||||
.map((i) => {
|
||||
const label = this.currentQuestionAnswers[i];
|
||||
if (label === '其他') return otherText;
|
||||
return label;
|
||||
})
|
||||
.filter(Boolean);
|
||||
if (!labels.length) return;
|
||||
this.answeringLock = true;
|
||||
this.$emit('answer', labels.join('、'));
|
||||
this.multiSelectedMap = {};
|
||||
this.multiSelectedIndexes = [];
|
||||
this.multiOtherText = '';
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -531,19 +605,22 @@ export default {
|
||||
font-weight: 500;
|
||||
border: none;
|
||||
white-space: normal;
|
||||
/* 覆盖微信 button 默认白底/按下灰底,避免按钮组背景错乱 */
|
||||
background-color: #0a84ff !important;
|
||||
color: #fff !important;
|
||||
|
||||
&::after {
|
||||
border: none;
|
||||
}
|
||||
|
||||
&.yes-btn {
|
||||
background: #0a84ff;
|
||||
color: #fff;
|
||||
background-color: #0a84ff !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
&.no-btn {
|
||||
background: #fff;
|
||||
color: #333;
|
||||
background-color: #fff !important;
|
||||
color: #333 !important;
|
||||
border: 2rpx solid #ddd;
|
||||
}
|
||||
|
||||
@@ -563,6 +640,18 @@ export default {
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.multi-other-input {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 16rpx 24rpx;
|
||||
min-height: 72rpx;
|
||||
border-radius: 12rpx;
|
||||
background: #f8fafc;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
border: 1rpx solid #e2e8f0;
|
||||
}
|
||||
|
||||
.multi-option-btn {
|
||||
min-width: 140rpx;
|
||||
padding: 0 28rpx;
|
||||
@@ -570,8 +659,8 @@ export default {
|
||||
line-height: 64rpx;
|
||||
border-radius: 32rpx;
|
||||
font-size: 26rpx;
|
||||
background: rgba(10, 132, 255, 0.08);
|
||||
color: #475569;
|
||||
background-color: rgba(10, 132, 255, 0.08) !important;
|
||||
color: #475569 !important;
|
||||
border: 2rpx solid transparent;
|
||||
|
||||
&::after {
|
||||
@@ -579,14 +668,16 @@ export default {
|
||||
}
|
||||
|
||||
&.selected {
|
||||
background: #0a84ff;
|
||||
color: #fff;
|
||||
background-color: #0a84ff !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
}
|
||||
|
||||
.confirm-btn {
|
||||
width: 100%;
|
||||
flex: none;
|
||||
background-color: #0a84ff !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user