Browse Source

Merge branch 'redesign‌-260706' of http://git.huaml.com/zhh/front-end into redesign‌-260706

ouyang 5 days ago
parent
commit
fa924e3f1e
35 changed files with 345 additions and 156 deletions
  1. 10 0
      .vscode/extensions.json
  2. 3 0
      .vscode/settings.json
  3. 10 0
      hdApp/jsconfig.json
  4. 1 1
      hdApp/src/admin/cg/me.vue
  5. 1 1
      hdApp/src/admin/hb/list.vue
  6. 2 2
      hdApp/src/admin/home/components/mall-home-panel.vue
  7. 2 2
      hdApp/src/admin/home/me.vue
  8. 33 10
      hdApp/src/admin/home/member.vue
  9. 15 13
      hdApp/src/admin/home/order.vue
  10. 14 7
      hdApp/src/admin/homePageConfig/groupBuy.vue
  11. 6 2
      hdApp/src/admin/homePageConfig/groupBuyGoodsEdit.vue
  12. 14 7
      hdApp/src/admin/homePageConfig/seckill.vue
  13. 6 3
      hdApp/src/admin/homePageConfig/seckillGoodsEdit.vue
  14. 29 50
      hdApp/src/admin/order/refund.vue
  15. 1 1
      hdApp/src/pages.json
  16. 0 1
      hdApp/src/static/icons/client-birthday.svg
  17. 0 1
      hdApp/src/static/icons/order-clock.svg
  18. 0 1
      hdApp/src/static/icons/order-number.svg
  19. 0 1
      hdApp/src/static/icons/order-product-no.svg
  20. 0 0
      hdApp/src/static/icons/order-remark.svg
  21. 0 1
      hdApp/src/static/icons/order-sub-account-name.svg
  22. 31 0
      hdApp/tsconfig.json
  23. 4 0
      mallApp/src/api/custom/index.js
  24. 6 2
      mallApp/src/api/group-buy/index.js
  25. 1 1
      mallApp/src/api/refund/index.js
  26. 4 4
      mallApp/src/components/home/activitySection.vue
  27. 18 4
      mallApp/src/components/item/plugin/modal.vue
  28. 2 2
      mallApp/src/pages/balance/changeList.vue
  29. 22 13
      mallApp/src/pages/groupBuy/detail.vue
  30. 9 6
      mallApp/src/pages/home/cart.vue
  31. 15 13
      mallApp/src/pages/home/recent.vue
  32. 1 1
      mallApp/src/pages/order/detail.vue
  33. 50 4
      mallApp/src/pages/order/refund.vue
  34. 4 2
      mallApp/src/plugins/luch-request_0.0.7/request.js
  35. 31 0
      mallApp/tsconfig.json

+ 10 - 0
.vscode/extensions.json

@@ -0,0 +1,10 @@
+{
+  "recommendations": [
+    "Vue.volar",
+    "simonhe.vscode-alias-jump",
+    "uni-helper.uni-helper-vscode"
+  ],
+  "unwantedRecommendations": [
+    "octref.vetur"
+  ]
+}

+ 3 - 0
.vscode/settings.json

@@ -0,0 +1,3 @@
+{
+  "editor.gotoLocation.multipleDefinitions": "goto"
+}

+ 10 - 0
hdApp/jsconfig.json

@@ -0,0 +1,10 @@
+{
+  "compilerOptions": {
+    "paths": {
+      "@/*": ["./src/*"]
+    },
+    "jsx": "preserve",
+    "checkJs": false
+  },
+  "exclude": ["node_modules", "dist", "unpackage"]
+}

+ 1 - 1
hdApp/src/admin/cg/me.vue

