فهرست منبع

feat:小程序所有页面UI

颜琼丽 20 ساعت پیش
والد
کامیت
0d17279713

+ 70 - 0
jd_logistics-app/api/address.js

@@ -0,0 +1,70 @@
+import request from "@/utils/request.js";
+
+
+
+/**
+ * 广告轮播图
+ * 
+ */
+export function adList(data) {
+  return request.get('mini/ad/list', data, {noAuth:true});
+}
+/**
+ * 广告轮播图
+ * 
+ */
+export function getAgentList(data) {
+  return request.get('mini/agent/list', data, {noAuth:true});
+}
+/**
+ * 热搜
+ * 
+ */
+export function getAdSearch(id='') {
+  return request.get(`mini/ad/search/${id}`, {}, {noAuth:true});
+}
+/**
+ * 获取客服电话
+ * 
+ */
+export function getAdServicePhone() {
+  return request.get(`mini/ad/servicePhone`, {}, {noAuth:true});
+}
+/**
+ * 广告详情
+ * 
+ */
+export function getAdDetails({dictCode}) {
+  return request.get(`mini/ad/details/${dictCode}`, {}, {noAuth:true});
+}
+
+
+// 查询地址簿管理列表
+export function listBook(query) {
+  return request.get('system/front/book/list',query)
+}
+
+// 查询地址簿管理详细
+export function getBook(addressId) {
+  return request.get('system/front/book/' + addressId)
+}
+
+// 新增地址簿管理
+export function addBook(data) {
+  return request.post('system/front/book',data)
+}
+
+// 修改地址簿管理
+export function updateBook(data) {
+  return request.put('system/front/book',data)
+}
+
+// 删除地址簿管理
+export function delBook(addressId) {
+  return request.delete('system/front/book/' + addressId)
+}
+export function getDefaultAddress() {
+  return request.get('system/book/getDefaultAddress')
+}
+
+

+ 65 - 0
jd_logistics-app/components/AddressInfo.vue

@@ -0,0 +1,65 @@
+<template>
+	<view class="address-info">
+		<view class="name-phone">
+			<text class="name">{{ address.name }}</text>
+			<text class="phone">{{ address.phone }}</text>
+		</view>
+		<view class="address-detail">{{ address.address }}</view>
+	</view>
+</template>
+
+<script setup>
+	defineProps({
+		address: {
+			type: Object,
+			required: true
+		},
+		isDefault: {
+			type: Boolean,
+			default: false
+		},
+		isSowAction: {
+			type: Boolean,
+			default: true
+		}
+	})
+</script>
+
+<style scoped lang="less">
+	
+	.address-info {
+		display: flex;
+		flex-direction: column;
+		margin-bottom: 16rpx;
+
+		.name-phone {
+			display: flex;
+			align-items: center;
+			margin-bottom: 16rpx;
+		}
+
+		.name {
+			height: 48rpx;
+			font-size: 32rpx;
+			font-weight: bold;
+			color: #333;
+			margin-right: 30rpx;
+			line-height: 48rpx;
+		}
+
+		.phone {
+			height: 48rpx;
+			font-size: 32rpx;
+			font-weight: bold;
+			color: #333;
+			line-height: 48rpx;
+		}
+
+		.address-detail {
+			font-size: 28rpx;
+			color: #666;
+			line-height: 44rpx;
+		}
+
+	}
+</style>

+ 180 - 0
jd_logistics-app/components/AddressItem.vue

