feat: 增加矩阵问题的组件

- 增加 MartrixQuestion 组件
- 增加对应测试数据
This commit is contained in:
Huangzhe
2025-03-05 17:10:16 +08:00
parent 6df0b0d320
commit d1d388354f
3 changed files with 467 additions and 35 deletions

View File

@@ -5166,7 +5166,321 @@ export const useCommonStore = defineStore('common', {
is_show: 0, is_show: 0,
use_type: 0, use_type: 0,
pageId: '30bb8256-2069-4458-ad67-0c9cefd3415d' pageId: '30bb8256-2069-4458-ad67-0c9cefd3415d'
},
{
id: '123',
title: 'Q4',
stem: '请每行选择1个选项',
question_index: 4,
question_type: 9,
config: {
is_required: 1,
is_change_row_cell: 0,
select_random: 0,
row_random: 0,
cell_random: 0,
disabled: [],
is_three_dimensions: 0,
material_sn: '',
version: '',
scene_information: null,
simple_scene_information: null,
scene: null,
shelf: null,
ware: null,
is_behavior: 0,
is_price_tag: 0,
is_brand: 0,
is_initialize: 0,
is_default_perspective: 0,
is_disable_lines_same: 0,
disable_lines_same: 1,
float_window: 0,
is_disable: 0,
float_window_content: '',
popup_window: 0,
popup_window_content: '',
is_show: [],
quick_type: 0,
is_limit_right_content: 0,
option_group_random_inside: null,
option_group_random_outside: null,
row_option_groups: {
max: 2,
min: 0,
option_group: [],
is_hide: 0
},
cell_option_groups: null,
is_repeat: 0,
allow_repeat_num: 2,
repeat_type: 0,
alert_text: '您在每一题的态度与观点均对我们有非常重要的意义,请您务必仔细阅读题目后回答,连续一致的答案可能会导致整个问卷的作废,谢谢您的配合。'
},
tip: '',
question_code: '',
question_value: '',
other: '',
logic_config: {
expect: '',
order: 0,
type: 0,
stay_time: ''
},
list: [
{
type: 2,
cite_type: 0,
relation_type: 2,
relation_out_scope: [],
relation_last_scope: 0,
relation_first_scope: 0,
relation_question_index: 2,
options: [
{
option: '<p>选项1</p>',
is_other: 0,
is_fixed: 0,
is_remove_other: 0,
level: 0,
option_key: 'Q2A1',
option_index: '1',
option_code: '',
option_config: {
type: 0,
price: 0,
title: '',
gradient: '',
image_url: [],
child_area: null,
option_type: 0,
instructions: [],
binding_goods_id: '',
limit_right_content: ''
},
parent_option_index: 0,
children: null
},
{
option: '<p>选项2</p>',
is_other: 0,
is_fixed: 0,
is_remove_other: 0,
level: 0,
option_key: 'Q2A2',
option_index: '2',
option_code: '',
option_config: {
type: 0,
price: 0,
title: '',
gradient: '',
image_url: [],
child_area: null,
option_type: 0,
instructions: [],
binding_goods_id: '',
limit_right_content: ''
},
parent_option_index: 0,
children: null
},
{
option: '<p>选项3</p>',
is_other: 0,
is_fixed: 0,
is_remove_other: 0,
level: 0,
option_key: 'Q2A3',
option_index: '3',
option_code: '',
option_config: {
type: 0,
price: 0,
title: '',
gradient: '',
image_url: [],
child_area: null,
option_type: 0,
instructions: [],
binding_goods_id: '',
limit_right_content: ''
},
parent_option_index: 0,
children: null
} }
]
},
{
type: 1,
cite_type: 0,
relation_type: 0,
relation_out_scope: [],
relation_last_scope: 0,
relation_first_scope: 0,
relation_question_index: 0,
options: [
{
option: '<p style="text-align:center;">行标签11</p>',
is_other: 0,
is_fixed: 0,
is_remove_other: 0,
level: 0,
option_key: '1',
option_index: '9',
option_code: '',
option_config: {
type: 0,
price: 0,
title: '',
gradient: '',
image_url: [],
child_area: null,
option_type: 0,
instructions: [],
binding_goods_id: '',
limit_right_content: '右极文字1'
},
parent_option_index: 0,
children: null
},
{
option: '<p style="text-align:center;">行标签21</p>',
is_other: 0,
is_fixed: 0,
is_remove_other: 0,
level: 0,
option_key: '2',
option_index: '10',
option_code: '',
option_config: {
type: 0,
price: 0,
title: '',
gradient: '',
image_url: [],
child_area: null,
option_type: 0,
instructions: [],
binding_goods_id: '',
limit_right_content: '右极文字2'
},
parent_option_index: 0,
children: null
},
{
option: '<p style="text-align:center;">行标签31</p>',
is_other: 0,
is_fixed: 0,
is_remove_other: 0,
level: 0,
option_key: '3',
option_index: '11',
option_code: '',
option_config: {
type: 0,
price: 0,
title: '',
gradient: '',
image_url: [],
child_area: null,
option_type: 0,
instructions: [],
binding_goods_id: '',
limit_right_content: '右极文字3'
},
parent_option_index: 0,
children: null
}
]
},
{
type: 2,
cite_type: 0,
relation_type: 0,
relation_out_scope: [],
relation_last_scope: 0,
relation_first_scope: 0,
relation_question_index: 0,
options: [
{
option: '<p style="text-align:center;">列标签1</p>',
is_other: 0,
is_fixed: 0,
is_remove_other: 0,
level: 0,
option_key: '1',
option_index: '12',
option_code: '',
option_config: {
type: 0,
price: 0,
title: '',
gradient: '',
image_url: [],
child_area: null,
option_type: 0,
instructions: [],
binding_goods_id: '',
limit_right_content: '右极文字1'
},
parent_option_index: 0,
children: null
},
{
option: '<p style="text-align:center;">列标签2</p>',
is_other: 0,
is_fixed: 0,
is_remove_other: 0,
level: 0,
option_key: '2',
option_index: '13',
option_code: '',
option_config: {
type: 0,
price: 0,
title: '',
gradient: '',
image_url: [],
child_area: null,
option_type: 0,
instructions: [],
binding_goods_id: '',
limit_right_content: '右极文字2'
},
parent_option_index: 0,
children: null
},
{
option: '<p style="text-align:center;">列标签3</p>',
is_other: 0,
is_fixed: 0,
is_remove_other: 0,
level: 0,
option_key: '3',
option_index: '14',
option_code: '',
option_config: {
type: 0,
price: 0,
title: '',
gradient: '',
image_url: [],
child_area: null,
option_type: 0,
instructions: [],
binding_goods_id: '',
limit_right_content: '右极文字3'
},
parent_option_index: 0,
children: null
}
]
}
],
related: []
}
], ],
cycle_pages: null cycle_pages: null
} }

