Compare commits

..

No commits in common. "f6821ade2d844169a4f8ce8d89f84bdd678f08e5" and "e2fe0a365b6935f775a78671a5ec811587235089" have entirely different histories.

9 changed files with 36 additions and 238 deletions

View File

@ -61,8 +61,8 @@ const ERROR_MESSAGES = {
* @typedef {Object} FormCardProps * @typedef {Object} FormCardProps
* @property {string} title - 表单标题 * @property {string} title - 表单标题
* @property {Object} form - 表单数据对象 * @property {Object} form - 表单数据对象
* @property {string} form.visitorName - 姓名 * @property {string} form.name - 姓名
* @property {string} form.contactPhone - 手机号 * @property {string} form.phone - 手机号
* @property {boolean} showDeleteIcon - 是否显示删除图标 * @property {boolean} showDeleteIcon - 是否显示删除图标
*/ */
const props = defineProps({ const props = defineProps({
@ -73,16 +73,12 @@ const props = defineProps({
form: { form: {
type: Object, type: Object,
default: () => ({ default: () => ({
visitorName: "", name: "",
contactPhone: "", phone: "",
}), }),
validator: (value) => { validator: (value) => {
return ( return value && typeof value === 'object' &&
value && 'name' in value && 'phone' in value;
typeof value === "object" &&
"visitorName" in value &&
"contactPhone" in value
);
}, },
}, },
showDeleteIcon: { showDeleteIcon: {
@ -94,15 +90,11 @@ const props = defineProps({
/** /**
* FormCard 组件事件 * FormCard 组件事件
* @typedef {Object} FormCardEmits * @typedef {Object} FormCardEmits
* @property {Function} update:visitorName - 更新姓名事件 * @property {Function} update:name - 更新姓名事件
* @property {Function} update:contactPhone - 更新手机号事件 * @property {Function} update:phone - 更新手机号事件
* @property {Function} delete - 删除表单事件 * @property {Function} delete - 删除表单事件
*/ */
const emit = defineEmits([ const emit = defineEmits(["update:name", "update:phone", "delete"]);
"update:visitorName",
"update:contactPhone",
"delete",
]);
// //
const nameError = ref(""); const nameError = ref("");
@ -110,16 +102,16 @@ const phoneError = ref("");
// - // -
const nameValue = computed({ const nameValue = computed({
get: () => props.form?.visitorName || "", get: () => props.form?.name || "",
set: (value) => emit("update:visitorName", value?.trim() || ""), set: (value) => emit("update:name", value?.trim() || ""),
}); });
const phoneValue = computed({ const phoneValue = computed({
get: () => props.form?.contactPhone || "", get: () => props.form?.phone || "",
set: (value) => { set: (value) => {
// //
const numericValue = value.replace(/\D/g, ""); const numericValue = value.replace(/\D/g, "");
emit("update:contactPhone", numericValue); emit("update:phone", numericValue);
}, },
}); });
@ -153,11 +145,11 @@ const getPhoneError = (phone) => {
// //
const validateName = () => { const validateName = () => {
nameError.value = getNameError(props.form?.visitorName); nameError.value = getNameError(props.form?.name);
}; };
const validatePhone = () => { const validatePhone = () => {
phoneError.value = getPhoneError(props.form?.contactPhone); phoneError.value = getPhoneError(props.form?.phone);
}; };
// //

View File

@ -1,45 +0,0 @@
<template>
<view class="store-address" @click="openMap">
<text class="location-label">位于 [{{ orderData.commodityAddress }}]</text>
<text class="address-text">{{ orderData.commodityAddress }}</text>
</view>
</template>
<script setup>
import { defineProps } from "vue";
const props = defineProps({
orderData: {
type: Object,
required: true,
default: () => ({}),
},
});
//
const openMap = () => {
const address = props.orderData.commodityAddress;
const latitude = Number(props.orderData.commodityLatitude);
const longitude = Number(props.orderData.commodityLongitude);
uni.getLocation({
type: "gcj02", //uni.openLocation
success: (res) => {
console.log("当前经纬度", latitude, longitude);
uni.openLocation({
latitude: latitude,
longitude: longitude,
address: address,
success: () => {
console.log("success");
},
});
},
});
};
</script>
<style scoped lang="scss">
@import "./styles/index.scss";
</style>

View File

@ -1,49 +0,0 @@
.store-address {
display: flex;
align-items: start;
flex-direction: column;
padding: 16px 12px;
background-color: #f0f0f0;
background-image: url(""); // 预留背景图片位置用户手动导入
background-size: cover;
background-position: center;
border-radius: 12px;
font-size: 14px;
color: #333;
position: relative;
overflow: hidden;
// 添加半透明遮罩层确保文字可读性
&::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(255, 255, 255, 0.8);
z-index: 1;
}
// 确保内容在遮罩层之上
.location-label,
.address-text {
position: relative;
z-index: 2;
}
.location-label {
color: #333;
font-size: 14px;
margin-right: 4px;
font-weight: 500;
}
.address-text {
margin-top: 4px;
flex: 1;
color: #666;
font-size: 12px;
font-weight: 400;
}
}

View File

@ -83,12 +83,8 @@
:form="item" :form="item"
:showDeleteIcon="userFormList.length > 1" :showDeleteIcon="userFormList.length > 1"
:key="index" :key="index"
@update:visitorName=" @update:name="(value) => updateUserForm(index, 'name', value)"
(value) => updateUserForm(index, 'visitorName', value) @update:phone="(value) => updateUserForm(index, 'phone', value)"
"
@update:contactPhone="
(value) => updateUserForm(index, 'contactPhone', value)
"
@delete="() => deleteUserForm(index)" @delete="() => deleteUserForm(index)"
/> />
</scroll-view> </scroll-view>
@ -130,10 +126,10 @@ const showToast = (title, icon = "none", duration = 2000) => {
const isValidUserForm = (user) => { const isValidUserForm = (user) => {
return ( return (
user && user &&
typeof user.visitorName === "string" && typeof user.name === "string" &&
user.visitorName.trim() !== "" && user.name.trim() !== "" &&
typeof user.contactPhone === "string" && typeof user.phone === "string" &&
user.contactPhone.trim() !== "" user.phone.trim() !== ""
); );
}; };
@ -169,7 +165,7 @@ const emits = defineEmits(["confirm", "close"]);
// //
const createEmptyUserForm = () => { const createEmptyUserForm = () => {
return { visitorName: "", contactPhone: "" }; return { name: "", phone: "" };
}; };
// //
@ -247,7 +243,7 @@ const updateUserForm = (index, field, value) => {
return; return;
} }
if (!["visitorName", "contactPhone"].includes(field)) { if (!["name", "phone"].includes(field)) {
return; return;
} }
@ -312,8 +308,8 @@ const confirmOrder = () => {
quantity: quantity.value, quantity: quantity.value,
totalPrice: parseFloat(totalPrice.value), totalPrice: parseFloat(totalPrice.value),
userFormList: userFormList.value.map((user) => ({ userFormList: userFormList.value.map((user) => ({
visitorName: user.visitorName.trim(), name: user.name.trim(),
contactPhone: user.contactPhone.trim(), phone: user.phone.trim(),
})), })),
commodityType: props.goodsData?.commodityTypeCode, commodityType: props.goodsData?.commodityTypeCode,
timestamp: Date.now(), timestamp: Date.now(),

View File

@ -21,7 +21,7 @@
<!-- 地址区域 --> <!-- 地址区域 -->
<view class="address-section"> <view class="address-section">
<LocationCard :orderData="goodsData" /> <LocationInfo :orderData="goodsData" />
</view> </view>
<!-- 设施信息区域 --> <!-- 设施信息区域 -->
@ -41,7 +41,7 @@
<script setup> <script setup>
import { computed, defineProps, defineEmits } from "vue"; import { computed, defineProps, defineEmits } from "vue";
import LocationCard from "@/components/LocationCard/index.vue"; import LocationInfo from "@/components/LocationInfo/index.vue";
// //
const emits = defineEmits(["showCalendar"]); const emits = defineEmits(["showCalendar"]);

View File

@ -38,7 +38,9 @@
// 地址区域 // 地址区域
.address-section { .address-section {
padding: 6px 0; padding: 12px 0;
border-top: 1px solid #f0f0f0;
border-bottom: 1px solid #f0f0f0;
.address-item { .address-item {
display: flex; display: flex;
@ -59,8 +61,8 @@
margin-top: 12px; margin-top: 12px;
.facilities-grid { .facilities-grid {
display: flex; display: grid;
flex-wrap: wrap; grid-template-columns: repeat(3, 1fr);
gap: 8px; gap: 8px;
.facility-item { .facility-item {

View File

@ -15,42 +15,9 @@
<!-- 商品信息组件 --> <!-- 商品信息组件 -->
<GoodInfo :goodsData="goodsData" @showCalendar="showCalendar" /> <GoodInfo :goodsData="goodsData" @showCalendar="showCalendar" />
<view v-if="goodsData.commodityPurchaseInstruction" class="use-notice"> <ModuleTitle title="购买须知" />
<ModuleTitle
:title="goodsData.commodityPurchaseInstruction.templateTitle"
/>
<view
class="use-notice-content"
v-for="(moduleItem, index) in goodsData.commodityPurchaseInstruction
.commodityPurchaseInstructionModuleEntityList"
:key="index"
>
<view
class="module-item"
:class="{
'border-bottom':
index <
goodsData.commodityPurchaseInstruction
.commodityPurchaseInstructionModuleEntityList.length -
1,
}"
>
<view class="module-icon">
<uni-icons fontFamily="znicons" size="20" color="#333">{{
zniconsMap[moduleItem.moduleIcon]
}}</uni-icons>
<text class="module-title">{{ moduleItem.moduleTitle }}</text>
</view>
<text class="module-desc">{{ moduleItem.moduleContent }}</text>
</view>
</view>
</view>
<zero-markdown-view <zero-markdown-view :markdown="goodsData.commodityTip" :aiMode='true' />
v-else
:markdown="goodsData.commodityTip"
:aiMode="true"
/>
</view> </view>
</scroll-view> </scroll-view>
@ -96,7 +63,6 @@ import GoodInfo from "./components/GoodInfo/index.vue";
import ModuleTitle from "@/components/ModuleTitle/index.vue"; import ModuleTitle from "@/components/ModuleTitle/index.vue";
import GoodConfirm from "./components/GoodConfirm/index.vue"; import GoodConfirm from "./components/GoodConfirm/index.vue";
import Calender from "@/components/Calender/index.vue"; import Calender from "@/components/Calender/index.vue";
import { zniconsMap } from "@/static/fonts/znicons.js";
const calendarVisible = ref(false); const calendarVisible = ref(false);
const goodsData = ref({}); const goodsData = ref({});
@ -280,8 +246,4 @@ const handleDateSelect = (data) => {
<style scoped lang="scss"> <style scoped lang="scss">
@import "./styles/index.scss"; @import "./styles/index.scss";
@font-face {
font-family: znicons;
src: url("@/static/fonts/znicons.ttf");
}
</style> </style>

View File

@ -15,47 +15,6 @@ $button-hover-color: darken($button-color, 8%);
flex-shrink: 0; flex-shrink: 0;
} }
// 使用须知样式
.use-notice {
margin: 16px 0;
}
.use-notice-content {
.module-item {
display: flex;
align-items: flex-start;
flex-direction: column;
padding: 12px 0;
.module-icon {
display: flex;
flex-direction: row;
align-items: center;
margin-right: 8px;
flex-shrink: 0;
.module-title {
font-size: 14px;
color: #333;
text-align: center;
word-wrap: break-word;
margin-left: 4px;
}
}
.module-desc {
flex: 1;
font-size: 12px;
color: #666;
line-height: 1.5;
margin-top: 4px;
}
}
.border-bottom {
border-bottom: 1px solid #f0f0f0;
}
}
.content-wrapper { .content-wrapper {
flex: 1; flex: 1;
height: 0; // 关键让flex子项能够正确计算高度 height: 0; // 关键让flex子项能够正确计算高度

View File

@ -1,19 +0,0 @@
export const zniconsMap = {
"zn-wifi": "\ue681",
"zn-bath": "\ue682",
"zn-frame": "\ue683",
"zn-shower-gel": "\ue684",
"zn-a-washingmachine": "\ue685",
"zn-live": "\ue686",
"zn-user": "\ue687",
"zn-dish-cover": "\ue688",
"zn-glass-cup": "\ue689",
"zn-check-circle": "\ue68a",
"zn-send-filled": "\ue68b",
"zn-nav-arrow-right": "\ue68c",
"zn-nav-arrow-left": "\ue68d",
"zn-nav-arrow-down": "\ue68e",
"zn-fast-arrow-down": "\ue68f",
"zn-nav-arrow-up": "\ue690",
"zn-microphone": "\ue691",
};