@@ -0,0 +1,180 @@
+<template>
+	<view class="address-item">
+		<view class="address-content">
+			<!-- 地址信息 -->
+			<view class="address-info">
+				<view class="name-phone">
+					<text class="name">{{ address.name }}</text>
+					<text class="phone">{{ address.phone }}</text>
+				</view>
+				<view class="address-detail">{{ address.address }}</view>
+			</view>
+
+			<!-- 操作区域 -->
+			<view class="actions" v-if="isSowAction">
+				<!-- 设为默认 -->
+				<view class="set-default" @click="$emit('set-default')">
+					<view class="default-checkbox" :class="{ 'checked': isDefault }">
+						<text v-if="isDefault" class="checkmark">✓</text>
+					</view>
+					<text class="default-text" :class="{ 'checked': isDefault }">设为默认</text>
+				</view>
+
+				<!-- 删除和编辑按钮 -->
+				<view class="edit-delete">
+					<view class="action-text"  @click="$emit('delete')">
+						<image src="/static/img/address-delete.png" />
+						<text class=" delete">删除</text>
+					</view>
+					<view class="action-text" @click="$emit('edit')">
+						<image src="/static/img/address-edit.png" />
+						<text class=" edit" >编辑</text>
+					</view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script setup>
+	defineProps({
+		address: {
+			type: Object,
+			required: true
+		},
+		isDefault: {
+			type: Boolean,
+			default: false
+		},
+		isSowAction: {
+			type: Boolean,
+			default: true
+		}
+	})
+
+	defineEmits(['set-default', 'edit', 'delete'])
+</script>
+
+<style scoped lang="less">
+	.address-item {
+		background-color: #fff;
+		border-radius: 16rpx;
+		padding: 16rpx;
+		margin-bottom: 20rpx;
+	}
+
+	.address-content {
+		display: flex;
+		flex-direction: column;
+	}
+
+	.address-info {
+		display: flex;
+		flex-direction: column;
+		margin-bottom: 16rpx;
+		
+		.name-phone {
+			display: flex;
+			align-items: center;
+			margin-bottom: 16rpx;
+		}
+		
+		.name {
+			height: 48rpx;
+			font-size: 32rpx;
+			font-weight: bold;
+			color: #333;
+			margin-right: 30rpx;
+			line-height: 48rpx;
+		}
+		
+		.phone {
+			height: 48rpx;
+			font-size: 32rpx;
+			font-weight: bold;
+			color: #333;
+			line-height: 48rpx;
+		}
+		
+		.address-detail {
+			font-size: 28rpx;
+			color: #666;
+			line-height: 44rpx;
+		}
+		
+	}
+
+	.actions {
+		display: flex;
+		justify-content: space-between;
+		align-items: center;
+	}
+
+	.set-default {
+		display: flex;
+		align-items: center;
+	}
+
+	.default-checkbox {
+		width: 36rpx;
+		height: 36rpx;
+		border: 2rpx solid #ccc;
+		border-radius: 50%;
+		margin-right: 16rpx;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.default-checkbox.checked {
+		background-color: #1B64F0;
+		border-color: #1B64F0;
+	}
+
+	.default-text.checked {
+		color: #1B64F0;
+	}
+
+
+	.checkmark {
+		color: #fff;
+		font-size: 24rpx;
+	}
+
+	.default-text {
+		font-size: 28rpx;
+		color: #666;
+	}
+
+	.edit-delete {
+		display: flex;
+		align-items: center;
+	}
+
+	.action-text {
+		display: flex;
+		align-items: center;
+		font-size: 28rpx;
+		padding: 6rpx 20rpx;
+
+		image {
+			width: 32rpx;
+			height: 32rpx;
+			margin-right: 8rpx;
+		}
+	}
+
+	.delete {
+		color: #ff3b30;
+	}
+
+	.edit {
+		color: #007aff;
+	}
+
+	.action-separator {
+		color: #e0e0e0;
+		font-size: 24rpx;
+	}
+</style>
+

+ 566 - 0
jd_logistics-app/pages/address/edit1.vue

@@ -0,0 +1,566 @@
+<template>
+	<view class="container">
+		<scroll-view class="scroll-content" scroll-y>
+			<!-- 基本信息区域 -->
+			<view class="section-card">
+
+				<!-- 联系人 -->
+				<view class="form-item">
+					<view class="label required">姓名</view>
+					<view class="input-area">
+						<u-input v-model="formData.shopContacts" placeholder="请输入联系人" border="none" clearable
+							@blur="validateField('shopContacts')" input-align="right" />
+						<view class="error-msg" v-if="errors.shopContacts">{{ errors.shopContacts }}</view>
+					</view>
+				</view>
+
+				<!-- 联系电话 -->
+				<view class="form-item">
+					<view class="label required">联系电话</view>
+					<view class="input-area">
+						<u-input v-model="formData.shopContactInfo" placeholder="请输入联系电话" border="none" clearable
+							@blur="validateField('shopContactInfo')" input-align="right" />
+						<view class="error-msg" v-if="errors.shopContactInfo">{{ errors.shopContactInfo }}</view>
+					</view>
+				</view>
+
+				<!-- 位置 -->
+				<view class="form-item  time-picker-item" @click="showAreaPicker = true">
+					<view class="label required">所在省市区</view>
+					<view class="input-area">
+						<view class="time-display">
+							{{ formData.shopLocation || '请选择省市区' }}
+							<u-icon name="arrow-right" color="#c0c4cc" class="time-arrow"></u-icon>
+						</view>
+						<view class="error-msg" v-if="errors.shopLocation">{{ errors.shopLocation }}</view>
+					</view>
+				</view>
+
+				<!-- 详细地址 -->
+				<!-- 	<view class="form-item">
+				<view class="label">详细地址</view>
+				<view class="input-area">
+					<u-input v-model="formData.shopLocationLine" placeholder="请输入详细地址" border="none" clearable
+						input-align="right" />
+				</view>
+			</view> -->
+
+				<!-- 详细地址 -->
+				<view class="upload-section">
+					<view class="form-label required">详细地址</view>
+					<u-textarea class="textarea" v-model="formData.goodsOverview" placeholder="请填写详细地址" maxlength="200"
+						height="160" count></u-textarea>
+				</view>
+			</view>
+			<!-- 占位元素,确保内容不被底部按钮遮挡 -->
+			<view class="bottom-placeholder"></view>
+		</scroll-view>
+
+		<view class="add-btn-container">
+			<button class="add-btn" @click="handleSave">
+				<text class="add-btn-text">保存</text>
+			</button>
+		</view>
+
+
+
+		<!-- 省市区选择器组件 -->
+		<AreaPickerCustommer :show="showAreaPicker" @update:show="showAreaPicker = $event"
+			@confirm="handleAreaConfirm" />
+
+	</view>
+</template>
+
+<script setup>
+	import {
+		ref,
+		reactive,
+		onMounted
+	} from 'vue'
+
+	import {
+		onLoad
+	} from '@dcloudio/uni-app' // 导入 UniApp 的生命周期
+	import AreaPickerCustommer from '@/components/AreaPickerCustommer.vue';
+
+
+
+	const tenantId = ref('')
+	// 表单数据 - 根据UI设计图预填数据
+	const formData = reactive({
+		id: '',
+		shopImage: [],
+		shopAvatar: undefined,
+		shopLocation: '',
+		shopLocationLine: '',
+		shopContacts: '',
+		shopContactInfo: '',
+		wechatId: '',
+		goodsOverview: '',
+		approvalType: '0' //0:门店审批 1:无需审批
+	})
+	// {
+	// 	"locationLng": 112.45,
+	// 	"locationLat": 34.61
+	// }
+
+	// 错误信息
+	const errors = reactive({
+		shopLocation: '',
+		shopContacts: '',
+		shopContactInfo: ''
+	})
+
+	// 头像上传
+	const avatarList = ref([])
+
+	// 海报上传
+	const posterList = ref([])
+	// 地区选择器
+	const showAreaPicker = ref(false);
+	// 时间选择器
+	const showTimePicker = ref(false)
+
+	const filterNumber = (value) => {
+		// 移除所有非数字字符,包括小数点(如果不需要小数点可以这样)
+		// 如果允许小数点,可以使用 /[^\d.]/g,但注意只能有一个小数点
+		// 这里我们只需要整数,所以移除非数字
+		formData.value.shopPromotionProportion = value.replace(/\D/g, '');
+	};
+
+	onLoad((option) => {
+		tenantId.value = option.tenantId
+	})
+
+	onMounted(() => {
+		getAddressInfo()
+	})
+
+
+	const getAddressInfo = () => {
+		const params = {
+			tenantId: tenantId.value
+		}
+		// getAddressApi(params).then(res => {
+		// 	if (res.code == 200) {
+		// 		if (res.data.length == 0) {
+		// 			uni.showToast({
+		// 				title: '未查询到店铺信息',
+		// 				icon: 'success'
+		// 			})
+		// 			return
+		// 		}
+		// 		const shopItemTemp = res.data[0]
+		// 		Object.assign(formData, shopItemTemp)
+		// 		if (!shopItemTemp.approvalType) {
+		// 			formData.approvalType = '0'
+		// 		}
+
+		// 		// if (formData.businessHoursStart && formData.businessHoursEnd) {
+		// 		// 	formData.businessHours = `${formData.businessHoursStart}-${formData.businessHoursEnd}`
+		// 		// }
+		// 		formData.shopAvatar = shopItemTemp.shopAvatar
+		// 		if (shopItemTemp.shopAvatarUrl) {
+		// 			avatarList.value.push({
+		// 				url: shopItemTemp.shopAvatarUrl,
+		// 				status: 'success'
+		// 			})
+		// 		}
+
+		// 		formData.shopImage = []
+		// 		const imageIdList = shopItemTemp.shopImage.split(",")
+		// 		formData.shopImage = imageIdList
+		// 		const imageList = shopItemTemp.shopImageUrl.split(",")
+
+		// 		if (shopItemTemp.shopImageUrl) {
+		// 			imageList.map(it => {
+		// 				posterList.value.push({
+		// 					url: it,
+		// 					status: 'success'
+		// 				})
+		// 			})
+		// 		}
+		// 	}
+		// })
+	}
+
+	// 表单验证
+	const validateField = (field) => {
+		switch (field) {
+			case 'shopContacts':
+				errors.shopContacts = formData.shopContacts.trim() ? '' : '联系人不能为空'
+				break
+			case 'shopContactInfo':
+				if (!formData.shopContactInfo) {
+					errors.shopContactInfo = '联系电话不能为空'
+				} else if (!/^1[3-9]\d{9}$/.test(formData.shopContactInfo)) {
+					errors.shopContactInfo = '请输入正确的手机号码'
+				} else {
+					errors.shopContactInfo = ''
+				}
+				break
+			case 'shopLocation':
+				errors.shopLocation = formData.shopLocation.trim() ? '' : '店铺位置不能为空'
+				break
+		}
+	}
+
+
+
+
+	// 时间选择确认
+	const timeConfirm = (event) => {
+		const start = event.value[0] ? event.value[0]?.label : '00:00'
+		const end = event.value[1] ? event.value[1]?.label : '00:00'
+		formData.businessHoursStart = start
+		formData.businessHoursEnd = end
+		formData.businessHours = `${start}-${end}`
+		showTimePicker.value = false
+		validateField('businessHours')
+	}
+
+	// 处理地区选择确认
+	const handleAreaConfirm = (areaData) => {
+		console.log('选择的地区数据:', areaData);
+		// 更新表单数据
+		const district = areaData.district ? areaData.district.name : '';
+		const province = areaData.province ? areaData.province.name : '';
+		const city = areaData.city ? areaData.city.name : '';
+		formData.shopLocation = province + city + district;
+		// 触发地区字段验证
+		validateField('shopLocation');
+	};
+
+	//0:门店审批 1:无需审批
+	const checkApprovalType = (type) => {
+		formData.approvalType = type
+	}
+	// 保存处理
+	const handleSave = () => {
+		// 验证所有必填字段
+		validateField('shopName')
+		validateField('shopLocation')
+		validateField('shopContacts')
+		validateField('shopContactInfo')
+		validateField('businessHours')
+
+		// 检查是否有错误
+		const hasErrors = Object.values(errors).some(error => error !== '')
+
+		if (hasErrors) {
+			return
+		}
+		if (!formData.shopAvatar) {
+			uni.showToast({
+				icon: 'none',
+				title: "请上传店铺头像~"
+			})
+			return
+		}
+
+		const params = {
+			...formData
+		}
+		params.shopImage = params.shopImage.join(",")
+		editShopInfoApi(params).then(res => {
+			if (res.code == 200) {
+				uni.showToast({
+					title: "修改成功~",
+					icon: "success"
+				})
+				uni.navigateBack()
+			}
+		})
+
+	}
+</script>
+
+<style lang="scss" scoped>
+	.container {
+		height: 100vh;
+		display: flex;
+		flex-direction: column;
+		background-color: #F5F7FA;
+	}
+
+	.page-header {
+		padding: 32rpx;
+		background-color: #fff;
+		border-bottom: 1rpx solid #eee;
+		flex-shrink: 0;
+
+		.page-title {
+			font-size: 36rpx;
+			font-weight: 600;
+			color: #333;
+		}
+	}
+
+	.scroll-content {
+		flex: 1;
+		overflow-y: auto;
+		padding-bottom: 160rpx;
+		/* 为底部按钮留出空间 */
+	}
+
+	.section-card {
+		padding: 16rpx;
+
+
+
+		.form-label {
+			font-size: 28rpx;
+			color: #333;
+			font-weight: 500;
+			margin-bottom: 20rpx;
+		}
+
+		.form-label.required::before {
+			content: "*";
+			color: #fa3534;
+			margin-right: 8rpx;
+		}
+
+		/* 上传区域样式 */
+		.upload-section {
+			background: #FFFFFF;
+			border-radius: 16rpx;
+			margin-bottom: 16rpx;
+			padding: 16rpx;
+			
+			
+			/* 确保上传的头像预览也是圆形 */
+			:deep(.u-textarea) {
+				background-color: #F5F7FA;
+				border: none;
+				padding: 16rpx;
+				font-size: 28rpx;
+			}
+			
+			:deep(.u-textarea__count) {
+				background-color: #F5F7FA;
+			}
+			
+			
+
+		}
+
+		.textarea {
+			background-color: #F5F7FA;
+			border: none;
+			padding: 16rpx;
+			font-size: 28rpx;
+		}
+
+		.column {
+			display: flex;
+			flex-direction: column;
+			background: #FFFFFF;
+			border-radius: 16rpx;
+			margin-bottom: 16rpx;
+			padding: 16rpx;
+
+			&:last-child {
+				border-bottom: none;
+			}
+
+			.label {
+				width: 260rpx;
+				font-size: 28rpx;
+				color: #333;
+				flex-shrink: 0;
+
+				&.required::before {
+					content: '*';
+					color: #ff4444;
+					margin-right: 8rpx;
+				}
+			}
+		}
+
+		.form-item {
+			height: 100rpx;
+			background: #FFFFFF;
+			border-radius: 16rpx;
+			margin-bottom: 16rpx;
+			padding: 16rpx;
+			display: flex;
+			align-items: center;
+
+			&:last-child {
+				border-bottom: none;
+			}
+
+			.label {
+				width: 260rpx;
+				font-size: 28rpx;
+				color: #333;
+				flex-shrink: 0;
+
+				&.required::before {
+					content: '*';
+					color: #ff4444;
+					margin-right: 8rpx;
+				}
+			}
+
+			.input-area {
+				flex: 1;
+				display: flex;
+				flex-direction: column;
+				align-items: flex-end;
+
+				.error-msg {
+					font-size: 24rpx;
+					color: #ff4444;
+					margin-top: 8rpx;
+					width: 100%;
+					text-align: right;
+				}
+			}
+
+			.textarea {
+				background-color: #F5F7FA;
+				border: none;
+				padding: 16rpx;
+				font-size: 28rpx;
+			}
+		}
+
+
+		.section-title {
+			font-size: 32rpx;
+			font-weight: bold;
+			color: #333;
+			margin-bottom: 16rpx;
+			height: 48rpx;
+			line-height: 48rpx;
+		}
+
+		.upload-desc {
+			font-size: 24rpx;
+			color: #999;
+			margin-top: 16rpx;
+		}
+	}
+
+	/* 营业时间选择项 - 整个横排可点击 */
+	.time-picker-item {
+		cursor: pointer;
+
+		.time-display {
+			display: flex;
+			align-items: center;
+			justify-content: flex-end;
+			width: 100%;
+			color: #333;
+
+			.time-arrow {
+				margin-left: 16rpx;
+			}
+		}
+	}
+
+	.avatar-upload {
+		display: flex;
+		justify-content: flex-end;
+		align-items: center;
+	}
+
+	.upload-avatar-btn {
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		width: 60rpx;
+		height: 60rpx;
+		border: 2rpx dashed #c0c4cc;
+		/* 圆形头像 */
+		background-color: #f8f8f8;
+
+
+		/* 确保上传的头像预览也是圆形 */
+		:deep(.u-upload__wrap) {
+			.u-upload__wrap__preview {
+				border-radius: 50%;
+				overflow: hidden;
+			}
+		}
+	}
+
+
+	.poster-upload-area {
+		margin-top: 16rpx;
+		display: flex;
+		justify-content: flex-start;
+	}
+
+	.upload-poster-btn {
+		display: flex;
+		flex-direction: column;
+		justify-content: center;
+		align-items: center;
+		width: 148rpx;
+		height: 148rpx;
+		border: 2rpx dashed #c0c4cc;
+		border-radius: 8rpx;
+		background-color: #f8f8f8;
+
+		.upload-text {
+			font-size: 24rpx;
+			color: #999;
+			margin-top: 12rpx;
+		}
+	}
+
+	.radio-group {
+		width: 100%;
+		display: flex;
+		flex-direction: column;
+		margin-top: 16rpx;
+
+		.radio-item {
+			margin-bottom: 24rpx;
+			width: 100%;
+			display: flex;
+			flex-direction: column;
+			align-items: left;
+			font-size: 28rpx;
+			color: #333;
+
+			.radio-desc {
+				font-size: 24rpx;
+				color: #999;
+				margin-top: 8rpx;
+			}
+		}
+	}
+
+	.bottom-placeholder {
+		height: 40rpx;
+	}
+
+	.add-btn-container {
+		padding: 32rpx;
+		background-color: #fff;
+		border-top: 1rpx solid #eee;
+	}
+
+	.add-btn {
+		height: 88rpx;
+		background: #1B64F0;
+		border-radius: 44rpx;
+	}
+
+	.add-btn-text {
+		color: #fff;
+		font-size: 32rpx;
+		font-weight: 500;
+		height: 88rpx;
+		line-height: 88rpx;
+	}
+
+	/* 按钮激活效果 */
+	.add-btn:active {
+		opacity: 0.8;
+	}
+</style>

+ 1 - 1
jd_logistics-app/pages/mine/mine.vue

@@ -479,7 +479,7 @@ function userLogoutFn() {
 				padding: 7rpx 16rpx;
 				line-height: 1;
 				flex-shrink: 0;
-				max-width: 200rpx;
+				max-width: 250rpx;
 				white-space: nowrap; // 强制文本在一行内显示
 				overflow: hidden; // 隐藏溢出部分
 				text-overflow: ellipsis; // 用省略号代替被隐藏的文本

+ 886 - 0
jd_logistics-app/pages/mine/settlementCode.vue

@@ -0,0 +1,886 @@
+<template>
+	<view class="container">
+
+		<!-- Tab切换 - 平均分配宽度 -->
+		<view class="custom-tabs">
+			<view class="tab-item" :class="{ active: currentTab === 0 }" @click="switchTab(0)">
+				<text class="tab-text">京东月结码</text>
+			</view>
+			<view class="tab-item" :class="{ active: currentTab === 1 }" @click="switchTab(1)">
+				<text class="tab-text">顺丰月结码</text>
+			</view>
+		</view>
+
+		<!-- 二维码邀请内容 -->
+		<view  class="tab-content">
+			<scroll-view scroll-y class="scroll-view">
+				<!-- 店铺信息 -->
+				<view class="store-info">
+					<view class="store-name">月结卡号</view>
+					<view class="store">
+						<!-- <text class="store-name">{{shopInfo.shopName}}</text> -->
+						<text class="store-address">12345444</text>
+						<!-- <u-icon name="arrow-right"></u-icon> -->
+					</view>
+				</view>
+			
+				<!-- 二维码区域 -->
+				<view class="qrcode-container">
+			
+					<view class="store-manager-content">
+						<text class="store-manager title">请小哥扫此二维码</text>
+					</view>
+			
+					<view class="store-manager-content">
+						<text class="store-manager">警告:系统将记录所有操作,请勿违规使用</text>
+					</view>
+					<!-- 空出二维码位置 -->
+					<view class="qrcode-placeholder">
+						<!-- 这里在实际应用中会显示二维码图片 -->
+						<!-- 使用说明 inviteType 1 是添加员工  0是邀请会员 -->
+						<image :src="qrCodeUrl"></image>
+			
+					</view>
+			
+					<view class="expiry-info">
+						<text class="text">此二维码300秒有效,点击</text>
+					</view>
+				</view>
+			
+				<!-- 使用说明 inviteType 1 是添加员工  0是邀请会员 -->
+				<!-- <view class="instructions" v-if="inviteType == '1'">
+					<text class="instructions-title">使用说明</text>
+					<view class="instructions-list">
+						<text class="instruction-item">1. 让员工使用微信扫描上方二维码</text>
+						<text class="instruction-item">2. 员工确认门店信息并提交申请</text>
+					</view>
+				</view>
+			
+				<view class="instructions" v-if="inviteType == '0'">
+					<text class="instructions-title">使用说明</text>
+					<view class="instructions-list">
+						<text class="instructions-content-title">1. 扫码申请加入门店会员</text>
+						<text class="instruction-item">会员扫描二维码后,可自主提交申请成为门店会员,审核通过后即可享受会员权益。</text>
+						<text class="instructions-content-title">2. 添加用户手机号直接添加门店会员</text>
+						<text class="instruction-item">输入用户手机号,直接为其开通门店会员资格</text>
+					</view>
+				</view> -->
+			
+			</scroll-view>
+		</view>
+
+	</view>
+</template>
+
+<script setup>
+	import {
+		ref,
+		onMounted
+	} from 'vue'
+
+	import {
+		onLoad,
+		onShow
+	} from '@dcloudio/uni-app' // 导入 UniApp 的生命周期
+
+	// 当前选中的tab
+	const currentTab = ref(0)
+	const linkType = ref(0) //0门店  1外聘 2平台
+
+	// 手机号
+	const phoneNumber = ref('')
+	const qrCodeUrl = ref('')
+	const imgData = ref('')
+	const searchUser = ref({
+		id: undefined
+	})
+
+	const tenantId = ref('')
+	const shopInfo = ref({})
+	const title = ref({})
+	const btnName = ref({})
+	const inviteType = ref('1') // 1 是添加员工  0是邀请会员
+
+
+	onLoad((option) => {
+		tenantId.value = option.tenantId
+		inviteType.value = option.inviteType
+		
+	})
+
+	onShow(() => {
+		// 1 是添加员工  0是邀请会员
+		// if (inviteType.value == '0') {
+		// 	getShopInfo()
+		// 	// getShopShareQrcode()
+		// }else{
+		// 	getShopInfo()
+		// }
+	})
+
+	// 切换Tab
+	const switchTab = (index) => {
+		currentTab.value = index
+	}
+
+	// 分享二维码
+	const shareQrcode = () => {
+		uni.showToast({
+			title: '分享功能',
+			icon: 'none'
+		})
+	}
+
+
+	const handleSearch = () => {
+		if (!ValidationUtils.validatePhone(phoneNumber.value)) {
+			uni.showToast({
+				title: "请填写正确手机号码",
+				icon: 'none'
+			})
+			return
+		}
+		uni.showLoading({
+			title: "正在查找,请稍等"
+		})
+		if (inviteType.value == '1') {
+			getStaffByPhone()
+		} else {
+			getUserByPhone()
+		}
+	}
+
+	const handleAdd = () => {
+		if (!searchUser.value.id) {
+			uni.showToast({
+				title: "请查找添加人员信息",
+				icon: 'none'
+			})
+			return
+		}
+		if (inviteType.value == '1') {
+			addEmployee()
+		} else {
+			addShareShopUser()
+		}
+	}
+
+	const addShareShopUser = async () => {
+		//promoterStatus推广状态(0 封禁 1 正常 )
+		try {
+			const params = {
+				applyUserId: searchUser.value.id,
+				tenantId: tenantId.value,
+				promoterStatus: 1
+			}
+			uni.showLoading()
+			const res = await addStaffApi(params)
+			if (res.code == 200) {
+				uni.showToast({
+					title: "添加成功",
+					icon: "success"
+				})
+				// 清空输入框
+				phoneNumber.value = ''
+				searchUser.value.id = undefined
+			}
+			uni.hideLoading()
+		} catch (error) {
+
+		} finally {
+			uni.hideLoading()
+		}
+	}
+
+
+	// 添加员工
+	const addEmployee = async () => {
+		try {
+			const params = {
+				userId: searchUser.value.id,
+				tenantId: tenantId.value,
+				linkType: linkType.value
+			}
+
+			uni.showLoading()
+			const res = await addStaffApi(params)
+			if (res.code == 200) {
+				uni.showToast({
+					title: "添加成功",
+					icon: "success"
+				})
+				// 清空输入框
+				phoneNumber.value = ''
+				searchUser.value.id = undefined
+			}
+			uni.hideLoading()
+
+		} catch (error) {
+
+		} finally {
+
+			uni.hideLoading()
+		}
+	}
+
+	const getShopInfo = () => {
+		const params = {
+			tenantId: tenantId.value,
+			linkType: linkType.value
+		}
+		getShopUserInfoApi(params).then(res => {
+			console.log("res======", res)
+			if (res.code == 200) {
+				shopInfo.value = res.data
+				//门店员工直接返回二维码
+				// 1 是添加员工  0是邀请会员
+				// if (inviteType.value == '1') {
+				qrCodeUrl.value = res.data.qrCodeUrl
+				// }
+			}
+		})
+	}
+
+	// const getShopShareQrcode = () => {
+	// 	//codeType 0:门店推广人 1门店用户
+	// 	const params = {
+	// 		userId: searchUser.value.id,
+	// 		tenantId: shopInfo.value.tenantId,
+	// 		codeType: inviteType.value,
+	// 		linkType: linkType.value
+	// 	}
+	// 	getShopShareQrcodeApi(params).then(res => {
+	// 		console.log('res====',res)
+	// 		if (res.code == 200 && res.data.length > 0) {
+	// 			//门店推广单独请求二维码
+	// 			// 1 是添加员工  0是邀请会员
+	// 			if (inviteType.value == '0') {
+	// 				qrCodeUrl.value = res.data[0].qrCodeUrl
+	// 			}
+	// 		} else {
+	// 			uni.showToast({
+	// 				title: '暂无查到相关二维码',
+	// 				icon: 'none'
+	// 			})
+	// 		}
+	// 	})
+	// }
+
+	const getStaffByPhone = () => {
+		uni.showLoading({
+			title: '正在查找'
+		})
+		const params = {
+			userPhone: phoneNumber.value
+		}
+		getStaffByPhoneApi(params).then(res => {
+			uni.hideLoading()
+			if (res.code == 200 && res.data.length > 0) {
+				searchUser.value = res.data[0]
+			} else {
+				uni.showToast({
+					title: "暂无此人",
+					icon: 'error'
+				})
+			}
+		}, err => {
+			uni.hideLoading()
+		})
+	}
+
+	const getUserByPhone = () => {
+		const params = {
+			userPhone: phoneNumber.value
+		}
+		queryUserByPhoneApi(params).then(res => {
+			uni.hideLoading()
+			if (res.code == 200 && res.data.length > 0) {
+				searchUser.value = res.data[0]
+			} else {
+				uni.showToast({
+					title: "暂无此人",
+					icon: 'error'
+				})
+			}
+		}, err => {
+			uni.hideLoading()
+		})
+	}
+
+
+	// 判断是否为网络图片
+	const isNetworkImage = (text) => {
+		// 检查是否以http或https开头
+		const networkPattern = /^(https?:\/\/[^\s]+)/i
+		if (networkPattern.test(text)) {
+			return true
+		}
+	}
+	// 保存Base64图片到相册
+	const saveBase64ToAlbum1 = async () => {
+		if (!qrCodeUrl.value) {
+			uni.showToast({
+				title: '暂无需要保存的图片',
+				icon: 'none'
+			})
+			return
+		}
+
+		if (isNetworkImage(qrCodeUrl.value)) {
+			saveImageToAlbum()
+			return
+		}
+		console.log('=====my_document====')
+		saveBaseImgFile(qrCodeUrl.value)
+	}
+
+
+	// 保存图片到相册
+	const saveImageToAlbum = async () => {
+		try {
+			// 第一步:下载网络图片到本地
+			const downloadResult = await downloadImage(qrCodeUrl.value)
+
+			if (!downloadResult.tempFilePath) {
+				throw new Error('图片下载失败')
+			}
+
+			// 第二步:保存到相册
+			await saveImage(downloadResult.tempFilePath)
+
+			uni.showToast({
+				title: '图片保存成功',
+				icon: 'success',
+				duration: 2000
+			})
+
+		} catch (error) {
+			console.error('保存失败:', error)
+
+			// 处理权限问题
+			if (error.errMsg && error.errMsg.includes('auth')) {
+				// 权限被拒绝,提示用户手动开启
+				uni.showModal({
+					title: '需要相册权限',
+					content: '保存图片需要访问您的相册权限,请在设置中开启权限后重试',
+					confirmText: '去设置',
+					success: (res) => {
+						if (res.confirm) {
+							// 跳转到应用设置页面
+							uni.openSetting()
+						}
+					}
+				})
+			} else {
+				uni.showModal({
+					title: '保存失败',
+					content: error.errMsg || '保存图片失败,请重试',
+					showCancel: false
+				})
+			}
+		} finally {
+			// saving.value = false
+		}
+	}
+
+	// 下载图片到本地临时文件
+	const downloadImage = (url) => {
+		return new Promise((resolve, reject) => {
+			uni.downloadFile({
+				url: url,
+				success: resolve,
+				fail: reject
+			})
+		})
+	}
+
+	// 保存图片到相册
+	const saveImage = (tempFilePath) => {
+		return new Promise((resolve, reject) => {
+			uni.saveImageToPhotosAlbum({
+				filePath: tempFilePath,
+				success: resolve,
+				fail: reject
+			})
+		})
+	}
+
+	const saveBaseImgFile = (base64) => {
+		const bitmap = new plus.nativeObj.Bitmap('base64')
+		bitmap.loadBase64Data(base64, () => {
+				const url = '_doc/' + new Date().getTime() + '.png'
+				bitmap.save(
+					url, {
+						overwrite: true // 是否覆盖  
+						// quality: 'quality'  // 图片清晰度  
+					},
+					(i) => {
+						uni.saveImageToPhotosAlbum({
+							filePath: url,
+							success: () => {
+								uni.showToast({
+									title: '图片保存成功',
+									duration: 2000
+								})
+								console.log('图片保存成功')
+								bitmap.clear()
+							}
+						})
+					},
+					(e) => {
+						uni.showToast({
+							title: '图片保存失败',
+							content: e.errMsg || '保存图片失败,请重试',
+							duration: 2000
+						})
+						console.log('图片保存失败')
+						bitmap.clear()
+					}
+				)
+			},
+			(e) => {
+				console.log('图片保存失败')
+				bitmap.clear()
+			}
+		)
+	}
+</script>
+
+<style lang="scss" scoped>
+	.container {
+		display: flex;
+		flex-direction: column;
+		height: 100vh;
+		background-color: #F5F7FA;
+	}
+
+	.header {
+		padding: 44rpx 0 30rpx 0;
+		text-align: center;
+		background-color: #fff;
+		border-bottom: 1rpx solid #eee;
+
+		.header-title {
+			font-size: 36rpx;
+			font-weight: bold;
+			color: #333;
+		}
+	}
+
+	// 自定义Tab布局 - 平均分配
+	.custom-tabs {
+		display: flex;
+		background-color: #fff;
+		border-bottom: 1rpx solid #eee;
+	}
+
+	.tab-item {
+		flex: 1;
+		text-align: center;
+		padding: 30rpx 0;
+		position: relative;
+
+		&.active {
+			.tab-text {
+				color: #2979ff;
+				font-weight: bold;
+			}
+
+			&::after {
+				content: '';
+				position: absolute;
+				bottom: 0;
+				left: 50%;
+				transform: translateX(-50%);
+				width: 80rpx;
+				height: 4rpx;
+				background-color: #2979ff;
+				border-radius: 2rpx;
+			}
+		}
+
+		.tab-text {
+			font-size: 32rpx;
+			color: #666;
+		}
+	}
+
+	// 内容区域
+	.tab-content {
+		padding: 16rpx;
+		flex: 1;
+		display: flex;
+		flex-direction: column;
+		overflow: hidden;
+		background-color: #F5F7FA;
+		margin-bottom: 140rpx;
+
+		.scroll-view {
+			flex: 1;
+			margin-bottom: 156rpx;
+		}
+	}
+
+	// 店铺信息
+	.store-info {
+		min-height: 124rpx;
+		background: #FFFFFF;
+		border-radius: 32rpx;
+		text-align: center;
+		margin-bottom: 20rpx;
+		padding: 32rpx;
+		display: flex;
+		justify-content: space-between;
+		align-items: center;
+		box-sizing: border-box;
+
+		.store-icon {
+			width: 80rpx;
+			height: 80rpx;
+			display: flex;
+			align-items: center;
+			justify-content: center;
+			background: rgba(0, 137, 255, 0.1);
+			border-radius: 16rpx 16rpx 16rpx 16rpx;
+			flex-shrink: 0;
+
+			image {
+				width: 48rpx;
+				height: 48rpx;
+			}
+		}
+
+		.store {
+			display: flex;
+
+			.store-name {
+				height: 44rpx;
+				font-weight: 400;
+				font-size: 28rpx;
+				color: #333333;
+				line-height: 44rpx;
+				text-align: left;
+			}
+
+			.store-address {
+				min-height: 44rpx;
+				line-height: 44rpx;
+				font-size: 28rpx;
+				color: #1B64F0;
+				text-align: left;
+			}
+
+		}
+
+	}
+
+	// 二维码区域
+	.qrcode-container {
+		background-color: #fff;
+		border-radius: 32rpx;
+		padding: 20rpx;
+		margin-bottom: 32rpx;
+		text-align: center;
+
+		.store-manager-content {
+			display: flex;
+			justify-content: center;
+			text-align: center;
+
+			image {
+				width: 48rpx;
+				height: 48rpx;
+				border-radius: 48rpx;
+			}
+
+
+			.store-manager {
+				height: 44rpx;
+				font-weight: 400;
+				font-size: 28rpx;
+				color: #666666;
+				line-height: 44rpx;
+
+				&.title {
+					height: 48rpx;
+					font-weight: bold;
+					font-size: 32rpx;
+					color: #333333;
+					line-height: 48rpx;
+
+				}
+			}
+		}
+
+
+		// 二维码占位区域
+		.qrcode-placeholder {
+			width: 400rpx;
+			height: 400rpx;
+			margin: 20rpx auto 30rpx;
+			border-radius: 16rpx;
+			background-color: #f5f5f5;
+			display: flex;
+			align-items: center;
+			justify-content: center;
+
+			/* 这里在实际应用中会显示二维码图片 */
+			/* 暂时使用背景色占位 */
+			image {
+				width: 400rpx;
+				height: 400rpx;
+				border-radius: 16rpx;
+			}
+		}
+
+		.expiry-info {
+			margin: 20rpx;
+			height: 84rpx;
+			background: #F5F7FA;
+			border-radius: 16rpx;
+
+			font-weight: 400;
+			font-size: 28rpx;
+			color: #3D3D3D;
+			line-height: 84rpx;
+			text-align: center;
+			.text{
+				&::after{
+					content: '刷新二维码';
+					color: #1B64F0;
+				}
+			}
+		}
+	}
+
+
+	// 使用说明
+	.instructions {
+		background-color: #fff;
+		border-radius: 16rpx;
+		padding: 16rpx;
+		margin-bottom: 16rpx;
+
+		.instructions-title {
+			display: inline-block;
+			font-size: 32rpx;
+			font-weight: bold;
+			margin-bottom: 16rpx;
+			color: #333;
+		}
+
+		.instructions-content-title {
+			display: inline-block;
+			font-size: 28rpx;
+			color: #333;
+			font-weight: bold;
+			margin-top: 8rpx;
+		}
+
+		.instructions-list {
+			display: flex;
+			flex-direction: column;
+		}
+
+		.instruction-item {
+			font-size: 26rpx;
+			color: #666;
+			line-height: 1.6;
+		}
+	}
+
+	// 按钮组
+	.button-group {
+		width: 100%;
+		height: 132rpx;
+		display: flex;
+		justify-content: space-around;
+		align-items: center;
+		position: fixed;
+		bottom: 0;
+		padding: 0rpx 32rpx;
+		background-color: #fff;
+
+		.button {
+			height: 88rpx;
+			line-height: 88rpx;
+			flex: 1;
+			text-align: center;
+			border-radius: 16rpx;
+			font-size: 30rpx;
+			font-weight: bold;
+
+			&.share-button {
+				color: #1B64F0;
+				margin-right: 32rpx;
+				background: rgba(0, 137, 255, 0.1);
+			}
+
+			&.save-button {
+				background-color: #1B64F0;
+				color: #fff;
+			}
+
+			.button-text {
+				font-size: 30rpx;
+			}
+		}
+
+
+	}
+
+	// 手机号邀请表单
+	.phone-form {
+		background-color: #fff;
+		border-radius: 16rpx;
+		padding: 16rpx;
+
+		.phone-title {
+			font-size: 32rpx;
+			font-weight: bold;
+			color: #333;
+			margin-bottom: 16rpx;
+			display: block;
+		}
+
+		.phone-input-group {
+			height: 88rpx;
+			display: flex;
+			border-radius: 16rpx;
+			overflow: hidden;
+			background-color: #F5F7FA;
+
+			.country-code {
+				width: 140rpx;
+				padding: 24rpx;
+				text-align: center;
+				font-size: 28rpx;
+				color: #333;
+				display: flex;
+				align-items: center;
+				justify-content: center;
+				border-right: 2rpx solid #e0e0e0;
+			}
+
+			.phone-input {
+				height: 88rpx;
+				line-height: 88rpx;
+				flex: 1;
+				padding: 24rpx;
+				font-size: 28rpx;
+			}
+		}
+
+	}
+
+
+	.employee-item-main {
+		display: flex;
+		align-items: center;
+		margin-top: 20rpx;
+		background-color: #fff;
+		border-radius: 32rpx;
+		padding: 20rpx;
+
+		.photo {
+			background-color: #F5F7FA;
+			width: 88rpx;
+			height: 88rpx;
+			border-radius: 80rpx;
+		}
+
+		.employee-main-info {
+			height: 84rpx;
+			margin-left: 20rpx;
+			align-self: center;
+			display: flex;
+			flex-direction: column;
+			justify-content: center;
+			margin-bottom: 20rpx;
+			flex: 1;
+
+			.employee-name {
+				height: 44rpx;
+				line-height: 44rpx;
+				font-size: 28rpx;
+				font-weight: 500;
+				color: #333333;
+			}
+
+			.employee-phone {
+				height: 40rpx;
+				line-height: 40rpx;
+				font-size: 24rpx;
+				color: #666666;
+			}
+
+		}
+
+		.employee-actions {
+			display: flex;
+			align-items: center;
+			height: 116rpx;
+			background-color: #fff;
+			border-radius: 32rpx;
+			margin-top: 16rpx;
+
+
+			.status-badge {
+				display: flex;
+				align-items: center;
+				font-size: 26rpx;
+				margin-right: 16rpx;
+
+				.enabled {
+					// background-color: #e6f7ff;
+					margin-left: 16rpx;
+					color: #1B64F0;
+				}
+
+				.disabled {
+					// background-color: #f5f5f5;
+					margin-left: 16rpx;
+					color: #333333;
+				}
+			}
+
+			.btn-view-order {
+				height: 40rpx;
+				font-weight: 400;
+				font-size: 24rpx;
+				color: #1B64F0;
+				line-height: 40rpx;
+				text-align: left;
+				margin-right: 16rpx;
+			}
+
+			.dismiss-btn {
+				width: 88rpx;
+				height: 60rpx;
+				line-height: 60rpx;
+				text-align: center;
+				background: #F52929;
+				border-radius: 8rpx;
+				font-size: 28rpx;
+				color: #FFFFFF;
+			}
+		}
+
+	}
+
+
+	.submit-button {
+		flex: 1;
+		height: 88rpx;
+		line-height: 88rpx;
+		background-color: #1B64F0;
+		color: #fff;
+		text-align: center;
+		border-radius: 16rpx;
+
+		.submit-text {
+			font-size: 32rpx;
+			font-weight: bold;
+		}
+	}
+</style>

+ 179 - 0
jd_logistics-app/pages/order/components/OrderFeesInfo.vue

@@ -0,0 +1,179 @@
+<template>
+	<view class="info-card">
+		<!-- <view class="card-header">
+			<image src="/static/images/verification/icon-fee.png"></image>
+			<text class="card-title">费用信息</text>
+		</view> -->
+		<view class="card-body">
+			<view class="info-row">
+				<text class="info-label">代收货款:</text>
+				<text class="info-value">¥{{orderDetail.shopOrderAmount}}</text>
+			</view>
+			<view class="info-row">
+				<text class="info-label">保价{{orderDetail.platformShopCommissionPercent}}%:</text>
+				<text class="info-value">{{orderDetail.platformServiceFee}}</text>
+			</view>
+			<view class="info-row">
+				<text class="info-label">全额保:</text>
+				<text class="info-value price">{{commission}}</text>
+			</view>
+			<view class="info-row">
+				<text class="info-label">签单返还:</text>
+				<text class="info-value">{{orderDetail.memberPromotionFee}}</text>
+			</view>
+			<view class="info-row">
+				<text class="info-label">包装服务:</text>
+				<text class="info-value">{{orderDetail.actualIncomeAmount}}</text>
+			</view>
+			<view class="info-row">
+				<text class="info-label">预约派送:</text>
+				<text class="info-value">{{orderDetail.actualIncomeAmount}}</text>
+			</view>
+			<view class="info-row">
+				<text class="info-label">指定签收:</text>
+				<text class="info-value">{{orderDetail.actualIncomeAmount}}</text>
+			</view>
+		</view>
+	</view>
+
+</template>
+
+<script setup>
+	import {
+		ref,
+		computed,
+		defineProps
+	} from 'vue'
+	import { onShow } from '@dcloudio/uni-app'
+
+	const props = defineProps({
+		isGrab: {
+			type: Boolean,
+			default: false
+		},
+		orderDetail: {
+			type: Object,
+			default: () => ({
+				dispatchInfo: null,
+				platformServiceFee:0, //平台服务费
+				memberPromotionFee:0, //会员推广费
+				actualIncomeAmount:0, //实际收入金额
+				goodsCommission: null,
+				goodsInfo: {},
+				grabInfo: {},
+				id: 22,
+				orderCreateTime: "2025-11-19 15:20:18",
+				refundReason: null,
+				serviceProviderInfo: null,
+				serviceTaskInfo: {},
+				shopConfirmStatus: null,
+				shopDesc: null,
+				shopDispatchVerifyStatus: "3",
+				shopEvaluateStatus: "1",
+				shopGoodsId: 10,
+				shopOrderAmount: 101,
+				shopOrderId: "6234567",
+				shopOrderNum: 1,
+				shopOrderStatus: "5",
+				shopPrice: 101,
+				shopRefundReviewStatus: null,
+				shopServiceStatus: "2",
+				shopUserTime: null,
+				userId: "",
+				platformShopCommissionPercent:'5'
+			})
+		}
+	})
+
+	// 计算属性 - 佣金单位
+	const commissionUnit = ref('元')
+	const percent = ref('5')
+	
+	// formData.commissionType === '0' ? '%' : '元'
+	const commission = computed(() => {
+		//bs_service_user_task.serivce_commission > bs_service_user_grab.service_commission > bs_shop_goods.service_commission
+		// if(props.orderDetail.serviceTaskInfo && props.orderDetail.serviceTaskInfo.serviceCommission){
+		// 	return props.orderDetail.serviceTaskInfo.serviceCommission
+		// }
+		// if(props.orderDetail.grabInfo && props.orderDetail.grabInfo.serviceCommission){
+		// 	return props.orderDetail.grabInfo.serviceCommission
+		// }
+		// // if(props.orderDetail.goodsInfo && props.orderDetail.goodsInfo.serviceCommission){
+		// // 	// commissionUnit.value =  props.orderDetail.goodsInfo.serviceCommission === '0' ? '%' : '元'
+		// // 	return props.orderDetail.goodsInfo.serviceCommission
+		// // }
+		// // platformPercent()
+		// return props.orderDetail.serviceCommission || props.orderDetail.goodsCommission || ''
+		return ''
+	})
+	
+	// onShow(()=>{
+	// 	platformPercent()
+	// })
+	
+	const platformPercent = ()=>{
+		getPlatformPerentApi().then(res=>{
+			if(res.code == 200){
+				percent.value = res.data.platformShopCommissionPercent
+			}
+		})
+	}
+</script>
+
+<style scoped lang="scss">
+	.info-card {
+		background-color: #ffffff;
+		border-radius: 16rpx;
+		overflow: hidden;
+		padding: 20rpx;
+
+		.card-header {
+			display: flex;
+			align-items: center;
+
+			image {
+				width: 35rpx;
+				height: 35rpx;
+			}
+
+			.card-title {
+				height: 48rpx;
+				line-height: 48rpx;
+				font-weight: 400;
+				font-size: 32rpx;
+				font-weight: bold;
+				color: #333;
+				margin-left: 10rpx;
+			}
+		}
+
+	}
+
+	.info-row {
+		height: 44rpx;
+		line-height: 44rpx;
+		display: flex;
+		justify-content: space-between;
+		align-items: center;
+		margin-top: 16rpx;
+
+		&:last-child {
+			border-bottom: none;
+		}
+
+		.info-label {
+			font-size: 28rpx;
+			color: #666666;
+		}
+
+		.info-value {
+			font-size: 28rpx;
+			color: #333;
+
+			&.price {
+				color: #FD5F3C;
+				font-weight: bold;
+			}
+		}
+	}
+</style>

+ 125 - 0
jd_logistics-app/pages/order/components/OrderInfo.vue

@@ -0,0 +1,125 @@
+<template>
+	<view class="info-card">
+		<!-- <view class="card-header">
+			<image src="/static/images/verification/icon-order.png"></image>
+			<text class="card-title">订单信息</text>
+		</view> -->
+		<view class="card-body">
+			<!-- 			<view class="info-row">
+				<text class="info-label">订单类型:</text>
+				<text class="info-value">普通订单</text>
+			</view> -->
+			<view class="info-row">
+				<text class="info-label">运单单号:</text>
+				<text class="info-value">{{orderDetail.shopOrderId}}</text>
+			</view>
+			<view class="info-row">
+				<text class="info-label">物品信息:</text>
+				<text class="info-value">{{orderDetail.userInfo.nickName}}</text>
+			</view>
+			<view class="info-row">
+				<text class="info-label">件数:</text>
+				<text class="info-value">{{orderDetail.userInfo.nickName}}</text>
+			</view>
+			<view class="info-row">
+				<text class="info-label">付款方式:</text>
+				<!-- <text class="duration">{{ ValidationUtils.encryptPhone(orderDetail.userInfo.userPhone) }}</text> -->
+				<text class="info-value">{{orderDetail.userInfo.userPhone}}</text>
+			</view>
+			<view class="info-row">
+				<text class="info-label">计费重量:</text>
+				<text class="info-value">{{orderDetail.shopUserTime}}</text>
+			</view>
+			<view class="info-row">
+				<text class="info-label">实际重量:</text>
+				<text class="info-value">{{orderDetail.orderCreateTime}}</text>
+			</view>
+			<view class="info-row">
+				<text class="info-label">实际体积:</text>
+				<text class="info-value price">¥{{orderDetail.shopOrderAmount}}</text>
+			</view>
+			<view class="info-row">
+				<text class="info-label">下单时间:</text>
+				<text class="info-value price">¥{{orderDetail.shopOrderAmount}}</text>
+			</view>
+		</view>
+	</view>
+
+</template>
+
+<script setup>
+	import {
+		defineProps
+	} from 'vue'
+	
+	const props = defineProps({
+		orderDetail: {
+			userInfo:{
+				userPhone:"",
+				nickName:''
+			},
+			shopOrderId:'',
+			orderCreateTime:'',
+			shopUserTime:'',
+			shopOrderAmount:''
+		}
+	})
+</script>
+
+<style scoped lang="scss">
+	.info-card {
+		background-color: #ffffff;
+		border-radius: 16rpx;
+		overflow: hidden;
+		padding: 20rpx;
+
+		.card-header {
+			display: flex;
+			align-items: center;
+
+			image {
+				width: 35rpx;
+				height: 35rpx;
+			}
+
+			.card-title {
+				height: 48rpx;
+				line-height: 48rpx;
+				font-weight: 400;
+				font-size: 32rpx;
+				font-weight: bold;
+				color: #333;
+				margin-left: 10rpx;
+			}
+		}
+
+	}
+
+	.info-row {
+		height: 44rpx;
+		line-height: 44rpx;
+		display: flex;
+		justify-content: space-between;
+		align-items: center;
+		margin-top: 16rpx;
+
+		&:last-child {
+			border-bottom: none;
+		}
+
+		.info-label {
+			font-size: 28rpx;
+			color: #666666;
+		}
+
+		.info-value {
+			font-size: 28rpx;
+			color: #333;
+
+			&.price {
+				color: #FD5F3C;
+				font-weight: bold;
+			}
+		}
+	}
+</style>

+ 783 - 0
jd_logistics-app/pages/order/components/TimePopup.vue

@@ -0,0 +1,783 @@
+<template>
+  <!-- 使用 u-popup 作为弹窗容器 -->
+  <u-popup 
+    :show="visible" 
+    mode="bottom" 
+    round="20"
+    :closeable="false"
+    @close="close"
+    :safeAreaInsetBottom="true"
+    customStyle="height: 80vh;"
+  >
+    <view class="time-picker-container">
+      <!-- 标题栏 -->
+      <view class="picker-header">
+        <text class="picker-title">期望上门时间</text>
+        <text class="close-btn" @tap="close">×</text>
+      </view>
+      
+      <!-- 主要内容区域:左侧日期 + 右侧时间 -->
+      <view class="main-content">
+        <!-- 左侧日期选择 -->
+        <scroll-view class="date-sidebar" scroll-y>
+          <view 
+            v-for="date in dateList" 
+            :key="date.value"
+            class="date-item"
+            :class="{ 
+              active: selectedDate === date.value,
+              today: date.isToday
+            }"
+            @tap="selectDate(date.value)"
+          >
+            <view class="date-content">
+              <text class="date-name">{{ date.label }}</text>
+              <text class="date-info">{{ date.month }}月{{ date.day }}日</text>
+              <text class="date-week">{{ date.week }}</text>
+            </view>
+          </view>
+        </scroll-view>
+        
+        <!-- 右侧时间选择 -->
+        <scroll-view class="time-content" scroll-y>
+          <!-- 推荐时间段(仅今天显示) -->
+          <view v-if="selectedDate === todayDate && withinOneHourSlot" class="recommend-section">
+            <view class="recommend-header">
+              <text class="recommend-title">一小时内</text>
+              <!-- <text class="recommend-desc">推荐时间:{{ withinOneHourSlot.label }}</text> -->
+            </view>
+            <view class="recommend-time"
+			 @tap="selectTime(withinOneHourSlot.value, true)">
+              <text class="time-value">{{ withinOneHourSlot.label }}</text>
+              <!-- <text class="time-tag">推荐</text> -->
+            </view>
+          </view>
+          
+          <!-- 时间段列表 -->
+          <view class="time-section">
+            <view class="section-title">可选时间段</view>
+            
+            <view v-if="loading" class="loading">加载中...</view>
+            
+            <view v-else class="time-list">
+              <view 
+                v-for="timeSlot in timeSlots" 
+                :key="timeSlot.value"
+                class="time-item"
+                :class="{ 
+                  active: selectedTime === timeSlot.value,
+                  disabled: timeSlot.disabled,
+                  night: timeSlot.night
+                }"
+                @tap="!timeSlot.disabled && selectTime(timeSlot.value, false)"
+              >
+                <text class="time-text">{{ timeSlot.label }}</text>
+                <text v-if="timeSlot.tag" class="time-tag">{{ timeSlot.tag }}</text>
+              </view>
+            </view>
+          </view>
+          
+          <!-- 提示信息 -->
+          <view class="notice-section">
+            <text class="notice-text">
+              部分区域支持夜间上门,具体以快递员联系为准
+            </text>
+          </view>
+        </scroll-view>
+      </view>
+      
+      <!-- 操作按钮 -->
+      <view class="action-bar">
+        <button 
+          class="confirm-btn" 
+          :class="{ active: selectedTime }"
+          @tap="confirm"
+        >
+          {{ buttonText }}
+        </button>
+      </view>
+    </view>
+  </u-popup>
+</template>
+
+<script setup>
+import { ref, computed, watch, onMounted, onUnmounted } from 'vue'
+
+const props = defineProps({
+  visible: {
+    type: Boolean,
+    default: false
+  },
+  // 显示天数
+  days: {
+    type: Number,
+    default: 3
+  },
+  // 开始时间
+  startTime: {
+    type: Number,
+    default: 9
+  },
+  // 结束时间
+  endTime: {
+    type: Number,
+    default: 21
+  },
+  // 是否自动选择推荐时间
+  autoSelect: {
+    type: Boolean,
+    default: true
+  }
+})
+
+const emit = defineEmits(['update:visible', 'close', 'confirm'])
+
+// 当前时间
+const currentTime = ref(new Date())
+const selectedDate = ref('')
+const selectedTime = ref('')
+const loading = ref(false)
+const isWithinOneHour = ref(false)
+
+// 计算当前时间20分钟后的时间
+const twentyMinutesLater = computed(() => {
+  const now = new Date()
+  now.setMinutes(now.getMinutes() + 10)
+  return now
+})
+
+// 计算一小时后的小时(向上取整)
+const oneHourLaterHour = computed(() => {
+  const now = new Date()
+  now.setHours(now.getHours() + 1)
+  return Math.ceil(now.getHours())
+})
+
+// 获取今天日期字符串
+const todayDate = computed(() => {
+  const today = new Date()
+  return formatDate(today)
+})
+
+// 生成日期列表
+const dateList = computed(() => {
+  const days = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']
+  const list = []
+  const today = new Date()
+  
+  for (let i = 0; i < props.days; i++) {
+    const date = new Date(today)
+    date.setDate(date.getDate() + i)
+    
+    const month = date.getMonth() + 1
+    const day = date.getDate()
+    const week = days[date.getDay()]
+    const dateStr = formatDate(date)
+    
+    let label = ''
+    if (i === 0) {
+      label = '今天'
+    } else if (i === 1) {
+      label = '明天'
+    } else {
+      label = '后天'
+    }
+    
+    list.push({
+      value: dateStr,
+      label: label,
+      week: week,
+      month: month,
+      day: day,
+      fullLabel: `${month}月${day}日 ${week}`,
+      isToday: i === 0,
+      isTomorrow: i === 1,
+      isDayAfterTomorrow: i === 2,
+      displayDate: `${date.getFullYear()}-${month.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')}`
+    })
+  }
+  
+  return list
+})
+
+// 基础时间段配置
+const baseTimeSlots = computed(() => {
+  const slots = []
+  const startHour = props.startTime
+  const endHour = props.endTime
+  const interval = 1 // 小时间隔
+  
+  for (let hour = startHour; hour < endHour; hour += interval) {
+    const start = hour
+    const end = hour + interval
+    const startStr = start.toString().padStart(2, '0')
+    const endStr = end.toString().padStart(2, '0')
+    
+    slots.push({
+      start: start,
+      end: end,
+      label: `${startStr}:00-${endStr}:00`,
+      value: `${startStr}:00-${endStr}:00`,
+      startHour: start,
+      endHour: end
+    })
+  }
+  
+  return slots
+})
+
+// 计算一小时内时间段
+const withinOneHourSlot = computed(() => {
+  if (!dateList.value.length || !dateList.value[0].isToday) return null
+  
+  const now = currentTime.value
+  const later20min = twentyMinutesLater.value
+  
+  // 计算开始时间:当前时间 + 20分钟,分钟向上取整到10的倍数
+  const startMinutes = later20min.getMinutes()
+  const roundedMinutes = Math.ceil(startMinutes / 10) * 10
+  let startHour = later20min.getHours()
+  let startMinute = roundedMinutes
+  
+  // 如果分钟超过60,小时加1,分钟归零
+  if (startMinute >= 60) {
+    startHour += 1
+    startMinute = 0
+  }
+  
+  // 计算结束时间:开始时间 + 1小时
+  let endHour = startHour + 1
+  let endMinute = startMinute
+  
+  // 如果开始时间已经超过结束时间限制,则不显示
+  if (startHour >= props.endTime) return null
+  
+  // 如果结束时间超过结束时间限制,则调整
+  if (endHour > props.endTime) {
+    endHour = props.endTime
+    endMinute = 0
+  }
+  
+  // 如果开始时间小于开始时间限制,则调整
+  if (startHour < props.startTime) {
+    startHour = props.startTime
+    startMinute = 0
+  }
+  
+  // 检查时间段是否有效(至少30分钟)
+  const slotDuration = (endHour - startHour) * 60 + (endMinute - startMinute)
+  if (slotDuration < 30) return null
+  
+  const startStr = formatTime(startHour, startMinute)
+  const endStr = formatTime(endHour, endMinute)
+  
+  return {
+    start: startHour + startMinute / 60,
+    end: endHour + endMinute / 60,
+    label: `(${startStr}-${endStr})`,
+    value: `${startStr}-${endStr}`,
+    isWithinOneHour: true,
+    startHour: startHour,
+    startMinute: startMinute,
+    endHour: endHour,
+    endMinute: endMinute
+  }
+})
+
+// 是否是夜间时间段
+const isNightTime = (hour) => {
+  return hour >= 18
+}
+
+// 根据选择的日期获取时间段
+const timeSlots = computed(() => {
+  const slots = []
+  const isToday = selectedDate.value === todayDate.value
+  
+  if (isToday) {
+    const oneHourLater = oneHourLaterHour.value
+    
+    // 添加普通时间段(开始时间从一小时后开始)
+    baseTimeSlots.value.forEach(slot => {
+      // 时间段开始时间必须在当前时间+1小时之后
+      const isDisabled = slot.start < oneHourLater
+      
+      if (!isDisabled) {
+        slots.push({
+          ...slot,
+          disabled: false,
+          night: false,
+          tag: ''
+        })		
+		// night: isNightTime(slot.start),
+      }
+    })
+  } else {
+    // 明天及以后显示所有时间段
+    baseTimeSlots.value.forEach(slot => {
+      slots.push({
+        ...slot,
+        disabled: false,
+        night: isNightTime(slot.start),
+        tag: ''
+      })
+    })
+  }
+  
+  return slots
+})
+
+// 按钮文本
+const buttonText = computed(() => {
+  if (!selectedTime.value) return '请选择上门时间'
+  return '确定'
+})
+
+// 初始化选择
+const initSelection = () => {
+  if (dateList.value.length > 0) {
+    selectedDate.value = dateList.value[0].value
+    
+    // 自动选择推荐时间或第一个可用时间
+    if (withinOneHourSlot.value && props.autoSelect) {
+      selectedTime.value = withinOneHourSlot.value.value
+      isWithinOneHour.value = true
+    } else {
+      const firstSlot = timeSlots.value[0]
+      if (firstSlot) {
+        selectedTime.value = firstSlot.value
+        isWithinOneHour.value = false
+      }
+    }
+  }
+}
+
+// 选择日期
+const selectDate = (date) => {
+  selectedDate.value = date
+  selectedTime.value = '' // 重置时间选择
+  isWithinOneHour.value = false
+}
+
+// 选择时间
+const selectTime = (time, isWithinOneHourFlag = false) => {
+  selectedTime.value = time
+  isWithinOneHour.value = isWithinOneHourFlag
+}
+
+// 格式化日期时间
+const formatDateTime = (dateStr, hour) => {
+  const date = new Date(dateStr)
+  const wholeHour = Math.floor(hour)
+  const minutes = Math.round((hour - wholeHour) * 60)
+  date.setHours(wholeHour, minutes, 0, 0)
+  
+  const year = date.getFullYear()
+  const month = String(date.getMonth() + 1).padStart(2, '0')
+  const day = String(date.getDate()).padStart(2, '0')
+  const hours = String(date.getHours()).padStart(2, '0')
+  const mins = String(date.getMinutes()).padStart(2, '0')
+  const seconds = String(date.getSeconds()).padStart(2, '0')
+  
+  return `${year}-${month}-${day} ${hours}:${mins}:${seconds}`
+}
+
+// 获取开始小时
+const getStartHour = (timeLabel) => {
+  if (isWithinOneHour.value) {
+    return withinOneHourSlot.value.startHour + withinOneHourSlot.value.startMinute / 60
+  }
+  
+  const match = timeLabel.match(/(\d{2}):/)
+  return match ? parseInt(match[1]) : 0
+}
+
+// 获取结束小时
+const getEndHour = (timeLabel) => {
+  if (isWithinOneHour.value) {
+    return withinOneHourSlot.value.endHour + withinOneHourSlot.value.endMinute / 60
+  }
+  
+  const match = timeLabel.match(/-(\d{2}):/)
+  return match ? parseInt(match[1]) : 0
+}
+
+// 确认选择
+const confirm = () => {
+  if (!selectedTime.value) return
+  
+  const selectedDateObj = dateList.value.find(d => d.value === selectedDate.value)
+  const selectedTimeSlot = isWithinOneHour.value ? withinOneHourSlot.value : 
+                          baseTimeSlots.value.find(s => s.value === selectedTime.value)
+  
+  if (!selectedDateObj || !selectedTimeSlot) return
+  
+  // 计算开始和结束时间
+  const startHour = getStartHour(selectedTime.value)
+  const endHour = getEndHour(selectedTime.value)
+  
+  // 计算具体的开始和结束时间字符串
+  const startTimeStr = formatDateTime(selectedDate.value, startHour)
+  const endTimeStr = formatDateTime(selectedDate.value, endHour)
+  
+  // 生成显示文本
+  let displayText = ''
+  if (isWithinOneHour.value) {
+    displayText = `${selectedDateObj.label} 一小时内`
+  } else {
+    displayText = `${selectedDateObj.label} ${selectedTime.value}`
+  }
+  
+  const timeData = {
+    date: selectedDate.value,
+    time: selectedTime.value,
+    dateLabel: selectedDateObj.label,
+    timeLabel: selectedTime.value,
+    fullLabel: displayText,
+    displayText: displayText,
+    startTime: startTimeStr,
+    endTime: endTimeStr,
+    isToday: selectedDateObj.isToday,
+    isImmediate: isWithinOneHour.value,
+    isNight: isNightTime(selectedTimeSlot.startHour),
+    startHour: startHour,
+    endHour: endHour
+  }
+  
+  emit('confirm', timeData)
+  close()
+}
+
+// 关闭弹框
+const close = () => {
+  emit('close')
+  emit('update:visible', false)
+}
+
+// 工具函数
+const formatDate = (date) => {
+  const year = date.getFullYear()
+  const month = String(date.getMonth() + 1).padStart(2, '0')
+  const day = String(date.getDate()).padStart(2, '0')
+  return `${year}-${month}-${day}`
+}
+
+const formatTime = (hour, minute) => {
+  return `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`
+}
+
+// 监听可见性变化
+watch(() => props.visible, (newVal) => {
+  if (newVal) {
+    currentTime.value = new Date()
+    initSelection()
+  }
+})
+
+// 定时更新当前时间
+let timer = null
+onMounted(() => {
+  timer = setInterval(() => {
+    if (props.visible) {
+      currentTime.value = new Date()
+    }
+  }, 60000) // 每分钟更新一次
+})
+
+// 组件销毁时清除定时器
+onUnmounted(() => {
+  if (timer) {
+    clearInterval(timer)
+  }
+})
+</script>
+
+<style scoped lang="less">
+/* 弹窗内部容器 */
+.time-picker-container {
+  height: 80vh;
+  display: flex;
+  flex-direction: column;
+}
+
+.picker-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 32rpx 32rpx 24rpx;
+  border-bottom: 1rpx solid #f0f0f0;
+  flex-shrink: 0;
+}
+
+.picker-title {
+  font-size: 36rpx;
+  font-weight: 600;
+  color: #333;
+}
+
+.close-btn {
+  font-size: 50rpx;
+  color: #999;
+  line-height: 40rpx;
+  padding: 10rpx;
+}
+
+/* 主要内容区域 */
+.main-content {
+  flex: 1;
+  display: flex;
+  overflow: hidden;
+}
+
+/* 左侧日期选择 */
+.date-sidebar {
+  width: 220rpx;
+  background-color: #f8f8f8;
+  border-right: 1rpx solid #f0f0f0;
+}
+
+.date-item {
+  padding: 32rpx 24rpx;
+  border-bottom: 1rpx solid #f0f0f0;
+}
+
+.date-item.active {
+  background-color: #fff;
+  position: relative;
+}
+
+.date-item.active::before {
+  content: '';
+  position: absolute;
+  left: 0;
+  top: 50%;
+  transform: translateY(-50%);
+  width: 6rpx;
+  height: 40rpx;
+  background-color: #1B64F0;
+  border-radius: 0 4rpx 4rpx 0;
+}
+
+.date-item.today .date-name {
+  color: #1B64F0;
+}
+
+.date-item.active .date-content {
+  color: #1B64F0;
+}
+
+.date-content {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  text-align: center;
+}
+
+.date-name {
+  font-size: 32rpx;
+  font-weight: 600;
+  color: #333;
+  margin-bottom: 8rpx;
+}
+
+.date-info {
+  font-size: 24rpx;
+  color: #666;
+  margin-bottom: 4rpx;
+}
+
+.date-week {
+  font-size: 22rpx;
+  color: #999;
+}
+
+/* 右侧时间选择 */
+.time-content {
+  flex: 1;
+  padding: 0 32rpx;
+  overflow-y: auto;
+}
+
+.recommend-section {
+  margin-top: 32rpx;
+  padding-bottom: 24rpx;
+  border-bottom: 1rpx solid #f0f0f0;
+}
+
+.recommend-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 20rpx;
+}
+
+.recommend-title {
+  font-size: 28rpx;
+  font-weight: 500;
+  color: #333;
+}
+
+.recommend-desc {
+  font-size: 24rpx;
+  color: #1B64F0;
+}
+
+.recommend-time {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 28rpx 24rpx;
+  // background: linear-gradient(135deg, #fff2f0 0%, #ffe6e6 100%);
+  border-radius: 16rpx;
+  border: 2rpx solid #1B64F0;
+}
+
+.time-value {
+  font-size: 32rpx;
+  font-weight: 500;
+  color: #1B64F0;
+}
+
+.recommend-time .time-tag {
+  font-size: 24rpx;
+  padding: 8rpx 16rpx;
+  background: #1B64F0;
+  color: white;
+  border-radius: 20rpx;
+}
+
+/* 时间段列表 */
+.time-section {
+  margin-top: 32rpx;
+  margin-bottom: 32rpx;
+}
+
+.section-title {
+  font-size: 28rpx;
+  font-weight: 500;
+  color: #333;
+  margin-bottom: 24rpx;
+}
+
+.time-list {
+  display: flex;
+  flex-direction: column;
+  gap: 20rpx;
+}
+
+.time-item {
+  padding: 28rpx 24rpx;
+  border: 2rpx solid #e8e8e8;
+  border-radius: 12rpx;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  position: relative;
+  transition: all 0.2s ease;
+}
+
+.time-item.active {
+  border-color: #1B64F0;
+  // background: #fff2f0;
+}
+
+.time-item.night {
+  border-color: #4a5cff;
+}
+
+.time-item:not(.disabled):active {
+  transform: scale(0.98);
+  opacity: 0.8;
+}
+
+.time-item.disabled {
+  opacity: 0.5;
+}
+
+.time-text {
+  font-size: 28rpx;
+  color: #333;
+}
+
+.time-item.active .time-text {
+  color: #1B64F0;
+  font-weight: 500;
+}
+
+.time-item.night .time-text {
+  color: #4a5cff;
+}
+
+.time-item .time-tag {
+  font-size: 20rpx;
+  padding: 4rpx 12rpx;
+  border-radius: 12rpx;
+  background: #f5f5f5;
+  color: #666;
+}
+
+.time-item.active .time-tag {
+  background: #1B64F0;
+  color: white;
+}
+
+.time-item.night .time-tag {
+  background: #4a5cff;
+  color: white;
+}
+
+/* 提示信息 */
+.notice-section {
+  padding: 24rpx;
+  margin-bottom: 32rpx;
+  background: #f8f8f8;
+  border-radius: 12rpx;
+}
+
+.notice-text {
+  font-size: 24rpx;
+  color: #666;
+  line-height: 1.4;
+}
+
+/* 操作按钮 */
+.action-bar {
+  padding: 24rpx 32rpx;
+  padding-top: 0;
+  background: #fff;
+  border-top: 1rpx solid #f0f0f0;
+  flex-shrink: 0;
+}
+
+.confirm-btn {
+  width: 100%;
+  height: 88rpx;
+  background: #f5f5f5;
+  color: #999;
+  border-radius: 44rpx;
+  font-size: 32rpx;
+  font-weight: 500;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  border: none;
+  transition: all 0.2s ease;
+}
+
+.confirm-btn.active {
+  background: #1B64F0;
+  color: white;
+}
+
+.confirm-btn.active:active {
+  opacity: 0.9;
+  transform: scale(0.99);
+}
+
+.loading {
+  text-align: center;
+  padding: 60rpx;
+  font-size: 28rpx;
+  color: #999;
+}
+</style>

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1008 - 0
jd_logistics-app/pages/order/create_order.vue


BIN
jd_logistics-app/static/img/address-delete.png


BIN
jd_logistics-app/static/img/address-edit.png


BIN
jd_logistics-app/static/img/create-order-address.png


BIN
jd_logistics-app/static/img/create-order-change.png


BIN
jd_logistics-app/static/img/icon-receive.png


BIN
jd_logistics-app/static/img/icon-send.png


BIN
jd_logistics-app/static/img/mine/icon-mine-qr.png