黄琪勇 2 månader sedan
förälder
incheckning
6cd1f19951
69 ändrade filer med 4888 tillägg och 1209 borttagningar
  1. 4 0
      .gitignore
  2. 127 1
      miniprogram/api/login.ts
  3. 4 2
      miniprogram/app.json
  4. 25 1
      miniprogram/app.less
  5. 3 3
      miniprogram/components/navigation-bar/navigation-bar.less
  6. 4 0
      miniprogram/components/numberDisplay/numberDisplay.json
  7. 0 0
      miniprogram/components/numberDisplay/numberDisplay.less
  8. 22 0
      miniprogram/components/numberDisplay/numberDisplay.ts
  9. 3 0
      miniprogram/components/numberDisplay/numberDisplay.wxml
  10. 1 1
      miniprogram/config.ts
  11. 8 0
      miniprogram/pages/address/addAddress.json
  12. 93 0
      miniprogram/pages/address/addAddress.less
  13. 217 0
      miniprogram/pages/address/addAddress.ts
  14. 40 0
      miniprogram/pages/address/addAddress.wxml
  15. 6 0
      miniprogram/pages/address/addressList.json
  16. 222 0
      miniprogram/pages/address/addressList.less
  17. 110 0
      miniprogram/pages/address/addressList.ts
  18. 47 0
      miniprogram/pages/address/addressList.wxml
  19. BIN
      miniprogram/pages/index/images/chevron.png
  20. BIN
      miniprogram/pages/index/images/icon-close.png
  21. BIN
      miniprogram/pages/index/images/member.png
  22. BIN
      miniprogram/pages/index/images/order.png
  23. BIN
      miniprogram/pages/index/images/yhj.png
  24. 2 1
      miniprogram/pages/index/index.json
  25. 249 295
      miniprogram/pages/index/index.less
  26. 78 67
      miniprogram/pages/index/index.ts
  27. 63 63
      miniprogram/pages/index/index.wxml
  28. 4 3
      miniprogram/pages/login/login.less
  29. 10 0
      miniprogram/pages/member/addMember.json
  30. 262 0
      miniprogram/pages/member/addMember.less
  31. 607 0
      miniprogram/pages/member/addMember.ts
  32. 97 0
      miniprogram/pages/member/addMember.wxml
  33. BIN
      miniprogram/pages/member/images/chevron-down.png
  34. BIN
      miniprogram/pages/member/images/icon-search.png
  35. BIN
      miniprogram/pages/member/images/label1.png
  36. BIN
      miniprogram/pages/member/images/label2.png
  37. BIN
      miniprogram/pages/member/images/user.png
  38. 5 0
      miniprogram/pages/member/memberList.json
  39. 223 0
      miniprogram/pages/member/memberList.less
  40. 105 0
      miniprogram/pages/member/memberList.ts
  41. 62 0
      miniprogram/pages/member/memberList.wxml
  42. BIN
      miniprogram/pages/orders/images/discount.png
  43. BIN
      miniprogram/pages/orders/images/error.png
  44. BIN
      miniprogram/pages/orders/images/ing.png
  45. BIN
      miniprogram/pages/orders/images/member.png
  46. BIN
      miniprogram/pages/orders/images/success.png
  47. 3 1
      miniprogram/pages/orders/order-detail.json
  48. 305 52
      miniprogram/pages/orders/order-detail.less
  49. 85 57
      miniprogram/pages/orders/order-detail.ts
  50. 94 18
      miniprogram/pages/orders/order-detail.wxml
  51. 2 1
      miniprogram/pages/orders/order-result.json
  52. 325 209
      miniprogram/pages/orders/order-result.less
  53. 242 219
      miniprogram/pages/orders/order-result.ts
  54. 120 76
      miniprogram/pages/orders/order-result.wxml
  55. 7 0
      miniprogram/pages/orders/order-result1.json
  56. 384 0
      miniprogram/pages/orders/order-result1.less
  57. 321 0
      miniprogram/pages/orders/order-result1.ts
  58. 98 0
      miniprogram/pages/orders/order-result1.wxml
  59. 2 1
      miniprogram/pages/orders/orders.json
  60. 88 70
      miniprogram/pages/orders/orders.less
  61. 40 36
      miniprogram/pages/orders/orders.ts
  62. 31 25
      miniprogram/pages/orders/orders.wxml
  63. 1 1
      miniprogram/plugins/request.ts
  64. 6 1
      node_modules/.package-lock.json
  65. 13 0
      package-lock.json
  66. 3 0
      package.json
  67. 9 3
      project.config.json
  68. 1 1
      project.private.config.json
  69. 5 1
      tsconfig.json

+ 4 - 0
.gitignore

@@ -0,0 +1,4 @@
+
+
+node_modules
+miniprogram/miniprogram_npm

+ 127 - 1
miniprogram/api/login.ts

@@ -30,6 +30,15 @@ export const api_shopProduct = (params: any) => {
   } as any);
 };
 
