feat: 首页模块包含模型卡片、操作指引和场景组件添加神策埋点

This commit is contained in:
2025-06-24 22:04:12 +08:00
parent 4cbf5f6a47
commit 9852bcc14e
7 changed files with 194 additions and 179 deletions

View File

@@ -78,5 +78,10 @@ installAntDesign(app);
app.config.globalProperties.emitter = emitter; app.config.globalProperties.emitter = emitter;
// 神策数据插件 // 神策数据插件
app.use(sensorsData(), {}); app.use(sensorsData(), {
// 测试环境
server_url: 'https://digitaldmo.yili.com/sa?project=sensorstest',
// 正式环境
// server_url: 'https://digitaldmo.yili.com/sa?project=YIP',
});
app.use(store).use(router).mount('#app'); app.use(store).use(router).mount('#app');

View File

@@ -632,9 +632,8 @@ router.beforeEach(async (to, from, next) => {
sa.instance = window.sa; sa.instance = window.sa;
// 检测是否使用神策的登陆 // 检测是否使用神策的登陆
const userInfo = JSON.parse(localStorage.getItem('plantUserInfo')); const userInfo = JSON.parse(localStorage.getItem('plantUserInfo'));
const loginID = `id-${userInfo.id}.login_team_id-${userInfo.login_team_id}`; globalThis.sa.setOnceProfile({loginID:userInfo.id});
sa.instance.login(globalThis.btoa(loginID));
sa.register = true; sa.register = true;
} }

View File

@@ -21,13 +21,9 @@ export function sensorsData() {
// 注册页面公共属性 // 注册页面公共属性
sensors.registerPage({ sensors.registerPage({
platform: 'pc', product_name: '伊调研',
// 产品名称 platform_type: 'PC'
production_name: 'ylst',
current_url: location.href,
referrer: document.referrer
}); });
// 提供全局注入的 sensors 实例 // 提供全局注入的 sensors 实例
app.provide('sensors', sensors); app.provide('sensors', sensors);
// 注册到window中 // 注册到window中
@@ -48,16 +44,11 @@ function registerDirective(app) {
return () => { return () => {
const { arg: eventName, value: properties } = binding; const { arg: eventName, value: properties } = binding;
if (eventName) { sensorsTrack(properties);
sensors.track(eventName, properties);
console.warn(properties);
} else {
console.warn('[sensorsData] 事件名未提供');
}
}; };
} }
app.directive('saTrack', { app.directive('sensorsTrack', {
mounted(el, binding) { mounted(el, binding) {
el.addEventListener('click', bindTrackListener(binding)); el.addEventListener('click', bindTrackListener(binding));
}, },
@@ -68,4 +59,7 @@ function registerDirective(app) {
}); });
} }
export { sensors }; function sensorsTrack(properties){
sensors.track("YiliResearch_PageClick", properties);
}
export { sensors,sensorsTrack };

View File

