feat: 新增问卷列表页面及相关组件和样式文件

This commit is contained in:
Huangzhe
2025-05-14 23:23:09 +08:00
parent de25406283
commit bc6bd0200f
9 changed files with 66 additions and 101 deletions

View File

@@ -32,7 +32,7 @@
"editor.formatOnSave": true
},
"[vue]": {
"editor.defaultFormatter": "Vue.volar",
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true
},
"css.validate": false, //用来校验CSS文件中的语法错误和潜在的问题

View File

@@ -6,3 +6,4 @@ trigger: always_on
2. 尽量使用 element-plus 的组件内容
3. 开发的时候尽量少使用 css 内容,能不用尽量不用
4. 使用 vue3 的 <script setup> 语法, 拒绝使用以前的语法
5. git 提交的时候内容要详细。 划分好几个点用无序列表

15
components.d.ts vendored
View File

@@ -11,25 +11,17 @@ declare module 'vue' {
Contenteditable: typeof import('./src/components/contenteditable.vue')['default']
ElButton: typeof import('element-plus/es')['ElButton']
ElCard: typeof import('element-plus/es')['ElCard']
ElCarousel: typeof import('element-plus/es')['ElCarousel']
ElCarouselItem: typeof import('element-plus/es')['ElCarouselItem']
ElCol: typeof import('element-plus/es')['ElCol']
ElDialog: typeof import('element-plus/es')['ElDialog']
ElDropdown: typeof import('element-plus/es')['ElDropdown']
ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
ElEmpty: typeof import('element-plus/es')['ElEmpty']
ElIcon: typeof import('element-plus/es')['ElIcon']
ElImage: typeof import('element-plus/es')['ElImage']
ElImg: typeof import('element-plus/es')['ElImg']
ElInput: typeof import('element-plus/es')['ElInput']
ElOption: typeof import('element-plus/es')['ElOption']
ElRow: typeof import('element-plus/es')['ElRow']
ElSelect: typeof import('element-plus/es')['ElSelect']
ElSpace: typeof import('element-plus/es')['ElSpace']
ElTable: typeof import('element-plus/es')['ElTable']
ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
ElTag: typeof import('element-plus/es')['ElTag']
ElText: typeof import('element-plus/es')['ElText']
Index: typeof import('./src/components/Analysis/Index.vue')['default']
MarketItem: typeof import('./src/components/MarketItem/MarketItem.vue')['default']
@@ -38,13 +30,10 @@ declare module 'vue' {
RouterView: typeof import('vue-router')['RouterView']
VanActionSheet: typeof import('vant/es')['ActionSheet']
VanButton: typeof import('vant/es')['Button']
VanCard: typeof import('vant/es')['Card']
VanCell: typeof import('vant/es')['Cell']
VanCellGroup: typeof import('vant/es')['CellGroup']
VanCheckbox: typeof import('vant/es')['Checkbox']
VanCheckboxGroup: typeof import('vant/es')['CheckboxGroup']
VanCol: typeof import('vant/es')['Col']
VanDialog: typeof import('vant/es')['Dialog']
VanDivider: typeof import('vant/es')['Divider']
VanField: typeof import('vant/es')['Field']
VanIcon: typeof import('vant/es')['Icon']
@@ -55,7 +44,6 @@ declare module 'vue' {
VanPopup: typeof import('vant/es')['Popup']
VanRadio: typeof import('vant/es')['Radio']
VanRadioGroup: typeof import('vant/es')['RadioGroup']
VanRow: typeof import('vant/es')['Row']
VanSearch: typeof import('vant/es')['Search']
VanSpace: typeof import('vant/es')['Space']
VanStepper: typeof import('vant/es')['Stepper']
@@ -72,7 +60,4 @@ declare module 'vue' {
YLPicker: typeof import('./src/components/YLPicker.vue')['default']
YLSelect: typeof import('./src/components/YLSelect.vue')['default']
}
export interface ComponentCustomProperties {
vLoading: typeof import('element-plus/es')['ElLoadingDirective']
}
}

View File

@@ -1,3 +1,4 @@
@use 'theme';
/* eslint-disable */
@import 'theme';
@@ -22,11 +23,11 @@ a,
}
.theme-color {
color: $theme-color;
color: theme.$theme-color;
}
.theme-background {
background: $theme-color;
background: theme.$nav-header-color;
}
.ml10 {
@@ -42,21 +43,21 @@ a,
//height: calc(100vh - 100px);
//width: 100%;
// 绿色 #70B937 白色过渡渐变 竖向 上一半部分 渐变到白色就可以
background: linear-gradient(to bottom, $theme-color 200px, #f2f2f2 300px);
background: linear-gradient(to bottom, theme.$theme-color 200px, #f2f2f2 300px);
}
.navbar-header {
position: sticky;
top: 0;
width: 100%;
background-color: #70b937;
color: #fff;
background-color: theme.$nav-header-color;
color: #000;
& .van-nav-bar__content {
color: #fff;
color: #000;
& .van-nav-bar__title {
color: #fff;
color: #000;
}
}
}

View File

@@ -1,3 +1,4 @@
$theme-color: #71b73c;
$card-radius: 10px;
$gap: 10px;
$nav-header-color: #f2f2f2;

View File

@@ -4,10 +4,10 @@
v-model="value"
:placeholder="placeholder"
style="--van-search-padding: 0"
@search="searchMethod"
@search="handleSearchActino"
>
</van-search>
<el-text @click="searchMethod">搜索</el-text>
<el-text @click="handleSearchActino">搜索</el-text>
</section>
</template>
@@ -25,6 +25,13 @@ const placeholder = defineModel('placeholder', {
type: String,
default: '请输入搜索关键词'
});
const emit = defineEmits(['search']);
function handleSearchActino() {
emit('search');
searchMethod.value && searchMethod.value();
}
</script>
<style scoped lang="scss">

View File

@@ -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>

View File

@@ -1,13 +1,14 @@
<template>
<div class="survey-search">
<van-search
<!-- <van-search
v-model="searchValue"
placeholder="请输入关键词"
class="theme-background"
:border="false"
background="#71b73c"
background="#fff"
@search="blurs"
></van-search>
></van-search> -->
<nav-search v-model:value="searchValue" @search="blurs" />
</div>
<div class="new-survey-container">
<div style="margin-bottom: 80px">
@@ -17,7 +18,7 @@
finished-text="没有更多了"
@load="onLoad"
>
<div v-if="survey.length> 0" v-for="item in survey" :key="item" class="new-survey_item">
<div v-for="item in survey" v-if="survey.length > 0" :key="item" class="new-survey_item">
<survey-item :survey="item" />
</div>
<empty-container v-else />
@@ -25,17 +26,22 @@
</div>
<NewSurvey v-if="survey.length > 0" />
</div>
</template>
<script setup>
import { onMounted } from 'vue';
import NavSearch from '@/components/Search/Index.vue';
import NewSurvey from '@/views/Home/components/NewSurvey/index.vue';
import EmptyContainer from '@/views/Survey/components/EmptyContainer.vue';
import SurveyItem from '@/views/Survey/components/SurveyItem.vue';
import { form, fetchSurveys, loading, finished, survey, searchValue } from '@/views/Survey/hooks/useSurveyData';
import {
form,
fetchSurveys,
loading,
finished,
survey,
searchValue
} from '@/views/Survey/hooks/useSurveyData';
const blurs = () => {
form.value.page = 1;
@@ -57,8 +63,9 @@ onMounted(() => {
</script>
<style scoped lang="scss">
@import "@/assets/css/base";
@import "@/assets/css/main";
@use '@/assets/css/theme';
@import '@/assets/css/base';
@import '@/assets/css/main';
.el-dropdown-menu__item:not(.is-disabled):focus,
.el-dropdown-menu__item:not(.is-disabled):hover {
@@ -71,7 +78,7 @@ onMounted(() => {
z-index: 1000;
width: 100%;
padding: 0;
background-color: $theme-color;
background-color: theme.$nav-header-color;
}
.new-survey-container {

View File

@@ -16,12 +16,11 @@ import { form, fetchSurveys, deleteItem, saveTemplate, currentSurvey } from '@/v
// router
const router = useRouter();
const emit = defineEmits(["post-analysis", "post-surveys"]);
const emit = defineEmits(['post-analysis', 'post-surveys']);
const survey = defineModel<SurveyItem>('survey', { required: true });
const isAnalysis = defineModel('isAnalysis', { default: false, type: Boolean });
const postAnalysis = defineModel<Function>("post-analysis")
function setImg(code: number) {
const postAnalysis = defineModel<Function>('post-analysis');
function setImg (code: number) {
const imageMap: { [key: number]: string } = {
11: png11,
13: png13,
@@ -34,18 +33,18 @@ function setImg(code: number) {
};
// 默认返回 png11 如果 code 不存在
return imageMap[code] || png11;
};
}
function editItem(item: SurveyItem) {
function editItem (item: SurveyItem) {
router.push({
path: '/create',
query: {
sn: item.sn
}
});
};
}
function toPreview(item: SurveyItem) {
function toPreview (item: SurveyItem) {
router.push({
path: '/preview',
query: {
@@ -60,7 +59,7 @@ function toPreview(item: SurveyItem) {
* 跳转 统计分析 页面
* @param item
*/
function toAnalysis(item: SurveyItem) {
function toAnalysis (item: SurveyItem) {
// 设置当前的节点信息
currentSurvey.value = item;
// 跳转
@@ -72,7 +71,7 @@ function toAnalysis(item: SurveyItem) {
});
}
function toPublish(item: SurveyItem) {
function toPublish (item: SurveyItem) {
if (item.status === 1) {
showDialog({
title: `确定要取消投放${item.project_name}?`,
@@ -97,9 +96,9 @@ function toPublish(item: SurveyItem) {
}
});
}
};
}
function copyItem(item: SurveyItem) {
function copyItem (item: SurveyItem) {
showDialog({
title: `确认复制问卷${item.project_name} ?`,
showCancelButton: true,
@@ -121,7 +120,6 @@ function copyItem(item: SurveyItem) {
});
}
</script>
<template>
@@ -144,20 +142,13 @@ function copyItem(item: SurveyItem) {
<el-space spacer="|">
<!--报名签到-->
<div class="flex align-center">
<img
:src="setImg(survey.scene_code_info as number)"
alt="Content Icon"
style="width: 15px; height: 15px"
/>
<img :src="setImg(survey.scene_code_info as number)" alt="Content Icon"
style="width: 15px; height: 15px" />
<el-text size="small">{{ survey.owner }}</el-text>
</div>
<!-- 问卷来源 -->
<div class="flex align-center">
<img
v-if="survey.source === 1"
src="@/assets/img/publish/phone.png"
alt=""
/>
<img v-if="survey.source === 1" src="@/assets/img/publish/phone.png" alt="" />
<img v-else src="@/assets/img/publish/pc.png" alt="" />
<el-text size="small">
{{ survey.source === 1 ? '移动端' : 'PC端' }}
@@ -170,22 +161,10 @@ function copyItem(item: SurveyItem) {
</div>
</el-space>
</div>
<div class="survey_item_status" v-if="!isAnalysis">
<img
v-if="survey.status === 0"
src="@/assets/img/publish/edit.png"
alt=""
/>
<img
v-else-if="survey.status === 1"
src="@/assets/img/publish/publish.png"
alt=""
/>
<img
v-else-if="survey.status === 2"
src="@/assets/img/publish/end.png"
alt=""
/>
<div v-if="!isAnalysis" class="survey_item_status">
<img v-if="survey.status === 0" src="@/assets/img/publish/edit.png" alt="" />
<img v-else-if="survey.status === 1" src="@/assets/img/publish/publish.png" alt="" />
<img v-else-if="survey.status === 2" src="@/assets/img/publish/end.png" alt="" />
</div>
</div>
<!--问卷描述-->
@@ -205,7 +184,7 @@ function copyItem(item: SurveyItem) {
</el-space>
</div>
<!-- action 功能位置 -->
<div class="survey_item_action" v-if="!isAnalysis">
<div v-if="!isAnalysis" class="survey_item_action">
<div>
<el-button :disabled="survey.source === 0" @click="editItem(survey)">
编辑
@@ -216,10 +195,7 @@ function copyItem(item: SurveyItem) {
<!-- >-->
<!-- <el-text style="color: #71b73c">预览</el-text>-->
<!-- </el-button>-->
<el-button
style="border: 1px solid #71b73c"
@click="toAnalysis(survey)"
>
<el-button style="border: 1px solid #71b73c" @click="toAnalysis(survey)">
<el-text style="color: #71b73c">统计</el-text>
</el-button>
@@ -229,23 +205,10 @@ function copyItem(item: SurveyItem) {
</el-text>
</el-button>
</div>
<el-dropdown
v-if="survey.source === 1"
placement="top-end"
trigger="click"
active-color="#71b73c"
>
<van-icon
class-prefix="mobilefont"
name="gengduo"
size="0.7rem"
></van-icon>
<el-dropdown v-if="survey.source === 1" placement="top-end" trigger="click" active-color="#71b73c">
<van-icon class-prefix="mobilefont" name="gengduo" size="0.7rem"></van-icon>
<template #dropdown>
<el-dropdown-menu
active-color="#71b73c"
:close-on-click-overlay="false"
:close-on-click-outside="false"
>
<el-dropdown-menu active-color="#71b73c" :close-on-click-overlay="false" :close-on-click-outside="false">
<el-dropdown-item @click="copyItem(survey)">
复制
</el-dropdown-item>
@@ -298,7 +261,7 @@ function copyItem(item: SurveyItem) {
}
}
& > :nth-child(2) {
&> :nth-child(2) {
position: relative;
left: 10px;
padding: 1px 3px;
@@ -330,7 +293,7 @@ function copyItem(item: SurveyItem) {
align-items: center;
justify-content: center;
& > :nth-last-child(-n+1) {
&> :nth-last-child(-n+1) {
font-size: 20px;
font-weight: bold;
color: $theme-color;