Просмотр исходного кода

Merge branch 'zhongqi-delivery'

shish 7 месяцев назад
Родитель
Сommit
11b08a96c7

+ 28 - 16
ghsApp/src/admin/billing/affirm.vue

@@ -31,9 +31,8 @@
 
                       <text style="position: absolute;right:300upx;top:2upx;font-size:28upx;color:green;font-weight:bold;" v-if="item.bigCount > 0">¥{{ parseFloat((Number(item.bigCount)*Number(item.userPrice)).toFixed(2)) }}</text>
                       <text style="position: absolute;right:300upx;top:2upx;font-size:28upx;color:green;font-weight:bold;" v-else>¥{{ parseFloat((Number(item.smallCount)*Number(item.userPrice)).toFixed(2)) }}</text>
-                      <text :class="[Number(item.cost) > Number(item.userPrice) && item.bigCount > 0 ? 'warning-price' : 'normal-price']" style="position: absolute;right:0upx;top:55upx;font-size:24upx;font-weight:bold;width:350upx;text-align:right;">
-                        ¥{{ item.cost?parseFloat(item.cost):0 }}
-                        <text style="margin-left:8upx;" v-if="Number(item.cost) > Number(item.userPrice) && item.bigCount > 0">售价过低</text>
+                      <text v-if="showFinance==1" :class="[Number(item.avCost) > Number(item.userPrice) && item.bigCount > 0 ? 'warning-price' : 'normal-price']" style="position: absolute;right:0upx;top:55upx;font-size:24upx;font-weight:bold;width:350upx;text-align:right;">
+                        成本¥{{ item.avCost?parseFloat(item.avCost):0 }}<text style="margin-left:8upx;" v-if="Number(item.avCost) > Number(item.userPrice) && item.bigCount > 0">售价过低</text>
                       </text>
 
                       <view class="open-bx" >
@@ -54,19 +53,18 @@
               <view class="operate-view" v-if="isScanEnv" @click="removeFromSave(option.customId)"> <text class="iconfont iconshanchu1"></text>清除花材 </view>
               <view class="operate-view" v-else @click="gobackEvent" style="font-size:32upx;font-weight:bold;"><text class="iconfont icongouwuche" style="margin-right:5upx;"></text>返回修改</view>
               <view class="describe-view">
-                <text>合计 ¥{{ allPrice }},</text>
-                <text>¥{{ allCount.cost }},</text>
-                <text>¥{{ parseFloat((Number(allPrice)-Number(allCount.cost)).toFixed(2)) }}</text>
+                <text>合计 ¥{{ allPrice }}</text>
+                <text>,{{ selectList.length }}种</text>
+                <text v-if="Number(totalItemNum.big)>0">,{{totalItemNum.big?parseFloat(totalItemNum.big):0}}扎</text>
+                <text v-if="Number(totalItemNum.small)>0">,{{totalItemNum.small?parseFloat(totalItemNum.small):0}}支</text>
+                <text>,{{ allCount.weight }}公斤</text>
               </view>
             </view>
-            <view class="summary-bar">
-              <view class="operate-view" v-if="isScanEnv" @click="pageToItemList()"><text class="iconfont iconzeng"></text>手动添加花材</view>
-              <view class="operate-view" v-if="isScanEnv == false"><text> </text></view>
-              <view class="describe-view">
-                <text>{{ selectList.length }}种,</text>
-                <text v-if="Number(totalItemNum.big)>0">{{totalItemNum.big?parseFloat(totalItemNum.big):0}}扎</text>
-                <text v-if="Number(totalItemNum.small)>0">{{totalItemNum.small?parseFloat(totalItemNum.small):0}}支</text>
-                <text>,{{ allCount.weight }}公斤</text>
+            <view class="summary-bar" v-if="hasFinance==1">
+              <view class="operate-view"></view>
+              <view class="describe-view" style="color:#3385ff;font-weight:bold;">
+                  <text v-if="showFinance==1" @click="getMyFinance">成本 ¥{{ allCount.avCost }},利润 ¥{{ parseFloat((Number(allPrice)-Number(allCount.avCost)).toFixed(2)) }}</text>
+                  <text v-else @click="getMyFinance">查看财务</text>
               </view>
             </view>
           </view>
@@ -306,7 +304,7 @@ import { getAllStaff } from "@/api/shop-admin"
 import { mapActions, mapGetters } from "vuex";
 import { getUserDet} from "@/api/member"
 import ModalModule from "@/components/plugin/modal"
