Merge branch 'feature/feature-20250331-h5' of https://e.coding.yili.com/yldc/ylst/ylst-survey-h5 into feature/feature-20250331-h5

This commit is contained in:
liu.huiying@ebiz-digits.com
2025-03-18 15:36:33 +08:00
40 changed files with 610 additions and 415 deletions

3
components.d.ts vendored
View File

@@ -2,7 +2,7 @@
// @ts-nocheck
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399
export {};
export {}
/* prettier-ignore */
declare module 'vue' {
@@ -39,6 +39,7 @@ declare module 'vue' {
VanRadio: typeof import('vant/es')['Radio']
VanRadioGroup: typeof import('vant/es')['RadioGroup']
VanRow: typeof import('vant/es')['Row']
VanSearch: typeof import('vant/es')['Search']
VanStepper: typeof import('vant/es')['Stepper']
VanSwitch: typeof import('vant/es')['Switch']
VanTab: typeof import('vant/es')['Tab']

View File

@@ -4,7 +4,7 @@ import { onMounted } from 'vue';
import appBridge from '@/assets/js/appBridge';
import utils from '@/assets/js/common';
onMounted(async () => {
onMounted(async() => {
if (utils.getParameter('digitalYiliToken')) {
// 隐藏/显示 header
appBridge.setHeaderShown(false);

View File

@@ -85,9 +85,9 @@ export default class CommonApi {
};
/* eslint-disable no-useless-escape */
const reg = /\\|\/|\?|\|\*|"|“|”|'|||<|>|{|}|\[|\]|\【|\】||:|、|\^|\$|!|~|`|\s|\+/g;
name =
name ||
getRandomFileName(file?.name?.replace(reg, '') ?? '' ?? `${new Date().getTime()}.png`);
name
= name
|| getRandomFileName(file?.name?.replace(reg, '') ?? '' ?? `${new Date().getTime()}.png`);
const res = await CommonApi.getOssInfo();
/* eslint-enable no-useless-escape */

View File

@@ -20,6 +20,8 @@
--van-calendar-range-edge-background: var(--primary-color);
--van-cascader-active-color: var(--primary-color);
--status-bar-height: 20px;
--sticky-top-height: calc(var(--status-bar-height) + calc(var(--van-nav-bar-height) + 13px));
--van-radius-sm: 16px;
}
/* semantic color variables for this project */

View File

@@ -5,7 +5,7 @@
}
.van-cell {
padding: 8px !important;
//padding: 8px !important;
}
.van-divider {

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

@@ -83,14 +83,14 @@ export default defineComponent({
<style scoped lang="scss">
.yl-select-wrapper {
position: relative;
outline-color: transparent;
border-color: transparent;
display: inline-block;
padding: 2px 0;
border-color: transparent;
border-radius: 12px;
background: #fafbfc;
outline-color: transparent;
font-size: 16px; /* 增加字体大小 */
line-height: 1.5; /* 增加行高 */
padding: 2px 0;
background: #fafbfc;
border-radius: 12px;
}
.yl-select-label {

View File

@@ -62,7 +62,7 @@ const functions = {
document.execCommand('italic', false, null);
},
uploadImage: async () => {
uploadImage: async() => {
// 保存当前光标位置
savedRange.value = saveSelection();
@@ -71,7 +71,7 @@ const functions = {
fileInput.click();
fileInput.onchange = async (e) => {
fileInput.onchange = async(e) => {
const [file] = e.target.files;
if (!file) return;
if (file.size > 2 * 1024 * 1024) {

View File

@@ -4,11 +4,11 @@
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
src:
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix')
format('embedded-opentype'),
format('embedded-opentype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont')
format('svg');
format('svg');
}
.logo {

View File

@@ -4,11 +4,11 @@
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
src:
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix')
format('embedded-opentype'),
format('embedded-opentype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont')
format('svg');
format('svg');
}
.logo {

View File

@@ -376,39 +376,39 @@ export function isCross(range1, range2) {
const isSibling = isLeft || isRight;
// 逻辑包含循环
const contain =
(isPlainSequence &&
(((isNullish(start2) || isSequence(judge, start2, start1)) &&
(isNullish(end2) || isSequence(judge, end2, start1))) ||
((isNullish(start2) || isSequence(start1, start2, end1)) &&
(isNullish(end2) || isSequence(start1, end2, end1))))) ||
(!isPlainSequence &&
(judge < start1
? ((isNullish(start2) || isSequence(judge, start2, start1)) &&
(isNullish(end2) || isSequence(judge, end2, start1))) ||
((isNullish(start2) || isSequence(start1, start2, end1)) &&
(isNullish(end2) || isSequence(start1, end2, end1)))
: ((isNullish(start2) || isSequence(start1, start2, judge)) &&
(isNullish(end2) || isSequence(start1, end2, judge))) ||
((isNullish(start2) || isSequence(judge, start2, end1)) &&
(isNullish(end2) || isSequence(judge, end2, end1)))));
const contain
= (isPlainSequence
&& (((isNullish(start2) || isSequence(judge, start2, start1))
&& (isNullish(end2) || isSequence(judge, end2, start1)))
|| ((isNullish(start2) || isSequence(start1, start2, end1))
&& (isNullish(end2) || isSequence(start1, end2, end1)))))
|| (!isPlainSequence
&& (judge < start1
? ((isNullish(start2) || isSequence(judge, start2, start1))
&& (isNullish(end2) || isSequence(judge, end2, start1)))
|| ((isNullish(start2) || isSequence(start1, start2, end1))
&& (isNullish(end2) || isSequence(start1, end2, end1)))
: ((isNullish(start2) || isSequence(start1, start2, judge))
&& (isNullish(end2) || isSequence(start1, end2, judge)))
|| ((isNullish(start2) || isSequence(judge, start2, end1))
&& (isNullish(end2) || isSequence(judge, end2, end1)))));
// 循环存在封闭区间,并且循环包含逻辑
const contained =
!isNullish(start2) &&
!isNullish(end2) &&
const contained
= !isNullish(start2)
&& !isNullish(end2)
// [judge, start1, end1];
((isPlainSequence && start2 <= judge && end1 <= end2) ||
&& ((isPlainSequence && start2 <= judge && end1 <= end2)
// [judge, start1, end1];
// [start1, judge, end1];
(!isPlainSequence && start2 <= start1 && start2 <= judge && end1 <= end2));
|| (!isPlainSequence && start2 <= start1 && start2 <= judge && end1 <= end2));
// 循环不存在封闭区间
const unCircled =
(!isNullish(start2) &&
isNullish(end2) &&
((isPlainSequence && start2 === judge) || (!isPlainSequence && judge < start1)
const unCircled
= (!isNullish(start2)
&& isNullish(end2)
&& ((isPlainSequence && start2 === judge) || (!isPlainSequence && judge < start1)
? start2 === judge
: start2 === start1)) ||
(isNullish(start2) && !isNullish(end2) && end2 === end1);
: start2 === start1))
|| (isNullish(start2) && !isNullish(end2) && end2 === end1);
return !(isSibling || contain || contained || unCircled);
}
@@ -428,8 +428,8 @@ function isSequence(s1, s2, s3, equal) {
* @param store
*/
export function updateNewQuestionsByLoopingEffect(quesSaveParam, store) {
const { questionInfoBeforeModified = {}, questionInfo = {} } =
JSON.parse(JSON.stringify(store.state.common)) || {};
const { questionInfoBeforeModified = {}, questionInfo = {} }
= JSON.parse(JSON.stringify(store.state.common)) || {};
const oldPages = questionInfoBeforeModified.survey.pages;
const newQuestions = questionInfo.questions;

View File

@@ -1,6 +1,5 @@
import { showConfirmDialog } from 'vant';
import { getQuestionList, getCheckSurvey } from '@/api/survey';
import appBridge from '@/assets/js/appBridge';
import { QUESTION_TYPE } from '@/layouts/config3d.constant.js';
import { loopingAvailable } from '@/layouts/logic.js';
import { getDomText } from '@/utils/utils';
@@ -19,8 +18,12 @@ function showModal(options) {
icon: null,
...options
})
.then(() => {})
.catch(() => {});
.then(() => {
// then back
})
.catch(() => {
// error back
});
}
/**
@@ -28,13 +31,13 @@ function showModal(options) {
* @param {*} data
* @returns
*/
const canPlanetPublishPSM = function (data) {
const canPlanetPublishPSM = function(data) {
let isFb = true;
let message = '';
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;
message = 'psm题目未完成设置请设置价格区间后投放';
@@ -58,15 +61,15 @@ const canPlanetPublishPSM = function (data) {
* @param {*} data
* @returns
*/
const canPlanetPublishMxdAndHotArea = function (data) {
const canPlanetPublishMxdAndHotArea = function(data) {
let isFb = true;
let message = '';
const qSteams = [];
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;
message = 'maxdiff题目未完成设置请生成设计后投放';
@@ -105,14 +108,14 @@ const canPlanetPublishMxdAndHotArea = function (data) {
* @param {*} data
* @returns
*/
const canPlanetPublish3D = function (data) {
const canPlanetPublish3D = function(data) {
{
let canFB = true;
let message = '';
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) {
@@ -142,15 +145,15 @@ const canPlanetPublish3D = function (data) {
let message = '';
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) => {
@@ -200,14 +203,14 @@ const canPlanetPublish3D = function (data) {
* @param {*} data
* @returns
*/
const canPlanetPublishImage = function (data) {
const canPlanetPublishImage = function(data) {
{
let canFB = true;
let message = '';
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)) {
@@ -302,8 +305,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}"`
});
}
});
@@ -382,11 +385,11 @@ function isLoopingLogicValid(data, publishType) {
if (
(data?.cycle_pages || []).every((i) => {
return (
i.question_index &&
i.relation_type !== undefined &&
i.relation_type !== null &&
i.first_page &&
i.last_page
i.question_index
&& i.relation_type !== undefined
&& i.relation_type !== null
&& i.first_page
&& i.last_page
);
})
) {
@@ -410,7 +413,7 @@ function isLoopingLogicValid(data, publishType) {
* @param sn
* @param publishType undefined投放null投放0投放1预览2投放3测试
*/
export const canPlanetPublish = async function (sn, publishType) {
export const canPlanetPublish = async function(sn, publishType) {
const parsedPublishType = !publishType ? 2 : publishType;
const num = window.location.href.indexOf('code=');
let code;

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

@@ -39,10 +39,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

@@ -45,10 +45,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

@@ -52,8 +52,8 @@
<martrix-question
v-if="
element.question_type === 8 ||
element.question_type === 9 ||
element.question_type === 10
element.question_type === 9 ||
element.question_type === 10
"
:element="computedElement(element)"
:index="index"

View File

@@ -1,12 +1,13 @@
<template>
<div class="option-action">
<draggable
v-model:data="data"
:data="element"
item-key="option_index"
:handle="handle"
chosenClass="chosen"
animation="300"
:scroll="true"
@update:data="updateData"
>
<!-- eslint-disable-next-line -->
<template #item="{ element, index }">
@@ -83,7 +84,7 @@ import CheckboxAction from './components/OptionItemAction/CheckboxAction.vue';
import { ref } from 'vue';
import { showConfirmDialog } from 'vant';
import Draggable from '@/views/Design/components/Draggable.vue';
const props = defineProps({
defineProps({
active: {
type: Boolean,
default: false
@@ -100,7 +101,7 @@ const props = defineProps({
}
});
const data = defineModel('data', {
const element = defineModel('data', {
type: Array,
default: () => []
});
@@ -113,7 +114,10 @@ const show = ref(false);
const moveShow = ref(false);
const activeOption = ref({});
const activeIndex = ref(-1);
const element = ref(props.data);
const updateData = (newValue) => {
element.value = newValue;
};
// emit('update:data');
/**
@@ -134,23 +138,23 @@ const openOptionActionModel = (item, index) => {
// 上下移动
const optionMove = (action) => {
switch (action.action) {
case 'up':
if (activeIndex.value === 0) {
moveShow.value = false;
return false;
}
// 向上移动
element.value.splice(activeIndex.value - 1, 0, element.value.splice(activeIndex.value, 1)[0]);
activeIndex.value -= 1;
break;
case 'down':
if (activeIndex.value === element.value.length - 1) {
moveShow.value = false;
return false;
}
element.value.splice(activeIndex.value + 1, 0, element.value.splice(activeIndex.value, 1)[0]);
activeIndex.value += 1;
break;
case 'up':
if (activeIndex.value === 0) {
moveShow.value = false;
return false;
}
// 向上移动
element.value.splice(activeIndex.value - 1, 0, element.value.splice(activeIndex.value, 1)[0]);
activeIndex.value -= 1;
break;
case 'down':
if (activeIndex.value === element.value.length - 1) {
moveShow.value = false;
return false;
}
element.value.splice(activeIndex.value + 1, 0, element.value.splice(activeIndex.value, 1)[0]);
activeIndex.value += 1;
break;
}
};

View File

@@ -268,8 +268,8 @@ const getSkipTypeText = (skipType) => {
const ls = [];
logics.map((item) => {
if (
item.skip_type === skipType &&
item.question_index === activeQuestion.value.question_index
item.skip_type === skipType
&& item.question_index === activeQuestion.value.question_index
) {
ls.push(item);
}
@@ -285,13 +285,13 @@ const getSkipTypeText = (skipType) => {
const questionSetting = (type) => {
switch (type) {
case 'before':
questionBeforeShow.value = true;
case 'before':
questionBeforeShow.value = true;
break;
case 'after':
questionBeforeShow.value = true;
break;
break;
case 'after':
questionBeforeShow.value = true;
break;
}
skipType.value = type === 'before' ? 1 : 0;
};

View File

@@ -235,7 +235,7 @@ const textTypeList = [
const emit = defineEmits(['update:modelValue', 'saveOption']);
//
const selectText = (textType) => {
let item = textTypeList.filter((item) => item.value === textType)[0];
const item = textTypeList.filter((item) => item.value === textType)[0];
return item ? item.text : '';
};
const confirm = ({ selectedValues }) => {

View File

@@ -144,8 +144,8 @@
<BeforeRate
v-if="
log.logic !== 'always' &&
log.is_answer !== 0 &&
[5, 106].includes(log.question_type)
log.is_answer !== 0 &&
[5, 106].includes(log.question_type)
"
:activeQuestion="activeQuestion"
:logic="log"

View File

@@ -108,9 +108,9 @@ function isSurplus() {
return false;
} else {
return (
parseFloat(((localConfig.value.max - localConfig.value.min) * 1000).toFixed(4, 10)) %
parseFloat((localConfig.value.score_interval * 1000).toFixed(4, 10)) ===
0
parseFloat(((localConfig.value.max - localConfig.value.min) * 1000).toFixed(4, 10))
% parseFloat((localConfig.value.score_interval * 1000).toFixed(4, 10))
=== 0
);
}
}

View File

@@ -12,93 +12,90 @@
</div>
</template>
<script>
<script setup>
import Sortable from 'sortablejs';
import { onMounted, reactive, ref } from 'vue';
import { onMounted, ref } from 'vue';
export default {
name: 'Draggable',
props: {
data: {
type: Array,
default: () => []
},
itemKey: {
type: String,
default: ''
},
handle: {
type: String,
default: ''
},
filter: {
type: String,
default: ''
},
chosenClass: {
type: String,
default: ''
},
animation: {
type: [String, Number],
default: 0
},
scroll: {
type: Boolean,
default: true
},
group: {
type: String,
default: ''
},
move: {
type: Function,
default: () => {
// 后续扩展
}
}
const props = defineProps({
itemKey: {
type: String,
default: ''
},
emits: ['update:data', 'end'],
setup(props, context) {
const sortable = ref(null);
const draggable = ref(null);
const copyData = reactive([]);
const options = {
handle: props.handle,
filter: props.filter,
chosenClass: props.chosenClass,
animation: props.animation,
scroll: props.scroll,
scrollSensitivity: 100,
forceFallback: true,
scrollSpeed: 30,
group: props.group,
onMove: (evt) => {
const index = evt.related.getAttribute('data_index');
evt.newIndex = Number(index);
return props.move(evt);
},
// 拖动结束
onEnd: (evt) => {
evt.stopPropagation();
const tempData = JSON.parse(JSON.stringify(props.data));
const oldEle = tempData[evt.oldIndex];
tempData.splice(evt.oldIndex, 1);
tempData.splice(evt.newIndex, 0, oldEle);
context.emit('update:data', tempData);
context.emit('end', evt);
}
};
onMounted(() => {
if (sortable.value) sortable.value.destory();
sortable.value = Sortable.create(draggable.value, options);
});
return {
copyData,
draggable
};
handle: {
type: String,
default: ''
},
filter: {
type: String,
default: ''
},
chosenClass: {
type: String,
default: ''
},
animation: {
type: [String, Number],
default: 0
},
scroll: {
type: Boolean,
default: true
},
group: {
type: String,
default: ''
},
move: {
type: Function,
default: () => {
// 后续扩展
}
}
});
const data = defineModel('data', {
type: Array,
default: () => []
});
const emit = defineEmits(['update:data', 'end']);
const sortable = ref(null);
const draggable = ref(null);
// const copyData = reactive([]);
const options = {
handle: props.handle,
filter: props.filter,
chosenClass: props.chosenClass,
animation: props.animation,
scroll: props.scroll,
scrollSensitivity: 100,
forceFallback: true,
scrollSpeed: 30,
group: props.group,
onMove: (evt) => {
const index = evt.related.getAttribute('data_index');
evt.newIndex = Number(index);
return props.move(evt);
},
// 拖动结束
onEnd: (evt) => {
evt.stopPropagation();
const tempData = JSON.parse(JSON.stringify(data.value));
const oldEle = tempData[evt.oldIndex];
data.value.splice(evt.oldIndex, 1);
data.value.splice(evt.newIndex, 0, oldEle);
// data.value = tempData;
// emit('update:data', tempData);
emit('end', evt);
}
};
onMounted(() => {
if (sortable.value) sortable.value.destroy();
sortable.value = Sortable.create(draggable.value, options);
});
</script>
<style lang="scss" scoped></style>

View File

@@ -102,7 +102,7 @@
</template>
<script setup>
import OptionAction from '@/views/Design/components/ActionCompoents/OptionAction.vue';
import { defineAsyncComponent, toRefs, ref } from 'vue';
import { defineAsyncComponent, ref } from 'vue';
// 是否是预览
const isPreview = defineModel('isPreview', { default: false, type: Boolean });
@@ -111,15 +111,7 @@ const choiceValue = defineModel('answer', { default: '1', type: String });
// console.log(`choiceValue.value`, choiceValue.value);
const Contenteditable = defineAsyncComponent(() => import('@/components/contenteditable.vue'));
const props = defineProps({
element: {
type: Object,
default: () => {
return {
stem: ''
};
}
},
defineProps({
active: {
type: Boolean,
default: false
@@ -129,7 +121,14 @@ const props = defineProps({
default: 0
}
});
const { element } = toRefs(props);
const element = defineModel('element', {
type: Object,
default: () => {
return {
stem: ''
};
}
});
const value = ref([]);
const emit = defineEmits(['update:element']);
const emitValue = () => {

View File

@@ -8,12 +8,12 @@ const question = defineModel<question>('element', { default: () => ({}), require
// eslint-disable-next-line
const activeComponent = computed<Component>(() => {
switch (question.value.question_type) {
case 8:
return MatrixText;
case 9:
return MatrixRadio;
case 10:
return MatrixCheckbox;
case 8:
return MatrixText;
case 9:
return MatrixRadio;
case 10:
return MatrixCheckbox;
}
});

View File

@@ -30,7 +30,6 @@
<p>{{ element.config.prompt_right }}</p>
</div>
<RateCharacter
v-model="answerValue"
:config="element.config"
:index="optionIndex"
@change="handleRateChange"
@@ -47,7 +46,7 @@ import { ref } from 'vue';
import RateCharacter from './RateCharacter.vue';
const isPreview = defineModel('isPreview', { default: false, type: Boolean });
const props = defineProps({
/*const props = */ defineProps({
index: {
type: Number,
default: 0
@@ -60,11 +59,10 @@ const props = defineProps({
questionType: { type: [String, Number], default: 4 }
});
// answer 的答案以 矩阵形式存储, 例如 [4,7],上层更新答案的时候也容易
const rates = defineModel('rates', { default: [], type: Array });
const rate = ref(0);
const answerValue = ref();
/**
* element === question
* @type {ModelRef<Object, string, Object, Object>}
*/
const element = defineModel('element', {
type: Object,
default: () => {
@@ -72,29 +70,13 @@ const element = defineModel('element', {
}
});
// 不知道的 BUG ,开始的时候不能重置颜色。 故如此
setTimeout(() => {
rate.value = localStorage.getItem(props.sn);
// console.log(`rate value:`, rate.value);
// if (rates.value[0] !== undefined) {
// console.log(`rates value:`, rates.value);
// rate.value = rates.value[0]
// }
// else return
}, 1000);
/**
*
* @param index {number} 索引
* @param rate {number} 具体数值
*/
function handleRateChange(index, rate) {
// 如果没有查询到对应索引的数值, 那么就直接push一个直到有数值为止
while (rates.value.length < index) {
rates.value.push(NaN);
}
rates.value[index] = rate;
localStorage.setItem(props.sn, rate.value);
function handleRateChange(/* index, rate */) {
// 占位
}
const chooseId = ref('');

View File

@@ -16,6 +16,7 @@
<script setup>
import { ref, watch } from 'vue';
import { value as model } from '@/views/Design/components/Questions/hooks/useNPSHooks';
const rateItem = ref([
{
@@ -52,10 +53,6 @@ const props = defineProps({
}
});
const model = defineModel('model', {
type: Number
});
const index = defineModel('index', {
type: Number
});
@@ -74,12 +71,14 @@ const renderScore = (min, max, interval) => {
}
rateItem.value = result;
};
// 重置颜色
function getItem(value) {
model.value = value.label;
// console.log(value.label);
rateItem.value.forEach((item, index) => {
rateItem.value[index].active = item.label <= value.label;
});
model.value = value.label;
}
watch(

View File

@@ -0,0 +1,3 @@
import { ref } from 'vue';
export const value = ref<number>(-1);

View File

@@ -11,8 +11,7 @@
class="iconfont active-icon"
:style="{ marginRight: isLastPage ? '0' : '16px' }"
@click="activePage"
>&#xe86c;</i
>
>&#xe86c;</i>
<template v-if="!isLastPage">
<i class="iconfont moverQues" style="margin-right: 16px">&#xe71b;</i>
<i class="iconfont" @click="deleteHandle">&#xe6c5;</i>

View File

@@ -9,7 +9,7 @@ import { showFailToast } from 'vant';
const contentShow = ref(false);
const show = ref(false);
onMounted(async () => {
onMounted(async() => {
if (utils.getSessionStorage('xToken')) {
const appToken = utils.getSessionStorage('xToken');
getUserInfo(appToken)

View File

@@ -51,7 +51,7 @@ import { getSurveysPage } from '@/api/home/index.js';
const survey = ref({
project_name: ''
});
const fetchSurveys = async () => {
const fetchSurveys = async() => {
const params = {
page: 1,
per_page: 10,
@@ -111,6 +111,7 @@ onMounted(() => {
border-radius: 10px;
background: #fff;
color: #000;
img {
height: 12px;
margin-right: 3px;

View File

@@ -20,7 +20,7 @@ const marketList = ref([]);
const active = ref(null);
const marketInfo = ref([]);
const getTableList = async () => {
const getTableList = async() => {
const res = await getListScene();
if (res.data.code === 0) {
res.data.data.forEach((item) => {
@@ -31,7 +31,7 @@ const getTableList = async () => {
getMarketInfo(marketList.value[0]);
}
};
const getMarketInfo = async (item) => {
const getMarketInfo = async(item) => {
const data = marketList.value.filter((market, index) => item === index)[0];
if (data) {
const params = {

View File

@@ -2,7 +2,7 @@
<div class="">
<div class="mark_container">
<!-- <van-row gutter="20">-->
<div v-for="(item, index) in info" @click="toDetail(item)" :key="index" class="market-item">
<div v-for="(item, index) in info" :key="index" class="market-item" @click="toDetail(item)">
<div class="content">
<div class="title fw-bold fs-14">
<div class="flex align-center">
@@ -70,7 +70,7 @@ const deleteItem = (item) => {
showCancelButton: true,
confirmButtonColor: '#03B03C'
})
.then(async () => {
.then(async() => {
const res = await deleteTemplate(item.sn);
if (res.data.code === 0) {
showSuccessToast('删除成功');

View File

@@ -3,9 +3,7 @@
<div v-for="item in 10" :key="item" class="template">
<img src="https://picsum.photos/131/128" width="110" height="100" alt="" />
<span>报名/签到模板</span>
<span style="color: rgb(127, 127, 127)"
>报名签到 | 引用 {{ item }} | 创建人: {{ '张三' }}</span
>
<span style="color: rgb(127, 127, 127)">报名签到 | 引用 {{ item }} | 创建人: {{ '张三' }}</span>
</div>
</div>
</template>

View File

@@ -1,4 +1,14 @@
<template>
<div class="survey-search">
<van-search
class="theme-background"
:border="false"
background="#71b73c"
v-model="searchValue"
@blur="blurs"
@search="blurs"
></van-search>
</div>
<div class="new-survey-container container">
<van-list
v-model:loading="loading"
@@ -100,9 +110,18 @@ const loading = ref(false);
const finished = ref(false);
const form = ref({
page: 0,
pageSize: 10
pageSize: 10,
project_name: ''
});
const searchValue = ref('');
const blurs = () => {
form.value.page = 1;
form.value.project_name = searchValue.value;
survey.value = [];
fetchSurveys();
};
const onLoad = () => {
// 异步更新数据
setTimeout(() => {
@@ -114,7 +133,8 @@ const fetchSurveys = async () => {
const params = {
page: form.value.page,
per_page: form.value.pageSize,
group_id: 0
group_id: 0,
project_name: searchValue.value
};
const res = await getSurveysPage(params);
if (res.data.code === 0) {
@@ -245,22 +265,32 @@ onMounted(() => {
background-color: #000;
}
.survey-search {
position: sticky;
top: var(--sticky-top-height);
z-index: 1000;
width: 100%;
padding: 0;
background-color: $theme-color;
}
.new-survey-container {
min-height: calc(100vh - 100px);
padding: 1px;
//min-height: calc(100vh - 100px);
//padding: 1px;
//background: linear-gradient(to bottom, $theme-color 200px, #f2f2f2 300px);
.new-survey_item {
margin: 10px;
margin: 0 10px 10px 10px;
padding: 10px 0 8px 7px;
border-radius: 8px;
background-color: white;
.survey_item_info {
.survey_item_info_status {
margin-bottom: 15px;
display: flex;
margin-bottom: 15px;
img {
height: 12px;
margin-right: 3px;
@@ -341,5 +371,9 @@ onMounted(() => {
}
}
}
.new-survey_item + .new-survey_item {
margin: 0 10px 10px 10px;
}
}
</style>

View File

@@ -408,14 +408,14 @@ const questionEvent = (item) => {
options:
item.json.options.length > 0
? item.json.options.map((item) => {
return item.map((it) => {
return {
...it,
// 主键生成
id: uuidv4()
};
});
})
return item.map((it) => {
return {
...it,
// 主键生成
id: uuidv4()
};
});
})
: []
})
);
@@ -548,7 +548,7 @@ const previewQuestion = () => {
router.push({ name: 'preview', query: { ...route.query } });
};
onMounted(async () => {
onMounted(async() => {
await getQuestionDetail();
});
</script>

View File

@@ -680,9 +680,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;
@@ -857,51 +857,51 @@ async function answer(callback, callbackBeforePage) {
const { value } = answer;
const newValue = value.replace(/\n|\r|\r\n/g, '');
switch (config.text_type) {
// 字母
case 3:
isError =
config.include_mark === 1
? !/^[a-zA-Z·~@#¥%……&*()——\-+={}|《》?:“”【】、;‘’,。、`~!@#$%^&*()_\-+=<>?:"{}|,./;'\\[\]]+$/.test(
newValue
) || !newValue.length
: !/^[a-zA-Z]+$/.test(newValue) || !newValue.length;
question.error = isError ? translatedText.value.PleaseEnterEnglishLetters : '';
break;
// 字母
case 3:
isError
= config.include_mark === 1
? !/^[a-zA-Z·~@#¥%……&*()——\-+={}|《》?:“”【】、;‘’,。、`~!@#$%^&*()_\-+=<>?:"{}|,./;'\\[\]]+$/.test(
newValue
) || !newValue.length
: !/^[a-zA-Z]+$/.test(newValue) || !newValue.length;
question.error = isError ? translatedText.value.PleaseEnterEnglishLetters : '';
break;
// 中文
case 4:
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
: !/^(?:[\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;
question.error = isError ? translatedText.value.PleaseEnterChineseWords : '';
break;
case 4:
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
: !/^(?:[\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;
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(
value
);
question.error = isError ? translatedText.value.PleaseEnterACorrectEmail : '';
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(
value
);
question.error = isError ? translatedText.value.PleaseEnterACorrectEmail : '';
break;
// 手机号
case 6:
isError = !/^(?:(?:\+|00)86)?1[3-9]\d{9}$/.test(value);
question.error = isError ? translatedText.value.PleaseEnterACorrectPhone : '';
break;
case 6:
isError = !/^(?:(?:\+|00)86)?1[3-9]\d{9}$/.test(value);
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(
value
);
question.error = isError ? translatedText.value.PleaseEnterACorrectID : '';
break;
default:
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(
value
);
question.error = isError ? translatedText.value.PleaseEnterACorrectID : '';
break;
default:
break;
}
if (!isError && value.length < config.min && ![1, 2].includes(config.text_type)) {
isError = true;
@@ -913,54 +913,54 @@ async function answer(callback, callbackBeforePage) {
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 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 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 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 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;
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);
@@ -1037,14 +1037,14 @@ async function answer(callback, callbackBeforePage) {
currentQuestions.forEach((question, index) => {
if (index >= warnStart && index < warnEnd) {
if (repeat.repeat_type) {
question.warning =
translatedText.value.TheAnswerIsRepeatedMoreThanOneTimesPleaseRevise(
question.warning
= translatedText.value.TheAnswerIsRepeatedMoreThanOneTimesPleaseRevise(
repeat.allow_repeat_num,
repeat.repeat_type
);
} else {
question.error =
translatedText.value.TheAnswerIsRepeatedMoreThanOneTimesPleaseRevise(
question.error
= translatedText.value.TheAnswerIsRepeatedMoreThanOneTimesPleaseRevise(
repeat.allow_repeat_num,
repeat.repeat_type
);
@@ -1208,6 +1208,174 @@ async function answer(callback, callbackBeforePage) {
callback();
}
}
// 关联引用
function onRelation(
// 避免出现参数 undefined 情况
{ options, value, list } = {},
{ question_type: _questionType, question_index: _questionIndex, related, answer } = {}
) {
// 关联
related.forEach((relationItem) => {
let relationOptions = [];
if (_questionType === 9 || _questionType === 10) {
// 矩阵选择
list.forEach((item) => {
if (item.type === relationItem.cite_type) {
relationOptions = [...relationOptions, ...item.options];
}
if (relationItem.relation_type === 1) {
relationOptions = relationOptions.filter((option) =>
_questionType === 9 ? option.value : option.value?.length
);
} else if (relationItem.relation_type === 2) {
relationOptions = relationOptions.filter((option) =>
_questionType === 9 ? !option.value : !option.value?.length
);
}
});
} else if (_questionType === 11) {
// 矩阵打分
list.forEach((item) => {
if (item.type === relationItem.cite_type) {
relationOptions = [...relationOptions, ...item.options];
}
});
} else if (_questionType === 25 || _questionType === 26) {
// 热区题
relationOptions = options.filter((option) => {
if (relationItem.relation_type === 1) {
return option.status === 1;
} else if (relationItem.relation_type === 2) {
return option.status === 2;
} else if (relationItem.relation_type === 3) {
return !option.status;
}
return true;
});
} else if (_questionType === 105) {
// MXD
options.forEach((currentOptions) => {
currentOptions.forEach((option) => {
const index = relationOptions.findIndex(
(relationOption) => relationOption.option_key === option.option_key
);
if (index === -1) {
// 全部项
if (relationItem.relation_type === 0) {
return relationOptions.push(option);
}
// 高相关
if (relationItem.relation_type === 3) {
return option.value === 'b' && relationOptions.push(option);
}
// 不相关
if (relationItem.relation_type === 4) {
return option.value === 'w' && relationOptions.push(option);
}
}
});
});
} else if (relationItem.relation_type === 0) {
// 全部选项
relationOptions = options;
} else {
// 过滤选中/未选中选项
relationOptions = options.filter((option) => {
if (_questionType === 1) {
// 单选
if (relationItem.relation_type === 1) return value === option.option_key;
return value !== option.option_key;
} else if (_questionType === 2) {
// 多选
if (relationItem.relation_type === 1) return value.includes(option.option_key);
return !value.includes(option.option_key);
}
return true;
});
}
// 找到关联题
const question = questionsData.value.questions.find(
(question) => question.question_index === relationItem.relation_question_index
);
// 深拷贝关联选项
const copyRelationOptions = JSON.parse(JSON.stringify(relationOptions));
// 更新关联选项key
copyRelationOptions.forEach((option) => {
if (option.option_key[0] !== 'Q') {
let letter = 'A';
// 矩阵题行、列
if (_questionType >= 9 && _questionType <= 11) {
letter = relationItem.cite_type === 1 ? 'R' : 'C';
}
option.option_key = `Q${_questionIndex}${letter}${option.option_key}`;
}
// 其他项特殊处理
if (option.is_other && option.value) {
option.is_other = 0;
option.option = option.value;
}
delete option.value;
delete option.status;
});
// 更新关联题列表
const relatedList = question.list.find(
(relatedListItem) => relatedListItem.relation_question_index === _questionIndex
);
relatedList.options = answer ? copyRelationOptions : [];
});
}
function jumpImmediately() {
const code = questionsData.value.action?.code;
if (page.value !== pages.value.length + 1 && ![20004, 20011, 20016].includes(code)) {
return;
}
const survey = questionsData.value.survey;
let countTime = 0;
let url = '';
if (code === 20004 && survey.screening_end_url_select && survey.screening_end_url) {
countTime = survey.screening_standing_time;
url = survey.screening_end_url;
}
if (code === 20011 && survey.success_end_url_select && survey.success_end_url) {
countTime = survey.success_standing_time;
url = survey.success_end_url;
}
if (code === 20016 && survey.quota_end_url_select && survey.quota_end_url) {
countTime = survey.quota_standing_time;
url = survey.quota_end_url;
}
// 跳转链接
if (countTime <= 0 && url) {
questionsData.value.action.code = -1 * code; // 防止 AnswerMob AnswerPc 组件里显示最后一页
url = url.replaceAll('#sn#', questionsData.value.answer.sn);
url = url.replaceAll('#user#', questionsData.value.answer.respondent);
url = url.replaceAll('#survey_sn#', questionsData.value.answer.survey_sn);
if (proxy.$route.query.source === 'YILI_APP_WANGYI') {
Object.keys(proxy.$route.query).forEach((key) => {
if (!['sn', 'source', 'is_template', 'channelUCode'].includes(key)) {
url += `${url.indexOf('?') === -1 ? '?' : '&'}${key}=${proxy.$route.query[key]}`;
}
});
}
// 判断是否小程序路径
if (url[0] === '/') {
// 判断是否在小程序环境
wx.miniProgram.getEnv(() => {
wx.miniProgram.redirectTo({ url });
});
} else {
if (url.indexOf('http://') === -1 && url.indexOf('https://') === -1) {
url = `http://${url}`;
}
open(url, '_self');
}
}
}
</script>
<style lang="scss" scoped>
::v-deep .van-cell::after {
@@ -1268,6 +1436,8 @@ async function answer(callback, callbackBeforePage) {
}
.preview-info-header-desc {
color: white;
@include preview-info-header;
font-size: 12px;

View File

@@ -1,43 +1,45 @@
<template>
<n-p-s v-model:element="question" v-model:rates="rates" :active="false" :isPreview="true" />
<n-p-s v-model:element="question" v-model:value="value" :active="false" :isPreview="true" />
</template>
<script setup lang="ts">
import NPS from '@/views/Design/components/Questions/NPS.vue';
import { ref, watch } from 'vue';
import { watch } from 'vue';
import { value } from '@/views/Design/components/Questions/hooks/useNPSHooks';
const question = defineModel<question>('question', { default: { config: { is_required: false } } });
const answer = defineModel<{ [key: string]: number }>('answer', { default: undefined });
// rates 数值取决与 answer 没有数据重新建立一个对应长度的数组
const rates = ref(answer.value ? getRates() : new Array(question.value.list[0].options!.length));
// // 预览新增 emit ['changeAnswer', 'previous', 'next']
const emit = defineEmits(['changeAnswer', 'previous', 'next', 'update:element']);
// 获取 rates
function getRates() {
const keys = Object.keys(answer.value);
return keys.map((item) => {
return answer.value[item];
});
const question = defineModel<question>('question', { default: { config: { is_required: false } } });
/**
* answer 的答案类型
* {
* "1": 10
* }
*/
const answer = defineModel<NPSAnswerType>('answer', { default: undefined });
// 解析答案
// function parseAnswer() {
// return answer.value[`1`];
// }
/**
* 生成NPS答案
*/
function genAnswer(value: number): NPSAnswerType {
const res: any = {};
res[`1`] = value;
return res;
}
// console.log(answer.value && getRates());
watch(
rates,
() => {
const res = {};
rates.value.map((item, index) => {
// index 是 key, item 是 value
res[index + 1] = item;
});
answer.value = res;
emit('changeAnswer', res);
},
{
deep: true
}
);
watch(value, (newValue) => {
// console.log(genAnswer(newValue as number));
answer.value = genAnswer(newValue as number);
// 提交答案
emit('changeAnswer', answer.value);
});
</script>
<style scoped></style>

View File

@@ -0,0 +1 @@
type NPSAnswerType = { [key: string]: number };

View File

@@ -94,17 +94,17 @@ type OperateItem = (typeof operateList)[0];
const operateBtn = (item: OperateItem) => {
switch (item.type) {
case 'shareLink':
shareLink();
break;
case 'copyLink':
copyLink();
break;
case 'qrCode':
downLoadImg();
break;
default:
break;
case 'shareLink':
shareLink();
break;
case 'copyLink':
copyLink();
break;
case 'qrCode':
downLoadImg();
break;
default:
break;
}
};
// 复制链接
@@ -192,7 +192,7 @@ watch(status, (val) => {
getCode();
}
});
onMounted(async () => {
onMounted(async() => {
fetchInfo();
});
</script>
@@ -224,10 +224,10 @@ onMounted(async () => {
flex-direction: column;
justify-content: center;
margin: 0 10px;
color: #000;
font-weight: 600;
font-size: 14px;
line-height: 20px;
color: #000;
}
}

View File

@@ -6,8 +6,8 @@
</template>
<script setup>
const successImg =
'https://files.axshare.com/gsc/DR6075/c7/5a/53/c75a534148d349f1bb8e185629f784ac/images/%E9%A2%84%E8%A7%88/u123.png?pageId=18fb9d8a-b9b7-465f-9bd7-625b1b78f72e';
const successImg
= 'https://files.axshare.com/gsc/DR6075/c7/5a/53/c75a534148d349f1bb8e185629f784ac/images/%E9%A2%84%E8%A7%88/u123.png?pageId=18fb9d8a-b9b7-465f-9bd7-625b1b78f72e';
</script>
<style lang="scss" scoped>