@@ -387,7 +387,7 @@ export default {
       } else if (item.key == "book") {
         this.$util.pageTo({ url: "/admin/book/index" });
       } else if (item.key == "shopInvite") {
-        // 与 home/me「邀请店」一致:进入分佣 / 邀请 hub
+        // 与 home/me「邀请店」一致:进入分佣 / 邀请 hub
         this.$util.pageTo({ url: "/admin/home/shopInviteHub" });
       } else if (item.key == "modifyName") {
         this.$util.pageTo({ url: "/admin/home/edit" });

+ 1 - 1
hdApp/src/admin/hb/list.vue

@@ -228,7 +228,7 @@ export default {
         this.showSearch = false
         return
       }
-      getList({ page: 1, name: value, type: 0 }).then((res) => {
+      getList({ page: 1, name: value, type: 0, searchStyle: 1 }).then((res) => {
         this.searchList = res.data && res.data.list ? res.data.list : []
         this.showSearch = true
       })

+ 2 - 2
hdApp/src/admin/home/components/mall-home-panel.vue

@@ -10,7 +10,7 @@
             </view>
             <view class="brand-info">
               <view class="brand-name">{{ shopInfo.merchantName || '' }}</view>
-              <view class="brand-desc">{{ shopInfo.shopName||'' }} · 店铺管理</view>
+              <view class="brand-desc">{{ shopInfo.shopName||'' }}</view>
             </view>
           </view>
           <view class="hero-actions">
@@ -467,7 +467,7 @@ export default {
 
 .brand-desc {
   margin-top: 6upx;
-  font-size: 20upx;
+  font-size: 22upx;
   color: rgba(255, 255, 255, 0.88);
   white-space: nowrap;
   overflow: hidden;

+ 2 - 2
hdApp/src/admin/home/me.vue

@@ -297,10 +297,10 @@ export default {
       outAmountShow: false,
       inAmountShow: false,
       menuList: [
-        { key: "shopInvite", name: "邀请店", icon: "member-level" },
+        { key: "shopInvite", name: "邀请店", icon: "member-level" },
         { key: "address", name: "修改门店", icon: "shop_modify" },
         { key: "book", name: "使用教程", icon: "book" },
-        { key: "lakala", name: "收款账户管理", icon: "pay-code" },
+        { key: "lakala", name: "收款账户", icon: "pay-code" },
         { key: "password", name: "密码修改", icon: "password" },
         { key: "cashSet", name: "提现账号", icon: "bell" },
         { key: "mall", name: "零售商城", icon: "shop-outline" },

+ 33 - 10
hdApp/src/admin/home/member.vue

@@ -295,6 +295,9 @@ export default {
     shortDateTime (value) {
       return value ? value.substr(5, 11) : "";
     },
+    /**
+     * 余额展示文案:负值显示绝对值;正值显示余额;0 显示 0
+     */
     amountText (item) {
       const balance = Number(item.balance) || 0;
       if (balance < 0) {
@@ -303,19 +306,25 @@ export default {
       if (balance > 0) {
         return `${this.formatNumber(balance)}`;
       }
-      return "";
+      return "0";
     },
     decorateMemberList () {
       this.list.data.forEach(item => {
         this.$set(item, "amountClass", this.getAmountClass(item));
       });
     },
+    /**
+     * 余额样式:欠款红 / 有余额蓝 / 零余额灰
+     */
     getAmountClass (item) {
-      const type = this.tabs[this.tabIndex] ? this.tabs[this.tabIndex].type : 0;
-      if (type == 1 || Number(item.balance) >= 0) {
+      const balance = Number(item.balance) || 0;
+      if (balance < 0) {
+        return "negative";
+      }
+      if (balance > 0) {
         return "positive";
       }
-      return "negative";
+      return "zero";
     },
     formatNumber (value) {
       return value ? parseFloat(value) : 0;
@@ -337,13 +346,10 @@ export default {
       };
       return map[Number(item.overTimeUnExpend)] || "";
     },
+    /**
+     * 未下单提示图标:与「没有下过 / 1月未下」等统一用时钟,不用单独生日图标
+     */
     statusIcon (item) {
-      if (item.passStatus != 1) {
-        return "client-clock";
-      }
-      if (Number(item.overTimeUnExpend) == 180 || Number(item.overTimeUnExpend) == 365) {
-        return "client-birthday";
-      }
       return "client-clock";
     }
   }
@@ -739,6 +745,23 @@ export default {
   color: #ff1f1f;
 }
 
+.meta-item.zero {
+  color: #9aa3ad;
+}
+
+/* image 无法继承 color,用 filter 把黑色 SVG 染成对应色 */
+.meta-item.positive .meta-icon-balance {
+  filter: brightness(0) saturate(100%) invert(36%) sepia(98%) saturate(2476%) hue-rotate(201deg) brightness(101%) contrast(101%);
+}
+
+.meta-item.negative .meta-icon-balance {
+  filter: brightness(0) saturate(100%) invert(18%) sepia(97%) saturate(6400%) hue-rotate(358deg) brightness(98%) contrast(118%);
+}
+
+.meta-item.zero .meta-icon-balance {
+  filter: brightness(0) saturate(100%) invert(70%) sepia(6%) saturate(300%) hue-rotate(169deg) brightness(92%) contrast(88%);
+}
+
 .status-pill {
   padding: 4upx 14upx;
   border-radius: 18upx;

+ 15 - 13
hdApp/src/admin/home/order.vue

@@ -88,7 +88,7 @@
             <view class="header-tags">
               <text class="tag debt-tag" v-if="item.debt == 1">挂账</text>
               <text class="tag refund-tag" v-if="item.refund == 1">有售后</text>
-              <view class="status-label">
+              <view class="status-label" :class="{ 'status-label--cancel': item.status == 5 }">
                 <image v-if="item._statusIcon" class="card-icon-sm" :src="iconSrc(item._statusIcon)" mode="aspectFit" />
                 <text>{{ item._statusText }}</text>
               </view>
@@ -98,39 +98,32 @@
           <view class="card-body">
             <view class="order-info">
               <view class="info-row">
-                <image class="card-icon-sm" :src="iconSrc('order-product-no')" mode="aspectFit" />
                 <text class="field-label">货号:</text>
                 <text class="field-value">{{ item.sendNum || '' }}</text>
               </view>
               <view class="info-row">
-                <image class="card-icon-sm" :src="iconSrc(item.sendType == 1 ? 'order-clock' : 'order-truck')" mode="aspectFit" />
                 <text class="field-label">{{ item.sendType == 1 ? '取花:' : '配送:' }}</text>
                 <text class="field-value">{{ item._reachText }}</text>
               </view>
               <view class="info-row">
-                <image class="card-icon-sm" :src="iconSrc('order-sub-account-name')" mode="aspectFit" />
                 <text class="field-label">收花:</text>
                 <text class="field-value">{{ item.receiveUserName || '' }}</text>
               </view>
               <view class="info-row">
-                <image class="card-icon-sm" :src="iconSrc('order-sub-account-name')" mode="aspectFit" />
                 <text class="field-label">下单:</text>
                 <text class="field-value">{{ item.shopAdminName || '' }}</text>
               </view>
               <view class="info-row">
-                <image class="card-icon-sm" :src="iconSrc('order-clock')" mode="aspectFit" />
                 <text class="field-label">时间:</text>
                 <text class="field-value">{{ item._addTimeText }}</text>
               </view>
               <view class="info-row">
-                <image class="card-icon-sm" :src="iconSrc('order-number')" mode="aspectFit" />
                 <text class="field-label">编号:</text>
                 <text class="field-value">{{ item.orderSn || '' }}</text>
               </view>
-              <view class="info-row">
-                <image class="card-icon-sm" :src="iconSrc('order-remark')" mode="aspectFit" />
+              <view class="info-row" v-if="item.remark!=''">
                 <text class="field-label">备注:</text>
-                <text class="field-value remark-text">{{ item.remark || '无' }}</text>
+                <text class="field-value remark-text">{{ item.remark}}</text>
               </view>
             </view>
 
@@ -201,7 +194,12 @@
             </view>
 
             <view class="action-more-wrap">
-              <view class="outline-action" @click.stop="toggleActionMore(index)">更多</view>
+              <!-- 已取消订单:「更多」与状态文案同为灰色 -->
+              <view
+                class="outline-action"
+                :class="{ disabled: item.status == 5 }"
+                @click.stop="toggleActionMore(index)"
+              >更多</view>
             </view>
           </view>
         </view>
@@ -1448,6 +1446,11 @@ export default {
   font-weight: 800;
 }
 
+/* 已取消:灰色,与其它进行中状态区分 */
+.status-label--cancel {
+  color: #9aa3ad;
+}
+
 .status-label text {
   margin-left: 6upx;
 }
@@ -1476,7 +1479,6 @@ export default {
 }
 
 .field-label {
-  margin-left: 14upx;
   flex-shrink: 0;
 }
 
@@ -1530,7 +1532,7 @@ export default {
   display: block;
   margin-bottom: 6upx;
   color: #8c929a;
-  font-size: 22upx;
+  font-size: 28upx;
 }
 
 .price-line {

+ 14 - 7
hdApp/src/admin/homePageConfig/groupBuy.vue

@@ -113,8 +113,8 @@
           </view>
         </view>
         <view class="goods-actions">
-          <text class="action-edit" @click="goGoodsEdit(index)">编辑</text>
-          <text class="action-delete" @click="removeGoods(index)">删除</text>
+          <view class="action-edit" @click="goGoodsEdit(index)">编辑</view>
+          <view class="action-delete" @click="removeGoods(index)">删除</view>
         </view>
       </view>
     </view>
@@ -625,17 +625,24 @@ export default {
   margin-left: 12upx;
 }
 
-.action-edit {
+.action-edit,
+.action-delete {
   font-size: 26upx;
+  line-height: 1.2;
+  padding: 8upx 20upx;
+  border-radius: 8upx;
+  text-align: center;
+}
+
+.action-edit {
   color: #09C567;
-  padding: 8upx 0;
+  border: 2upx solid #09C567;
 }
 
 .action-delete {
-  font-size: 26upx;
   color: #f04545;
-  padding: 8upx 0;
-  margin-top: 8upx;
+  border: 2upx solid #f04545;
+  margin-top: 32upx;
 }
 
 .bottom-space {

+ 6 - 2
hdApp/src/admin/homePageConfig/groupBuyGoodsEdit.vue

@@ -190,12 +190,17 @@ export default {
     /**
      * 解析路由 index,从 groupBuyDraft 加载待编辑商品
      * 编辑态按单条展示(列表中每规格已是独立一条)
+     * index>=0 为编辑,-1 为新增,据此切换导航栏标题
      */
     init() {
       this.goodsIndex = parseInt(this.option && this.option.index, 10)
       if (isNaN(this.goodsIndex)) {
         this.goodsIndex = -1
       }
+      // 新增/编辑共用本页,标题按入口区分,避免一直显示 pages.json 里的「新增」
+      uni.setNavigationBarTitle({
+        title: this.goodsIndex >= 0 ? '编辑' : '新增'
+      })
       const draft = uni.getStorageSync(DRAFT_KEY) || {}
       if (this.goodsIndex >= 0 && draft.goods && draft.goods[this.goodsIndex]) {
         const item = draft.goods[this.goodsIndex]
@@ -389,8 +394,7 @@ export default {
           return
         }
         // 列表展示名带规格后缀,便于区分同商品多规格
-        const displayName = form.specName
-          ? `${this.goodsBase.name}(${form.specName})` : this.goodsBase.name
+        const displayName = this.goodsBase.name
         items.push({
           id: parseInt(form.id, 10) || 0,
           goodsId,

+ 14 - 7
hdApp/src/admin/homePageConfig/seckill.vue

@@ -110,8 +110,8 @@
           </view>
         </view>
         <view class="goods-actions">
-          <text class="action-edit" @click="goGoodsEdit(index)">编辑</text>
-          <text class="action-delete" @click="removeGoods(index)">删除</text>
+          <view class="action-edit" @click="goGoodsEdit(index)">编辑</view>
+          <view class="action-delete" @click="removeGoods(index)">删除</view>
         </view>
       </view>
     </view>
@@ -605,17 +605,24 @@ export default {
   margin-left: 12upx;
 }
 
-.action-edit {
+.action-edit,
+.action-delete {
   font-size: 26upx;
+  line-height: 1.2;
+  padding: 8upx 20upx;
+  border-radius: 8upx;
+  text-align: center;
+}
+
+.action-edit {
   color: #09C567;
-  padding: 8upx 0;
+  border: 2upx solid #09C567;
 }
 
 .action-delete {
-  font-size: 26upx;
   color: #f04545;
-  padding: 8upx 0;
-  margin-top: 8upx;
+  border: 2upx solid #f04545;
+  margin-top: 32upx;
 }
 
 .bottom-space {

+ 6 - 3
hdApp/src/admin/homePageConfig/seckillGoodsEdit.vue

@@ -138,12 +138,17 @@ export default {
     /**
      * 解析路由 index,从 seckillDraft 加载待编辑商品
      * 编辑态按单条展示(列表中每规格已是独立一条)
+     * index>=0 为编辑,-1 为新增,据此切换导航栏标题
      */
     init() {
       this.goodsIndex = parseInt(this.option && this.option.index, 10)
       if (isNaN(this.goodsIndex)) {
         this.goodsIndex = -1
       }
+      // 新增/编辑共用本页,标题按入口区分,避免一直显示 pages.json 里的「新增」
+      uni.setNavigationBarTitle({
+        title: this.goodsIndex >= 0 ? '编辑' : '新增'
+      })
       const draft = uni.getStorageSync(DRAFT_KEY) || {}
       if (this.goodsIndex >= 0 && draft.goods && draft.goods[this.goodsIndex]) {
         const item = draft.goods[this.goodsIndex]
@@ -310,9 +315,7 @@ export default {
           return
         }
         // 列表展示名带规格后缀,便于区分同商品多规格
-        const displayName = form.specName
-          ? `${this.goodsBase.name}(${form.specName})`
-          : this.goodsBase.name
+        const displayName = this.goodsBase.name
         items.push({
           goodsId,
           price,

+ 29 - 50
hdApp/src/admin/order/refund.vue

@@ -57,20 +57,10 @@
 										placeholder="0" 
 										v-model="res.refundCount" 
 										placeholder-style="color:#ccc"
-										@focus="clearRefundCount(res)" />
+										@focus="clearRefundCount(res)"
+										@input="onRefundCountInput" />
 									<text class="unit-label">份</text>
 								</view>
-								<view class="input-item">
-									<text class="input-label">单价</text>
-									<input 
-										class="refund-input-compact" 
-										type="digit" 
-										placeholder="0.00" 
-										v-model="res.perPrice" 
-										placeholder-style="color:#ccc"
-										@focus="clearPerPrice(res)" />
-									<text class="unit-label">元</text>
-								</view>
 							</view>
 						</view>
 					</view>
@@ -94,20 +84,10 @@
 										placeholder="0" 
 										v-model="res.refundCount" 
 										placeholder-style="color:#ccc"
-										@focus="clearRefundCount(res)" />
+										@focus="clearRefundCount(res)"
+										@input="onRefundCountInput" />
 									<text class="unit-label">{{res.unitName}}</text>
 								</view>
-								<view class="input-item">
-									<text class="input-label">单价</text>
-									<input 
-										class="refund-input-compact" 
-										type="digit" 
-										placeholder="0.00" 
-										v-model="res.perPrice" 
-										placeholder-style="color:#ccc"
-										@focus="clearPerPrice(res)" />
-									<text class="unit-label">元</text>
-								</view>
 							</view>
 						</view>
 					</view>
@@ -229,6 +209,10 @@
 	</view>
 </template>
 <script>
+/**
+ * 花店订单售后页:选择退货商品、填写退款金额并提交。
+ * 退货单价直接取订单原单价,只需填数量。
+ */
 import { getDetail,refund } from "@/api/order/index";
 import ModalModule from "@/components/plugin/modal";
 export default {
@@ -260,28 +244,26 @@ export default {
 			// 金额比较按 2 位小数对齐,避免浮点误差
 			return refundMoney.toFixed(2) === couldRefund.toFixed(2)
 		},
+		/**
+		 * 按退货数量 × 商品原单价汇总金额,并回填退款金额。
+		 * 单价不再手填,避免漏填导致退款金额为 0。
+		 */
 		refundPrice(){
 			let price = 0
 			if(!this.$util.isEmpty(this.goodsInfoList)){
 				for (const item of this.goodsInfoList) {
 					if(Number(item.refundCount)>0){
-						let currentPrice = Number(item.refundCount)*Number(item.perPrice)
-						currentPrice.toFixed(2)
+						let currentPrice = Number(item.refundCount)*Number(item.unitPrice)
 						price = Number(price) + Number(currentPrice)
-						price.toFixed(2)
 					}
-
 				}
 			}
 			if(!this.$util.isEmpty(this.itemInfoList)){
 				for (const item of this.itemInfoList) {
 					if(Number(item.refundCount)>0){
-						let currentPrice = Number(item.refundCount)*Number(item.perPrice)
-						currentPrice.toFixed(2)
+						let currentPrice = Number(item.refundCount)*Number(item.unitPrice)
 						price = Number(price) + Number(currentPrice)
-						price.toFixed(2)
 					}
-
 				}
 			}
 			this.refundMoney = parseFloat(price.toFixed(2))
@@ -309,9 +291,16 @@ export default {
 		},
 		clearRefundCount(item) {
 			this.$set(item, 'refundCount', '');
+			this.onRefundCountInput()
 		},
-		clearPerPrice(item) {
-			this.$set(item, 'perPrice', '');
+		/**
+		 * 退货数量变化后读取 refundPrice,按原单价回填退款金额。
+		 * 计算属性默认懒求值,不主动读取就不会更新退款金额。
+		 */
+		onRefundCountInput() {
+			this.$nextTick(() => {
+				void this.refundPrice
+			})
 		},
 		clearRefundMoney() {
 			this.refundMoney = '';
@@ -354,12 +343,7 @@ export default {
 						return false
 					}
 					if(Number(ele.refundCount)>0){
-						if(Number(ele.perPrice)>Number(ele.unitPrice)){
-							uni.showToast({title:ele.name+' 退款单价不能大于原价',icon:'none'})
-							hasError = true;
-							return false
-						}
-						selectProduct.push({"productId":ele.goodsId,"num":ele.refundCount,"unitType":ele.unitType,unitName:ele.unitName,unitPrice:ele.perPrice || ele.unitPrice,property:0})
+						selectProduct.push({"productId":ele.goodsId,"num":ele.refundCount,"unitType":ele.unitType,unitName:ele.unitName,unitPrice:ele.unitPrice,property:0})
 					}
 				})
 			}
@@ -377,12 +361,7 @@ export default {
 						return false
 					}
 					if(Number(ele.refundCount)>0){
-						if(Number(ele.perPrice)>Number(ele.unitPrice)){
-							uni.showToast({title:ele.name+' 退款单价不能大于原价',icon:'none'})
-							hasError = true;
-							return false
-						}
-						selectProduct.push({"productId":ele.itemId,"num":ele.refundCount,"unitType":ele.unitType,unitName:ele.unitName,unitPrice:ele.perPrice || ele.unitPrice,property:1})
+						selectProduct.push({"productId":ele.itemId,"num":ele.refundCount,"unitType":ele.unitType,unitName:ele.unitName,unitPrice:ele.unitPrice,property:1})
 					}
 				})
 			}
@@ -416,14 +395,14 @@ export default {
 			if(!this.$util.isEmpty(this.goodsInfoList)){
 				this.goodsInfoList.forEach(ele=>{
 					if(Number(ele.refundCount)>0){
-						selectProduct.push({"productId":ele.goodsId,"num":ele.refundCount,"unitType":ele.unitType,unitName:ele.unitName,unitPrice:ele.perPrice || ele.unitPrice,property:0})
+						selectProduct.push({"productId":ele.goodsId,"num":ele.refundCount,"unitType":ele.unitType,unitName:ele.unitName,unitPrice:ele.unitPrice,property:0})
 					}
 				})
 			}
 			if(!this.$util.isEmpty(this.itemInfoList)){
 				this.itemInfoList.forEach(ele=>{
 					if(Number(ele.refundCount)>0){
-						selectProduct.push({"productId":ele.itemId,"num":ele.refundCount,"unitType":ele.unitType,unitName:ele.unitName,unitPrice:ele.perPrice || ele.unitPrice,property:1})
+						selectProduct.push({"productId":ele.itemId,"num":ele.refundCount,"unitType":ele.unitType,unitName:ele.unitName,unitPrice:ele.unitPrice,property:1})
 					}
 				})
 			}
@@ -499,10 +478,10 @@ export default {
 			this.coundRefundPrice = parseFloat(this.coundRefundPrice)
 
 			this.goodsInfoList = res.data.goodsInfoList.map(ele=>{
-				return {...ele,refundCount:null,perPrice:''}
+				return {...ele,refundCount:null}
 			})
 			this.itemInfoList = res.data.itemInfoList.map(ele=>{
-				return {...ele,refundCount:null,perPrice:''}
+				return {...ele,refundCount:null}
 			})
 		}
 	}

+ 1 - 1
hdApp/src/pages.json

@@ -658,7 +658,7 @@
 		{
 			"root": "admin/lakala",
 			"pages": [
-				{"path": "lakala","style": {"navigationBarTitleText": "收款账户管理", "enablePullDownRefresh": true}},
+				{"path": "lakala","style": {"navigationBarTitleText": "收款账户", "enablePullDownRefresh": true}},
 				{"path": "lakalaOnboarding","style": {"navigationBarTitleText": "商户入网"}},
 				{"path": "lakalaAuthorize","style": {"navigationBarTitleText": "商户认证"}}
 			]

+ 0 - 1
hdApp/src/static/icons/client-birthday.svg

@@ -1 +0,0 @@
-<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1779193902738" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6235" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M992 960h-64V480a96 96 0 0 0-96-96h-64v-128a32 32 0 0 0-64 0v128H544V224a32 32 0 0 0-64 0v160H320v-128a32 32 0 0 0-64 0v128h-64a96 96 0 0 0-96 96v480H32a32 32 0 0 0 0 64h960a32 32 0 0 0 0-64zM192 448h640a32 32 0 0 1 32 32v117.92a134.56 134.56 0 0 0-58.72 56.32c-16 24-23.84 33.76-37.28 33.76s-21.44-9.76-37.44-33.76S688.96 592 640 592s-73.12 36-90.56 62.24S525.44 688 512 688s-21.28-9.76-37.28-33.76S432.96 592 384 592s-73.12 36-90.56 62.24S269.44 688 256 688s-21.44-9.76-37.44-33.76A133.28 133.28 0 0 0 160 597.92V480a32 32 0 0 1 32-32z m-32 233.92c1.76 2.4 3.52 4.96 5.28 7.84C182.88 716 206.88 752 256 752s73.12-36 90.56-62.24S370.4 656 384 656s21.44 9.76 37.44 33.76S462.72 752 512 752s73.12-36 90.72-62.24S626.4 656 640 656s21.44 9.76 37.44 33.76S718.72 752 768 752s73.12-36 90.56-62.24c1.92-2.88 3.68-5.6 5.44-8V960H160z" p-id="6236"></path><path d="M288 128m-32 0a32 32 0 1 0 64 0 32 32 0 1 0-64 0Z" p-id="6237"></path><path d="M512 96m-32 0a32 32 0 1 0 64 0 32 32 0 1 0-64 0Z" p-id="6238"></path><path d="M736 128m-32 0a32 32 0 1 0 64 0 32 32 0 1 0-64 0Z" p-id="6239"></path></svg>

+ 0 - 1
hdApp/src/static/icons/order-clock.svg

@@ -1 +0,0 @@
-<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1779194814547" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7732" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M511.913993 63.989249c-247.012263 0-447.924744 200.912481-447.924744 447.924744s200.912481 447.924744 447.924744 447.924744 447.924744-200.912481 447.924744-447.924744S758.926256 63.989249 511.913993 63.989249zM511.913993 895.677474c-211.577356 0-383.763481-172.186125-383.763481-383.763481 0-211.577356 172.014111-383.763481 383.763481-383.763481s383.763481 172.014111 383.763481 383.763481S723.491349 895.677474 511.913993 895.677474z" fill="#09C567" p-id="7733"></path><path d="M672.05913 511.913993l-159.973123 0L512.086007 288.123635c0-17.717453-14.277171-32.166639-31.994625-32.166639-17.717453 0-31.994625 14.449185-31.994625 32.166639l0 255.956996c0 17.717453 14.277171 31.994625 31.994625 31.994625l191.967747 0c17.717453 0 32.166639-14.277171 32.166639-31.994625C704.053754 526.191164 689.604569 511.913993 672.05913 511.913993z" fill="#09C567" p-id="7734"></path></svg>

+ 0 - 1
hdApp/src/static/icons/order-number.svg

@@ -1 +0,0 @@
-<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1779195865276" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="25429" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M877.714286 73.142857H146.285714c-20.114286 0-36.571429 16.457143-36.571428 36.571429v804.571428c0 10.971429 5.485714 21.942857 12.8 29.257143 7.314286 7.314286 20.114286 9.142857 31.085714 7.314286L512 879.542857 870.4 950.857143h7.314286c9.142857 0 16.457143-3.657143 23.771428-9.142857 9.142857-7.314286 12.8-18.285714 12.8-29.257143v-804.571429c0-18.285714-16.457143-34.742857-36.571428-34.742857z m-36.571429 795.428572L519.314286 804.571429h-14.628572L182.857143 868.571429V146.285714h658.285714v722.285715z" p-id="25430" fill="#09C567"></path><path d="M694.857143 363.885714H329.142857v73.142857h365.714286v-73.142857zM694.857143 546.742857H329.142857v73.142857h365.714286v-73.142857z" p-id="25431" fill="#09C567"></path></svg>

+ 0 - 1
hdApp/src/static/icons/order-product-no.svg

@@ -1 +0,0 @@
-<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1779194854952" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8313" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M916 779.1l-22.4-544.8C890.4 158 825.7 98.2 746.5 98.2H276.1c-80.1 0-143.4 58.4-147.2 136.1l-22.3 541.8c-2 38.7 12.5 79.2 37.8 105.7 28.1 29.4 64.5 46.3 99.9 46.3h534c34.6 0 71.1-17.3 99.9-47.5 26-27 39.8-64.2 37.8-101.5z m-82.9 58.6c-16.9 17.7-37.4 28.3-54.9 28.3h-534c-18.1 0-38.6-10.1-54.8-27-13.5-14.1-21.8-38-20.6-59.8l22.3-541.9c2.2-44.4 37.9-76.7 85-76.7h470.3c45.8 0 83.1 33.6 85 76.4l22.4 545.1c1.1 20.5-6.4 40.8-20.7 55.6zM677.4 274.6c-17.2 0-31.1 13.9-31.1 31.1 0 74.4-60.5 134.9-134.9 134.9s-134.9-60.5-134.9-134.9c0-17.2-13.9-31.1-31.1-31.1-17.2 0-31.1 13.9-31.1 31.1 0 108.7 88.5 197.1 197.2 197.1 108.8 0 197.2-88.4 197.2-197.1-0.1-17.2-14.1-31.1-31.3-31.1z" p-id="8314" fill="#09C567"></path></svg>

File diff suppressed because it is too large
+ 0 - 0
hdApp/src/static/icons/order-remark.svg


+ 0 - 1
hdApp/src/static/icons/order-sub-account-name.svg

@@ -1 +0,0 @@
-<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1779194608539" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6105" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M602.38506667 974.16533333H421.888c-175.44533333 0-314.1632 0-314.1632-97.21173333v-17.6128c0-171.34933333 140.9024-310.74986667 314.1632-310.74986667h180.49706667c173.12426667 0 314.02666667 139.40053333 314.02666666 310.74986667v17.74933333c0 97.00693333-145.54453333 97.00693333-314.02666666 97.00693334zM421.888 617.81333333c-135.23626667 0-245.3504 108.3392-245.3504 241.4592v17.74933334c0 27.78453333 165.6832 27.78453333 245.3504 27.78453333h180.49706667c60.6208 0 245.21386667 0 245.21386666-27.8528v-17.74933333c0-133.12-109.9776-241.39093333-245.21386666-241.39093334H421.888z m81.1008-71.2704c-138.30826667 0-250.88-111.4112-250.88-248.35413333 0-136.94293333 112.57173333-248.35413333 250.88-248.35413333 138.37653333 0 250.94826667 111.4112 250.94826667 248.35413333 0 136.94293333-112.57173333 248.35413333-250.94826667 248.35413333zM320.9216 298.32533333c0 98.7136 81.7152 179.06346667 182.13546667 179.06346667s182.13546667-80.2816 182.13546666-179.06346667c0-98.7136-81.7152-179.06346667-182.13546666-179.06346666-100.352 0-182.13546667 80.34986667-182.13546667 179.06346666z" fill="#09C567" p-id="6106"></path></svg>

+ 31 - 0
hdApp/tsconfig.json

@@ -1,10 +1,41 @@
 {
   "compilerOptions": {
+    "target": "ESNext",
+    "module": "ESNext",
+    "moduleResolution": "bundler",
+    "allowJs": true,
+    "checkJs": false,
+    "noEmit": true,
+    "jsx": "preserve",
+    "paths": {
+      "@/*": [
+        "./src/*",
+        "./src/*.vue",
+        "./src/*/index.vue",
+        "./src/*/index.js"
+      ]
+    },
+    "lib": ["ESNext", "DOM"],
+    "skipLibCheck": true,
     "types": [
       "uni-app",
       "html5plus",
       "miniprogram-api-typings/types/lib.wx.api.d.ts",
       "mini-types/types/api"
     ]
+  },
+  "include": [
+    "src/**/*.js",
+    "src/**/*.ts",
+    "src/**/*.d.ts",
+    "src/**/*.vue"
+  ],
+  "exclude": [
+    "node_modules",
+    "dist",
+    "unpackage"
+  ],
+  "vueCompilerOptions": {
+    "target": 2.7
   }
 }

+ 4 - 0
mallApp/src/api/custom/index.js

@@ -6,4 +6,8 @@ export const initCustom = data => {
 
 export const getBalanceChangeList = data => {
 	return https.get('/balance-change/list', data)
+}
+
+export const getBalancePayChangeDetail = data => {
+	return https.get('/balance-change/balance-pay-change', data)
 }

+ 6 - 2
mallApp/src/api/group-buy/index.js

@@ -10,8 +10,12 @@ export const getGoodsLanding = data => https.get('/group-buy/goods-landing', dat
 /** 指定拼团详情(分享进入用 id=groupBuyId) */
 export const getGroupDetail = data => https.get('/group-buy/detail', data)
 
-/** 我要开团 */
-export const createGroup = data => https.post('/group-buy/create', data)
+/**
+ * 我要开团
+ * @param {Object} data 业务参数
+ * @param {Object} config 请求控制,如 hideError 由页面自行弹失败提示(须透传到 post,否则第二参会被丢掉)
+ */
+export const createGroup = (data, config = {}) => https.post('/group-buy/create', data, {}, config)
 
 /**
  * 我要参团

+ 1 - 1
mallApp/src/api/refund/index.js

@@ -9,7 +9,7 @@ export const getRefundData = data => {
 	return https.get('/refund/get-refund-data', data)
 }
 
-/** 顾客提交售后申请(待审核) */
+/** 顾客提交售后申请;若上次已取消则把该记录改回待审核 */
 export const createRefund = data => {
 	return https.post('/refund/create-order', data)
 }

+ 4 - 4
mallApp/src/components/home/activitySection.vue

@@ -384,11 +384,11 @@ export default {
 }
 .action-btn {
   flex-shrink: 0;
-  padding: 10upx 20upx;
-  font-size: 22upx;
+  padding: 13upx 24upx;
+  font-size: 24upx;
   color: #fff;
   background: linear-gradient(135deg, #FF8FA3, #FF4D6D);
-  border-radius: 30upx;
+  border-radius: 28upx;
   white-space: nowrap;
 }
 .price {
@@ -460,7 +460,7 @@ export default {
 }
 .grid-btn {
   margin-top: 10upx;
-  padding: 12upx 0;
+  padding: 13upx 0;
   text-align: center;
   font-size: 24upx;
   color: #fff;

+ 18 - 4
mallApp/src/components/item/plugin/modal.vue

@@ -110,11 +110,28 @@ export default {
 		fadein: {
 			type: Boolean,
 			default: false
+		},
+		/**
+		 * 是否使用 customContent 插槽
+		 * 小程序端勿用 $slots 判断(会触发 then 未定义告警),由页面显式传入
+		 */
+		useCustomContent: {
+			type: Boolean,
+			default: false
 		}
 	},
 	computed:{
+		/** 优先用 prop;H5 可兜底读 slot(避免仅依赖 $slots 在 MP 上报错) */
 		isCustomContent(){
-			return !!this.$slots.customContent
+			if (this.useCustomContent) {
+				return true
+			}
+			// #ifdef H5
+			return !!(this.$slots && this.$slots.customContent)
+			// #endif
+			// #ifndef H5
+			return false
+			// #endif
 		}
 	},
 	data() {
@@ -122,9 +139,6 @@ export default {
 
 		}
 	},
-	mounted(){
-		console.log(this)
-	},
 	methods: {
 		handleClick(e) {
 			if (!this.show) return

+ 2 - 2
mallApp/src/pages/balance/changeList.vue

@@ -40,7 +40,7 @@
     </template>
     <script>
     import AppWrapperEmpty from "@/components/app-wrapper-empty";
-    import { getBalanceChangeList } from '@/api/custom'
+    import { getBalanceChangeList, getBalancePayChangeDetail } from '@/api/custom'
     import list from '@/mixins/list'
     export default {
         name: "balanceChange",
@@ -70,7 +70,7 @@
             },
             async init(){
                 let hdId = this.option.hdId ? this.option.hdId : 0
-                const res = await getBalanceChangeList({ page:this.list.page,hdId:hdId })
+                const res = await getBalancePayChangeDetail({ page:this.list.page, hdId:hdId})
                 if (this.$util.isEmpty(res.data.list)){
                     this.completes(res)
                     return

+ 22 - 13
mallApp/src/pages/groupBuy/detail.vue

@@ -525,20 +525,29 @@ export default {
         activityGoodsId,
         goodsNum: 1,
         sendType: 1
+      },
+      { hideError: true }
+    ).then((res) => {
+        uni.hideLoading()
+        this.submitting = false
+        if (res.code === 1 && res.data) {
+          this.groupBuyId = res.data.groupBuyId
+          this.setupShare()
+          this.goPay(res.data)
+        }
+        if (res && res.msg) {
+          uni.showToast({
+            title: res.msg,
+            icon: 'none',
+            mask: true,
+            duration: 3000
+          })
+        }
+      })
+      .catch(() => {
+        uni.hideLoading()
+        this.submitting = false
       })
-        .then((res) => {
-          uni.hideLoading()
-          this.submitting = false
-          if (res.code === 1 && res.data) {
-            this.groupBuyId = res.data.groupBuyId
-            this.setupShare()
-            this.goPay(res.data)
-          }
-        })
-        .catch(() => {
-          uni.hideLoading()
-          this.submitting = false
-        })
     },
     joinOpenGroup() {
       if (!this.openGroup || !this.openGroup.id) return

+ 9 - 6
mallApp/src/pages/home/cart.vue

@@ -126,6 +126,7 @@
     <!-- 自定义扎数 -->
     <modal-module
       :show="isModel"
+      :use-custom-content="true"
       @cancel="modalCancel"
       @click="affirm"
       :title="customModalTitle"
@@ -634,7 +635,8 @@ export default {
     goCategory() {
       this.$util.pageTo({
         url: '/pages/home/shop-category',
-        query: { account: this.shopAccount, hdId: this.hdId }
+        query: { account: this.shopAccount, hdId: this.hdId },
+        type:2
       })
     },
     goItemDetail(item) {
@@ -1021,12 +1023,13 @@ export default {
 }
 
 .cart-empty-btn {
-  width: 280upx;
-  height: 72upx;
-  line-height: 72upx;
+  width: 260upx;
+  height: 87upx;
   margin: 32upx auto 0;
-  text-align: center;
-  font-size: 28upx;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  font-size: 30upx;
   color: #fff;
   background: $greenColor;
   border-radius: 36upx;

+ 15 - 13
mallApp/src/pages/home/recent.vue

@@ -1,6 +1,7 @@
 <!--
   个人首页
   未登录展示服务说明与登录引导(符合审核可先浏览);已登录管理真实花店,并在列表加载后接收尚未通知的红包到账提醒。
+  已登录时每次打开或回到前台都会重新请求花店列表,保证余额、休店状态与列表本身是最新的。
 -->
 <template>
   <view class="page-container">
@@ -259,14 +260,11 @@ export default {
     } else {
       this.loginStyle = 0;
     }
-    if (this.pageAction.refresh == 1) {
-      this.resetList();
-      this.init();
-      this.pageAction.refresh = 0;
-    }
-    if (this.loginStyle == 1 && !this.$util.isEmpty(this.list.data)) {
-      this.checkHbArrival();
+    // 切 Tab、从子页返回、App 回前台都会进 onShow,已登录则立刻重拉花店列表
+    if (this.loginStyle == 1) {
+      this.refreshMyHdList();
     }
+    this.pageAction.refresh = 0;
   },
   onPullDownRefresh() {
     this.resetList();
@@ -284,6 +282,9 @@ export default {
     this.toBottom();
   },
   methods: {
+    init() {
+      this.getLoginInfo()
+    },
     /**
      * 未登录引导页点击登录:自愿进入授权页,登录成功后可按 needBack 返回本页。
      */
@@ -351,8 +352,13 @@ export default {
     hasDelHd(){
       this.pageTo({ url: "/pages/hd/hasDel" });
     },
-    init() {
-      this.getLoginInfo()
+    /**
+     * 从第 1 页重新请求花店列表。
+     * 不清空现有 list.data,避免切回本页时先闪「暂无花店」;completes 在 page=1 时会整表替换。
+     */
+    refreshMyHdList() {
+      this.list.page = 1;
+      this.list.finished = false;
       this.getMyHdList()
     },
     /**
@@ -946,10 +952,6 @@ page {
         border-bottom: none;
       }
 
-      /* &:active {
-        background-color: #f8f9fa;
-      } */
-
       &.cancel {
         color: #999;
       }

+ 1 - 1
mallApp/src/pages/order/detail.vue

@@ -222,7 +222,7 @@ export default {
         uni.showToast({ title: "分销佣金已结算,无法申请售后", icon: "none" });
         return;
       }
-      this.$util.pageTo({ url: "/pages/order/refund?id=" + this.data.id });
+      this.$util.pageTo({ url: "/pages/order/refund?account=" + this.option.account + "&id=" + this.data.id });
     },
     init() {
       this.getDetail().then(() => {

+ 50 - 4
mallApp/src/pages/order/refund.vue

@@ -1,11 +1,12 @@
 <!--
   商城订单申请售后页
   供订单详情「申请售后」进入;顾客勾选商品/金额后提交待审核申请,商家在 hdApp 审核
+  撤销后仍可重新申请:把已取消记录改回待审核
 -->
 <template>
 	<view class="refund-page">
-		<!-- 已有申请:展示进度 -->
-		<template v-if="apply && apply.id">
+		<!-- 已有申请:展示进度(点「重新申请」后切到表单) -->
+		<template v-if="showApplyProgress">
 			<view class="card-section">
 				<view class="section-title">
 					<text class="title-text">申请进度</text>
@@ -33,6 +34,10 @@
 			<view class="bottom-actions" v-if="apply.status == 0">
 				<button class="action-btn cancel-btn" @tap="doCancel">撤销申请</button>
 			</view>
+			<view class="bottom-actions" v-else-if="canReapply">
+				<button class="action-btn cancel-btn" @tap="goBack">返回</button>
+				<button class="action-btn confirm-btn" @tap="startReapply">重新申请</button>
+			</view>
 			<view class="bottom-actions" v-else>
 				<button class="action-btn cancel-btn" @tap="goBack">返回</button>
 			</view>
@@ -184,7 +189,7 @@
 			</view>
 
 			<view class="bottom-actions">
-				<button class="action-btn cancel-btn" @tap="goBack">取消</button>
+				<button class="action-btn cancel-btn" @tap="onFormCancel">取消</button>
 				<button class="action-btn confirm-btn" @tap="askSubmit">提交申请</button>
 			</view>
 		</template>
@@ -207,10 +212,29 @@ export default {
 			apply: null,
 			canApply: 0,
 			refundDeadlineTip: '',
-			submitting: false
+			submitting: false,
+			// 已取消后点「重新申请」进入表单,提交时把原记录改回待审核
+			reapplying: false
 		}
 	},
 	computed: {
+		/** 是否展示申请进度;重新申请中不锁在进度页 */
+		showApplyProgress() {
+			if (!this.apply || !this.apply.id) {
+				return false
+			}
+			if (this.reapplying) {
+				return false
+			}
+			return true
+		},
+		/** 已取消且订单仍可售后时允许重新申请 */
+		canReapply() {
+			if (!this.apply || !this.apply.id) {
+				return false
+			}
+			return Number(this.apply.status) === 3 && Number(this.canApply) === 1
+		},
 		/** 是否展示已退金额行(避免模板里写 > 比较,兼容小程序 WXML) */
 		hasTkPrice() {
 			return Number(this.orderInfo.tkPrice) > 0
@@ -267,11 +291,33 @@ export default {
 		goBack() {
 			uni.navigateBack({ delta: 1 })
 		},
+		/**
+		 * 表单取消:重新申请中退回已取消进度页,首次申请则离开本页
+		 */
+		onFormCancel() {
+			if (this.reapplying) {
+				this.reapplying = false
+				return
+			}
+			this.goBack()
+		},
+		/**
+		 * 已取消后重新申请:切到表单,提交时后端把该记录改回待审核
+		 */
+		startReapply() {
+			if (!this.canReapply) {
+				return
+			}
+			this.reapplying = true
+			this.remark = ''
+			this.refundType = 1
+		},
 		/** 切换为只退款 */
 		onOnlyRefund() {
 			this.refundType = 2
 		},
 		init() {
+			this.reapplying = false
 			const id = this.option.id
 			if (!id) {
 				this.$msg('缺少订单信息')

+ 4 - 2
mallApp/src/plugins/luch-request_0.0.7/request.js

@@ -195,7 +195,8 @@ class Request {
 								uni.showToast({
 									title: response.data.msg,
 									icon: 'none',
-									mask: true
+									mask: true,
+									duration: 3000
 								})
 							}
 							reject(response.data)
@@ -216,7 +217,8 @@ class Request {
 								uni.showToast({
 									title: response.data.msg,
 									icon: 'none',
-									mask: true
+									mask: true,
+									duration: 3000
 								})
 							}
 							reject(response.data)

+ 31 - 0
mallApp/tsconfig.json

@@ -1,10 +1,41 @@
 {
   "compilerOptions": {
+    "target": "ESNext",
+    "module": "ESNext",
+    "moduleResolution": "bundler",
+    "allowJs": true,
+    "checkJs": false,
+    "noEmit": true,
+    "jsx": "preserve",
+    "paths": {
+      "@/*": [
+        "./src/*",
+        "./src/*.vue",
+        "./src/*/index.vue",
+        "./src/*/index.js"
+      ]
+    },
+    "lib": ["ESNext", "DOM"],
+    "skipLibCheck": true,
     "types": [
       "uni-app",
       "html5plus",
       "miniprogram-api-typings/types/lib.wx.api.d.ts",
       "mini-types/types/api"
     ]
+  },
+  "include": [
+    "src/**/*.js",
+    "src/**/*.ts",
+    "src/**/*.d.ts",
+    "src/**/*.vue"
+  ],
+  "exclude": [
+    "node_modules",
+    "dist",
+    "unpackage"
+  ],
+  "vueCompilerOptions": {
+    "target": 2.7
   }
 }

Some files were not shown because too many files changed in this diff