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

This commit is contained in:
liu.huiying@ebiz-digits.com
2025-03-18 17:25:43 +08:00
19 changed files with 367 additions and 93 deletions

View File

@@ -22,6 +22,9 @@
--status-bar-height: 20px;
--sticky-top-height: calc(var(--status-bar-height) + calc(var(--van-nav-bar-height) + 13px));
--van-radius-sm: 16px;
--van-tabs-line-height: 30px;
--van-tabs-bottom-bar-height: 2px;
--van-tabs-bottom-bar-width: 28px;
}
/* semantic color variables for this project */

View File

@@ -17,6 +17,20 @@
background: #f2f2f2;
}
.van-tabs__nav--line.van-tabs__nav--shrink,
.van-tabs__nav--line.van-tabs__nav--complete {
padding-left: 0;
}
.van-tab--grow {
margin: 0 20px 0 0;
padding: 0;
}
.van-tab--grow:last-child {
margin-right: 0;
}
.van-radio-group {
& .van-radio {
.van-radio__icon--checked {

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

View File

@@ -138,6 +138,6 @@
content: '\e6a0';
}
.mobilefont-fasong:before {
.mobilefont-fasong::before {
content: '\e647';
}

View File

@@ -3,7 +3,7 @@
<!-- title 标题和搜索栏 -->
<header class="header">
<van-nav-bar
class="navbar-header"
class=""
:title="$route.meta.title"
left-arrow
safe-area-inset-top
@@ -11,7 +11,7 @@
@click-left="goBack"
>
<template #left>
<van-icon name="left-long" class-prefix="mobilefont" size="18" style="color: #fff" />
<van-icon name="left-long" class-prefix="mobilefont" size="18" style="color: #000" />
</template>
</van-nav-bar>
</header>
@@ -36,16 +36,28 @@ function goBack() {
</script>
<style scoped lang="scss">
.common-layout {
background-color: white;
//background-size: contain; /* 或者使用具体的尺寸,如 100% 100% */
//background-position: center; /* 确保图片居中显示 */
//background-repeat: no-repeat;
background-image: url('@/assets/img/home/home-pen.png');
//background-color: white;
color: #333;
}
.van-nav-bar {
//background-color: transparent;
background-image: url('@/assets/img/home/home-pen.png');
}
.header {
position: sticky;
top: 0;
z-index: 1000;
background-color: #a5d380;
//background-color: #a5d380;
//background-image: url('@/assets/img/home/home-pen.png');
.title {
display: flex;
align-items: end;

60
src/layouts/redirect.vue Normal file
View File

@@ -0,0 +1,60 @@
<template>
<div class="common-layout">
<!-- title 标题和搜索栏 -->
<header class="header">
<van-nav-bar
class="navbar-header"
:title="$route.meta.title"
left-arrow
safe-area-inset-top
:border="false"
@click-left="goBack"
>
<template #left>
<van-icon name="left-long" class-prefix="mobilefont" size="18" style="color: #fff" />
</template>
</van-nav-bar>
</header>
<!-- content -->
<RouterView />
</div>
</template>
<script setup>
import { RouterView, useRouter, useRoute } from 'vue-router';
import appBridge from '@/assets/js/appBridge';
const route = useRoute();
const router = useRouter();
function goBack() {
if (window.history.length > 1 && route.name !== 'home') {
router.go(-1);
} else {
appBridge.navigateBack();
}
}
</script>
<style scoped lang="scss">
.common-layout {
background-color: white;
color: #333;
}
.header {
position: sticky;
top: 0;
z-index: 1000;
background-color: #a5d380;
.title {
display: flex;
align-items: end;
justify-content: center;
}
.back-icon {
width: 18px;
height: 18px;
}
}
</style>

View File

@@ -1,9 +1,8 @@
import { showConfirmDialog } from 'vant';
import { getQuestionList, getCheckSurvey } from '@/api/survey';
import { getQuestionList } from '@/api/survey';
import { QUESTION_TYPE } from '@/layouts/config3d.constant.js';
import { loopingAvailable } from '@/layouts/logic.js';
import { getDomText } from '@/utils/utils';
import utils from '@/assets/js/common';
// /**
// * 统一的弹窗
// * @param options
@@ -431,6 +430,7 @@ export const canPlanetPublish = async function(sn, publishType) {
if (!canPublishRandom(data?.data, parsedPublishType)) return false;
if (!isLoopingLogicValid(data?.data, parsedPublishType)) return false;
/* eslint-disable */
// if (parsedPublishType === 2) {
// const qrcodeRes = await getCheckSurvey(sn);
// if (qrcodeRes?.data?.data?.show_test_button) {
@@ -478,6 +478,6 @@ export const canPlanetPublish = async function(sn, publishType) {
// if (!res) return;
// }
// }
/* eslint-enable */
return true;
};

View File

@@ -1,6 +1,7 @@
import { createRouter, createWebHistory } from 'vue-router';
import layout from '@/layouts/index.vue';
import Design from '@/views/Design/Index.vue';
import Redirect from '@/layouts/redirect.vue';
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
@@ -20,7 +21,18 @@ const router = createRouter({
title: '伊调研'
},
component: () => import('../views/Home/Index.vue')
},
}
]
},
{
path: '/redirect',
name: '/redirect',
component: Redirect,
redirect: '/survey',
meta: {
title: '伊调研'
},
children: [
{
path: '/survey',
name: 'survey',

View File

@@ -32,8 +32,9 @@
<RateCharacter
:config="element.config"
:index="optionIndex"
v-model:model="value"
@change="handleRateChange"
></RateCharacter>
/>
</div>
</div>
</template>
@@ -45,8 +46,9 @@
import { ref } from 'vue';
import RateCharacter from './RateCharacter.vue';
const value = defineModel('value', { default: -1, type: Number });
const isPreview = defineModel('isPreview', { default: false, type: Boolean });
/*const props = */ defineProps({
/* const props = */ defineProps({
index: {
type: Number,
default: 0

View File

@@ -16,8 +16,8 @@
<script setup>
import { ref, watch } from 'vue';
import { value as model } from '@/views/Design/components/Questions/hooks/useNPSHooks';
const model = defineModel('model', -1);
const rateItem = ref([
{
label: 1,

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)
@@ -40,16 +40,21 @@ function create() {
</script>
<template>
<div v-if="contentShow" class="container">
<create-survey :createdNewPage="false" />
<!-- 最新问卷 -->
<last-survey />
<!-- 模板市场 -->
<Market />
<div class="new_survey">
<van-button type="primary" block color="#70B937" @click="create">
<span class="fw-bold">+</span> 新建问卷
</van-button>
<div v-if="contentShow" class="container-home">
<!-- <div class="home-pen">-->
<!-- <img :src="homePen" alt="" />-->
<!-- </div>-->
<div class="container-body">
<create-survey :createdNewPage="false" />
<!-- 最新问卷 -->
<last-survey />
<!-- 模板市场 -->
<Market />
<div class="new_survey">
<van-button type="primary" block color="#70B937" @click="create">
<span class="fw-bold">+</span> 新建问卷
</van-button>
</div>
</div>
</div>
<van-popup v-model:show="show" round closeable position="bottom">
@@ -58,15 +63,47 @@ function create() {
</template>
<style scoped lang="scss">
.container {
padding: 30px 10px 80px;
background: linear-gradient(0deg, #f5f5f5 0%, #f5f5f5 84%, #a5d380 100%);
.container-home {
overflow: hidden;
width: 100%;
//background: #f2f2f2;
//position: relative;
.home-pen {
//height: 200px;
position: absolute;
top: -10px;
left: 0;
z-index: 8;
//width: 100%;
background: #fff;
//background: linear-gradient(180deg, rgba(242, 242, 242, 0) 0%, #ebffe9 100%);
img {
width: 100%;
//height: 200px;
}
}
}
.container-body {
padding: 0 10px 80px;
//background: linear-gradient(0deg, #f5f5f5 0%, #f5f5f5 84%, #a5d380 100%);
& > :first-child {
display: flex;
justify-content: space-around;
border-radius: 6px;
background-color: white;
position: relative;
z-index: 10;
//background-color: white;
margin-top: 10px;
//display: flex;
//justify-content: space-around;
border-radius: 16px;
& > div {
display: flex;
@@ -77,7 +114,7 @@ function create() {
// background-color: #B9F8CF;
padding: 20px 10px;
//padding: 20px 10px;
}
}

View File

@@ -19,8 +19,9 @@ const createdNewPage = defineModel('createdNewPage', {
const createdQuestion = (item) => {
const query = {
group_id: 0,
source: 1,
project_name: `${item.title}问卷 `,
remarks: '',
remarks: '为优化活动服务品质,烦请完成问卷,感谢配合',
scene_code: item.parentCode,
scene_code_info: item.code,
// 很迷茫 模板新增 tag 空数组 非模板 就是k
@@ -104,10 +105,13 @@ onMounted(() => {
</script>
<template>
<van-cell class="create_survey">
<div class="create_survey_title" style="color: #000; text-align: left">请选择新建类型</div>
<van-row>
<van-col
<!-- <div class="home-pen">-->
<!-- <img :src="homePen" alt="" />-->
<!-- </div>-->
<div class="create_survey">
<div class="create_survey_title" style="color: #000; text-align: left">新建问卷</div>
<div class="flex align-center space-between warp">
<div
v-for="survey in surveys"
:key="survey.title"
span="6"
@@ -116,30 +120,68 @@ onMounted(() => {
>
<img :src="survey.image" alt="" width="40" />
<span>{{ survey.title }}</span>
</van-col>
</van-row>
</van-cell>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.home-pen {
//height: 200px;
position: absolute;
top: -10px;
left: 0;
z-index: 8;
//width: 100%;
background: #fff;
img {
width: 100%;
//height: 200px;
}
}
.create_survey {
padding: 15px;
overflow: hidden;
border-radius: 16px;
background-image: url('@/assets/img/home/home-back.png');
background-position: center; /* 确保图片居中显示 */
background-size: contain; /* 或者使用具体的尺寸,如 100% 100% */
background-repeat: no-repeat;
//padding: 15px;
color: #000;
.create_survey_title {
margin-bottom: 15px;
margin: 16px;
color: #000;
font-weight: bold;
font-size: 15px;
font-family: PingFangSC, 'PingFang SC';
}
& .warp {
flex-wrap: wrap;
}
}
.survey {
display: flex;
//margin-right: 30px;
flex-direction: column;
align-items: center;
justify-content: space-around;
//flex: 1;
width: 25%;
//margin: 0 16px;
text-align: center;
//justify-content: space-around;
span {
margin-top: 8px;

View File

@@ -2,16 +2,18 @@
<!-- 问卷 -->
<div class="last-survey">
<div class="survey_header">
<div class="flex space-between">
<div class="flex space-between align-center">
<div class="flex align-center">
<p class="fw-bold">最新问卷</p>
<p class="survey_header_tag">NEW</p>
</div>
<p @click="$router.push('/survey')">全部问卷 ></p>
<p class="survey-all" @click="$router.push('/survey')">
全部问卷 <van-icon name="arrow"></van-icon>
</p>
</div>
</div>
<div class="survey_con">
<div class="flex">
<div class="flex align-center space-between mb10">
<div>
<div class="survey_con_title flex align-center">
<p class="mr-10 fw-bold">{{ survey.project_name }}</p>
@@ -37,9 +39,14 @@
</div>
</div>
</div>
<img src="" alt="" />
<div class="survey_item_status">
<img v-if="survey.status === 0" :src="editPng" alt="" />
<img v-else-if="survey.status === 1" :src="publishPng" alt="" />
<img v-else-if="survey.status === 2" :src="endPng" alt="" />
<!-- <span class="survey_item_info_status_text">-{{ item.status_txt }}-</span>-->
</div>
</div>
<div class="survey_remark">{{ survey.remarks }}</div>
<div v-if="survey.remarks" class="survey_remark">{{ survey.remarks }}</div>
</div>
</div>
</template>
@@ -47,11 +54,14 @@
<script setup>
import { ref, onMounted } from 'vue';
import { getSurveysPage } from '@/api/home/index.js';
import editPng from '@/assets/img/publish/edit.png';
import publishPng from '@/assets/img/publish/publish.png';
import endPng from '@/assets/img/publish/end.png';
const survey = ref({
project_name: ''
});
const fetchSurveys = async() => {
const fetchSurveys = async () => {
const params = {
page: 1,
per_page: 10,
@@ -83,35 +93,55 @@ onMounted(() => {
<style scoped lang="scss">
.last-survey {
margin-top: 6px;
padding: 10px 3px 3px;
border-radius: 10px;
margin-top: 10px;
padding: 9px 3px 3px;
border-radius: 16px;
background-color: #27d6ac;
color: #fff;
.survey_header {
padding: 0 10px;
padding: 0 15px;
font-size: 15px;
& .survey-all {
font-size: 13px;
}
.survey_header_tag {
width: 32px;
//width: 32px;
height: 15px;
margin-left: 3px;
border-radius: 4px;
margin-left: 7px;
border-radius: 5px;
background-color: #fff;
color: #27d6ac;
font-size: 10px;
font-size: 11px;
line-height: 15px;
text-align: center;
}
}
.survey_con {
margin-top: 10px;
position: relative;
margin-top: 5px;
padding-bottom: 5px;
border-radius: 10px;
background: #fff;
color: #000;
.survey_item_status {
position: absolute;
top: 0;
right: -15px;
overflow: hidden;
width: 85px;
height: 80px;
& img {
width: 100%;
height: 100%;
}
}
img {
height: 12px;
margin-right: 3px;
@@ -138,18 +168,19 @@ onMounted(() => {
.survey_con_label {
margin-left: 10px;
color: #666;
font-size: 10px !important;
div {
& div {
margin-right: 5px;
font-size: 11px;
}
}
.survey_remark {
box-sizing: border-box;
margin: 10px 0 0 10px;
padding: 10px 5px;
border-radius: 10px;
margin: 0 10px 1px;
padding: 8px;
border-radius: 8px;
background: #f6f7f8;
color: #828282;
font-weight: 400;
font-style: normal;
@@ -157,4 +188,8 @@ onMounted(() => {
}
}
}
.mb10 {
margin-bottom: 10px;
}
</style>

View File

@@ -3,9 +3,10 @@
<div class="market">
<div class="market_title fw-bold">模板市场</div>
<van-tabs v-model:active="active" @change="getMarketInfo">
<van-tab v-for="item in marketList" :key="item.title" :title="item.title"> </van-tab>
<van-tab v-for="item in marketList" :key="item.title" :title="item.title">
<market-item :info="marketInfo" />
</van-tab>
</van-tabs>
<market-item :info="marketInfo"></market-item>
</div>
<div class="more">
<p>-更多模板期待您的探索-</p>
@@ -70,11 +71,12 @@ onMounted(() => {
.market {
margin-top: 10px;
padding: 15px 15px 0;
border-radius: 10px;
padding: 10px 12px 0;
border-radius: 16px;
background: #fff;
.market_title {
margin-bottom: 5px;
color: #000;
font-size: 15px;
}

View File

@@ -26,11 +26,12 @@
style="color: #c1c1c1"
/>
</div>
<div class="desc flex space-between">
<div class="desc flex space-between align-center">
<div>
<p>创建人</p>
<p class="fw-bold">{{ item.created_user }}</p>
</div>
<div class="line"></div>
<div>
<p>引用次数</p>
<p class="fw-bold">{{ item.quote_nums }}</p>
@@ -93,23 +94,36 @@ onMounted(() => {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
padding: 10px 0;
}
.market-item {
//margin-right: 4%;
flex: 1;
box-sizing: border-box;
width: 49%;
margin-bottom: 12px;
padding: 10px;
border-radius: 8px;
background: #fff;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
max-width: 50%;
margin-bottom: 5px;
margin-left: 7px;
padding: 15px 12px;
border: 1px solid #fff;
border-radius: 10px;
background: rgba(241, 241, 241, 0.39);
// 偶数项的 margin-right 设置为 0
&:nth-child(even) {
&:nth-child(n-1) {
margin-right: 7px;
margin-left: 0;
}
&:nth-child(2n) {
margin-right: 0;
}
//width: 49%;
//margin-bottom: 12px;
//padding: 10px;
//border-radius: 8px;
//background: #fff;
//box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
.content {
.title {
display: flex;
@@ -137,6 +151,13 @@ onMounted(() => {
color: #666;
font-size: 12px;
.line {
width: 1px;
height: 20px;
background: #979797;
opacity: 0.1;
}
div p:last-child {
color: #000;
}

View File

@@ -1,10 +1,10 @@
<template>
<div class="survey-search">
<van-search
v-model="searchValue"
class="theme-background"
:border="false"
background="#71b73c"
v-model="searchValue"
@blur="blurs"
@search="blurs"
></van-search>
@@ -68,20 +68,26 @@
<div class="survey_item_action">
<!-- <el-space direction="horizontal">-->
<div>
<el-button @click="deleteItem(item)"> 删除</el-button>
<el-button @click="copyItem(item)"> 复制</el-button>
<el-button :disabled="item.source === 0" @click="deleteItem(item)"> 删除</el-button>
<el-button :disabled="item.source === 0" @click="copyItem(item)"> 复制</el-button>
<el-button style="border: 2px solid #71b73c" @click="toPreview(item)">
<el-text style="color: #71b73c">预览</el-text>
</el-button>
<el-button color="#6fb937" @click="toPublish(item)">
<el-button color="#6fb937" :disabled="item.source === 0" @click="toPublish(item)">
<el-text style="color: white">开启投放</el-text>
</el-button>
</div>
<el-dropdown placement="top-end" trigger="click" active-color="#ee0a24">
<Io5EllipsisHorizontalSharp />
<el-dropdown
v-if="item.source === 1"
placement="top-end"
trigger="click"
active-color="#71b73c"
>
<!-- <Io5EllipsisHorizontalSharp />-->
<van-icon class-prefix="mobilefont" name="gengduo" size="0.7rem"></van-icon>
<template #dropdown>
<el-dropdown-menu
active-color="#ee0a24"
active-color="#71b73c"
:close-on-click-overlay="false"
:close-on-click-outside="false"
>
@@ -100,7 +106,6 @@
<script setup>
import { ref, onMounted } from 'vue';
import { getSurveysPage, copySurveys, deleteSurveys, saveTemplates } from '@/api/home/index.js';
import { Io5EllipsisHorizontalSharp } from 'vue-icons-plus/io5';
import { showDialog, showConfirmDialog, showFailToast, showSuccessToast, showToast } from 'vant';
import { useRouter } from 'vue-router';
const router = useRouter();
@@ -281,7 +286,7 @@ onMounted(() => {
//background: linear-gradient(to bottom, $theme-color 200px, #f2f2f2 300px);
.new-survey_item {
margin: 0 10px 10px 10px;
margin: 0 10px 10px;
padding: 10px 0 8px 7px;
border-radius: 8px;
background-color: white;
@@ -373,7 +378,7 @@ onMounted(() => {
}
.new-survey_item + .new-survey_item {
margin: 0 10px 10px 10px;
margin: 0 10px 10px;
}
}
</style>

View File

@@ -109,12 +109,36 @@
<!-- <span>投放设置</span>-->
<!-- </div>-->
<div class="survey-action_btn">
<van-button size="small" plain type="primary" @click="saveAs">保存</van-button>
<van-button size="small" plain type="primary" @click="previewQuestion">预览</van-button>
<van-button
:key="1"
size="small"
plain
type="primary"
:disabled="activeActionButton"
@click="saveAs"
>
保存
</van-button>
<van-button
size="small"
plain
type="primary"
:disabled="activeActionButton"
@click="previewQuestion"
>
预览
</van-button>
<van-button size="small" plain type="success" @click="openSettingAction">
投放设置
</van-button>
<van-button size="small" icon="guide-o" @click="publishQuestion">立即投放</van-button>
<van-button
size="small"
icon="guide-o"
:disabled="activeActionButton"
@click="publishQuestion"
>
立即投放
</van-button>
</div>
</div>
</div>
@@ -336,6 +360,7 @@ import { basicQuesTypeList } from '@/utils/common';
import { useRoute, useRouter } from 'vue-router';
import YLPicker from '@/components/YLPicker.vue';
import { getPages } from '@/utils/public';
import { showConfirmDialog } from 'vant';
// 获取 Store 实例
const counterStore = useCounterStore();
@@ -355,6 +380,9 @@ const activeId = ref(0);
const showSetting = ref(false);
const timePickerModel = ref(false);
const activeActionButton = computed<boolean>(() => {
return questionInfo.value.questions.length === 0;
});
const openSettingAction = () => {
showSetting.value = true;
};
@@ -538,6 +566,10 @@ watch(
// 保存 目前没有任何逻辑可以执行所有保存
const saveAs = () => {
// 保存所有
showConfirmDialog({
message: '问卷保存成功',
showCancelButton: false
});
};
// 投放
const publishQuestion = () => {

View File

@@ -4,14 +4,12 @@
<script setup lang="ts">
import NPS from '@/views/Design/components/Questions/NPS.vue';
import { watch } from 'vue';
import { value } from '@/views/Design/components/Questions/hooks/useNPSHooks';
import { watch, ref } from 'vue';
const value = ref(-1);
// // 预览新增 emit ['changeAnswer', 'previous', 'next']
const emit = defineEmits(['changeAnswer', 'previous', 'next', 'update:element']);
const question = defineModel<question>('question', { default: { config: { is_required: false } } });
/**
* answer 的答案类型
* {
@@ -24,7 +22,6 @@ const answer = defineModel<NPSAnswerType>('answer', { default: undefined });
// function parseAnswer() {
// return answer.value[`1`];
// }
/**
* 生成NPS答案
*/