+/** 获取乐器信息 */
+export const api_shopInstruments = (params: any) => {
+  return request({
+    url: `/edu-app/open/shop/instruments`,
+    method: "get",
+    data: params,
+  } as any);
+};
+
 /** 用户下单 */
 export const api_executeOrder = (params: any) => {
   return request({
@@ -79,7 +88,7 @@ export const api_studentOrderPage = (params: any) => {
 /** 订单详情 */
 export const api_userPaymentOrderDetail = (orderNo: string) => {
   return request({
-    url: `/edu-app/userPaymentOrder/detail/${orderNo}`,
+    url: `/edu-app/userPaymentOrder/detail/${orderNo}?version=V2`,
     method: "get"
   } as any);
 };
@@ -99,4 +108,121 @@ export const api_userPaymentOrderRefundPayment = (data: any) => {
     method: "post",
     data
   } as any);
+};
+
+/** 查询受益人列表 */
+export const api_getUserBeneficiaryPage = () => {
+  return request({
+    url: `/edu-app/userBeneficiary/page`,
+    method: "post",
+    data: {
+      page: 1,
+      rows: 9999
+    }
+  } as any);
+};
+
+/** 新增受益人 */
+export const api_userBeneficiarySave = (params: any) => {
+  return request({
+    url: `/edu-app/userBeneficiary/save`,
+    method: "post",
+    data: params,
+  } as any);
+};
+
+/** 修改受益人 */
+export const api_userBeneficiaryUpdate = (params: any) => {
+  return request({
+    url: `/edu-app/userBeneficiary/update`,
+    method: "post",
+    data: params,
+  } as any);
+};
+
+/** 删除受益人 */
+export const api_userBeneficiaryRemove = (id: string) => {
+  return request({
+    url: `/edu-app/userBeneficiary/remove/${id}`,
+    method: "get"
+  } as any);
+};
+
+/** 受益人详情 */
+export const api_userBeneficiaryDetail = (id: string) => {
+  return request({
+    url: `/edu-app/userBeneficiary/detail/${id}`,
+    method: "get"
+  } as any);
+};
+/** 获取省市区 */
+export const api_sysAreaQueryAllProvince = (params: any) => {
+  return request({
+    url: `/edu-app/open/sysArea/queryAllProvince`,
+    method: "get",
+    params: params,
+  } as any);
+};
+
+/** 获取学校列表 */
+export const api_schoolAreaList = (params: any) => {
+  return request({
+    url: `/edu-app/open/schoolArea/list`,
+    method: "post",
+    data: params,
+  } as any);
+};
+
+/** 获取地区学校详情 */
+export const api_schoolAreaDetail = (params: any) => {
+  return request({
+    url: `/edu-app/open/schoolArea/detail/${params.id}`,
+    method: "get"
+  } as any);
+};
+
+/** 查询收货地址列表 */
+export const api_getUserReceiveAddressPage = () => {
+  return request({
+    url: `/edu-app/userReceiveAddress/page`,
+    method: "post",
+    data: {
+      page: 1,
+      rows: 9999
+    }
+  } as any);
+};
+
+/** 新增收货地址 */
+export const api_userReceiveAddressSave = (params: any) => {
+  return request({
+    url: `/edu-app/userReceiveAddress/save`,
+    method: "post",
+    data: params,
+  } as any);
+};
+
+/** 修改收货地址 */
+export const api_userReceiveAddressUpdate = (params: any) => {
+  return request({
+    url: `/edu-app/userReceiveAddress/update`,
+    method: "post",
+    data: params,
+  } as any);
+};
+
+/** 删除收货地址  */
+export const api_userReceiveAddressRemove = (id: string) => {
+  return request({
+    url: `/edu-app/userReceiveAddress/remove?id=${id}`,
+    method: "post"
+  } as any);
+};
+
+/** 收货地址详情 */
+export const api_userReceiveAddressDetail = (id: string) => {
+  return request({
+    url: `/edu-app/userReceiveAddress/detail/${id}`,
+    method: "get"
+  } as any);
 };

+ 4 - 2
miniprogram/app.json

@@ -8,13 +8,15 @@
     "pages/orders/order-result",
     "pages/protocol/register",
     "pages/service/service",
-    "pages/download/download"
+    "pages/download/download",
+    "pages/member/addMember",
+    "pages/member/memberList",
+    "pages/address/addressList"
   ],
   "window": {
     "navigationBarTextStyle": "black",
     "navigationStyle": "custom"
   },
-  "style": "v2",
   "rendererOptions": {
     "skyline": {
       "defaultDisplayBlock": true,

+ 25 - 1
miniprogram/app.less

@@ -1,4 +1,28 @@
 /**app.wxss**/
 .container {
   height: 100%;
-} 
+}
+
+page {
+  --overlay-background-color: rgba(0, 0, 0, 0.6);
+  --search-background-color: #f4f4f4;
+  --picker-cancel-action-color: #777777;
+  --picker-confirm-action-color: #0AAF20;
+  --picker-option-text-color: #000000;
+  --picker-option-font-size: 32rpx;
+}
+
+.van-picker__cancel {
+  font-size: var(--picker-option-font-size) !important;
+  padding: 0 14rpx !important;
+}
+
+.van-picker__confirm {
+  font-size: var(--picker-option-font-size) !important;
+  padding: 0 14rpx !important;
+}
+
+.van-picker__toolbar {
+  margin: 0 26rpx;
+  border-bottom: 2rpx solid #F2F2F2;
+}

+ 3 - 3
miniprogram/components/navigation-bar/navigation-bar.less

@@ -1,5 +1,5 @@
 .weui-navigation-bar {
-  --weui-FG-0:rgba(0,0,0,.9);
+  --weui-FG-0:rgba(0,0,0,1);
   --height: 44px;
   --left: 16px;
 }
@@ -48,8 +48,8 @@
 
 .weui-navigation-bar__btn_goback {
   font-size: 12px;
-  width: 12px;
-  height: 24px;
+  width: 36rpx;
+  height: 40rpx;
   -webkit-mask: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='24' viewBox='0 0 12 24'%3E  %3Cpath fill-opacity='.9' fill-rule='evenodd' d='M10 19.438L8.955 20.5l-7.666-7.79a1.02 1.02 0 0 1 0-1.42L8.955 3.5 10 4.563 2.682 12 10 19.438z'/%3E%3C/svg%3E") no-repeat 50% 50%;
   mask: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='24' viewBox='0 0 12 24'%3E  %3Cpath fill-opacity='.9' fill-rule='evenodd' d='M10 19.438L8.955 20.5l-7.666-7.79a1.02 1.02 0 0 1 0-1.42L8.955 3.5 10 4.563 2.682 12 10 19.438z'/%3E%3C/svg%3E") no-repeat 50% 50%;
   -webkit-mask-size: cover;

+ 4 - 0
miniprogram/components/numberDisplay/numberDisplay.json

@@ -0,0 +1,4 @@
+{
+  "component": true,
+  "usingComponents": {}
+}

+ 0 - 0
miniprogram/components/numberDisplay/numberDisplay.less


+ 22 - 0
miniprogram/components/numberDisplay/numberDisplay.ts

@@ -0,0 +1,22 @@
+Component({
+  properties: {
+    number: {
+      type: Number,
+      value: 0
+    }
+  },
+  data: {
+    integerPart: '',
+    decimalPart: ''
+  },
+  observers: {
+    number(newVal) {
+      const amountStr = newVal.toFixed(2)
+      const [integerPart, decimalPart] = amountStr.split('.');
+      this.setData({
+        integerPart,
+        decimalPart
+      });
+    }
+  }
+})

+ 3 - 0
miniprogram/components/numberDisplay/numberDisplay.wxml

@@ -0,0 +1,3 @@
+  <text class="integer">{{ integerPart }}</text>
+  <text class="decimal">.</text>
+  <text class="decimal">{{ decimalPart }}</text>

+ 1 - 1
miniprogram/config.ts

@@ -1,4 +1,4 @@
-const environmentVariable = "online";
+const environmentVariable = "dev";
 const apiUrlInfo = {
   dev: "https://dev.kt.colexiu.com",
   test: "https://test.kt.colexiu.com",

+ 8 - 0
miniprogram/pages/address/addAddress.json

@@ -0,0 +1,8 @@
+{
+  "component": true,
+  "usingComponents": {
+    "van-area": "@vant/weapp/area/index",
+    "van-popup": "@vant/weapp/popup/index",
+    "van-field": "@vant/weapp/field/index"
+  }
+}

+ 93 - 0
miniprogram/pages/address/addAddress.less

@@ -0,0 +1,93 @@
+.popup-section {
+  .popup-mask {
+    position: fixed;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background-color: rgba(0, 0, 0, 0.6);
+    z-index: 99999;
+  }
+
+  .popup-container {
+    position: fixed;
+    left: 0;
+    right: 0;
+    top: 50%;
+    transform: translateY(-50%);
+    z-index: 999999;
+    margin: 0 40rpx;
+    padding: 40rpx;
+    background: #FFFFFF;
+    border-radius: 32rpx;
+
+    .tit {
+      font-weight: 600;
+      font-size: 34rpx;
+      color: #131415;
+      line-height: 44rpx;
+      text-align: center;
+    }
+
+    .fromBox {
+      margin-top: 30rpx;
+
+      .fromCon {
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        padding: 16rpx 0;
+        border-bottom: 2rpx solid #F2F2F2;
+
+        .fromTit {
+          font-weight: 600;
+          font-size: 28rpx;
+          color: #666666;
+          line-height: 40rpx;
+          position: relative;
+        }
+
+        .fromIpt {
+          .van-field {
+            padding: 0;
+            --cell-line-height: 80rpx;
+
+            .van-cell__right-icon {
+              color: #cccccc;
+            }
+          }
+
+          .van-field__body {
+            .van-field__control {
+              color: #000000;
+              font-weight: 400;
+              font-size: 28rpx;
+            }
+          }
+        }
+      }
+    }
+
+    .closeBtn {
+      right: 26rpx;
+      top: 30rpx;
+      position: absolute;
+      width: 80rpx;
+      height: 80rpx;
+      background: url("https://oss.dayaedu.com/ktyq/1739246513167.png") no-repeat;
+      background-size: 52rpx 52rpx;
+      background-position: center center;
+    }
+
+    .subBtn {
+      margin-top: 100rpx;
+      font-weight: 600;
+      font-size: 32rpx;
+      color: #FFFFFF;
+      line-height: 88rpx;
+      text-align: center;
+      background: url("https://oss.dayaedu.com/ktyq/1738898417485.png") no-repeat;
+      background-size: 100% 100%;
+    }
+  }
+}

+ 217 - 0
miniprogram/pages/address/addAddress.ts

@@ -0,0 +1,217 @@
+import { api_sysAreaQueryAllProvince, api_userReceiveAddressUpdate, api_userReceiveAddressSave, api_userReceiveAddressDetail } from "../../api/login";
+Component({
+  properties: {
+    popupShow: {
+      type: Boolean,
+      value: false
+    },
+    editId: {
+      type: String,
+      value: ""
+    }
+  },
+  data: {
+    name: "",
+    phoneNumber: "",
+
+    showArea: false,
+    areaList: [] as any, // 省市区
+    province: "",
+    city: "",
+    region: "",
+    provinceName: "",
+    cityName: "",
+    regionName: "",
+
+    detailAddress: ""
+  },
+  pageLifetimes: {
+    show() {
+      this.getAreas()
+    },
+  },
+  observers: {
+    async editId(newVal: any) {
+      if (newVal) {
+        try {
+          const { data } = await api_userReceiveAddressDetail(newVal)
+          if (data.code === 200) {
+            const params = data.data
+            this.setData({
+              phoneNumber: params.phoneNumber,
+              name: params.name,
+              province: params.province,
+              city: params.city,
+              region: params.region,
+              provinceName: params.provinceName,
+              cityName: params.cityName,
+              regionName: params.regionName,
+              detailAddress: params.detailAddress
+            })
+          }
+        } catch (e: any) {
+          console.log(e, 888)
+        }
+      }
+    }
+  },
+  methods: {
+    onDialogClose() {
+      this.setData({
+        popupShow: false,
+        name: "",
+        phoneNumber: "",
+        province: "",
+        city: "",
+        region: "",
+        provinceName: "",
+        cityName: "",
+        regionName: "",
+        detailAddress: ""
+      })
+    },
+    /** 显示选择地区 */
+    onShowAreaList() {
+      this.setData({
+        showArea: true
+      })
+    },
+    /** 关闭选择地区 */
+    onCloseAreaList() {
+      this.setData({
+        showArea: false
+      })
+    },
+    /** 确定选择地区 */
+    submitArea(e: any) {
+      const selectedOptions: any = e.detail.values
+      if (!selectedOptions || !selectedOptions[selectedOptions.length - 1]) {
+        wx.showToast({
+          title: '未选中值',
+          icon: 'none'
+        })
+        return
+      }
+      this.setData({
+        province: selectedOptions[0].code,
+        city: selectedOptions[1].code,
+        region: selectedOptions[2].code,
+        provinceName: selectedOptions[0].name,
+        cityName: selectedOptions[1].name,
+        regionName: selectedOptions[2].name,
+        showArea: false
+      })
+    },
+    /** 获取省市区 */
+    async getAreas() {
+      try {
+        const { data } = await api_sysAreaQueryAllProvince({})
+        this.setData({
+          areaList: this.formateArea(data.data)
+        })
+      } catch {
+        // 
+      }
+    },
+    formateArea(area: any[]) {
+      const province_list: { [_: string]: string } = {};
+      const city_list: { [_: string]: string } = {};
+      const county_list: { [_: string]: string } = {};
+      area.forEach((item: any) => {
+        province_list[item.code] = item.name;
+      });
+      area.forEach((item: any) => {
+        item.areas && item.areas.forEach((city: any) => {
+          city_list[city.code] = city.name;
+        });
+      });
+      area.forEach((item: any) => {
+        item.areas && item.areas.forEach((city: any) => {
+          city.areas && city.areas.forEach((county: any) => {
+            county_list[county.code] = county.name;
+          });
+        });
+      });
+      return {
+        province_list,
+        city_list,
+        county_list
+      };
+    },
+    /** 最终提交 */
+    async onSubmit() {
+      try {
+        const params = this.data
+        if (!params.name) {
+          wx.showToast({
+            title: '请输入收货人',
+            icon: "none"
+          })
+          return
+        }
+        if (!params.phoneNumber || !/^1[3456789]\d{9}$/.test(params.phoneNumber)) {
+          wx.showToast({
+            title: '请输入正确的手机号',
+            icon: "none"
+          })
+          return
+        }
+
+        if (!params.province || !params.city || !params.region) {
+          wx.showToast({
+            title: '请选择地区',
+            icon: "none"
+          })
+          return
+        }
+        if (!params.detailAddress) {
+          wx.showToast({
+            title: '请输入详细地址',
+            icon: "none"
+          })
+          return
+        }
+        // 编辑
+        let id
+        if (params.editId) {
+          id = params.editId
+          await api_userReceiveAddressUpdate({
+            id: params.editId,
+            phoneNumber: params.phoneNumber,
+            name: params.name,
+            province: params.province,
+            city: params.city,
+            region: params.region,
+            detailAddress: params.detailAddress,
+            defaultStatus: false,
+            postCode: "",
+          })
+          wx.showToast({
+            title: '保存成功',
+            icon: 'none'
+          })
+        } else {
+          const { data } = await api_userReceiveAddressSave({
+            phoneNumber: params.phoneNumber,
+            name: params.name,
+            province: params.province,
+            city: params.city,
+            region: params.region,
+            detailAddress: params.detailAddress,
+            defaultStatus: false,
+            postCode: "",
+          })
+          id = data.data
+          wx.showToast({
+            title: '保存成功',
+            icon: 'none'
+          })
+        }
+        this.triggerEvent('addAddress', { addressInfo: { id, name: params.name, phoneNumber: params.phoneNumber, addressDes: params.provinceName + params.cityName + params.regionName + params.detailAddress } }, {})
+        this.onDialogClose()
+      } catch {
+        // 
+      }
+    },
+  }
+})

+ 40 - 0
miniprogram/pages/address/addAddress.wxml

@@ -0,0 +1,40 @@
+<view class="popup-section" wx:if="{{popupShow}}">
+  <view class="popup-mask" bind:tap="onDialogClose"></view>
+  <view class="popup-container">
+    <view class="closeBtn" bind:tap="onDialogClose"></view>
+    <view class="tit">{{ editId?"编辑收货信息":"新建收货地址" }}</view>
+    <view class="fromBox">
+      <view class="fromCon">
+        <text class="fromTit">收货人</text>
+        <view class="fromIpt">
+          <van-field model:value="{{ name }}" input-align="right" placeholder="请填写收货人姓名" border="{{ false }}" />
+        </view>
+      </view>
+      <view class="fromCon">
+        <text class="fromTit">联系电话</text>
+        <view class="fromIpt">
+          <van-field model:value="{{ phoneNumber }}" type="{{ 'number' }}" input-align="right" placeholder="请输入联系电话" border="{{ false }}" />
+        </view>
+      </view>
+      <view class="fromCon">
+        <text class="fromTit">选择地区</text>
+        <view class="fromIpt">
+          <van-field placeholder="请选择地区" value="{{  provinceName  + cityName  + regionName}}" input-align="right" bind:tap="onShowAreaList" border="{{ false }}" is-link readonly />
+        </view>
+      </view>
+      <view class="fromCon">
+        <text class="fromTit">详细地址</text>
+        <view class="fromIpt">
+          <van-field model:value="{{ detailAddress }}" input-align="right" placeholder="请填写街道、小区、门牌号等信息" border="{{ false }}" />
+        </view>
+      </view>
+    </view>
+    <view class="subBtn" bind:tap="onSubmit">
+      保存
+    </view>
+  </view>
+  <!-- 地区 -->
+  <van-popup round="{{true}}" lock-scroll="{{true}}" z-index="{{99999999}}" show="{{showArea}}" position="bottom" safe-area-inset-bottom="{{false}}" bind:close="onCloseAreaList">
+    <van-area areaList="{{areaList}}" visible-item-count="6" item-height="46" value="{{ region }}" bind:cancel="onCloseAreaList" bind:confirm="submitArea" />
+  </van-popup>
+</view>

+ 6 - 0
miniprogram/pages/address/addressList.json

@@ -0,0 +1,6 @@
+{
+  "usingComponents": {
+    "navigation-bar": "/components/navigation-bar/navigation-bar",
+    "addAddress": "../address/addAddress"
+  }
+}

+ 222 - 0
miniprogram/pages/address/addressList.less

@@ -0,0 +1,222 @@
+.memberList {
+  position: relative;
+  height: 100vh;
+  background: #F5F6F7;
+  display: flex;
+  flex-direction: column;
+
+  .weui-navigation-bar {
+    position: relative;
+    z-index: 2;
+  }
+
+  .appBg {
+    position: absolute;
+    left: 0;
+    top: 0;
+    width: 100%;
+    height: 592rpx;
+    background: url("https://oss.dayaedu.com/ktyq/1738997023805.png") no-repeat;
+    background-size: 100% 100%;
+    z-index: 1;
+  }
+
+  .memberListCon {
+    position: relative;
+    z-index: 2;
+    flex-grow: 1;
+    padding-bottom: 200rpx;
+    padding-top: 36rpx;
+    overflow: hidden;
+
+    .memberInfo {
+      margin: 0 26rpx;
+      background: #FFFFFF;
+      border-radius: 20rpx;
+      padding: 24rpx 24rpx 32rpx;
+      margin-bottom: 24rpx;
+      border: 3rpx solid transparent;
+
+      &.active {
+        border-color: #0AAF20;
+      }
+
+      &:last-child {
+        margin-bottom: 0;
+      }
+
+      .infoCon {
+        display: flex;
+        align-items: center;
+        font-weight: 600;
+        font-size: 28rpx;
+        color: #131415;
+        line-height: 40rpx;
+
+        .tip {
+          width: 44rpx;
+          height: 44rpx;
+        }
+
+        .name,
+        .phone {
+          margin-left: 16rpx;
+        }
+      }
+
+      .schoolInfoCon {
+        margin-top: 20rpx;
+
+        .schoolInfo {
+          margin-right: 8rpx;
+          border-radius: 4rpx;
+          border: 1rpx solid rgba(243, 131, 9, 0.5);
+          padding: 2rpx 6rpx;
+          font-weight: 400;
+          font-size: 20rpx;
+          color: #F38309;
+          line-height: 30rpx;
+        }
+
+        .schoolInfoDes {
+          font-weight: 400;
+          font-size: 24rpx;
+          color: #777777;
+          line-height: 32rpx;
+        }
+      }
+
+      .operateCon {
+        margin-top: 32rpx;
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+
+        .radio {
+          display: flex;
+          align-items: center;
+
+          image {
+            width: 32rpx;
+            height: 32rpx;
+          }
+
+          text {
+            margin-left: 12rpx;
+            font-weight: 400;
+            font-size: 24rpx;
+            color: #777777;
+            line-height: 32rpx;
+          }
+        }
+
+        .operate {
+          display: flex;
+          align-items: center;
+
+          view {
+            background: #F2F2F2;
+            border-radius: 24rpx;
+            padding: 6rpx 24rpx;
+            font-weight: 400;
+            font-size: 24rpx;
+            color: #333333;
+            line-height: 34rpx;
+
+            &:first-child {
+              margin-right: 24rpx;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  .submitCon {
+    z-index: 10;
+    position: fixed;
+    left: 0;
+    bottom: 0;
+    padding: 32rpx 40rpx 56rpx;
+    width: 100%;
+    box-sizing: border-box;
+    background: #FFFFFF;
+    box-shadow: 0rpx -2rpx 24rpx 0rpx rgba(0, 0, 0, 0.1);
+    border-radius: 32rpx 32rpx 0rpx 0rpx;
+
+    .subBtn {
+      width: 100%;
+      height: 88rpx;
+      font-weight: 600;
+      font-size: 32rpx;
+      color: #FFFFFF;
+      line-height: 88rpx;
+      background: url("https://oss.dayaedu.com/ktyq/1738898417485.png") no-repeat;
+      background-size: 100% 100%;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+
+      image {
+        width: 40rpx;
+        height: 40rpx;
+        margin-right: 12rpx;
+      }
+    }
+  }
+
+  .popup-section {
+    .popup-mask {
+      position: fixed;
+      top: 0;
+      left: 0;
+      right: 0;
+      bottom: 0;
+      background-color: rgba(0, 0, 0, 0.6);
+      z-index: 99999;
+    }
+
+    .popup-container {
+      position: fixed;
+      left: 0;
+      right: 0;
+      top: 50%;
+      transform: translateY(-50%);
+      z-index: 999999;
+      margin: 0 100rpx;
+      padding: 50rpx 0 40rpx 0;
+      background: #FFFFFF;
+      border-radius: 32rpx;
+
+      .tit {
+        font-weight: 600;
+        font-size: 32rpx;
+        color: #000000;
+        line-height: 44rpx;
+        text-align: center;
+      }
+
+      .btnCon {
+        display: flex;
+        justify-content: center;
+        margin-top: 50rpx;
+
+        view {
+          font-weight: 400;
+          font-size: 28rpx;
+          color: #000000;
+          line-height: 36rpx;
+          padding: 16rpx 72rpx;
+          border-radius: 36rpx;
+          border: 2rpx solid #DCDCDC;
+
+          &:last-child {
+            margin-left: 32rpx;
+            background: #000000;
+            color: #fff;
+          }
+        }
+      }
+    }
+  }
+}

+ 110 - 0
miniprogram/pages/address/addressList.ts

@@ -0,0 +1,110 @@
+import { api_getUserReceiveAddressPage, api_userReceiveAddressRemove } from "../../api/login";
+
+
+Page({
+  data: {
+    id: "", //当前选中的id
+    popupShow: false,
+    selectedId: "",
+    addressList: [],
+    addAddressPopupShow: false,
+    editId: ""
+  },
+  onShow() {
+    this.getPageList()
+  },
+  onLoad(options: any) {
+    const { id } = options;
+    this.setData({
+      id
+    })
+  },
+  async getPageList() {
+    try {
+      const resData = await api_getUserReceiveAddressPage()
+      const pageRows = resData?.data?.data?.rows || []
+      this.setData({
+        addressList: pageRows
+      })
+    } catch (e) {
+      console.log(e, 'e')
+    }
+  },
+  onDialogClose() {
+    this.setData({
+      popupShow: false
+    })
+  },
+  async onDialogOk() {
+    try {
+      const { data } = await api_userReceiveAddressRemove(this.data.selectedId)
+      if (data.code === 200) {
+        this.setData({
+          popupShow: false
+        })
+        await this.getPageList()
+        // 当删的是当前选中的
+        if (this.data.selectedId === this.data.id) {
+          let item: any
+          if (this.data.addressList.length) {
+            item = this.data.addressList[0]
+            this.setData({
+              id: item.id
+            })
+          }
+          this.setPagesData(item)
+        }
+      }
+    } catch (e: any) { }
+  },
+  onDel(e: any) {
+    const { dataset } = e.currentTarget
+    this.setData({
+      selectedId: dataset.id
+    })
+    this.setData({
+      popupShow: true
+    })
+  },
+  onEdit(e: any) {
+    const { dataset } = e.currentTarget
+    this.setData({
+      editId: dataset.id,
+      addAddressPopupShow: true
+    })
+  },
+  onAdd() {
+    this.setData({
+      editId: "",
+      addAddressPopupShow: true
+    })
+  },
+  onSelect(e: any) {
+    const { dataset } = e.currentTarget
+    const item = dataset.item;
+    this.setPagesData(item)
+    wx.navigateBack()
+  },
+  async onAddAddress() {
+    // 编辑
+    if (this.data.editId) {
+      await this.getPageList()
+      if (this.data.editId === this.data.id) {
+        // 编辑 完了之后刷新上一页的数据
+        const item = this.data.addressList.find(((item: any) => {
+          return item.id === this.data.id
+        }))
+        this.setPagesData(item)
+      }
+    } else {
+      // 新增
+      this.getPageList()
+    }
+  },
+  setPagesData(item: any) {
+    console.log(item,233339999)
+    const pages = getCurrentPages();
+    const prevPage = pages[pages.length - 2]; // 获取上一个页面实例
+    prevPage.setData({ addressInfo: item ? { id: item.id, name: item.name, phoneNumber: item.phoneNumber, addressDes: item.provinceName + item.cityName + item.regionName + item.detailAddress } : {} });
+  }
+})

+ 47 - 0
miniprogram/pages/address/addressList.wxml

@@ -0,0 +1,47 @@
+<view class="memberList">
+  <navigation-bar title="选择收货信息"></navigation-bar>
+  <view class="appBg"></view>
+  <scroll-view scroll-y class="memberListCon">
+    <view wx:for="{{ addressList }}" wx:key="index" bind:tap="onSelect" data-item="{{ item }}" class="memberInfo {{ item.id === id?'active':'' }}">
+      <view class="infoCon">
+        <image class="tip" src="../orders/images/member.png" />
+        <text class="name">{{item.name}}</text>
+        <text class="phone">{{item.phoneNumber}}</text>
+      </view>
+      <view class="schoolInfoCon">
+        <text class="schoolInfo">收货地址</text><text class="schoolInfoDes">{{
+          item.provinceName + item.cityName + item.regionName + item.detailAddress
+        }}
+        </text>
+      </view>
+      <view class="operateCon">
+        <view class="radio">
+          <image wx:if="{{item.id === id}}" src="../login/images/radio-active.png"></image>
+          <image wx:else src="../login/images/radio-default.png"></image>
+          <text>{{ item.id === id ? "当前选中" : "未选中"}}</text>
+        </view>
+        <view class="operate">
+          <view catch:tap="onDel" data-id="{{ item.id }}">删除</view>
+          <view catch:tap="onEdit" data-id="{{ item.id }}">编辑</view>
+        </view>
+      </view>
+    </view>
+  </scroll-view>
+  <view class="submitCon">
+    <view class="subBtn" bind:tap="onAdd">
+      <image src="../member/images/user.png" />
+      新增收货信息
+    </view>
+  </view>
+  <view class="popup-section" wx:if="{{popupShow}}">
+    <view class="popup-mask" bind:tap="onDialogClose"></view>
+    <view class="popup-container">
+      <view class="tit">请确认是否删除该收货信息</view>
+      <view class="btnCon">
+        <view bind:tap="onDialogClose">取消</view>
+        <view bind:tap="onDialogOk">确认</view>
+      </view>
+    </view>
+  </view>
+  <addAddress editId="{{editId}}" popupShow='{{addAddressPopupShow}}' bind:addAddress="onAddAddress"></addAddress>
+</view>

BIN
miniprogram/pages/index/images/chevron.png


BIN
miniprogram/pages/index/images/icon-close.png


BIN
miniprogram/pages/index/images/member.png


BIN
miniprogram/pages/index/images/order.png


BIN
miniprogram/pages/index/images/yhj.png


+ 2 - 1
miniprogram/pages/index/index.json

@@ -1,6 +1,7 @@
 {
   "usingComponents": {
     "navigation-bar": "/components/navigation-bar/navigation-bar",
-    "service": "/components/service/service"
+    "service": "/components/service/service",
+    "numberDisplay": "/components/numberDisplay/numberDisplay"
   }
 }

+ 249 - 295
miniprogram/pages/index/index.less

@@ -12,14 +12,6 @@ page {
 
 .container {
   position: relative;
-  .topShadow {
-    position: absolute;
-    top: 0;
-    z-index: 1;
-    width: 100%;
-    height: 200rpx;
-    background: linear-gradient( 180deg, rgba(0,0,0,0.7) 0%, rgba(0,0,0,0) 100%);
-  }
   .slider-count {
     position: absolute;
     top: 678rpx;
@@ -56,131 +48,7 @@ page {
   }
 }
 
-
-.shop-section {
-  background: #FFFFFF;
-  // border-radius: 20rpx;
-  // margin: 16rpx 16rpx 0;
-  padding: 32rpx 32rpx 40rpx;
-  .showPrice {
-    display: flex;
-    justify-content: space-between;
-    align-items: center;
-  }
-  .left {
-    flex: 1 auto;
-    display: flex;
-    align-items: flex-end;
-  }
-  .currentPrice {
-    font-weight: bold;
-    color: #FF5000;
-    font-family: DINAlternate, DINAlternate;
-    .stuff {
-      font-size: 36rpx;
-    }
-    .priceZ {
-      font-size: 60rpx;
-    }
-    .priceF {
-      font-size: 36rpx;
-    }
-  }
-  .originPrice {
-    padding-left: 16rpx;
-    font-size: 32rpx;
-    color: #AAAAAA;
-    line-height: 44rpx;
-    text-decoration: line-through;
-    padding-bottom: 12rpx;
-  }
-  .right {
-    padding-top: 14rpx;
-    font-weight: 400;
-    font-size: 28rpx;
-    color: #FF5000;
-    line-height: 40rpx;
-  }
-}
-.shopName {
-  font-weight: 600;
-  font-size: 32rpx;
-  color: #131415;
-  line-height: 44rpx;
-  padding: 24rpx 0 10rpx;
-}
-
-.goodsInfo {
-  display: flex;
-  // align-items: center;
-  .desc {
-    font-size: 28rpx;
-    color: #131415;
-    line-height: 68rpx;
-    margin: 24rpx 0;
-    flex-shrink: 0;
-  }
-
-  .goodsList {
-    display: flex;
-    align-items: center;
-    flex-wrap: nowrap;
-    overflow-x: auto;
-    overflow-y: hidden;
-    &::-webkit-scrollbar {
-      display: none;
-    }
-  }
-  .goodsItem {
-    line-height: 68rpx;
-    background: #F6F5F5;
-    border-radius: 8rpx;
-    font-size: 28rpx;
-    color: #131415;
-    position: relative;
-    margin-top: 30rpx;
-    margin-right: 30rpx;
-    display: flex;
-    flex-direction: column;
-    border: 4rpx solid #F4F4F4;
-
-    &.selected {
-      background: #FFEEE6;
-      color: #FF5000;
-      border: 4rpx solid #FF5000;
-      border-radius: 12rpx;
-    }
-
-    &.nosale {
-      background: #F6F5F5;
-      color: #B3B3B3;
-      .goods-cover, .name {
-        opacity: 0.6;
-      }
-    }
-    .name {
-      padding-left: 8rpx;
-    }
-    .goods-cover {
-      width: 124rpx;
-      height: 124rpx;
-      border-radius: 8rpx 8rpx 0 0;
-    }
-    .iconSale {
-      position: absolute;
-      top: -14rpx;
-      right: -14rpx;
-      width: 56rpx;
-      height: 28rpx;
-      display: block;
-      z-index: 1;
-    }
-  }
-}
-
 .goodsSection {
-  // margin-bottom: 156rpx;
-  padding-bottom: 160rpx;
 }
 .goodsIntro {
   background: #FFFFFF;
@@ -243,79 +111,45 @@ page {
   }
 }
 
-.orders {
-    display: flex;
-    flex-direction: column;
-    position: fixed;
-    right: 12rpx;
-    bottom: 202rpx;
-    image {
-      width: 112rpx;
-      height: 118rpx;
-    }
-    // text {
-    //   font-weight: 500;
-    //   font-size: 22rpx;
-    //   color: #131415;
-    //   line-height: 32rpx;
-    //   text-align: center;
-    // }
-  }
-
+.bottom-sectionBox{
+  width: 100%;
+  background-color: #E0F5DA;
+}
 .bottom-section {
-  position: fixed;
-  bottom: 0;
-  left: 0;
   width: 100%;
-  background-color: #FFFFFF;
-  box-shadow: inset 0rpx 2rpx 0rpx 0rpx #F0F0F0;
-  padding: 20rpx 32rpx 58rpx 32rpx;
+  background: #FFFFFF;
+  box-shadow: 0rpx -2rpx 32rpx 0rpx rgba(0,0,0,0.1);
+  border-radius: 32rpx 32rpx 0rpx 0rpx;
+  padding: 34rpx 40rpx 56rpx 48rpx;
   display: flex;
   align-items: center;
   box-sizing: border-box;
   .orders {
     display: flex;
     flex-direction: column;
-    margin-right: 40rpx;
     image {
       width: 48rpx;
       height: 48rpx;
     }
     text {
-      font-weight: 500;
+      margin-top: 2px;
+      font-weight: 400;
       font-size: 22rpx;
       color: #131415;
       line-height: 32rpx;
-      text-align: center;
     }
   }
   .btnSection {
-    flex: 1 auto;
-    display: flex;
-    button {
-      width: 100%;
-      line-height: 88rpx;
-      background: linear-gradient( 315deg, #FF4A00 0%, #FE8C00 100%);
-      border-radius: 16rpx;
-      font-weight: 500;
-      font-size: 32rpx;
-      color: #FFFFFF;
-      padding-top: 0;
-      padding-bottom: 0;
-
-      &[disabled][type=primary] {
-        opacity: 0.7;
-      }
-
-      &:first-child {
-        background: linear-gradient( 135deg, #FF9800 0%, #FFB300 100%);
-        border-radius: 16rpx 0rpx 0rpx 16rpx;
-      }
-      &:last-child {
-        background: linear-gradient( 315deg, #FF4A00 0%, #FE8C00 100%);
-        border-radius: 0rpx 16rpx 16rpx 0rpx;
-      }
-    }
+    margin-left: 48rpx;
+    flex-grow: 1;
+    font-weight: 600;
+    font-size: 32rpx;
+    color: #FFFFFF;
+    line-height: 88rpx;
+    text-align: center;
+    background: url("https://oss.dayaedu.com/ktyq/1738898417485.png") no-repeat;
+    background-size: 100% 100%;
+    border-radius: 78rpx;
   }
 }
 
@@ -326,9 +160,6 @@ page {
 
 // 'demo-text-1', 'demo-text-2', 'demo-text-3'
 .popup-section {
-  &.hidden {
-    display: none;
-  }
 
   .popup-mask {
     position: fixed;
@@ -350,131 +181,254 @@ page {
     border-radius: 32rpx 32rpx 0rpx 0rpx;
     padding: 40rpx 0 58rpx;
     box-sizing: border-box;
-
-    .goodsInfo {
-      .desc {
-        padding-bottom: 0;
-        margin-left: 0;
-        margin-bottom: 0;
-        font-size: 32rpx;
-        font-weight: 600;
+    .iconClose {
+      position: absolute;
+      right: 40rpx;
+      top: 40rpx;
+      width: 40rpx;
+      height: 40rpx;
+    }
+    .product-section {
+      display: flex;
+      padding: 0 40rpx;
+      .product-img {
+        width: 160rpx;
+        height: 160rpx;
+        flex-shrink: 0;
+        margin-right: 32rpx;
+        border-radius: 6px;
+        overflow: hidden;
+        image {
+          width: 100%;
+          height: 100%;
+        }
       }
-      .goodsList {
-        max-height: 500rpx;
-        padding: 0 32rpx;
-        flex-wrap: wrap;
-        overflow-x: hidden;
-        overflow-y: auto;
-        &::-webkit-scrollbar {
-          display: none;
+      .product-left {
+        display: flex;
+        flex-direction: column;
+        align-items: flex-start;
+        overflow: hidden;
+        .price-s {
+          display: flex;
+          align-items: center;
+          .priceImg{
+            margin-right: 8rpx;
+            width: 96rpx;
+            height: 40rpx;
+          }
+          .currentPrice {
+            font-weight: bold;
+            color: #000000;
+            font-family: DINAlternate, DINAlternate;
+            line-height: 1;
+            .stuff {
+              font-size: 32rpx;
+            }
+            .numberDisplay--integer{
+              line-height: 60rpx;
+              font-size: 52rpx;
+            }
+            .numberDisplay--decimal{
+              font-size: 32rpx;
+            }
+          }
+          .originPrice {
+            margin-left: 8rpx;
+            font-weight: 400;
+            font-size: 28rpx;
+            color: #AAAAAA;
+            text-decoration: line-through;
+          }
         }
+        .current-s {
+          margin-top: 8rpx;
+          font-weight: 400;
+          font-size: 26rpx;
+          color: #777777;
+          line-height: 36rpx;
+          white-space: nowrap;
+          overflow: hidden;
+          text-overflow: ellipsis;
+        }
+        .discountCon{
+          margin-top: 16rpx;
+          font-weight: 400;
+          font-size: 24rpx;
+          color: #FD4502;
+          line-height: 32rpx;
+          border-radius: 6rpx;
+          border: 2rpx solid #FD4502;
+          padding: 4rpx 8rpx;
+        }
+      }
+    }
+    .memberBox{
+      margin: 48rpx 40rpx;
+      background: #F5F6F7;
+      border-radius: 20rpx;
+      border: 3rpx solid transparent;
+      &.showMemberInfoTip{
+        border-color: #FD4502;
       }
-      .goodsItem {
-        margin-right: 18rpx;
-        .goods-cover {
-          width: 208rpx;
-          height: 208rpx;
+      .memberCon{
+        padding: 24rpx;
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        .memberImg{
+          width: 44rpx;
+          height: 44rpx;
+        }
+        .info{
+          flex-grow: 1;
+          margin-left: 16rpx;
+          font-weight: 600;
+          font-size: 28rpx;
+          color: #131415;
+          line-height: 40rpx;
+        }
+        .chevronImg{
+          flex-shrink: 0;
+          width: 32rpx;
+          height: 32rpx;
+        }
+        .memberInfoCon{
+          overflow: hidden;
         }
-        &:nth-child(3n + 3) {
-          margin-right: 0;
+        .infoCon {
+          display: flex;
+          align-items: center;
+          font-weight: 600;
+          font-size: 28rpx;
+          color: #131415;
+          line-height: 40rpx;
+          .tip {
+            width: 44rpx;
+            height: 44rpx;
+          }
+          .name,
+          .phone {
+            margin-left: 16rpx;
+          }
+        }
+        .schoolInfoCon{
+          margin-top: 20rpx;
+          display: flex;
+          align-items: center;
+          .schoolInfo{
+            margin-right: 8rpx;
+            border-radius: 4rpx;
+            border: 1rpx solid rgba(15,179,96,0.5);
+            padding: 2rpx 6rpx;
+            font-weight: 400;
+            font-size: 20rpx;
+            color: #0FB360;
+            line-height: 30rpx;
+            flex-shrink: 0;
+          }
+          .schoolInfoDes{
+            margin-right: 10rpx;
+            font-weight: 400;
+            font-size: 24rpx;
+            color: #777777;
+            line-height: 32rpx;
+            white-space: nowrap;
+            overflow: hidden;
+            text-overflow: ellipsis;
+          }
         }
       }
     }
-  }
-
-  .iconClose {
-    position: absolute;
-    right: 32rpx;
-    top: 40rpx;
-    width: 30rpx;
-    height: 30rpx;
-  }
-
-  .product-section {
-    display: flex;
-    // padding-bottom: 60rpx;
-    padding: 0 32rpx 60rpx;
-    .product-img {
-      width: 160rpx;
-      height: 160rpx;
-      flex-shrink: 0;
-      margin-right: 32rpx;
-      border-radius: 6px;
-      overflow: hidden;
-      image {
+    .btnSections {
+      margin-top: 128rpx;
+      padding: 0 40rpx;
+      button {
         width: 100%;
-        height: 100%;
+        line-height: 88rpx;
+        background: url("https://oss.dayaedu.com/ktyq/1738898417485.png") no-repeat;
+        background-size: 100% 100%;
+        font-weight: 500;
+        font-size: 32rpx;
+        color: #FFFFFF;
+        padding-top: 0;
+        padding-bottom: 0;
+        border-radius: 78rpx;
+        &[disabled][type=primary] {
+          color: #fff;
+          opacity: 0.7;
+        }
       }
     }
-    .product-left {
-      display: flex;
-      flex-direction: column;
-      .price-s {
-        display: flex;
-        align-items: flex-start;
+    .goodsInfo {
+      padding: 0 40rpx;
+      max-height: 478rpx;
+      overflow-x: hidden;
+      overflow-y: auto;
+      &::-webkit-scrollbar {
+        display: none;
       }
-      .current-s {
+      .desc {
+        margin-top: 48rpx;
+        font-weight: 600;
         font-size: 28rpx;
-        color: #131415;
         line-height: 40rpx;
-        padding-top: 20rpx;
-        text {
-          color: #FF5000;
-        }
-      }
-
-      .currentPrice {
-        font-weight: bold;
-        color: #FF5000;
-        font-family: DINAlternate, DINAlternate;
-        .stuff {
-          font-size: 36rpx;
-        }
-        .priceZ {
-          font-size: 60rpx;
+        color: #131415;
+        &:first-child{
+          margin-top: 0;
         }
-        .priceF {
-          font-size: 36rpx;
+        text{
+          color: #FD4502;
         }
       }
-      .originPrice {
-        padding-left: 16rpx;
-        font-size: 32rpx;
-        color: #AAAAAA;
-        line-height: 44rpx;
-        text-decoration: line-through;
-        padding-top: 30rpx;
+      .goodsList {
+        display: flex;
+        flex-wrap: wrap;
+        .goodsItem {
+          margin-right: 24rpx;
+          margin-top: 24rpx;
+          padding: 10rpx 30rpx;
+          background: #F2F2F2;
+          border-radius: 12rpx;
+          font-weight: 400;
+          font-size: 28rpx;
+          color: #444444;
+          line-height: 40rpx;
+          position: relative;
+          border:2rpx solid transparent;
+          &.instrumentsGoodsItem{
+            display: flex;
+            align-items: center;
+            view{
+              margin: 0 16rpx;
+              width: 2rpx;
+              height: 32rpx;
+              background: rgba(0,0,0,0.3);
+            }
+          }
+          &.nosale{
+            color: #BBBBBB;
+          }
+          &.selected{
+            background: #E6FADB;
+            font-weight: 600;
+            color: #0AAF5F;
+            border-color: #51BA35;
+            border-radius: 12rpx;
+            view{
+              background: #0AAF5F; 
+            }
+          }
+          .iconSale{
+            position: absolute;
+            width: 56rpx;
+            height: 28rpx;
+            right: -14rpx;
+            top: -14rpx;
+          }
+        }
       }
     }
   }
-
-  .goodsInfo {
-    flex-direction: column;
-    align-items: flex-start;
-    padding-bottom: 90rpx;
-    
-    .desc {
-      font-size: 28rpx;
-      color: #131415;
-      line-height: 40rpx;
-      padding: 0 32rpx 30rpx;
-    }
-  }
-
-  .btnSections {
-    padding: 0 32rpx;
-  }
-  button {
-    width: 100%;
-    line-height: 88rpx;
-    background: linear-gradient( 315deg, #FF4A00 0%, #FE8C00 100%);
-    border-radius: 16rpx;
-    font-weight: 500;
-    font-size: 32rpx;
-    color: #FFFFFF;
-    padding-top: 0;
-    padding-bottom: 0;
-  }
 }
 
 .showMoreContainer {

+ 78 - 67
miniprogram/pages/index/index.ts

@@ -1,6 +1,6 @@
 // index.ts
 
-import { api_shopProduct } from "../../api/login";
+import { api_shopProduct, api_shopInstruments, api_getUserBeneficiaryPage } from "../../api/login";
 import { debounce } from '../../utils/util'
 
 // 获取应用实例
@@ -11,29 +11,21 @@ Page({
    * 页面的初始数据
    */
   data: {
-    imgList: [
-      'https://oss.dayaedu.com/ktyq/1732672861312.png',
-      'https://oss.dayaedu.com/ktyq/1732613781003.png',
-      'https://oss.dayaedu.com/ktyq/1733118132694.png',
-      'https://oss.dayaedu.com/ktyq/1732613807112.png',
-      // 'https://oss.dayaedu.com/ktyq/1732101102921.png',
-    ],
-    
     goodsImgList: [
-      "https://oss.dayaedu.com/ktyq/1733130441242.png",
-      "https://oss.dayaedu.com/ktyq/1733118166964.png",
-      "https://oss.dayaedu.com/ktyq/1732706055542.png",
-      "https://oss.dayaedu.com/ktyq/1732706066094.png"
+      "https://oss.dayaedu.com/ktyq/1738911119867.png",
+      "https://oss.dayaedu.com/ktyq/1738911247330.png",
+      "https://oss.dayaedu.com/ktyq/1738911265298.png",
+      "https://oss.dayaedu.com/ktyq/1738911576725.png"
     ],
     serviceShow: true,
-    current: 0,
-    // autoplay: false,
-    // interval: 5000,
-    // duration: 500,
     popupShow: false,
     list: [] as any,
+    instrumentsList: [] as any[],
     isOverSaled: false, // 是否所有商品都没有库存
     selected: {} as any,
+    selectedInstruments: {} as any,
+    memberInfo: {} as any, // 会员信息
+    isShowMemberInfoTip: false, // 会员信息提示
     isFromPreviewImage: false,
     isShowOperation: false, // 是否显示操作按钮
   },
@@ -49,49 +41,37 @@ Page({
    */
   async onInit() {
     try {
-      const { data } = await api_shopProduct({ appId: app.globalData.appId });
+      const [{ data }, { data: instrumentsData }] = await Promise.all([api_shopProduct({ appId: app.globalData.appId }), api_shopInstruments({ appId: app.globalData.appId })])
+      // 商品
       const list = data.data || []
       let selected: any = {}
       let isOverSaled = true // 是否销售完
       list.forEach((item: any) => {
-        item.originalPrice = this.formatPrice(item.originalPrice, 'ALL');
         item.typeName = this.formatPeriod(item.num, item.period);
-        const prices: any = this.formatPrice(item.salePrice)
-        item.integerPart = prices.integerPart
-        item.decimalPart = prices.decimalPart
-        if(item.stockNum > 0) {
+        if (item.stockNum > 0) {
           isOverSaled = false
-          if( !selected.id) {
+          if (!selected.id) {
             selected = item
           }
         }
       });
-      if(isOverSaled) {
+      if (isOverSaled) {
         // 没有可购买商品则默认选中第一个商品
         selected = list[0]
       }
-
+      // 乐器
+      const instrumentsList = instrumentsData.data
       this.setData({
         list,
         isOverSaled,
-        selected
+        selected,
+        instrumentsList,
+        selectedInstruments: {}
       })
-    } catch(e) {
+    } catch (e) {
       console.log(e, 'e')
     }
   },
-  // 格式化价格
-  formatPrice(price: number, type?: string) {
-    const amountStr = price.toFixed(2)
-    const [integerPart, decimalPart] = amountStr.split('.');
-    if(type === 'ALL') {
-      return amountStr
-    }
-    return {
-      integerPart,
-      decimalPart
-    }
-  },
   // 格式化类型
   formatPeriod(num: number, type: string) {
     const template: any = {
@@ -99,7 +79,7 @@ Page({
       MONTH: "月卡",
       YEAR: "年卡"
     }
-    if(type === "YEAR" && num >= 99) {
+    if (type === "YEAR" && num >= 99) {
       return '永久卡'
     }
     return num + template[type]
@@ -109,25 +89,26 @@ Page({
     const { dataset } = e.currentTarget
     const item = this.data.list.find((item: any) => item.id === dataset.id)
     // 判断是否有库存
-    if(item.stockNum <= 0) {
+    if (item.stockNum <= 0) {
       return
     }
     this.setData({
       selected: item || {}
     })
   },
-  // 事件处理函数
-  changeSwiper(e: any) {
-    const detail = e.detail;
-    if(detail.source === 'touch' || detail.source == 'autoplay') {
-      this.setData({
-        current: detail.current
-      })
+  onSelectInstrumentsGoods(e: any) {
+    const { dataset } = e.currentTarget
+    let item = this.data.instrumentsList[dataset.index]
+    if (item?.id === this.data.selectedInstruments?.id) {
+      item = {}
     }
+    this.setData({
+      selectedInstruments: item || {}
+    })
   },
   isLogin() {
     // 判断是否登录
-    if(!app.globalData.isLogin) {
+    if (!app.globalData.isLogin) {
       wx.navigateTo({
         url: '../login/login',
       })
@@ -138,7 +119,7 @@ Page({
   /** 我的订单 */
   onOrder() {
     // 判断是否登录
-    if(!this.isLogin()) {
+    if (!this.isLogin()) {
       return
     }
     wx.navigateTo({
@@ -147,7 +128,7 @@ Page({
   },
   onBuyShop() {
     // 判断是否登录
-    if(!this.isLogin()) {
+    if (!this.isLogin()) {
       return
     }
     this.setData({
@@ -159,38 +140,68 @@ Page({
       popupShow: false
     })
   },
+  async onMemberInfo() {
+    this.setData({
+      isShowMemberInfoTip: false
+    })
+    try {
+      const resData = await api_getUserBeneficiaryPage()
+      const pageRows = resData?.data?.data?.rows || []
+      // 当有权益人的时候跳转到权益人选择列表页面,当没有权益人的时候到添加权益人页面
+      if (pageRows.length) {
+        wx.navigateTo({
+          url: `/pages/member/memberList?id=${this.data.memberInfo.id}`
+        });
+      } else {
+        // 当redirectUrl等于index的时候证明是首次添加,需要给上一个页面
+        wx.navigateTo({
+          url: `/pages/member/addMember?redirectUrl=index`
+        });
+      }
+    } catch (e) {
+      console.log(e, 'e')
+    }
+  },
   onSubmit() {
     // 判断是否登录
     const that = this
     debounce(function () {
-      if(!that.isLogin()) {
+      if (!that.isLogin()) {
+        return
+      }
+      if (!that.data.memberInfo.id) {
+        wx.showToast({
+          title: "请填写会员信息",
+          icon: 'none'
+        })
+        that.setData({
+          isShowMemberInfoTip: true
+        })
         return
       }
       let info = JSON.stringify({
         ...that.data.selected
       });
+      let instrumentsInfo = JSON.stringify({
+        ...that.data.selectedInstruments
+      })
+      let memberInfo = JSON.stringify({
+        ...that.data.memberInfo
+      })
       info = encodeURIComponent(info);
+      instrumentsInfo = encodeURIComponent(instrumentsInfo);
+      memberInfo = encodeURIComponent(memberInfo);
       wx.navigateTo({
-        url: `../orders/order-detail?orderInfo=${info}`,
+        url: `../orders/order-detail?orderInfo=${info}&instrumentsInfo=${instrumentsInfo}&memberInfo=${memberInfo}`,
         success: () => {
           that.setData({
+            memberInfo: {},
             popupShow: false
           })
         }
       })
     }, 300)()
   },
-  onPreivewBannerImg(e: { currentTarget: { dataset: any } }) {
-    wx.previewImage({
-      current: e.currentTarget.dataset.src,
-      urls: this.data.imgList,
-      success: () => {
-        this.setData({
-          isFromPreviewImage: true
-        })
-      }
-    })
-  },
   onPreivewGoodsImg(e: { currentTarget: { dataset: any } }) {
     wx.previewImage({
       current: e.currentTarget.dataset.src,
@@ -217,7 +228,7 @@ Page({
    * 生命周期函数--监听页面显示
    */
   onShow() {
-    if(!this.data.isFromPreviewImage) {
+    if (!this.data.isFromPreviewImage && !this.data.popupShow) {
       this.onInit()
     } else {
       this.setData({
@@ -236,7 +247,7 @@ Page({
   onScroll(e: { detail: any }) {
     // console.log(e, 'any')
     const scrollTop = e.detail.scrollTop || 0
-    if(scrollTop > 40) {
+    if (scrollTop > 40) {
       this.setData({
         isShowOperation: true
       })

+ 63 - 63
miniprogram/pages/index/index.wxml

@@ -1,64 +1,27 @@
 <!--index.wxml-->
 <scroll-view class="scrollarea" scroll-y="{{popupShow ? false : true}}" type="list" bindscroll="onScroll" enable-passive="true">
   <view class="container">
-    <!-- <view class="topShadow"></view>
-    <view class="slider-count">{{current + 1}}/{{imgList.length}}</view>
-    <swiper indicator-dots="{{false}}" autoplay="{{autoplay}}" interval="{{interval}}" duration="{{duration}}" bindchange="changeSwiper">
-      <swiper-item wx:for="{{imgList}}" wx:key="index">
-        <view class="swiper-item">
-          <image bind:tap="onPreivewBannerImg" data-src="{{ item }}" src="{{ item }}"></image>
-        </view>
-      </swiper-item>
-    </swiper>
 
-    <view class="shop-section">
-      <view class="showPrice">
-        <view class="left">
-          <view class="currentPrice">
-            <text class="stuff">¥</text>
-            <text class="priceZ">{{ selected.integerPart || 0 }}</text>
-            <text class="priceF">.{{ selected.decimalPart || '00' }}</text>
-          </view>
-          <view class="originPrice" wx:if="{{ selected.originalPrice > selected.salePrice }}">¥{{ selected.originalPrice || '0.00' }}</view>
-        </view>
-        <view class="right">
-          已售1w+
-        </view>
-      </view>
-
-      <view class="shopName">
-        {{ selected.name }}
-      </view>
-
-      <view class="goodsInfo">
-        <view class="goodsList">
-          <view wx:for="{{ list }}" wx:key="index" class="goodsItem {{ item.id == selected.id ? 'selected' : '' }} {{ item.stockNum <= 0 ? 'nosale' : '' }}" bind:tap="onSelectGoods" data-id="{{ item.id }}">
-          <image class="goods-cover" src="{{item.pic}}"></image>
-          <text class="name">{{ item.typeName }}</text><image class="iconSale" wx:if="{{ item.stockNum <= 0 }}" src="./images/nosale.png"></image>
-          </view>
-        </view>
-      </view>
-    </view> -->
-    
     <view class="goodsSection">
       <view class="goodsIntro">
-        <!-- <view class="title">
-          <view class="before"></view>
-          <view>商品详情</view>
-          <view class="after"></view>
-        </view> -->
         <view class="images">
           <block wx:for="{{goodsImgList}}" wx:key="index">
-            <image  mode="widthFix" bind:tap="onPreivewGoodsImg" data-src="{{item}}" src="{{item}}"></image>
+            <image mode="widthFix" bind:tap="onPreivewGoodsImg" data-src="{{item}}" src="{{item}}"></image>
           </block>
         </view>
       </view>
     </view>
-
-    <view class="bottom-section {{ isShowOperation ? '' : 'hide' }}">
-      <view class="btnSection">
-        <button bind:tap="onOrder" type="primary" disabled="{{ isOverSaled }}">我的订单</button>
-        <button bind:tap="onBuyShop" type="primary" disabled="{{ isOverSaled }}">立即购买</button>
+    <view class="bottom-sectionBox">
+      <view class="bottom-section">
+        <view class="orders" bind:tap="onOrder">
+          <image class="appImg" src="./images/order.png"></image>
+          <text>订单</text>
+        </view>
+        <button class="btnSection" bind:tap="onBuyShop">
+          立即购买
+        </button>
+        <!-- <button bind:tap="onOrder" type="primary" disabled="{{ isOverSaled }}">我的订单</button>
+        <button bind:tap="onBuyShop" type="primary" disabled="{{ isOverSaled }}">立即购买</button> -->
       </view>
     </view>
 
@@ -73,38 +36,75 @@
           </view>
           <view class="product-left">
             <view class="price-s">
+              <image wx:if="{{selected.originalPrice + (selectedInstruments.originalPrice || 0) - (selected.salePrice + (selectedInstruments.salePrice || 0)) > 0}}" class="priceImg" src="./images/yhj.png" />
               <view class="currentPrice">
-                <text class="stuff">¥</text>
-                <text class="priceZ">{{ selected.integerPart }}</text>
-                <text class="priceF">.{{ selected.decimalPart }}</text>
+                <text class="stuff">¥ </text>
+                <numberDisplay number="{{ selected.salePrice + (selectedInstruments.salePrice || 0) }}" />
+                <text wx:if="{{selected.originalPrice + (selectedInstruments.originalPrice || 0) - (selected.salePrice + (selectedInstruments.salePrice || 0)) > 0}}" class="originPrice">¥{{ my.formatValue(selected.originalPrice + (selectedInstruments.originalPrice || 0)) }}</text>
               </view>
-              <view class="originPrice">¥{{ selected.originalPrice }}</view>
             </view>
             <view class="current-s">
-              当前选中:<text>{{ selected.typeName }}</text>
+              当前选中:{{ selected.typeName + (selectedInstruments.name?"+"+selectedInstruments.name:"")}}
             </view>
+            <view wx:if="{{selected.originalPrice + (selectedInstruments.originalPrice || 0) - (selected.salePrice + (selectedInstruments.salePrice || 0)) > 0}}" class="discountCon">已优惠 ¥{{my.formatValue(selected.originalPrice + (selectedInstruments.originalPrice || 0) - (selected.salePrice + (selectedInstruments.salePrice || 0)))}}</view>
+          </view>
+        </view>
+        <view class="memberBox {{isShowMemberInfoTip?'showMemberInfoTip':''}}">
+          <view wx:if="{{ !memberInfo.id }}" class="memberCon" bind:tap="onMemberInfo">
+            <image class="memberImg" src="./images/member.png"></image>
+            <text class="info">请填写会员信息</text>
+            <image class="chevronImg" src="./images/chevron.png"></image>
+          </view>
+          <view wx:else class="memberCon" bind:tap="onMemberInfo">
+            <view class="memberInfoCon">
+              <view class="infoCon">
+                <image class="tip" src="./images/member.png" />
+                <text class="name">{{memberInfo.name}}</text>
+                <text class="phone">{{memberInfo.phone}}</text>
+              </view>
+              <view class="schoolInfoCon">
+                <text class="schoolInfo">学校信息</text><text class="schoolInfoDes">{{memberInfo.schoolInfo}}</text>
+              </view>
+            </view>
+            <image class="chevronImg" src="./images/chevron.png"></image>
           </view>
         </view>
-
         <view class="goodsInfo">
-          <view class="desc">规格类型({{ list.length }})</view>
+          <view class="desc"><text>*</text>会员卡类型</view>
           <view class="goodsList">
             <view wx:for="{{ list }}" wx:key="index" class="goodsItem {{ item.id == selected.id ? 'selected' : '' }} {{ item.stockNum <= 0 ? 'nosale' : '' }}" bind:tap="onSelectGoods" data-id="{{ item.id }}">
-              <image class="goods-cover" src="{{item.pic}}"></image>
-              <text class="name">{{ item.typeName }}</text><image class="iconSale" wx:if="{{ item.stockNum <= 0 }}" src="./images/nosale.png"></image>
+              <text class="name">{{ item.typeName }}</text>
+              <image class="iconSale" wx:if="{{ item.stockNum <= 0 }}" src="./images/nosale.png"></image>
+            </view>
+          </view>
+          <view wx:if="{{ instrumentsList.length > 0 }}" class="desc">乐器套装</view>
+          <view wx:if="{{ instrumentsList.length > 0 }}" class="goodsList">
+            <view wx:for="{{ instrumentsList }}" wx:key="index" class="goodsItem instrumentsGoodsItem {{ item.id == selectedInstruments.id ? 'selected' : '' }}" bind:tap="onSelectInstrumentsGoods" data-index="{{ index }}">
+              <text class="name">{{ item.name }}</text>
+              <view></view>
+              <text>{{ "¥" + my.formatValue(item.salePrice) }}</text>
             </view>
           </view>
         </view>
 
-        <view class="btnSections"><button type="primary" bind:tap="onSubmit">立即购买</button></view>
+        <view class="btnSections"><button type="primary" disabled="{{ isOverSaled }}" bind:tap="onSubmit">立即购买</button></view>
       </view>
     </view>
 
-    <view class="showMoreContainer {{ !isShowOperation ? '' : 'hide' }}">
+    <!-- <view class="showMoreContainer {{ !isShowOperation ? '' : 'hide' }}">
       <image src="./images/icon-up-scroll.png" class="iconUpScroll" />
-    </view>
+    </view> -->
   </view>
 
   <!-- 客服 -->
-  <service wx:if="{{serviceShow}}"></service>
-</scroll-view>
+  <!-- <service wx:if="{{serviceShow}}"></service> -->
+</scroll-view>
+
+<wxs module="my">
+  var formatValue = function (value) {
+    return parseFloat(value).toFixed(2);
+  }
+  module.exports = {
+    formatValue: formatValue
+  }
+</wxs>

+ 4 - 3
miniprogram/pages/login/login.less

@@ -25,7 +25,7 @@
     height: 160rpx;
   }
   .appname {
-    margin-top: 34rpx;
+    margin-top: 24rpx;
     width: 248rpx;
     height: 43rpx;
   }
@@ -43,6 +43,7 @@
     color: #FFFFFF;
     padding-top: 0;
     padding-bottom: 0;
+    border-radius: 78rpx;
     &[disabled][type=primary] {
       color: #fff;
       opacity: 0.7;
@@ -53,8 +54,8 @@
     width: 100%;
     text-align: center;
     font-size: 26rpx;
-    padding-top: 44rpx;
-    color: #777777;
+    padding-top: 80rpx;
+    color: #999999;
     line-height: 36rpx;
     .radioSection {
       height: 36rpx;

+ 10 - 0
miniprogram/pages/member/addMember.json

@@ -0,0 +1,10 @@
+{
+  "usingComponents": {
+    "navigation-bar": "/components/navigation-bar/navigation-bar",
+    "van-popup": "@vant/weapp/popup/index",
+    "van-area": "@vant/weapp/area/index",
+    "van-picker": "@vant/weapp/picker/index",
+    "van-search": "@vant/weapp/search/index",
+    "van-field": "@vant/weapp/field/index"
+  }
+}

+ 262 - 0
miniprogram/pages/member/addMember.less

@@ -0,0 +1,262 @@
+.addMember {
+  position: relative;
+  height: 100vh;
+  background: #F5F6F7;
+  display: flex;
+  flex-direction: column;
+
+  .weui-navigation-bar {
+    position: relative;
+    z-index: 2;
+  }
+
+  .appBg {
+    position: absolute;
+    left: 0;
+    top: 0;
+    width: 100%;
+    height: 592rpx;
+    background: url("https://oss.dayaedu.com/ktyq/1738997023805.png") no-repeat;
+    background-size: 100% 100%;
+    z-index: 1;
+  }
+
+  .addMemberCon {
+    position: relative;
+    z-index: 2;
+    flex-grow: 1;
+    padding-bottom: 200rpx;
+    overflow: hidden;
+
+    .labelCon {
+      padding-top: 22rpx;
+      padding-left: 40rpx;
+      box-sizing: border-box;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+
+      .labelLeft {
+        display: flex;
+        flex-direction: column;
+
+        image {
+          width: 244rpx;
+          height: 66rpx;
+        }
+
+        text {
+          margin-top: 24rpx;
+          font-weight: 400;
+          font-size: 26rpx;
+          color: rgba(0, 0, 0, 0.6);
+          line-height: 36rpx;
+        }
+      }
+
+      .labelRight {
+        flex-shrink: 0;
+        width: 134rpx;
+        height: 154rpx;
+      }
+    }
+
+    .fromBox {
+      margin: 24rpx 26rpx 0;
+      background: #FFFFFF;
+      border-radius: 20rpx;
+      padding: 0 24rpx;
+
+      &.firstFromBox {
+        margin-top: 44rpx;
+      }
+
+      .fromCon {
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        padding: 16rpx 0;
+        border-bottom: 2rpx solid #F2F2F2;
+
+        &:last-child {
+          border-bottom: none;
+        }
+
+        .fromTit {
+          font-weight: 600;
+          font-size: 28rpx;
+          color: #666666;
+          line-height: 40rpx;
+          position: relative;
+          margin-left: 20rpx;
+
+          &::after {
+            content: "*";
+            position: absolute;
+            top: 50%;
+            transform: translateY(-38%);
+            left: -20rpx;
+            font-weight: 600;
+            font-size: 28rpx;
+            color: #FD4502;
+            line-height: 1;
+          }
+        }
+
+        .fromIpt {
+          .van-field {
+            padding: 0;
+            --cell-line-height: 80rpx;
+
+            .van-cell__right-icon {
+              color: #cccccc;
+            }
+          }
+
+          .van-field__body {
+            .van-field__control {
+              color: #000000;
+              font-weight: 400;
+              font-size: 28rpx;
+            }
+          }
+        }
+
+        .genderIpt {
+          padding: 16rpx 0;
+          display: flex;
+
+          .gender {
+            font-weight: 600;
+            font-size: 28rpx;
+            color: #000000;
+            line-height: 48rpx;
+            width: 104rpx;
+            height: 48rpx;
+            text-align: center;
+            background: #F2F2F2;
+            border-radius: 8rpx;
+
+            &:first-child {
+              margin-right: 24rpx;
+            }
+
+            &.active {
+              background: #AAED51;
+            }
+          }
+        }
+      }
+    }
+
+    .botBox {
+      width: 100%;
+      height: 20rpx;
+    }
+  }
+
+  .submitCon {
+    z-index: 10;
+    position: fixed;
+    left: 0;
+    bottom: 0;
+    padding: 32rpx 40rpx 56rpx;
+    width: 100%;
+    box-sizing: border-box;
+    background: #FFFFFF;
+    box-shadow: 0rpx -2rpx 24rpx 0rpx rgba(0, 0, 0, 0.1);
+    border-radius: 32rpx 32rpx 0rpx 0rpx;
+
+    .subBtn {
+      width: 100%;
+      height: 88rpx;
+      font-weight: 600;
+      font-size: 32rpx;
+      color: #FFFFFF;
+      text-align: center;
+      line-height: 88rpx;
+      background: url("https://oss.dayaedu.com/ktyq/1738898417485.png") no-repeat;
+      background-size: 100% 100%;
+    }
+  }
+  // 弹窗
+  .toolbar-top{
+    display: flex;
+    justify-content: space-between;
+    height: 44px;
+    margin: 0 26rpx;
+    border-bottom: 2rpx solid #F2F2F2;
+    font-size: var(--picker-option-font-size);
+    .toolbar-cancel{
+      color: var(--picker-cancel-action-color);
+      line-height: 44px;
+      padding: 0 14rpx
+    }
+    .toolbar-confirm{
+      color: var(--picker-confirm-action-color);
+      line-height: 44px;
+      padding: 0 14rpx
+    }
+  }
+  .areaListOpen{
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    height: 56rpx;
+    margin: 20rpx 40rpx ;
+    overflow: hidden;
+    text{
+      margin-right: 20rpx;
+      font-weight: 400;
+      font-size: 32rpx;
+      color: #000000;
+      line-height: 44rpx;
+      white-space: nowrap;
+      overflow: hidden;
+      text-overflow: ellipsis;
+    }
+    image{
+      flex-shrink: 0;
+      width: 32rpx;
+      height: 32rpx;
+    }
+  }
+  .searchList {
+    .icon-search {
+      width: 32rpx;
+      height: 32rpx;
+      margin: auto 10rpx auto auto;
+    }
+  
+    .van-search {
+      margin: 26rpx !important;
+      padding: 0 !important;
+      height: 72rpx !important;
+      background: #F6F6F6 !important;
+      border-radius: 35rpx !important;
+      border: 1rpx solid #FFFFFF !important;
+    }
+  
+    .van-search__content {
+      border-top-left-radius: 35rpx !important;
+      border-bottom-left-radius: 35rpx !important;
+    }
+  
+    .van-cell {
+      font-size: 26rpx !important;
+    }
+  
+    .searchBtn {
+      width: 112rpx;
+      line-height: 54rpx !important;
+      padding: 0 !important;
+      text-align: center;
+      background-color: #000000;
+      font-weight: 500;
+      font-size: 28rpx;
+      color: #FFFFFF;
+      border-radius: 35rpx;
+      margin-right: 8rpx;
+    }
+  }
+}

+ 607 - 0
miniprogram/pages/member/addMember.ts

@@ -0,0 +1,607 @@
+import { api_schoolAreaDetail, api_schoolAreaList, api_sysAreaQueryAllProvince, api_userBeneficiarySave, api_userBeneficiaryUpdate, api_userBeneficiaryDetail } from "../../api/login";
+
+const classList: any = [];
+for (let i = 1; i <= 40; i++) {
+  classList.push({ text: i + '班', value: i });
+}
+
+const GRADE_ENUM = {
+  '1': '一年级',
+  '2': '二年级',
+  '3': '三年级',
+  '4': '四年级',
+  '5': '五年级',
+  '6': '六年级',
+  '7': '七年级',
+  '8': '八年级',
+  '9': '九年级'
+} as any;
+
+/** 获取年级 */
+const getGradeList = (gradeYear?: string, instrumentCode?: string) => {
+  let tempList: any = [];
+  const five = [
+    { text: '一年级', value: 1, instrumentCode },
+    { text: '二年级', value: 2, instrumentCode },
+    { text: '三年级', value: 3, instrumentCode },
+    { text: '四年级', value: 4, instrumentCode },
+    { text: '五年级', value: 5, instrumentCode }
+  ];
+  const one = [{ text: '六年级', value: 6, instrumentCode }];
+  const three = [
+    { text: '七年级', value: 7, instrumentCode },
+    { text: '八年级', value: 8, instrumentCode },
+    { text: '九年级', value: 9, instrumentCode }
+  ];
+  if (gradeYear === 'FIVE_YEAR_SYSTEM') {
+    tempList.push(...[...five]);
+  } else if (gradeYear === 'SIX_YEAR_SYSTEM') {
+    tempList.push(...[...five, ...one]);
+  } else if (gradeYear === 'THREE_YEAR_SYSTEM') {
+    tempList.push(...[...three]);
+  } else if (gradeYear === 'FORE_YEAR_SYSTEM') {
+    tempList.push(...[...one, ...three]);
+  } else {
+    tempList.push(...[...five, ...one, ...three]);
+  }
+  return tempList;
+};
+
+Page({
+  data: {
+    redirectUrl: "",
+    id: "",
+
+    phone: "",
+    name: "",
+    gender: "1",
+
+    showArea: false,
+    areaList: [] as any, // 省市区
+    provinceCode: null, // 地区
+    cityCode: null,
+    regionCode: null,
+    provinceName: "",
+    cityName: "",
+    regionName: "",
+
+    showSchool: false,
+    schoolLoading: false,
+    schoolAreaList: [] as any,
+    tempChangeSchoolAreaId: '', // 临时改变的学校id
+    schoolAreaId: '', //学校
+    schoolAreaName: '',
+    schoolAreaIndex: 0,
+    searchName: '',
+
+    showGrade: false, //年级
+    gradeList: [] as any,
+    gradeId: "",
+    gradeName: "",
+    gradeIndex: 0,
+
+    showClass: false, //班级
+    classList: [] as any,
+    classId: "",
+    className: "",
+    classIndex: 0,
+  },
+  async onLoad(options: any) {
+    const { redirectUrl, id } = options;
+    this.setData({
+      redirectUrl,
+      id
+    })
+    if (this.data.id) {
+      wx.showLoading({
+        title: '',
+      })
+      await this.getUserDetail()
+      wx.hideLoading()
+    } else {
+      this.getAreas()
+    }
+  },
+  async getUserDetail() {
+    try {
+      const { data } = await api_userBeneficiaryDetail(this.data.id)
+      if (data.code === 200) {
+        const params = data.data
+        this.setData({
+          phone: params.phone,
+          name: params.name,
+          gender: params.gender + "",
+          provinceCode: params.provinceCode,
+          cityCode: params.cityCode,
+          regionCode: params.regionCode,
+          provinceName: params.provinceName,
+          cityName: params.cityName,
+          regionName: params.regionName,
+          schoolAreaId: params.schoolAreaId,
+          schoolAreaName: params.schoolAreaName,
+          gradeId: params.currentGradeNum,
+          gradeName: GRADE_ENUM[params.currentGradeNum],
+          classId: params.currentClass,
+          className: params.currentClass + "班"
+        })
+        await this.getAreas()
+        await this.getSchools()
+        await this.getSchoolAreaDetail()
+        // 学校index
+        const schoolAreaIndex = this.data.schoolAreaList.findIndex(((item: any) => {
+          return item.value === this.data.schoolAreaId
+        }))
+        // 筛选出年级 赋值班级
+        const gradeIndex = (this.data.gradeList[0]?.values || []).findIndex((item: any) => {
+          return item.value === params.currentGradeNum
+        })
+        const gradeData = this.data.gradeList[0]?.values[gradeIndex]
+        const classListData = gradeData?.classList || classList
+        // 班级index
+        const classIndex = classListData.findIndex(((item: any) => {
+          return item.value === this.data.classId
+        }))
+        this.setData({
+          classList: [{
+            values: classListData
+          }]
+        }, () => {
+          // 不知道为啥 直接写在上面 gradeIndex 不能回显
+          this.setData({
+            schoolAreaIndex,
+            gradeIndex,
+            classIndex
+          })
+        })
+      }
+    } catch (e: any) {
+
+    }
+  },
+  /** 选择男女 */
+  onCheckGender(e: any) {
+    const { dataset } = e.target
+    this.setData({
+      gender: dataset.gender
+    })
+  },
+  /** 显示选择地区 */
+  onShowAreaList() {
+    this.setData({
+      showArea: true
+    })
+  },
+  /** 关闭选择地区 */
+  onCloseAreaList() {
+    this.setData({
+      showArea: false
+    })
+  },
+  /** 确定选择地区 */
+  submitArea(e: any) {
+    const selectedOptions: any = e.detail.values
+    if (!selectedOptions || !selectedOptions[selectedOptions.length - 1]) {
+      wx.showToast({
+        title: '未选中值',
+        icon: 'none'
+      })
+      return
+    }
+    this.setData({
+      provinceCode: selectedOptions[0].code,
+      cityCode: selectedOptions[1].code,
+      regionCode: selectedOptions[2].code,
+      provinceName: selectedOptions[0].name,
+      cityName: selectedOptions[1].name,
+      regionName: selectedOptions[2].name,
+      showArea: false,
+
+      searchName: "",
+      tempChangeSchoolAreaId: '',
+      schoolAreaId: '',
+      schoolAreaName: '',
+
+      gradeId: "",
+      gradeName: "",
+
+      classId: "",
+      className: ""
+    }, () => {
+      this.getSchools()
+    })
+  },
+  /** 获取省市区 */
+  async getAreas() {
+    try {
+      const { data } = await api_sysAreaQueryAllProvince({})
+      this.setData({
+        areaList: this.formateArea(data.data)
+      })
+    } catch {
+      // 
+    }
+  },
+  formateArea(area: any[]) {
+    const province_list: { [_: string]: string } = {};
+    const city_list: { [_: string]: string } = {};
+    const county_list: { [_: string]: string } = {};
+    area.forEach((item: any) => {
+      province_list[item.code] = item.name;
+    });
+    area.forEach((item: any) => {
+      item.areas && item.areas.forEach((city: any) => {
+        city_list[city.code] = city.name;
+      });
+    });
+    area.forEach((item: any) => {
+      item.areas && item.areas.forEach((city: any) => {
+        city.areas && city.areas.forEach((county: any) => {
+          county_list[county.code] = county.name;
+        });
+      });
+    });
+    return {
+      province_list,
+      city_list,
+      county_list
+    };
+  },
+  /** 选择学校 */
+  onSelectSchool() {
+    if (!this.data.provinceName) {
+      wx.showToast({
+        title: '请先选择学校地区',
+        icon: 'none'
+      })
+      return
+    }
+    this.setData({
+      showSchool: true
+    })
+  },
+  /** 关闭选择学校 */
+  onCloseSchool() {
+    this.setData({
+      showSchool: false
+    })
+  },
+  onChangeSchool(e: any) {
+    const { value } = e.detail.value
+    this.setData({
+      tempChangeSchoolAreaId: value
+    })
+  },
+  onSearchChange(e: any) {
+    this.setData({
+      searchName: e.detail
+    })
+  },
+  onSearch() {
+    this.getSchools(this.data.searchName);
+  },
+  /** 确定选择学校 */
+  onSubmitSchool() {
+    if (!this.data.tempChangeSchoolAreaId) {
+      wx.showToast({
+        title: '未选中值',
+        icon: 'none'
+      })
+      return
+    }
+    const detail = this.data.schoolAreaList.find((item: any) => item.value === this.data.tempChangeSchoolAreaId)
+    this.setData({
+      schoolAreaName: detail.text,
+      schoolAreaId: detail.value,
+      showSchool: false,
+
+      gradeId: "",
+      gradeName: "",
+
+      classId: "",
+      className: ""
+    }, () => {
+      this.getSchoolAreaDetail()
+    })
+  },
+  /** 获取学校列表 */
+  async getSchools(name?: string) {
+    this.setData({
+      schoolLoading: true
+    })
+    try {
+      // 判断是否有地区信息
+      if (!this.data.provinceCode || !this.data.cityCode || !this.data.regionCode) {
+        return
+      }
+      const { data } = await api_schoolAreaList({
+        name,
+        testFlag: true,
+        provinceCode: this.data.provinceCode,
+        cityCode: this.data.cityCode,
+        regionCode: this.data.regionCode
+      })
+      const result = data.data || []
+      const tempList: any[] = []
+      result.forEach((item: any) => {
+        tempList.push({
+          text: item.name,
+          value: item.id
+        })
+      })
+
+      let tempSchoolId = ''
+      if (tempList.length > 0) {
+        const first = tempList[0]
+        tempSchoolId = first.value || ''
+      }
+
+      this.setData({
+        schoolAreaList: tempList,
+        tempChangeSchoolAreaId: tempSchoolId
+      })
+    } catch {
+      // 
+    }
+    this.setData({
+      schoolLoading: false
+    })
+  },
+  /** 获取学校详情 */
+  async getSchoolAreaDetail() {
+    const { data } = await api_schoolAreaDetail({ id: this.data.schoolAreaId })
+    const result = data.data || {}
+    if (result.school) {
+      const schoolInfo = result.school || {};
+      const schoolInstrumentList = schoolInfo.schoolInstrumentList || [];
+      if (schoolInfo.instrumentSetType === 'SCHOOL') {
+        const gradeClassList = [{
+          values: getGradeList(schoolInfo.gradeYear),
+        }]
+        this.setData({
+          gradeList: gradeClassList
+        })
+      } else if (schoolInfo.instrumentSetType === 'GRADE') {
+        const gradeList: any = []
+        schoolInstrumentList.forEach((item: any) => {
+          gradeList.push({
+            text: GRADE_ENUM[item.gradeNum],
+            value: item.gradeNum,
+            instrumentId: item.instrumentId
+          })
+        });
+        gradeList.sort((a: any, b: any) => a.value - b.value);
+        const gradeClassList = [{
+          values: gradeList
+        }]
+        this.setData({
+          gradeList: gradeClassList,
+        })
+      } else if (schoolInfo.instrumentSetType === 'CLASS') {
+        //   // 班级
+        const tempGradeList: any[] = [];
+        schoolInstrumentList.forEach((item: any) => {
+          if (!tempGradeList.includes(item.gradeNum)) {
+            tempGradeList.push(item.gradeNum);
+          }
+        });
+
+        const lastGradeList: any[] = [];
+        tempGradeList.forEach((temp: any) => {
+          const list = {
+            text: GRADE_ENUM[temp],
+            value: temp,
+            instrumentId: '',
+            instrumentCode: '',
+            instrumentName: '',
+            classList: [] as any
+          };
+          schoolInstrumentList.forEach((item: any) => {
+            if (temp === item.gradeNum) {
+              list.instrumentId = item.instrumentId;
+              list.instrumentCode = item.instrumentCode;
+              list.instrumentName = item.instrumentName;
+              list.classList.push({
+                text: item.classNum + '班',
+                value: item.classNum,
+                instrumentCode: item.instrumentCode
+              });
+            }
+          });
+          // 排序班级
+          list.classList.sort((a: any, b: any) => a.value - b.value);
+          lastGradeList.push(list);
+        });
+        lastGradeList.sort((a: any, b: any) => a.value - b.value);
+        console.log(lastGradeList, 'lastGradeList')
+        this.setData({
+          gradeList: [{
+            values: lastGradeList
+          }]
+        })
+      } else {
+        const gradeClassList = [{
+          values: getGradeList(),
+        }]
+        this.setData({
+          gradeList: gradeClassList
+        })
+      }
+    } else {
+      const gradeClassList = [{
+        values: getGradeList(),
+      }]
+      this.setData({
+        gradeList: gradeClassList
+      })
+    }
+  },
+  /** 选择年级 */
+  onSelectGrade() {
+    if (!this.data.schoolAreaId) {
+      wx.showToast({
+        title: '请先选择学校',
+        icon: 'none'
+      })
+      return
+    }
+    this.setData({
+      showGrade: true
+    })
+  },
+  onCloseGrade() {
+    this.setData({
+      showGrade: false
+    })
+  },
+  /** 确认选择年级 */
+  onSubmitGrade(e: any) {
+    const selectedOptions: any = e.detail.value
+    if (!selectedOptions || !selectedOptions[selectedOptions.length - 1]) {
+      wx.showToast({
+        title: '未选中值',
+        icon: 'none'
+      })
+      return
+    }
+    this.setData({
+      gradeId: selectedOptions[0].value,
+      gradeName: selectedOptions[0].text,
+      showGrade: false,
+
+      classId: "",
+      className: ""
+    })
+    this.setData({
+      classList: [{
+        values: selectedOptions[0].classList || classList
+      }]
+    })
+  },
+  /** 选择班级 */
+  onSelectClass() {
+    if (!this.data.gradeId) {
+      wx.showToast({
+        title: '请先选择年级',
+        icon: 'none'
+      })
+      return
+    }
+    this.setData({
+      showClass: true
+    })
+  },
+  onCloseClass() {
+    this.setData({
+      showClass: false
+    })
+  },
+  /** 确认选择班级 */
+  onSubmitClass(e: any) {
+    const selectedOptions: any = e.detail.value
+    if (!selectedOptions || !selectedOptions[selectedOptions.length - 1]) {
+      wx.showToast({
+        title: '未选中值',
+        icon: 'none'
+      })
+      return
+    }
+    this.setData({
+      classId: selectedOptions[0].value,
+      className: selectedOptions[0].text,
+      showClass: false
+    })
+  },
+  /** 最终提交 */
+  async onSubmit() {
+    try {
+      const params = this.data
+      if (!params.phone || !/^1[3456789]\d{9}$/.test(params.phone)) {
+        wx.showToast({
+          title: '请输入正确的手机号',
+          icon: "none"
+        })
+        return
+      }
+
+      if (!params.name) {
+        wx.showToast({
+          title: '请输入学生姓名',
+          icon: "none"
+        })
+        return
+      }
+
+      if (!params.provinceCode || !params.cityCode || !params.regionCode) {
+        wx.showToast({
+          title: '请选择学校地区',
+          icon: "none"
+        })
+        return
+      }
+
+      if (!params.schoolAreaId) {
+        wx.showToast({
+          title: '请选择学校',
+          icon: "none"
+        })
+        return
+      }
+
+      if (!params.gradeId) {
+        wx.showToast({
+          title: '请选择年级',
+          icon: "none"
+        })
+        return
+      }
+
+      if (!params.classId) {
+        wx.showToast({
+          title: '请选择班级',
+          icon: "none"
+        })
+        return
+      }
+
+      const pages = getCurrentPages();
+      const prevPage = pages[pages.length - 2]; // 获取上一个页面实例
+      // 编辑
+      if (params.id) {
+        await api_userBeneficiaryUpdate({
+          id: params.id,
+          phone: params.phone,
+          name: params.name,
+          gender: params.gender,
+          currentGradeNum: params.gradeId,
+          currentClass: params.classId,
+          schoolAreaId: params.schoolAreaId,
+          defaultStatus: false
+        })
+        wx.showToast({
+          title: '保存成功',
+          icon: 'none'
+        })
+      } else {
+        const { data } = await api_userBeneficiarySave({
+          "phone": params.phone,
+          "name": params.name,
+          "gender": params.gender,
+          "currentGradeNum": params.gradeId,
+          "currentClass": params.classId,
+          "schoolAreaId": params.schoolAreaId,
+          defaultStatus: false
+        })
+        if(this.data.redirectUrl === "index"){
+          prevPage.setData({ memberInfo: { id: data.data.id, name: params.name, phone: params.phone, schoolInfo: params.provinceName + params.cityName + params.regionName + params.schoolAreaName + params.gradeName + params.className } });
+        }
+        wx.showToast({
+          title: '保存成功',
+          icon: 'none'
+        })
+      }
+      wx.navigateBack()
+    } catch {
+      // 
+    }
+  },
+})

+ 97 - 0
miniprogram/pages/member/addMember.wxml

@@ -0,0 +1,97 @@
+<view class="addMember">
+  <navigation-bar title=""></navigation-bar>
+  <view class="appBg"></view>
+  <scroll-view scroll-y class="addMemberCon">
+    <view class="labelCon">
+      <view class="labelLeft">
+        <image src="./images/label1.png"></image>
+        <text>为了提供更好的服务,请您耐心填写以下内容</text>
+      </view>
+      <image class="labelRight" src="./images/label2.png"></image>
+    </view>
+    <view class="fromBox firstFromBox">
+      <view class="fromCon">
+        <text class="fromTit">联系电话</text>
+        <view class="fromIpt">
+          <van-field model:value="{{ phone }}" input-align="right" type="{{ 'number' }}" placeholder="请输入联系电话" border="{{ false }}" />
+        </view>
+      </view>
+      <view class="fromCon">
+        <text class="fromTit">学生姓名</text>
+        <view class="fromIpt">
+          <van-field model:value="{{ name }}" input-align="right" placeholder="请输入学生姓名" border="{{ false }}" />
+        </view>
+      </view>
+      <view class="fromCon">
+        <text class="fromTit">学生性别</text>
+        <view class="fromIpt genderIpt">
+          <view class="gender {{gender==='1'?'active':''}}" bind:tap="onCheckGender" data-gender="1">男</view>
+          <view class="gender {{gender==='0'?'active':''}}" bind:tap="onCheckGender" data-gender="0">女</view>
+        </view>
+      </view>
+    </view>
+    <view class="fromBox">
+      <view class="fromCon">
+        <text class="fromTit">学校地区</text>
+        <view class="fromIpt">
+          <van-field placeholder="请选择学校地区" value="{{  provinceName  + cityName  + regionName}}" input-align="right" bind:tap="onShowAreaList" border="{{ false }}" is-link readonly />
+        </view>
+      </view>
+      <view class="fromCon">
+        <text class="fromTit">所在学校</text>
+        <view class="fromIpt">
+          <van-field placeholder="请选择学校" value="{{ schoolAreaName }}" input-align="right" bind:tap="onSelectSchool" border="{{ false }}" is-link readonly />
+        </view>
+      </view>
+      <view class="fromCon">
+        <text class="fromTit">所在年级</text>
+        <view class="fromIpt">
+          <van-field placeholder="请选择年级" value="{{ gradeName }}" input-align="right" bind:tap="onSelectGrade" border="{{ false }}" is-link readonly />
+        </view>
+      </view>
+      <view class="fromCon">
+        <text class="fromTit">所在班级</text>
+        <view class="fromIpt">
+          <van-field placeholder="请选择班级" value="{{ className }}" input-align="right" bind:tap="onSelectClass" border="{{ false }}" is-link readonly />
+        </view>
+      </view>
+    </view>
+    <view class="botBox"></view>
+  </scroll-view>
+  <view class="submitCon">
+    <view class="subBtn" bind:tap="onSubmit">保存</view>
+  </view>
+  <!-- 地区 -->
+  <van-popup round="{{true}}" lock-scroll="{{true}}" z-index="{{103}}" show="{{showArea}}" position="bottom" safe-area-inset-bottom="{{false}}" bind:close="onCloseAreaList">
+    <van-area areaList="{{areaList}}" visible-item-count="6" item-height="46" value="{{ regionCode }}" bind:cancel="onCloseAreaList" bind:confirm="submitArea" />
+  </van-popup>
+  <!-- 学校 -->
+  <van-popup round="{{true}}" lock-scroll="{{true}}" z-index="{{102}}" show="{{showSchool}}" position="bottom" safe-area-inset-bottom="{{false}}" bind:close="onCloseSchool">
+    <view class="toolbar-top">
+      <view class="toolbar-cancel" bind:tap="onCloseSchool">取消</view>
+      <view class="toolbar-confirm" bind:tap="onSubmitSchool">确认</view>
+    </view>
+    <view class="areaListOpen" bind:tap="onShowAreaList">
+      <text>{{ provinceName  + " " + cityName + " " + regionName}}</text>
+      <image src="./images/chevron-down.png" />
+    </view>
+    <view class="searchList">
+      <van-search use-left-icon-slot use-action-slot show-action placeholder="请输入学校名称关键字" value="{{ searchName }}" bind:search="onSearch" bind:change="onSearchChange" bind:clear="onSearch">
+        <image slot="left-icon" src="./images/icon-search.png" class="icon-search" />
+        <view slot="action" class="searchBtn" bind:tap="onSearch">搜索</view>
+      </van-search>
+    </view>
+    <van-picker loading="{{ schoolLoading }}" columns="{{ schoolAreaList }}" bind:change="onChangeSchool" visible-item-count="6" default-index="{{ schoolAreaIndex }}">
+    </van-picker>
+  </van-popup>
+  <!-- 年级 -->
+  <van-popup round="{{true}}" lock-scroll="{{true}}" z-index="{{102}}" show="{{showGrade}}" position="bottom" safe-area-inset-bottom="{{false}}" bind:close="onCloseGrade">
+    <van-picker columns="{{ gradeList }}" visible-item-count="6" show-toolbar bind:cancel="onCloseGrade" bind:confirm="onSubmitGrade" default-index="{{ gradeIndex }}">
+    </van-picker>
+  </van-popup>
+  <!-- 班级 -->
+  <van-popup round="{{true}}" lock-scroll="{{true}}" z-index="{{102}}" show="{{showClass}}" position="bottom" safe-area-inset-bottom="{{false}}" bind:close="onCloseClass">
+    <van-picker columns="{{ classList }}" visible-item-count="6" show-toolbar bind:cancel="onCloseClass" bind:confirm="onSubmitClass" default-index="{{ classIndex }}">
+    </van-picker>
+  </van-popup>
+</view>

BIN
miniprogram/pages/member/images/chevron-down.png


BIN
miniprogram/pages/member/images/icon-search.png


BIN
miniprogram/pages/member/images/label1.png


BIN
miniprogram/pages/member/images/label2.png


BIN
miniprogram/pages/member/images/user.png


+ 5 - 0
miniprogram/pages/member/memberList.json

@@ -0,0 +1,5 @@
+{
+  "usingComponents": {
+    "navigation-bar": "/components/navigation-bar/navigation-bar"
+  }
+}

+ 223 - 0
miniprogram/pages/member/memberList.less

@@ -0,0 +1,223 @@
+.memberList {
+  position: relative;
+  height: 100vh;
+  background: #F5F6F7;
+  display: flex;
+  flex-direction: column;
+
+  .weui-navigation-bar {
+    position: relative;
+    z-index: 2;
+  }
+
+  .appBg {
+    position: absolute;
+    left: 0;
+    top: 0;
+    width: 100%;
+    height: 592rpx;
+    background: url("https://oss.dayaedu.com/ktyq/1738997023805.png") no-repeat;
+    background-size: 100% 100%;
+    z-index: 1;
+  }
+
+  .memberListCon {
+    position: relative;
+    z-index: 2;
+    flex-grow: 1;
+    padding-bottom: 200rpx;
+    padding-top: 36rpx;
+    overflow: hidden;
+
+    .memberInfo {
+      margin: 0 26rpx;
+      background: #FFFFFF;
+      border-radius: 20rpx;
+      padding: 24rpx 24rpx 32rpx;
+      margin-bottom: 24rpx;
+      border: 3rpx solid transparent;
+
+      &.active {
+        border-color: #0AAF20;
+      }
+
+      &:last-child {
+        margin-bottom: 0;
+      }
+
+      .infoCon {
+        display: flex;
+        align-items: center;
+        font-weight: 600;
+        font-size: 28rpx;
+        color: #131415;
+        line-height: 40rpx;
+
+        .tip {
+          width: 44rpx;
+          height: 44rpx;
+        }
+
+        .name,
+        .phone {
+          margin-left: 16rpx;
+        }
+      }
+
+      .schoolInfoCon {
+        margin-top: 20rpx;
+
+        .schoolInfo {
+          margin-right: 8rpx;
+          border-radius: 4rpx;
+          border: 1rpx solid rgba(15, 179, 96, 0.5);
+          padding: 2rpx 6rpx;
+          font-weight: 400;
+          font-size: 20rpx;
+          color: #0FB360;
+          line-height: 30rpx;
+        }
+
+        .schoolInfoDes {
+          font-weight: 400;
+          font-size: 24rpx;
+          color: #777777;
+          line-height: 32rpx;
+        }
+      }
+
+      .operateCon {
+        margin-top: 32rpx;
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+
+        .radio {
+          display: flex;
+          align-items: center;
+
+          image {
+            width: 32rpx;
+            height: 32rpx;
+          }
+
+          text {
+            margin-left: 12rpx;
+            font-weight: 400;
+            font-size: 24rpx;
+            color: #777777;
+            line-height: 32rpx;
+          }
+        }
+
+        .operate {
+          display: flex;
+          align-items: center;
+
+          view {
+            background: #F2F2F2;
+            border-radius: 24rpx;
+            padding: 6rpx 24rpx;
+            font-weight: 400;
+            font-size: 24rpx;
+            color: #333333;
+            line-height: 34rpx;
+
+            &:first-child {
+              margin-right: 24rpx;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  .submitCon {
+    z-index: 10;
+    position: fixed;
+    left: 0;
+    bottom: 0;
+    padding: 32rpx 40rpx 56rpx;
+    width: 100%;
+    box-sizing: border-box;
+    background: #FFFFFF;
+    box-shadow: 0rpx -2rpx 24rpx 0rpx rgba(0, 0, 0, 0.1);
+    border-radius: 32rpx 32rpx 0rpx 0rpx;
+
+    .subBtn {
+      width: 100%;
+      height: 88rpx;
+      font-weight: 600;
+      font-size: 32rpx;
+      color: #FFFFFF;
+      line-height: 88rpx;
+      background: url("https://oss.dayaedu.com/ktyq/1738898417485.png") no-repeat;
+      background-size: 100% 100%;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+
+      image {
+        width: 40rpx;
+        height: 40rpx;
+        margin-right: 12rpx;
+      }
+    }
+  }
+
+  .popup-section {
+
+    .popup-mask {
+      position: fixed;
+      top: 0;
+      left: 0;
+      right: 0;
+      bottom: 0;
+      background-color: rgba(0, 0, 0, 0.6);
+      z-index: 99999;
+    }
+
+    .popup-container {
+      position: fixed;
+      left: 0;
+      right: 0;
+      top: 50%;
+      transform: translateY(-50%);
+      z-index: 999999;
+      margin: 0 100rpx;
+      padding: 50rpx 0 40rpx 0;
+      background: #FFFFFF;
+      border-radius: 32rpx;
+
+      .tit {
+        font-weight: 600;
+        font-size: 32rpx;
+        color: #000000;
+        line-height: 44rpx;
+        text-align: center;
+      }
+
+      .btnCon {
+        display: flex;
+        justify-content: center;
+        margin-top: 50rpx;
+
+        view {
+          font-weight: 400;
+          font-size: 28rpx;
+          color: #000000;
+          line-height: 36rpx;
+          padding: 16rpx 72rpx;
+          border-radius: 36rpx;
+          border: 2rpx solid #DCDCDC;
+
+          &:last-child {
+            margin-left: 32rpx;
+            background: #000000;
+            color: #fff;
+          }
+        }
+      }
+    }
+  }
+}

+ 105 - 0
miniprogram/pages/member/memberList.ts

@@ -0,0 +1,105 @@
+import { api_getUserBeneficiaryPage, api_userBeneficiaryRemove } from "../../api/login";
+
+const GRADE_ENUM = {
+  '1': '一年级',
+  '2': '二年级',
+  '3': '三年级',
+  '4': '四年级',
+  '5': '五年级',
+  '6': '六年级',
+  '7': '七年级',
+  '8': '八年级',
+  '9': '九年级'
+} as any
+
+Page({
+  data: {
+    id: "", //当前选中的id
+    popupShow: false,
+    selectedId: "",
+    memberList: []
+  },
+  onShow() {
+    this.getPageList()
+  },
+  onLoad(options: any) {
+    const { id } = options;
+    this.setData({
+      id
+    })
+  },
+  async getPageList() {
+    try {
+      const resData = await api_getUserBeneficiaryPage()
+      const pageRows = resData?.data?.data?.rows || []
+      this.setData({
+        memberList: pageRows
+      })
+      // 编辑 完了之后刷新上一页的数据
+      const item = this.data.memberList.find(((item: any) => {
+        return item.id === this.data.id
+      }))
+      this.setPagesData(item)
+    } catch (e) {
+      console.log(e, 'e')
+    }
+  },
+  onDialogClose() {
+    this.setData({
+      popupShow: false
+    })
+  },
+  async onDialogOk() {
+    try {
+      const { data } = await api_userBeneficiaryRemove(this.data.selectedId)
+      if (data.code === 200) {
+        this.setData({
+          popupShow: false
+        })
+        await this.getPageList()
+        // 当删的是当前选中的
+        if (this.data.selectedId === this.data.id) {
+          let item: any
+          if (this.data.memberList.length) {
+            item = this.data.memberList[0]
+            this.setData({
+              id: item.id
+            })
+          }
+          this.setPagesData(item)
+        }
+      }
+    } catch (e: any) { }
+  },
+  onDel(e: any) {
+    const { dataset } = e.currentTarget
+    this.setData({
+      selectedId: dataset.id
+    })
+    this.setData({
+      popupShow: true
+    })
+  },
+  onEdit(e: any) {
+    const { dataset } = e.currentTarget
+    wx.navigateTo({
+      url: `/pages/member/addMember?id=${dataset.id}`
+    });
+  },
+  onAdd() {
+    wx.navigateTo({
+      url: `/pages/member/addMember`
+    });
+  },
+  onSelect(e: any) {
+    const { dataset } = e.currentTarget
+    const item = dataset.item;
+    this.setPagesData(item)
+    wx.navigateBack()
+  },
+  setPagesData(item: any) {
+    const pages = getCurrentPages();
+    const prevPage = pages[pages.length - 2]; // 获取上一个页面实例
+    prevPage.setData({ memberInfo: item ? { id: item.id, name: item.name, phone: item.phone, schoolInfo: item.provinceName + item.cityName + item.regionName + item.schoolAreaName + GRADE_ENUM[item.currentGradeNum] + item.currentClass + "班" } : {} });
+  }
+})

+ 62 - 0
miniprogram/pages/member/memberList.wxml

@@ -0,0 +1,62 @@
+<view class="memberList">
+  <navigation-bar title="选择会员享用人"></navigation-bar>
+  <view class="appBg"></view>
+  <scroll-view scroll-y class="memberListCon">
+    <view wx:for="{{ memberList }}" wx:key="index" bind:tap="onSelect" data-item="{{ item }}" class="memberInfo {{ item.id === id?'active':'' }}">
+      <view class="infoCon">
+        <image class="tip" src="../index/images/member.png" />
+        <text class="name">{{item.name}}</text>
+        <text class="phone">{{item.phone}}</text>
+      </view>
+      <view class="schoolInfoCon">
+        <text class="schoolInfo">学校信息</text><text class="schoolInfoDes">{{
+          item.provinceName + item.cityName + item.regionName + item.schoolAreaName  + my.GRADE_ENUM[item.currentGradeNum] + item.currentClass + "班"
+        }}
+        </text>
+      </view>
+      <view class="operateCon">
+        <view class="radio">
+          <image wx:if="{{item.id === id}}" src="../login/images/radio-active.png"></image>
+          <image wx:else src="../login/images/radio-default.png"></image>
+          <text>{{ item.id === id ? "当前选中" : "未选中"}}</text>
+        </view>
+        <view class="operate">
+          <view catch:tap="onDel" data-id="{{ item.id }}">删除</view>
+          <view catch:tap="onEdit" data-id="{{ item.id }}">编辑</view>
+        </view>
+      </view>
+    </view>
+  </scroll-view>
+  <view class="submitCon">
+    <view class="subBtn" bind:tap="onAdd">
+      <image src="./images/user.png" />
+      新增会员信息
+    </view>
+  </view>
+  <view class="popup-section" wx:if="{{popupShow}}">
+    <view class="popup-mask" bind:tap="onDialogClose"></view>
+    <view class="popup-container">
+      <view class="tit">请确认是否删除该会员信息</view>
+      <view class="btnCon">
+        <view bind:tap="onDialogClose">取消</view>
+        <view bind:tap="onDialogOk">确认</view>
+      </view>
+    </view>
+  </view>
+</view>
+<wxs module="my">
+  var GRADE_ENUM = {
+    '1': '一年级',
+    '2': '二年级',
+    '3': '三年级',
+    '4': '四年级',
+    '5': '五年级',
+    '6': '六年级',
+    '7': '七年级',
+    '8': '八年级',
+    '9': '九年级'
+  }
+  module.exports = {
+    GRADE_ENUM: GRADE_ENUM
+  }
+</wxs>

BIN
miniprogram/pages/orders/images/discount.png


BIN
miniprogram/pages/orders/images/error.png


BIN
miniprogram/pages/orders/images/ing.png


BIN
miniprogram/pages/orders/images/member.png


BIN
miniprogram/pages/orders/images/success.png


+ 3 - 1
miniprogram/pages/orders/order-detail.json

@@ -1,6 +1,8 @@
 {
   "usingComponents": {
     "navigation-bar": "/components/navigation-bar/navigation-bar",
-    "service": "/components/service/service"
+    "service": "/components/service/service",
+    "addAddress": "../address/addAddress",
+    "numberDisplay": "/components/numberDisplay/numberDisplay"
   }
 }

+ 305 - 52
miniprogram/pages/orders/order-detail.less

@@ -1,10 +1,11 @@
 /* pages/orders/order-detail.wxss */
-page {
+.container {
   position: relative;
   height: 100vh;
   display: flex;
   flex-direction: column;
-  background: #F4F4F4;
+  background: #F5F6F7;
+
   // background: linear-gradient(to bottom, #FB660A, #F5F6F7) #f4f4f4;
   // background-size: 750rpx;
   &::before {
@@ -12,13 +13,17 @@ page {
     position: absolute;
     top: 0;
     width: 100%;
-    height: 750rpx; 
-    background: linear-gradient(to bottom, #FB660A, #F5F6F7) #f4f4f4;
-    background-size: 750rpx;
+    width: 100%;
+    height: 592rpx;
+    background: url("https://oss.dayaedu.com/ktyq/1738997023805.png") no-repeat;
+    background-size: 100% 100%;
   }
 
-  .weui-navigation-bar__btn_goback {
-    background-color: #fff;
+  .record-list {
+    padding-top: 36rpx;
+    flex-grow: 1;
+    padding-bottom: 200rpx;
+    overflow: hidden;
   }
 }
 
@@ -27,14 +32,17 @@ page {
   // background-color: #FFFFFF;
   border-radius: 20rpx;
   padding: 24rpx 32rpx;
+
   .status {
     display: flex;
     padding-bottom: 24rpx;
+
     image {
       width: 48rpx;
       height: 48rpx;
       margin-right: 16rpx;
     }
+
     text {
       font-weight: 600;
       font-size: 48rpx;
@@ -42,6 +50,7 @@ page {
       line-height: 48rpx;
     }
   }
+
   .tips {
     font-size: 28rpx;
     color: #FFFFFF;
@@ -49,19 +58,144 @@ page {
   }
 }
 
+.memberBox {
+  margin: 0 20rpx;
+  background: #ffffff;
+  border-radius: 20rpx;
+  border: 3rpx solid transparent;
+
+  &.showMemberInfoTip {
+    border-color: #FD4502;
+  }
+
+  .memberCon {
+    padding: 24rpx;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+
+    .memberImg {
+      width: 44rpx;
+      height: 44rpx;
+    }
+
+    .info {
+      flex-grow: 1;
+      margin-left: 16rpx;
+      font-weight: 600;
+      font-size: 28rpx;
+      color: #131415;
+      line-height: 40rpx;
+    }
+
+    .chevronImg {
+      flex-shrink: 0;
+      width: 32rpx;
+      height: 32rpx;
+    }
+
+    .memberInfoCon {
+      overflow: hidden;
+    }
+
+    .infoCon {
+      display: flex;
+      align-items: center;
+      font-weight: 600;
+      font-size: 28rpx;
+      color: #131415;
+      line-height: 40rpx;
+
+      .tip {
+        width: 44rpx;
+        height: 44rpx;
+      }
+
+      .name,
+      .phone {
+        margin-left: 16rpx;
+      }
+    }
+
+    .schoolInfoCon {
+      margin-top: 20rpx;
+      display: flex;
+      align-items: center;
+
+      .schoolInfo {
+        margin-right: 8rpx;
+        border-radius: 4rpx;
+        border: 1rpx solid rgba(243, 131, 9, 0.5);
+        padding: 2rpx 6rpx;
+        font-weight: 400;
+        font-size: 20rpx;
+        color: #F38309;
+        line-height: 30rpx;
+        flex-shrink: 0;
+      }
+
+      .schoolInfoDes {
+        margin-right: 10rpx;
+        font-weight: 400;
+        font-size: 24rpx;
+        color: #777777;
+        line-height: 32rpx;
+        white-space: nowrap;
+        overflow: hidden;
+        text-overflow: ellipsis;
+      }
+    }
+  }
+}
+
 .order-content {
-  margin: 36rpx 26rpx 0;
+  margin: 20rpx 26rpx 0;
   border-radius: 20rpx;
-  padding: 28rpx 24rpx;
+  padding: 24rpx 24rpx 32rpx;
   display: flex;
+  flex-direction: column;
   background-color: #FFFFFF;
+
+  &:first-child {
+    margin-top: 0;
+  }
 }
+
+.titTip {
+  font-weight: 600;
+  font-size: 28rpx;
+  color: #131415;
+  line-height: 40rpx;
+  margin-bottom: 32rpx;
+  position: relative;
+
+  &::after {
+    content: "";
+    display: inline-block;
+    position: absolute;
+    left: -24rpx;
+    top: 50%;
+    transform: translateY(-50%);
+    z-index: 1;
+    width: 6rpx;
+    height: 24rpx;
+    background: #24CD72;
+    border-radius: 0rpx 4rpx 4rpx 0rpx;
+  }
+}
+
 .item-content {
+  margin-top: 40rpx;
   display: flex;
   width: 100%;
+
+  &.first-item-content {
+    margin-top: 0;
+  }
+
   .goods-icon {
-    width: 160rpx;
-    height: 160rpx;
+    width: 120rpx;
+    height: 120rpx;
     margin-right: 24rpx;
     flex-shrink: 0;
     border-radius: 6px;
@@ -72,22 +206,26 @@ page {
     flex: 1 auto;
     display: flex;
     flex-direction: column;
+    overflow: hidden;
   }
 
   .goodsInfo {
     display: flex;
     justify-content: space-between;
-    padding-top: 4rpx;
+    margin-top: 8rpx;
+
     .goods-name {
       flex: 1 auto;
       white-space: nowrap;
       overflow: hidden;
+      text-overflow: ellipsis;
+      margin-right: 20rpx;
       font-weight: 600;
-      font-size: 30rpx;
+      font-size: 28rpx;
       color: #131415;
-      text-overflow: ellipsis;
-      max-width: 310rpx;
+      line-height: 48rpx;
     }
+
     .goods-price {
       flex-shrink: 0;
       font-family: DINAlternate, DINAlternate;
@@ -99,11 +237,9 @@ page {
       .stuff {
         font-size: 28rpx;
       }
+
       .priceZ {
-        font-size: 36rpx;
-      }
-      .priceF {
-        font-size: 28rpx;
+        font-size: 32rpx;
       }
     }
   }
@@ -113,21 +249,122 @@ page {
     justify-content: space-between;
     align-items: center;
     padding-top: 12rpx;
+
     .goods-card {
-      height: 40rpx;
+      font-weight: 400;
       font-size: 26rpx;
-      color: #131415;
-      line-height: 40rpx;
+      color: #777777;
+      line-height: 36rpx;
     }
+
     .goods-num {
+      font-weight: 400;
       font-size: 26rpx;
-      color: #999999;
+      color: #777777;
       line-height: 36rpx;
     }
   }
 
 }
 
+.discountCon {
+  margin-top: 42rpx;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+
+  .discountTip {
+    display: flex;
+    align-items: center;
+
+    image {
+      width: 32rpx;
+      height: 32rpx;
+    }
+
+    text {
+      margin-left: 8rpx;
+      font-weight: 400;
+      font-size: 28rpx;
+      color: #333333;
+      line-height: 40rpx;
+    }
+  }
+
+  .discount {
+    font-weight: bold;
+    font-size: 32rpx;
+    color: #FD4502;
+    line-height: 48rpx;
+
+    text {
+      &:first-child {
+        font-size: 28rpx;
+      }
+    }
+  }
+}
+
+.totalPic {
+  border-top: 2rpx solid #EEEEEE;
+  margin-top: 32rpx;
+  padding-top: 20rpx;
+  display: flex;
+  justify-content: flex-end;
+  align-items: flex-end;
+  font-weight: bold;
+  font-size: 32rpx;
+  color: #000000;
+
+  .titPic {
+    font-weight: 600;
+    font-size: 24rpx;
+    color: #777777;
+    line-height: 34rpx;
+  }
+
+  .stuff {
+    margin-left: 16rpx;
+    margin-right: 4rpx;
+  }
+
+  .numberDisplay--integer {
+    line-height: 56rpx;
+    font-size: 48rpx;
+  }
+
+  .numberDisplay--decimal {
+    font-size: 32rpx;
+  }
+}
+
+.memberInfo {
+  display: flex;
+  justify-content: space-between;
+  margin-bottom: 32rpx;
+
+  text {
+    &:nth-child(1) {
+      flex-shrink: 0;
+      font-weight: 400;
+      font-size: 28rpx;
+      color: #666666;
+      line-height: 40rpx;
+    }
+
+    &:nth-child(2) {
+      margin-left: 30rpx;
+      white-space: nowrap;
+      overflow: hidden;
+      text-overflow: ellipsis;
+      font-weight: 400;
+      font-size: 28rpx;
+      color: #000000;
+      line-height: 40rpx;
+    }
+  }
+}
+
 .order-time {
   margin: 24rpx 26rpx 0;
   border-radius: 20rpx;
@@ -138,14 +375,17 @@ page {
     display: flex;
     justify-content: space-between;
     padding-bottom: 36rpx;
+
     &:last-child {
       padding-bottom: 0;
     }
+
     .title {
       font-size: 28rpx;
       color: #131415;
       line-height: 40rpx;
     }
+
     .value {
       font-size: 28rpx;
       color: #777777;
@@ -160,19 +400,23 @@ page {
   left: 0;
   width: 100%;
   background-color: #FFFFFF;
-  padding: 20rpx 32rpx 58rpx 40rpx;
+  border-radius: 32rpx 32rpx 0rpx 0rpx;
+  padding: 32rpx 40rpx 56rpx 48rpx;
   display: flex;
   justify-content: space-between;
+  align-items: center;
   box-sizing: border-box;
 
   .orders {
     display: flex;
     flex-direction: column;
     margin-right: 40rpx;
+
     image {
       width: 48rpx;
       height: 48rpx;
     }
+
     text {
       font-weight: 500;
       font-size: 22rpx;
@@ -188,42 +432,51 @@ page {
 
   .price {
     display: flex;
-    align-items: center;
+    align-items: flex-end;
+    font-weight: bold;
+    font-size: 32rpx;
+    color: #000000;
+    line-height: 38rpx;
 
     .desc {
-      font-weight: 500;
-      font-size: 28rpx;
-      color: #131415;
-      line-height: 40rpx;
-      padding-top: 20rpx;
-      flex-shrink: 0;
+      font-weight: 600;
+      font-size: 24rpx;
+      color: #777777;
+      line-height: 34rpx;
     }
-    .currentPrice {
-      font-weight: bold;
-      color: #FF5000;
-      font-family: DINAlternate, DINAlternate;
-      .stuff {
-        font-size: 32rpx;
-      }
-      .priceZ {
-        font-size: 56rpx;
-      }
-      .priceF {
-        font-size: 32rpx;
-      }
+
+    .stuff {
+      margin-right: 4rpx;
+    }
+
+    .numberDisplay--integer {
+      line-height: 56rpx;
+      font-size: 48rpx;
+    }
+
+    .numberDisplay--decimal {
+      font-size: 32rpx;
     }
   }
 
+  .discountVal {
+    margin-top: 4rpx;
+    font-weight: 600;
+    font-size: 24rpx;
+    color: #FD4502;
+    line-height: 34rpx;
+  }
+
   button {
-    margin: 0 0 0 12rpx;
-    width: auto;
-    background: linear-gradient( 315deg, #FF4A00 0%, #FE8C00 100%);
-    border-radius: 16rpx;
-    padding: 22rpx 84rpx;
-    font-weight: 500;
+    margin: 0;
+    width: 280rpx;
+    height: 88rpx;
+    background: url("https://oss.dayaedu.com/ktyq/1739342836131.png") no-repeat;
+    background-size: 100% 100%;
+    border-radius: 78rpx;
+    font-weight: 600;
     font-size: 32rpx;
     color: #FFFFFF;
-    line-height: 44rpx;
-    flex-shrink: 0;
+    line-height: 88rpx;
   }
 }

+ 85 - 57
miniprogram/pages/orders/order-detail.ts

@@ -1,5 +1,5 @@
 // pages/orders/order-detail.ts
-import { api_executeOrder, api_executePayment, api_queryByParamName, api_userPaymentOrderUnpaid } from "../../api/login";
+import { api_executeOrder, api_executePayment, api_queryByParamName, api_userPaymentOrderUnpaid, api_getUserReceiveAddressPage } from "../../api/login";
 
 // 获取应用实例
 const app = getApp<IAppOption>()
@@ -8,6 +8,9 @@ Page({
    * 页面的初始数据
    */
   data: {
+    popupShow: false,
+    isAddressInfoTip: false,
+    addressInfo: {} as any,
     serviceShow: true,
     status: 'ing',
     statusList: {
@@ -18,6 +21,8 @@ Page({
       },
     },
     goodsInfo: {} as any,
+    instrumentsInfo: {} as any,
+    memberInfo: {} as any,
     paymentType: null as any, // 支付类型
     paymentChannel: null as any,
   },
@@ -29,9 +34,13 @@ Page({
     this.queryPayType()
     if (options.orderInfo) {
       const goods = JSON.parse(decodeURIComponent(options.orderInfo));
-      console.log(goods, 'goods')
+      const instrumentsInfo = JSON.parse(decodeURIComponent(options.instrumentsInfo));
+      const memberInfo = JSON.parse(decodeURIComponent(options.memberInfo));
+      console.log(goods, 'goods', instrumentsInfo, memberInfo)
       this.setData({
         goodsInfo: goods,
+        instrumentsInfo,
+        memberInfo,
         status: goods.status
       });
     }
@@ -46,6 +55,33 @@ Page({
       serviceShow: false
     })
   },
+  async onAddressInfo() {
+    this.setData({
+      isAddressInfoTip: false
+    })
+    try {
+      const resData = await api_getUserReceiveAddressPage()
+      const pageRows = resData?.data?.data?.rows || []
+      // 当有收货地址的时候跳转到收货地址选择列表页面,当没有收货地址的时候到添加收货地址
+      if (pageRows.length) {
+        wx.navigateTo({
+          url: `/pages/address/addressList?id=${this.data.addressInfo.id}`
+        });
+      } else {
+        this.setData({
+          popupShow: true
+        })
+      }
+    } catch (e) {
+      console.log(e, 'e')
+    }
+  },
+  onAddAddress(e: any) {
+    const { addressInfo } = e.detail
+    this.setData({
+      addressInfo
+    })
+  },
   // 获取后台配置的支付方式
   async queryPayType() {
     try {
@@ -73,14 +109,26 @@ Page({
   },
   // 购买
   async onSubmit() {
+    // 有乐器必须填收货信息
+    if (this.data.instrumentsInfo.id && !this.data.addressInfo.id) {
+      wx.showToast({
+        title: "请填写收货信息",
+        icon: 'none'
+      })
+      this.setData({
+        isAddressInfoTip: true
+      })
+      return
+    }
+    console.log(this.data.addressInfo)
     wx.showLoading({
       mask: true,
       title: "订单提交中...",
     });
     try {
       const { salePrice, shopId, name, id, orderNo } = this.data.goodsInfo
-      if(orderNo) {
-        const {data} = await api_userPaymentOrderUnpaid({
+      if (orderNo) {
+        const { data } = await api_userPaymentOrderUnpaid({
           orderNo: orderNo,
           paymentType: 'WECHAT_MINI'
         })
@@ -91,32 +139,52 @@ Page({
           this.onPayError()
         }
       } else {
+        const goodsInfos = [{
+          "goodsId": id,
+          "goodsNum": 1,
+          "goodsType": "ACTIVATION_CODE",
+          "paymentCashAmount": salePrice,
+          "paymentCouponAmount": 0
+        }]
+        // 乐器
+        if (this.data.instrumentsInfo.id) {
+          goodsInfos.push({
+            "goodsId": this.data.instrumentsInfo.id,
+            "goodsNum": 1,
+            "goodsType": "INSTRUMENTS",
+            "paymentCashAmount": this.data.instrumentsInfo.salePrice,
+            "paymentCouponAmount": 0
+          })
+        }
         const { data } = await api_executeOrder({
           "orderType": "WECHAT_MINI",
           "paymentType": this.data.paymentType,
-          "paymentCashAmount": salePrice,
+          "paymentCashAmount": salePrice + (this.data.instrumentsInfo.salePrice || 0),
           "paymentCouponAmount": 0,
           "shopId": shopId,
           "openId": app.globalData.userInfo?.liteOpenid,
-          "goodsInfos": [{
-            "goodsId": id,
-            "goodsNum": 1,
-            "goodsType": "ACTIVATION_CODE",
-            "paymentCashAmount": salePrice,
-            "paymentCouponAmount": 0
-          }],
-          "orderName": name,
-          "orderDesc": name
+          goodsInfos,
+          "orderName": name + (this.data.instrumentsInfo.name ? `+${this.data.instrumentsInfo.name}` : ""),
+          "orderDesc": name + (this.data.instrumentsInfo.name ? `+${this.data.instrumentsInfo.name}` : ""),
+          "receiveAddress": this.data.addressInfo.id || "",
+          "userBeneficiaryId": this.data.memberInfo.id
         })
         if (data.code === 200) {
           const { paymentConfig, paymentType, orderNo } = data.data
           this.onExecutePay(paymentConfig, paymentType, orderNo)
-        } else if(data.code === 5200) {
+        } else if (data.code === 5200) {
           wx.hideLoading()
           wx.showToast({
             title: data.message,
             icon: 'none'
           })
+        } else if (data.code === 5435) {
+          wx.hideLoading()
+          wx.showToast({
+            title: data.message,
+            icon: 'none'
+          })
+          setTimeout(() => { wx.navigateBack() }, 1000)
         } else {
           this.onPayError()
         }
@@ -125,7 +193,7 @@ Page({
       wx.hideLoading()
     }
   },
-  async onExecutePay( paymentConfig: any, paymentType: string, orderNo: string) {
+  async onExecutePay(paymentConfig: any, paymentType: string, orderNo: string) {
     wx.login({
       success: async (wxres: any) => {
         const res = await api_executePayment({
@@ -139,7 +207,7 @@ Page({
           // wxPubAppId: 'wxbde13f59d40cb4f2'
         })
         wx.hideLoading()
-        if(res.data.code === 200) {
+        if (res.data.code === 200) {
           this.onPay(paymentType, res.data.data.reqParams, orderNo)
         } else {
           this.onPayError(res.data.message)
@@ -180,46 +248,6 @@ Page({
       }
     })
   },
-  /**
-   * 生命周期函数--监听页面初次渲染完成
-   */
-  onReady() {
-  },
-
-  /**
-   * 生命周期函数--监听页面显示
-   */
-  onShow() {
-
-  },
-
-  /**
-   * 生命周期函数--监听页面隐藏
-   */
-  onHide() {
-
-  },
-
-  /**
-   * 生命周期函数--监听页面卸载
-   */
-  onUnload() {
-
-  },
-
-  /**
-   * 页面相关事件处理函数--监听用户下拉动作
-   */
-  onPullDownRefresh() {
-
-  },
-
-  /**
-   * 页面上拉触底事件的处理函数
-   */
-  onReachBottom() {
-
-  },
 
   /**
    * 用户点击右上角分享

+ 94 - 18
miniprogram/pages/orders/order-detail.wxml

@@ -1,34 +1,101 @@
 <!--pages/orders/order-detail.wxml-->
 <view class="container">
-  <navigation-bar color="#fff" title="订单详情"></navigation-bar>
+  <navigation-bar title="订单确认"></navigation-bar>
 
-  <scroll-view class="record-list" type="list" scroll-y bindscrolltolower="loadMore">
-    <view class="order-status">
+  <scroll-view class="record-list" type="list" scroll-y>
+    <!-- <view class="order-status">
       <view class="status">
-        <!-- <image src="{{ statusList[status].logo }}"></image> -->
+        <image src="{{ statusList[status].logo }}"></image>
         <text>{{ statusList[status].title }}</text>
       </view>
       <view class="tips">{{ statusList[status].content }}</view>
+    </view> -->
+
+    <view wx:if="{{ instrumentsInfo.id }}" class="memberBox {{isAddressInfoTip?'showMemberInfoTip':''}}">
+      <view wx:if="{{ !addressInfo.id }}" class="memberCon" bind:tap="onAddressInfo">
+        <image class="memberImg" src="./images/member.png"></image>
+        <text class="info">请填写收货信息</text>
+        <image class="chevronImg" src="../index/images/chevron.png"></image>
+      </view>
+      <view wx:else class="memberCon" bind:tap="onAddressInfo">
+        <view class="memberInfoCon">
+          <view class="infoCon">
+            <image class="tip" src="./images/member.png" />
+            <text class="name">{{addressInfo.name}}</text>
+            <text class="phone">{{addressInfo.phoneNumber}}</text>
+          </view>
+          <view class="schoolInfoCon">
+            <text class="schoolInfo">收货地址</text><text class="schoolInfoDes">{{addressInfo.addressDes}}</text>
+          </view>
+        </view>
+        <image class="chevronImg" src="../index/images/chevron.png"></image>
+      </view>
     </view>
 
     <view class="order-content">
-      <view class="item-content">
+      <view class="titTip">订单详情</view>
+      <view class="item-content first-item-content">
         <image class='goods-icon' src="{{ goodsInfo.pic }}" mode="" />
         <view class="goods-desc">
           <view class="goodsInfo">
             <view class="goods-name">{{ goodsInfo.name }}</view>
             <view class="goods-price">
               <text class="stuff">¥ </text>
-              <text class="priceZ">{{ goodsInfo.integerPart }}</text>
-              <text class="priceF">.{{ goodsInfo.decimalPart }}</text>
+              <text class="priceZ">{{ my.formatValue(goodsInfo.originalPrice) }}</text>
             </view>
           </view>
           <view class="goods-type">
             <view class="goods-card">{{ goodsInfo.typeName }}</view>
-            <view class="goods-num">共 1 件</view>
+            <view class="goods-num">x1</view>
+          </view>
+        </view>
+      </view>
+      <view wx:if="{{ instrumentsInfo.id }}" class="item-content">
+        <image class='goods-icon' src="{{ instrumentsInfo.pic }}" mode="" />
+        <view class="goods-desc">
+          <view class="goodsInfo">
+            <view class="goods-name">{{ instrumentsInfo.name }}</view>
+            <view class="goods-price">
+              <text class="stuff">¥ </text>
+              <text class="priceZ">{{ my.formatValue(instrumentsInfo.originalPrice) }}</text>
+            </view>
+          </view>
+          <view class="goods-type">
+            <view class="goods-card"></view>
+            <view class="goods-num">x1</view>
           </view>
         </view>
       </view>
+      <view wx:if="{{goodsInfo.originalPrice + (instrumentsInfo.originalPrice || 0) - (goodsInfo.salePrice + (instrumentsInfo.salePrice || 0)) > 0 }}" class="discountCon">
+        <view class="discountTip">
+          <image src="./images/discount.png"></image>
+          <text>优惠活动</text>
+        </view>
+        <view class="discount">
+          <text>-¥ </text>
+          <text>{{my.formatValue(goodsInfo.originalPrice + (instrumentsInfo.originalPrice || 0) - (goodsInfo.salePrice + (instrumentsInfo.salePrice || 0)))}}</text>
+        </view>
+      </view>
+      <view class="totalPic">
+        <text class="titPic">合计</text>
+        <text class="stuff">¥</text>
+        <numberDisplay number="{{ goodsInfo.salePrice + (instrumentsInfo.salePrice || 0) }}" />
+      </view>
+    </view>
+    <view class="order-content">
+      <view class="titTip">会员信息</view>
+      <view class="memberInfo">
+        <text>姓名</text>
+        <text>{{ memberInfo.name }}</text>
+      </view>
+      <view class="memberInfo">
+        <text>联系电话</text>
+        <text>{{ memberInfo.phone }}</text>
+      </view>
+      <view class="memberInfo">
+        <text>学校信息</text>
+        <text>{{ memberInfo.schoolInfo }}</text>
+      </view>
     </view>
 
     <!-- <view class="order-time">
@@ -44,16 +111,25 @@
   </scroll-view>
 
   <view class="order-btn">
+    <view class="priceCon">
       <view class="price">
-        <view class="desc">支付金额:</view>
-        <view class="currentPrice">
-          <text class="stuff">¥ </text>
-          <text class="priceZ">{{ goodsInfo.integerPart }}</text>
-          <text class="priceF">.{{ goodsInfo.decimalPart }}</text>
-        </view>
+        <view class="desc">待支付:</view>
+        <text class="stuff">¥</text>
+        <numberDisplay number="{{ goodsInfo.salePrice + (instrumentsInfo.salePrice || 0) }}" />
       </view>
-      <button type="primary" bind:tap="onSubmit">{{ goodsInfo.orderNo ? '继续支付' : '立即支付' }}</button>
+      <text wx:if="{{goodsInfo.originalPrice + (instrumentsInfo.originalPrice || 0) - (goodsInfo.salePrice + (instrumentsInfo.salePrice || 0)) > 0 }}" class="discountVal">已优惠 ¥{{my.formatValue(goodsInfo.originalPrice + (instrumentsInfo.originalPrice || 0) - (goodsInfo.salePrice + (instrumentsInfo.salePrice || 0)))}}</text>
+    </view>
+    <button type="primary" bind:tap="onSubmit">{{ goodsInfo.orderNo ? '继续支付' : '去支付' }}</button>
   </view>
-    <!-- 客服 -->
-    <service wx:if="{{serviceShow}}"></service>
-</view>
+  <addAddress popupShow='{{popupShow}}' bind:addAddress="onAddAddress"></addAddress>
+  <!-- 客服 -->
+  <!-- <service wx:if="{{serviceShow}}"></service> -->
+</view>
+<wxs module="my">
+  var formatValue = function (value) {
+    return parseFloat(value).toFixed(2);
+  }
+  module.exports = {
+    formatValue: formatValue
+  }
+</wxs>

+ 2 - 1
miniprogram/pages/orders/order-result.json

@@ -2,6 +2,7 @@
   "usingComponents": {
     "navigation-bar": "/components/navigation-bar/navigation-bar",
     "service": "/components/service/service",
-    "apply-refound": "/components/apply-refound/apply-refound"
+    "addAddress": "../address/addAddress",
+    "numberDisplay": "/components/numberDisplay/numberDisplay"
   }
 }

+ 325 - 209
miniprogram/pages/orders/order-result.less

@@ -1,82 +1,205 @@
 /* pages/orders/order-detail.wxss */
-page {
+.container {
+  position: relative;
   height: 100vh;
   display: flex;
   flex-direction: column;
-  background: #F4F4F4;
+  background: #F5F6F7;
 
+  // background: linear-gradient(to bottom, #FB660A, #F5F6F7) #f4f4f4;
+  // background-size: 750rpx;
   &::before {
     content: '';
     position: absolute;
     top: 0;
     width: 100%;
-    height: 750rpx; 
-    background: linear-gradient(to bottom, #FB660A, #F5F6F7) #f4f4f4;
-    background-size: 750rpx;
+    width: 100%;
+    height: 592rpx;
+    background: url("https://oss.dayaedu.com/ktyq/1738997023805.png") no-repeat;
+    background-size: 100% 100%;
   }
 
-  .weui-navigation-bar__btn_goback {
-    background-color: #fff;
+  .record-list {
+    padding-top: 24rpx;
+    flex-grow: 1;
+    overflow: hidden;
+    &.waitList{
+      padding-bottom: 200rpx;
+    }
   }
 }
 
-.scroll-container {
-  padding-bottom: 184rpx;
-}
-
 .order-status {
-  margin: 24rpx 26rpx 0;
+  margin: 0 24rpx 32rpx 50rpx;
   // background-color: #FFFFFF;
   border-radius: 20rpx;
-  padding: 24rpx 8rpx 24rpx 32rpx;
+  //padding: 24rpx 32rpx;
+
   .status {
     display: flex;
-    justify-content: space-between;
+    align-items: center;
+
     image {
       width: 48rpx;
       height: 48rpx;
       margin-right: 16rpx;
     }
-    .btn-refound {
-      text-align: center;
-      font-size: 26rpx;
-      color: rgba(255,255,255,0.7);
-      line-height: 34rpx;
-      height: 34rpx;
-      border-radius: 24rpx;
-      border: 1rpx solid rgba(255,255,255,0.7);
-      padding: 4rpx 12rpx;
-    }
-    
+
     text {
       font-weight: 600;
-      font-size: 48rpx;
-      color: #FFFFFF;
+      font-size: 40rpx;
+      color: #000000;
       line-height: 48rpx;
     }
   }
+
   .tips {
-    padding-top: 24rpx;
-    font-size: 28rpx;
-    color: #FFFFFF;
-    line-height: 40rpx;
+    margin-top: 20rpx;
+    font-weight: 400;
+    font-size: 26rpx;
+    color: rgba(0,0,0,0.5);
+    line-height: 36rpx;
+  }
+}
+
+.memberBox {
+  margin: 0 20rpx;
+  background: #ffffff;
+  border-radius: 20rpx;
+  border: 3rpx solid transparent;
+
+  &.showMemberInfoTip {
+    border-color: #FD4502;
+  }
+
+  .memberCon {
+    padding: 24rpx;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+
+    .memberImg {
+      width: 44rpx;
+      height: 44rpx;
+    }
+
+    .info {
+      flex-grow: 1;
+      margin-left: 16rpx;
+      font-weight: 600;
+      font-size: 28rpx;
+      color: #131415;
+      line-height: 40rpx;
+    }
+
+    .chevronImg {
+      flex-shrink: 0;
+      width: 32rpx;
+      height: 32rpx;
+    }
+
+    .memberInfoCon {
+      overflow: hidden;
+    }
+
+    .infoCon {
+      display: flex;
+      align-items: center;
+      font-weight: 600;
+      font-size: 28rpx;
+      color: #131415;
+      line-height: 40rpx;
+
+      .tip {
+        width: 44rpx;
+        height: 44rpx;
+      }
+
+      .name,
+      .phone {
+        margin-left: 16rpx;
+      }
+    }
+
+    .schoolInfoCon {
+      margin-top: 20rpx;
+      display: flex;
+      align-items: center;
+
+      .schoolInfo {
+        margin-right: 8rpx;
+        border-radius: 4rpx;
+        border: 1rpx solid rgba(243, 131, 9, 0.5);
+        padding: 2rpx 6rpx;
+        font-weight: 400;
+        font-size: 20rpx;
+        color: #F38309;
+        line-height: 30rpx;
+        flex-shrink: 0;
+      }
+
+      .schoolInfoDes {
+        margin-right: 10rpx;
+        font-weight: 400;
+        font-size: 24rpx;
+        color: #777777;
+        line-height: 32rpx;
+        white-space: nowrap;
+        overflow: hidden;
+        text-overflow: ellipsis;
+      }
+    }
   }
 }
 
 .order-content {
-  margin: 32rpx 26rpx 0;
+  margin: 20rpx 26rpx 0;
   border-radius: 20rpx;
-  padding: 28rpx 24rpx;
+  padding: 24rpx 24rpx 32rpx;
   display: flex;
   flex-direction: column;
   background-color: #FFFFFF;
+
+  &:first-child {
+    margin-top: 0;
+  }
+}
+
+.titTip {
+  font-weight: 600;
+  font-size: 28rpx;
+  color: #131415;
+  line-height: 40rpx;
+  margin-bottom: 32rpx;
+  position: relative;
+
+  &::after {
+    content: "";
+    display: inline-block;
+    position: absolute;
+    left: -24rpx;
+    top: 50%;
+    transform: translateY(-50%);
+    z-index: 1;
+    width: 6rpx;
+    height: 24rpx;
+    background: #24CD72;
+    border-radius: 0rpx 4rpx 4rpx 0rpx;
+  }
 }
+
 .item-content {
+  margin-top: 40rpx;
   display: flex;
   width: 100%;
+
+  &.first-item-content {
+    margin-top: 0;
+  }
+
   .goods-icon {
-    width: 140rpx;
-    height: 140rpx;
+    width: 120rpx;
+    height: 120rpx;
     margin-right: 24rpx;
     flex-shrink: 0;
     border-radius: 6px;
@@ -87,29 +210,26 @@ page {
     flex: 1 auto;
     display: flex;
     flex-direction: column;
+    overflow: hidden;
   }
 
   .goodsInfo {
     display: flex;
     justify-content: space-between;
-    padding-top: 4rpx;
+    margin-top: 8rpx;
+
     .goods-name {
       flex: 1 auto;
       white-space: nowrap;
       overflow: hidden;
-      font-weight: 600;
-      font-size: 30rpx;
       text-overflow: ellipsis;
-      max-width: 310rpx;
+      margin-right: 20rpx;
+      font-weight: 600;
+      font-size: 28rpx;
+      color: #131415;
+      line-height: 48rpx;
     }
-    // .goods-price {
-    //   flex-shrink: 0;
-    //   font-family: DINAlternate, DINAlternate;
-    //   font-weight: bold;
-    //   font-size: 28rpx;
-    //   color: #131415;
-    //   line-height: 48rpx;
-    // }
+
     .goods-price {
       flex-shrink: 0;
       font-family: DINAlternate, DINAlternate;
@@ -121,11 +241,9 @@ page {
       .stuff {
         font-size: 28rpx;
       }
+
       .priceZ {
-        font-size: 36rpx;
-      }
-      .priceF {
-        font-size: 28rpx;
+        font-size: 32rpx;
       }
     }
   }
@@ -135,135 +253,132 @@ page {
     justify-content: space-between;
     align-items: center;
     padding-top: 12rpx;
+
     .goods-card {
-      border-radius: 6rpx;
+      font-weight: 400;
       font-size: 26rpx;
-      color: #131415;
-      line-height: 40rpx;
+      color: #777777;
+      line-height: 36rpx;
     }
+
     .goods-num {
+      font-weight: 400;
       font-size: 26rpx;
-      color: #999999;
+      color: #777777;
       line-height: 36rpx;
     }
   }
+
 }
-.only_canvas {
-  position: absolute;
-  left: -300rpx;
-  top: 0;
-  width: 300rpx;
-  height: 300rpx;
-}
-/* HTML: <div class="loader"></div> */
-.loader {
-  position: absolute;
-  top: 50%;
-  left: 50%;
-  right: 0;
-  bottom: 0;
-  margin-top: -50rpx;
-  margin-left: -50rpx;
-  z-index: 9;
-  width: 100rpx;
-  aspect-ratio: 1;
-  border-radius: 50%;
-  background: 
-    radial-gradient(farthest-side,#E8E8E8 94%,#0000) top/8px 8px no-repeat,
-    conic-gradient(#0000 30%,#E8E8E8);
-  -webkit-mask: radial-gradient(farthest-side,#0000 calc(100% - 8px),#000 0);
-  animation: tempLoading 1s infinite linear;
-}
-@keyframes tempLoading{ 
-  100%{transform: rotate(1turn)}
-}
-.qrcode-section {
-  margin-top: 28rpx;
-  border-top: 2rpx solid #F0F0F0;
-  padding-top: 60rpx;
-  padding-bottom: 22rpx;
-  text-align: center;
+
+.discountCon {
+  margin-top: 42rpx;
   display: flex;
-  flex-direction: column;
-  .qrcode-wrap {
-    position: relative;
-    margin: 0 auto;
-    // border: 3rpx solid #EDEDED;
-    padding: 34rpx;
-    display: inline-block;
-    font-size: 0;
-    background: url('https://oss.dayaedu.com/ktyq/1732529619848.png') no-repeat center;
-    background-size: contain;
+  justify-content: space-between;
+  align-items: center;
 
-    &.used {
-      .arrow {
-        display: none;
-      }
-      background: url('https://oss.dayaedu.com/ktyq/1732530067551.png') no-repeat center;
-      background-size: contain;
+  .discountTip {
+    display: flex;
+    align-items: center;
+
+    image {
+      width: 32rpx;
+      height: 32rpx;
     }
 
-    .arrow {
-      position: absolute;
-      left: -126rpx;
-      top: 50%;
-      transform: translateY(-50%);
-      width: 106rpx;
-      height: 52rpx;
+    text {
+      margin-left: 8rpx;
+      font-weight: 400;
+      font-size: 28rpx;
+      color: #333333;
+      line-height: 40rpx;
     }
-    .arrow-right {
-      right: -126rpx;
-      left: auto;
-      transform: rotateY(180deg) translateY(-50%);
+  }
+
+  .discount {
+    font-weight: bold;
+    font-size: 32rpx;
+    color: #FD4502;
+    line-height: 48rpx;
+
+    text {
+      &:first-child {
+        font-size: 28rpx;
+      }
     }
   }
-  .my_draw_canvas {
-    width: 300rpx;
-    height: 300rpx;
+}
+
+.totalPic {
+  border-top: 2rpx solid #EEEEEE;
+  margin-top: 32rpx;
+  padding-top: 20rpx;
+  display: flex;
+  justify-content: flex-end;
+  align-items: flex-end;
+  font-weight: bold;
+  font-size: 32rpx;
+  color: #000000;
+
+  .titPic {
+    font-weight: 600;
+    font-size: 24rpx;
+    color: #777777;
+    line-height: 34rpx;
   }
-  .qrcode-text {
-    display: inline-block;
-    margin-top: 32rpx;
-    padding: 16rpx 32rpx 0;
-    font-weight: 500;
-    font-size: 28rpx;
-    color: #131415;
-    line-height: 40rpx;
-    // background: #FFE7C7;
-    border-radius: 36rpx;
 
-    &.used {
-      // background: #F2F2F2;
-      color: #AAAAAA;
-    }
+  .stuff {
+    margin-left: 16rpx;
+    margin-right: 4rpx;
+  }
+
+  .numberDisplay--integer {
+    line-height: 56rpx;
+    font-size: 48rpx;
+  }
+
+  .numberDisplay--decimal {
+    font-size: 32rpx;
   }
+}
 
-  .qrcode-btn--section {
+.memberInfo {
+  display: flex;
+  justify-content: space-between;
+  margin-bottom: 32rpx;
+  .orderInfoRight{
     display: flex;
     align-items: center;
-    justify-content: center;
-    // padding-bottom: 22rpx;
-    padding-top: 32rpx;
-    button {
-      border-radius: 78rpx;
-      // line-height: 68rpx;
-      padding: 14rpx 30rpx;
-      width: auto;
-      border-radius: 68rpx;
-      font-weight: 500;
+    font-weight: 400;
+    font-size: 28rpx;
+    color: #000000;
+    line-height: 40rpx;
+    .copy{
+      margin-left: 20rpx;
+      font-weight: 400;
       font-size: 28rpx;
-      margin: 0 16rpx;
-      min-width: 200rpx;
-      box-sizing: border-box;
+      color: #0AAF20;
+      line-height: 40rpx;
     }
-    .submit {
-      background: linear-gradient( 315deg, #FF4A00 0%, #FE8C00 100%);
-      color: #FFFFFF;
+  }
+  >text {
+    &:nth-child(1) {
+      flex-shrink: 0;
+      font-weight: 400;
+      font-size: 28rpx;
+      color: #666666;
+      line-height: 40rpx;
     }
-    .download {
-      background: #FFEADE;
-      
-      color: #FF5000;
+
+    &:nth-child(2) {
+      margin-left: 30rpx;
+      white-space: nowrap;
+      overflow: hidden;
+      text-overflow: ellipsis;
+      font-weight: 400;
+      font-size: 28rpx;
+      color: #000000;
+      line-height: 40rpx;
     }
   }
 }
@@ -271,41 +386,28 @@ page {
 .order-time {
   margin: 24rpx 26rpx 0;
   border-radius: 20rpx;
-  padding: 0 24rpx;
+  padding: 36rpx 24rpx;
   background-color: #FFFFFF;
 
   .order-item {
     display: flex;
     justify-content: space-between;
-    padding: 36rpx 0;
-    border-bottom: 2rpx solid #F0F0F0;
+    padding-bottom: 36rpx;
+
     &:last-child {
-      border-bottom: none;
+      padding-bottom: 0;
     }
+
     .title {
-      font-weight: 500;
-      font-size: 30rpx;
+      font-size: 28rpx;
       color: #131415;
-      line-height: 42rpx;
+      line-height: 40rpx;
     }
+
     .value {
-      font-size: 30rpx;
+      font-size: 28rpx;
       color: #777777;
-      line-height: 42rpx;
-      display: flex;
-      &.red {
-        color: #FF5000;
-      }
-
-      .copy {
-        font-size: 30rpx;
-        color: #FF5000;
-        line-height: 42rpx;
-        display: flex;
-        align-items: center;
-        font-weight: 400;
-        padding-left: 16rpx;
-      }
+      line-height: 40rpx;
     }
   }
 }
@@ -316,19 +418,23 @@ page {
   left: 0;
   width: 100%;
   background-color: #FFFFFF;
-  padding: 20rpx 32rpx 58rpx;
+  border-radius: 32rpx 32rpx 0rpx 0rpx;
+  padding: 32rpx 40rpx 56rpx 48rpx;
   display: flex;
   justify-content: space-between;
+  align-items: center;
   box-sizing: border-box;
 
   .orders {
     display: flex;
     flex-direction: column;
     margin-right: 40rpx;
+
     image {
       width: 48rpx;
       height: 48rpx;
     }
+
     text {
       font-weight: 500;
       font-size: 22rpx;
@@ -338,47 +444,57 @@ page {
     }
   }
 
+  .more {
+    display: flex;
+  }
+
   .price {
     display: flex;
-    align-items: center;
+    align-items: flex-end;
+    font-weight: bold;
+    font-size: 32rpx;
+    color: #000000;
+    line-height: 38rpx;
 
     .desc {
-      font-weight: 500;
-      font-size: 28rpx;
-      color: #131415;
-      line-height: 40rpx;
+      font-weight: 600;
+      font-size: 24rpx;
+      color: #777777;
+      line-height: 34rpx;
     }
-    .currentPrice {
-      font-weight: bold;
-      color: #FE2451;
-      font-family: DINAlternate, DINAlternate;
-      .stuff {
-        font-size: 32rpx;
-      }
-      .priceZ {
-        font-size: 56rpx;
-      }
-      .priceF {
-        font-size: 32rpx;
-      }
+
+    .stuff {
+      margin-right: 4rpx;
+    }
+
+    .numberDisplay--integer {
+      line-height: 56rpx;
+      font-size: 48rpx;
     }
+
+    .numberDisplay--decimal {
+      font-size: 32rpx;
+    }
+  }
+
+  .discountVal {
+    margin-top: 4rpx;
+    font-weight: 600;
+    font-size: 24rpx;
+    color: #FD4502;
+    line-height: 34rpx;
   }
 
   button {
     margin: 0;
-    width: 100%;
-    background: linear-gradient( 315deg, #FF4A00 0%, #FE8C00 100%);
-    border-radius: 16rpx;
-    padding: 22rpx 84rpx;
-    font-weight: 500;
+    width: 280rpx;
+    height: 88rpx;
+    background: url("https://oss.dayaedu.com/ktyq/1739342836131.png") no-repeat;
+    background-size: 100% 100%;
+    border-radius: 78rpx;
+    font-weight: 600;
     font-size: 32rpx;
     color: #FFFFFF;
-    line-height: 44rpx;
-    &[disabled][type=primary] {
-      color: #fff;
-      background: linear-gradient( 315deg, #FF4A00 0%, #FE8C00 100%);
-      color: #FFFFFF;
-      opacity: 0.7;
-    }
+    line-height: 88rpx;
   }
 }

+ 242 - 219
miniprogram/pages/orders/order-result.ts

@@ -1,24 +1,39 @@
 // pages/orders/order-detail.ts
-import drawQrcode from "../../utils/weapp.qrcode.esm";
-import { api_userPaymentCancelRefund, api_userPaymentOrderDetail } from "../../api/login";
+import { api_executeOrder, api_executePayment, api_queryByParamName, api_userPaymentOrderUnpaid, api_getUserReceiveAddressPage, api_userPaymentOrderDetail } from "../../api/login";
 
+const GRADE_ENUM = {
+  '1': '一年级',
+  '2': '二年级',
+  '3': '三年级',
+  '4': '四年级',
+  '5': '五年级',
+  '6': '六年级',
+  '7': '七年级',
+  '8': '八年级',
+  '9': '九年级'
+} as any;
 // 获取应用实例
+const app = getApp<IAppOption>()
 Page({
   /**
    * 页面的初始数据
    */
   data: {
-    status: 'WAIT_PAY',
+    popupShow: false,
+    isAddressInfoTip: false,
+    addressInfo: {} as any,
+    serviceShow: true,
+    status: '',
     statusList: {
       WAIT_PAY: {
         logo: './images/ing.png',
-        title: '待付款',
+        title: '待付',
         content: '为了确保您的订单顺利进行,请尽快完成支付'
       },
       PAID: {
         logo: './images/success.png',
         title: '已完成',
-        content: '登录「音乐数字课堂」APP,开启AI学练之旅~'
+        content: '订单流程已结束,感谢您的支持与参与!'
       },
       CLOSED: {
         logo: './images/error.png',
@@ -41,115 +56,91 @@ Page({
         content: '您的订单已成功退款,感谢您的耐心等待'
       }
     },
-    timerCount: 0,
-    timer: null as any,
+    orderNo: "",
     goodsInfo: {} as any,
-    tabIdx: 0, // 当前是从哪个tab来的
-    orderNo: "" as string,
-    showCanvas: false, // 是否显示二维码
-    canvasImg: "" as string,
-    serviceShow: true,
-    refoundStatus: false,
-    cancelRefoundStatus: false
+    instrumentsInfo: {} as any,
+    memberInfo: {} as any,
+    orderInfo: {} as any, //订单信息
+    paymentType: null as any, // 支付类型
+    paymentChannel: null as any,
   },
 
   /**
    * 生命周期函数--监听页面加载
    */
   onLoad(options: any) {
+    this.queryPayType()
+    // if (options.orderInfo) {
+    //   const goods = JSON.parse(decodeURIComponent(options.orderInfo));
+    //   const instrumentsInfo = JSON.parse(decodeURIComponent(options.instrumentsInfo));
+    //   const memberInfo = JSON.parse(decodeURIComponent(options.memberInfo));
+    //   console.log(goods, 'goods', instrumentsInfo, memberInfo)
+    //   this.setData({
+    //     goodsInfo: goods,
+    //     instrumentsInfo,
+    //     memberInfo,
+    //     status: goods.status
+    //   });
+    // }
     if (options.orderNo) {
       this.setData({
-        orderNo: options.orderNo,
-        tabIdx: options.tabIdx,
-      }, () => {
-        this.getDetail(this.onTimeout)
-      });
-    }
-  },
-  onShow() {
-    this.setData({
-      serviceShow: true
-    })
-    if(this.data.orderNo) {
-      this.getDetail(this.onTimeout)
+        orderNo: options.orderNo
+      })
+      this.getDetail()
     }
   },
-  onHide() {
-    this.setData({
-      serviceShow: false
-    })
-  },
   async getDetail(callback?: any) {
     try {
       const { data } = await api_userPaymentOrderDetail(this.data.orderNo);
       if (data.code == 200) {
-        const result = data.data || {}
-        const goodsInfos = result.goodsInfos || []
-        const tempGoods: any = []
-        goodsInfos.forEach((item: any) => {
-          const prices: any = this.formatPrice(item.paymentCashAmount)
-        
-          tempGoods.push({
-            ...item,
-            integerPart: prices.integerPart,
-            decimalPart: prices.decimalPart,
-            shortUrl: item.activationCodeInfo.shortUrl,
-            code: item.activationCodeInfo.activationCode,
-            originalPrice: this.formatPrice(item.paymentCashAmount, 'ALL'),
-            typeName: this.formatPeriod(item.activationCodeInfo?.times || 1, item.activationCodeInfo.type)
-          })
-        })
-        let refundStyleStr = ''
-        if(result.refundStyle === 'TURN_BACK') {
-          refundStyleStr = '原路返回'
-        } else if(result.refundStyle === 'OFFLINE') {
-          refundStyleStr = '线下'
+        const { goodsInfos, addresses, beneficiary, wechatStatus, createTime } = data.data
+        const goodsInfo = {}
+        if (goodsInfos[0]) {
+          goodsInfo.pic = goodsInfos[0].goodsUrl
+          goodsInfo.name = goodsInfos[0].goodsName
+          goodsInfo.originalPrice = goodsInfos[0].originalPrice
+          goodsInfo.salePrice = goodsInfos[0].paymentCashAmount
+          goodsInfo.typeName = this.formatPeriod(goodsInfos[0].activationCodeInfo.times, goodsInfos[0].activationCodeInfo.type)
+          goodsInfo.orderNo = this.data.orderNo
+        }
+        const instrumentsInfo = {}
+        if (goodsInfos[1]) {
+          instrumentsInfo.pic = goodsInfos[1].goodsUrl
+          instrumentsInfo.name = goodsInfos[1].goodsName
+          instrumentsInfo.originalPrice = goodsInfos[1].originalPrice
+          instrumentsInfo.salePrice = goodsInfos[1].paymentCashAmount
+          instrumentsInfo.id = goodsInfos[1].id
+        }
+        const addressInfo = {}
+        if (addresses && instrumentsInfo.id) {
+          addressInfo.id = addresses.id
+          addressInfo.name = addresses.name
+          addressInfo.phoneNumber = addresses.phoneNumber
+          addressInfo.addressDes = addresses.detailAddress
         }
-        const firstGoods = tempGoods[0]
-        const goodsInfo = {
-          orderNo: result.orderNo,
-          createTime: result.createTime,
-          wechatStatus: result.wechatStatus,
-          goods: tempGoods,
-          code: firstGoods.code || '',
-          refundOrderId: result.refundOrderId,
-          refundTime: result.refundTime,
-          refundAmount: this.formatPrice(result.refundAmount || 0, 'ALL'),
-          refundStyleStr
+        const memberInfo = {}
+        if (beneficiary) {
+          memberInfo.name = beneficiary.name
+          memberInfo.phone = beneficiary.phone
+          memberInfo.schoolInfo = beneficiary.provinceName + beneficiary.cityName + beneficiary.regionName + beneficiary.schoolAreaName + GRADE_ENUM[beneficiary.currentGradeNum] + beneficiary.currentClass + "班"
+        }
+        const orderInfo = {
+          createTime,
+          orderNo: this.data.orderNo
         }
         this.setData({
           goodsInfo,
-          status: result.wechatStatus
-        }, () => {
-          callback && typeof callback === 'function' && callback()
+          instrumentsInfo,
+          addressInfo,
+          memberInfo,
+          status: wechatStatus,
+          orderInfo
         })
-        if(result.wechatStatus != 'CLOSED' || result.wechatStatus != 'WAIT_PAY') {
-          const firstGoods = tempGoods[0]
-          if(firstGoods?.shortUrl) {
-            this.setData({
-              showCanvas: true
-            }, () => {
-              this.createQrCode(firstGoods?.shortUrl, 'canvasCode')
-            })
-          }
-        }
       }
     } catch (error) {
       console.log(error, "error");
     }
   },
-  // 格式化价格
-  formatPrice(price: number, type?: string) {
-    const amountStr = price.toFixed(2)
-    const [integerPart, decimalPart] = amountStr.split('.');
-    if(type === 'ALL') {
-      return amountStr
-    }
-    return {
-      integerPart,
-      decimalPart
-    }
-  },
   // 格式化类型
   formatPeriod(num: number, type: string) {
     const template: any = {
@@ -157,160 +148,192 @@ Page({
       MONTH: "月卡",
       YEAR: "年卡"
     }
-    if(type === "YEAR" && num >= 99) {
+    if (type === "YEAR" && num >= 99) {
       return '永久卡'
     }
     return num + template[type]
   },
-  onSubmit() {
-    wx.redirectTo({
-      url: '../index/index'
+  onCopy(e: { currentTarget: any }) {
+    wx.setClipboardData({
+      data: e.currentTarget.dataset.orderno,
+      success: () => {
+        wx.showToast({ title: '复制成功', icon: 'none' })
+      },
+      fail: () => {
+        wx.showToast({ title: '复制失败,请稍后再试', icon: 'none' })
+      }
     })
   },
-  setCanvasSize: function () {
-    const size = {} as any;
+  // 获取后台配置的支付方式
+  async queryPayType() {
     try {
-      const res = wx.getWindowInfo()
-      const scale = 750 / 300; //不同屏幕下canvas的适配比例;设计稿是750宽
-      const width = res.windowWidth / scale;
-      const height = width; //canvas画布为正方形
-      size.w = width;
-      size.h = height;
-    } catch (e) {
-      // Do something when catch error
-      console.log("获取设备信息失败" + e);
+      // wxlite_payment_service_provider
+      const { data } = await api_queryByParamName({
+        paramName: app.globalData.appId
+      });
+      if (data.code == 200) {
+        const paramValue = data.data.paramValue ? JSON.parse(data.data.paramValue) : {}
+        this.setData({
+          paymentType: paramValue.vendor,
+          paymentChannel: paramValue.channel
+        });
+      }
+    } catch (error) {
+      console.log(error, "error");
     }
-    return size;
   },
-  createQrCode(content: any, canvasId: any) {
-    const size = this.setCanvasSize();
-    drawQrcode({
-      width: size.w,
-      height: size.h,
-      canvasId: canvasId,
-      text: content,
-      callback: () => {
-        // 安卓机上不准确,生成的二维码无法扫描,加延时解决
-        setTimeout(() => {
-          wx.canvasToTempFilePath(
-            {
-              canvasId: canvasId,
-              success: (res) => {
-                this.setData({
-                  canvasImg: res.tempFilePath,
-                });
-              },
-            },
-            this
-          );
-        }, 0);
-      },
-    });
+  onPayError(message?: string) {
+    wx.hideLoading()
+    wx.showToast({
+      title: message || '支付取消',
+      icon: 'none'
+    })
   },
-  onTimeout() {
-    // 轮询10次查询订单状态
-    const goodsInfo = this.data.goodsInfo
-    const timerCount = this.data.timerCount
-    const timer = this.data.timer
-    if(goodsInfo.wechatStatus === 'WAIT_PAY' && timerCount <= 10) {
-      let count = timerCount
-      const tempT = setTimeout(async () => {
-        count += 1
-        await this.getDetail()
-        this.setData({
-          timer: tempT,
-          timerCount: count
-        }, () => {
-          this.onTimeout()
+  // 购买
+  async onSubmit() {
+    // 有乐器必须填收货信息
+    // if (this.data.instrumentsInfo.id && !this.data.addressInfo.id) {
+    //   wx.showToast({
+    //     title: "请填写收货信息",
+    //     icon: 'none'
+    //   })
+    //   this.setData({
+    //     isAddressInfoTip: true
+    //   })
+    //   return
+    // }
+    console.log(this.data.addressInfo)
+    wx.showLoading({
+      mask: true,
+      title: "订单提交中...",
+    });
+    try {
+      const { salePrice, shopId, name, id, orderNo } = this.data.goodsInfo
+      if (orderNo) {
+        const { data } = await api_userPaymentOrderUnpaid({
+          orderNo: orderNo,
+          paymentType: 'WECHAT_MINI'
         })
-      }, 3000);
-    } else {
-      clearTimeout(timer)
-    }
-  },
-  /** 申请退款 */
-  async cancelRefound() {
-    this.setData({
-      cancelRefoundStatus: true
-    }, async () => {
-      try {
-        const {data} = await api_userPaymentCancelRefund(this.data.goodsInfo.refundOrderId)
-        // console.log(data, 'data')
-        if(data.code == 200) {
-          wx.showToast({ title: '取消退款成功', icon: 'none' })
-          this.getDetail()
+        if (data.code === 200) {
+          const { paymentConfig, paymentType, orderNo } = data.data.paymentConfig
+          this.onExecutePay(paymentConfig, paymentType, orderNo)
         } else {
-          wx.showToast({ title: data.message, icon: 'none' })
+          this.onPayError()
         }
-        setTimeout(() => {
-          this.setData({
-            cancelRefoundStatus: false
+      } else {
+        const goodsInfos = [{
+          "goodsId": id,
+          "goodsNum": 1,
+          "goodsType": "ACTIVATION_CODE",
+          "paymentCashAmount": salePrice,
+          "paymentCouponAmount": 0
+        }]
+        // 乐器
+        if (this.data.instrumentsInfo.id) {
+          goodsInfos.push({
+            "goodsId": this.data.instrumentsInfo.id,
+            "goodsNum": 1,
+            "goodsType": "INSTRUMENTS",
+            "paymentCashAmount": this.data.instrumentsInfo.salePrice,
+            "paymentCouponAmount": 0
           })
-        }, 500);
-      } catch {}
-    })
-  },
-  /** 申请退款 */
-  useRefound() {
-    this.setData({
-      refoundStatus: true
-    })
-  },
-  changeRefoundStatus(e: {detail: any}) {
-    this.setData({
-      refoundStatus: e.detail
-    })
-  },
-  onRefoundComfirm() {
-    this.setData({
-      refoundStatus: false
-    })
-    // wx.navigateBack({
-    //   delta: 1
-    // })
-    this.getDetail()
+        }
+        const { data } = await api_executeOrder({
+          "orderType": "WECHAT_MINI",
+          "paymentType": this.data.paymentType,
+          "paymentCashAmount": salePrice + (this.data.instrumentsInfo.salePrice || 0),
+          "paymentCouponAmount": 0,
+          "shopId": shopId,
+          "openId": app.globalData.userInfo?.liteOpenid,
+          goodsInfos,
+          "orderName": name + (this.data.instrumentsInfo.name ? `+${this.data.instrumentsInfo.name}` : ""),
+          "orderDesc": name + (this.data.instrumentsInfo.name ? `+${this.data.instrumentsInfo.name}` : ""),
+          "receiveAddress": this.data.addressInfo.id || "",
+          "userBeneficiaryId": this.data.memberInfo.id
+        })
+        if (data.code === 200) {
+          const { paymentConfig, paymentType, orderNo } = data.data
+          this.onExecutePay(paymentConfig, paymentType, orderNo)
+        } else if (data.code === 5200) {
+          wx.hideLoading()
+          wx.showToast({
+            title: data.message,
+            icon: 'none'
+          })
+        } else if (data.code === 5435) {
+          wx.hideLoading()
+          wx.showToast({
+            title: data.message,
+            icon: 'none'
+          })
+          setTimeout(() => { wx.navigateBack() }, 1000)
+        } else {
+          this.onPayError()
+        }
+      }
+    } catch {
+      wx.hideLoading()
+    }
   },
-  onCopy(e: { currentTarget: any }) {
-    wx.setClipboardData({
-      data: e.currentTarget.dataset.orderno,
-      success: () => {
-        wx.showToast({title: '复制成功', icon: 'none'})
+  async onExecutePay(paymentConfig: any, paymentType: string, orderNo: string) {
+    wx.login({
+      success: async (wxres: any) => {
+        const res = await api_executePayment({
+          merOrderNo: paymentConfig.merOrderNo,
+          paymentChannel: this.data.paymentChannel || 'wx_lite', // 'wx_pub', //
+          paymentType,
+          userId: app.globalData.userInfo?.id,
+          code: wxres.code,
+          wxMiniAppId: app.globalData.appId
+          // code: '011yjYkl289aye4q2zml24UEWT3yjYkn',
+          // wxPubAppId: 'wxbde13f59d40cb4f2'
+        })
+        wx.hideLoading()
+        if (res.data.code === 200) {
+          this.onPay(paymentType, res.data.data.reqParams, orderNo)
+        } else {
+          this.onPayError(res.data.message)
+        }
       },
       fail: () => {
-        wx.showToast({title: '复制失败,请稍后再试', icon: 'none'})
+        this.onPayError()
       }
     })
   },
-  onActivation(e: { currentTarget: any  }) {
-    const code = e.currentTarget.dataset.code || ''
-    if(!code) {
-      wx.showToast({
-        title: '暂无法激活',
-        icon: 'none'
-      })
-      return
-    }
-    wx.navigateTo({
-      url: '../protocol/register?type=activation&code=' + code
-    })
-  },
-  onDownload() {
-    wx.saveImageToPhotosAlbum({
-      filePath: this.data.canvasImg,
-      success: () => { 
-        wx.showToast({
-          title: '保存成功',
-          icon: 'success',
-        });
+  onPay(paymentType: string, paymentConfig: any, orderNo: string) {
+    const isYeePay = paymentType.indexOf('yeepay') !== -1
+    const prePayInfo = isYeePay ? JSON.parse(paymentConfig.prePayTn)
+      : paymentConfig?.expend
+        ? JSON.parse(paymentConfig?.expend?.pay_info)
+        : paymentConfig
+    const that = this
+    wx.requestPayment({
+      timeStamp: prePayInfo.timeStamp,
+      nonceStr: prePayInfo.nonceStr,
+      package: prePayInfo.package ? prePayInfo.package : prePayInfo.packageValue,
+      paySign: prePayInfo.paySign,
+      signType: prePayInfo.signType ? prePayInfo.signType : 'MD5',
+      success() {
+        wx.showToast({ title: '支付成功', icon: 'success' });
+        setTimeout(() => {
+          that.getDetail()
+        }, 1000)
       },
-      fail: () => {
-        wx.showToast({
-          title: '保存失败',
-          icon: 'none',
-        });
+      fail(ressonInfo) {
+        console.log('支付失败', ressonInfo)
+        that.onPayError()
+        const goodsInfo = that.data.goodsInfo
+        goodsInfo.orderNo = orderNo
+        that.setData({
+          goodsInfo
+        })
       }
     })
   },
+
+  /**
+   * 用户点击右上角分享
+   */
   onShareAppMessage() {
     return {
       title: '音乐数字AI器乐工具',

+ 120 - 76
miniprogram/pages/orders/order-result.wxml

@@ -1,98 +1,142 @@
 <!--pages/orders/order-detail.wxml-->
 <view class="container">
-  <navigation-bar color="#fff" title="订单详情"></navigation-bar>
+  <navigation-bar title=""></navigation-bar>
 
-  <scroll-view class="record-list" type="list" scroll-y bindscrolltolower="loadMore">
-    <view class="scroll-container">
-      <view class="order-status" wx:if="{{statusList[status]}}">
-        <view class="status">
-          <!-- <image src="{{ statusList[status].logo }}"></image> -->
-          <text>{{ statusList[status].title }}</text>
-          <view class="btn-refound" bind:tap="useRefound"  wx:if="{{ goodsInfo.wechatStatus == 'WAIT_USE' && tabIdx == 5 }}">申请退款</view>
-        </view>
-        <view class="tips" wx:if="{{ statusList[status].content }}">{{ statusList[status].content }}</view>
+  <scroll-view class="record-list {{ status==='WAIT_PAY'?'waitList':'' }}" type="list" scroll-y>
+    <view class="order-status">
+      <view class="status">
+        <image src="{{ statusList[status].logo }}"></image>
+        <text>{{ statusList[status].title }}</text>
       </view>
+      <view class="tips">{{ statusList[status].content }}</view>
+    </view>
 
-      <view class="order-content">
-        <view class="item-content" wx:for="{{ goodsInfo.goods }}" wx:key="index">
-          <image class='goods-icon' src="{{ item.goodsUrl }}" mode="" />
-          <view class="goods-desc">
-            <view class="goodsInfo">
-              <view class="goods-name">{{ item.goodsName }}</view>
-              <view class="goods-price">
-                <text class="stuff">¥ </text>
-                <text class="priceZ">{{ item.integerPart }}</text>
-                <text class="priceF">.{{ item.decimalPart }}</text>
-              </view>
-              <!-- <view class="goods-price">¥ {{ item.originalPrice }}</view> -->
-            </view>
-            <view class="goods-type">
-              <view class="goods-card">{{ item.typeName }}</view>
-              <view class="goods-num">共 {{ item.goodsNum }} 件</view>
-            </view>
+    <view wx:if="{{ instrumentsInfo.id }}" class="memberBox {{isAddressInfoTip?'showMemberInfoTip':''}}">
+      <view class="memberCon">
+        <view class="memberInfoCon">
+          <view class="infoCon">
+            <image class="tip" src="./images/member.png" />
+            <text class="name">{{addressInfo.name}}</text>
+            <text class="phone">{{addressInfo.phoneNumber}}</text>
+          </view>
+          <view class="schoolInfoCon">
+            <text class="schoolInfo">收货地址</text><text class="schoolInfoDes">{{addressInfo.addressDes}}</text>
           </view>
         </view>
-        <view class="qrcode-section" wx:if="{{ (goodsInfo.wechatStatus == 'PAID' || goodsInfo.wechatStatus == 'WAIT_USE') && showCanvas }}">
-          <view class="qrcode-wrap {{goodsInfo.wechatStatus == 'WAIT_USE' ? '' : 'used' }}">
-            <image class="arrow arrow-left" src="./images/icon-arrow.png"></image>
-            <image class="arrow arrow-right" src="./images/icon-arrow.png"></image>
+        <!-- <image class="chevronImg" src="../index/images/chevron.png"></image> -->
+      </view>
+    </view>
 
-            <image src="{{canvasImg}}" mode="scaleToFill" class='my_draw_canvas' style="opacity: {{ goodsInfo.wechatStatus == 'PAID' ? 0.4 : 1 }};" show-menu-by-longpress="true"></image>
-            <view class="loader" wx:if="{{!canvasImg}}"></view>
+    <view class="order-content">
+      <view class="titTip">订单详情</view>
+      <view class="item-content first-item-content">
+        <image class='goods-icon' src="{{ goodsInfo.pic }}" mode="" />
+        <view class="goods-desc">
+          <view class="goodsInfo">
+            <view class="goods-name">{{ goodsInfo.name }}</view>
+            <view class="goods-price">
+              <text class="stuff">¥ </text>
+              <text class="priceZ">{{ my.formatValue(goodsInfo.originalPrice) }}</text>
+            </view>
           </view>
-          <view>
-            <view class="qrcode-text" wx:if="{{goodsInfo.wechatStatus == 'WAIT_USE'}}">扫描二维码或点击激活按钮使用</view>
-            <view class="qrcode-text used" wx:else>二维码已激活</view>
+          <view class="goods-type">
+            <view class="goods-card">{{ goodsInfo.typeName }}</view>
+            <view class="goods-num">x1</view>
           </view>
-          <view class="qrcode-btn--section" wx:if="{{goodsInfo.wechatStatus == 'WAIT_USE'}}">
-              <button class="download" disabled="{{ !canvasImg ? true : false }}" bind:tap="onDownload">下载二维码</button>
-              <button class="submit" disabled="{{ !canvasImg ? true : false }}"  bind:tap="onActivation" data-code="{{ goodsInfo.code }}">立即激活</button>
-            </view>
         </view>
       </view>
-
-      <canvas class='my_draw_canvas only_canvas' data-type="image" canvas-id='canvasCode' id="canvasCode"></canvas>
-
-      <view class="order-time">
-        <view class="order-item">
-          <view class="title">订单编号</view>
-          <view class="value">{{ goodsInfo.orderNo }}
-            <view class="copy" bind:tap="onCopy" data-orderno="{{goodsInfo.orderNo}}">复制</view></view>
-        </view>
-        <view class="order-item">
-          <view class="title">创建时间</view>
-          <view class="value">{{ goodsInfo.createTime }}</view>
+      <view wx:if="{{ instrumentsInfo.id }}" class="item-content">
+        <image class='goods-icon' src="{{ instrumentsInfo.pic }}" mode="" />
+        <view class="goods-desc">
+          <view class="goodsInfo">
+            <view class="goods-name">{{ instrumentsInfo.name }}</view>
+            <view class="goods-price">
+              <text class="stuff">¥ </text>
+              <text class="priceZ">{{ my.formatValue(instrumentsInfo.originalPrice) }}</text>
+            </view>
+          </view>
+          <view class="goods-type">
+            <view class="goods-card"></view>
+            <view class="goods-num">x1</view>
+          </view>
         </view>
       </view>
-
-      <view class="order-time" wx:if="{{ goodsInfo.wechatStatus == 'REFUNDED' || goodsInfo.wechatStatus == 'REFUNDING' }}">
-        <view class="order-item">
-          <view class="title">{{ goodsInfo.wechatStatus == 'REFUNDED' ? '退款时间' : '申请退款时间' }}</view>
-          <view class="value">{{ goodsInfo.refundTime }}</view>
+      <view wx:if="{{goodsInfo.originalPrice + (instrumentsInfo.originalPrice || 0) - (goodsInfo.salePrice + (instrumentsInfo.salePrice || 0)) > 0 }}" class="discountCon">
+        <view class="discountTip">
+          <image src="./images/discount.png"></image>
+          <text>优惠活动</text>
         </view>
-        <view class="order-item">
-          <view class="title">退款金额</view>
-          <view class="value red">¥{{ goodsInfo.refundAmount }}</view>
+        <view class="discount">
+          <text>-¥ </text>
+          <text>{{my.formatValue(goodsInfo.originalPrice + (instrumentsInfo.originalPrice || 0) - (goodsInfo.salePrice + (instrumentsInfo.salePrice || 0)))}}</text>
         </view>
-        <view class="order-item" wx:if="{{goodsInfo.wechatStatus == 'REFUNDED'}}">
-          <view class="title">退款路径</view>
-          <view class="value">{{ goodsInfo.refundStyleStr }}</view>
+      </view>
+      <view class="totalPic">
+        <text class="titPic">合计</text>
+        <text class="stuff">¥</text>
+        <numberDisplay number="{{ goodsInfo.salePrice + (instrumentsInfo.salePrice || 0) }}" />
+      </view>
+    </view>
+    <view class="order-content">
+      <view class="titTip">会员信息</view>
+      <view class="memberInfo">
+        <text>姓名</text>
+        <text>{{ memberInfo.name }}</text>
+      </view>
+      <view class="memberInfo">
+        <text>联系电话</text>
+        <text>{{ memberInfo.phone }}</text>
+      </view>
+      <view class="memberInfo">
+        <text>学校信息</text>
+        <text>{{ memberInfo.schoolInfo }}</text>
+      </view>
+    </view>
+    <view class="order-content">
+      <view class="titTip">订单信息</view>
+      <view class="memberInfo">
+        <text>订单编号</text>
+        <view class="orderInfoRight">
+          <text>{{ orderInfo.orderNo }}</text>
+          <view class="copy" bind:tap="onCopy" data-orderno="{{orderInfo.orderNo}}">复制</view>
         </view>
       </view>
+      <view class="memberInfo">
+        <text>下单时间</text>
+        <text>{{ orderInfo.createTime }}</text>
+      </view>
     </view>
+    <!-- <view class="order-time">
+      <view class="order-item">
+        <view class="title">订单号</view>
+        <view class="value">2133442226668</view>
+      </view>
+      <view class="order-item">
+        <view class="title">下单时间</view>
+        <view class="value">2023-07-12 18:12:45</view>
+      </view>
+    </view> -->
   </scroll-view>
 
-  <view class="order-btn" wx:if="{{ goodsInfo.wechatStatus != 'WAIT_PAY' }}">
-    <!-- <button type="primary" bind:tap="useRefound" wx:if="{{ goodsInfo.wechatStatus == 'WAIT_USE' }}">申请退款</button>
-    <block wx:else> -->
-      <button type="primary" bind:tap="cancelRefound" wx:if="{{ goodsInfo.wechatStatus == 'REFUNDING' }}" disabled="{{cancelRefoundStatus}}">取消退款</button>
-      <button type="primary" wx:else bind:tap="onSubmit">再次购买</button>
-    <!-- </block> -->
+  <view wx:if="{{status==='WAIT_PAY'}}" class="order-btn">
+    <view class="priceCon">
+      <view class="price">
+        <view class="desc">待支付:</view>
+        <text class="stuff">¥</text>
+        <numberDisplay number="{{ goodsInfo.salePrice + (instrumentsInfo.salePrice || 0) }}" />
+      </view>
+      <text wx:if="{{goodsInfo.originalPrice + (instrumentsInfo.originalPrice || 0) - (goodsInfo.salePrice + (instrumentsInfo.salePrice || 0)) > 0 }}" class="discountVal">已优惠 ¥{{my.formatValue(goodsInfo.originalPrice + (instrumentsInfo.originalPrice || 0) - (goodsInfo.salePrice + (instrumentsInfo.salePrice || 0)))}}</text>
+    </view>
+    <button type="primary" bind:tap="onSubmit">{{ '继续支付'  }}</button>
   </view>
-
-   <!-- 客服 -->
-   <service wx:if="{{serviceShow}}"></service>
-
-  <!-- 退费 -->
-  <apply-refound refoundStatus="{{ refoundStatus }}" goodsInfo="{{goodsInfo}}" bind:changeRefoundStatus="changeRefoundStatus" bind:onConfirm="onRefoundComfirm"></apply-refound>
-</view>
+  <!-- 客服 -->
+  <!-- <service wx:if="{{serviceShow}}"></service> -->
+</view>
+<wxs module="my">
+  var formatValue = function (value) {
+    return parseFloat(value).toFixed(2);
+  }
+  module.exports = {
+    formatValue: formatValue
+  }
+</wxs>

+ 7 - 0
miniprogram/pages/orders/order-result1.json

@@ -0,0 +1,7 @@
+{
+  "usingComponents": {
+    "navigation-bar": "/components/navigation-bar/navigation-bar",
+    "service": "/components/service/service",
+    "apply-refound": "/components/apply-refound/apply-refound"
+  }
+}

+ 384 - 0
miniprogram/pages/orders/order-result1.less

@@ -0,0 +1,384 @@
+/* pages/orders/order-detail.wxss */
+page {
+  height: 100vh;
+  display: flex;
+  flex-direction: column;
+  background: #F4F4F4;
+
+  &::before {
+    content: '';
+    position: absolute;
+    top: 0;
+    width: 100%;
+    height: 750rpx; 
+    background: linear-gradient(to bottom, #FB660A, #F5F6F7) #f4f4f4;
+    background-size: 750rpx;
+  }
+
+  .weui-navigation-bar__btn_goback {
+    background-color: #fff;
+  }
+}
+
+.scroll-container {
+  padding-bottom: 184rpx;
+}
+
+.order-status {
+  margin: 24rpx 26rpx 0;
+  // background-color: #FFFFFF;
+  border-radius: 20rpx;
+  padding: 24rpx 8rpx 24rpx 32rpx;
+  .status {
+    display: flex;
+    justify-content: space-between;
+    image {
+      width: 48rpx;
+      height: 48rpx;
+      margin-right: 16rpx;
+    }
+    .btn-refound {
+      text-align: center;
+      font-size: 26rpx;
+      color: rgba(255,255,255,0.7);
+      line-height: 34rpx;
+      height: 34rpx;
+      border-radius: 24rpx;
+      border: 1rpx solid rgba(255,255,255,0.7);
+      padding: 4rpx 12rpx;
+    }
+    
+    text {
+      font-weight: 600;
+      font-size: 48rpx;
+      color: #FFFFFF;
+      line-height: 48rpx;
+    }
+  }
+  .tips {
+    padding-top: 24rpx;
+    font-size: 28rpx;
+    color: #FFFFFF;
+    line-height: 40rpx;
+  }
+}
+
+.order-content {
+  margin: 32rpx 26rpx 0;
+  border-radius: 20rpx;
+  padding: 28rpx 24rpx;
+  display: flex;
+  flex-direction: column;
+  background-color: #FFFFFF;
+}
+.item-content {
+  display: flex;
+  width: 100%;
+  .goods-icon {
+    width: 140rpx;
+    height: 140rpx;
+    margin-right: 24rpx;
+    flex-shrink: 0;
+    border-radius: 6px;
+    overflow: hidden;
+  }
+
+  .goods-desc {
+    flex: 1 auto;
+    display: flex;
+    flex-direction: column;
+  }
+
+  .goodsInfo {
+    display: flex;
+    justify-content: space-between;
+    padding-top: 4rpx;
+    .goods-name {
+      flex: 1 auto;
+      white-space: nowrap;
+      overflow: hidden;
+      font-weight: 600;
+      font-size: 30rpx;
+      text-overflow: ellipsis;
+      max-width: 310rpx;
+    }
+    // .goods-price {
+    //   flex-shrink: 0;
+    //   font-family: DINAlternate, DINAlternate;
+    //   font-weight: bold;
+    //   font-size: 28rpx;
+    //   color: #131415;
+    //   line-height: 48rpx;
+    // }
+    .goods-price {
+      flex-shrink: 0;
+      font-family: DINAlternate, DINAlternate;
+      font-weight: bold;
+      font-size: 28rpx;
+      color: #131415;
+      line-height: 48rpx;
+
+      .stuff {
+        font-size: 28rpx;
+      }
+      .priceZ {
+        font-size: 36rpx;
+      }
+      .priceF {
+        font-size: 28rpx;
+      }
+    }
+  }
+
+  .goods-type {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding-top: 12rpx;
+    .goods-card {
+      border-radius: 6rpx;
+      font-size: 26rpx;
+      color: #131415;
+      line-height: 40rpx;
+    }
+    .goods-num {
+      font-size: 26rpx;
+      color: #999999;
+      line-height: 36rpx;
+    }
+  }
+}
+.only_canvas {
+  position: absolute;
+  left: -300rpx;
+  top: 0;
+  width: 300rpx;
+  height: 300rpx;
+}
+/* HTML: <div class="loader"></div> */
+.loader {
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  right: 0;
+  bottom: 0;
+  margin-top: -50rpx;
+  margin-left: -50rpx;
+  z-index: 9;
+  width: 100rpx;
+  aspect-ratio: 1;
+  border-radius: 50%;
+  background: 
+    radial-gradient(farthest-side,#E8E8E8 94%,#0000) top/8px 8px no-repeat,
+    conic-gradient(#0000 30%,#E8E8E8);
+  -webkit-mask: radial-gradient(farthest-side,#0000 calc(100% - 8px),#000 0);
+  animation: tempLoading 1s infinite linear;
+}
+@keyframes tempLoading{ 
+  100%{transform: rotate(1turn)}
+}
+.qrcode-section {
+  margin-top: 28rpx;
+  border-top: 2rpx solid #F0F0F0;
+  padding-top: 60rpx;
+  padding-bottom: 22rpx;
+  text-align: center;
+  display: flex;
+  flex-direction: column;
+  .qrcode-wrap {
+    position: relative;
+    margin: 0 auto;
+    // border: 3rpx solid #EDEDED;
+    padding: 34rpx;
+    display: inline-block;
+    font-size: 0;
+    background: url('https://oss.dayaedu.com/ktyq/1732529619848.png') no-repeat center;
+    background-size: contain;
+
+    &.used {
+      .arrow {
+        display: none;
+      }
+      background: url('https://oss.dayaedu.com/ktyq/1732530067551.png') no-repeat center;
+      background-size: contain;
+    }
+
+    .arrow {
+      position: absolute;
+      left: -126rpx;
+      top: 50%;
+      transform: translateY(-50%);
+      width: 106rpx;
+      height: 52rpx;
+    }
+    .arrow-right {
+      right: -126rpx;
+      left: auto;
+      transform: rotateY(180deg) translateY(-50%);
+    }
+  }
+  .my_draw_canvas {
+    width: 300rpx;
+    height: 300rpx;
+  }
+  .qrcode-text {
+    display: inline-block;
+    margin-top: 32rpx;
+    padding: 16rpx 32rpx 0;
+    font-weight: 500;
+    font-size: 28rpx;
+    color: #131415;
+    line-height: 40rpx;
+    // background: #FFE7C7;
+    border-radius: 36rpx;
+
+    &.used {
+      // background: #F2F2F2;
+      color: #AAAAAA;
+    }
+  }
+
+  .qrcode-btn--section {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    // padding-bottom: 22rpx;
+    padding-top: 32rpx;
+    button {
+      border-radius: 78rpx;
+      // line-height: 68rpx;
+      padding: 14rpx 30rpx;
+      width: auto;
+      border-radius: 68rpx;
+      font-weight: 500;
+      font-size: 28rpx;
+      margin: 0 16rpx;
+      min-width: 200rpx;
+      box-sizing: border-box;
+    }
+    .submit {
+      background: linear-gradient( 315deg, #FF4A00 0%, #FE8C00 100%);
+      color: #FFFFFF;
+    }
+    .download {
+      background: #FFEADE;
+      
+      color: #FF5000;
+    }
+  }
+}
+
+.order-time {
+  margin: 24rpx 26rpx 0;
+  border-radius: 20rpx;
+  padding: 0 24rpx;
+  background-color: #FFFFFF;
+
+  .order-item {
+    display: flex;
+    justify-content: space-between;
+    padding: 36rpx 0;
+    border-bottom: 2rpx solid #F0F0F0;
+    &:last-child {
+      border-bottom: none;
+    }
+    .title {
+      font-weight: 500;
+      font-size: 30rpx;
+      color: #131415;
+      line-height: 42rpx;
+    }
+    .value {
+      font-size: 30rpx;
+      color: #777777;
+      line-height: 42rpx;
+      display: flex;
+      &.red {
+        color: #FF5000;
+      }
+
+      .copy {
+        font-size: 30rpx;
+        color: #FF5000;
+        line-height: 42rpx;
+        display: flex;
+        align-items: center;
+        font-weight: 400;
+        padding-left: 16rpx;
+      }
+    }
+  }
+}
+
+.order-btn {
+  position: fixed;
+  bottom: 0;
+  left: 0;
+  width: 100%;
+  background-color: #FFFFFF;
+  padding: 20rpx 32rpx 58rpx;
+  display: flex;
+  justify-content: space-between;
+  box-sizing: border-box;
+
+  .orders {
+    display: flex;
+    flex-direction: column;
+    margin-right: 40rpx;
+    image {
+      width: 48rpx;
+      height: 48rpx;
+    }
+    text {
+      font-weight: 500;
+      font-size: 22rpx;
+      color: #131415;
+      line-height: 32rpx;
+      text-align: center;
+    }
+  }
+
+  .price {
+    display: flex;
+    align-items: center;
+
+    .desc {
+      font-weight: 500;
+      font-size: 28rpx;
+      color: #131415;
+      line-height: 40rpx;
+    }
+    .currentPrice {
+      font-weight: bold;
+      color: #FE2451;
+      font-family: DINAlternate, DINAlternate;
+      .stuff {
+        font-size: 32rpx;
+      }
+      .priceZ {
+        font-size: 56rpx;
+      }
+      .priceF {
+        font-size: 32rpx;
+      }
+    }
+  }
+
+  button {
+    margin: 0;
+    width: 100%;
+    background: linear-gradient( 315deg, #FF4A00 0%, #FE8C00 100%);
+    border-radius: 16rpx;
+    padding: 22rpx 84rpx;
+    font-weight: 500;
+    font-size: 32rpx;
+    color: #FFFFFF;
+    line-height: 44rpx;
+    &[disabled][type=primary] {
+      color: #fff;
+      background: linear-gradient( 315deg, #FF4A00 0%, #FE8C00 100%);
+      color: #FFFFFF;
+      opacity: 0.7;
+    }
+  }
+}

+ 321 - 0
miniprogram/pages/orders/order-result1.ts

@@ -0,0 +1,321 @@
+// pages/orders/order-detail.ts
+import drawQrcode from "../../utils/weapp.qrcode.esm";
+import { api_userPaymentCancelRefund, api_userPaymentOrderDetail } from "../../api/login";
+
+// 获取应用实例
+Page({
+  /**
+   * 页面的初始数据
+   */
+  data: {
+    status: 'WAIT_PAY',
+    statusList: {
+      WAIT_PAY: {
+        logo: './images/ing.png',
+        title: '待付款',
+        content: '为了确保您的订单顺利进行,请尽快完成支付'
+      },
+      PAID: {
+        logo: './images/success.png',
+        title: '已完成',
+        content: '登录「音乐数字课堂」APP,开启AI学练之旅~'
+      },
+      CLOSED: {
+        logo: './images/error.png',
+        title: '已取消',
+        content: '您的订单已被关闭,如有需要请重新下单'
+      },
+      WAIT_USE: {
+        logo: './images/wait.png',
+        title: '待使用',
+        content: '为了顺利使用,请尽快扫描下方二维码进行激活'
+      },
+      REFUNDING: {
+        logo: './images/refounding.png',
+        title: '退款中',
+        content: '您的订单正在退款中,预计7个工作日内审核完'
+      },
+      REFUNDED: {
+        logo: './images/refounded.png',
+        title: '已退款',
+        content: '您的订单已成功退款,感谢您的耐心等待'
+      }
+    },
+    timerCount: 0,
+    timer: null as any,
+    goodsInfo: {} as any,
+    tabIdx: 0, // 当前是从哪个tab来的
+    orderNo: "" as string,
+    showCanvas: false, // 是否显示二维码
+    canvasImg: "" as string,
+    serviceShow: true,
+    refoundStatus: false,
+    cancelRefoundStatus: false
+  },
+
+  /**
+   * 生命周期函数--监听页面加载
+   */
+  onLoad(options: any) {
+    if (options.orderNo) {
+      this.setData({
+        orderNo: options.orderNo,
+        tabIdx: options.tabIdx,
+      }, () => {
+        this.getDetail(this.onTimeout)
+      });
+    }
+  },
+  onShow() {
+    this.setData({
+      serviceShow: true
+    })
+    if(this.data.orderNo) {
+      this.getDetail(this.onTimeout)
+    }
+  },
+  onHide() {
+    this.setData({
+      serviceShow: false
+    })
+  },
+  async getDetail(callback?: any) {
+    try {
+      const { data } = await api_userPaymentOrderDetail(this.data.orderNo);
+      if (data.code == 200) {
+        const result = data.data || {}
+        const goodsInfos = result.goodsInfos || []
+        const tempGoods: any = []
+        goodsInfos.forEach((item: any) => {
+          const prices: any = this.formatPrice(item.paymentCashAmount)
+        
+          tempGoods.push({
+            ...item,
+            integerPart: prices.integerPart,
+            decimalPart: prices.decimalPart,
+            shortUrl: item.activationCodeInfo.shortUrl,
+            code: item.activationCodeInfo.activationCode,
+            originalPrice: this.formatPrice(item.paymentCashAmount, 'ALL'),
+            typeName: this.formatPeriod(item.activationCodeInfo?.times || 1, item.activationCodeInfo.type)
+          })
+        })
+        let refundStyleStr = ''
+        if(result.refundStyle === 'TURN_BACK') {
+          refundStyleStr = '原路返回'
+        } else if(result.refundStyle === 'OFFLINE') {
+          refundStyleStr = '线下'
+        }
+        const firstGoods = tempGoods[0]
+        const goodsInfo = {
+          orderNo: result.orderNo,
+          createTime: result.createTime,
+          wechatStatus: result.wechatStatus,
+          goods: tempGoods,
+          code: firstGoods.code || '',
+          refundOrderId: result.refundOrderId,
+          refundTime: result.refundTime,
+          refundAmount: this.formatPrice(result.refundAmount || 0, 'ALL'),
+          refundStyleStr
+        }
+        this.setData({
+          goodsInfo,
+          status: result.wechatStatus
+        }, () => {
+          callback && typeof callback === 'function' && callback()
+        })
+        if(result.wechatStatus != 'CLOSED' || result.wechatStatus != 'WAIT_PAY') {
+          const firstGoods = tempGoods[0]
+          if(firstGoods?.shortUrl) {
+            this.setData({
+              showCanvas: true
+            }, () => {
+              this.createQrCode(firstGoods?.shortUrl, 'canvasCode')
+            })
+          }
+        }
+      }
+    } catch (error) {
+      console.log(error, "error");
+    }
+  },
+  // 格式化价格
+  formatPrice(price: number, type?: string) {
+    const amountStr = price.toFixed(2)
+    const [integerPart, decimalPart] = amountStr.split('.');
+    if(type === 'ALL') {
+      return amountStr
+    }
+    return {
+      integerPart,
+      decimalPart
+    }
+  },
+  // 格式化类型
+  formatPeriod(num: number, type: string) {
+    const template: any = {
+      DAY: "天卡",
+      MONTH: "月卡",
+      YEAR: "年卡"
+    }
+    if(type === "YEAR" && num >= 99) {
+      return '永久卡'
+    }
+    return num + template[type]
+  },
+  onSubmit() {
+    wx.redirectTo({
+      url: '../index/index'
+    })
+  },
+  setCanvasSize: function () {
+    const size = {} as any;
+    try {
+      const res = wx.getWindowInfo()
+      const scale = 750 / 300; //不同屏幕下canvas的适配比例;设计稿是750宽
+      const width = res.windowWidth / scale;
+      const height = width; //canvas画布为正方形
+      size.w = width;
+      size.h = height;
+    } catch (e) {
+      // Do something when catch error
+      console.log("获取设备信息失败" + e);
+    }
+    return size;
+  },
+  createQrCode(content: any, canvasId: any) {
+    const size = this.setCanvasSize();
+    drawQrcode({
+      width: size.w,
+      height: size.h,
+      canvasId: canvasId,
+      text: content,
+      callback: () => {
+        // 安卓机上不准确,生成的二维码无法扫描,加延时解决
+        setTimeout(() => {
+          wx.canvasToTempFilePath(
+            {
+              canvasId: canvasId,
+              success: (res) => {
+                this.setData({
+                  canvasImg: res.tempFilePath,
+                });
+              },
+            },
+            this
+          );
+        }, 0);
+      },
+    });
+  },
+  onTimeout() {
+    // 轮询10次查询订单状态
+    const goodsInfo = this.data.goodsInfo
+    const timerCount = this.data.timerCount
+    const timer = this.data.timer
+    if(goodsInfo.wechatStatus === 'WAIT_PAY' && timerCount <= 10) {
+      let count = timerCount
+      const tempT = setTimeout(async () => {
+        count += 1
+        await this.getDetail()
+        this.setData({
+          timer: tempT,
+          timerCount: count
+        }, () => {
+          this.onTimeout()
+        })
+      }, 3000);
+    } else {
+      clearTimeout(timer)
+    }
+  },
+  /** 申请退款 */
+  async cancelRefound() {
+    this.setData({
+      cancelRefoundStatus: true
+    }, async () => {
+      try {
+        const {data} = await api_userPaymentCancelRefund(this.data.goodsInfo.refundOrderId)
+        // console.log(data, 'data')
+        if(data.code == 200) {
+          wx.showToast({ title: '取消退款成功', icon: 'none' })
+          this.getDetail()
+        } else {
+          wx.showToast({ title: data.message, icon: 'none' })
+        }
+        setTimeout(() => {
+          this.setData({
+            cancelRefoundStatus: false
+          })
+        }, 500);
+      } catch {}
+    })
+  },
+  /** 申请退款 */
+  useRefound() {
+    this.setData({
+      refoundStatus: true
+    })
+  },
+  changeRefoundStatus(e: {detail: any}) {
+    this.setData({
+      refoundStatus: e.detail
+    })
+  },
+  onRefoundComfirm() {
+    this.setData({
+      refoundStatus: false
+    })
+    // wx.navigateBack({
+    //   delta: 1
+    // })
+    this.getDetail()
+  },
+  onCopy(e: { currentTarget: any }) {
+    wx.setClipboardData({
+      data: e.currentTarget.dataset.orderno,
+      success: () => {
+        wx.showToast({title: '复制成功', icon: 'none'})
+      },
+      fail: () => {
+        wx.showToast({title: '复制失败,请稍后再试', icon: 'none'})
+      }
+    })
+  },
+  onActivation(e: { currentTarget: any  }) {
+    const code = e.currentTarget.dataset.code || ''
+    if(!code) {
+      wx.showToast({
+        title: '暂无法激活',
+        icon: 'none'
+      })
+      return
+    }
+    wx.navigateTo({
+      url: '../protocol/register?type=activation&code=' + code
+    })
+  },
+  onDownload() {
+    wx.saveImageToPhotosAlbum({
+      filePath: this.data.canvasImg,
+      success: () => { 
+        wx.showToast({
+          title: '保存成功',
+          icon: 'success',
+        });
+      },
+      fail: () => {
+        wx.showToast({
+          title: '保存失败',
+          icon: 'none',
+        });
+      }
+    })
+  },
+  onShareAppMessage() {
+    return {
+      title: '音乐数字AI器乐工具',
+      path: '/pages/index/index',
+      imageUrl: 'https://oss.dayaedu.com/ktyq/1733311074676.png'
+    }
+  }
+})

+ 98 - 0
miniprogram/pages/orders/order-result1.wxml

@@ -0,0 +1,98 @@
+<!--pages/orders/order-detail.wxml-->
+<view class="container">
+  <navigation-bar color="#fff" title="订单详情"></navigation-bar>
+
+  <scroll-view class="record-list" type="list" scroll-y bindscrolltolower="loadMore">
+    <view class="scroll-container">
+      <view class="order-status" wx:if="{{statusList[status]}}">
+        <view class="status">
+          <!-- <image src="{{ statusList[status].logo }}"></image> -->
+          <text>{{ statusList[status].title }}</text>
+          <view class="btn-refound" bind:tap="useRefound"  wx:if="{{ goodsInfo.wechatStatus == 'WAIT_USE' && tabIdx == 5 }}">申请退款</view>
+        </view>
+        <view class="tips" wx:if="{{ statusList[status].content }}">{{ statusList[status].content }}</view>
+      </view>
+
+      <view class="order-content">
+        <view class="item-content" wx:for="{{ goodsInfo.goods }}" wx:key="index">
+          <image class='goods-icon' src="{{ item.goodsUrl }}" mode="" />
+          <view class="goods-desc">
+            <view class="goodsInfo">
+              <view class="goods-name">{{ item.goodsName }}</view>
+              <view class="goods-price">
+                <text class="stuff">¥ </text>
+                <text class="priceZ">{{ item.integerPart }}</text>
+                <text class="priceF">.{{ item.decimalPart }}</text>
+              </view>
+              <!-- <view class="goods-price">¥ {{ item.originalPrice }}</view> -->
+            </view>
+            <view class="goods-type">
+              <view class="goods-card">{{ item.typeName }}</view>
+              <view class="goods-num">共 {{ item.goodsNum }} 件</view>
+            </view>
+          </view>
+        </view>
+        <view class="qrcode-section" wx:if="{{ (goodsInfo.wechatStatus == 'PAID' || goodsInfo.wechatStatus == 'WAIT_USE') && showCanvas }}">
+          <view class="qrcode-wrap {{goodsInfo.wechatStatus == 'WAIT_USE' ? '' : 'used' }}">
+            <image class="arrow arrow-left" src="./images/icon-arrow.png"></image>
+            <image class="arrow arrow-right" src="./images/icon-arrow.png"></image>
+
+            <image src="{{canvasImg}}" mode="scaleToFill" class='my_draw_canvas' style="opacity: {{ goodsInfo.wechatStatus == 'PAID' ? 0.4 : 1 }};" show-menu-by-longpress="true"></image>
+            <view class="loader" wx:if="{{!canvasImg}}"></view>
+          </view>
+          <view>
+            <view class="qrcode-text" wx:if="{{goodsInfo.wechatStatus == 'WAIT_USE'}}">扫描二维码或点击激活按钮使用</view>
+            <view class="qrcode-text used" wx:else>二维码已激活</view>
+          </view>
+          <view class="qrcode-btn--section" wx:if="{{goodsInfo.wechatStatus == 'WAIT_USE'}}">
+              <button class="download" disabled="{{ !canvasImg ? true : false }}" bind:tap="onDownload">下载二维码</button>
+              <button class="submit" disabled="{{ !canvasImg ? true : false }}"  bind:tap="onActivation" data-code="{{ goodsInfo.code }}">立即激活</button>
+            </view>
+        </view>
+      </view>
+
+      <canvas class='my_draw_canvas only_canvas' data-type="image" canvas-id='canvasCode' id="canvasCode"></canvas>
+
+      <view class="order-time">
+        <view class="order-item">
+          <view class="title">订单编号</view>
+          <view class="value">{{ goodsInfo.orderNo }}
+            <view class="copy" bind:tap="onCopy" data-orderno="{{goodsInfo.orderNo}}">复制</view></view>
+        </view>
+        <view class="order-item">
+          <view class="title">创建时间</view>
+          <view class="value">{{ goodsInfo.createTime }}</view>
+        </view>
+      </view>
+
+      <view class="order-time" wx:if="{{ goodsInfo.wechatStatus == 'REFUNDED' || goodsInfo.wechatStatus == 'REFUNDING' }}">
+        <view class="order-item">
+          <view class="title">{{ goodsInfo.wechatStatus == 'REFUNDED' ? '退款时间' : '申请退款时间' }}</view>
+          <view class="value">{{ goodsInfo.refundTime }}</view>
+        </view>
+        <view class="order-item">
+          <view class="title">退款金额</view>
+          <view class="value red">¥{{ goodsInfo.refundAmount }}</view>
+        </view>
+        <view class="order-item" wx:if="{{goodsInfo.wechatStatus == 'REFUNDED'}}">
+          <view class="title">退款路径</view>
+          <view class="value">{{ goodsInfo.refundStyleStr }}</view>
+        </view>
+      </view>
+    </view>
+  </scroll-view>
+
+  <view class="order-btn" wx:if="{{ goodsInfo.wechatStatus != 'WAIT_PAY' }}">
+    <!-- <button type="primary" bind:tap="useRefound" wx:if="{{ goodsInfo.wechatStatus == 'WAIT_USE' }}">申请退款</button>
+    <block wx:else> -->
+      <button type="primary" bind:tap="cancelRefound" wx:if="{{ goodsInfo.wechatStatus == 'REFUNDING' }}" disabled="{{cancelRefoundStatus}}">取消退款</button>
+      <button type="primary" wx:else bind:tap="onSubmit">再次购买</button>
+    <!-- </block> -->
+  </view>
+
+   <!-- 客服 -->
+   <service wx:if="{{serviceShow}}"></service>
+
+  <!-- 退费 -->
+  <apply-refound refoundStatus="{{ refoundStatus }}" goodsInfo="{{goodsInfo}}" bind:changeRefoundStatus="changeRefoundStatus" bind:onConfirm="onRefoundComfirm"></apply-refound>
+</view>

+ 2 - 1
miniprogram/pages/orders/orders.json

@@ -2,6 +2,7 @@
   "usingComponents": {
     "navigation-bar": "/components/navigation-bar/navigation-bar",
     "apply-refound": "/components/apply-refound/apply-refound",
-    "service": "/components/service/service"
+    "service": "/components/service/service",
+    "numberDisplay": "/components/numberDisplay/numberDisplay"
   }
 }

+ 88 - 70
miniprogram/pages/orders/orders.less

@@ -1,5 +1,5 @@
 /* pages/orders/orders.wxss */
-page {
+.container {
   height: 100vh;
   display: flex;
   flex-direction: column;
@@ -10,9 +10,9 @@ page {
     position: absolute;
     top: 0;
     width: 100%;
-    height: 334rpx; 
-    background: url('https://oss.dayaedu.com/ktyq/1732098006493.png') no-repeat top center;
-    background-size: contain;
+    height: 592rpx;
+    background: url("https://oss.dayaedu.com/ktyq/1738997023805.png") no-repeat;
+    background-size: 100% 100%;
   }
 }
 
@@ -33,34 +33,33 @@ page {
   display: flex;
   align-items: center;
   justify-content: space-between;
-  padding: 28rpx 30rpx 16rpx;
+  padding: 32rpx 60rpx 36rpx;
   position: relative;
+  font-weight: 600;
+  font-size: 30rpx;
+  color: rgba(0, 0, 0, 0.4);
+  line-height: 42rpx;
+
   >view {
-      font-size: 32rpx;
-      font-family: PingFangSC-Regular, PingFang SC;
-      font-weight: 500;
-      color: rgba(0, 0, 0, 0.4);
 
-      &.active {
-          font-size: 32rpx;
-          font-family: PingFangSC-Semibold, PingFang SC;
-          font-weight: 600;
-          color: #131415;
-          position: relative;
-          z-index: 2;
-
-          &::before {
-              content: "";
-              position: absolute;
-              left: 50%;
-              margin-left: -32rpx;
-              bottom: 0rpx;
-              z-index: -1;
-              width: 64rpx;
-              height: 14rpx;
-              background: linear-gradient( 90deg, #FF902B 0%, #FFDD84 100%);
-          }
+    &.active {
+      color: #000000;
+      position: relative;
+      z-index: 2;
+
+      &::before {
+        content: "";
+        position: absolute;
+        left: 50%;
+        transform: translateX(-50%);
+        bottom: -4rpx;
+        z-index: -1;
+        width: 32rpx;
+        height: 8rpx;
+        background: #000000;
+        border-radius: 4rpx;
       }
+    }
   }
 }
 
@@ -78,34 +77,51 @@ page {
   background: #FFFFFF;
   border-radius: 20rpx;
   margin: 20rpx 26rpx 0;
-  padding: 24rpx;
+  padding: 24rpx 24rpx 16rpx 24rpx;
+
+  &:first-child {
+    margin-top: 0;
+  }
 
   .item-top {
     display: flex;
     justify-content: space-between;
-    font-size: 28rpx;
-    line-height: 48rpx;
     padding-bottom: 24rpx;
-    
+
     .item-mid {
-      color: #999999;
+      font-weight: 400;
+      font-size: 26rpx;
+      color: #AAAAAA;
+      line-height: 36rpx;
     }
 
-    > text {
-      color: #777777;
+    >text {
+      font-weight: 600;
+      font-size: 28rpx;
+      color: #131415;
+      line-height: 40rpx;
     }
 
     .red {
-      color: #FF5000;
+      color: #FD4502;
+    }
+
+    .closed {
+      color: #AAAAAA;
     }
   }
 
   .item-content {
+    margin-bottom: 16rpx;
     display: flex;
+    justify-content: space-between;
+    .imgCon{
+      display: flex;
+    }
 
     .goods-icon {
-      width: 140rpx;
-      height: 140rpx;
+      width: 120rpx;
+      height: 120rpx;
       margin-right: 24rpx;
       flex-shrink: 0;
       border-radius: 6px;
@@ -113,7 +129,6 @@ page {
     }
 
     .goods-desc {
-      flex: 1 auto;
       display: flex;
       flex-direction: column;
     }
@@ -122,15 +137,6 @@ page {
       display: flex;
       justify-content: space-between;
       padding-top: 4rpx;
-      .goods-name {
-        flex: 1 auto;
-        white-space: nowrap;
-        overflow: hidden;
-        font-weight: 600;
-        font-size: 30rpx;
-        text-overflow: ellipsis;
-        max-width: 310rpx;
-      }
       .goods-price {
         flex-shrink: 0;
         font-family: DINAlternate, DINAlternate;
@@ -138,24 +144,30 @@ page {
         font-size: 28rpx;
         color: #131415;
         line-height: 48rpx;
-  
+
+
         .stuff {
-          font-size: 28rpx;
+          font-size: 32rpx;
+          margin-right: 4rpx;
         }
-        .priceZ {
-          font-size: 36rpx;
+
+        .numberDisplay--integer {
+          line-height: 52rpx;
+          font-size: 44rpx;
         }
-        .priceF {
-          font-size: 28rpx;
+
+        .numberDisplay--decimal {
+          font-size: 32rpx;
         }
       }
     }
 
     .goods-type {
       display: flex;
-      justify-content: space-between;
+      justify-content: flex-end;
       align-items: center;
-      padding-top: 12rpx;
+      padding-top: 10rpx;
+
       .goods-card {
         // background: #FEEDF0;
         border-radius: 6rpx;
@@ -164,17 +176,21 @@ page {
         line-height: 40rpx;
         // padding: 0 12rpx;
       }
+
       .goods-num {
         font-size: 26rpx;
         color: #999999;
         line-height: 36rpx;
+        text-align: right;
       }
     }
 
   }
 
   .item-footer {
-    padding-top: 8rpx;
+    border-top: 2rpx solid #EEEEEE;
+    margin-top:8rpx;
+    padding-top: 16rpx;
     display: flex;
     justify-content: space-between;
     align-items: center;
@@ -189,6 +205,7 @@ page {
         color: #FE2451;
         font-size: 28rpx;
       }
+
       .price {
         font-family: DINAlternate, DINAlternate;
         font-weight: bold;
@@ -202,18 +219,22 @@ page {
       margin: 0;
       border-radius: 12rpx;
       background: #fff;
-      border: 2rpx solid #DCDCDC;
+      //border: 2rpx solid #DCDCDC;
       font-weight: 500;
       font-size: 28rpx;
       color: #131415;
       width: auto;
-      padding: 14rpx 32rpx;
-      line-height: 40rpx;
+      padding: 0 24rpx;
+      line-height: 54rpx;
       box-sizing: content-box;
     }
+
     .sure {
-      background: linear-gradient( 315deg, #FF4A00 0%, #FE8C00 100%);
-      border-color: transparent;
+      background: #000000;
+      border-radius: 36rpx;
+      font-family: PingFangSC, PingFang SC;
+      font-weight: 500;
+      font-size: 26rpx;
       color: #FFFFFF;
     }
   }
@@ -224,21 +245,18 @@ page {
   left: 50%;
   top: 50%;
   transform: translate(-50%, -80%);
-  font-size: 32rpx;
-  font-family: PingFangSC-Regular, PingFang SC;
-  font-weight: 400;
-  color: #999999;
 
   image {
-    width: 410rpx;
-    height: 348rpx;
+    width: 375rpx;
+    height: 250rpx;
   }
 
   .empty-text {
+    font-weight: 400;
     font-size: 28rpx;
-    color: #aaa;
+    color: #AAAAAA;
     line-height: 40rpx;
     text-align: center;
-    padding-top: 24rpx;
+    padding-top: -24rpx;
   }
 }

+ 40 - 36
miniprogram/pages/orders/orders.ts

@@ -10,16 +10,16 @@ Page({
     tabList: [
       {
         id: 0,
-        label: "全部",
+        label: "全部订单",
       },
       {
         id: 1,
-        label: "待付款",
-      },
-      {
-        id: 2,
-        label: "待使用",
+        label: "待支付",
       },
+      // {
+      //   id: 2,
+      //   label: "待使用",
+      // },
       {
         id: 3,
         label: "已完成",
@@ -28,10 +28,10 @@ Page({
         id: 4,
         label: "已取消",
       },
-      {
-        id: 5,
-        label: "售后",
-      },
+      // {
+      //   id: 5,
+      //   label: "售后",
+      // },
       // {
       //   id: 6,
       //   label: "已退款",
@@ -96,6 +96,7 @@ Page({
     try {
       // @ApiModelProperty("订单状态 WAIT_PAY:待付款,WAIT_USE:待使用,SUCCESS:已完成,CLOSE:已取消")
       const { data } = await api_studentOrderPage({
+        "version": "V2",
         openId: app.globalData.userInfo?.liteOpenid,
         page: currentPage,
         rows: this.data.rows,
@@ -116,7 +117,7 @@ Page({
           })
           item.studentPaymentOrderDetails = studentPaymentOrderDetails
         });
-        
+
         const newList = this.data.recordList.concat(rows);
         this.setData(
           {
@@ -128,7 +129,7 @@ Page({
       } else {
         wx.hideLoading();
       }
-    } catch(e) {
+    } catch (e) {
       console.log(e, 'e')
       wx.hideLoading()
     }
@@ -137,7 +138,7 @@ Page({
   formatOrderStatus(status: string) {
     // 订单状态 WAIT_PAY:待付款,  WAIT_USE:待使用, SUCCESS:已完成, CLOSE:已取消
     const template: any = {
-      WAIT_PAY: '待付',
+      WAIT_PAY: '待付',
       WAIT_USE: '待使用',
       PAID: '已完成',
       CLOSED: '已取消',
@@ -150,7 +151,7 @@ Page({
   formatPrice(price: number, type?: string) {
     const amountStr = price.toFixed(2)
     const [integerPart, decimalPart] = amountStr.split('.');
-    if(type === 'ALL') {
+    if (type === 'ALL') {
       return amountStr
     }
     return {
@@ -160,7 +161,7 @@ Page({
   },
   // 格式化类型
   formatPeriod(num: number, type: string) {
-    if(!num || !type) {
+    if (!num || !type) {
       return ''
     }
     const template: any = {
@@ -168,7 +169,7 @@ Page({
       MONTH: "月卡",
       YEAR: "年卡"
     }
-    if(type === "YEAR" && num >= 99) {
+    if (type === "YEAR" && num >= 99) {
       return '永久卡'
     }
     return num + template[type]
@@ -196,7 +197,7 @@ Page({
   onPay(e: any) {
     const { dataset } = e.currentTarget
     const item: any = this.data.recordList.find((item: any) => item.id === dataset.id)
-    if(item) {
+    if (item) {
       this.onSubmit({
         orderNo: item.orderNo
       })
@@ -209,13 +210,16 @@ Page({
   },
   onDetail(e: any) {
     const { dataset } = e.currentTarget
-    if(dataset.wechatstatus === "WAIT_PAY") {
-      this.onSubmit({orderNo: dataset.orderno})
-    } else {
-      wx.navigateTo({
-        url: `../orders/order-result?orderNo=${dataset.orderno}&tabIdx=${this.data.tabIdx}`
-      })
-    }
+    wx.navigateTo({
+      url: `../orders/order-result?orderNo=${dataset.orderno}&tabIdx=${this.data.tabIdx}`
+    })
+    // if (dataset.wechatstatus === "WAIT_PAY") {
+    //   this.onSubmit({ orderNo: dataset.orderno })
+    // } else {
+    //   wx.navigateTo({
+    //     url: `../orders/order-result?orderNo=${dataset.orderno}&tabIdx=${this.data.tabIdx}`
+    //   })
+    // }
   },
   // 购买
   async onSubmit(goodsInfo: any) {
@@ -225,7 +229,7 @@ Page({
     });
     try {
       const { orderNo } = goodsInfo
-      const {data} = await api_userPaymentOrderUnpaid({
+      const { data } = await api_userPaymentOrderUnpaid({
         orderNo: orderNo,
         paymentType: 'WECHAT_MINI'
       })
@@ -239,19 +243,19 @@ Page({
       wx.hideLoading()
     }
   },
-  async onExecutePay( paymentConfig: any, paymentType: string, orderNo: string) {
+  async onExecutePay(paymentConfig: any, paymentType: string, orderNo: string) {
     wx.login({
       success: async (wxres: any) => {
         const res = await api_executePayment({
           merOrderNo: paymentConfig.merOrderNo,
-          paymentChannel: this.data.paymentChannel || 'wx_lite', 
+          paymentChannel: this.data.paymentChannel || 'wx_lite',
           paymentType,
           userId: app.globalData.userInfo?.id,
           code: wxres.code,
           wxMiniAppId: app.globalData.appId
         })
         wx.hideLoading()
-        if(res.data.code === 200) {
+        if (res.data.code === 200) {
           this.onPaying(paymentType, res.data.data.reqParams, orderNo)
         } else {
           this.onPayError(res.data.message)
@@ -314,19 +318,19 @@ Page({
     const { dataset } = e.currentTarget
     const item: any = this.data.recordList.find((item: any) => item.id === dataset.id)
     console.log(dataset, item, 'item')
-    if(!item) {
+    if (!item) {
       return
     }
 
-    if(item.wechatStatus === "REFUNDING") {
+    if (item.wechatStatus === "REFUNDING") {
       this.setData({
         cancelRefoundStatus: true
       }, async () => {
         try {
           const refundOrderId = item.refundOrderId
-          const {data} = await api_userPaymentCancelRefund(refundOrderId)
+          const { data } = await api_userPaymentCancelRefund(refundOrderId)
           console.log(data, 'data')
-          if(data.code == 200) {
+          if (data.code == 200) {
             wx.showToast({ title: '你已成功取消退款', icon: 'none' })
             this.onRefoundComfirm()
           } else {
@@ -335,16 +339,16 @@ Page({
               cancelRefoundStatus: false
             })
           }
-        } catch {}
+        } catch { }
       })
-      
+
     } else {
       const { orderNo, studentPaymentOrderDetails } = item
       const goodsInfo: any = {
         orderNo,
         goods: []
       }
-      if(Array.isArray(studentPaymentOrderDetails)) {
+      if (Array.isArray(studentPaymentOrderDetails)) {
         studentPaymentOrderDetails.forEach((item: any) => {
           goodsInfo.goods.push({
             ...item,
@@ -360,7 +364,7 @@ Page({
       })
     }
   },
-  changeRefoundStatus(e: {detail: any}) {
+  changeRefoundStatus(e: { detail: any }) {
     this.setData({
       refoundStatus: e.detail,
       cancelRefoundStatus: false,

+ 31 - 25
miniprogram/pages/orders/orders.wxml

@@ -13,56 +13,62 @@
         <view class="list-item-group">
           <view class="list-item" wx:for="{{recordList}}" wx:key="index" data-orderno="{{item.orderNo}}" data-wechatstatus="{{item.wechatStatus}}" bind:tap="onDetail">
             <view class="item-top">
-              <view class="item-mid">订单编号:{{ item.orderNo }}</view>
-              <text class="{{ item.wechatStatus == 'WAIT_PAY' || item.wechatStatus == 'WAIT_USE' || item.wechatStatus == 'REFUNDING' ? 'red' : '' }}">{{ item.statusName }}</text>
+              <text class="{{ item.wechatStatus == 'WAIT_PAY' || item.wechatStatus == 'WAIT_USE' || item.wechatStatus == 'REFUNDING' ? 'red' : item.wechatStatus === 'CLOSED' ? 'closed' : '' }}">{{ item.statusName }}</text>
+              <view class="item-mid">{{ item.createTime }}</view>
             </view>
-            <view class="item-content" wx:for="{{item.studentPaymentOrderDetails}}" wx:key="studentIndex">
-              <image class='goods-icon' src="{{item.goodsUrl}}" mode="" />
+            <view class="item-content">
+              <view class="imgCon">
+                <image class='goods-icon' wx:for="{{item.studentPaymentOrderDetails}}" wx:key="studentIndex" src="{{item.goodsUrl}}" mode="" />
+              </view>
               <view class="goods-desc">
                 <view class="goodsInfo">
-                  <view class="goods-name">
-                    <text class="{{ outerItem.wechatStatus == 'WAIT_PAY' || outerItem.wechatStatus == 'WAIT_USE' ? 'red' : '' }}">{{ outerItem.statusName }}</text>
-                    {{item.goodsName}}
-                  </view>
                   <view class="goods-price">
                     <text class="stuff">¥ </text>
-                    <text class="priceZ">{{ item.integerPart }}</text>
-                    <text class="priceF">.{{ item.decimalPart }}</text>
+                    <numberDisplay number="{{ my.sumArray(item.studentPaymentOrderDetails, 'paymentCashAmount') }}" />
                   </view>
-                  <!-- <view class="goods-price">¥ {{(item.originalPrice)}}</view> -->
                 </view>
                 <view class="goods-type">
-                  <view class="goods-card" wx:if="{{ item.typeName }}">{{item.typeName}}</view>
-                  <view class="goods-num">共 {{ item.goodsNum }} 件</view>
+                  <view class="goods-num">共 {{ item.studentPaymentOrderDetails.length }} 件</view>
                 </view>
               </view>
             </view>
-            <view class="item-footer">
+            <view wx:if="{{ item.wechatStatus == 'WAIT_PAY' }}" class="item-footer">
               <view class="order-price">
                 <!-- 订单金额:<text class="price-first">¥ </text><text class="price">{{item.amount}}</text> -->
               </view>
-              <block wx:if="{{ item.wechatStatus == 'REFUNDING' || (item.wechatStatus == 'WAIT_USE' && tabIdx == 5) }}" wx:key="block">
-                <button wx:if="{{ item.wechatStatus == 'REFUNDING' }}" type="primary" wx:if="{{ item.wechatStatus == 'REFUNDING' }}"  catch:tap="onRefounded" data-id="{{item.id}}" disabled="{{ cancelRefoundStatus }}">取消退款</button>
+              <!-- <block wx:if="{{ item.wechatStatus == 'REFUNDING' || (item.wechatStatus == 'WAIT_USE' && tabIdx == 5) }}" wx:key="block">
+                <button wx:if="{{ item.wechatStatus == 'REFUNDING' }}" type="primary" wx:if="{{ item.wechatStatus == 'REFUNDING' }}" catch:tap="onRefounded" data-id="{{item.id}}" disabled="{{ cancelRefoundStatus }}">取消退款</button>
                 <button wx:else type="primary" catch:tap="onRefounded" data-id="{{item.id}}" disabled="{{ cancelRefoundStatus }}">申请退款</button>
-              </block>
-              <block wx:else wx:key="block">
-                <button class="sure" type="primary" wx:if="{{ item.wechatStatus == 'WAIT_PAY' }}"  catch:tap="onPay" data-id="{{item.id}}">继续支付</button>
-                <button type="primary" wx:else catch:tap="onOne" data-id="{{item.id}}">再次购买</button>
-              </block>
+              </block> -->
+              <!-- <block wx:else wx:key="block"> -->
+                <button class="sure" type="primary" catch:tap="onPay" data-id="{{item.id}}">继续支付</button>
+                <!-- <button type="primary" wx:else catch:tap="onOne" data-id="{{item.id}}">再次购买</button> -->
+              <!-- </block> -->
             </view>
           </view>
         </view>
       </block>
       <block wx:else>
         <view class="empty-box">
-          <image src="https://oss.dayaedu.com/ktyq/1732697111162.png"></image>
+          <image src="https://oss.dayaedu.com/ktyq/1739278149891.png"></image>
           <view class="empty-text">暂无订单</view>
         </view>
       </block>
     </scroll-view>
   </view>
   <!-- 客服 -->
-  <service wx:if="{{serviceShow}}"></service>
+  <!-- <service wx:if="{{serviceShow}}"></service> -->
   <!-- 申请退款 -->
-  <apply-refound refoundStatus="{{ refoundStatus }}" goodsInfo="{{goodsInfo}}" bind:changeRefoundStatus="changeRefoundStatus" bind:onConfirm="onRefoundComfirm"></apply-refound>
-</view>
+  <!-- <apply-refound refoundStatus="{{ refoundStatus }}" goodsInfo="{{goodsInfo}}" bind:changeRefoundStatus="changeRefoundStatus" bind:onConfirm="onRefoundComfirm"></apply-refound> -->
+</view>
+
+<wxs module="my">
+  var sumArray = function (value, key) {
+    return value.reduce(function(num, item){
+      return item[key] + num
+    }, 0)
+  }
+  module.exports = {
+    sumArray: sumArray
+  }
+</wxs>

+ 1 - 1
miniprogram/plugins/request.ts

@@ -58,7 +58,7 @@ module.exports = function (options: any) {
             }, 100);
           }
           reject(res.data.msg);
-        } else if (res.data.code == 403) {
+        } else if (res.data.code == 5000) {
           wx.setStorageSync("token", "");
           if(!hideLoading) {
             setTimeout(() => {

+ 6 - 1
node_modules/.package-lock.json

@@ -1,9 +1,14 @@
 {
   "name": "miniprogram-ts-less-quickstart",
   "version": "1.0.0",
-  "lockfileVersion": 2,
+  "lockfileVersion": 3,
   "requires": true,
   "packages": {
+    "node_modules/@vant/weapp": {
+      "version": "1.11.7",
+      "resolved": "https://registry.npmmirror.com/@vant/weapp/-/weapp-1.11.7.tgz",
+      "integrity": "sha512-Rwn9BBnb4kHSV4XmvBicwtd42J+amEUfnFDcXJsGNPNX4a9c/DoT6YLsm4X1wB2+sQbdiQsbFBLAvGRBxCkD8g=="
+    },
     "node_modules/miniprogram-api-typings": {
       "version": "2.12.0",
       "resolved": "https://registry.npmmirror.com/miniprogram-api-typings/-/miniprogram-api-typings-2.12.0.tgz",

+ 13 - 0
package-lock.json

@@ -7,10 +7,18 @@
     "": {
       "name": "miniprogram-ts-less-quickstart",
       "version": "1.0.0",
+      "dependencies": {
+        "@vant/weapp": "^1.11.7"
+      },
       "devDependencies": {
         "miniprogram-api-typings": "^2.8.3-1"
       }
     },
+    "node_modules/@vant/weapp": {
+      "version": "1.11.7",
+      "resolved": "https://registry.npmmirror.com/@vant/weapp/-/weapp-1.11.7.tgz",
+      "integrity": "sha512-Rwn9BBnb4kHSV4XmvBicwtd42J+amEUfnFDcXJsGNPNX4a9c/DoT6YLsm4X1wB2+sQbdiQsbFBLAvGRBxCkD8g=="
+    },
     "node_modules/miniprogram-api-typings": {
       "version": "2.12.0",
       "resolved": "https://registry.npmmirror.com/miniprogram-api-typings/-/miniprogram-api-typings-2.12.0.tgz",
@@ -19,6 +27,11 @@
     }
   },
   "dependencies": {
+    "@vant/weapp": {
+      "version": "1.11.7",
+      "resolved": "https://registry.npmmirror.com/@vant/weapp/-/weapp-1.11.7.tgz",
+      "integrity": "sha512-Rwn9BBnb4kHSV4XmvBicwtd42J+amEUfnFDcXJsGNPNX4a9c/DoT6YLsm4X1wB2+sQbdiQsbFBLAvGRBxCkD8g=="
+    },
     "miniprogram-api-typings": {
       "version": "2.12.0",
       "resolved": "https://registry.npmmirror.com/miniprogram-api-typings/-/miniprogram-api-typings-2.12.0.tgz",

+ 3 - 0
package.json

@@ -8,5 +8,8 @@
   "license": "",
   "devDependencies": {
     "miniprogram-api-typings": "^2.8.3-1"
+  },
+  "dependencies": {
+    "@vant/weapp": "^1.11.7"
   }
 }

+ 9 - 3
project.config.json

@@ -17,11 +17,17 @@
     "minified": false,
     "enhance": true,
     "showShadowRootInWxmlPanel": false,
-    "packNpmRelationList": [],
     "ignoreUploadUnusedFiles": true,
     "compileHotReLoad": false,
     "skylineRenderEnable": true,
-    "es6": true
+    "es6": true,
+    "packNpmManually": true,
+    "packNpmRelationList": [
+      {
+        "packageJsonPath": "./package.json",
+        "miniprogramNpmDistDir": "./miniprogram/"
+      }
+    ]
   },
   "simulatorType": "wechat",
   "simulatorPluginLibVersion": {},
@@ -36,6 +42,6 @@
     "ignore": [],
     "include": []
   },
-  "appid": "wx75545e30eed207ef",
+  "appid": "wx524b61f5bec60655",
   "projectname": "orchestra-music-activation"
 }

+ 1 - 1
project.private.config.json

@@ -4,7 +4,7 @@
   "setting": {
     "compileHotReLoad": true
   },
-  "libVersion": "3.6.6",
+  "libVersion": "3.7.7",
   "condition": {
     "miniprogram": {
       "list": [

+ 5 - 1
tsconfig.json

@@ -16,7 +16,11 @@
     "noUnusedParameters": true,
     "strict": true,
     "strictPropertyInitialization": true,
-    "lib": ["ES2020"],
+    "types": ["miniprogram-api-typings"],
+    "paths": {
+      "@vant/weapp/*": ["path/to/node_modules/@vant/weapp/dist/*"]
+    },
+    "lib": ["ES6"],
     "typeRoots": [
       "./typings"
     ]