@@ -9,7 +9,11 @@
<p class="banner-block-slogan">实时链接消费者的深度洞察及日常信息采集工具</p> <p class="banner-block-slogan">实时链接消费者的深度洞察及日常信息采集工具</p>
<div class="banner-block-desc"> <div class="banner-block-desc">
已支持 已支持
<CountTo :end="surveyStats.user_count" :use-comma="true" :key="surveyStats.user_count" /> <CountTo
:end="surveyStats.user_count"
:use-comma="true"
:key="surveyStats.user_count"
/>
用户 | 发起 用户 | 发起
<CountTo :end="surveyStats.survey_count" :use-comma="true" /> <CountTo :end="surveyStats.survey_count" :use-comma="true" />
次调研 | 有效回收 次调研 | 有效回收
@@ -18,12 +22,16 @@
</div> </div>
</div> </div>
<!-- 动态 Banner 列表 --> <!-- 动态 Banner 列表 -->
<div v-for="(item, index) in bannerList" :key="index" class="swiper-slide banner-content" <div
:style="{ backgroundImage: 'url(' + item.banner_address + ')' }"> v-for="(item, index) in bannerList"
<p class="banner-content-title" :class="{ 'white': index === 0 }"> :key="index"
class="swiper-slide banner-content"
:style="{ backgroundImage: 'url(' + item.banner_address + ')' }"
>
<p class="banner-content-title" :class="{ white: index === 0 }">
{{ item.title }} {{ item.title }}
</p> </p>
<p class="banner-content-desc" :class="{ 'white': index === 0 }"> <p class="banner-content-desc" :class="{ white: index === 0 }">
{{ item.synopsis }} {{ item.synopsis }}
</p> </p>
<p v-if="index === 0" class="banner-content-btn" @click="toBannerDetail(item)"> <p v-if="index === 0" class="banner-content-btn" @click="toBannerDetail(item)">
@@ -34,16 +42,25 @@
<!-- 左右按钮 --> <!-- 左右按钮 -->
<div class="custom-swiper-button-prev" ref="prevBtn" @click="goPre"> <div class="custom-swiper-button-prev" ref="prevBtn" @click="goPre">
<img src="@/assets/img/home/arrow-act.png" alt="上一张" style="transform: rotate(180deg)"> <img
src="@/assets/img/home/arrow-act.png"
alt="上一张"
style="transform: rotate(180deg)"
/>
</div> </div>
<div class="custom-swiper-button-next" ref="nextBtn" @click="goNext"> <div class="custom-swiper-button-next" ref="nextBtn" @click="goNext">
<img src="@/assets/img/home/arrow-act.png" alt="下一张"> <img src="@/assets/img/home/arrow-act.png" alt="下一张" />
</div> </div>
<!-- 分页器 --> <!-- 分页器 -->
<div class="custom-pagination"> <div class="custom-pagination">
<span v-for="(item, index) in 3" :key="'dot' + index" class="custom-pagination-bullet" <span
:class="{ 'active': activeIndex === index }" @click="goToSlide(index)"></span> v-for="(item, index) in 3"
:key="'dot' + index"
class="custom-pagination-bullet"
:class="{ active: activeIndex === index }"
@click="goToSlide(index)"
></span>
</div> </div>
</div> </div>
</div> </div>
@@ -62,18 +79,19 @@ import { useRouter } from 'vue-router';
import CountTo from '@/components/CountTo.vue'; import CountTo from '@/components/CountTo.vue';
import { getBannerList, getDynamicDataStatistics, getQuestionnaireStatistics } from '@/api/home'; import { getBannerList, getDynamicDataStatistics, getQuestionnaireStatistics } from '@/api/home';
import Charts from './Charts.vue'; import Charts from './Charts.vue';
import { sensors, sensorsTrack } from '@/utils/plugins/sa';
const router = useRouter() const router = useRouter();
// 必须注册模块 // 必须注册模块
Swiper.use([Autoplay]) Swiper.use([Autoplay]);
const swiperContainer = ref(null); const swiperContainer = ref(null);
let bannerSwiper = null let bannerSwiper = null;
const activeIndex = ref(0) const activeIndex = ref(0);
const prevBtn = ref(null) const prevBtn = ref(null);
const nextBtn = ref(null) const nextBtn = ref(null);
// 数据部分 // 数据部分
const surveyStats = ref({}) const surveyStats = ref({});
const surveyData = ref({ const surveyData = ref({
survey_count: 0, survey_count: 0,
survey_count_collect: 0, survey_count_collect: 0,
@@ -82,25 +100,24 @@ const surveyData = ref({
survey_count_edit_ratio: 0, survey_count_edit_ratio: 0,
survey_count_end: 0, survey_count_end: 0,
survey_count_end_ratio: 0 survey_count_end_ratio: 0
}) });
const bannerList = ref([]) const bannerList = ref([]);
const sensors = inject('sensors')
// 获取数据 // 获取数据
const getBannerData = async () => { const getBannerData = async () => {
const res = await getBannerList() const res = await getBannerList();
bannerList.value = res.data.banner_list bannerList.value = res.data.banner_list;
} };
const getStatics = async () => { const getStatics = async () => {
const res = await getDynamicDataStatistics() const res = await getDynamicDataStatistics();
surveyStats.value = res.data surveyStats.value = res.data;
} };
const getQuesStatics = async () => { const getQuesStatics = async () => {
const res = await getQuestionnaireStatistics() const res = await getQuestionnaireStatistics();
surveyData.value = res.data surveyData.value = res.data;
} };
// function readyLoop(){ // function readyLoop(){
// initSwiper(true) // initSwiper(true)
@@ -141,12 +158,12 @@ const initSwiper = (loop = false) => {
on: { on: {
slideChange: () => { slideChange: () => {
if (bannerSwiper) { if (bannerSwiper) {
activeIndex.value = bannerSwiper.realIndex activeIndex.value = bannerSwiper.realIndex;
} }
}, }
}, }
}) });
} };
const goPre = () => { const goPre = () => {
if (bannerSwiper) { if (bannerSwiper) {
@@ -163,50 +180,44 @@ const goNext = () => {
const goToSlide = (index) => { const goToSlide = (index) => {
if (bannerSwiper) { if (bannerSwiper) {
// 如果使用 loop: true则需用 slideToLoop // 如果使用 loop: true则需用 slideToLoop
bannerSwiper.slideToLoop(index) bannerSwiper.slideToLoop(index);
activeIndex.value = index activeIndex.value = index;
} }
} };
// 方法 // 方法
const toBannerDetail = (item) => { const toBannerDetail = (item) => {
// 神策埋点 // 神策埋点
saTrack(item) saTrack(item);
router.push({ router.push({
path: '/home/bannerDetail', path: '/home/bannerDetail',
query: { query: {
code: item.code code: item.code
} }
}) });
} };
onMounted(async () => { onMounted(async () => {
await getBannerData() await getBannerData();
await getStatics() await getStatics();
await getQuesStatics() await getQuesStatics();
initSwiper() initSwiper();
}) });
onBeforeUnmount(() => { onBeforeUnmount(() => {
if (bannerSwiper) { if (bannerSwiper) {
bannerSwiper.destroy() bannerSwiper.destroy();
bannerSwiper = null bannerSwiper = null;
} }
}) });
function saTrack(record) { function saTrack(record) {
const config = { const properties = {
eventName: "ClickBanner", page_name: 'PC首页',
properties: { model_name: '轮播图',
page: "首页", button_name: `${record.title}`
module: "Banner", };
position: "查看详情", sensorsTrack(properties);
title: record.code,
clickTime: new Date().toLocaleString().toString()
}
}
sensors.track(config.eventName, config.properties);
} }
</script> </script>
@@ -237,7 +248,7 @@ function saTrack(record) {
height: 100%; height: 100%;
.banner-block { .banner-block {
background-image: url("../../../assets/img/home/banner.png"); background-image: url('../../../assets/img/home/banner.png');
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 100% 100%; background-size: 100% 100%;
width: 100%; width: 100%;
@@ -252,7 +263,7 @@ function saTrack(record) {
left: calc(16%); left: calc(16%);
font-weight: bold; font-weight: bold;
font-size: 30px; font-size: 30px;
color: #1F1E64; color: #1f1e64;
line-height: 32px; line-height: 32px;
} }
@@ -261,7 +272,7 @@ function saTrack(record) {
top: calc(54%); top: calc(54%);
left: calc(4.4%); left: calc(4.4%);
font-size: 17px; font-size: 17px;
color: #696C9F; color: #696c9f;
letter-spacing: 2px; letter-spacing: 2px;
font-weight: bold; font-weight: bold;
@@ -269,7 +280,7 @@ function saTrack(record) {
background: #fff; background: #fff;
border: 1px solid rgba(31, 30, 100, 0.55); border: 1px solid rgba(31, 30, 100, 0.55);
font-size: 16px; font-size: 16px;
color: #1F1E64; color: #1f1e64;
line-height: 23px; line-height: 23px;
text-align: left; text-align: left;
font-style: normal; font-style: normal;
@@ -457,7 +468,7 @@ function saTrack(record) {
border: none; border: none;
display: block; display: block;
//opacity: .48; //opacity: .48;
background-color: #8B97C3; background-color: #8b97c3;
width: 6px; width: 6px;
height: 6px; height: 6px;
border-radius: 50%; border-radius: 50%;
@@ -469,7 +480,7 @@ function saTrack(record) {
border: none; border: none;
display: block; display: block;
//opacity: .48; //opacity: .48;
background-color: #F5F6F9; background-color: #f5f6f9;
width: 18px; width: 18px;
height: 6px; height: 6px;
border-radius: 10px; border-radius: 10px;

View File

@@ -15,6 +15,7 @@
</template> </template>
<script setup> <script setup>
import { sensorsTrack } from '@/utils/plugins/sa';
import { ref, inject } from 'vue' import { ref, inject } from 'vue'
const hoverIndex = ref(-1); const hoverIndex = ref(-1);
const { model,index } = defineProps({ const { model,index } = defineProps({
@@ -28,7 +29,6 @@ const { model,index } = defineProps({
}) })
const emit = defineEmits(['open']) const emit = defineEmits(['open'])
const sensors = inject('sensors')
const getText = (model, index) => { const getText = (model, index) => {
if (hoverIndex.value === index) { if (hoverIndex.value === index) {
return model.sort === 103 ? "敬请期待" : "去查看"; return model.sort === 103 ? "敬请期待" : "去查看";
@@ -38,21 +38,16 @@ const getText = (model, index) => {
function handleModelClick() { function handleModelClick() {
emit('open') emit('open')
console.log(model);
saTrack(model) saTrack(model)
function saTrack(record) { function saTrack(record) {
const config = { const properties = {
eventName: "IntroduceModel", page_name: 'PC首页',
properties: { model_name: '调研类型模块',
page: "首页", button_name: `${record.title}`
module: "模型介绍", };
position: record.title,
buttonName: "去查看", sensorsTrack(properties)
clickTime: new Date().toLocaleString().toString()
}
}
sensors.track(config.eventName, config.properties);
} }
} }
</script> </script>

View File

@@ -73,6 +73,7 @@ import 'swiper/swiper-bundle.css';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { getQueryUserSurvey } from '@/api/home'; import { getQueryUserSurvey } from '@/api/home';
import { message } from 'ant-design-vue'; import { message } from 'ant-design-vue';
import { sensorsTrack } from '@/utils/plugins/sa';
const router = useRouter(); const router = useRouter();
const emit = defineEmits(['create-survey']); const emit = defineEmits(['create-survey']);
@@ -124,8 +125,6 @@ const operatingList = [
key: 'particulars' key: 'particulars'
}] }]
const sensors = inject('sensors')
const goPre = () => { const goPre = () => {
pauseCurrentVideo(); pauseCurrentVideo();
if (mySwiper) { if (mySwiper) {
@@ -188,20 +187,13 @@ const toSurveyInfo = async (item, index) => {
} }
} }
function saTrack(record, index) { function saTrack(_, index) {
const operates = ["创建", "设计","投放","分析"] const operates = ["创建", "设计","投放","分析"]
// 操作引导埋点 sensorsTrack({
const config = { page_name: 'PC首页',
eventName: "OperatingGuide", model_name: '操作指引',
properties: { button_name: operates[index]+"问卷"
page: "首页", });
module: "操作指引",
position: operates[index]+"问卷",
buttonName: "立即体验",
clickTime: new Date().toLocaleString().toString()
}
}
sensors.track(config.eventName, config.properties);
} }
} }

View File

@@ -1,5 +1,5 @@
<template> <template>
<div class="scene-container "> <div class="scene-container">
<div class="flex"> <div class="flex">
<p></p> <p></p>
<p class="fw-bold fs-24 align--center scene-title">从场景出发满足你的各类调研需求</p> <p class="fw-bold fs-24 align--center scene-title">从场景出发满足你的各类调研需求</p>
@@ -7,33 +7,47 @@
</div> </div>
<div class="flex mt20 sceneList"> <div class="flex mt20 sceneList">
<div v-for="(scene, index) in sceneList" :key="index" class="sceneItem" <div
:class="{ 'fix-scene': [0, 1, 2].includes(index) }" @click="createScene(scene, index)"> v-for="(scene, index) in sceneList"
:key="index"
class="sceneItem"
:class="{ 'fix-scene': [0, 1, 2].includes(index) }"
@click="createScene(scene, index)"
>
<div class="flex-start"> <div class="flex-start">
<img :src="scene.image" alt="" style="width: 28px;"> <img :src="scene.image" alt="" style="width: 28px" />
<p class="sceneItem-title" :class="{ 'sceneItem-title-color': index === 0 }">{{ scene.title }}</p> <p class="sceneItem-title" :class="{ 'sceneItem-title-color': index === 0 }">
{{ scene.title }}
</p>
</div> </div>
<p class="sceneItem-desc" :style="{ 'minHeight': index === 0 ? 'auto' : '30px' }">{{ scene.description }}</p> <p class="sceneItem-desc" :style="{ minHeight: index === 0 ? 'auto' : '30px' }">
{{ scene.description }}
</p>
<div style="text-align: left"> <div style="text-align: left">
<a-button v-if="index === 0" class="createBtn" type="primary"> <a-button v-if="index === 0" class="createBtn" type="primary"> 立即创建 </a-button>
立即创建
</a-button>
<div v-else> <div v-else>
<a-button class="custom-button toCreate" :class="{ <a-button
'createG': [0, 1, 2].includes(index), class="custom-button toCreate"
'create-normal': [11, 13, 15, 16, 17].includes(scene.code) :class="{
}" type="text"> createG: [0, 1, 2].includes(index),
'create-normal': [11, 13, 15, 16, 17].includes(scene.code)
}"
type="text"
>
<span>去创建</span> <span>去创建</span>
<!-- 'normal':[11,13,15,16,17].includes(scene.code)--> <!-- 'normal':[11,13,15,16,17].includes(scene.code)-->
<img src="@/assets/img/home/tob.png" alt="" <img
v-if="[0, 1, 2].includes(index) || [11, 13, 15, 16, 17].includes(scene.code)" /> src="@/assets/img/home/tob.png"
alt=""
v-if="[0, 1, 2].includes(index) || [11, 13, 15, 16, 17].includes(scene.code)"
/>
<img src="@/assets/img/home/tog.png" alt="" v-else /> <img src="@/assets/img/home/tog.png" alt="" v-else />
</a-button> </a-button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<create ref="createRef" style="width: 1px;height: 0" @update:ai-assistant-visible="getValue"> <create ref="createRef" style="width: 1px; height: 0" @update:ai-assistant-visible="getValue">
</create> </create>
<!-- 概念测试 --> <!-- 概念测试 -->
@@ -45,22 +59,23 @@
<script setup> <script setup>
import { onMounted, ref, inject } from 'vue'; import { onMounted, ref, inject } from 'vue';
import create from '@/views/ProjectManage/create/Index.vue' import create from '@/views/ProjectManage/create/Index.vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { getSceneListHome } from '@/api/home'; import { getSceneListHome } from '@/api/home';
import deep from '@/assets/img/home/deep.png' import deep from '@/assets/img/home/deep.png';
import quickImport from '@/assets/img/home/quickImport.png' import quickImport from '@/assets/img/home/quickImport.png';
import whiteCreate from '@/assets/img/home/whiteCreate.png' import whiteCreate from '@/assets/img/home/whiteCreate.png';
import ConceptTest from '@/views/ProjectManage/create/presets/concept/ConceptTest.vue'; import ConceptTest from '@/views/ProjectManage/create/presets/concept/ConceptTest.vue';
import PackageTest from '@/views/ProjectManage/create/presets/package/PackageTest.vue'; import PackageTest from '@/views/ProjectManage/create/presets/package/PackageTest.vue';
import TasteTest from '@/views/ProjectManage/create/presets/taste/TasteTest.vue'; import TasteTest from '@/views/ProjectManage/create/presets/taste/TasteTest.vue';
import { Modal } from 'ant-design-vue'; import { Modal } from 'ant-design-vue';
import { currentMode } from '@/config'; import { currentMode } from '@/config';
import { sensorsTrack } from '@/utils/plugins/sa';
const router = useRouter() const router = useRouter();
const conceptTestRef = ref(null); const conceptTestRef = ref(null);
const tasteTestRef = ref(null) const tasteTestRef = ref(null);
const packageTestRef = ref(null) const packageTestRef = ref(null);
// const // const
const fixedSceneList = [ const fixedSceneList = [
{ {
@@ -80,27 +95,26 @@ const fixedSceneList = [
description: '点击创建新的空白问卷,自定义编辑内容', description: '点击创建新的空白问卷,自定义编辑内容',
image: whiteCreate, image: whiteCreate,
value: 3 value: 3
}, }
] ];
const sceneList = ref([]) const sceneList = ref([]);
// ref声明需与组件ref属性值一致 // ref声明需与组件ref属性值一致
const createRef = ref() const createRef = ref();
const sensors = inject('sensors')
onMounted(() => { onMounted(() => {
getSceneList() getSceneList();
}) });
const toModels = () => { const toModels = () => {
router.push({ router.push({
path: '/market' path: '/market'
}); });
} };
const getSceneList = () => { const getSceneList = () => {
getSceneListHome().then(res => { getSceneListHome().then((res) => {
sceneList.value = [] sceneList.value = [];
sceneList.value = fixedSceneList.concat(res.data.items) sceneList.value = fixedSceneList.concat(res.data.items);
}) });
} };
/** /**
* 创建问卷 * 创建问卷
* @param record * @param record
@@ -108,13 +122,13 @@ const getSceneList = () => {
*/ */
const createScene = (record, index) => { const createScene = (record, index) => {
// 调用神策埋点 // 调用神策埋点
saTrack(record, index) saTrack(record, index);
if ([0, 1, 2].includes(index)) { if ([0, 1, 2].includes(index)) {
if (createRef.value) { if (createRef.value) {
// 检查 record 是否有 value 属性,如果没有则直接使用 record // 检查 record 是否有 value 属性,如果没有则直接使用 record
const sceneData = record.value !== undefined ? record.value : record; const sceneData = record.value !== undefined ? record.value : record;
createRef.value.createCustom(sceneData) createRef.value.createCustom(sceneData);
} }
} else if ([22, 36, 37, 38].includes(record.code)) { } else if ([22, 36, 37, 38].includes(record.code)) {
return conceptTestRef.value.openModal({ return conceptTestRef.value.openModal({
@@ -136,7 +150,7 @@ const createScene = (record, index) => {
}); });
} else if ([11, 13, 15, 16, 17, 27, 45, 46].includes(record.code)) { } else if ([11, 13, 15, 16, 17, 27, 45, 46].includes(record.code)) {
if (createRef.value) { if (createRef.value) {
createRef.value.createNormalSurvey(record) createRef.value.createNormalSurvey(record);
} }
} else { } else {
Modal.confirm({ Modal.confirm({
@@ -166,22 +180,28 @@ const createScene = (record, index) => {
} }
}); });
} }
} };
function saTrack(record,index) { function saTrack(record, index) {
const config = { // const config = {
eventName: "SurveyCreate", // eventName: 'SurveyCreate',
properties: { // properties: {
page: "首页", // page: '首页',
module: "创建问卷", // module: '创建问卷',
// 排除智能创建、快捷导入、空白创建,其他都是模板创建 // // 排除智能创建、快捷导入、空白创建,其他都是模板创建
position: [0,1,2].includes(index) ? record.title: `模板创建-${record.title}`, // position: [0, 1, 2].includes(index) ? record.title : `模板创建-${record.title}`,
// 第一个默认是智能创建 // // 第一个默认是智能创建
buttonName: index === 0 ? "立即创建" : "去创建", // buttonName: index === 0 ? '立即创建' : '去创建',
clickTime: new Date().toLocaleString().toString() // clickTime: new Date().toLocaleString().toString()
} // }
} // };
sensors.track(config.eventName, config.properties); const properties = {
page_name: 'PC首页',
model_name: '调研类型模块',
button_name: `${record.title}`
};
sensorsTrack(properties);
} }
/** /**
@@ -190,21 +210,21 @@ function saTrack(record,index) {
*/ */
const getValue = (val) => { const getValue = (val) => {
// 获取元素并转换为数组 // 获取元素并转换为数组
const containers = Array.from(document.getElementsByClassName('el-carousel__container')) const containers = Array.from(document.getElementsByClassName('el-carousel__container'));
const indicators = Array.from(document.getElementsByClassName('el-carousel__indicators')) const indicators = Array.from(document.getElementsByClassName('el-carousel__indicators'));
const allElements = [...containers, ...indicators] const allElements = [...containers, ...indicators];
// allElements.forEach(item => { // allElements.forEach(item => {
// if (item) { // if (item) {
// item.style.zIndex = val ? '-1' : 'unset' // item.style.zIndex = val ? '-1' : 'unset'
// } // }
// }) // })
} };
// 使用 defineExpose 显式暴露方法,使其可以被外部组件通过 ref 访问 // 使用 defineExpose 显式暴露方法,使其可以被外部组件通过 ref 访问
defineExpose({ defineExpose({
createScene createScene
}) });
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@@ -219,11 +239,10 @@ p {
.scene-title { .scene-title {
margin: 32px 0 26px 4vw; margin: 32px 0 26px 4vw;
} }
.more { .more {
color: #70B937; color: #70b937;
cursor: pointer; cursor: pointer;
} }
@@ -245,7 +264,7 @@ p {
min-height: 125px; min-height: 125px;
margin-right: 10px; margin-right: 10px;
background: #fff; background: #fff;
border: 1px solid #EBEBEB; border: 1px solid #ebebeb;
} }
.sceneItem-title { .sceneItem-title {
@@ -256,23 +275,23 @@ p {
} }
.sceneItem-title-color { .sceneItem-title-color {
background: linear-gradient(135deg, #C352E7, #3962FF); background: linear-gradient(135deg, #c352e7, #3962ff);
background-clip: text; background-clip: text;
color: transparent; color: transparent;
} }
.sceneItem-desc { .sceneItem-desc {
font-size: 10px; font-size: 10px;
color: #7F7F7F; color: #7f7f7f;
text-align: left; text-align: left;
margin-top: 10px; margin-top: 10px;
text-wrap: wrap; text-wrap: wrap;
min-height: 30px min-height: 30px;
} }
.fix-scene { .fix-scene {
border: 1px solid rgba(98, 93, 248, 0.5); border: 1px solid rgba(98, 93, 248, 0.5);
background-image: url("../../../assets/img/home/sceneBg.png"); background-image: url('../../../assets/img/home/sceneBg.png');
background-size: 100% 100%; background-size: 100% 100%;
} }
@@ -282,7 +301,7 @@ p {
} }
.createBtn { .createBtn {
background-image: url("../../../assets/img/home/createbtn.png"); background-image: url('../../../assets/img/home/createbtn.png');
background-size: 100% 100%; background-size: 100% 100%;
background-color: transparent; background-color: transparent;
border: none; border: none;
@@ -301,7 +320,7 @@ p {
} }
.createG { .createG {
color: #5562FB !important; color: #5562fb !important;
} }
.create-normal { .create-normal {
@@ -323,7 +342,7 @@ p {
} }
::-webkit-scrollbar-thumb { ::-webkit-scrollbar-thumb {
background: #DFE1E7; background: #dfe1e7;
/* 滚动条滑块颜色 */ /* 滚动条滑块颜色 */
border-radius: 4px; border-radius: 4px;
/* 滑块圆角 */ /* 滑块圆角 */