refactor: update env configs, replace uni-ui and fix issues
- add VITE_CLIENT_ID environment variable to all .env files, adjust API and socket URLs across dev/staging/prod environments - update request utility to use env var for client ID instead of hardcoded "6" - refactor GoodDetail component: replace uni-icons with van-icon, switch markdown renderer to vue3-markdown-it - refactor Calendar component: swap uni-popup for van-popup, remove deprecated SCSS styles, update markup and toast calls - fix ImageSwiper: rename handler methods, update preview navigation to use vue router, remove redundant code - correct margin class syntax in goods index page
This commit is contained in:
@@ -9,3 +9,6 @@ VITE_API_TIMEOUT_MS = 10000
|
||||
|
||||
# Socket 基础 URL
|
||||
VITE_SOCKET_BASE_URL = "/ingress/agent/ws/chat"
|
||||
|
||||
# Client ID
|
||||
VITE_CLIENT_ID = "12"
|
||||
@@ -8,4 +8,7 @@ VITE_API_BASE_URL = 'https://biz.nianxx.cn'
|
||||
VITE_API_TIMEOUT_MS = 10000
|
||||
|
||||
# Socket 基础 URL
|
||||
VITE_SOCKET_BASE_URL = "wss://biz.nianxx.cn/ingress/agent/ws/chat"
|
||||
VITE_SOCKET_BASE_URL = "wss://biz.nianxx.cn/ingress/agent/ws/chat"
|
||||
|
||||
# Client ID
|
||||
VITE_CLIENT_ID = "12"
|
||||
@@ -2,10 +2,13 @@
|
||||
VITE_APP_ENV = 'staging'
|
||||
|
||||
# API 基础 URL
|
||||
VITE_API_BASE_URL = 'https://onefeel.brother7.cn/ingress'
|
||||
VITE_API_BASE_URL = 'https://abroadbiz.nianxx.com/ingress'
|
||||
|
||||
# API 请求超时时间(毫秒)
|
||||
VITE_API_TIMEOUT_MS = 10000
|
||||
|
||||
# Socket 基础 URL
|
||||
VITE_SOCKET_BASE_URL = "wss://onefeel.brother7.cn/ingress/agent/ws/chat"
|
||||
VITE_SOCKET_BASE_URL = "wss://abroadbiz.nianxx.com/ingress/agent/ws/chat"
|
||||
|
||||
# Client ID
|
||||
VITE_CLIENT_ID = "12"
|
||||
@@ -1,21 +1,22 @@
|
||||
<template>
|
||||
<uni-popup ref="popup" type="bottom" :safe-area="false" @maskClick="handleMaskClick">
|
||||
<van-popup ref="popup" position="bottom" @maskClick="handleMaskClick">
|
||||
<!-- 弹窗主体 -->
|
||||
<div class="calendar-popup" @tap.stop>
|
||||
<div class="relative w-full bg-white rounded-[12px] overflow-hidden">
|
||||
<!-- 头部区域 -->
|
||||
<div class="calendar-header">
|
||||
<div class="header-content">
|
||||
<span class="header-title">日历选择</span>
|
||||
<span v-if="props.rangeRequirePrice" class="header-subtitle">选择住宿日期,以下价格为单晚参考价</span>
|
||||
<div class="flex items-start justify-between p-[12px] border-b border-[#d9d9d9] bg-white">
|
||||
<div class="flex-1 flex flex-col gap-[4px]">
|
||||
<span class="text-[18px] font-semibold text-[#333] leading-[1.4]">日历选择</span>
|
||||
<span v-if="props.rangeRequirePrice" class="text-[14px] text-[#8c8c8c] leading-[1.4]">选择住宿日期,以下价格为单晚参考价</span>
|
||||
</div>
|
||||
<div class="header-close" @tap="handleClose">
|
||||
<uni-icons type="closeempty" size="20" color="#8c8c8c"></uni-icons>
|
||||
<div class="flex items-center justify-center w-[32px] h-[32px] " @click="handleClose">
|
||||
<van-icon name="cross" size="20" color="#8c8c8c"></van-icon>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 周标题行 - 固定显示 -->
|
||||
<div class="week-header">
|
||||
<span class="week-day" v-for="day in weekDays" :key="day">
|
||||
<div class="flex p-[16px_12px_8px] bg-white border-b border-[#d9d9d9] border-solid">
|
||||
<span class="flex-1 text-center text-[14px] text-[#8c8c8c] font-medium leading-[1.4]" v-for="day in weekDays"
|
||||
:key="day">
|
||||
{{ day }}
|
||||
</span>
|
||||
</div>
|
||||
@@ -23,10 +24,10 @@
|
||||
<!-- 日历主体区域 -->
|
||||
<div class="calendar-body">
|
||||
<!-- 全年月份显示区域 -->
|
||||
<div class="year-container">
|
||||
<div class="month-section" v-for="monthData in yearMonthsGrid" :key="monthData.key">
|
||||
<div class="flex flex-col gap-[32px]">
|
||||
<div class="flex flex-col" v-for="monthData in yearMonthsGrid" :key="monthData.key">
|
||||
<span class="month-title">{{ monthData.title }}</span>
|
||||
<div class="date-grid">
|
||||
<div class="grid grid-cols-7 gap-[4px]">
|
||||
<div class="date-cell" v-for="(dateInfo, index) in monthData.grid" :key="index"
|
||||
:class="getDateCellClass(dateInfo)" @tap="handleDateClick(dateInfo)">
|
||||
<template v-if="dateInfo">
|
||||
@@ -44,7 +45,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</uni-popup>
|
||||
</van-popup>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
@@ -62,7 +63,7 @@ defineOptions({
|
||||
name: "Calendar",
|
||||
});
|
||||
|
||||
// uni-popup组件引用
|
||||
// van-popup组件引用
|
||||
const popup = ref(null);
|
||||
|
||||
// 定义Props
|
||||
@@ -322,7 +323,7 @@ const getDateLabel = (dateStr) => {
|
||||
|
||||
// 获取日期格子样式类
|
||||
const getDateCellClass = (dateInfo) => {
|
||||
if (!dateInfo) return "date-cell-empty";
|
||||
if (!dateInfo) return "bg-transparent cursor-default";
|
||||
|
||||
const classes = ["date-cell-content"];
|
||||
|
||||
@@ -345,7 +346,7 @@ const getDateCellClass = (dateInfo) => {
|
||||
const handleDateClick = (dateInfo) => {
|
||||
if (!dateInfo) return;
|
||||
if (dateInfo.disabled) {
|
||||
uni.showToast({ title: "该日期不可选", icon: "none" });
|
||||
showToast("该日期不可选");
|
||||
// 仍然触发点击事件,供上层参考
|
||||
emit("date-click", {
|
||||
date: dateInfo.date,
|
||||
@@ -399,14 +400,11 @@ const handleRangeSelection = (dateInfo) => {
|
||||
dateInfo.price !== undefined &&
|
||||
dateInfo.price !== "-";
|
||||
if (!hasPrice) {
|
||||
uni.showToast({ title: "所选日期不可预订,请重新选择", icon: "none" });
|
||||
showToast('所选日期不可预订,请重新选择');
|
||||
return;
|
||||
}
|
||||
if (dateInfo.stock !== undefined && Number(dateInfo.stock) <= 0) {
|
||||
uni.showToast({
|
||||
title: "所选日期库存不足,请选择其他日期",
|
||||
icon: "none",
|
||||
});
|
||||
showToast("所选日期库存不足,请选择其他日期");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -419,7 +417,7 @@ const handleRangeSelection = (dateInfo) => {
|
||||
|
||||
// 否则为结束日期(完成选择)
|
||||
if (rangeStart.value === dateInfo.date) {
|
||||
uni.showToast({ title: "离店日期不能与入住日期相同", icon: "none" });
|
||||
showToast("离店日期不能与入住日期相同");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -434,11 +432,7 @@ const handleRangeSelection = (dateInfo) => {
|
||||
// 检查日期跨度是否超过28天
|
||||
const daysBetween = calculateDaysBetween(rangeStart.value, rangeEnd.value);
|
||||
if (daysBetween > 28) {
|
||||
uni.showToast({
|
||||
title: "预定时间不能超过28天",
|
||||
icon: "none",
|
||||
duration: 3000,
|
||||
});
|
||||
showToast("预定时间不能超过28天");
|
||||
rangeStart.value = null;
|
||||
rangeEnd.value = null;
|
||||
isRangeSelecting.value = false;
|
||||
@@ -452,10 +446,7 @@ const handleRangeSelection = (dateInfo) => {
|
||||
(d) => d.price === null || d.price === undefined || d.price === "-",
|
||||
);
|
||||
if (missing) {
|
||||
uni.showToast({
|
||||
title: "所选区间包含无价格日期,请重新选择",
|
||||
icon: "none",
|
||||
});
|
||||
showToast("所选区间包含无价格日期,请重新选择");
|
||||
rangeStart.value = null;
|
||||
rangeEnd.value = null;
|
||||
return;
|
||||
@@ -466,10 +457,7 @@ const handleRangeSelection = (dateInfo) => {
|
||||
return item && item.stock !== undefined && Number(item.stock) <= 0;
|
||||
});
|
||||
if (badStock) {
|
||||
uni.showToast({
|
||||
title: "所选区间包含库存不足的日期,请重新选择",
|
||||
icon: "none",
|
||||
});
|
||||
showToast("所选区间包含库存不足的日期,请重新选择");
|
||||
rangeStart.value = null;
|
||||
rangeEnd.value = null;
|
||||
return;
|
||||
@@ -554,7 +542,7 @@ const calculateDaysBetween = (startDate, endDate) => {
|
||||
return days === 0 ? 1 : days;
|
||||
};
|
||||
|
||||
// 监听visible属性变化,控制uni-popup显示
|
||||
// 监听visible属性变化,控制van-popup显示
|
||||
watch(
|
||||
() => props.visible,
|
||||
(newVisible) => {
|
||||
|
||||
@@ -33,68 +33,6 @@ $font-size-date: 16px;
|
||||
$font-size-price: 12px;
|
||||
$font-size-label: 10px;
|
||||
|
||||
// uni-popup会自动处理遮罩层和定位,这里移除相关样式
|
||||
|
||||
// 弹窗主体
|
||||
.calendar-popup {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
background-color: $background-white;
|
||||
border-radius: $modal-border-radius;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
// 头部区域
|
||||
.calendar-header {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
padding: $modal-padding;
|
||||
border-bottom: 1px solid $border-color;
|
||||
background-color: $background-white;
|
||||
}
|
||||
|
||||
.header-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: $font-size-title;
|
||||
font-weight: 600;
|
||||
color: $text-primary;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.header-subtitle {
|
||||
font-size: $font-size-subtitle;
|
||||
color: $text-secondary;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.header-close {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
transition: background-color 0.2s;
|
||||
|
||||
&:active {
|
||||
background-color: $background-gray;
|
||||
}
|
||||
}
|
||||
|
||||
// 周标题行 - 固定显示
|
||||
.week-header {
|
||||
display: flex;
|
||||
padding: 16px $modal-padding 8px;
|
||||
background-color: $background-white;
|
||||
border-bottom: 1px solid #eeeeee;
|
||||
}
|
||||
|
||||
// 日历主体区域
|
||||
.calendar-body {
|
||||
@@ -108,28 +46,6 @@ $font-size-label: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.week-day {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
font-size: $font-size-subtitle;
|
||||
color: $text-secondary;
|
||||
font-weight: 500;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
// 全年容器
|
||||
.year-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 32px;
|
||||
}
|
||||
|
||||
// 月份区域
|
||||
.month-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.month-title {
|
||||
font-size: $font-size-title;
|
||||
font-weight: 600;
|
||||
@@ -140,13 +56,6 @@ $font-size-label: 10px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
// 日期网格
|
||||
.date-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(7, 1fr);
|
||||
gap: $date-cell-gap;
|
||||
}
|
||||
|
||||
// 日期格子基础样式
|
||||
.date-cell {
|
||||
position: relative;
|
||||
@@ -162,12 +71,6 @@ $font-size-label: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
// 空白格子
|
||||
.date-cell-empty {
|
||||
background-color: transparent;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
// 有内容的格子
|
||||
.date-cell-content {
|
||||
background-color: $background-white;
|
||||
@@ -280,4 +183,4 @@ $font-size-label: 10px;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
min-height: 12px;
|
||||
}
|
||||
}
|
||||
@@ -12,9 +12,9 @@
|
||||
1,
|
||||
}">
|
||||
<div class="flex flex-items-center flex-row flex-shrink-0 mr-8">
|
||||
<uni-icons fontFamily="znicons" size="20" color="#333">
|
||||
<van-icon fontFamily="znicons" size="20" color="#333">
|
||||
{{ zniconsMap[moduleItem.moduleIcon] }}
|
||||
</uni-icons>
|
||||
</van-icon>
|
||||
<span class="ml-4 font-size-14 color-171717 line-height-20">
|
||||
{{ moduleItem.moduleTitle }}
|
||||
</span>
|
||||
@@ -25,14 +25,15 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<zero-markdown-div v-else :markdown="goodsData.commodityTip" :aiMode="true" />
|
||||
<vue3-markdown-it v-else :source="goodsData.commodityTip" :html="true" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { defineProps } from "vue";
|
||||
import Vue3MarkdownIt from 'vue3-markdown-it';
|
||||
import ModuleTitle from "@/components/ModuleTitle/index.vue";
|
||||
import { zniconsMap } from "@/assets/fonts/znicons";
|
||||
import { defineProps } from "vue";
|
||||
|
||||
// Props定义
|
||||
const props = defineProps({
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="relative w-full">
|
||||
<van-swipe class="overflow-hidden" :style="swiperStyle" @change="handleSwiperChange">
|
||||
<van-swipe-item class="swiper-item" v-for="(item, index) in thumbnails" :key="index">
|
||||
<van-swipe-item v-for="(item, index) in thumbnails" :key="index">
|
||||
<img class="w-full h-full" :src="item.photoUrl">
|
||||
</van-swipe-item>
|
||||
</van-swipe>
|
||||
@@ -21,7 +21,7 @@
|
||||
</div>
|
||||
|
||||
<div class="ml-[12px] bg-[rgba(0,0,0,0.5)] rounded-[50px] p-[0_6px_4px_8px] flex-auto shrink-0 whitespace-nowrap"
|
||||
@click="handlePredivClick">
|
||||
@click="handlePreviewClick">
|
||||
<van-icon name="arrow-left" size="10" color="#fff"></van-icon>
|
||||
<span class="mx-[4px] text-[10px] text-white align-center">
|
||||
{{ thumbnails.length }}
|
||||
@@ -34,9 +34,11 @@
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, nextTick } from "vue";
|
||||
import { useRouter } from 'vue-router'
|
||||
import { usePictureStore } from "@/store";
|
||||
|
||||
const pictureStore = usePictureStore();
|
||||
const router = useRouter();
|
||||
|
||||
// Props定义
|
||||
const props = defineProps({
|
||||
@@ -136,10 +138,9 @@ const handleSwiperChange = (e) => {
|
||||
scrollToActiveItem(currentIndex);
|
||||
};
|
||||
|
||||
const handlePredivClick = () => {
|
||||
pictureStore.setPredivImageData(thumbnails.value);
|
||||
uni.navigateTo({
|
||||
url: `/pages/goods/album/index`,
|
||||
});
|
||||
const handlePreviewClick = () => {
|
||||
pictureStore.setPreviewImageData(thumbnails.value);
|
||||
|
||||
router.push({ name: 'album' })
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div class="flex-1 overflow-y-auto" @scroll="handleScroll">
|
||||
<ImageSwiper :border-radius="0" :height="300" :images="goodsData.commodityPhotoList" thumbnailBottom="42px" />
|
||||
|
||||
<div class="bg-white py-[20px] relative -mt-[30px] z-10 rounded-t-[28px]">
|
||||
<div class="bg-white py-[20px] relative mt-[-30px] z-10 rounded-t-[28px]">
|
||||
<!-- 商品信息组件 -->
|
||||
<GoodInfo :goodsData="goodsData" />
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ const http = axios.create({
|
||||
|
||||
let context: RequestContext = {
|
||||
token: null,
|
||||
clientId: "6",
|
||||
clientId: import.meta.env.VITE_CLIENT_ID,
|
||||
latitude: null,
|
||||
longitude: null,
|
||||
language: null,
|
||||
|
||||
@@ -40,7 +40,7 @@ export default defineConfig({
|
||||
open: false,
|
||||
proxy: {
|
||||
"/ingress": {
|
||||
target: "https://onefeel.brother7.cn",
|
||||
target: "https://abroadbiz.nianxx.com",
|
||||
changeOrigin: true,
|
||||
ws: true,
|
||||
secure: false,
|
||||
|
||||
Reference in New Issue
Block a user