From 308aeeafb5daf530a2da96c2266adacabe97c324 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=94=90=E6=98=8E=E6=98=8E?= <970899069@qq.com> Date: Mon, 28 Aug 2023 17:51:33 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E9=80=80=E8=B4=A7=E6=B5=81?= =?UTF-8?q?=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/index.js | 6 +- api/interfaces/refund.js | 50 ++++++++++++++++ app.json | 4 +- pages/idcard/idcard.js | 5 +- pages/mall/confirm/confirm.js | 3 + pages/order/details/details.js | 7 ++- pages/order/details/details.wxml | 2 +- pages/order/details/details.wxss | 2 +- pages/order/index.js | 17 +++++- pages/order/index.wxml | 3 +- pages/order/index.wxss | 6 +- pages/refund/aftersale/aftersale.js | 82 ++++++++++++++++++++++++++ pages/refund/aftersale/aftersale.json | 4 ++ pages/refund/aftersale/aftersale.wxml | 39 ++++++++++++ pages/refund/aftersale/aftersale.wxss | 34 +++++++++++ pages/refund/refund.js | 50 ++++++++++++++++ pages/refund/refund.json | 4 ++ pages/refund/refund.wxml | 35 +++++++++++ pages/refund/refund.wxss | 23 ++++++++ pages/user/index.wxml | 21 ++++--- pages/user/index.wxss | 4 ++ static/icons/add_gray.png | Bin 0 -> 4242 bytes static/icons/copy_icon.png | Bin 0 -> 2341 bytes static/imgs/tool_08.png | Bin 2507 -> 3213 bytes 24 files changed, 380 insertions(+), 21 deletions(-) create mode 100644 api/interfaces/refund.js create mode 100644 pages/refund/aftersale/aftersale.js create mode 100644 pages/refund/aftersale/aftersale.json create mode 100644 pages/refund/aftersale/aftersale.wxml create mode 100644 pages/refund/aftersale/aftersale.wxss create mode 100644 pages/refund/refund.js create mode 100644 pages/refund/refund.json create mode 100644 pages/refund/refund.wxml create mode 100644 pages/refund/refund.wxss create mode 100644 static/icons/add_gray.png create mode 100644 static/icons/copy_icon.png diff --git a/api/index.js b/api/index.js index 9a23d9e..774d756 100644 --- a/api/index.js +++ b/api/index.js @@ -33,6 +33,9 @@ import idcard from "./interfaces/idcard" // 身份认证 import withdraw from "./interfaces/withdraw" +// 售后服务 +import refund from "./interfaces/refund" + export default { auth, bank, @@ -43,5 +46,6 @@ export default { user, pay, idcard, - withdraw + withdraw, + refund } \ No newline at end of file diff --git a/api/interfaces/refund.js b/api/interfaces/refund.js new file mode 100644 index 0000000..142e0a9 --- /dev/null +++ b/api/interfaces/refund.js @@ -0,0 +1,50 @@ + /* + * 手太欠 + * 愿这世界都如故事里一样 美好而动人~ +*/ + +import { req } from "../request" + +// 售后服务 +const list = data => req({ + url : "mall/refunds", + data +}) + +// 用户退货 +const deliver = (refund, data) => req({ + url: "mall/refunds/" + refund + "/deliver", + method: "POST", + data +}) + +// 退货详情 +const info = refund => req({ + url: "mall/refunds/" + refund +}) + +// 退货日志 +const log = refund => req({ + url: "mall/refunds/" + refund + "/logs" +}) + +// 申请售后前置 +const refundPreposition = id => req({ + url: "mall/orders/" + id + "/refund" +}) + +// 提交退货 +const submitRefund = (id, data) => req({ + url : "mall/orders/" + id + "/refund", + method : "POST", + data +}) + +export default ({ + list, + deliver, + info, + log, + refundPreposition, + submitRefund +}) \ No newline at end of file diff --git a/app.json b/app.json index c5eaef4..caef518 100644 --- a/app.json +++ b/app.json @@ -32,7 +32,9 @@ "pages/idcard/eSign/eSign", "pages/withdraw/withdraw", "pages/pay/success/success", - "pages/resetPassword/resetPassword" + "pages/resetPassword/resetPassword", + "pages/refund/refund", + "pages/refund/aftersale/aftersale" ], "window": { "backgroundTextStyle": "light", diff --git a/pages/idcard/idcard.js b/pages/idcard/idcard.js index 2944101..3b42b86 100644 --- a/pages/idcard/idcard.js +++ b/pages/idcard/idcard.js @@ -44,6 +44,7 @@ Page({ created_at : data.created_at, verified : data.verified, need_sign : data.need_sign, + address : data.address } }) } @@ -84,9 +85,9 @@ Page({ back_card : this.data.back.path, address }).then(res => { - let { name, id_card, created_at, verified, need_sign } = res.data + let { name, id_card, created_at, verified, need_sign, address } = res.data this.setData({ - info : { name, id_card, created_at, verified, need_sign }, + info : { name, id_card, created_at, verified, need_sign, address }, procedure : need_sign ? 2 : 3, isSignContract : data.is_sign_contract, }) diff --git a/pages/mall/confirm/confirm.js b/pages/mall/confirm/confirm.js index 460e935..fae8780 100644 --- a/pages/mall/confirm/confirm.js +++ b/pages/mall/confirm/confirm.js @@ -72,6 +72,9 @@ Page({ qty : this.data.goodsQty, address_id : this.data.addressId }).then(res => { + + console.log(res) + wx.redirectTo({ url: '/pages/pay/index?params=' + encodeURIComponent(JSON.stringify(res.data)) }) diff --git a/pages/order/details/details.js b/pages/order/details/details.js index 94d8857..8e34f01 100644 --- a/pages/order/details/details.js +++ b/pages/order/details/details.js @@ -54,8 +54,13 @@ Page({ * 支付订单 */ payClick() { + let payData = { + order_id : this.data.goodsData.order_id, + order_no : this.data.goodsData.order_no, + order_type : this.data.goodsData.order_type + } wx.navigateTo({ - url: '/pages/pay/index?order_no=' + this.data.goodsData.order_no + '&total=' + this.data.goodsData.total + url: '/pages/pay/index?params=' + encodeURIComponent(JSON.stringify(payData)) }) }, diff --git a/pages/order/details/details.wxml b/pages/order/details/details.wxml index 92cb4b5..79bd7ea 100644 --- a/pages/order/details/details.wxml +++ b/pages/order/details/details.wxml @@ -1,7 +1,7 @@ - + 订单编号 diff --git a/pages/order/details/details.wxss b/pages/order/details/details.wxss index 1d6d40e..32c73df 100644 --- a/pages/order/details/details.wxss +++ b/pages/order/details/details.wxss @@ -215,7 +215,7 @@ page { } .reserve-status { - color: #ff8100 + color: #da2b54 } /* 底部菜单 */ diff --git a/pages/order/index.js b/pages/order/index.js index 8e1e0f7..018ea55 100644 --- a/pages/order/index.js +++ b/pages/order/index.js @@ -60,8 +60,14 @@ Page({ * 支付订单 */ payClick(e) { + let { item } = e.currentTarget.dataset + let data = { + order_id : item.order_id, + order_no : item.order_no, + order_type : item.order_type + } wx.navigateTo({ - url: '/pages/pay/index?order_no=' + e.currentTarget.dataset.order_no + '&total=' + e.currentTarget.dataset.total + url: '/pages/pay/index?params=' + encodeURIComponent(JSON.stringify(data)) }) }, @@ -137,5 +143,14 @@ Page({ // 获取订单列表 this.listInfo(pageNumber); } + }, + /** + * 申请售后 + */ + signRefund(e){ + let { order_no } = e.currentTarget.dataset + wx.navigateTo({ + url: "/pages/refund/aftersale/aftersale?id=" + order_no, + }) } }) diff --git a/pages/order/index.wxml b/pages/order/index.wxml index 55849c2..f80f697 100644 --- a/pages/order/index.wxml +++ b/pages/order/index.wxml @@ -44,8 +44,9 @@ 更多 - 立即付款 + 立即付款 签收订单 + 申请退货 查看详情 diff --git a/pages/order/index.wxss b/pages/order/index.wxss index fb61ea3..fc37232 100644 --- a/pages/order/index.wxss +++ b/pages/order/index.wxss @@ -52,7 +52,7 @@ page { } .list-top-status { - color: #ff8100; + color: #da2b54; } .list-goods { @@ -157,8 +157,8 @@ page { } .list-btn-labor { - border: 2rpx solid #ff8100; - color: #ff8100; + border: 2rpx solid #da2b54; + color: #da2b54; border-radius: 80rpx; height: 56rpx; line-height: 56rpx; diff --git a/pages/refund/aftersale/aftersale.js b/pages/refund/aftersale/aftersale.js new file mode 100644 index 0000000..62a3d79 --- /dev/null +++ b/pages/refund/aftersale/aftersale.js @@ -0,0 +1,82 @@ +Page({ + + /** + * 页面的初始数据 + */ + data: { + order : null, + title : [], + imgs : null, + titleVal: '' + }, + + /** + * 生命周期函数--监听页面加载 + */ + onLoad(options) { + wx.showLoading({ + title: '加载中...', + mask : true + }) + wx.$api.refund.refundPreposition(options.id).then(res => { + let { title, order } = res.data; + console.log(order) + console.log(title) + this.setData({ + title, + order, + titleVal: title[0] + }) + wx.hideLoading() + }) + }, + /** + * 选择退货理由 + */ + onRadio(e){ + console.log(e.detail.value) + }, + /** + * 选择图片上传 + */ + onUpd(){ + wx.chooseMedia({ + count : 1, + mediaType : ['image'], + success : path => { + wx.$api.file.uploadImg(path.tempFiles[0].tempFilePath, {}).then(res => { + this.setData({ + imgs: res + }) + }) + } + }) + }, + /** + * 提交申请 + */ + onSubmit(){ + let data = { + title : this.data.titleVal, + pictures : this.data.imgs != null ? this.data.imgs.path : '' + } + wx.showLoading({ + title: '加载中...', + mask : true + }) + wx.$api.refund.submitRefund(this.data.order.order_no, data).then(res => { + wx.showModal({ + title : '提示', + content : res.data, + showCancel : false, + confirmColor: '#da2b54', + success : modalRes => { + if(modalRes.confirm){ + wx.navigateBack() + } + wx.hideLoading() + } + }) + }) + } +}) \ No newline at end of file diff --git a/pages/refund/aftersale/aftersale.json b/pages/refund/aftersale/aftersale.json new file mode 100644 index 0000000..fa2aa1c --- /dev/null +++ b/pages/refund/aftersale/aftersale.json @@ -0,0 +1,4 @@ +{ + "usingComponents": {}, + "navigationBarTitleText": "申请退货" +} \ No newline at end of file diff --git a/pages/refund/aftersale/aftersale.wxml b/pages/refund/aftersale/aftersale.wxml new file mode 100644 index 0000000..e706c0b --- /dev/null +++ b/pages/refund/aftersale/aftersale.wxml @@ -0,0 +1,39 @@ + + + + + 本次售后服务将由 绚火健康 为您提供服务 + + + + + + + {{item.sku.goods_name}} + 金额:{{item.price}} + 数量:{{item.qty}} + + + + + 选择退货理由 + + + + + + + 退货照片(仅限一张图片) + + + + + + + + + + + \ No newline at end of file diff --git a/pages/refund/aftersale/aftersale.wxss b/pages/refund/aftersale/aftersale.wxss new file mode 100644 index 0000000..fc720e7 --- /dev/null +++ b/pages/refund/aftersale/aftersale.wxss @@ -0,0 +1,34 @@ + +.content{ background: #f7f8f9; min-height: 100vh; padding: 30rpx; box-sizing: border-box; } + +/* 售后服务提醒 */ +.service-content { display: flex; flex-direction: row; align-items: center; justify-content: center; } +.service { font-size: 24rpx; padding: 4rpx 20rpx; border-radius: 30rpx; background-color: #f9f9f9; display: inline-block; text-align: center; color: #666; } +.service text{ color: #da2b54; } + +/* 商品信息 */ +.goods{ background-color: #fff; padding: 10rpx 30rpx; box-sizing: border-box; border-radius: 20rpx; margin-top: 30rpx; } +.goods-item { display: flex; flex-direction: row; align-items: center; justify-content: flex-start; margin: 20rpx 0; } +.good-img{ width: 128rpx; height: 128rpx; border-radius: 10rpx; } +.good-content{ padding-left: 30rpx; box-sizing: border-box; width: calc(100% - 128rpx); } +.good-content > .title{ font-size: 30rpx; line-height: 48rpx; } +.good-content > .text{ font-size: 26rpx; color: gray; line-height: 40rpx; } + +/* 退货标题 */ +.block-title{ font-size: 30rpx; padding-top: 30rpx; color: gray; } + +/* 退货原因 */ +.reason{ background: white; border-radius: 20rpx; margin-top: 30rpx; } +.reason-flex{ display: flex; justify-content: space-between; align-items: center; padding: 0 30rpx; height: 120rpx; font-weight: bold; font-size: 30rpx; border-bottom: solid 1rpx #f7f8f9; } +.reason-radio{ transform: scale(.75); } +.reason-flex:last-child{ border-bottom: none; } + +/* 上传退货照片 */ +.imgs{ background: white; border-radius: 20rpx; margin-top: 30rpx; padding: 20rpx; display: flex; flex-wrap: wrap; } +.imgs-upd{ background: #f7f8f9; width: calc(25% - 20rpx); padding-top: calc(25% - 20rpx); margin: 10rpx; position: relative; } +.imgs-add{ width: 48rpx; height: 48rpx; opacity: .3; position: absolute; left: 50%; top: 50%; margin-top: -24rpx; margin-left: -24rpx; } +.imgs-cover{ position: absolute; top: 0; left: 0; width: 100%; height: 100%; } + +/* 退货 */ +.button{ margin-top: 40rpx; } +.button button[size="default"]{ background: #da2b54; color: white; width: 100%; height: 90rpx; font-size: 32rpx; line-height: 90rpx; padding: 0; border-radius: 45rpx; } diff --git a/pages/refund/refund.js b/pages/refund/refund.js new file mode 100644 index 0000000..59505a0 --- /dev/null +++ b/pages/refund/refund.js @@ -0,0 +1,50 @@ +Page({ + + /** + * 页面的初始数据 + */ + data: { + listsArr : [], // 订单列表 + page : { current: 1 }, // 分页信息 + lodingStats : false, // 加载状态 + }, + + /** + * 生命周期函数--监听页面显示 + */ + onShow() { + this.getList() + }, + /** + * 获取列表 + */ + getList(){ + wx.showLoading({ + title: '加载中...', + mask : true + }) + wx.$api.refund.list({ + page : this.data.page.current + }).then(res => { + let { data, page } = res.data + + console.log(data) + + this.setData({ + listsArr : page.current == 1 ? data : this.data.listsArr.concat(data), + page : res.data.page, + lodingStats : !page.has_more + }) + wx.stopPullDownRefresh() + wx.hideLoading() + }) + }, + /** + * 申请售后 + */ + onAftersale(){ + wx.navigateTo({ + url: './aftersale/aftersale', + }) + } +}) \ No newline at end of file diff --git a/pages/refund/refund.json b/pages/refund/refund.json new file mode 100644 index 0000000..076a7d7 --- /dev/null +++ b/pages/refund/refund.json @@ -0,0 +1,4 @@ +{ + "usingComponents": {}, + "navigationBarTitleText": "售后记录" +} \ No newline at end of file diff --git a/pages/refund/refund.wxml b/pages/refund/refund.wxml new file mode 100644 index 0000000..901ab80 --- /dev/null +++ b/pages/refund/refund.wxml @@ -0,0 +1,35 @@ + + + + + + + + {{items.goods_name}} + 金额:{{items.price}} + 数量:{{items.qty}} + + + + {{item.state.text}} + {{item.state.remark}} + + + 售后详情 + + + + + + 加载中... + + 没有更多了~ + + + + + + + 暂无可售后服务订单 + + diff --git a/pages/refund/refund.wxss b/pages/refund/refund.wxss new file mode 100644 index 0000000..e687e5f --- /dev/null +++ b/pages/refund/refund.wxss @@ -0,0 +1,23 @@ + +/* 售后服务列表 */ +.orders{ background: #f7f8f9; min-height: 100vh; padding:10rpx 30rpx 30rpx; box-sizing: border-box; } +.order-item{ background: white; padding: 30rpx; border-radius: 20rpx; margin-top: 20rpx; } + +/* 订单数量 */ +.order-flex{ display: flex; flex-wrap: wrap; } +.order-cover{ background-color: #f7f8f9; width: 140rpx; height: 140rpx; margin-right: 30rpx; border-radius: 10rpx; } +.order-content{ width: calc(100% - 178rpx); } +.order-title{ font-size: 30rpx; font-weight: bold; line-height: 50rpx; height: 50rpx; } +.order-text{ color: gray; font-size: 28rpx; line-height: 45rpx; } +.order-text text{ color: #da2b54; font-weight: bold; } + +/* 订单状态 */ +.order-state { display: flex; flex-direction: row; align-items: center; justify-content: flex-start; box-sizing: border-box; font-size: 26rpx; background: #f7f8f9; margin: 30rpx 0; padding: 20rpx; border-radius: 10rpx; } +.order-des { padding-left: 20rpx; color: #777; } + +/* 订单操作 */ +.order-btns { border-top: solid 1rpx #f9f9f9; display: flex; justify-content: flex-end; padding-top: 20rpx; } +.order-btns .item{ font-size: 28rpx; margin-left: 20rpx; color: #da2b54; line-height: 60rpx; border: solid 1rpx #da2b54; padding: 0 30rpx; border-radius: 30rpx; } + +/* 售后服务 */ +.pages-hint{ padding-bottom: 10vh; } diff --git a/pages/user/index.wxml b/pages/user/index.wxml index 8f9241c..aed7bd7 100644 --- a/pages/user/index.wxml +++ b/pages/user/index.wxml @@ -1,9 +1,12 @@ - + {{userData.user.nickname}} - 生命可以如此精彩~ + + + + 编辑 > @@ -63,17 +66,13 @@ 我的账户 - 我的团队 - - - 邀请码 + + + 售后记录 @@ -83,6 +82,10 @@ 实名认证 + + + 邀请码 + 关于我们 diff --git a/pages/user/index.wxss b/pages/user/index.wxss index 20bbab1..907f26a 100644 --- a/pages/user/index.wxss +++ b/pages/user/index.wxss @@ -40,6 +40,10 @@ page { color: #111111; } +.head-text text{ background: #da2b54; color: white; padding: 0 20rpx; border-radius: 30rpx; line-height: 40rpx; display: inline-block; color: white; font-size: 24rpx; } +.head-name image, +.head-text image{ width: 90rpx; height: 34rpx; vertical-align: middle; } + .head-edit { position: absolute; right: 0; diff --git a/static/icons/add_gray.png b/static/icons/add_gray.png new file mode 100644 index 0000000000000000000000000000000000000000..2cbbb3bd95adfbaea88279ca72a976e3eb8e2a74 GIT binary patch literal 4242 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 bzW_!*xLBG!?haP`HSi>FbS?fqbnia_6I1r& literal 0 HcmV?d00001 diff --git a/static/icons/copy_icon.png b/static/icons/copy_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..45a4cb0536630bdd8de1efaf824badc3b7fe8046 GIT binary patch literal 2341 zcmbVO32+lt7~UL&9)fKVxjdGw2MEa?xi(8%+GNu<3@L5tNDGMF?rzg9NjBZxwrQzc z9!!fII*1%mgb`GPS{?D2BGwTR@j}E>oK&mMAcJy^GE_wIZJGwuqK=vD?%Vgi@4x?l zwzasZU_{FJ6bOPwcnaxK@XS@OBm=nb6zaYLkK|Bcg$zNdqtr_SZHkPApkb$kvT~)| zJCkC?fQjM6D&7j z4!95qdA$k2K{*~M5Hd8(gizdsp@D$vR}3vHrTkShhD6I{O(7mF=EuEW>fiN>YS<3Pw^G zHURaCoKW5LcPK$&W(vdq1O@%VF$(jqV2-7#MJd35(h&lTk4Hm69|9*bL%Br1C;`R5 zI`g&r9+#_F5~~G2IFL&VoUq63vf&P!%}AJVwL9X;*6cF0OW)2 zp%_+eWZ)13Y*v-3n?o7=-)d@r-&n%~k=Lg7FZmjP$zrwA$Vhyi57hn;r31nWPx3OX z5L8#zW_og(Igocdi^&a?^^p@94~_tY9kMDQMYRm%jXAO$is6zyCmf;mh0S z`o-<#E8BPP`CX?m`uEqC(1#Bot9GP~F6-z>@AiJQ`n`?MbKVn=%3=|BW=?hRlglSI zzyFr(+mYr@Z`x6FYu6^Yi&|=Za}4&_p4=Db&iedvMo8C#SN`Jbqe8RhbsX_OTXDsZ z-=vS|){otLe*cH-zkMx}S*N{u*`{sx8H3X@h%H(jc|$~R)1{x&Z5TeI?FvAQ`L1PH z<%saey>+)9-Ln*t`WG0A&dwUMTj4=#;;7&=Y%!Psv9 zw2?D2H;(!&rDyrO?LPgk*t&m>Oym#%!2zI=GcT^F@2 zA17aG?(2WOb;Hd5v~%Ob+Li))^3JU*qtS@r#4TUwFDHee=>FaV7f))Bt!*9W>rd;r zy(f9^d%ZsvPaxBdHMHHR@jW)Kcg?}9ZK+h3iK{*|IY<8ylzQ8#=7|@3E7K}L>Y}OV z>e5@1qXq5J@$ZyG*mUyL#7~P`lEQ6SPk26@8qzo3_gu>D+CyD+eG@Lt_NVl$TJiGY zj2!(`XwkBlPCoK(I?=G{akRt!F3qhwv+ZO6B3yBj3$9 z+k1k3RlBe6_mU@P%_vmY_pW`(+OjYCOq=cTdiUq$cRq8(zgN3{*_eZ_Lv`C%a`RW4 k?=DUHdgS+!n1bn=r_a?M9hrM^zWO2KaTn3;&dTL~0JNMqSO5S3 literal 0 HcmV?d00001 diff --git a/static/imgs/tool_08.png b/static/imgs/tool_08.png index 47aa73b7d7e5ceb6bb44b91f0cb57d7399d71a8a..f8915954b04052a978cad8f58d827b632ee764c5 100644 GIT binary patch delta 1573 zcma)!YakN{0Dw0$^IC=$3Yj*KF0qX@E18B+dDOy=c35+rM%1Cu?a{WV^C*%>nnH%o z4QH$C+=h|IBL#hd8Fjj-OqmB_wW1hef{RSR-&z-EjSDv=Rw1IxS;76tcyE_ zj(5T1@i>QR^{j${1*0B}m6uMhbcd#;R<9qqTCFO|NXD;+|Xov++2v@@{Zp4|=Z;@JVK zN@`0Wa8q9cp>EYpIf{dHNO(>R4fBn*3xgT!no2Ar5IA_zK1j_`^NslXLnc3;)r@&z z$Fbv*cNJj{ipj@{-)0H5510+J+{cr4JBl?ROLks~ z!yC3d|Ma~oL)GfT?T6h9SKlyLy#kV%5J8~^XDi&?bgi$xx(aXwyaEZ}hm}`{JBFAy z<~RICX9reOeHiUoiG}Dxa^C~W*TZA%M=WsN(zSuRJ*yX;Uhmrmb=lZWX&w>b2c^zU zPq7_z!{K*kk%7~+80X{!{ds@hC!*>67b;pW8+d>EVCU#xOPlYD5b;2@!uw#0@eam%&B@k6Yfi4 z&#{H|$rv<4_ib5lbq^tJiu(#+O>LK3otwK@7jS#sw#vJJuO6hdD}LH8Lrd-9l!A); z)N;6T=|zS(_7q1xCJT`Mc@Eak68yBR`pTQU5N?fRn1*he4((s5oel0!a?sOcADoX2 zIcbi!#FqU-B304L>bOcKJKn-`XawzH?0~s7v>YWUDq4M)G?KQ7p6~UY-@_zI&GrTy zAQP5;u7*QGn+ea~h$m7~NZ3t#LFKGDSu-)x+uFkTi5kJa`|vD_U(uf-3v&RdiywgeqTpmJ$Nsk>%!QpG>oGIf*YoV*|_*aL|bZctUG zimsxl2A3^v_?uzLC-)aSzFZa*UvH=twpO!lZAmN!Jp(kb+YSs2P#d}kbk2xUjto^M ziKaAr(NTo@IZ*D0_qrrm)5@ZA$Dsc2I^EnR@`d$eyZ8{>A2_RM@g3MEy1UUq()WC*Pd~gSMR@DhDNS%3Q)j2n zE?i>~JnvyJDzPE0$Eq|Tc7neK(JT;8!<#0FAHh}G5A-QEj<0PyU@^!I!M6{mu^Y28 zHua8936LVuTG7Kp;_TQz;k}jIl6B{PPH8xClespI#BJRntT)wOe+Ik*;E|xEPZst2 zW%ldCK@l(MVV|JshgVJ7>;X1yv8SWee8bF@IiKEI7hAo!-loWjagcLsAiY$52IZ>N z@*R0e0;eN0YUyA1Ak)OlgFu=+^~Wq5u>EsuX!-A~BO3(iC*u2Pu(%`pg1quBIU%4- z_Css$%`yn&{5B%P5^>ZO+5GpD zRDOC!&XTwKfxjRblLfYmiZE50s?IQDHk0!ptL?G^74rO2yka4%Y|V1x2a8ODWdRNS zOF+k2nb!bEq}SpfSJVg0LR44&QB{*FfAebh9-heHlTnt5Fg4G+{Nvyw*(4_kNPQR4 za_62z@`AAg(PoA>iX>0S*fFYz7ZMWVO|o!}>>IG?tu3dOIO3kUg)kbYEGtpVt|%J} U;B?fLaKL{A`UU$o?up_23%;$^{Qv*} delta 861 zcmeB`JT1IIi&;6@+`!Zz&Dd1eD9zGB*TmE~Q8y{kEJ-)X#4N?oJjKEwIcc&la}Bql zMTnt^m4T_1f!X9M%u2}o&5SI(Ohg%E$R>`gadHc5$mHd0k@ahn8y+z*Fs=7=aSX|5 ze0$5k!#7aoz{m5mCI6@W>HTwdey@-iSF4EUMzxKCsfp>Wt&?<84xbD1>~y@Qp&c1{ zV}_EL)J#t9`cLZhY0o0(X!n1AS6g0me^2%D-)nEzt}ov8ci;PYpRK?DJGVMyb?D=X zeP!$yw7fPh3hWZ?4O){?UvkvcCVubp@5ehM+GQj9JlFDTPkUd{W?j)DzhTe&wAkYj z8>PNIG?1Bcc{dqb^q;!r+_WZf6>6v5h zckRp1&hj5>f2xvwLuasUHe|F7tnm*t7n^+K+x0E`4+Y*4XSuCrcX^l-mrwJG7^nBo!BE zbaxo36;>?~%&wYfGs*3ZvK&XGhQ4!sp_Ey&Tg-Bkr1dTB4;phGooaF2q3x*S8}>#- z&gQercAiVNKW8WVK9<~`e_?6FMUA6fZkk~xzyLJNJ9=r~wk@+>-cYdFdOfU6yQ1;9 z(@lNTN`cuu-Zw-q+o@dPTQB9BY0K|iD0fY5OF8G$H-UFsZ0>BVi#Z_Y^YQt*kVTJq z>+>=X2FP6eb$4p<4n-0B|8tX@4@KALhWcjB%{-zeG5h<*>5E_7UUDOBV$FTf07CN|Nhh5pAi*VQ<9k42yNYD_owy O00f?{elF{r5}E*rlzp-Q