8 Commits

Author SHA1 Message Date
9c83a47260 feat: 组件01 2026-05-09 23:58:47 +08:00
255b40aad7 feat: 更新一些配置 2026-05-08 16:52:07 +08:00
25c8a3570d feat: 增加获取位置的方法 2026-05-08 14:58:13 +08:00
a3c82382c2 feat: 通知详情的页面调整 2026-05-08 12:52:03 +08:00
42e0e4920f feat; 消息与天气接口对接 2026-05-07 17:16:45 +08:00
9455beec4d feat: 重新yarn 安装了一下 2026-05-07 15:14:13 +08:00
3a5fa0b7d2 feat: 调整头图的高度 2026-04-30 14:02:26 +08:00
af7366f32b feat: 头图的调整 2026-04-30 12:09:17 +08:00
19 changed files with 723 additions and 2259 deletions

View File

@@ -74,5 +74,6 @@
"@vue/tsconfig": "^0.1.3",
"sass": "1.58.3",
"vite": "5.2.8"
}
},
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
}

View File

@@ -1,15 +1,20 @@
{
"name": "YGTianmuCS",
"appid": "__UNI__BB03E8A",
"name" : "YGChatCS",
"appid" : "__UNI__38F74B8",
"description" : "",
"versionName" : "1.0.0",
"versionCode" : "100",
"transformPx" : false,
/* 5+App */
"app-plus" : {
"usingComponents" : true,
"nvueStyleCompiler" : "uni-app",
"compilerVersion" : 3,
"optimization" : {
"subPackages" : true
},
"compatible" : {
"ignoreVersion" : true
},
"splashscreen" : {
"alwaysShowBeforeRender" : true,
"waiting" : true,
@@ -18,14 +23,11 @@
},
"safearea" : {
"bottom" : {
"offset": "auto" // 自动适配安全区域
"offset" : "auto"
}
},
/* */
"modules" : {},
/* */
"distribute" : {
/* android */
"android" : {
"permissions" : [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
@@ -45,20 +47,13 @@
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
},
/* ios */
"ios" : {},
/* SDK */
"sdkConfigs" : {
"oauth" : {}
}
}
},
/* */
"quickapp" : {},
/* project.config.json
wx5e79df5996572539
wx23f86d809ae80259
*/
"mp-weixin" : {
"appid" : "wx5e79df5996572539",
"setting" : {
@@ -105,5 +100,6 @@
"devServer" : {
"https" : false
}
}
},
"fallbackLocale" : "zh-Hans"
}

View File

@@ -38,6 +38,12 @@
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/ChatMain/NoticeMessage/detail",
"style": {
"navigationStyle": "custom"
}
}
],
"subPackages": [

View File

@@ -9,8 +9,8 @@
</view>
<view class="relative">
<image class="w-full block" src="https://images.unsplash.com/photo-1506744038136-46273834b3fb?w=800&q=80"
mode="widthFix" />
<image class="w-full block" :src="mainPageDataModel?.initPageImages?.backgroundImageUrl"
mode="aspectFill" style="height: 252px;" />
<view class="absolute bottom-0 left-0 right-0 flex-full">
<view class="px-12 pt-12">
<HomeWelcome :mainPageDataModel="mainPageDataModel" />
@@ -92,14 +92,21 @@
item.toolCall.componentName === CompName.mapCard
"
/>
<GeneratorPhotoComponent
<!-- <GeneratorPhotoComponent
v-else-if="
item.toolCall &&
item.toolCall.componentName ===
CompName.aigcPhotoGeneratorCard
"
:toolCall="item.toolCall"
/> -->
<ZModuleC01
v-else-if="
item.toolCall &&
item.toolCall.componentName === CompName.aigcPhotoGeneratorCard
"
/>
<Feedback
v-else-if="
item.toolCall &&
@@ -204,8 +211,6 @@ import HomeWelcome from "../HomeWelcome/index.vue";
import AiTabSwitch from "@/components/AiTabSwitch/index.vue";
import Discovery from "../../Discovery/index.vue";
import ChatTopWelcome from "../ChatTopWelcome/index.vue";
import NoticeMessage from "../NoticeMessage/index.vue";
import ChatTopNavBar from "../ChatTopNavBar/index.vue";
import ChatCardAI from "../ChatCardAi/index.vue";
import ChatCardMine from "../ChatCardMine/index.vue";
@@ -223,6 +228,8 @@ import OpenMapComponent from "../../ChatModule/OpenMapComponent/index.vue";
import AnswerComponent from "../../ChatModule/AnswerComponent/index.vue";
import GeneratorPhotoComponent from "../../ChatModule/GeneratorPhotoComponent/index.vue";
import ZModuleC01 from "../../ChatModule/ZModuleC01/index.vue";
import CreateServiceOrder from "@/components/CreateServiceOrder/index.vue";
import Feedback from "@/components/Feedback/index.vue";
import AddCarCrad from "@/components/AddCarCrad/index.vue";

View File

@@ -7,58 +7,21 @@
<view class="flex flex-col flex-full min-width-0">
<view class="flex flex-row flex-items-center flex-justify-between min-width-0">
<text class="flex-full min-width-0 font-size-20 font-500 color-white ellipsis-1">{{ mainPageDataModel.welcomeContent }}</text>
<text class="flex-shrink-0 font-size-20 font-500 color-white mt-4"> 26°C </text>
<text class="flex-shrink-0 font-size-20 font-500 color-white mt-4"> {{ weatherText }} </text>
</view>
<swiper @change="onSwiperChange" class="swiper" circular :autoplay="autoplay" :interval="interval"
:duration="duration" :indicator-dots="false">
<swiper-item v-for="item in bannerList" :key="item.title">
<view class="swiper-item flex flex-col flex-items-start flex-justify-between px-10">
<text class="font-size-12 font-600 color-B45309">
{{ item.title }}
</text>
<view class="flex flex-row flex-justify-between">
<text class="font-size-10 font-500 color-D97706">
发布时间{{ item.time }}
</text>
<text class="font-size-10 font-500 color-B45309 underline-text">
详情
</text>
</view>
</view>
</swiper-item>
</swiper>
<yo-indicator-dot :current-index="currentIndex" :length="bannerList.length" duration="0.5" default-width="4px"
active-width="16px" dot-height="4px" shape="circle" default-color="rgba(255,255,255,0.5)"
active-color="rgba(255,255,255,1)" />
<NoticeMessage />
</view>
</view>
</template>
<script setup>
import { ref } from "vue";
import { onMounted, ref } from "vue";
import { defineProps, computed } from "vue";
import SpriteAnimator from "@/components/Sprite/SpriteAnimator.vue";
import NoticeMessage from "../NoticeMessage/index.vue";
import { getLocalWeather } from "@/request/api/MainPageDataApi";
const autoplay = ref(true);
const interval = ref(7000);
const duration = ref(500);
const currentIndex = ref(0);
const bannerList = ref([
{
title: "小七欢迎你~",
time: "2025年7月12日 09:30",
},
{
title: "小8欢迎你",
time: "2025年7月13日 09:30",
},
{
title: "小9欢迎你",
time: "2025年7月15日 09:30",
},
]);
const weatherText = ref("26°C ☀️");
const props = defineProps({
mainPageDataModel: {
@@ -92,29 +55,18 @@ const spriteStyle = computed(() => {
};
});
const onSwiperChange = (e) => {
currentIndex.value = e.detail.current;
};
const getLocalWeatherData = async () => {
const res = await getLocalWeather();
if (res && res.code === 0) {
const { temperature, weather } = res.data;
weatherText.value = `${temperature}°C ${weather}`;
}
}
onMounted(() => {
getLocalWeatherData();
});
</script>
<style scoped>
.swiper {
height: 50px;
margin-top: 8px;
}
.swiper-item {
display: block;
height: 46px;
background: #fffbeb;
box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.05);
border-radius: 12px;
border: 2px solid #fef3c7;
}
.underline-text {
text-decoration: underline;
text-decoration-color: #b45309;
}
</style>
<style scoped></style>

View File

@@ -0,0 +1,77 @@
<template>
<view class="flex flex-col bg-liner h-screen overflow-hidden">
<!-- 顶部固定导航 -->
<view class="flex-shrink-0">
<TopNavBar :title="detailTitle" background="transparent" />
</view>
<!-- 滚动区域 -->
<scroll-view class="flex-full overflow-hidden" scroll-y >
<view class="pb-24 border-box overflow-hidden">
<image v-if="coverImage" class="w-full block" :src="coverImage" mode="aspectFill" />
<view class="pt-16 px-12 pb-24 border-box">
<view class="color-171717 font-size-16 font-weight-600">{{ detailTitle }}</view>
<view v-if="publishTime" class="notice-time-tag flex flex-row flex-items-center mt-16">
<uni-icons type="clock" size="18" color="#5A6780" />
<text class="color-171717 font-size-12 font-weight-600 ml-8">发布时间{{ publishTime }}</text>
</view>
<view class="mt-16 mx-12 bg-gray w-full height-1"></view>
<view class="mt-16 color-666 font-size-14 line-height-20">{{ noticeContent }}</view>
</view>
</view>
</scroll-view>
</view>
</template>
<script setup>
import TopNavBar from "@/components/TopNavBar/index.vue";
import { computed, ref } from "vue";
import { onLoad } from "@dcloudio/uni-app";
const noticeData = ref({});
const detailTitle = computed(() => {
return noticeData.value.entityName?.trim() || "消息详情";
});
const publishTime = computed(() => {
return noticeData.value.effectiveStartTime?.trim();
});
const coverImage = computed(() => {
return noticeData.value.eventImage?.trim();
});
const noticeContent = computed(() => {
return noticeData.value.eventDescription?.trim();
});
onLoad((query = {}) => {
if (query.noticeData) {
try {
noticeData.value = JSON.parse(decodeURIComponent(query.noticeData));
} catch (error) {
console.warn("noticeData parse failed:", error);
}
}
});
</script>
<style lang="scss" scoped>
.notice-time-tag {
display: inline-flex;
height: 28px;
padding: 6px 12px;
background: linear-gradient(180deg, #f4f7fb 0%, #e9eef6 100%);
border: 1px solid #d6dde8;
border-radius: 14px;
box-sizing: border-box;
}
</style>

View File

@@ -1,40 +1,100 @@
<template>
<view class="border-box pl-12 pr-12">
<view class="wrap rounded-20 bg-white relative overflow-hidden">
<view class="flex flex-col p-16 mr-110 border-box">
<view class="flex flex-row flex-items-center justify-center">
<view class="w-24 h-24 rounded-full bg-theme-color-500 flex flex-items-center flex-justify-center">
<uni-icons type="sound" size="16" color="#ffffff"/>
<view >
<swiper @change="onSwiperChange" class="swiper" circular :autoplay="autoplay" :interval="interval"
:duration="duration" :indicator-dots="false">
<swiper-item v-for="item in bannerList" :key="item.entityName">
<view class="swiper-item flex flex-col flex-items-start flex-justify-between px-10" @click="clickItem(item)">
<text class="font-size-12 font-600 color-B45309">
{{ item.entityName }}
</text>
<view class="flex flex-row flex-justify-between">
<text class="font-size-10 font-500 color-D97706">
发布时间{{ item.effectiveStartTime }}
</text>
<text class="font-size-10 font-500 color-B45309 underline-text">
详情
</text>
</view>
<text class="font-size-16 font-500 text-color-900 ml-6">临时提醒</text>
</view>
<view class="font-size-12 font-color-600 mt-8">{{ props.noticeContent.eventMessageContent }}</view>
</view>
<image class="mt-4 object-cover absolute right-0 bottom-0 bg-image" src="./notice_bg_img.png"/>
</view>
</swiper-item>
</swiper>
<yo-indicator-dot :current-index="currentIndex" :length="bannerList.length" duration="0.5" default-width="4px"
active-width="16px" dot-height="4px" shape="circle" default-color="rgba(255,255,255,0.5)"
active-color="rgba(255,255,255,1)" />
</view>
</template>
<script setup>
import { defineProps } from "vue";
import { onMounted, ref } from "vue";
import { getTimeNoticeList } from "@/request/api/MainPageDataApi";
const props = defineProps({
noticeContent: {
type: Object,
default: () => ({}),
const autoplay = ref(true);
const interval = ref(7000);
const duration = ref(500);
const currentIndex = ref(0);
// const bannerList = ref([]);
const bannerList = ref([
{
entityName: "小七欢迎你~",
effectiveStartTime: "2025年7月12日 09:30",
},
{
entityName: "小8欢迎你",
effectiveStartTime: "2025年7月13日 09:30",
},
{
entityName: "小9欢迎你",
effectiveStartTime: "2025年7月15日 09:30",
},
]);
const onSwiperChange = (e) => {
currentIndex.value = e.detail.current;
};
const getTimeNoticeListData = async () => {
const res = await getTimeNoticeList();
if (res && res.code === 0) {
bannerList.value = res.data;
}
}
onMounted(() => {
getTimeNoticeListData();
});
const clickItem = (item) => {
uni.navigateTo({
url: `/pages/ChatMain/NoticeMessage/detail?noticeData=${encodeURIComponent(JSON.stringify(item))}`
});
}
</script>
<style lang="scss" scoped>
.bg-image {
width: 140px;
height: 96px;
.swiper {
height: 50px;
margin-top: 8px;
}
.mr-110 {
margin-right: 110px;
.swiper-item {
display: block;
height: 46px;
background: #fffbeb;
box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.05);
border-radius: 12px;
border: 2px solid #fef3c7;
}
.underline-text {
text-decoration: underline;
text-decoration-color: #b45309;
}
</style>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 178 KiB

View File

@@ -0,0 +1,21 @@
<template>
<view class="container w-full border-box border-ff overflow-hidden rounded-24 flex flex-col">
<!-- 占位撑开 -->
<view class="w-vw"></view>
<view class="flex flex-col m-4 border-box rounded-24">
<slot name="content"></slot>
</view>
</view>
</template>
<script setup>
</script>
<style scoped>
.container {
background: rgba(255, 255, 255, 0.2);
box-shadow: 0px 9px 34px 0px rgba(27, 9, 91, 0.07);
}
</style>

View File

@@ -0,0 +1,12 @@
<template>
<ZModuleBase>
<template #content >
灌灌灌灌灌滚滚滚
</template>
</ZModuleBase>
</template>
<script setup>
import ZModuleBase from "../ZModuleBase/index.vue";
</script>

View File

@@ -28,7 +28,7 @@
<view class="card-title ellipsis-1">
{{ slot.item.title }}
</view>
<view v-if="slot.item.subTitle" class="card-desc ellipsis-2">
<view v-if="slot.item.subTitle" class="card-desc ellipsis-1">
{{ slot.item.subTitle }}
</view>
</view>

View File

@@ -29,10 +29,12 @@ import CardSwiper from "./components/CardSwiper/index.vue";
import QuickQuestions from "./components/QuickQuestions/index.vue";
import discoveryCover from "@/components/ImageSwiper/images/2025-07-12_180248.jpg";
import { homeTabsData, homeTabContentData, homeQuickQuestionData } from "../../request/api/MainPageDataApi";
import { useAppStore } from "@/store";
import { homeTabsData, getNearbyTags, homeTabContentData, homeQuickQuestionData } from "../../request/api/MainPageDataApi";
import { useAppStore, useLocationStore } from "@/store";
import { JumpType } from "../../model/ChatModel";
const appStore = useAppStore();
const locationStore = useLocationStore();
/// 从个渠道获取如二维码
const sceneId = appStore.sceneId || "";
@@ -58,15 +60,20 @@ const queryTabsList = async () => {
}));
/// 设置tab数据
discoveryTabs.value = tabList;
/// 查询是否有sceneId参数
const activeTabIndex = discoveryTabs.value.findIndex((tab) => tab.id === sceneId);
/// 根据sceneId查询对应tab数据
findTabByIdWithActiveTabIndex(sceneId);
}
}
/// 根据id查询tab并设置activeIndex
const findTabByIdWithActiveTabIndex = (tabsId) => {
/// 查询是否有id参数
const activeTabIndex = discoveryTabs.value.findIndex((tab) => tab.id === tabsId);
/// 如果有则优先展示对应tab数据没有则展示第一个tab数据
if (activeTabIndex > -1) {
activeIndex.value = activeTabIndex;
queryDiscoveryData(sceneId);
queryDiscoveryData(tabsId);
} else {
if (discoveryTabs.value.length > 0) {
activeIndex.value = 0;
queryDiscoveryData(discoveryTabs.value[0].id);
}
@@ -145,10 +152,37 @@ const handleClick = async (item) => {
}
}
/// 获取位置信息
const getLocation = () => {
/// 已经有sceneId了说明之前已经获取过位置信息了就不需要再获取一次了
if (sceneId) return;
uni.getLocation({
type: 'wgs84',
success: function (res) {
// 将位置信息存储到 Pinia 中
locationStore.setLocationData({
latitude: res.latitude,
longitude: res.longitude,
});
console.log('当前位置:' + JSON.stringify(res));
getNearbyTagsData();
}
});
}
/// 获取附近标签数据
const getNearbyTagsData = async () => {
const res = await getNearbyTags();
if (res.code === 0) {
const nearbyTagId = res.data;
findTabByIdWithActiveTabIndex(nearbyTagId);
}
}
/// 组件挂载后请求数据
onMounted(() => {
queryTabsList();
getLocation();
});
</script>

View File

@@ -21,7 +21,7 @@
<script setup>
import { onLoad } from "@dcloudio/uni-app";
import { ref, onUnmounted } from "vue";
import { ref, onUnmounted, onMounted } from "vue";
import { getUrlParams } from "@/utils/UrlParams";
import { useAppStore } from "@/store";
import { checkToken } from "@/hooks/useGoLogin";
@@ -31,7 +31,7 @@ import DrawerSection from "../DrawerSection/index.vue";
import Calender from "@/components/Calender/index.vue";
const appStore = useAppStore();
const locationStore = useLocationStore();
const calendarVisible = ref(false);
const selectedDate = ref("");
@@ -52,14 +52,6 @@ uni.$on("openCalendar", () => {
calendarVisible.value = true;
});
const getWeixinMiniProgramParams = (e) => {
console.log("Params:", e);
if (e.q && e.q != "undefined") {
const qrUrl = decodeURIComponent(e.q); // 获取到二维码原始链接内容
const params = getUrlParams(qrUrl);
appStore.setSceneId(params.sceneId || params.tagId);
}
};
// 打开窗口
const drawerRef = ref(null);
@@ -68,19 +60,32 @@ const showDrawer = async (e) => {
drawerRef.value.open();
};
uni.$on("SHOW_DRAWER", showDrawer);
// 关闭窗口
const closeDrawer = (e) => drawerRef.value.close();
///获取到二维码原始链接内容
const getWeixinMiniProgramParams = (e) => {
console.log("Params:", e);
if (e.q && e.q != "undefined") {
const qrUrl = decodeURIComponent(e.q);
const params = getUrlParams(qrUrl);
appStore.setSceneId(params.sceneId || params.tagId);
}
};
onLoad((e) => {
getWeixinMiniProgramParams(e);
});
onMounted(() => {
});
onUnmounted(() => {
// uni.$off('openCalendar')
});
</script>
<style lang="scss" scoped>

View File

@@ -10,6 +10,21 @@ function homeTabContentData(args) {
return request.post("/hotelBiz/mainScene/queryContentListWithCache", args);
}
/// 获取距离用户最近的标签
function getNearbyTags(args) {
return request.get("/hotelBiz/mainScene/nearestTag", args);
}
/// 获取本地天气
function getLocalWeather(args) {
return request.get("/hotelBiz/mainScene/getLocalWeather", args);
}
/// 获取时间公告列表
function getTimeNoticeList(args) {
return request.get("/hotelBiz/mainScene/eventList", args);
}
/// 快速问题列表
function homeQuickQuestionData(args) {
return request.post("/hotelBiz/mainScene/queryQuickQuestionListWithCache", args);
@@ -34,6 +49,9 @@ function discoveryCradComponent() {
export {
homeTabsData,
homeTabContentData,
getNearbyTags,
getLocalWeather,
getTimeNoticeList,
homeQuickQuestionData,
mainPageData,
quickBookingComponent,

View File

@@ -1,14 +1,14 @@
import { getCurrentConfig } from "@/constant/base";
import { useAppStore } from "@/store";
import { useAppStore, useLocationStore } from "@/store";
import { NOTICE_EVENT_LOGOUT } from "@/constant/constant";
import { getAccessToken } from "@/constant/token";
import { getAccessToken, removeAccessToken } from "@/constant/token";
import { goLogin } from "../../hooks/useGoLogin";
const clientId = getCurrentConfig().clientId;
const defaultConfig = {
header: {
Authorization: "", // 可在此动态设置 token
"Content-Type": "application/json",
Authorization: "", // 可在此动态设置 token
clientId: clientId,
},
};
@@ -19,6 +19,17 @@ function request(url, args = {}, method = "POST", customConfig = {}) {
if (!/^http/.test(url)) {
url = appStore.serverConfig?.baseUrl + url;
}
// 获取位置信息并添加到请求头
const locationStore = useLocationStore();
if (locationStore.latitude && locationStore.longitude) {
customConfig.header = {
...customConfig.header,
"X-Latitude": locationStore.latitude,
"X-Longitude": locationStore.longitude
};
}
// 动态获取 token
const token = getAccessToken();

View File

@@ -6,6 +6,10 @@
height: 100%;
}
.h-1 {
height: 1px;
}
.h-8 {
height: 8px;
}

View File

@@ -1,5 +1,6 @@
import { useAppStore } from "./app";
import { useSelectedDateStore } from "./selectedDate";
import { usePictureStore } from "./picture";
import { useLocationStore } from "./location";
export { useAppStore, useSelectedDateStore, usePictureStore };
export { useAppStore, useSelectedDateStore, usePictureStore, useLocationStore };

View File

@@ -0,0 +1,19 @@
import { defineStore } from "pinia";
export const useLocationStore = defineStore("location", {
state() {
return {
latitude: 0, // 纬度
longitude: 0, // 经度
};
},
actions: {
setLocationData(data) {
this.latitude = data.latitude;
this.longitude = data.longitude;
},
},
unistorage: true,
});

2316
yarn.lock

File diff suppressed because it is too large Load Diff