fix[create]: 预览题目统一

- 预览题目跟随pc, 取 title 值
This commit is contained in:
Huangzhe
2025-03-23 17:40:09 +08:00
parent 678c0cd6e2
commit 0d8123ffda
22 changed files with 77 additions and 166 deletions

2
components.d.ts vendored
View File

@@ -38,6 +38,8 @@ declare module 'vue' {
VanRow: typeof import('vant/es')['Row']
VanStepper: typeof import('vant/es')['Stepper']
VanSwitch: typeof import('vant/es')['Switch']
VanTab: typeof import('vant/es')['Tab']
VanTabs: typeof import('vant/es')['Tabs']
YLCascader: typeof import('./src/components/YLCascader.vue')['default']
YLInput: typeof import('./src/components/YLInput.vue')['default']
YLPicker: typeof import('./src/components/YLPicker.vue')['default']

View File

@@ -69,9 +69,7 @@ const element = defineModel('element', {
return {};
}
});
const index = defineModel('index', {
type: Number
});
const index = defineModel('index');
// watch(
// () => index.value,

View File

@@ -130,8 +130,7 @@ defineProps({
default: false
},
index: {
type: Number,
default: 0
default: ''
}
});

View File

@@ -45,7 +45,6 @@ const props = defineProps({
}
},
index: {
type: Number,
default: 0
},
active: {

View File

@@ -7,7 +7,7 @@ import { fileLimit, answer } from './hooks/useFileUploadHooks';
const isPreview = defineModel('isPreview', { default: false, type: Boolean, required: false });
const props = defineProps<{
element: any;
index: number;
index: number | String;
active: boolean;
}>();
const { element } = toRefs(props);

View File

@@ -1,10 +1,6 @@
<template>
<input
type="checkbox"
:name="`R${rowIndex + 1}`"
:checked="isOptionChecked(rowIndex, colIndex)"
@change="handleMatrixCheckboxChange(rowIndex, colIndex)"
/>
<input type="checkbox" :name="`R${rowIndex + 1}`" :checked="isOptionChecked(rowIndex, colIndex)"
@change="handleMatrixCheckboxChange(rowIndex, colIndex)" />
</template>
<script setup lang="ts">

View File

@@ -28,7 +28,7 @@ const rows = defineModel<_questionOptionType[]>('rows', { required: false, defau
// 列标签
const cols = defineModel<_questionOptionType[]>('cols', { required: false, default: () => [] });
// 题的序号
const index = defineModel<number>('index', { required: false, default: 0 });
const index = defineModel<number|string>('index', { required: false, default: 0 });
// 是否是编辑状态
const active = defineModel<boolean>('active', { required: false, default: false });

View File

@@ -58,8 +58,7 @@ const isPreview = defineModel('isPreview', { default: false, type: Boolean });
default: false
},
index: {
type: Number,
default: 0
default: ''
},
active: {
type: Boolean,

View File

@@ -1,42 +1,22 @@
<template>
<div class="content">
<van-field
v-model="element.stem"
:label="element.stem"
:required="element.config.is_required === 1"
label-align="top"
class="contenteditable-question-title"
>
<van-field v-model="element.stem" :label="element.stem" :required="element.config.is_required === 1"
label-align="top" class="contenteditable-question-title">
<template #left-icon> {{ isPreview ? element.title : index + 1 }}. </template>
<template #label>
<contenteditable
v-model="element.stem"
:active="active"
@blur="emitValue"
className="contenteditable-label"
:errorMessage="errorMessage"
></contenteditable>
<contenteditable v-model="element.stem" :active="active" @blur="emitValue" className="contenteditable-label"
:errorMessage="errorMessage"></contenteditable>
</template>
<template #input>
<div
v-for="(optionItem, optionItemIndex) in element.list ?? element.options"
:key="optionItemIndex"
class="rate-content"
>
<div
v-for="(item, optionIndex) in isPreview ? optionItem.options : optionItem"
:key="optionIndex"
class="rate-item"
@click="chooseOption(item)"
>
<div v-for="(optionItem, optionItemIndex) in element.list ?? element.options" :key="optionItemIndex"
class="rate-content">
<div v-for="(item, optionIndex) in isPreview ? optionItem.options : optionItem" :key="optionIndex"
class="rate-item" @click="chooseOption(item)">
<div class="mb5">
<contenteditable v-model="item.option" :active="active"></contenteditable>
</div>
<div class="mb10">
<RateCharacter
v-model:model="answerValue[optionIndex]"
:config="element.config"
></RateCharacter>
<RateCharacter v-model:model="answerValue[optionIndex]" :config="element.config"></RateCharacter>
</div>
<div class="tips">
@@ -76,7 +56,6 @@ defineProps({
default: false
},
index: {
type: Number,
default: 0
},
sn: { type: String, default: '' },

View File

@@ -6,7 +6,7 @@ const element = defineModel<question>('element', { default: {} });
// 属性框是否激活
const active = defineModel<boolean>('active', { default: false });
// 题目索引
const index = defineModel<number>('index', { default: 0 });
const index = defineModel<number | string>('index', { default: 0 });
// 答案
const answer = defineModel<string>('answer', { default: '' });
// 错误信息
@@ -197,44 +197,23 @@ async function handleUploadImg() {
</script>
<template>
<van-field
:label="element.stem"
:required="element.config.is_required === 1"
label-align="top"
:border="false"
readonly
>
<van-field :label="element.stem" :required="element.config.is_required === 1" label-align="top" :border="false"
readonly>
<template #left-icon> {{ isPreview ? element.title : index + 1 }}. </template>
<template #label>
<contenteditable
v-model="element.stem"
className="contenteditable-label"
:active="active"
@blur="emitValue"
:errorMessage="errorMessage"
></contenteditable>
<contenteditable v-model="element.stem" className="contenteditable-label" :active="active" @blur="emitValue"
:errorMessage="errorMessage"></contenteditable>
</template>
<template #input>
<div class="sign-question">
<canvas
ref="signatureCanvas"
:width="canvasWidth"
:height="canvasHeight"
style="border: 1px dashed #ccc; border-radius: 4px"
>
<canvas ref="signatureCanvas" :width="canvasWidth" :height="canvasHeight"
style="border: 1px dashed #ccc; border-radius: 4px">
</canvas>
<div class="sign-text" :class="{ show: true }">
<span
class="icon mobilefont mobilefont-qingkong"
title="清空"
@click="clearCanvas"
></span>
<span class="icon mobilefont mobilefont-qingkong" title="清空" @click="clearCanvas"></span>
<span class="icon mobilefont mobilefont-chexiao" @click="undo"></span>
<span
class="icon mobilefont"
:class="isEraser ? 'mobilefont-huabi' : 'mobilefont-rubber'"
@click="togglePen"
></span>
<span class="icon mobilefont" :class="isEraser ? 'mobilefont-huabi' : 'mobilefont-rubber'"
@click="togglePen"></span>
<span class="icon mobilefont mobilefont-shangchuan" @click="handleUploadImg"></span>
</div>
<div class="sign-tips">请在空白区域书写您的签名</div>

View File

@@ -1,21 +1,11 @@
<template>
<div class="text-with-images-container">
<van-field
readonly
:label="element.stem"
:required="element.config?.is_required === 1"
label-align="top"
class="base-select contenteditable-question-title"
>
<van-field readonly :label="element.stem" :required="element.config?.is_required === 1" label-align="top"
class="base-select contenteditable-question-title">
<template #left-icon> {{ isPreview ? element.title : index + 1 }}. </template>
<template #label>
<contenteditable
v-model="element.stem"
:active="active"
className="contenteditable-label"
@blur="emitValue"
:errorMessage="errorMessage"
></contenteditable>
<contenteditable v-model="element.stem" :active="active" className="contenteditable-label" @blur="emitValue"
:errorMessage="errorMessage"></contenteditable>
</template>
</van-field>
</div>
@@ -41,7 +31,6 @@ const props = defineProps({
default: false
},
index: {
type: Number,
default: 0
}
});

View File

@@ -8,7 +8,7 @@
/>
</template>
<script setup lang="ts">
import { watch, ref } from 'vue';
import { watch, ref, computed } from 'vue';
import Choice from '@/views/Design/components/Questions/Choice.vue';
type answerType = {
@@ -24,9 +24,9 @@ type answerType = {
*/
// 预览新增 v-model
const answer = defineModel<answerType>('answer', { default: undefined });
const answerIndex = defineModel<number>('answerIndex');
// const stem = defineModel<string>('stem', { default: '' });
const question = defineModel<question>('question', { default: { config: { is_required: false } } });
const answerIndex = computed<string>(() => question.value.title);
// const list = defineModel<questionsList[]>('list', { default: [[]] });
initData();

View File

@@ -8,7 +8,7 @@
/>
</template>
<script setup lang="ts">
import { watch, ref } from 'vue';
import { watch, ref, computed } from 'vue';
import Choice from '@/views/Design/components/Questions/Choice.vue';
type answerType = {
@@ -17,7 +17,7 @@ type answerType = {
};
// // 预览新增 v-model
const answer = defineModel<answerType>('answer', { default: undefined });
const answerIndex = defineModel<number>('answerIndex');
const answerIndex = computed(() => question.value.title);
// const stem = defineModel<string>('stem', { default: '' });4
const question = defineModel<question>('question', { default: { config: { is_required: false } } });
const list = defineModel<questionsList[]>('list', { default: [[]] });

View File

@@ -10,13 +10,15 @@
></completion>
</template>
<script setup lang="ts">
import { defineEmits, ref, watch } from 'vue';
import { computed, defineEmits, ref, watch } from 'vue';
import Completion from '@/views/Design/components/Questions/Completion.vue';
import Rate from '@/views/Design/components/Questions/Rate.vue';
// 预览新增 v-model
// const config = defineModel('config');
const answer = defineModel<{ value: string | number }>('answer', { default: { value: '' } });
const answerIndex = defineModel<number>('answerIndex');
const answerIndex = computed(() => {
return question.value.title;
});
// const stem = defineModel('stem');
const question = defineModel<question>('question', { default: () => {} });
// const list = defineModel<questionsList[]>('list');

View File

@@ -1,10 +1,10 @@
<script setup lang="ts">
import FileUpload from '@/views/Design/components/Questions/FileUpload.vue';
const questionIndex = defineModel<number>('questionIndex', { default: NaN });
const answerIndex = defineModel<number>('answerIndex', { default: NaN });
const answerIndex = computed(() => question.value.title);
const question = defineModel<question>('question', { default: () => {} });
import { answer } from '@/views/Design/components/Questions/hooks/useFileUploadHooks';
import { watch } from 'vue';
import { computed, watch } from 'vue';
const emit = defineEmits(['changeAnswer']);
watch(answer, () => {

View File

@@ -1,13 +1,6 @@
<template>
<MatrixQuestion
v-model:rowRecord="rowRecord"
v-model:matrix-radio-answer="answer!"
:rows="rows"
:cols="cols"
:is-preview="true"
:errorMessage="question.error"
:element="question"
/>
<MatrixQuestion :index="answerIndex" v-model:rowRecord="rowRecord" v-model:matrix-radio-answer="answer!" :rows="rows"
:cols="cols" :is-preview="true" :errorMessage="question.error" :element="question" />
</template>
<script setup lang="ts">
@@ -25,6 +18,7 @@ type answerType = {
// const list = defineModel<questionsList[]>('list', { required: false });
// const config = defineModel<OptionConfigType>('config', { required: false });
const question = defineModel<question>('question', { default: () => { } });
const answerIndex = computed(() => question.value.title);
const emit = defineEmits(['changeAnswer', 'previous', 'next']);
// 示例
// {

View File

@@ -1,14 +1,6 @@
<template>
<MatrixQuestion
v-model:rowRecord="rowRecord"
:rows="rows"
:cols="cols"
:index="questionIndex"
:element="question"
:is-preview="true"
:active="false"
:errorMessage="question.error"
/>
<MatrixQuestion v-model:rowRecord="rowRecord" :rows="rows" :cols="cols" :index="answerIndex" :element="question"
:is-preview="true" :active="false" :errorMessage="question.error" />
</template>
<script setup lang="ts">
@@ -27,7 +19,7 @@ type answerType = {
// const list = defineModel<questionsList[]>('list', { required: false });
// const config = defineModel<OptionConfigType>('config', { required: false });
const question = defineModel<question>('question', { default: () => { } });
const questionIndex = defineModel<number>('answerIndex', { required: false, default: 0 });
const answerIndex = computed(() => question.value?.title ?? 0);
// console.log(question.value);
const emit = defineEmits(['changeAnswer', 'previous', 'next']);
// 示例

View File

@@ -1,21 +1,13 @@
<template>
<MatrixQuestion
v-model:rowRecord="rowRecord"
:rows="rows"
:cols="cols"
:index="questionIndex"
:element="question"
:is-preview="true"
:active="false"
:errorMessage="question.error"
/>
<MatrixQuestion v-model:rowRecord="rowRecord" :rows="rows" :cols="cols" :index="answerIndex" :element="question"
:is-preview="true" :active="false" :errorMessage="question.error" />
</template>
<script setup lang="ts">
// import MatrixText from '@/views/Design/components/Questions/MatrixText.vue';
import { computed, ref, watch } from 'vue';
import MatrixQuestion from '@/views/Design/components/Questions/MatrixQuestion.vue';
const questionIndex = defineModel<number>('answerIndex', { required: false, default: 0 });
const answerIndex = computed(() => question.value?.title ?? 0);
// 矩阵多选的答案类型
type answerType = {

View File

@@ -11,12 +11,13 @@
<script setup lang="ts">
import NPS from '@/views/Design/components/Questions/NPS.vue';
import { watch, ref } from 'vue';
import { watch, ref, computed } from 'vue';
const value = ref(-1);
// // 预览新增 emit ['changeAnswer', 'previous', 'next']
const emit = defineEmits(['changeAnswer', 'previous', 'next', 'update:element']);
const question = defineModel<question>('question', { default: { config: { is_required: false } } });
/**
* answer 的答案类型
* {
@@ -24,7 +25,9 @@ const question = defineModel<question>('question', { default: { config: { is_req
* }
*/
const answer = defineModel<NPSAnswerType>('answer', { default: undefined });
const answerIndex = defineModel<number>('answerIndex', { default: undefined });
const answerIndex = computed(() => {
return question.value.title;
});
// 解析答案
// function parseAnswer() {

View File

@@ -1,18 +1,12 @@
<template>
<rate
v-model:element="question"
v-model:answer-value="value"
:active="false"
:isPreview="true"
:index="answerIndex"
:errorMessage="question.error"
/>
<rate v-model:element="question" v-model:answer-value="value" :active="false" :isPreview="true" :index="answerIndex"
:errorMessage="question.error" />
</template>
<script setup lang="ts">
import Rate from '@/views/Design/components/Questions/Rate.vue';
import { watch, ref, nextTick } from 'vue';
import { watch, ref, nextTick, computed } from 'vue';
const value = ref<number[]>([]);
// // 预览新增 emit ['changeAnswer', 'previous', 'next']
@@ -26,7 +20,7 @@ const question = defineModel<question>('question', { default: { config: { is_req
* }
*/
const answer = defineModel<NPSAnswerType>('answer', { default: undefined });
const answerIndex = defineModel<number>('answerIndex', { default: undefined });
const answerIndex = computed(() => question.value?.title ?? 0);
parseAnswer();
// 解析答案

View File

@@ -1,12 +1,11 @@
<script setup lang="ts">
import SignQuestion from '@/views/Design/components/Questions/SignQuestion.vue';
import { ref, watch } from 'vue';
import Rate from '@/views/Design/components/Questions/Rate.vue';
import { ref, watch, computed } from 'vue';
const question = defineModel<question>('question', { default: {} });
const answer = defineModel<{ value: string }>('answer', { default: undefined });
const answerValue = ref<string>('');
const answerIndex = defineModel<number>('answerIndex', { default: 0 });
const answerIndex = computed(() => question.value?.title ?? 0);
// emit
const emit = defineEmits(['changeAnswer']);
@@ -32,13 +31,7 @@ function parseAnswer() {
</script>
<template>
<sign-question
:element="question"
:active="false"
:isPreview="true"
:index="answerIndex"
v-model:answer="answerValue"
:error-message="question.error"
/>
<sign-question :element="question" :active="false" :isPreview="true" :index="answerIndex" v-model:answer="answerValue"
:error-message="question.error" />
</template>
<style scoped lang="scss"></style>

View File

@@ -1,10 +1,11 @@
<script setup lang="ts">
import TextWithImages from '@/views/Design/components/Questions/TextWithImages.vue';
import { computed } from 'vue';
// 问题
const question = defineModel<question>('question', { default: {} });
// question 序号
const answerIndex = defineModel('answerIndex', { default: 0 });
const answerIndex = computed(() => question.value?.title ?? 0);
// 答案
const answer = defineModel('answer', { default: {} });
// answer 提供默认值