-import { getAllWl } from "@/api/shop"
+import { getStaffInfo } from "@/api/staff"
 import MxDatePicker from '@/components/mx-datepicker/mx-datepicker.vue';
 export default {
   name: "affirm",
@@ -376,6 +374,8 @@ export default {
       currentShop:{default:0},
       book:0,
       selectStaff: { id: '', name: '' },
+      showFinance:0,
+      hasFinance:0,
     };
   },
   onLoad (option) {
@@ -422,6 +422,15 @@ export default {
 	  //#endif
 
     this.listenScanItem()
+
+
+    getStaffInfo().then(res=>{
+      if(res.code == 1){
+        let staffInfo = res.data.staff?res.data.staff:[]
+        this.hasFinance = staffInfo.finance?staffInfo.finance:0
+      }
+    })
+
   },
 	onShow(){
 		if(!this.$util.isEmpty(uni.getStorageSync("newClient"))){
@@ -502,6 +511,9 @@ export default {
   },
   methods: {
     ...mapActions(["initMerchantInfo"]),
+    getMyFinance(){
+      this.showFinance = this.showFinance == 1 ? 0 : 1
+    },
     bindHistoryDateChange(){
 			this.pickerType = 'history'
 			this.showPicker = true
@@ -873,7 +885,7 @@ export default {
           display: flex;
           align-items: center;
           color: #333;
-          font-size: 28upx;
+          font-size: 26upx;
           font-weight:bold;
           .price {
             margin-left:8upx;

+ 14 - 7
ghsApp/src/admin/delivery/allDelivery.vue

@@ -3,7 +3,7 @@
 
     <!-- 地址选择区 -->
     <view class="address-section">
-      <view class="address-item address-send">
+      <view class="address-item address-send" @click="changeAddress('send')">
         <view class="address-label">
           <view class="label-text" style="color: #1abc9c">发</view>
         </view>
@@ -16,7 +16,7 @@
         </view>
       </view>
 
-      <view class="address-item address-receive">
+      <view class="address-item address-receive" @click="changeAddress('receive')">
         <view class="address-label">
           <view class="label-text" style="color: #e74c3c">收</view>
         </view>
@@ -168,9 +168,6 @@ export default {
             address: ''
         },
         deliveryList: [],
-        //     { name: '闪送', price: '19.00', type: '两轮' },
-        //     { name: '达达秒送', price: '11.30', type: '团送' },
-        // ],
         weight: 1,
         pickupTime: {
             label: '立即取件',
@@ -220,8 +217,6 @@ export default {
     // 从路由参数获取订单ID,可用于后续加载真实数据
     if (options && options.orderId) {
       this.orderId = options.orderId;
-      this.loadOrderData();
-      this.handleLoadDelivery();
     }
 
 		//返回订单列表页不需要刷新
@@ -230,6 +225,10 @@ export default {
 		prevPage.$vm.fromDetail = {status:1}
 
   },
+  onShow() {
+    this.loadOrderData();
+    this.handleLoadDelivery();
+  },
   created() {
       if (this.deliveryList.length > 0 && !this.selectedDelivery) {
           this.selectedDelivery = this.deliveryList[0].name;
@@ -282,7 +281,15 @@ export default {
   },
   methods: {
     init() {},
+    changeAddress(type) {
+      if(type == 'receive') {
+        uni.navigateTo({url: '/pagesOrder/modify?id='+this.orderId})
+      }
 
+      if(type == 'send') {
+        uni.navigateTo({url: '/admin/shop/add?id='+this.getLoginInfo.shopId})
+      }
+    },
     // 清空运力列表
     clearDeliveryList() {
       this.deliveryList = [];

+ 4 - 0
ghsApp/src/api/staff/index.js

@@ -82,4 +82,8 @@ export const getStaffAuthCode = data => {
 //添加员工
 export const createStaff = data => {
 	return https.post('/shop-admin/add-staff', data)
+}
+
+export const getStaffInfo = data => {
+	return https.get('/shop-admin/get-staff-info', data)
 }

+ 1 - 4
ghsApp/src/components/app-area-sel.vue

@@ -6,12 +6,9 @@
 					<div class="map-top-tit">地址</div>
 					<app-close icon="iconguanbi" @close="hidePopup" />
 				</div>
-				<!-- 搜索 -->
 				<div class="map-search">
-					<app-search-module ref="aaaaa" placeholder="请输入地址搜索" :focus="false" @input="searchFn" />
+					<app-search-module ref="aaaaa" fontSize="30" height="120" placeholder="请输入地址搜索" :focus="false" @input="searchFn" />
 				</div>
-				
-				<!-- 列表 -->
 				<scroll-view class="near-list" scroll-y>
 					<view v-for="(item,index) in nearListData" :key="index" @click="switchAddress(item,index)" class="near-item">
 						<div class="current-site" :class="{'active' : currentSelectAddress === index}"></div>

+ 1 - 1
ghsApp/src/components/module/app-search.vue

@@ -1,6 +1,6 @@
 <template>
 	<div class="app-search-module" :style="{ height: height + 'upx' }">
-		<div class="map-search" :style="{ backgroundColor: backColor }" style="height:72upx">
+		<div class="map-search" :style="{ backgroundColor: backColor }" style="height:90upx">
 			<div class="icon-wrap" v-if="isIcon">
 				<i class="iconfont" :class="[icon]"></i>
 			</div>

+ 1 - 38
ghsApp/src/components/plugin/simple-address.vue

@@ -79,24 +79,6 @@
 						</view>
 					</view>
 					
-					<!-- 热门城市 -->
-					<view class="hot-section">
-						<view class="section-title">
-							<text class="section-title-text">热门城市</text>
-						</view>
-						<view class="hot-cities">
-							<view 
-								v-for="(city, index) in hotCities" 
-								:key="index"
-								class="hot-city-item"
-								:class="{ 'selected': isSelected(city) }"
-								@click="selectHotCity(city)"
-							>
-								<text class="hot-city-text">{{ city.cityName }}</text>
-							</view>
-						</view>
-					</view>
-					
 					<!-- 省份城市列表 -->
 					<view class="province-section">
 						<view class="section-title">
@@ -199,18 +181,7 @@ export default {
 			selectedCity: null,
 			expandedProvinces: [],
 			scrollIntoView: '',
-			recentCities: [],
-			hotCities: [
-				{ provinceCode: '530000', cityCode: '530100', provinceName: '云南省', cityName: '昆明市', label: '云南省 昆明市' },
-				{ provinceCode: '110000', cityCode: '110100', provinceName: '北京市', cityName: '北京市', label: '北京市' },
-				{ provinceCode: '310000', cityCode: '310100', provinceName: '上海市', cityName: '上海市', label: '上海市' },
-				{ provinceCode: '440000', cityCode: '440100', provinceName: '广东省', cityName: '广州市', label: '广东省 广州市' },
-				{ provinceCode: '440000', cityCode: '440300', provinceName: '广东省', cityName: '深圳市', label: '广东省 深圳市' },
-				{ provinceCode: '330000', cityCode: '330100', provinceName: '浙江省', cityName: '杭州市', label: '浙江省 杭州市' },
-				{ provinceCode: '320000', cityCode: '320100', provinceName: '江苏省', cityName: '南京市', label: '江苏省 南京市' },
-				{ provinceCode: '510000', cityCode: '510100', provinceName: '四川省', cityName: '成都市', label: '四川省 成都市' },
-				{ provinceCode: '420000', cityCode: '420100', provinceName: '湖北省', cityName: '武汉市', label: '湖北省 武汉市' }
-			]
+			recentCities: []
 		}
 	},
 	watch: {
@@ -336,14 +307,6 @@ export default {
 			this._$emit('onConfirm')
 			this.close()
 		},
-		// 选择热门城市
-		selectHotCity(city) {
-			this.selectedCity = city
-			this.saveRecentCity(city)
-			// 自动确认并关闭
-			this._$emit('onConfirm')
-			this.close()
-		},
 		// 切换省份展开状态
 		toggleProvince(index) {
 			const expandIndex = this.expandedProvinces.indexOf(index)

+ 7 - 7
ghsApp/src/mixins/product.js

@@ -83,7 +83,7 @@ export default {
 			let bigLength = 0;
 			let smallLength = 0;
 			let weight = 0
-			let cost = 0
+			let avCost = 0
 			if (this.selectList) {
 				for (const item of this.selectList) {
 					bigLength += Number(item.bigCount)
@@ -92,17 +92,17 @@ export default {
 					let currentWeight = Number(thisWeight)*Number(item.bigCount)
 					weight = Number(weight) + Number(currentWeight)
 
-					let thisCost = item.cost ? item.cost : 0
-					let currentCost = Number(thisCost)*Number(item.bigCount)
-					cost = Number(cost) + Number(currentCost)
+					let thisAvCost = item.avCost ? item.avCost : 0
+					let currentAvCost = Number(thisAvCost)*Number(item.bigCount)
+					avCost = Number(avCost) + Number(currentAvCost)
 				}
 				weight = weight.toFixed(2)
 				weight = parseFloat(weight)
 
-				cost = cost.toFixed(2)
-				cost = parseFloat(cost)
+				avCost = avCost.toFixed(2)
+				avCost = parseFloat(avCost)
 			}
-			return {bigLength:bigLength,smallLength:smallLength,weight:weight,cost:cost};
+			return {bigLength:bigLength,smallLength:smallLength,weight:weight,avCost:avCost};
 		},
 		//当前选中商品列表中是否有没有库存的商品
 		hasNoStock() {

+ 8 - 2
ghsApp/src/pagesOrder/detail.vue

@@ -381,7 +381,7 @@
 
 				<block v-if="detailInfo.staffFinance==1">
 					<tui-list-cell class="line-cell" :hover="false" @click="toggleFinanceInfo">
-						<div class="tui-title">财务信息</div>
+						<div class="tui-title">查看财务</div>
 						<div v-if="showFinanceInfo" class="detail-price_box" style="font-weight:normal;font-size:30upx;">成本¥{{ detailInfo.remainCost?parseFloat(detailInfo.remainCost):0 }} 利润¥{{ detailInfo.profit?parseFloat(detailInfo.profit):0 }}</div>
 						<div v-else class="detail-price_box" style="color:#ada8a8;font-size:30upx;font-weight:normal;">点击查看</div>
 					</tui-list-cell>
@@ -1199,6 +1199,12 @@ export default {
 		},
 		confirmReach(info){
 			let that = this
+
+
+			if(![-1, -4].includes(that.detailInfo.sendStatus)){
+				that.$msg('已使用跑腿配送')
+				return
+			}
 			that.$util.confirmModal({content:'确认已经送达?'},() => {
 				confirmReachFn({id:info.id}).then(res=>{
 					if(res.code == 1){
@@ -1581,7 +1587,7 @@ export default {
 
 <style lang="scss" scoped>
 .info-content_box {
-	padding: 0 20upx 100upx;
+	padding: 1rpx 20rpx 100rpx;
 
 	.order-msg-blo {
 		.msg-list {

+ 9 - 0
ghsApp/src/pagesOrder/modify.vue

@@ -48,6 +48,7 @@ import SimpleAddress from '@/components/plugin/simple-address'
 import AppAreaSel from '@/components/app-area-sel'
 const form = require('@/utils/formValidation.js')
 import { modifyAddress } from '@/api/order'
+import { getInfo } from '@/api/shop'
 import {getHasMap} from "@/api/express"
 export default {
 	name: 'modify',
@@ -97,6 +98,14 @@ export default {
 					this.couldNavigation = 1
 				}
 			})
+			getInfo().then(res=>{
+				if(res.code == 1){
+					let city = res.data.city ? res.data.city : ''
+					let province = res.data.province?res.data.province:''
+					this.form.province = province
+					this.form.city = city
+				}
+			})
 		},
 		//省市联动
 		openAddres() {

+ 144 - 1
hdApp/src/admin/billing/affirmGhs.vue

@@ -245,6 +245,9 @@
 				<view>
 					<text :class="isFreeDelivery ? 'delivery-price-free' : 'delivery-price-normal'">¥ {{ form.sendCost }}</text>
 					<text v-if="isFreeDelivery" class="free-delivery-tag">【免跑腿费】</text>
+					<text v-if="showDeliveryPolicy" class="delivery-policy-link" @click="showDeliveryPolicyModal">
+						<text class="iconfont iconchangjianwentixiangguanwenti2 policy-icon"></text>包配送政策
+					</text>
 				</view>
 			</tui-list-cell>
 					<tui-list-cell class="line-cell" :hover="false" :arrow="true" v-if="displayAddress == true" @click="modifyAddress">
@@ -304,6 +307,20 @@
 			</view>
 		</uni-popup>
 
+		<uni-popup ref="deliveryPolicyPopup" type="center" background-color="#fff">
+			<view class="policy-popup-content">
+				<view class="policy-title">包配送政策</view>
+				<scroll-view scroll-y="true" class="policy-scroll">
+					<view class="policy-list">
+						<block v-for="(item, index) in deliveryPolicyList" :key="index">
+							<view class="policy-item">{{ item }}</view>
+						</block>
+					</view>
+				</scroll-view>
+				<view class="policy-btn" @click="closeDeliveryPolicy">知道了</view>
+			</view>
+		</uni-popup>
+
 	</view>
 </template>
 
@@ -403,7 +420,8 @@ export default {
 			deliveryQuotes: [], // 跑腿平台报价列表
 			selectedDeliveryIndex: -1, // 选中的报价索引
 			deliveryQuotesLoading: false, // 报价加载状态
-			selectedDeliveryData: null // 选中的报价数据
+			selectedDeliveryData: null, // 选中的报价数据
+			deliveryPolicyList: [] // 包配送政策列表
 		};
 	},
 	onLoad() {
@@ -479,6 +497,9 @@ export default {
 			
 			// 条件2: 如果距离大于免费公里数,判断hcMap
 			if(distanceInMeters > freeKmInMeters){
+				if(this.ghsInfo.hcMap && typeof this.ghsInfo.hcMap == 'string'){
+					this.ghsInfo.hcMap = JSON.parse(this.ghsInfo.hcMap)
+				}
 				// 判断hcMap是否为空
 				if(this.ghsInfo.hcMap && Array.isArray(this.ghsInfo.hcMap) && this.ghsInfo.hcMap.length > 0){
 					// 获取花材数量和总价
@@ -501,6 +522,31 @@ export default {
 			
 			return false
 		},
+		/**
+		 * 是否显示包配送政策
+		 */
+		showDeliveryPolicy() {
+			if (!this.ghsInfo) return false
+			
+			// 检查 hcFreeKm
+			const hasFreeKm = this.ghsInfo.hcFreeKm && Number(this.ghsInfo.hcFreeKm) > 0
+			
+			// 检查 hcMap
+			let hasMap = false
+			let mapData = this.ghsInfo.hcMap
+			if(mapData && typeof mapData == 'string'){
+				try {
+					mapData = JSON.parse(mapData)
+				} catch(e) {
+					// 解析失败忽略
+				}
+			}
+			if(mapData && Array.isArray(mapData) && mapData.length > 0){
+				hasMap = true
+			}
+			
+			return hasFreeKm || hasMap
+		},
 		/**
 		 * 计算总金额
 		 * @returns {number}
@@ -548,6 +594,47 @@ export default {
 			this.form.wlId = this.wlSelData.id
 			this.form.wlName = this.wlSelData.name
 		},
+		// 展示包配送政策弹窗
+		showDeliveryPolicyModal() {
+			this.deliveryPolicyList = []
+			
+			// 1. hcFreeKm 规则
+			if (this.ghsInfo.hcFreeKm && Number(this.ghsInfo.hcFreeKm) > 0) {
+				this.deliveryPolicyList.push(`${Number(this.ghsInfo.hcFreeKm)}公里内免费配送`)
+			}
+			
+			// 2. hcMap 规则
+			let mapData = this.ghsInfo.hcMap
+			if(mapData && typeof mapData == 'string'){
+				try {
+					mapData = JSON.parse(mapData)
+				} catch(e) {
+					mapData = []
+				}
+			}
+			if(mapData && Array.isArray(mapData) && mapData.length > 0){
+				mapData.forEach(rule => {
+					const num = Number(rule.num) || 0
+					const price = Number(rule.price) || 0
+					const distance = Number(rule.distance) || 0
+					
+					this.deliveryPolicyList.push(`满${num}扎${price}元,${distance}公里内免费配送`)
+				})
+			}
+			
+			if (this.deliveryPolicyList.length === 0) {
+				uni.showToast({
+					title: '暂无详细配送政策',
+					icon: 'none'
+				})
+				return
+			}
+			
+			this.$refs.deliveryPolicyPopup.open()
+		},
+		closeDeliveryPolicy() {
+			this.$refs.deliveryPolicyPopup.close()
+		},
 		closeRemind(){
 			this.$refs.selectFlowerNumRef.close()
 			this.lackList = []
@@ -1440,4 +1527,60 @@ export default {
 	color: #3385FF;
 	margin-left: 10upx;
 }
+
+.delivery-policy-link {
+	color: rgb(201, 52, 52);
+	font-size: 28upx;
+	margin-left: 26upx;
+	text-decoration: underline;
+}
+
+.policy-icon {
+	font-size: 28upx;
+	margin-left: 4upx;
+}
+
+.policy-popup-content {
+	width: 600upx;
+	background-color: #fff;
+	border-radius: 20upx;
+	padding: 30upx;
+	display: flex;
+	flex-direction: column;
+	align-items: center;
+}
+.policy-title {
+	font-size: 34upx;
+	font-weight: bold;
+	color: #333;
+	margin-bottom: 30upx;
+}
+.policy-scroll {
+	width: 100%;
+	max-height: 50vh;
+	margin-bottom: 30upx;
+}
+.policy-list {
+	width: 100%;
+}
+.policy-item {
+	font-size: 30upx;
+	color: #666;
+	margin-bottom: 20upx;
+	text-align: left;
+	line-height: 1.5;
+	display: list-item;
+	list-style-type: disc;
+	margin-left: 40upx;
+}
+.policy-btn {
+	width: 100%;
+	height: 80upx;
+	line-height: 80upx;
+	text-align: center;
+	background-color: #3385ff;
+	color: #fff;
+	font-size: 32upx;
+	border-radius: 40upx;
+}
 </style>

+ 16 - 4
hdApp/src/admin/delivery/allDelivery.vue

@@ -3,7 +3,7 @@
 
     <!-- 地址选择区 -->
     <view class="address-section">
-      <view class="address-item address-send">
+      <view class="address-item address-send" @click="changeAddress('send')">
         <view class="address-label">
           <view class="label-text" style="color: #1abc9c">发</view>
         </view>
@@ -16,7 +16,7 @@
         </view>
       </view>
 
-      <view class="address-item address-receive">
+      <view class="address-item address-receive" @click="changeAddress('receive')">
         <view class="address-label">
           <view class="label-text" style="color: #e74c3c">收</view>
         </view>
@@ -217,8 +217,6 @@ export default {
     // 从路由参数获取订单ID,可用于后续加载真实数据
     if (options && options.orderId) {
       this.orderId = options.orderId;
-      this.loadOrderData();
-      this.handleLoadDelivery();
     }
 
     //返回订单列表页时不需要刷新
@@ -227,6 +225,10 @@ export default {
     prevPage.$vm.refreshPage = 0
 
   },
+  onShow() {
+    this.loadOrderData();
+    this.handleLoadDelivery();
+  },
   created() {
       if (this.deliveryList.length > 0 && !this.selectedDelivery) {
           this.selectedDelivery = this.deliveryList[0].name;
@@ -280,6 +282,16 @@ export default {
   methods: {
     init() {},
 
+    // 修改发货与收货地址
+    changeAddress(type) {
+      if(type == 'receive') {
+        uni.navigateTo({url: '/admin/order/modify?id='+this.orderId})
+      }
+
+      if(type == 'send') {
+        uni.navigateTo({url: '/admin/shop/add?id='+this.getLoginInfo.shopId})
+      }
+    },
     // 清空运力列表
     clearDeliveryList() {
       this.deliveryList = [];

+ 3 - 3
hdApp/src/admin/home/order.vue

@@ -71,8 +71,8 @@
               <view class="admin-button-com default" v-else>通知制作</view>
 
               <block v-if="item.status == 2">
-                <view class="admin-button-com middle" v-if="item.sendType == 1" @click.stop="getOrderFn(item)">确认取货</view>
-                <view class="admin-button-com middle" v-else @click.stop="sendOrderFn(item)">确认发货</view>
+                <view class="admin-button-com middle" v-if="item.sendType == 1" @click.stop="getOrderFn(item)">取货</view>
+                <view class="admin-button-com middle" v-else @click.stop="sendOrderFn(item)">自配送</view>
               </block>
               <block v-if="item.status == 3">
                 <view class="admin-button-com middle" @click.stop="confirmReach(item)">确认送达</view>
@@ -389,7 +389,7 @@ export default {
     },
     sendOrderFn(item){
       let that = this
-      that.$util.confirmModal({content:'确认发货?'},() => {
+      that.$util.confirmModal({content:'自配送?'},() => {
         sendOrder({id:item.id}).then(res=>{
           if(res.code == 1){
             that.$msg('操作成功')

+ 1 - 1
hdApp/src/admin/ll/eventDetail.vue

@@ -24,7 +24,7 @@
 				<view class="order-info_box">
 					<view>失信证据:</view>
 					<view>
-						<image :src="item" v-for="(item, index) in eventInfo.proveSmall" mode="widthFix" 
+						<image :src="item" v-for="(item, index) in eventInfo.proveSmall" :key="index" mode="widthFix" 
 						style="width:90upx;height:90upx;display:inline-block;float:right;margin-left:10upx;" @click="showImg(index)"></image>
 					</view>
 				</view>

+ 1 - 5
hdApp/src/admin/order/components/sel-ship-manage.vue

@@ -205,11 +205,7 @@ export default {
       };
     },
     sendSelfFn(num) {
-      if (num == 0) {
-        this.selfShipHint = "确认自己送?";
-      } else {
-        this.selfShipHint = "确认发货?";
-      }
+      this.selfShipHint = "确认自配送?";
       this.selfShipModal = true;
       this.form = {
         sendType: 2,

+ 2 - 2
hdApp/src/admin/order/detail.vue

@@ -47,7 +47,7 @@
           <view class="goods-list" v-if="!$util.isEmpty(orderInfo.goodsInfoList)">
             <detailGoods 
               v-for="(item, index) in orderInfo.goodsInfoList" 
-              :key="`goods-${index}`" 
+              :key="index" 
               :info="item">
             </detailGoods>
           </view>
@@ -56,7 +56,7 @@
           <view class="items-list" v-if="!$util.isEmpty(orderInfo.itemInfoList)">
             <detailItem 
               v-for="(item, index) in orderInfo.itemInfoList" 
-              :key="`item-${index}`" 
+              :key="index" 
               :info="item">
             </detailItem>
           </view>

+ 5 - 5
hdApp/src/components/module/app-search.vue

@@ -1,6 +1,6 @@
 <template>
-	<div class="app-search-module" :style="{ height: height + 'rpx' }">
-		<div class="map-search" :style="{ backgroundColor: backColor }" style="height: 80upx">
+	<div class="app-search-module" :style="{ height: height + 'upx' }">
+		<div class="map-search" :style="{ backgroundColor: backColor }" style="height:90upx">
 			<div class="icon-wrap" v-if="isIcon">
 				<i class="iconfont" :class="[icon]"></i>
 			</div>
@@ -12,7 +12,7 @@
 				v-model="search"
 				:focus="focus"
 				@input="inputFn" @focus="inputEmptyFn"
-				:style="{ fontSize: fontSize + 'rpx' }"
+				:style="{ fontSize: fontSize + 'upx' }"
 				:placeholder="placeholder"
 				placeholder-class="placeholder"
 				@confirm="searchFn"
@@ -24,7 +24,7 @@
 			<button
 				v-if="isTextBtn"
 				class="search-btn"
-				:style="{ fontSize: fontSize + 'rpx' }"
+				:style="{ fontSize: fontSize + 'upx' }"
 				@click="searchFn"
 			>
 				{{ btnText }}
@@ -32,7 +32,7 @@
 			<button
 				v-else
 				class="search-btn admin-button-com middle blue"
-				:style="{ fontSize: fontSize + 'rpx' }"
+				:style="{ fontSize: fontSize + 'upx' }"
 				@click="searchFn"
 			>
 				{{ btnText }}

+ 1 - 38
hdApp/src/components/plugin/simple-address.vue

@@ -79,24 +79,6 @@
 						</view>
 					</view>
 					
-					<!-- 热门城市 -->
-					<view class="hot-section">
-						<view class="section-title">
-							<text class="section-title-text">热门城市</text>
-						</view>
-						<view class="hot-cities">
-							<view 
-								v-for="(city, index) in hotCities" 
-								:key="index"
-								class="hot-city-item"
-								:class="{ 'selected': isSelected(city) }"
-								@click="selectHotCity(city)"
-							>
-								<text class="hot-city-text">{{ city.cityName }}</text>
-							</view>
-						</view>
-					</view>
-					
 					<!-- 省份城市列表 -->
 					<view class="province-section">
 						<view class="section-title">
@@ -203,18 +185,7 @@ export default {
 			selectedCity: null,
 			expandedProvinces: [],
 			scrollIntoView: '',
-			recentCities: [],
-			hotCities: [
-				{ provinceCode: '530000', cityCode: '530100', provinceName: '云南省', cityName: '昆明市', label: '云南省 昆明市' },
-				{ provinceCode: '110000', cityCode: '110100', provinceName: '北京市', cityName: '北京市', label: '北京市' },
-				{ provinceCode: '310000', cityCode: '310100', provinceName: '上海市', cityName: '上海市', label: '上海市' },
-				{ provinceCode: '440000', cityCode: '440100', provinceName: '广东省', cityName: '广州市', label: '广东省 广州市' },
-				{ provinceCode: '440000', cityCode: '440300', provinceName: '广东省', cityName: '深圳市', label: '广东省 深圳市' },
-				{ provinceCode: '330000', cityCode: '330100', provinceName: '浙江省', cityName: '杭州市', label: '浙江省 杭州市' },
-				{ provinceCode: '320000', cityCode: '320100', provinceName: '江苏省', cityName: '南京市', label: '江苏省 南京市' },
-				{ provinceCode: '510000', cityCode: '510100', provinceName: '四川省', cityName: '成都市', label: '四川省 成都市' },
-				{ provinceCode: '420000', cityCode: '420100', provinceName: '湖北省', cityName: '武汉市', label: '湖北省 武汉市' }
-			]
+			recentCities: []
 		}
 	},
 	watch: {
@@ -340,14 +311,6 @@ export default {
 			this._$emit('onConfirm')
 			this.close()
 		},
-		// 选择热门城市
-		selectHotCity(city) {
-			this.selectedCity = city
-			this.saveRecentCity(city)
-			// 自动确认并关闭
-			this._$emit('onConfirm')
-			this.close()
-		},
 		// 切换省份展开状态
 		toggleProvince(index) {
 			const expandIndex = this.expandedProvinces.indexOf(index)

+ 1 - 1
mallApp/src/components/app-area-sel.vue

@@ -7,7 +7,7 @@
           <app-close icon="iconguanbi" @close="hidePopup" />
         </div>
         <div class="map-search">
-          <app-search-module ref="aaaaa" placeholder="请输入你的收货地址" :focus="isFocus" @input="searchFn" />
+          <app-search-module ref="aaaaa" height="100" fontSize="32" placeholder="请输入收货地址" :focus="isFocus" @input="searchFn" />
         </div>
         <scroll-view class="near-list" scroll-y>
           <view v-for="(item,index) in nearListData" :key="index" @click="switchAddress(item,index)" class="near-item" >

+ 4 - 4
mallApp/src/components/module/app-search.vue

@@ -1,16 +1,16 @@
 <template>
-	<div class="app-search-module" :style="{height: height + 'rpx'}">
+	<div class="app-search-module" :style="{height: height + 'upx'}">
 		<div class="map-search" :style="{backgroundColor: backColor}">
 			<div class="icon-wrap" v-if="isIcon">
 				<i class="iconfont" :class="[icon]" style="font-size:38upx;"></i>
 			</div>
 			<div class="input-wrap">
-				<input type="text" ref="searchInput" v-model="search" :focus="focus" @input="inputFn" :style="{fontSize: fontSize + 'rpx'}" :placeholder="placeholder" placeholder-class="placeholder" />
+				<input type="text" ref="searchInput" v-model="search" :focus="focus" @input="inputFn" :style="{fontSize: fontSize + 'upx'}" :placeholder="placeholder" placeholder-class="placeholder" />
 			</div>
 		</div>
 		<block v-if="isBtn">
-			<button v-if="isTextBtn" class="search-btn" :style="{fontSize: fontSize + 'rpx'}" @click="searchFn">{{ btnText }}</button>
-			<button v-else class="search-btn admin-button-com middle blue" :style="{fontSize: fontSize + 'rpx'}" @click="searchFn">{{ btnText }}</button>
+			<button v-if="isTextBtn" class="search-btn" :style="{fontSize: fontSize + 'upx'}" @click="searchFn">{{ btnText }}</button>
+			<button v-else class="search-btn admin-button-com middle blue" :style="{fontSize: fontSize + 'upx'}" @click="searchFn">{{ btnText }}</button>
 		</block>
 	</div>
 </template>

+ 1 - 38
mallApp/src/components/plugin/simple-address.vue

@@ -79,24 +79,6 @@
 						</view>
 					</view>
 					
-					<!-- 热门城市 -->
-					<view class="hot-section">
-						<view class="section-title">
-							<text class="section-title-text">热门城市</text>
-						</view>
-						<view class="hot-cities">
-							<view 
-								v-for="(city, index) in hotCities" 
-								:key="index"
-								class="hot-city-item"
-								:class="{ 'selected': isSelected(city) }"
-								@click="selectHotCity(city)"
-							>
-								<text class="hot-city-text">{{ city.cityName }}</text>
-							</view>
-						</view>
-					</view>
-					
 					<!-- 省份城市列表 -->
 					<view class="province-section">
 						<view class="section-title">
@@ -203,18 +185,7 @@ export default {
 			selectedCity: null,
 			expandedProvinces: [],
 			scrollIntoView: '',
-			recentCities: [],
-			hotCities: [
-				{ provinceCode: '530000', cityCode: '530100', provinceName: '云南省', cityName: '昆明市', label: '云南省 昆明市' },
-				{ provinceCode: '110000', cityCode: '110100', provinceName: '北京市', cityName: '北京市', label: '北京市' },
-				{ provinceCode: '310000', cityCode: '310100', provinceName: '上海市', cityName: '上海市', label: '上海市' },
-				{ provinceCode: '440000', cityCode: '440100', provinceName: '广东省', cityName: '广州市', label: '广东省 广州市' },
-				{ provinceCode: '440000', cityCode: '440300', provinceName: '广东省', cityName: '深圳市', label: '广东省 深圳市' },
-				{ provinceCode: '330000', cityCode: '330100', provinceName: '浙江省', cityName: '杭州市', label: '浙江省 杭州市' },
-				{ provinceCode: '320000', cityCode: '320100', provinceName: '江苏省', cityName: '南京市', label: '江苏省 南京市' },
-				{ provinceCode: '510000', cityCode: '510100', provinceName: '四川省', cityName: '成都市', label: '四川省 成都市' },
-				{ provinceCode: '420000', cityCode: '420100', provinceName: '湖北省', cityName: '武汉市', label: '湖北省 武汉市' }
-			]
+			recentCities: []
 		}
 	},
 	watch: {
@@ -340,14 +311,6 @@ export default {
 			this._$emit('onConfirm')
 			this.close()
 		},
-		// 选择热门城市
-		selectHotCity(city) {
-			this.selectedCity = city
-			this.saveRecentCity(city)
-			// 自动确认并关闭
-			this._$emit('onConfirm')
-			this.close()
-		},
 		// 切换省份展开状态
 		toggleProvince(index) {
 			const expandIndex = this.expandedProvinces.indexOf(index)

+ 142 - 2
mallApp/src/pages/billing/affirmGhs.vue

@@ -112,6 +112,9 @@
 							<view>
 								<text :class="isFreeDelivery ? 'delivery-price-free' : 'delivery-price-normal'">¥ {{ form.sendCost }}</text>
 								<text v-if="isFreeDelivery" class="free-delivery-tag">【免跑腿费】</text>
+								<text v-if="showDeliveryPolicy" class="delivery-policy-link" @click="showDeliveryPolicyModal">
+									<text class="iconfont iconchangjianwentixiangguanwenti2 policy-icon"></text>包配送政策
+								</text>
 							</view>
 						</tui-list-cell>
 					</block>
@@ -168,7 +171,7 @@
 	<mx-date-picker :show="showDatePicker" format="yyyy-mm-dd" type="date" :value="defaultPickerDate" :show-tips="true" @confirm="confirmDatePicker" @cancel="showDatePicker = false" />
 
 	<!-- 配送时间选择弹框 -->
-	<uni-popup ref="timePopup" type="bottom" background-color="#fff">
+		<uni-popup ref="timePopup" type="bottom" background-color="#fff">
 		<view class="time-picker-popup">
 			<view class="popup-header">
 				<text class="popup-title">选择配送时间</text>
@@ -231,6 +234,20 @@
 		</view>
 	</uni-popup>
 
+	<uni-popup ref="deliveryPolicyPopup" type="center" background-color="#fff">
+		<view class="policy-popup-content">
+			<view class="policy-title">包配送政策</view>
+			<scroll-view scroll-y="true" class="policy-scroll">
+				<view class="policy-list">
+					<block v-for="(item, index) in deliveryPolicyList" :key="index">
+						<view class="policy-item">{{ item }}</view>
+					</block>
+				</view>
+			</scroll-view>
+			<view class="policy-btn" @click="closeDeliveryPolicy">知道了</view>
+		</view>
+	</uni-popup>
+
 </view>
 </template>
 <script>
@@ -283,7 +300,8 @@ export default {
 			selectedDeliveryIndex: -1, // 选中的报价索引
 			deliveryQuotesLoading: false, // 报价加载状态
 			selectedDeliveryData: null, // 选中的报价数据
-			isFreeDelivery: false // 是否免跑腿费
+			isFreeDelivery: false, // 是否免跑腿费
+			deliveryPolicyList: [] // 包配送政策列表
 		};
 	},
 	onShow() {
@@ -350,6 +368,31 @@ export default {
 			}
 			return price.toFixed(2)
 		},
+		/**
+		 * 是否显示包配送政策
+		 */
+		showDeliveryPolicy() {
+			if (!this.shopInfo) return false
+			
+			// 检查 hcFreeKm
+			const hasFreeKm = this.shopInfo.hcFreeKm && Number(this.shopInfo.hcFreeKm) > 0
+			
+			// 检查 hcMap
+			let hasMap = false
+			let mapData = this.shopInfo.hcMap
+			if(mapData && typeof mapData == 'string'){
+				try {
+					mapData = JSON.parse(mapData)
+				} catch(e) {
+					// 解析失败忽略
+				}
+			}
+			if(mapData && Array.isArray(mapData) && mapData.length > 0){
+				hasMap = true
+			}
+			
+			return hasFreeKm || hasMap
+		},
 	},
 	onLoad(){
 		if(this.option.account){
@@ -377,6 +420,47 @@ export default {
 			this.form.reachPeriod = `${this.selectedHour}:${this.selectedMinute}`
 			this.closeTimePopup()
 		},
+		// 展示包配送政策弹窗
+		showDeliveryPolicyModal() {
+			this.deliveryPolicyList = []
+			
+			// 1. hcFreeKm 规则
+			if (this.shopInfo.hcFreeKm && Number(this.shopInfo.hcFreeKm) > 0) {
+				this.deliveryPolicyList.push(`${Number(this.shopInfo.hcFreeKm)}公里内免费配送`)
+			}
+			
+			// 2. hcMap 规则
+			let mapData = this.shopInfo.hcMap
+			if(mapData && typeof mapData == 'string'){
+				try {
+					mapData = JSON.parse(mapData)
+				} catch(e) {
+					mapData = []
+				}
+			}
+			if(mapData && Array.isArray(mapData) && mapData.length > 0){
+				mapData.forEach(rule => {
+					const num = Number(rule.num) || 0
+					const price = Number(rule.price) || 0
+					const distance = Number(rule.distance) || 0
+					
+					this.deliveryPolicyList.push(`满${num}扎${price}元,${distance}公里内免费配送`)
+				})
+			}
+			
+			if (this.deliveryPolicyList.length === 0) {
+				uni.showToast({
+					title: '暂无详细配送政策',
+					icon: 'none'
+				})
+				return
+			}
+			
+			this.$refs.deliveryPolicyPopup.open()
+		},
+		closeDeliveryPolicy() {
+			this.$refs.deliveryPolicyPopup.close()
+		},
 		checkFreeDelivery(){
 			// 不显示跑腿费时,不需要判断
 			if(this.displaySendCost == false){
@@ -1125,4 +1209,60 @@ export default {
     opacity: 0;
   }
 }
+
+.delivery-policy-link {
+	color: rgb(201, 52, 52);
+	font-size: 28upx;
+	margin-left: 26upx;
+	text-decoration: underline;
+}
+
+.policy-icon {
+	font-size: 28upx;
+	margin-left: 4upx;
+}
+
+.policy-popup-content {
+	width: 600upx;
+	background-color: #fff;
+	border-radius: 20upx;
+	padding: 30upx;
+	display: flex;
+	flex-direction: column;
+	align-items: center;
+}
+.policy-title {
+	font-size: 34upx;
+	font-weight: bold;
+	color: #333;
+	margin-bottom: 30upx;
+}
+.policy-scroll {
+	width: 100%;
+	max-height: 50vh;
+	margin-bottom: 30upx;
+}
+.policy-list {
+	width: 100%;
+}
+.policy-item {
+	font-size: 30upx;
+	color: #666;
+	margin-bottom: 20upx;
+	text-align: left;
+	line-height: 1.5;
+	display: list-item;
+	list-style-type: disc;
+	margin-left: 40upx;
+}
+.policy-btn {
+	width: 100%;
+	height: 80upx;
+	line-height: 80upx;
+	text-align: center;
+	background-color: #3385ff;
+	color: #fff;
+	font-size: 32upx;
+	border-radius: 40upx;
+}
 </style>

+ 114 - 1
mallApp/src/pages/order/components/app-delivery.vue

@@ -72,6 +72,9 @@
               <view class="tui-input">
                 <text :class="isFreeDelivery ? 'delivery-price-free' : 'delivery-price-normal'">¥ {{ form.sendCost }}</text>
                 <text v-if="isFreeDelivery" class="free-delivery-tag">【免跑腿费】</text>
+                <text v-if="showDeliveryPolicy" class="delivery-policy-link" @click="showDeliveryPolicyModal">
+									<text class="iconfont iconchangjianwentixiangguanwenti2 policy-icon"></text>包配送政策
+								</text>
               </view>
           </tui-list-cell>
           
@@ -189,6 +192,20 @@
     <view v-if="showDatePicker" class="date-picker-mask" @click="showDatePicker = false"></view>
     
     <mx-date-picker :show="showDatePicker" format="yyyy-mm-dd" type="date" :value="defaultPickerDate" :show-tips="true" @confirm="confirmDatePicker" @cancel="showDatePicker = false" />
+
+    <uni-popup ref="deliveryPolicyPopup" type="center" background-color="#fff">
+      <view class="policy-popup-content">
+        <view class="policy-title">包配送政策</view>
+        <scroll-view scroll-y="true" class="policy-scroll">
+          <view class="policy-list">
+            <block v-for="(item, index) in deliveryPolicyList" :key="index">
+              <view class="policy-item">{{ item }}</view>
+            </block>
+          </view>
+        </scroll-view>
+        <view class="policy-btn" @click="closeDeliveryPolicy">知道了</view>
+      </view>
+    </uni-popup>
   </div>
 </template>
 
@@ -285,12 +302,20 @@ export default {
       selectedDeliveryIndex: -1, // 选中的报价索引
       deliveryQuotesLoading: false, // 报价加载状态
       selectedDeliveryData: null, // 选中的报价数据
-      goodsInfo: {}
+      goodsInfo: {},
+      deliveryPolicyList: []
     };
   },
   computed: {
     ...mapGetters({ orderShop: "getOrderShop" }),
     ...mapGetters({ shopUser: "getShopUser" }),
+    /**
+     * 是否显示包配送政策
+     */
+    showDeliveryPolicy() {
+      // 只要有免费公里数或者有加收费用配置且不是收配送费,就显示政策
+      return (Number(this.hsFreeKm) > 0 || Number(this.hsAddFee) > 0) && !this.isFreight;
+    },
     /**
      * 是否免跑腿费
      * @returns {boolean}
@@ -504,6 +529,38 @@ export default {
       }
       
       return 0;
+    },
+    // 展示包配送政策弹窗
+    showDeliveryPolicyModal() {
+      this.deliveryPolicyList = []
+      
+      const freeKm = Number(this.hsFreeKm) || 0
+      const addFee = Number(this.hsAddFee) || 0
+
+      if (freeKm > 0) {
+        this.deliveryPolicyList.push(`${freeKm}公里内免费配送`)
+      }
+
+      if (addFee > 0) {
+        if (freeKm > 0) {
+          this.deliveryPolicyList.push(`超出${freeKm}公里后,每公里收取${addFee}元`)
+        } else {
+          this.deliveryPolicyList.push(`每公里收取${addFee}元配送费`)
+        }
+      }
+      
+      if (this.deliveryPolicyList.length === 0) {
+        uni.showToast({
+          title: '暂无详细配送政策',
+          icon: 'none'
+        })
+        return
+      }
+      
+      this.$refs.deliveryPolicyPopup.open()
+    },
+    closeDeliveryPolicy() {
+      this.$refs.deliveryPolicyPopup.close()
     }
   }
 };
@@ -995,4 +1052,60 @@ export default {
     opacity: 0;
   }
 }
+
+.delivery-policy-link {
+	color: rgb(201, 52, 52);
+	font-size: 28upx;
+	margin-left: 26upx;
+	text-decoration: underline;
+}
+
+.policy-icon {
+	font-size: 28upx;
+	margin-left: 4upx;
+}
+
+.policy-popup-content {
+	width: 600upx;
+	background-color: #fff;
+	border-radius: 20upx;
+	padding: 30upx;
+	display: flex;
+	flex-direction: column;
+	align-items: center;
+}
+.policy-title {
+	font-size: 34upx;
+	font-weight: bold;
+	color: #333;
+	margin-bottom: 30upx;
+}
+.policy-scroll {
+	width: 100%;
+	max-height: 50vh;
+	margin-bottom: 30upx;
+}
+.policy-list {
+	width: 100%;
+}
+.policy-item {
+	font-size: 30upx;
+	color: #666;
+	margin-bottom: 20upx;
+	text-align: left;
+	line-height: 1.5;
+	display: list-item;
+	list-style-type: disc;
+	margin-left: 40upx;
+}
+.policy-btn {
+	width: 100%;
+	height: 80upx;
+	line-height: 80upx;
+	text-align: center;
+	background-color: #3385ff;
+	color: #fff;
+	font-size: 32upx;
+	border-radius: 40upx;
+}
 </style>