feat(Design): 重构题前逻辑组件

- 新增 YLInput 组件
- 新增 questionSteeingList 工具文件
- 新增 BeforeRadio、BeforeCheckbox 和 BeforeCompletion 组件
- 重构 QuestionBefore 组件,支持不同题型的逻辑配置
- 优化 QuestionAction 和 ChooseQuestion组件,增加 questionsInfo 参数
- 调整 NPS 和 Design 组件,以适应新的逻辑配置方式
This commit is contained in:
陈昱达
2025-03-14 19:16:58 +08:00
parent 144dc28eca
commit 8c2d426421
30 changed files with 950 additions and 554 deletions

9
components.d.ts vendored
View File

@@ -2,12 +2,13 @@
// @ts-nocheck
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399
export {};
export {}
/* prettier-ignore */
declare module 'vue' {
export interface GlobalComponents {
Contenteditable: typeof import('./src/components/contenteditable.vue')['default']
ElInput: typeof import('element-plus/es')['ElInput']
ElOption: typeof import('element-plus/es')['ElOption']
ElSelect: typeof import('element-plus/es')['ElSelect']
RichText: typeof import('./src/components/RichText.vue')['default']
@@ -22,7 +23,10 @@ declare module 'vue' {
VanCol: typeof import('vant/es')['Col']
VanDivider: typeof import('vant/es')['Divider']
VanField: typeof import('vant/es')['Field']
VanGrid: typeof import('vant/es')['Grid']
VanGridItem: typeof import('vant/es')['GridItem']
VanIcon: typeof import('vant/es')['Icon']
VanNavBar: typeof import('vant/es')['NavBar']
VanPicker: typeof import('vant/es')['Picker']
VanPopup: typeof import('vant/es')['Popup']
VanRadio: typeof import('vant/es')['Radio']
@@ -31,11 +35,10 @@ declare module 'vue' {
VanSearch: typeof import('vant/es')['Search']
VanStepper: typeof import('vant/es')['Stepper']
VanSwitch: typeof import('vant/es')['Switch']
VanTab: typeof import('vant/es')['Tab']
VanTabbar: typeof import('vant/es')['Tabbar']
VanTabbarItem: typeof import('vant/es')['TabbarItem']
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']
YLSelect: typeof import('./src/components/YLSelect.vue')['default']
}

View File

@@ -12,6 +12,14 @@ a,
transition: 0.4s;
}
.theme-color {
color: $theme-color;
}
.theme-background {
background: $theme-color;
}
.ml10 {
margin-left: 10px;
}

View File

@@ -0,0 +1,70 @@
<template>
<el-input v-model="selectedValue" @blur="handleChange($event.target.value)"></el-input>
</template>
<script>
import { defineComponent, ref, watch } from 'vue';
import 'element-plus/dist/index.css';
import { ElInput } from 'element-plus';
export default defineComponent({
name: 'YLSelect',
components: {
ElInput
},
props: {
modelValue: {
type: [String, Number],
default: ''
},
options: {
type: Array,
default: () => []
},
placeholder: {
type: String,
default: '请选择'
},
disabled: {
type: Boolean,
default: false
}
},
setup(props, { emit }) {
const selectedValue = ref(props.modelValue);
watch(
() => props.modelValue,
(newVal) => {
selectedValue.value = newVal;
}
);
const handleChange = (event) => {
console.log(event);
emit('update:modelValue', event);
emit('change', event);
};
const format = (html) => {
const div = document.createElement('div');
div.innerHTML = html;
return div.innerText;
};
return {
selectedValue,
handleChange,
format
};
}
});
</script>
<style scoped lang="scss">
.yl-select-wrapper {
position: relative;
display: inline-block;
font-size: 16px; /* 增加字体大小 */
line-height: 1.5; /* 增加行高 */
//margin-botton: 10px;
}
</style>

View File

@@ -170,8 +170,8 @@ const getMaxDateLimit = computed(() => {
props.format
);
const tempStr = '0000-12-31 23:59:59';
const result =
props.maxDate.length !== 0 && thisMax.length > props.maxDate.length
const result
= props.maxDate.length !== 0 && thisMax.length > props.maxDate.length
? thisMax.slice(0, props.maxDate.length) + tempStr.slice(props.maxDate.length)
: thisMax;
return result.slice(0, props.format.length);
@@ -194,8 +194,8 @@ function onChange({ selectedValues, columnIndex }) {
renderMinuteColumns,
renderSecondColumns
];
updateColumns[columnIndex] &&
updateColumns[columnIndex](changeValue, getMinDateLimit.value, getMaxDateLimit.value, false);
updateColumns[columnIndex]
&& updateColumns[columnIndex](changeValue, getMinDateLimit.value, getMaxDateLimit.value, false);
}
// 渲染全部列

View File

@@ -18,6 +18,8 @@
<!-- {{ option }}-->
<div class="yl-select-label" v-html="format(label)"></div>
</template>
<!-- <template #suffix-icon></template>-->
</el-select>
</template>
@@ -84,6 +86,7 @@ export default defineComponent({
display: inline-block;
font-size: 16px; /* 增加字体大小 */
line-height: 1.5; /* 增加行高 */
//margin-botton: 10px;
}
.yl-select-label {
@@ -97,6 +100,6 @@ export default defineComponent({
<style>
.yl-select {
overflow: hidden;
max-width: 80%;
max-width: 95vw;
}
</style>

View File

@@ -51,8 +51,8 @@ const canPlanetPublishPSM = function (data) {
let content = '';
let title = '题目设置未完成';
const incompleteQuestionList = [];
data.questions &&
data.questions.forEach((s) => {
data.questions
&& data.questions.forEach((s) => {
if (s.question_type === 101 && s.config.price_gradient.length <= 0) {
isFb = false;
content = 'psm题目未完成设置请设置价格区间后投放';
@@ -84,8 +84,8 @@ const canPlanetPublishMxdAndHotArea = function (data) {
const incompleteQuestionList = [];
let type = 0;
let title = '题目设置未完成';
data.questions &&
data.questions.forEach((s) => {
data.questions
&& data.questions.forEach((s) => {
if (s.question_type === 105 && s.config.design_version <= 0) {
isFb = false;
content = 'maxdiff题目未完成设置请生成设计后投放';
@@ -130,8 +130,8 @@ const canPlanetPublish3D = function (data) {
let content = '';
const qSteams = [];
let title = '';
data.questions &&
data.questions.forEach((s) => {
data.questions
&& data.questions.forEach((s) => {
if (QUESTION_TYPE.contains(s.question_type)) {
try {
if (s.config.is_three_dimensions && !s.config.scene) {
@@ -161,15 +161,15 @@ const canPlanetPublish3D = function (data) {
let content = '';
const qSteams = [];
let title = '';
data.questions &&
data.questions.forEach((s) => {
data.questions
&& data.questions.forEach((s) => {
if (QUESTION_TYPE.contains(s.question_type)) {
try {
if (s.config.is_three_dimensions && s.config.is_binding_goods) {
const wares = [];
const _sceneInformation = s.config.scene_information;
const sceneInformation =
typeof _sceneInformation === 'string'
const sceneInformation
= typeof _sceneInformation === 'string'
? JSON.parse(_sceneInformation)
: _sceneInformation;
sceneInformation.shelves.forEach((shelf) => {
@@ -227,8 +227,8 @@ const canPlanetPublishImage = function (data) {
let content = '';
const qSteams = [];
let title = '';
data.questions &&
data.questions.forEach((s) => {
data.questions
&& data.questions.forEach((s) => {
if (s.question_type === 13) {
try {
if (s.options.length <= 0 || s.options.some((y) => y.length <= 0)) {
@@ -323,8 +323,8 @@ function canPublishRandom(data, publishType) {
if (!isValidated) {
errors.push({
message:
field.message ||
`请填写“${random.title}”中第${index + 1}组“随机题组”的“${field.name}`
field.message
|| `请填写“${random.title}”中第${index + 1}组“随机题组”的“${field.name}`
});
}
});

View File

@@ -3,8 +3,6 @@ import 'amfe-flexible';
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';
import 'vant/lib/index.css';
import router from './router';
import utils from '@/assets/js/common';
// 2. 引入组件样式
@@ -12,9 +10,11 @@ import 'vant/lib/index.css';
import '@/style/utils.scss';
import appBridge from '@/assets/js/appBridge';
import VConsole from 'vconsole';
let vconsole;
const app = createApp(App);
if (import.meta.env.VITE_APP_ENV !== 'production') {
vconsole = new VConsole();
const vconsole = new VConsole();
app.use(vconsole);
}
// 添加 TypeScript 类型声明,在文件顶部添加
@@ -52,7 +52,6 @@ router.beforeEach((to, from, next) => {
};
next();
});
const app = createApp(App);
app.use(createPinia());
app.use(router);
app.mount('#app');

View File

@@ -1,2 +1,2 @@
export const surveyQuestion =
'https://yls-api-uat.dctest.digitalyili.com/api/console/surveys/RWNK9BYp/questions';
export const surveyQuestion
= 'https://yls-api-uat.dctest.digitalyili.com/api/console/surveys/RWNK9BYp/questions';

View File

@@ -38,10 +38,10 @@ service.interceptors.request.use(
service.interceptors.response.use(
(response) => {
if (
response.status === 200 ||
response.status === 201 ||
response.status === 202 ||
response.status === 204
response.status === 200
|| response.status === 201
|| response.status === 202
|| response.status === 204
) {
if (response.config.method === 'put') {
// message.success('保存中...');

View File

@@ -0,0 +1,86 @@
const groupOptions = [
{
label: '选项',
value: 0
}
// {
// label: '分组',
// value: 1
// // disabled: true
// }
];
const settingIfOptions = [
{ label: 'IF', value: 'if' },
{ label: 'Always', value: 'always' }
];
const settingAndOptions = [
{ label: 'AND', value: 'and' },
{ label: 'OR', value: 'or' }
];
const answerOptions = [
{ label: '为空', value: 0 },
{ label: '不为空', value: 1 }
];
const chooseOptions = [
{ label: '被选中', value: 1 },
{ label: '未被选中', value: 0 }
];
const symbolOptions = [
{
label: '=',
value: '='
},
{
label: '≠',
value: '≠'
},
{
label: '>',
value: '>'
},
{
label: '≥',
value: '>'
},
{
label: '<',
value: '<'
},
{
label: '≤',
value: '≤'
}
];
// <a-select-option value="包含">包含</a-select-option>
// <a-select-option value="不包含">不包含</a-select-option>
// <a-select-option value="是">是</a-select-option>
// <a-select-option value="不是">不是</a-select-option>
const completionOptions = [
{
label: '包含',
value: '包含'
},
{
label: '不包含',
value: '不包含'
},
{
label: '是',
value: '是'
},
{
label: '不是',
value: '不是'
}
];
export {
groupOptions,
settingIfOptions,
settingAndOptions,
answerOptions,
symbolOptions,
chooseOptions,
completionOptions
};

View File

@@ -44,10 +44,10 @@ service.interceptors.request.use(
service.interceptors.response.use(
(response) => {
if (
response.status === 200 ||
response.status === 201 ||
response.status === 202 ||
response.status === 204
response.status === 200
|| response.status === 201
|| response.status === 202
|| response.status === 204
) {
if (response.config.method === 'put') {
// message.success('保存中...');

View File

@@ -14,6 +14,7 @@
:questions="questionInfo.questions"
:index="index"
:chooseQuestionId="chooseQuestionId"
:questionsInfo="questionInfo"
@get-choose-question-id="getChooseQuestionId"
@move="emitFun.move"
@copy="emitFun.copy"
@@ -239,10 +240,10 @@ const chooseQuestionIndex = ref(-1);
const questionInfo = computed(() => store.questionsInfo.value);
// 自动更新 题型
watch(
() => questionInfo.value.questions[chooseQuestionIndex.value],
() => questionInfo.value.questions,
(newVal) => {
if (newVal) {
// saveQueItem(questionInfo.value.logics, [newVal]);
saveQueItem(questionInfo.value.logics, newVal); // 确保保存最新的数据
}
},
{ deep: true }
@@ -417,6 +418,8 @@ const emitFun = {
saveQueItem(null, [item]);
},
logics: (item) => {
// console.log(questionInfo.value.logics[);
// return false;
saveQueItem(questionInfo.value.logics, [item]);
}
};

View File

@@ -124,7 +124,12 @@
</header>
<!-- 题前 题后逻辑 本来打算拆成两个 但是 只有最后的处理不一样-->
<div class="before-or-after">
<question-before :skipType="skipType" :activeQuestion="activeQuestion"></question-before>
{{ questionsInfo.logics[2].logic }}
<question-before
:skipType="skipType"
:activeQuestion="activeQuestion"
:questionsInfo="questionsInfo"
></question-before>
</div>
</div>
</van-popup>
@@ -132,19 +137,13 @@
<script setup>
import checkboxQuestionAction from './components/QuestionItemAction/CheckboxQuestionAction.vue';
import { showConfirmDialog } from 'vant';
import { ref } from 'vue';
import { useCounterStore } from '@/stores/counter';
import { storeToRefs } from 'pinia';
import { toRefs, ref } from 'vue';
import QuestionBefore from '@/views/Design/components/ActionCompoents/components/QuestionItemAction/QuestionBefore.vue';
import RateQuestionAction from './components/QuestionItemAction/RateQuestionAction.vue';
import CompletionQuestionAction from '@/views/Design/components/ActionCompoents/components/QuestionItemAction/CompletionQuestionAction.vue';
import FieldUploadQuestionAction from '@/views/Design/components/ActionCompoents/components/QuestionItemAction/FieldUploadQuestionAction.vue';
import MartrixQuestionAction from '@/views/Design/components/ActionCompoents/components/QuestionItemAction/MartrixQuestionAction.vue';
import { v4 as uuidv4 } from 'uuid';
const store = useCounterStore();
const { questionsInfo } = storeToRefs(store);
const logics = questionsInfo.value.logics;
const props = defineProps({
index: {
type: Number,
@@ -156,6 +155,12 @@ const props = defineProps({
// 传递
}
},
questionsInfo: {
type: Object,
default: () => {
// 传递
}
},
questions: {
type: Array,
default: () => []
@@ -165,6 +170,8 @@ const props = defineProps({
default: 0
}
});
const { questionsInfo } = toRefs(props);
const logics = questionsInfo.value.logics;
const questions = ref(props.questions);
// emit
const emit = defineEmits(['move', 'copy', 'delete', 'setting', 'logics']);
@@ -173,7 +180,7 @@ const saveSettings = () => {
emit('setting', activeQuestion.value);
};
const saveLogics = () => {
emit('logics', activeQuestion.value);
emit('logics', questionsInfo.value); // 将更新后的 questionsInfo 传递给父组件
};
// 当前题目

View File

@@ -0,0 +1,91 @@
<template>
<div class="flex mt10 align-center space-between">
<!-- 选项 or 分组 -->
<yl-select v-model="logic.is_option_group" :options="groupOptions" class="group"></yl-select>
<!-- 分组group_index 或者非分组 option_index-->
<yl-select
v-if="logic.is_option_group === 0"
v-model="logic.option_index"
class="ml10"
:options="changeQuestionIndex(logic.question_index, logic)"
></yl-select>
<yl-select
v-else
v-model="logic.group_index"
class="ml10"
:options="changeQuestionIndex(logic.question_index, logic)"
></yl-select>
<!--是否被选中-->
<yl-select v-model="logic.is_select" class="ml10" :options="chooseOptions"></yl-select>
<div class="action-setting flex ml10">
<van-icon name="clear" size="0.5rem" class="ml10 theme-color" />
<van-icon name="add" size="0.5rem" class="ml10 theme-color" />
<van-icon name="delete" size="0.5rem" class="ml10" />
</div>
</div>
</template>
<script setup>
import { groupOptions, chooseOptions } from '@/utils/questionSteeingList.js';
import YlSelect from '@/components/YLSelect.vue';
import { toRefs, watch } from 'vue';
const props = defineProps({
logic: {
type: Object,
default: () => {
return {};
}
},
logIndex: {
type: Number,
default: 0
},
beforeQuesOptions: {
type: Array,
default: () => {
return [];
}
},
activeQuestion: {
type: Object,
default: () => {
return {};
}
}
});
const changeQuestionIndex = () => {
let options = [];
beforeQuesOptions.value.forEach((item) => {
if (item.question_index === logic.value.question_index) {
if (item.question_type === 2) {
// 不是分组
if (logic.value.is_option_group === 0) {
options = item.options[0].map((optItem) => {
return {
...optItem,
label: optItem.option,
value: optItem.option_index
};
});
}
// 分组
}
}
});
return options;
};
const { logic, beforeQuesOptions } = toRefs(props);
watch(
() => logic.value,
(newVal, oldVal) => {
console.log(newVal);
if (newVal !== oldVal) {
changeQuestionIndex();
}
},
{ deep: true }
);
</script>
<style scoped lang="scss"></style>

View File

@@ -0,0 +1,20 @@
<template>
<div class="flex mt10 align-center space-between">
<!--是否被选中-->
<yl-select v-model="logic.operator" :options="completionOptions"></yl-select>
<yl-input v-model="logic.value" class="ml10" />
<div class="action-setting flex ml10">
<van-icon name="clear" size="0.5rem" class="ml10 theme-color" />
<van-icon name="add" size="0.5rem" class="ml10 theme-color" />
<van-icon name="delete" size="0.5rem" class="ml10" />
</div>
</div>
</template>
<script setup>
import { completionOptions } from '@/utils/questionSteeingList.js';
import YlSelect from '@/components/YLSelect.vue';
import YlInput from '@/components/YLInput.vue';
const logic = defineModel('logic', {});
</script>
<style scoped lang="scss"></style>

View File

@@ -0,0 +1,99 @@
<template>
<div class="flex align-center space-between mt10">
<!-- 选项 or 分组 -->
<yl-select
v-model="logic.is_option_group"
:options="groupOptions"
class="mr10 group"
></yl-select>
<!-- 符号-->
<yl-select
v-model="logic.operator"
:options="symbolOptions"
class="mr10 symbol ml10"
></yl-select>
<yl-select
v-if="logic.is_option_group === 0"
v-model="logic.option_index"
class="ml10"
:options="changeQuestionIndex(logic.question_index, logic)"
></yl-select>
<yl-select
v-else
v-model="logic.group_index"
class="ml10"
:options="changeQuestionIndex(logic.question_index, logic)"
></yl-select>
<div class="action-setting flex ml10">
<van-icon name="clear" size="0.5rem" class="ml10 theme-color" />
<van-icon name="add" size="0.5rem" class="ml10 theme-color" />
<van-icon name="delete" size="0.5rem" class="ml10" />
</div>
</div>
</template>
<script setup>
import { groupOptions, symbolOptions } from '@/utils/questionSteeingList.js';
import YlSelect from '@/components/YLSelect.vue';
import { toRefs, watch } from 'vue';
const props = defineProps({
// logic: {
// type: Object,
// default: () => {
// return {};
// }
// },
logIndex: {
type: Number,
default: 0
},
beforeQuesOptions: {
type: Array,
default: () => {
return [];
}
},
activeQuestion: {
type: Object,
default: () => {
return {};
}
}
});
const changeQuestionIndex = () => {
let options = [];
beforeQuesOptions.value.forEach((item) => {
if (item.question_index === logic.value.question_index) {
if (item.question_type === 1) {
// 不是分组
if (logic.value.is_option_group === 0) {
options = item.options[0].map((optItem) => {
return {
...optItem,
label: optItem.option,
value: optItem.option_index
};
});
}
// 分组
}
}
});
return options;
};
const { beforeQuesOptions } = toRefs(props);
const logic = defineModel('logic', {});
watch(
() => logic.value,
(newVal, oldVal) => {
console.log(newVal);
if (newVal !== oldVal) {
changeQuestionIndex();
}
},
{ deep: true }
);
</script>
<style scoped lang="scss"></style>

View File

@@ -5,8 +5,10 @@
>
<div class="mt10">
<template v-for="(log, logIndex) in item.logic" :key="logIndex">
<div class="flex align-center space-between">
<div class=" ">
<div class="question-before mb10">
<div>
<!-- 固定分组-->
<!-- if always-->
<yl-select
v-model="log.logic"
@@ -14,69 +16,73 @@
class="if mr10"
@change="logicIf($event, index)"
></yl-select>
</div>
<div class="flex align-center space-between">
<!-- 问题-->
<yl-select
v-if="log.logic !== 'always'"
v-model="log.question_index"
class="question"
class="question mt10"
:options="beforeQuesOptions"
placeholder="请选择问题"
@change="getQuestionType"
@change="getQuestionType($event, log)"
></yl-select>
<!-- 为空 不为空-->
<yl-select
v-if="log.logic !== 'always'"
v-model="log.is_answer"
class="answer mr10 mt10"
class="answer ml10 mt10"
:options="answerOptions"
></yl-select>
<!-- 选项 or 分组 -->
<yl-select
v-if="log.logic !== 'always' && log.is_answer !== 0"
v-model="log.is_option_group"
:options="groupOptions"
class="mr10 group mt10"
></yl-select>
<!-- 符号-->
<yl-select
v-if="log.logic !== 'always' && log.is_answer !== 0"
v-model="log.operator"
:options="symbolOptions"
class="mr10 symbol mt10"
></yl-select>
<!-- 分组 option 选项option-->
<div
v-if="log.logic !== 'always' && log.is_answer !== 0"
class="flex align-center space-between option mt10"
>
<yl-select
v-if="log.is_option_group === 0"
v-model="log.option_index"
class="mr10"
:options="changeQuestionIndex(log.question_index, log)"
></yl-select>
<yl-select
v-else
v-model="log.group_index"
class="mr10"
:options="changeQuestionIndex(log.question_index, log)"
></yl-select>
</div>
<!--单选-->
<BeforeRadio
v-if="
log.logic !== 'always' && log.is_answer !== 0 && [1].includes(log.question_type)
"
:activeQuestion="activeQuestion"
:logic="log"
:logIndex="logIndex"
:beforeQuesOptions="beforeQuesOptions"
></BeforeRadio>
<!-- 多选-->
<BeforeCkeckbox
v-if="
log.logic !== 'always' && log.is_answer !== 0 && [2].includes(log.question_type)
"
:activeQuestion="activeQuestion"
:logic="log"
:logIndex="logIndex"
:beforeQuesOptions="beforeQuesOptions"
></BeforeCkeckbox>
<!-- 填空-->
<!-- {{ questionsInfo.logics[index].logic }}-->
<BeforeCompletion
v-if="
log.logic !== 'always' && log.is_answer !== 0 && [4].includes(log.question_type)
"
:activeQuestion="activeQuestion"
:logic="log"
:logIndex="logIndex"
:index="index"
:beforeQuesOptions="beforeQuesOptions"
@update-logic="updateLogic"
></BeforeCompletion>
</div>
<div class="action">
<van-icon
v-if="logIndex !== 0 || log.logic === 'always'"
name="clear"
class="mr10"
@click="deleteLogic(logIndex, item.logic, index)"
></van-icon>
<van-icon
v-if="log.logic !== 'always'"
name="add"
@click="addLogicItem(logIndex, item.logic)"
></van-icon>
</div>
<!-- <div class="action">-->
<!-- <van-icon-->
<!-- v-if="logIndex !== 0 || log.logic === 'always'"-->
<!-- name="clear"-->
<!-- class="mr10"-->
<!-- @click="deleteLogic(logIndex, item.logic, index)"-->
<!-- ></van-icon>-->
<!-- <van-icon-->
<!-- v-if="log.logic !== 'always'"-->
<!-- name="add"-->
<!-- @click="addLogicItem(logIndex, item.logic)"-->
<!-- ></van-icon>-->
<!-- </div>-->
</div>
</template>
<!-- 如果是题前隐藏-->
@@ -92,14 +98,14 @@
</div>
</div>
<van-divider
:dashed="true"
:hairline="false"
content-position="right"
:style="{ borderColor: '#bfbfbf' }"
>
<van-icon name="delete" @click="remoteLogic(index)">删除</van-icon>
</van-divider>
<!-- <van-divider-->
<!-- :dashed="true"-->
<!-- :hairline="false"-->
<!-- content-position="right"-->
<!-- :style="{ borderColor: '#bfbfbf' }"-->
<!-- >-->
<!-- <van-icon name="delete" @click="remoteLogic(index)">删除</van-icon>-->
<!-- </van-divider>-->
<!-- <div-->
<!-- v-if="item.skip_type === skipType && item.question_index === activeQuestion.question_index"-->
<!-- >-->
@@ -112,14 +118,12 @@
</div>
</template>
<script setup>
import { settingIfOptions, settingAndOptions, answerOptions } from '@/utils/questionSteeingList.js';
import YlSelect from '@/components/YLSelect.vue';
import { ref } from 'vue';
import { storeToRefs } from 'pinia';
import { useCounterStore } from '@/stores/counter';
const store = useCounterStore();
const { questionsInfo } = storeToRefs(store);
const logics = ref(questionsInfo.value.logics);
const questions = questionsInfo.value.questions;
import BeforeRadio from './BeforComponent/BeforeRadio.vue';
import BeforeCkeckbox from './BeforComponent/BeforeCheckbox.vue';
import BeforeCompletion from './BeforComponent/BeforeCompletion.vue';
import { ref, toRefs } from 'vue';
const props = defineProps({
activeQuestion: {
type: Object,
@@ -127,11 +131,23 @@ const props = defineProps({
return {};
}
},
questionsInfo: {
type: Object,
default: () => {
return {};
}
},
skipType: {
type: [Number, String],
default: ''
}
});
const { questionsInfo } = toRefs(props);
console.log(questionsInfo, 32);
const logics = ref(questionsInfo.value.logics);
const questions = questionsInfo.value.questions;
// 变量为beforeList questions里面 获取activeQuestion 之前所有的题目
const questionIndex = questions.findIndex((item) => {
@@ -166,6 +182,17 @@ const skipOption = [
];
// questions 排除当前题目的所有数据 并且 排除questions里面无question_type的数据
const emit = defineEmits(['update-logic']);
const updateLogic = (ev) => {
const newLogics = [...questionsInfo.value.logics]; // 创建 logics 的副本
newLogics[ev.index.value].logic.splice(ev.logIndex.value, 1, ev.newVal); // 更新逻辑项
// 确保触发响应式更新
questionsInfo.value.logics = []; // 通过重新赋值触发 Vue 的响应式系统
questionsInfo.value.logics = newLogics; // 通过重新赋值触发 Vue 的响应式系统
emit('update-logic', questionsInfo.value.logics); // 向上触发事件
};
skipOption.push(
...questions
.filter((item) => {
@@ -180,147 +207,51 @@ skipOption.push(
})
);
// 题目选项
let optionOptions = [];
// todo 不同题型逻辑对应不同 需要开发
const changeQuestionIndex = (value, logicItem) => {
if (!value) {
return [];
}
beforeQuesOptions.map((item) => {
if (item.question_index === value) {
if ([1, 2].includes(logicItem.question_type)) {
if (logicItem.is_option_group === 0) {
optionOptions = item.options[0].map((optItem) => {
return {
...optItem,
label: optItem.option,
value: optItem.option_index
};
});
} else if (logicItem.is_option_group === 1) {
optionOptions = item.config.option_groups.option_group.map((groupItem) => {
return {
...groupItem,
label: groupItem.title,
value: groupItem.group_index
};
});
} else {
optionOptions = [];
}
}
}
});
return optionOptions;
};
// 删除 题目设置
const deleteLogic = (logIndex, item, index) => {
item.splice(logIndex, 1);
// 如果小删除 删除后一个都没有了 就删除掉整个数组
if (item.length === 0) {
logics.value.splice(index, 1);
}
};
// const deleteLogic = (logIndex, item, index) => {
// item.splice(logIndex, 1);
// // 如果小删除 删除后一个都没有了 就删除掉整个数组
// if (item.length === 0) {
// // logics.value.splice(index, 1);
// }
// };
// 删除 一个 逻辑
const remoteLogic = (index) => {
logics.value.splice(index, 1);
};
// const remoteLogic = (index) => {
// // logics.value.splice(index, 1);
// };
// 添加题目
const addLogicItem = (logIndex, item) => {
item.splice(logIndex + 1, 0, {
logic: 'and',
question_index: '',
question_type: 0,
is_answer: 1,
operator: '=',
option_index: '',
relation_question_index: 0,
type: 0,
is_option_group: '',
group_index: null
});
};
// const addLogicItem = (logIndex, item) => {
// item.splice(logIndex + 1, 0, {
// logic: 'and',
// question_index: '',
// question_type: 0,
// is_answer: 1,
// operator: '=',
// option_index: '',
// relation_question_index: 0,
// type: 0,
// is_option_group: '',
// group_index: null
// });
// };
// 增加逻辑配置
const addLogic = () => {
logics.value.push({
logic: [
{
type: 0,
logic: 'if',
operator: '=',
is_answer: 1,
question_type: 0,
question_index: 0,
relation_question_index: 0,
relation_question_row_index: 0,
relation_question_cell_index: 0,
option_index: 0
}
],
skip_type: props.skipType,
id: props.activeQuestion.id,
question_index: props.activeQuestion.question_index,
question_id: props.activeQuestion.question_id
});
// 增加逻辑配置
};
const groupOptions = [
{
label: '选项',
value: 0
}
// {
// label: '分组',
// value: 1
// // disabled: true
// }
];
const settingIfOptions = [
{ label: 'if', value: 'if' },
{ label: 'always', value: 'always' }
];
const settingAndOptions = [{ label: 'and', value: 'and' }];
const answerOptions = [
{ label: '为空', value: 0 },
{ label: '不为空', value: 1 }
];
const symbolOptions = [
{
label: '=',
value: '='
},
{
label: '≠',
value: '≠'
},
{
label: '>',
value: '>'
},
{
label: '≥',
value: '>'
},
{
label: '<',
value: '<'
},
{
label: '≤',
value: '≤'
}
];
const getQuestionType = () => {
// const type = beforeQuesOptions.filter((item) => item.question_index === value)[0];
// 获取题目类型
const getQuestionType = (value, log) => {
const question = beforeQuesOptions.filter((item) => item.question_index === value)[0];
log.question_type = question.question_type;
};
const logicIf = (value, index) => {
if (value === 'always') {
logics.value[index].logic = [logics.value[index].logic[0]];
const loginItem = logics.value[index].logic[0];
logics.value[index].logic = [loginItem];
}
};
</script>
@@ -356,19 +287,21 @@ const logicIf = (value, index) => {
}
.question-before {
width: 100%;
& .if {
flex: none;
width: 90px;
width: 100%;
}
& .question {
flex: none;
width: 210px;
//flex: none;
//width: 210px;
}
& .group {
flex: none;
width: 75px;
//flex: none;
//width: 75px;
}
& .answer {

View File

@@ -21,6 +21,7 @@
<template #right-icon>
<question-action
v-model:data="element"
:questionsInfo="questionsInfo"
:questions="questions"
:questionIndex="index"
@move="emit('move', $event)"
@@ -58,6 +59,12 @@ const props = defineProps({
type: Array,
default: () => []
},
questionsInfo: {
type: Object,
default: () => {
// 后续扩展
}
},
chooseQuestionId: {
type: String,
default: '0'
@@ -82,11 +89,10 @@ const getQuestionType = (type) => {
const element = ref(props.element);
// 选中题目后出现的操作
const emit = defineEmits(['getChooseQuestionId', 'move', 'copy']);
const emit = defineEmits(['getChooseQuestionId', 'move', 'copy', 'setting', 'logics']);
// 选中题目
const chooseItem = () => {
// 使用从 defineProps 接收的 element 对象
emit('getChooseQuestionId', props.element, props.index);
};
</script>

View File

@@ -33,7 +33,7 @@
</template>
<script setup>
import { ref } from 'vue';
import { ref, toRefs } from 'vue';
import RateCharacter from './RateCharacter.vue';
const props = defineProps({

View File

@@ -6,60 +6,10 @@
<div class="content">
<div class="title fw-bold fs-14">
<div class="flex align-center">
<svg
t="1741943948491"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="2494"
width="14"
height="14"
>
<path
d="M1024 354c0-1.8-0.2-3.6-0.5-5.4V158c0-51.8-42.2-94-94-94H798V30c0-16.5-13.5-30-30-30s-30 13.5-30 30v34H286V30c0-16.5-13.5-30-30-30s-30 13.5-30 30v34H94.5c-51.8 0-94 42.2-94 94v190.6c-0.3 1.8-0.5 3.6-0.5 5.4 0 1.8 0.2 3.6 0.5 5.4V930c0 51.8 42.2 94 94 94h835c51.8 0 94-42.2 94-94V359.4c0.3-1.8 0.5-3.6 0.5-5.4zM94.5 124H226v38c0 16.5 13.5 30 30 30s30-13.5 30-30v-38h452v38c0 16.5 13.5 30 30 30s30-13.5 30-30v-38h131.5c18.7 0 34 15.3 34 34v166h-903V158c0-18.7 15.3-34 34-34z m835 840h-835c-18.7 0-34-15.3-34-34V384h903v546c0 18.7-15.3 34-34 34z"
fill="#03B03C"
p-id="2495"
/>
<path
d="M697.3 511.6L444.1 764.8 326.7 647.4c-11.7-11.7-30.8-11.7-42.4 0-11.7 11.7-11.7 30.8 0 42.4l138.6 138.6c7.6 7.6 18.3 10.2 28.1 8 0.2 0 0.4-0.1 0.6-0.1 5.1-1.3 9.8-3.9 13.8-7.8L739.7 554c11.7-11.7 11.7-30.8 0-42.4-11.7-11.7-30.8-11.7-42.4 0z"
fill="#03B03C"
p-id="2496"
/>
</svg>
<component :is="contentSvg"></component>
<p class="title_con">{{ item.title }}</p>
</div>
<svg
t="1741944281591"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="3990"
width="16"
height="16"
>
<path
d="M607.897867 768.043004c-17.717453 0-31.994625-14.277171-31.994625-31.994625L575.903242 383.935495c0-17.717453 14.277171-31.994625 31.994625-31.994625s31.994625 14.277171 31.994625 31.994625l0 351.94087C639.892491 753.593818 625.61532 768.043004 607.897867 768.043004z"
fill="#d81e06"
p-id="3991"
/>
<path
d="M415.930119 768.043004c-17.717453 0-31.994625-14.277171-31.994625-31.994625L383.935495 383.935495c0-17.717453 14.277171-31.994625 31.994625-31.994625 17.717453 0 31.994625 14.277171 31.994625 31.994625l0 351.94087C447.924744 753.593818 433.647573 768.043004 415.930119 768.043004z"
fill="#d81e06"
p-id="3992"
/>
<path
d="M928.016126 223.962372l-159.973123 0L768.043004 159.973123c0-52.980346-42.659499-95.983874-95.295817-95.983874L351.94087 63.989249c-52.980346 0-95.983874 43.003528-95.983874 95.983874l0 63.989249-159.973123 0c-17.717453 0-31.994625 14.277171-31.994625 31.994625s14.277171 31.994625 31.994625 31.994625l832.032253 0c17.717453 0 31.994625-14.277171 31.994625-31.994625S945.73358 223.962372 928.016126 223.962372zM319.946246 159.973123c0-17.545439 14.449185-31.994625 31.994625-31.994625l320.806316 0c17.545439 0 31.306568 14.105157 31.306568 31.994625l0 63.989249L319.946246 223.962372 319.946246 159.973123 319.946246 159.973123z"
fill="#d81e06"
p-id="3993"
/>
<path
d="M736.048379 960.010751 288.123635 960.010751c-52.980346 0-95.983874-43.003528-95.983874-95.983874L192.139761 383.591466c0-17.717453 14.277171-31.994625 31.994625-31.994625s31.994625 14.277171 31.994625 31.994625l0 480.435411c0 17.717453 14.449185 31.994625 31.994625 31.994625l448.096758 0c17.717453 0 31.994625-14.277171 31.994625-31.994625L768.215018 384.795565c0-17.717453 14.277171-31.994625 31.994625-31.994625s31.994625 14.277171 31.994625 31.994625l0 479.231312C832.032253 916.835209 789.028725 960.010751 736.048379 960.010751z"
fill="#d81e06"
p-id="3994"
/>
</svg>
<component :is="MarketItemSvg"></component>
</div>
<div class="desc flex space-between">
<div>
@@ -78,6 +28,8 @@
</div>
</template>
<script setup lang="ts">
import contentSvg from './svgs/contentSvg.svg?componet';
import MarketItemSvg from './svgs/MarketItemSvg.svg?componet';
const { info } = defineProps({
info: {
type: Object,

View File

@@ -0,0 +1,31 @@
<svg
t="1741944281591"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="3990"
width="16"
height="16"
>
<path
d="M607.897867 768.043004c-17.717453 0-31.994625-14.277171-31.994625-31.994625L575.903242 383.935495c0-17.717453 14.277171-31.994625 31.994625-31.994625s31.994625 14.277171 31.994625 31.994625l0 351.94087C639.892491 753.593818 625.61532 768.043004 607.897867 768.043004z"
fill="#d81e06"
p-id="3991"
/>
<path
d="M415.930119 768.043004c-17.717453 0-31.994625-14.277171-31.994625-31.994625L383.935495 383.935495c0-17.717453 14.277171-31.994625 31.994625-31.994625 17.717453 0 31.994625 14.277171 31.994625 31.994625l0 351.94087C447.924744 753.593818 433.647573 768.043004 415.930119 768.043004z"
fill="#d81e06"
p-id="3992"
/>
<path
d="M928.016126 223.962372l-159.973123 0L768.043004 159.973123c0-52.980346-42.659499-95.983874-95.295817-95.983874L351.94087 63.989249c-52.980346 0-95.983874 43.003528-95.983874 95.983874l0 63.989249-159.973123 0c-17.717453 0-31.994625 14.277171-31.994625 31.994625s14.277171 31.994625 31.994625 31.994625l832.032253 0c17.717453 0 31.994625-14.277171 31.994625-31.994625S945.73358 223.962372 928.016126 223.962372zM319.946246 159.973123c0-17.545439 14.449185-31.994625 31.994625-31.994625l320.806316 0c17.545439 0 31.306568 14.105157 31.306568 31.994625l0 63.989249L319.946246 223.962372 319.946246 159.973123 319.946246 159.973123z"
fill="#d81e06"
p-id="3993"
/>
<path
d="M736.048379 960.010751 288.123635 960.010751c-52.980346 0-95.983874-43.003528-95.983874-95.983874L192.139761 383.591466c0-17.717453 14.277171-31.994625 31.994625-31.994625s31.994625 14.277171 31.994625 31.994625l0 480.435411c0 17.717453 14.449185 31.994625 31.994625 31.994625l448.096758 0c17.717453 0 31.994625-14.277171 31.994625-31.994625L768.215018 384.795565c0-17.717453 14.277171-31.994625 31.994625-31.994625s31.994625 14.277171 31.994625 31.994625l0 479.231312C832.032253 916.835209 789.028725 960.010751 736.048379 960.010751z"
fill="#d81e06"
p-id="3994"
/>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -0,0 +1,21 @@
<svg
t="1741943948491"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="2494"
width="14"
height="14"
>
<path
d="M1024 354c0-1.8-0.2-3.6-0.5-5.4V158c0-51.8-42.2-94-94-94H798V30c0-16.5-13.5-30-30-30s-30 13.5-30 30v34H286V30c0-16.5-13.5-30-30-30s-30 13.5-30 30v34H94.5c-51.8 0-94 42.2-94 94v190.6c-0.3 1.8-0.5 3.6-0.5 5.4 0 1.8 0.2 3.6 0.5 5.4V930c0 51.8 42.2 94 94 94h835c51.8 0 94-42.2 94-94V359.4c0.3-1.8 0.5-3.6 0.5-5.4zM94.5 124H226v38c0 16.5 13.5 30 30 30s30-13.5 30-30v-38h452v38c0 16.5 13.5 30 30 30s30-13.5 30-30v-38h131.5c18.7 0 34 15.3 34 34v166h-903V158c0-18.7 15.3-34 34-34z m835 840h-835c-18.7 0-34-15.3-34-34V384h903v546c0 18.7-15.3 34-34 34z"
fill="#03B03C"
p-id="2495"
/>
<path
d="M697.3 511.6L444.1 764.8 326.7 647.4c-11.7-11.7-30.8-11.7-42.4 0-11.7 11.7-11.7 30.8 0 42.4l138.6 138.6c7.6 7.6 18.3 10.2 28.1 8 0.2 0 0.4-0.1 0.6-0.1 5.1-1.3 9.8-3.9 13.8-7.8L739.7 554c11.7-11.7 11.7-30.8 0-42.4-11.7-11.7-30.8-11.7-42.4 0z"
fill="#03B03C"
p-id="2496"
/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -19,7 +19,10 @@
</van-field>
</van-cell-group>
</van-cell-group>
<div v-if="styleInfo.logo_status && styleInfo.logo_url" class="example-logo" :style="[
<div
v-if="styleInfo.logo_status && styleInfo.logo_url"
class="example-logo"
:style="[
{
'justify-content':
styleInfo.logo_site === 1
@@ -34,27 +37,59 @@
!styleInfo.head_img_status && styleInfo.background_status
? `background-color: ${styleInfo.background_color};background-image: url(${styleInfo.background_url})`
: ''
]">
]"
>
<img class="logo" :src="styleInfo.logo_url" alt="logo" />
</div>
<!-- 问题 -->
<div class="questions" :style="`min-height: ${styleInfo.head_img_status ? 'calc(100% - 240px)' : '100%'};${styleInfo.background_status
<div
class="questions"
:style="`min-height: ${styleInfo.head_img_status ? 'calc(100% - 240px)' : '100%'};${
styleInfo.background_status
? `background-color: ${styleInfo.background_color};background-image: url(${styleInfo.background_url})`
: ''
}`">
}`"
>
<!-- 提前终止和正常完成 -->
<q-last v-if="page === pages.length + 1" :code="questionsData.action?.code" :action="questionsData.action"
:survey="questionsData.survey" :isAnswer="isAnswer" :isTemplate="isTemplate" />
<q-last
v-if="page === pages.length + 1"
:code="questionsData.action?.code"
:action="questionsData.action"
:survey="questionsData.survey"
:isAnswer="isAnswer"
:isTemplate="isTemplate"
/>
<!-- 问卷名和描述 -->
<q-first v-else-if="page === 0" isMobile :title="questionsData?.survey?.title"
:desc="questionsData?.survey?.introduction" :questions="questionsData?.questions" :isAnswer="isAnswer"
:showTitle="styleInfo.is_title" :showDesc="styleInfo.is_introduce" :label="questionsData?.survey?.title" />
<q-first
v-else-if="page === 0"
isMobile
:title="questionsData?.survey?.title"
:desc="questionsData?.survey?.introduction"
:questions="questionsData?.questions"
:isAnswer="isAnswer"
:showTitle="styleInfo.is_title"
:showDesc="styleInfo.is_introduce"
:label="questionsData?.survey?.title"
/>
<!-- -mobile -->
<question v-for="question in questions" v-else :id="'questionIndex' + question.question_index"
:key="question.question_index" class="question" :tip="question.tip" :stem="question.stem"
:title="question.title" :error="question.error" :warning="question.warning" :questions="questionsData.questions"
:questionType="question.question_type" :questionIndex="question.question_index"
:showTitle="styleInfo.is_question_number && true" isMobile :isAnswer="isAnswer">
<question
v-for="question in questions"
v-else
:id="'questionIndex' + question.question_index"
:key="question.question_index"
class="question"
:tip="question.tip"
:stem="question.stem"
:title="question.title"
:error="question.error"
:warning="question.warning"
:questions="questionsData.questions"
:questionType="question.question_type"
:questionIndex="question.question_index"
:showTitle="styleInfo.is_question_number && true"
isMobile
:isAnswer="isAnswer"
>
<!-- <q-radio-->
<!-- v-if="question.question_type === 1"-->
<!-- :list="question.list"-->
@@ -70,11 +105,21 @@
<!-- :question="question"-->
<!-- />-->
<!-- 单选题 -->
<preview-choice v-if="question.question_type === 1" v-model:answer="question.answer"
v-model:answerIndex="question.answerIndex" :list="question.list" :config="question.config"
:hideOptions="question.hideOptions" :stem="question.stem" :answerSn="questionsData.answer.sn"
:answerSurveySn="questionsData.answer.survey_sn" :question="question" @previous="previous" @next="next"
@change-answer="onRelation($event, question)" />
<preview-choice
v-if="question.question_type === 1"
v-model:answer="question.answer"
v-model:answerIndex="question.answerIndex"
:list="question.list"
:config="question.config"
:hideOptions="question.hideOptions"
:stem="question.stem"
:answerSn="questionsData.answer.sn"
:answerSurveySn="questionsData.answer.survey_sn"
:question="question"
@previous="previous"
@next="next"
@change-answer="onRelation($event, question)"
/>
<!-- &lt;!&ndash; 多选题 &ndash;&gt;-->
<!-- <q-checkbox-->
<!-- v-else-if="question.question_type === 2"-->
@@ -102,9 +147,18 @@
<!-- isMobile-->
<!-- />-->
<!-- 填空题 -->
<preview-completion v-else-if="question.question_type === 4" :config="question.config" :answer="question.answer"
:stem="question.stem" :answerSn="questionsData.answer.sn" :answerSurveySn="questionsData.answer.survey_sn"
:question="question" @previous="previous" @next="next" @change-answer="onRelation($event, question)" />
<preview-completion
v-else-if="question.question_type === 4"
:config="question.config"
:answer="question.answer"
:stem="question.stem"
:answerSn="questionsData.answer.sn"
:answerSurveySn="questionsData.answer.survey_sn"
:question="question"
@previous="previous"
@next="next"
@change-answer="onRelation($event, question)"
/>
<!-- &lt;!&ndash; 打分题 &ndash;&gt;-->
<!-- <q-rate-->
<!-- v-else-if="question.question_type === 5"-->
@@ -137,18 +191,41 @@
<!-- isMobile-->
<!-- />-->
<!-- 矩阵填空题 -->
<preview-matrix-text v-else-if="question.question_type === 8" v-model:answer="question.answer"
:list="question.list" :config="question.config" :stem="question.stem" :question="question"
@previous="previous" @next="next" @change-answer="onRelation($event, question)" />
<preview-matrix-text
v-else-if="question.question_type === 8"
v-model:answer="question.answer"
:list="question.list"
:config="question.config"
:stem="question.stem"
:question="question"
@previous="previous"
@next="next"
@change-answer="onRelation($event, question)"
/>
<!-- 矩阵单选题 -->
<preview-matrix-radio v-else-if="question.question_type === 9" v-model:answer="question.answer"
:list="question.list" :config="question.config" :stem="question.stem" :answerSn="questionsData.answer.sn"
:answerSurveySn="questionsData.answer.survey_sn" :question="question"
@change-answer="onRelation($event, question)" @previous="previous" @next="next" />
<preview-matrix-radio
v-else-if="question.question_type === 9"
v-model:answer="question.answer"
:list="question.list"
:config="question.config"
:stem="question.stem"
:answerSn="questionsData.answer.sn"
:answerSurveySn="questionsData.answer.survey_sn"
:question="question"
@change-answer="onRelation($event, question)"
@previous="previous"
@next="next"
/>
<!-- 矩阵多选题 -->
<preview-matrix-checkbox v-else-if="question.question_type === 10" v-model:answer="question.answer"
:list="question.list" :config="question.config" :question="question" isMobile
@change-answer="onRelation($event, question)" />
<preview-matrix-checkbox
v-else-if="question.question_type === 10"
v-model:answer="question.answer"
:list="question.list"
:config="question.config"
:question="question"
isMobile
@change-answer="onRelation($event, question)"
/>
<!-- &lt;!&ndash; 矩阵打分题 &ndash;&gt;-->
<!-- <matrix-rate-->
<!-- v-else-if="question.question_type === 11"-->
@@ -216,8 +293,14 @@
<!-- isMobile-->
<!-- />-->
<!-- 文件上传题 -->
<preview-file-upload v-else-if="question.question_type === 18" v-model:answer="question.answer"
:config="question.config" :question="question" isMobile @change-answer="onRelation($event, question)" />
<preview-file-upload
v-else-if="question.question_type === 18"
v-model:answer="question.answer"
:config="question.config"
:question="question"
isMobile
@change-answer="onRelation($event, question)"
/>
<!-- &lt;!&ndash; 地理位置题 &ndash;&gt;-->
<!-- <q-map-->
<!-- v-else-if="question.question_type === 19"-->
@@ -376,26 +459,61 @@
<!-- :question="question"-->
<!-- />-->
<!-- &lt;!&ndash; 高级题型-NPS &ndash;&gt;-->
<preview-n-p-s v-else-if="question.question_type === 106" v-model:answer="question.answer" :isPreview="true"
:title="question.title" :stem="question.stem" :list="question.list" :config="question.config"
:isAnswer="isAnswer" :questionIndex="question.question_index" :label="question.title" :loading="loading"
:isTemplate="isTemplate" :showTitle="styleInfo.is_question_number" :question="question" @previous="previous"
@next="next" @change-answer="onRelation($event, question)" />
<preview-n-p-s
v-else-if="question.question_type === 106"
v-model:answer="question.answer"
:isPreview="true"
:title="question.title"
:stem="question.stem"
:list="question.list"
:config="question.config"
:isAnswer="isAnswer"
:questionIndex="question.question_index"
:label="question.title"
:loading="loading"
:isTemplate="isTemplate"
:showTitle="styleInfo.is_question_number"
:question="question"
@previous="previous"
@next="next"
@change-answer="onRelation($event, question)"
/>
</question>
<!-- 分页 -->
<div v-show="showPage" class="footer-page">
<pfe-pagination class="pagination" :page="page" :pages="pages.length + 1" :min="styleInfo.is_home ? 0 : 1"
:loading="loading" :showPrevious="styleInfo.is_up_button" :showStart="styleInfo.is_start_button"
:startText="styleInfo.start_button_text" :showSubmit="styleInfo.is_submit_button" :submitText="localPageTimer.is_show && localPageTimer.short_time
<pfe-pagination
class="pagination"
:page="page"
:pages="pages.length + 1"
:min="styleInfo.is_home ? 0 : 1"
:loading="loading"
:showPrevious="styleInfo.is_up_button"
:showStart="styleInfo.is_start_button"
:startText="styleInfo.start_button_text"
:showSubmit="styleInfo.is_submit_button"
:submitText="
localPageTimer.is_show && localPageTimer.short_time
? `${localPageTimer.short_time}S`
: styleInfo.submit_button_text
" :buttonTextColor="styleInfo.button_text_color" :buttonColor="styleInfo.button_color" :nextText="localPageTimer.is_show && localPageTimer.short_time
"
:buttonTextColor="styleInfo.button_text_color"
:buttonColor="styleInfo.button_color"
:nextText="
localPageTimer.is_show && localPageTimer.short_time
? `${localPageTimer.short_time}S`
: ''
" :nextDisabled="localPageTimer.short_time" isMobile @previous="previous" @next="next" />
"
:nextDisabled="localPageTimer.short_time"
isMobile
@previous="previous"
@next="next"
/>
</div>
<LangTranslate v-if="isAnswer && styleInfo.is_yip" translate-key="PoweredByDigitalTechnologyCenterYIP"
class="footer" />
<LangTranslate
v-if="isAnswer && styleInfo.is_yip"
translate-key="PoweredByDigitalTechnologyCenterYIP"
class="footer"
/>
</div>
</div>
</template>
@@ -574,9 +692,9 @@ async function answer (callback, callbackBeforePage) {
question.error = translatedText.value.ThisIsARequiredQuestion;
}
} else if (
answer &&
questionType === 1 &&
Object.keys(answer).findIndex((value) => !answer[value]) !== -1
answer
&& questionType === 1
&& Object.keys(answer).findIndex((value) => !answer[value]) !== -1
) {
// 单选题
isError = true;
@@ -804,8 +922,8 @@ async function answer (callback, callbackBeforePage) {
const value = answer[key];
switch (config.text_type) {
case 3: // 字母
isError =
config.include_mark === 1
isError
= config.include_mark === 1
? !/^[a-zA-Z·~@#¥%……&*()——\-+={}|《》?:“”【】、;‘’,。、`~!@#$%^&*()_\-+=<>?:"{}|,./;'\\[\]]+$/.test(
newValue
) || !newValue.length
@@ -813,8 +931,8 @@ async function answer (callback, callbackBeforePage) {
question.error = isError ? translatedText.value.PleaseEnterEnglishLetters : '';
break;
case 4: // 中文
isError =
config.include_mark === 1
isError
= config.include_mark === 1
? !/^(?:[\u3400-\u4DB5\u4E00-\u9FEA\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]|[\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|[·~@#¥%……&*()——\-+={}|《》?:“”【】、;‘’,。、`~!@#$%^&*()_\-+=<>?:"{}|,./;'\\[\]])+$/.test(
newValue
) || !newValue.length
@@ -824,8 +942,8 @@ async function answer (callback, callbackBeforePage) {
question.error = isError ? translatedText.value.PleaseEnterChineseWords : '';
break;
case 5: // 邮箱
isError =
!/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(
isError
= !/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(
value
);
question.error = isError ? translatedText.value.PleaseEnterACorrectEmail : '';
@@ -835,8 +953,8 @@ async function answer (callback, callbackBeforePage) {
question.error = isError ? translatedText.value.PleaseEnterACorrectPhone : '';
break;
case 7: // 身份证号
isError =
!/^[1-9]\d{5}(?:18|19|20)\d{2}(?:0[1-9]|10|11|12)(?:0[1-9]|[1-2]\d|30|31)\d{3}[\dXx]$/.test(
isError
= !/^[1-9]\d{5}(?:18|19|20)\d{2}(?:0[1-9]|10|11|12)(?:0[1-9]|[1-2]\d|30|31)\d{3}[\dXx]$/.test(
value
);
question.error = isError ? translatedText.value.PleaseEnterACorrectID : '';
@@ -848,61 +966,7 @@ async function answer (callback, callbackBeforePage) {
isError = true;
question.error = translatedText.value.PleaseEnterMoreThanOneCharacters(config.min);
}
} else if (answer && questionType === 8) {
// 矩阵填空题
question.error = '';
Object.keys(answer).forEach((key) => {
const value = answer[key];
switch (config.text_type) {
case 3: // 字母
if (
!/^[a-zA-Z·~@#¥%……&*()——\-+={}|《》?:“”【】、;‘’,。、`~!@#$%^&*()_\-+=<>?:"{}|,./;'\\[\]]+$/.test(
value
)
) {
question.error = translatedText.value.PleaseEnterEnglishLetters;
}
break;
case 4: // 中文
if (
!/^(?:[\u3400-\u4DB5\u4E00-\u9FEA\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]|[\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|[·~@#¥%……&*()——\-+={}|《》?:“”【】、;‘’,。、`~!@#$%^&*()_\-+=<>?:"{}|,./;'\\[\]])+$/.test(
value
)
) {
question.error = translatedText.value.PleaseEnterChineseWords;
}
break;
case 5: // 邮箱
if (
!/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(
value
)
) {
question.error = translatedText.value.PleaseEnterACorrectEmail;
}
break;
case 6: // 手机号
if (!/^(?:(?:\+|00)86)?1[3-9]\d{9}$/.test(value)) {
question.error = translatedText.value.PleaseEnterACorrectPhone;
}
break;
case 7: // 身份证号
if (
!/^[1-9]\d{5}(?:18|19|20)\d{2}(?:0[1-9]|10|11|12)(?:0[1-9]|[1-2]\d|30|31)\d{3}[\dXx]$/.test(
value
)
) {
question.error = translatedText.value.PleaseEnterACorrectID;
}
break;
default:
break;
}
if (!question.error && value.length < config.min && ![1, 2].includes(config.text_type)) {
question.error = translatedText.value.PleaseEnterMoreThanOneCharacters(config.min);
}
});
if (question.error) isError = true;
} else if (questionType === 27 && question.error) {
// 多项填空题
isError = true;

View File

@@ -224,7 +224,7 @@ function shareLink() {
scene: 0 // 朋友圈1 微信好友0
};
console.log('shareUrl', publishInfo.value.url);
appBridge.shareToWeChat(params, () => {});
appBridge.shareToWeChat(params);
}
// 下载二维码