feat(survey): 问卷列表页面添加搜索功能

- 在问卷列表页面添加搜索框
- 优化页面布局,调整搜索框位置- 更新样式,确保搜索框与页面其他元素协调
This commit is contained in:
陈昱达
2025-03-18 11:34:42 +08:00
parent b91850c508
commit 1f0ffa679b
34 changed files with 371 additions and 355 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,7 @@
--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));
}
/* semantic color variables for this project */

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

@@ -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,7 @@
<template>
<div class="survey-search">
<van-search class="theme-background" :border="false" background="#71b73c"></van-search>
</div>
<div class="new-survey-container container">
<van-list
v-model:loading="loading"
@@ -110,7 +113,7 @@ const onLoad = () => {
fetchSurveys();
}, 500);
};
const fetchSurveys = async () => {
const fetchSurveys = async() => {
const params = {
page: form.value.page,
per_page: form.value.pageSize,
@@ -147,7 +150,7 @@ const deleteItem = (item) => {
showCancelButton: true,
confirmButtonColor: '#03B03C'
})
.then(async () => {
.then(async() => {
const res = await deleteSurveys(item.sn);
if (res.data.message) {
showToast(res.data.message);
@@ -171,7 +174,7 @@ const copyItem = (item) => {
showCancelButton: true,
confirmButtonColor: '#03B03C'
})
.then(async () => {
.then(async() => {
const res = await copySurveys(item.sn);
if (res.data.code === 200 || res.data.code === 201) {
showSuccessToast('复制成功');
@@ -212,7 +215,7 @@ const editItem = (item) => {
});
};
// 保存为模板
const saveTemplate = async (item) => {
const saveTemplate = async(item) => {
const data = JSON.parse(JSON.stringify(item));
const res = await saveTemplates(item.sn, data);
if (res.data.code === 200 || res.data.code === 201) {
@@ -245,8 +248,17 @@ 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);
//min-height: calc(100vh - 100px);
padding: 1px;
//background: linear-gradient(to bottom, $theme-color 200px, #f2f2f2 300px);
@@ -259,8 +271,9 @@ onMounted(() => {
.survey_item_info {
.survey_item_info_status {
margin-bottom: 15px;
display: flex;
margin-bottom: 15px;
img {
height: 12px;
margin-right: 3px;

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
);

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>