View File

@@ -1,43 +1,24 @@
<template> <template>
<div class="design-create"> <div class="design-create">
<draggable <draggable v-model:data="questionInfo.questions" item-key="id" handle=".moverQues" chosenClass="chosen"
v-model:data="questionInfo.questions" animation="300" :scroll="true">
item-key="id"
handle=".moverQues"
chosenClass="chosen"
animation="300"
:scroll="true"
>
<template #item="{ element, index }"> <template #item="{ element, index }">
<choose-question <choose-question :element="element" :questions="questionInfo.questions" :index="index"
:element="element" :chooseQuestionId="chooseQuestionId" @get-choose-question-id="getChooseQuestionId">
:questions="questionInfo.questions" <base-select v-if="element.question_type === 1" :element="element"
:index="index" :active="chooseQuestionId === element.id"></base-select>
:chooseQuestionId="chooseQuestionId" <Completion v-if="element.question_type === 4" :element="element" :active="chooseQuestionId === element.id"
@get-choose-question-id="getChooseQuestionId" sn="lXEBBpE2"></Completion>
>
<base-select <martrix-question v-if="element.question_type === 9" :element="element"
v-if="element.question_type === 1" :active="chooseQuestionId === element.id" />
:element="element"
:active="chooseQuestionId === element.id"
></base-select>
<Completion
v-if="element.question_type === 4"
:element="element"
:active="chooseQuestionId === element.id"
sn="lXEBBpE2"
></Completion>
</choose-question> </choose-question>
<!-- {{ element.question_type }}--> <!-- {{ element.question_type }}-->
<!-- {{questionInfo.survey.pages.length}}--> <!-- {{questionInfo.survey.pages.length}}-->
<paging <paging v-if="!element.question_type && questionInfo.survey.pages.length > 1" :info="element" :index="index"
v-if="!element.question_type && questionInfo.survey.pages.length > 1" :active="pageIsActive(activeIndex, questionInfo.questions, element.page)" @click.stop="" />
:info="element"
:index="index"
:active="pageIsActive(activeIndex, questionInfo.questions, element.page)"
@click.stop=""
/>
</template> </template>
</draggable> </draggable>
</div> </div>
@@ -51,12 +32,12 @@ import BaseSelect from './components/Questions/BaseSelect.vue';
import ChooseQuestion from './components/ChooseQuestion.vue'; import ChooseQuestion from './components/ChooseQuestion.vue';
import Paging from './components/Questions/paging/Paging.vue'; import Paging from './components/Questions/paging/Paging.vue';
import Completion from './components/Questions/Completion.vue'; import Completion from './components/Questions/Completion.vue';
import MartrixQuestion from './components/Questions/MartrixQuestion.vue';
const activeIndex = ref(-1); const activeIndex = ref(-1);
/** /**
* 工具函数 * 工具函数
*/ */
function util() { function util () {
/** 通过id找到数组中对应的下标 */ /** 通过id找到数组中对应的下标 */
const getIndexById = (arr, id) => arr.findIndex((i) => i.id === id); const getIndexById = (arr, id) => arr.findIndex((i) => i.id === id);
/** 通过分页找到数组中对应的下标 */ /** 通过分页找到数组中对应的下标 */

View File

@@ -0,0 +1,137 @@
<script setup lang="ts">
// import { showConfirmDialog } from 'vant';
const { element } = defineProps({
element: {
type: Object,
required: true,
default: () => ({})
}
});
/**
* input 类型映射,里面自行处理逻辑返回对应类型
* @param regx
* @default 'radio'
*/
const tableInputTypeMapping = (/** regx?: any */) => {
return 'radio';
};
/**
* 增加行或者列
* @param addType 增加行或列的类型
*/
const handleAdd = (addType: 'row' | 'col') => {
const row = element.list[1].options;
const col = element.list[2].options;
addType === 'row' ? row.push([]) : col.push([]);
};
const handleMartrixAction = (action: 'delete' | 'setting' | 'more') => {
switch (action) {
// case 'delete':
// showConfirmDialog({
// title: '提示',
// message: '是否确认删除题目?'
// }).then(() => {
// element.list = [];
// });
// break;
// case 'setting':
// break;
// case 'more':
// break;
default:
break;
}
};
</script>
<template>
<van-cell-group :border="false">
<van-cell>
<!-- 使用 title 插槽来自定义标题 -->
<template #title>
<span v-if="element.config.is_required">*</span>
<span>{{ element.title }} {{ element.stem }}</span>
</template>
<!-- 使用 label 插槽来自定义标题 -->
<template #label>
<table class="martrix-table">
<tr>
<th></th>
<th v-for="col in element.list[2].options" :key="col.option" v-html="col.option"></th>
</tr>
<tr v-for="row in element.list[1].options" :key="row.option">
<td v-html="row.option"></td>
<!-- table 表格里面的内容和 th 保持一致 -->
<td v-for="col in element.list[2].options" :key="col.option">
<input :type="tableInputTypeMapping()" :name="col.option" />
</td>
</tr>
</table>
<!-- 底部功能按钮 -->
<van-row class="martrix-table-action">
<van-col :span="12">
<span @click="handleAdd('row')"> <van-icon name="add-o" />添加行标签</span>
<span @click="handleAdd('col')"> <van-icon name="add-o" />添加列标签</span>
</van-col>
<van-col :span="6" :offset="6" class="martrix-table-action-tool">
<span @click="handleMartrixAction('delete')"> <van-icon
name="delete"
style="color: red;"
/></span>
<span @click="handleMartrixAction('setting')"> <van-icon
name="setting"
style="color: lightgrey;"
/></span>
<span @click="handleMartrixAction('more')"> <van-icon
name="ellipsis"
style="color: lightgrey;"
/></span>
</van-col>
</van-row>
</template>
</van-cell>
</van-cell-group>
</template>
<style scoped lang="scss">
.martrix-table {
border-collapse: collapse;
color: black;
width: 100%;
th,
td {
border: 1px solid #ddd;
border-width: 0 0 1px 0;
padding: 8px;
text-align: left;
}
}
.martrix-table-action {
margin-top: 10px;
.van-icon {
font-size: 12px;
color: lightgreen;
}
.martrix-table-action-tool {
display: flex;
justify-content: flex-end;
&>span {
font-size: 16px;
margin-right: 6px;
}
}
}
</style>