Merge branch 'feature/feature-20250331-h5' into uat

This commit is contained in:
陈昱达
2025-03-14 19:30:11 +08:00
35 changed files with 1189 additions and 639 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

@@ -30,6 +30,7 @@
"vconsole": "^3.15.1",
"vite-plugin-vue": "^0.0.1",
"vue": "^3.4.29",
"vue-icons-plus": "^0.1.8",
"vue-router": "^4.3.3",
"vuex": "^4.1.0"
},

View File

@@ -7,7 +7,7 @@ import utils from '@/assets/js/common';
onMounted(async() => {
if (utils.getSessionStorage('xToken')) {
// 隐藏/显示 header
appBridge.setHeaderShown(true);
appBridge.setHeaderShown(false);
// 设置系统状态栏明暗主题
appBridge.setStatusBarStyle('light');
}

View File

@@ -1,5 +1,6 @@
/* color palette from <https://github.com/vuejs/theme> */
:root {
--primary-color : rgb(111,185, 55);
--vt-c-white: #fff;
--vt-c-white-soft: #f8f8f8;
--vt-c-white-mute: #f2f2f2;

View File

@@ -12,11 +12,21 @@ a,
transition: 0.4s;
}
.theme-color {
color: $theme-color;
}
.theme-background {
background: $theme-color;
}
.ml10 {
margin-left: 10px;
}
.container {
// 容器的高度 减少底部之后的高度
//height: calc(100vh - 100px);
//width: 100%;
// 绿色 #70B937 白色过渡渐变 竖向 上一半部分 渐变到白色就可以
background: linear-gradient(to bottom, $theme-color 200px, #f2f2f2 300px);

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

@@ -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');
src:
url('//at.alicdn.com/t/c/font_4841764_vat2jbvw3q.woff2?t=1741575060989') format('woff2'),
url('//at.alicdn.com/t/c/font_4841764_vat2jbvw3q.woff?t=1741575060989') format('woff'),

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

@@ -2,8 +2,18 @@
<div class="common-layout">
<!-- title 标题和搜索栏 -->
<header class="header">
<div class="title">{{ $route.meta.title }}</div>
<van-search placeholder="请输入搜索关键词" background="#A5D380" />
<van-nav-bar
class="header-nav"
:title="$route.meta.title"
left-arrow
@click-left="$route.go(-1)"
/>
<van-search
shape="round"
class="header-search"
placeholder="请输入搜索关键词"
background="#6fb937"
/>
</header>
<!-- content -->
<RouterView />
@@ -59,32 +69,29 @@ const table = [
}
];
function tabPath(path) {
router.push({
path
});
// if (utils.getParameter('digitalYiliToken')) {
// const appToken = utils.getParameter('digitalYiliToken');
// getUserInfo(appToken)
// .then((res) => {
// if (res.data) {
// utils.setSessionStorage('userInfo', res.data.data);
// router.push({
// path
// });
// } else {
// showFailToast(
// error.response.data?.message || error.data?.message || error.message || '服务器错误'
// );
// }
// })
// .catch((error) => {
// showFailToast(error?.response?.data?.message || error?.message || '服务器错误');
// });
// } else {
// router.push({
// path
// });
// }
if (utils.getParameter('digitalYiliToken')) {
const appToken = utils.getParameter('digitalYiliToken');
getUserInfo(appToken)
.then((res) => {
if (res.data) {
utils.setSessionStorage('userInfo', res.data.data);
router.push({
path
});
} else {
showFailToast(
error.response.data?.message || error.data?.message || error.message || '服务器错误'
);
}
})
.catch((error) => {
showFailToast(error?.response?.data?.message || error?.message || '服务器错误');
});
} else {
router.push({
path
});
}
}
</script>
@@ -96,10 +103,16 @@ function tabPath(path) {
}
.header {
position: sticky;
top: 0;
z-index: 1000;
background-color: #a5d380;
.header-nav {
background: var(--primary-color) !important;
}
.header-search {
padding: 13px;
//.input-class {
//}
}
.title {
display: flex;

View File

@@ -46,13 +46,13 @@ function showModal(options) {
* @param {*} data
* @returns
*/
const canPlanetPublishPSM = function (data) {
const canPlanetPublishPSM = function(data) {
let isFb = true;
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题目未完成设置请设置价格区间后投放';
@@ -77,15 +77,15 @@ const canPlanetPublishPSM = function (data) {
* @param {*} data
* @returns
*/
const canPlanetPublishMxdAndHotArea = function (data) {
const canPlanetPublishMxdAndHotArea = function(data) {
let isFb = true;
let content = '';
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;
content = 'maxdiff题目未完成设置请生成设计后投放';
@@ -124,14 +124,14 @@ const canPlanetPublishMxdAndHotArea = function (data) {
* @param {*} data
* @returns
*/
const canPlanetPublish3D = function (data) {
const canPlanetPublish3D = function(data) {
{
let canFB = true;
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) => {
@@ -221,14 +221,14 @@ const canPlanetPublish3D = function (data) {
* @param {*} data
* @returns
*/
const canPlanetPublishImage = function (data) {
const canPlanetPublishImage = function(data) {
{
let canFB = true;
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}`
});
}
});
@@ -378,7 +378,7 @@ function canPublishRandom(data, publishType) {
// return false;
// }
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=');

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,15 @@ 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);
// import VConsole from 'vconsole';
// let vconsole;
if (import.meta.env.VITE_APP_ENV !== 'production') {
vconsole = new VConsole();
const vconsole = new VConsole();
app.use(vconsole);
// eslint-disable-next-line no-unused-vars
// vconsole = new VConsole();
}
// 添加 TypeScript 类型声明,在文件顶部添加
@@ -29,7 +33,7 @@ router.beforeEach((to, from, next) => {
if (to.query.digitalYiliToken) {
utils.setSessionStorage('xToken', to.query.digitalYiliToken);
}
appBridge.setTitle(to.meta.title as string);
// appBridge.setTitle(to.meta.title as string);
// 设置禁止原生返回
appBridge.takeOverAndroidBack();
// 定义路由是否可以返回的判断
@@ -45,16 +49,13 @@ router.beforeEach((to, from, next) => {
// 添加 Android 返回按钮监听方法
window.onAndroidBack = () => {
if (routerCanGoBack()) {
console.log('h5返回')
router.back();
router.back();
} else {
console.log('app返回')
callAppGoBack(); // 调用 APP 的返回方法
callAppGoBack();
}
};
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

@@ -43,10 +43,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,78 +5,84 @@
>
<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">
<!-- if always-->
<yl-select
v-model="log.logic"
:options="logIndex === 0 ? settingIfOptions : settingAndOptions"
class="if mr10"
@change="logicIf($event, index)"
></yl-select>
<!-- 问题-->
<yl-select
v-if="log.logic !== 'always'"
v-model="log.question_index"
class="question"
:options="beforeQuesOptions"
placeholder="请选择问题"
@change="getQuestionType"
></yl-select>
<!-- 为空 不为空-->
<yl-select
v-if="log.logic !== 'always'"
v-model="log.is_answer"
class="answer mr10 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"
>
<div>
<!-- 固定分组-->
<!-- if always-->
<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)"
v-model="log.logic"
:options="logIndex === 0 ? settingIfOptions : settingAndOptions"
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 mt10"
:options="beforeQuesOptions"
placeholder="请选择问题"
@change="getQuestionType($event, log)"
></yl-select>
<!-- 为空 不为空-->
<yl-select
v-if="log.logic !== 'always'"
v-model="log.is_answer"
class="answer ml10 mt10"
:options="answerOptions"
></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

@@ -7,25 +7,24 @@ import { onMounted, ref } from 'vue';
// import { getUserInfo } from '@/api/common/index.js';
// import { showFailToast } from 'vant';
const contentShow = ref(false);
onMounted(async () => {
contentShow.value = true;
// if (utils.getSessionStorage('xToken')){
// const appToken = utils.getParameter('digitalYiliToken');
// getUserInfo(appToken).then((res) => {
// if (res.data) {
// contentShow.value = true;
// utils.setSessionStorage('userInfo', res.data.data);
// } else {
// contentShow.value = false;
// showFailToast(error.response.data?.message || error.data?.message || error.message || '服务器错误');
// }
// }).catch((error) => {
// contentShow.value = false;
// showFailToast(error?.response?.data?.message || error?.message || '服务器错误');
// });
// } else {
// contentShow.value = true;
// }
onMounted(async() => {
if (utils.getSessionStorage('xToken')) {
const appToken = utils.getParameter('digitalYiliToken');
getUserInfo(appToken).then((res) => {
if (res.data) {
contentShow.value = true;
utils.setSessionStorage('userInfo', res.data.data);
} else {
contentShow.value = false;
showFailToast(error.response.data?.message || error.data?.message || error.message || '服务器错误');
}
}).catch((error) => {
contentShow.value = false;
showFailToast(error?.response?.data?.message || error?.message || '服务器错误');
});
} else {
contentShow.value = true;
}
});
</script>

View File

@@ -46,7 +46,7 @@ import { consoleSurveys } from '@/api/home/index.js';
const survey = ref({
project_name: ''
});
const fetchSurveys = async () => {
const fetchSurveys = async() => {
const params = {
page: 1,
per_page: 10,

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) => {
@@ -32,7 +32,7 @@ const getTableList = async () => {
getMarketInfo(marketList.value[0]);
}
};
const getMarketInfo = async (item) => {
const getMarketInfo = async(item) => {
console.log(item);
const code = marketList.value.filter((market, index) => item === index)[0].code;
console.log(code);

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

@@ -1,44 +1,180 @@
<template>
<div class="container">
<div v-for="item in 4" :key="item" class="survey-item">
<span>
<img
src="https://files.axshare.com/gsc/DR6075/de/a0/49/dea049d6ad3e4c2c80af44258c6c76d6/images/%E9%97%AE%E5%8D%B7/u35.svg?pageId=04b2dc46-144e-4349-9301-11852899b094"
alt=""
/>
已结束 - 100
</span>
<div>移动端</div>
<div style="margin: 10px 0 0">报名签到问卷标题</div>
<div>问卷描述</div>
<div class="new-survey-container">
<div v-for="item in 10" :key="item" class="new-survey_item">
<!-- 问卷详情 -->
<div class="survey_item_info">
<div style="position: relative">
<div class="survey_item_info_title">
<el-text>
<b>{{ '报名签到问卷标题' }}</b>
</el-text>
<el-text>{{ 100 }}</el-text>
</div>
<div class="survey_item_info_status">
<el-space spacer="|">
<!--报名签到-->
<div>
<span><img src="" alt="" /></span>
<el-text size="small">{{ '报名签到' }}</el-text>
</div>
<!-- 问卷来源 -->
<div>
<span><img src="" alt="" /></span>
<el-text size="small">{{ '移动端' }}</el-text>
</div>
<!-- 问卷时间 -->
<div>
<span><img src="" alt="" /></span>
<el-text size="small">{{ '2025.03.04' }}</el-text>
</div>
</el-space>
</div>
<div class="survey_item_status">
<span class="survey_item_info_status_text">-已结束-</span>
</div>
</div>
<!--问卷描述-->
<div class="survey_item_info_desc">
<el-text>
{{ '问卷描述:为优化活动服务品质,烦请完成问卷,感谢配合!您的反馈至关重要' }}
</el-text>
</div>
</div>
<!-- action 功能位置 -->
<div class="survey_item_action">
<el-space direction="horizontal">
<div>
<el-button> 删除</el-button>
<el-button> 复制</el-button>
<el-button style="border: 2px solid #71b73c">
<el-text style="color: #71b73c">预览</el-text>
</el-button>
<el-button color="#6fb937">
<el-text style="color: white">开启投放</el-text>
</el-button>
</div>
<el-dropdown placement="top-end" trigger="click" style="">
<Io5EllipsisHorizontalSharp />
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item>编辑</el-dropdown-item>
<el-dropdown-item>存为模板</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</el-space>
</div>
</div>
</div>
</template>
<script setup lang="ts"></script>
<script setup lang="ts">
// import { ref } from 'vue';
import { Io5EllipsisHorizontalSharp } from 'vue-icons-plus/io5';
// const surveyStatus = ref('end');
// const getSurveyStatusUrl = computed(() => {
// const urlMap: { [key: string]: string } = {
// end: 'https://lanhu-oss-2537-2.lanhuapp.com/SketchPngbb370d01215f9cedc28d567c637c011047f83a99fbb5e7ac348ebd0ef0015f32',
// edit: 'https://lanhu-oss-2537-2.lanhuapp.com/SketchPngaa20b2a05d267d040d17ba3aca15ae8c8f43fc3d2541283276b51d601d069bcc',
// publish:
// 'https://lanhu-oss-2537-2.lanhuapp.com/SketchPngbdfd7252fb5f0fa698039bafcab00305a5b80f0e19c67522e6d4d29820f0d58e'
// };
// return `url(${urlMap[surveyStatus.value]})`;
// });
</script>
<style scoped lang="scss">
.container {
display: flex;
flex-flow: row wrap;
align-items: start;
justify-content: space-evenly;
@import '@/assets/css/base';
@import '@/assets/css/main';
.survey-item {
display: flex;
flex-direction: column;
align-items: start;
width: calc(194px / 1.2);
height: calc(144px / 1.2);
margin: 3px 0;
padding: 5px;
.new-survey-container {
min-height: calc(100vh - 100px);
padding: 1px;
background: linear-gradient(to bottom, $theme-color 200px, #f2f2f2 300px);
.new-survey_item {
margin: 10px;
padding: 10px 0 8px 7px;
border-radius: 8px;
background-color: white;
box-shadow: 4px 4px 3px 2px #e0e0e0;
font-size: 12px;
* {
font-size: 12px;
.survey_item_info {
.survey_item_status {
position: absolute;
top: 0;
right: 10px;
padding: 28px 13px 19px 7px;
background: url('https://lanhu-oss-2537-2.lanhuapp.com/SketchPngbb370d01215f9cedc28d567c637c011047f83a99fbb5e7ac348ebd0ef0015f32')
100% no-repeat;
background-size: 100% 100%;
opacity: 1;
.survey_item_info_status_text {
height: 12px;
color: rgba(206, 206, 206, 1);
//font-family: TBMCYXT;
font-weight: normal;
font-size: 11px;
line-height: 13px;
letter-spacing: 1.0083px;
text-align: left;
white-space: nowrap;
overflow-wrap: break-word;
}
}
.survey_item_info_title {
.el-text {
font-size: 15px;
}
& > :nth-child(2) {
position: relative;
left: 10px;
padding: 1px;
border: 2px solid #f5f5f5;
border-radius: 6px;
font-size: 12px;
}
}
.survey_item_info_desc {
margin: 15px 7px 0 0;
padding: 7px 9px 6px;
border-radius: 8px;
background-color: rgba(246, 247, 248, 0.5);
.el-text {
width: 323px;
height: 32px;
color: rgba(130, 130, 130, 1);
//font-family: PingFangSC-Regular;
font-weight: normal;
font-size: 12px;
line-height: 16px;
text-align: left;
overflow-wrap: break-word;
}
}
}
.survey_item_action {
position: relative;
padding: 5px;
border-top: 1px dashed #f5f5f5;
.el-button {
width: 18vw;
border-radius: 8px;
}
.el-space {
display: flex;
justify-content: space-evenly;
}
}
}
}

View File

@@ -374,14 +374,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()
};
});
})
: []
})
);
@@ -514,7 +514,7 @@ const previewQuestion = () => {
router.push({ name: 'preview', query: { ...route.query } });
};
onMounted(async () => {
onMounted(async() => {
await getQuestionDetail();
});
</script>

View File

@@ -19,42 +19,77 @@
</van-field>
</van-cell-group>
</van-cell-group>
<div v-if="styleInfo.logo_status && styleInfo.logo_url" class="example-logo" :style="[
{
'justify-content':
styleInfo.logo_site === 1
? 'flex-start'
: styleInfo.logo_site === 2
? 'center'
: 'flex-end'
},
{ 'padding-left': styleInfo.logo_site === 1 ? '20px' : '' },
{ 'padding-right': styleInfo.logo_site === 3 ? '20px' : '' },
{ position: styleInfo.head_img_status ? 'absolute' : '' },
!styleInfo.head_img_status && styleInfo.background_status
? `background-color: ${styleInfo.background_color};background-image: url(${styleInfo.background_url})`
: ''
]">
<div
v-if="styleInfo.logo_status && styleInfo.logo_url"
class="example-logo"
:style="[
{
'justify-content':
styleInfo.logo_site === 1
? 'flex-start'
: styleInfo.logo_site === 2
? 'center'
: 'flex-end'
},
{ 'padding-left': styleInfo.logo_site === 1 ? '20px' : '' },
{ 'padding-right': styleInfo.logo_site === 3 ? '20px' : '' },
{ position: styleInfo.head_img_status ? 'absolute' : '' },
!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
? `background-color: ${styleInfo.background_color};background-image: url(${styleInfo.background_url})`
: ''
}`">
<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>
@@ -461,7 +579,7 @@ const props = defineProps({
getQuestions();
// 更新数据
async function getQuestions () {
async function getQuestions() {
let { data } = await AnswerApi.getQuetions({
id: route.query.sn,
data: {
@@ -484,14 +602,14 @@ async function getQuestions () {
}
// 获取 DOM 的内容
function getDomString (htmlString) {
function getDomString(htmlString) {
if (typeof htmlString !== 'string') return;
const match = htmlString.match(/<.*>(.*?)<\/.*>/);
if (match) return match[1];
}
// 上一页
async function previous () {
async function previous() {
if (prevLoading.value || loading.value) {
return;
}
@@ -514,7 +632,7 @@ async function previous () {
}
// 下一页
async function next (callbackBeforePage) {
async function next(callbackBeforePage) {
if (prevLoading.value || loading.value) {
return;
}
@@ -533,7 +651,7 @@ async function next (callbackBeforePage) {
// 开始答题
// 答题
async function answer (callback, callbackBeforePage) {
async function answer(callback, callbackBeforePage) {
// console.log(`start input answer`);
// console.log(
// `(questions.value.length || !questionsData.value.questions.length)`,
@@ -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;
@@ -751,47 +869,47 @@ async function answer (callback, callbackBeforePage) {
const { value } = answer;
const newValue = value.replace(/\n|\r|\r\n/g, '');
switch (config.text_type) {
case 3: // 字母
isError
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
? !/^[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;
? !/^(?:[\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
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 7: // 身份证号
isError
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 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;
value
);
question.error = isError ? translatedText.value.PleaseEnterACorrectID : '';
break;
default:
break;
}
if (!isError && value.length < config.min && ![1, 2].includes(config.text_type)) {
isError = true;
@@ -803,114 +921,60 @@ async function answer (callback, callbackBeforePage) {
Object.keys(answer).forEach((key) => {
const value = answer[key];
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 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 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 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 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 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;
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;
} else {
question.error = '';
}
return isError;
});
});
} else if (questionType === 27 && question.error) {
// 多项填空题
isError = true;
} else {
question.error = '';
}
return isError;
});
if (!errors.length) {
// 质量控制
const question = questions.value.find((question) => {
@@ -1147,7 +1211,7 @@ async function answer (callback, callbackBeforePage) {
}
// 选项隐藏
function hideOptions (hide) {
function hideOptions(hide) {
const questionIndex = hide?.question_index;
if (questionIndex) {
const qustion = questionsData.value.questions.find(
@@ -1158,7 +1222,7 @@ function hideOptions (hide) {
}
// 更新答案
function updateAnswer (auto) {
function updateAnswer(auto) {
if (auto) {
auto.forEach((autoItem) => {
const question = questionsData.value.questions.find(
@@ -1182,7 +1246,7 @@ function updateAnswer (auto) {
}
// 如果有结束跳转,则判断是否需要立即跳转
function jumpImmediately () {
function jumpImmediately() {
// 2000
const code = questionsData.value.action?.code;
// 检测是否是最后一页
@@ -1236,7 +1300,7 @@ function jumpImmediately () {
}
// // 关联引用
function onRelation (
function onRelation(
{ options, value, list },
{ question_type: questionType, question_index: questionIndex, related, answer }
) {

View File

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