Browse Source

初始化

master
jianglong 3 years ago
commit
3db8a7425a
  1. 3
      .gitignore
  2. 94
      App.vue
  3. 28
      androidPrivacy.json
  4. 183
      api/activity.js
  5. 139
      api/app.js
  6. 131
      api/community.js
  7. 10
      api/live.js
  8. 46
      api/order.js
  9. 92
      api/shop.js
  10. 223
      api/store.js
  11. 332
      api/user.js
  12. 11
      apple-app-site-association
  13. 17
      autoRelease.sh
  14. 118
      bundle/pages/activity_detail/activity_detail.vue
  15. 209
      bundle/pages/address_edit/address_edit.vue
  16. 43
      bundle/pages/after_sales/after_sales.vue
  17. 235
      bundle/pages/after_sales_detail/after_sales_detail.vue
  18. 200
      bundle/pages/all_comments/all_comments.vue
  19. 260
      bundle/pages/apply_refund/apply_refund.vue
  20. 161
      bundle/pages/bargain/bargain.vue
  21. 77
      bundle/pages/bargain_code/bargain_code.vue
  22. 734
      bundle/pages/bargain_process/bargain_process.vue
  23. 637
      bundle/pages/chat/chat.vue
  24. 63
      bundle/pages/commission_details/commission_details.vue
  25. 158
      bundle/pages/contact_offical/contact_offical.vue
  26. 61
      bundle/pages/exchange_order/exchange_order.vue
  27. 369
      bundle/pages/exchange_order_details/exchange_order_details.vue
  28. 174
      bundle/pages/goods_combination/goods_combination.vue
  29. 240
      bundle/pages/goods_logistics/goods_logistics.vue
  30. 193
      bundle/pages/goods_reviews/goods_reviews.vue
  31. 219
      bundle/pages/goods_seckill/goods_seckill.vue
  32. 128
      bundle/pages/input_express_info/input_express_info.vue
  33. 83
      bundle/pages/integral_details/integral_details.vue
  34. 256
      bundle/pages/integral_goods_details/integral_goods_details.vue
  35. 265
      bundle/pages/integral_mall/integral_mall.vue
  36. 266
      bundle/pages/integral_settlement/integral_settlement.vue
  37. 357
      bundle/pages/integral_sign/integral_sign.vue
  38. 160
      bundle/pages/invite_fans/invite_fans.vue
  39. 379
      bundle/pages/invoice/invoice.vue
  40. 212
      bundle/pages/invoice_detail/invoice_detail.vue
  41. 72
      bundle/pages/license/license.vue
  42. 102
      bundle/pages/monthly_bill/monthly_bill.vue
  43. 156
      bundle/pages/monthly_bill_detail/monthly_bill_detail.vue
  44. 553
      bundle/pages/order_details/order_details.vue
  45. 63
      bundle/pages/recharge_record/recharge_record.vue
  46. 72
      bundle/pages/server_explan/server_explan.vue
  47. 97
      bundle/pages/settled_recode/settled_recode.vue
  48. 192
      bundle/pages/settled_result/settled_result.vue
  49. 38
      bundle/pages/sign_rule/sign_rule.vue
  50. 257
      bundle/pages/store_settled/store_settled.vue
  51. 250
      bundle/pages/user_address/user_address.vue
  52. 85
      bundle/pages/user_bill/user_bill.vue
  53. 51
      bundle/pages/user_collection/user_collection.vue
  54. 35
      bundle/pages/user_comment/user_comment.vue
  55. 41
      bundle/pages/user_coupon/user_coupon.vue
  56. 253
      bundle/pages/user_fans/user_fans.vue
  57. 59
      bundle/pages/user_group/user_group.vue
  58. 64
      bundle/pages/user_growth/user_growth.vue
  59. 58
      bundle/pages/user_order/user_order.vue
  60. 336
      bundle/pages/user_payment/user_payment.vue
  61. 612
      bundle/pages/user_profile/user_profile.vue
  62. 690
      bundle/pages/user_spread/user_spread.vue
  63. 48
      bundle/pages/user_spread_order/user_spread_order.vue
  64. 253
      bundle/pages/user_vip/user_vip.vue
  65. 212
      bundle/pages/user_wallet/user_wallet.vue
  66. 250
      bundle/pages/user_withdraw/user_withdraw.vue
  67. 97
      bundle/pages/user_withdraw_code/user_withdraw_code.vue
  68. 127
      bundle/pages/widthdraw_result/widthdraw_result.vue
  69. BIN
      bundle/static/No.0.png
  70. BIN
      bundle/static/activity_detail_bg.png
  71. BIN
      bundle/static/bg_sgin.png
  72. BIN
      bundle/static/contact_official_bg.png
  73. BIN
      bundle/static/icon_camera_line.png
  74. BIN
      bundle/static/icon_czjl.png
  75. BIN
      bundle/static/icon_fenxiao.png
  76. BIN
      bundle/static/icon_integral.png
  77. BIN
      bundle/static/icon_invite.png
  78. BIN
      bundle/static/icon_jifen.png
  79. BIN
      bundle/static/icon_wait.png
  80. BIN
      bundle/static/icon_yezz.png
  81. BIN
      bundle/static/icon_yongjin.png
  82. BIN
      bundle/static/icon_zhangdan.png
  83. BIN
      bundle/static/icon_zhmx.png
  84. BIN
      bundle/static/icon_zzjl.png
  85. BIN
      bundle/static/img_activity_coupon.png
  86. BIN
      bundle/static/img_activity_jifen.png
  87. BIN
      bundle/static/img_activity_pintuan.png
  88. BIN
      bundle/static/img_activity_seckill.png
  89. BIN
      bundle/static/invoice_success.png
  90. BIN
      bundle/static/invoice_wait.png
  91. BIN
      bundle/static/jifen_icon_data.png
  92. BIN
      bundle/static/jifen_icon_help.png
  93. BIN
      bundle/static/jifen_icon_select.png
  94. BIN
      bundle/static/jifen_popBg.png
  95. BIN
      bundle/static/logistics_address.png
  96. BIN
      bundle/static/logistics_address_gray.png
  97. BIN
      bundle/static/logistics_delivered.png
  98. BIN
      bundle/static/logistics_pay.png
  99. BIN
      bundle/static/logistics_success.png
  100. BIN
      bundle/static/logistics_transit.png

3
.gitignore

@ -0,0 +1,3 @@
unpackage
node_modules/
.hbuilderx/

94
App.vue

@ -0,0 +1,94 @@
<script>
import {
mapActions,
mapMutations
} from 'vuex'
import {
getConfig
} from '@/api/app'
import {
strToParams
} from '@/utils/tools'
import {
bindSuperior
} from '@/api/user'
import {INVITE_CODE} from '@/config/cachekey'
import Cache from '@/utils/cache'
export default {
onLaunch: function(options) {
//#ifdef MP-WEIXIN
this.checkMpUpdate()
//#endif
//
this.getConfigFun()
this.getUser()
this.getSystemInfo()
},
onShow: function(options) {
console.log(options)
this.bindCode(options)
},
onHide: function() {
},
methods: {
...mapActions(['getSystemInfo', 'getUser', 'wxShare', 'initLocationFunc']),
...mapMutations(['setConfig']),
async getConfigFun() {
const {
code,
data
} = await getConfig()
if (code == 1) {
this.setConfig(data)
if(data.is_open_nearby) {
//
this.initLocationFunc()
}
//
this.wxShare()
}
},
async bindCode(options) {
if(!options.query) return
let invite_code = options.query.invite_code || strToParams(decodeURIComponent(options.query.scene))
.invite_code
if (invite_code) {
const {
data,
code
} = await bindSuperior({
code: invite_code
})
if (code == -1) {
Cache.set(INVITE_CODE, invite_code)
}
}
},
//#ifdef MP-WEIXIN
checkMpUpdate() {
const updateManager = wx.getUpdateManager()
updateManager.onUpdateReady(function () {
wx.showModal({
title: '更新提示',
content: '新版本已准备好,是否重启?',
success: function (res) {
if (res.confirm) {
// applyUpdate
updateManager.applyUpdate()
}
}
})
})
}
//#endif
}
}
</script>
<style lang="scss">
@import 'styles/common.scss';
@import "components/uview-ui/index.scss";
@import url('@/plugin/emoji-awesome/css/apple.css');
/*每个页面公共css */
</style>

28
androidPrivacy.json

@ -0,0 +1,28 @@
{
"version" : "1",
"prompt" : "template",
"title" : "用户协议和隐私政策",
"message" : "  请你务必审慎阅读、充分理解“用户协议”和“隐私政策”各条款,包括但不限于:为了更好的向你提供服务,我们需要收集你的设备标识、操作日志等信息用于分析、优化应用性能。<br/>  你可阅读<a href=\"https://b2b2c.likeshop.cn/mobile/bundle/pages/server_explan/server_explan?type=0\">《用户协议》</a>和<a href=\"https://b2b2c.likeshop.cn/mobile/bundle/pages/server_explan/server_explan?type=1\">《隐私政策》</a>了解详细信息。如果你同意,请点击下面按钮开始接受我们的服务。",
"buttonAccept" : "同意并接受",
"buttonRefuse" : "暂不同意",
"hrefLoader" : "system|default",
"second" : {
"title" : "确认提示",
"message" : "  进入应用前,你需先同意<a href=\"https://b2b2c.likeshop.cn/mobile/bundle/pages/server_explan/server_explan?type=0\" >《用户协议》</a>和<a href=\"https://b2b2c.likeshop.cn/mobile/bundle/pages/server_explan/server_explan?type=1\">《隐私政策》</a>,否则将退出应用。",
"buttonAccept" : "同意并继续",
"buttonRefuse" : "退出应用"
},
"styles" : {
"backgroundColor" : "#ffffff",
"borderRadius" : "5px",
"title" : {
"color" : "#FF2C3C"
},
"buttonAccept" : {
"color" : "#FF2C3C"
},
"buttonRefuse" : {
"color" : "#545454"
}
}
}

183
api/activity.js

@ -0,0 +1,183 @@
import request from '@/utils/request'
import {client} from '@/utils/tools'
//领券中心
export function getCouponList(params) {
return request.get("coupon/getCouponList", {params});
}
//用户领取优惠券
export function getCoupon(id) {
return request.post('coupon/getCoupon', {coupon_id:id})
}
// 下单优惠券
export function getOrderCoupon(data) {
return request.post("coupon/getBuyCouponList", data);
}
//我的优惠券
export function getMyCoupon(params) {
return request.get('coupon/myCouponList', {
params
})
}
// 获取活动专区商品列表
export function getActivityGoodsLists(data) {
return request.get("activity_area/activityGoodsList", {params: data})
}
// 获取秒杀时间段
export function getSeckillTime() {
return request.get("seckill_goods/getSeckillTime");
}
// 获取秒杀商品
export function getSeckillGoods(params) {
return request.get("seckill_goods/getSeckillGoods", {params})
}
// 拼团列表
export function getGroupList(params) {
return request.get('team/activity', {params});
}
//拼团记录
export function getUserGroup(params) {
return request.get('team/record', {params});
}
//拼团详情
export function getTeamInfo(params) {
return request.get('team/teamInfo', {params});
}
//开团|结算
export function teamKaiTuan(data) {
return request.post('team/kaituan', data);
}
//参与拼团验证
export function teamCheck(data) {
return request.post('team/check', data);
}
//拼团下单
export function teamBuy(data) {
return request.post("team/buy",data);
}
// 获取砍价列表
export function getBargainList(data) {
return request.get('bargain/lists', {params: data})
}
// 获取砍价详情
export function getBargainDetail(data) {
return request.get('bargain/detail', {params: data})
}
// 获取砍价成功人数
export function getBargainNumber() {
return request.get("bargain/barginNumber")
}
// 发起砍价
export function launchBargain(data) {
return request.post('bargain/sponsor', data)
}
// 获取砍价活动商品列表
export function getBargainActivityList(data) {
return request.get('bargain/orderList', {params: data})
}
// 砍价详情
export function getBargainActivityDetail(data) {
return request.get("bargain/bargainDetail", {params: data})
}
// 砍价海报
export function getBargainPost(data) {
return request.get("share/shareBargain", {params: data})
}
// 好友助力
export function helpBargain(data) {
return request.post('bargain/knife', data)
}
// 关闭结算订单
export function closeBargainOrder(data) {
return request.get("bargain/closeBargain", {params: data})
}
// 获取签到列表
export function getSignLists() {
return request.get("sign/lists")
}
// 获取签到列表
export function getSignRule() {
return request.get("sign/rule")
}
// 签到
export function userSignIn() {
return request.get("sign/sign")
}
// 积分商城
export function getIntegralGoods(params) {
return request.get("integral_goods/lists", { params })
}
// 积分商品详情
export function getIntegralGoodsDetail(params) {
return request.get("integral_goods/detail", { params })
}
// 积分兑换订单结算
export function integralSettlement(params) {
return request.get("integral_order/settlement", { params })
}
// 积分兑换提交订单
export function integralSubmitOrder(params) {
return request.post("integral_order/submitOrder", params)
}
// 积分兑换订单列表
export function getIntegralOrder(params) {
return request.get("integral_order/lists", {params})
}
//删除积分兑换订单
export function delIntegralOrder(id) {
return request.post('integral_order/del', {id})
}
//积分兑换订单订单详情
export function getIntegralOrderDetail(id) {
return request.get('integral_order/detail', {params: {id}})
}
//取消积分兑换订单
export function cancelIntegralOrder(id) {
return request.post('integral_order/cancel', {id})
}
//确认收货积分兑换订单
export function confirmIntegralOrder(id) {
return request.post("integral_order/confirm", {id})
}
// 查看物流
export function getIntegralOrderTraces(id) {
return request.get("integral_order/orderTraces", {params: {id}})
}

139
api/app.js

@ -0,0 +1,139 @@
import request from '@/utils/request'
import wechath5 from '@/utils/wechath5'
import {client} from '@/utils/tools'
//小程序授权登录
export function authLogin(data) {
return request.post('account/authLogin', data);
}
//小程序静默登录
export function silentLogin(data) {
return request.post('account/silentLogin', data);
}
//更新小程序头像昵称
export function updateUser(data, token) {
return request.post('account/updateUser', data, {header: {token}});
}
// app登录
export function opLogin(data) {
return request.post('account/uinAppLogin', {...data, client});
}
//预支付接口
export function prepay(data) {
return request.post('pay/unifiedpay', {...data,});
}
//小程序订阅
export function getMnpNotice(data) {
return request.get("subscribe/lists", {
params: data
});
}
//账号登录
export function accountLogin(data) {
return request.post("account/login", {...data, client})
}
// 登录
export function wechatLogin(data) {
return request.post('account/oalogin', data)
}
// 向微信请求code的链接
export function getCodeUrl() {
return request.get('account/codeurl', {
params:{
url: encodeURIComponent(location.href)
}
});
}
//微信sdk配置
export function getJsconfig() {
return request.get('wechat/jsconfig', {
params: {
url: encodeURIComponent(wechath5.signLink())
}
});
}
// 忘记密码
export function forgetPwd(data) {
return request.post('login_password/forget', {...data, client})
}
// 发送短信
export function sendSms(data) {
return request.post('sms/send', {...data, client})
}
// Html5 注册账号
export function register(data) {
return request.post('account/register', {...data, client})
}
// 获取服务协议
export function getServerProto() {
return request.get("policy/service")
}
// 获取隐私政策
export function getPrivatePolicy() {
return request.get("policy/privacy")
}
// 获取售后保障
export function getAfterSaleGuar() {
return request.get("policy/afterSale")
}
//客服
export function getService() {
return request.get("setting/getPlatformCustomerService")
}
//客服配置
export function getChatConfig(params) {
return request.get("index/chatConfig", { params })
}
// 足迹气泡
export function getBubbleLists() {
return request.get("footprint/lists")
}
// 验证码登录
export function smsCodeLogin(data) {
return request.post('account/smsLogin', {...data, client})
}
export function getConfig() {
return request.get("index/config")
}
// 注册赠送优惠券
export function getRegisterCoupon() {
return request.get('coupon/registerSendCoupon')
}
// 获取支付配置
export function getPayway(params) {
return request.get('order/getPayWay', { params })
}
// 小程序码
export function apiMnpQrCode(params) {
return request.get('share/getMnQrcode', { params })
}

131
api/community.js

@ -0,0 +1,131 @@
import request from '@/utils/request'
// 关联商品
export function getCommunityGoods(params) {
return request.get("community/goods", {params})
}
// 关联店铺
export function getCommunityShop(params) {
return request.get("community/shop", {params})
}
// 推荐话题
export function getCommunityRecommendTopic() {
return request.get("community/recommendTopic")
}
// 话题列表
export function getCommunityTopicLists(params) {
return request.get("community/topicLists", {params})
}
// 发布文章
export function apiCommunityAdd(params) {
return request.post("community/addArticle", params)
}
// 编辑文章
export function apiCommunityEdit(params) {
return request.post("community/editArticle", params)
}
// 个人中心
export function getCommunityUserCenter(params) {
return request.get("community_user/center", {params})
}
// 分类
export function getCommunityCate() {
return request.get("community/cate")
}
// 发现页文章列表
export function getCommunityArticleLists(params) {
return request.get("community/articleLists", {params})
}
// 关注/取消
export function apiCommunityFollow(params) {
return request.post("community/follow", params)
}
// 获取设置
export function getCommunitySetting() {
return request.get("community_user/getSetting")
}
// 提交设置
export function apiCommunitySetSetting(params) {
return request.post("community_user/setSetting", params)
}
// 关注页-数据
export function getCommunityFollow(params) {
return request.get("community/followArticle", { params })
}
// 个人页-作品列表
export function getCommunityWorksLists(params) {
return request.get("community/worksLists", { params })
}
// 个人页-点赞列表
export function getCommunityLikeLists(params) {
return request.get("community/likeLists", { params })
}
// 相关话题
export function getCommunityTopicArticle(params) {
return request.get("community/topicArticle", { params })
}
// 文章详情
export function getCommunityDetail(params) {
return request.get("community/detail", { params })
}
// 文章中的关联商品
export function getCommunityGoodsLists(params) {
return request.get("community/relationGoods", { params })
}
// 文章中的关联店铺
export function getCommunityShopLists(params) {
return request.get("community/relationShop", { params })
}
// 删除文章
export function apiCommunityDel(params) {
return request.post("community/delArticle", params)
}
// 添加评论
export function apiCommunityCommentAdd(params) {
return request.post("community_comment/add", params)
}
// 文章评论
export function getCommunityCommentLists(params) {
return request.get("community_comment/lists", { params })
}
// 文章子级评论
export function getCommunityCommentChildLists(params) {
return request.get("community_comment/commentChild", { params })
}
// 点赞 | 取消 | 作品点赞 | 评论点赞
export function apiCommunityCommentLike(params) {
return request.post("community/giveLike", params)
}
// 搜索记录
export function getCommunitySearchHistory() {
return request.get("community_search/lists")
}
// 清空搜索记录
export function apiCommunityClearSearchHistory() {
return request.post("community_search/clear")
}

10
api/live.js

@ -0,0 +1,10 @@
import request from '@/utils/request'
// 直播间列表
export function getLiveLists(params) {
return request.get("live/lists", {params})
}
// 店铺直播间列表
export function getShopLive(params) {
return request.get("live/shopLive", {params})
}

46
api/order.js

@ -0,0 +1,46 @@
import request from '@/utils/request'
import {client} from '@/utils/tools'
//订单结算页
export function orderInfo(data) {
return request.post("order/settlement", data);
}
// 下单
export function orderBuy(data) {
return request.post("order/submitOrder", data);
}
//删除订单
export function delOrder(id) {
return request.post('order/del', {id})
}
//订单列表
export function getOrderList(data) {
return request.get('order/lists', {params: data})
}
//订单详情
export function getOrderDetail(id) {
return request.get('order/getOrderDetail', {params: {id}})
}
//取消订单
export function cancelOrder(id) {
return request.post('order/cancel', {id})
}
//物流
export function orderTraces(id) {
return request.get("order/orderTraces", {params: {id}})
}
//确认收货
export function confirmOrder(id) {
return request.post("order/confirm", {id})
}
// 支付结果
export function getPayResult(params) {
return request.get("order/pay_result", { params });
}

92
api/shop.js

@ -0,0 +1,92 @@
import request from '@/utils/request'
import {client} from '@/utils/tools'
//获取店铺列表
export function getShopList(params) {
return request.get('shop/getShopList', {params})
}
//获取附近店铺列表
export function getNearbyShops(params) {
return request.get('shop/getNearbyShops', {params})
}
//获取主营类目列表
export function getShopCategory() {
return request.get('shop_category/getList')
}
//获取店铺信息
export function getShopInfo(params) {
return request.get('shop/getShopInfo', {params})
}
//获取店铺商品分类
export function getShopGoodsCategory(params) {
return request.get('shop_goods_category/getShopGoodsCategory', {params})
}
//店铺关注/取消关注
export function changeShopFollow(data) {
return request.post('shop_follow/changeStatus', data)
}
// 商家入驻
export function shopApply(data) {
return request.post('ShopApply/apply', data)
}
// 申请记录
export function shopApplyRecord(params) {
return request.get('ShopApply/record', {params})
}
// 申请记录详情
export function shopApplyDetail(id) {
return request.get('ShopApply/detail', {params:{id}})
}
// 入住协议
export function getTreaty() {
return request.get('ShopApply/getTreaty')
}
//客服
export function getShopService(id) {
return request.get("setting/getShopCustomerService", {params:{shop_id: id}})
}
// 商家发票设置
export function getInvoiceSetting(params) {
return request.get("order_invoice/setting", { params })
}
// 发票提交
export function apiInvoiceAdd(params) {
return request.post("order_invoice/add", params)
}
// 发票编辑
export function apiInvoiceEdit(params) {
return request.post("order_invoice/edit", params)
}
// 发票详情
export function apiInvoiceDetail(params) {
return request.get("order_invoice/detail", { params })
}
// 订单发票详情
export function apiOrderInvoiceDetail(params) {
return request.get("order/invoice", { params })
}

223
api/store.js

@ -0,0 +1,223 @@
import request from '@/utils/request'
import {client} from '@/utils/tools'
//获取首页数据接口
export function getHome(params) {
return request.get('index/index', { params })
}
// 通过首页分类id获取数据
export function getIndexCategory(params) {
return request.get('index/indexCategory', {params})
}
//获取菜单
export function getMenu(data) {
return request.get('menu/lists', {
params: data,
});
}
//商品栏目
export function getGoodsColumn() {
return request.get('goods_column/getGoodsColumnList');
}
//栏目商品
export function getGoodsListColumn(params) {
return request.get('goods/getGoodsListByColumnId', {params});
}
//平台一级分类
export function getLevelOneList() {
return request.get('goods_category/getLevelOneList');
}
// 一级分类的后代分类
export function getListByLevelOne(params) {
return request.get('goods_category/getListByLevelOne', {params});
}
//品牌列表
export function getBrandList() {
return request.get('goods_brand/getGoodsBrandList');
}
//文章分类
export function getCategoryList(data) {
let {type} = data
let url = type ? 'help/category' : 'article/category'
delete data.type
return request.get(url)
}
//文章列表
export function getArticleList(data) {
let {type} = data
let url = type ? 'help/lists' : 'article/lists'
delete data.type
return request.get(url, {
params: data
})
}
// 文章详情
export function getArticleDetail(data) {
let {type} = data
let url = type ? 'help/detail' : 'article/detail'
delete data.type
return request.get(url, {
params: { id: data.id }
})
}
//购物车
export function getCartList() {
return request.get('cart/lists')
}
//商品详情
export function getGoodsDetail(data) {
return request.get('goods/getGoodsDetail', {
params: data
});
}
//加入购物车
export function addCart(data) {
return request.post('cart/add', data);
}
//购物车数量
export function getCartNum(params) {
return request.get("cart/num", {params});
}
// 购物车数量更改
export function changeGoodsCount(data) {
return request.post("cart/change", data)
}
// 单选/全选/店铺选择
export function selectedOpt(data) {
return request.post("cart/selected", data)
}
// 删除商品
export function deleteGoods(data) {
return request.post("cart/del", data);
}
//购物车选中状态
export function changeCartSelect(data) {
return request.post('cart/selected', data)
}
//广告位
export function getAdList(data) {
return request.get('ad_content/lists', {
params: data
});
}
// 商品分类
export function getCatrgory() {
return request.get('goods_category/lists');
}
// 商品搜索
export function getGoodsList(data) {
return request.get('goods/getGoodsList', {
params: data
});
}
//评价列表
export function getCommentList(data) {
return request.get("goods_comment/lists", {
params: data
})
}
//评价分类
export function getCommentCategory(id) {
return request.get("goods_comment/category", {
params: {
goods_id: id
}
})
}
//搜索页,热门搜索列表,和历史搜索列表
export function getSearchpage() {
return request.get('search_record/lists');
}
// 清空历史搜索
export function clearSearch() {
return request.post('search_record/clear');
}
//商品海报
export function getPoster(data) {
return request.get("share/sharegoods", {
params: data
});
}
// 消息中心首页
export function getMessageLists() {
return request.get("notice/index")
}
// 消息通知
export function getNoticeLists(params) {
return request.get("notice/lists", {params})
}
// 城市列表
export function getCityLists() {
return request.get("index/city")
}
// 逆解析定位地址
export function getGeocoder(params) {
return request.get("index/geocoder", {params})
}
//资料分类
export function getResourceCategoryList() {
let url = 'resource/category'
return request.get(url)
}
//资料列表
export function getResourceList(data) {
let url = 'resource/lists'
return request.get(url, {
params: data
})
}
// 资料详情
export function getResourceDetail(data) {
let url = 'resource/detail'
return request.get(url, {
params: { id: data.id }
})
}

332
api/user.js

@ -0,0 +1,332 @@
import request from '../utils/request'
import {client} from '@/utils/tools'
//个人中心
export function getUser() {
return request.get('user/center')
}
// 地址列表
export function getAddressLists() {
return request.get('user_address/lists')
}
// 商品的增添取消收藏
export function collectGoods(data) {
return request.post('goods_collect/changeStatus', data)
}
// 添加编辑地址
export function editAddress(data) {
return request.post('user_address/update', data)
}
export function addAddress(data) {
return request.post('user_address/add', data)
}
// 删除地址
export function delAddress(id) {
return request.post('user_address/del', {id})
}
// 获取单个地址
export function getOneAddress(id) {
return request.get('user_address/detail', {params: {id}})
}
// 获取默认地址
export function getDefaultAddress(id) {
return request.get('user_address/getDefault', {params: {id}})
}
// 设置默认地址
export function setDefaultAddress(id) {
return request.post('user_address/setDefault', {id})
}
//传省市区字符串判读是否有code
export function hasRegionCode(data) {
return request.post('user_address/handleRegion', data)
}
// 获取评价信息
export function getCommentInfo(params) {
return request.get("goods_comment/getCommentPage", {params});
}
// 未评价列表
export function getUnComment(params) {
return request.get("goods_comment/getUnCommentOrder", {params});
}
// 校验商品
export function apiCheckGoods(params) {
return request.get("goods_comment/checkGoods", {params});
}
// 已评价列表
export function getComment(params) {
return request.get("goods_comment/getCommentOrder", {params});
}
//商品评价
export function goodsComment(data) {
return request.post("goods_comment/addGoodsComment", data)
}
// 获取抽奖配置
export function getPrize(data) {
return request.get("Luckdraw/prize", data)
}
// 抽奖记录
export function getUserRecord(data) {
return request.get("Luckdraw/record", data)
}
// 获取个人详情
export function getUserInfo() {
return request.get('user/info')
}
// 获取资质信息
export function getCopyright(data) {
return request.get('index/copyright', {data})
}
// 设置个人信息
export function setUserInfo(data) {
return request.post('user/setInfo', data)
}
// 获取手机号
export function getWxMnpMobile(data) {
return request.post('user/getMobile',data);
}
//更新微信信息
export function setWechatInfo(data) {
return request.post('user/setWechatInfo', data)
}
// 更换手机号
export function changeUserMobile(data) {
return request.post("user/changeMobile", {...data, client})
}
//会员中心
export function getLevelList() {
return request.get('user/getUserLevelInfo');
}
// 用户钱包
export function getWallet() {
return request.get("user/myWallet")
}
// 账户流水
export function getAccountLog(params) {
return request.get("user/accountLog", {params})
}
// 充值模板
export function rechargeTemplate() {
return request.get("recharge/rechargeTemplate");
}
//充值
export function recharge(data) {
return request.post("recharge/recharge", data)
}
//充值记录
export function getRechargeRecord(params) {
return request.post("recharge/rechargeRecord", {params})
}
// 填写邀请码(绑定上级)
export function bindSuperior(data) {
return request.post("distribution/code", data)
}
// 分销会员申请
export function applyDistribute(data) {
return request.post("distribution/apply", data)
}
// 分销入口验证
export function veryfiyDistribute() {
return request.post('distribution/check')
}
// 最新分销会员申请详情
export function applyDetail() {
return request.post("distribution/applydetail")
}
// 邀请人信息
export function getSuperiorInfo() {
return request.get("distribution/myLeader")
}
// 分销主页
export function getDistribution() {
return request.get("distribution/index")
}
// 分销订单列表
export function getDistributionOrder(params) {
return request.get("distribution/order", {params})
}
// 我的粉丝
export function getUserFans(data) {
return request.get("user/fans", {params: data})
}
// 佣金明细
export function getCommission(params) {
return request.get("distribution/commission", {params})
}
// 月度账单
export function getMonthBill(params) {
return request.get("distribution/monthbill", {params})
}
// 月度账单明细
export function getMonthOrderDetail(params) {
return request.get("distribution/monthDetail", {params})
}
// 获取商品的收藏列表
export function getCollectGoods(params) {
return request.get('goods_collect/lists', {params})
}
// 获取店铺的收藏列表
export function getCollectShop(params) {
return request.get('shop_follow/lists', {params})
}
// 获取售后列表
export function getAfterSaleList(params) {
return request.get("after_sale/lists", {params});
}
// 申请售后
export function applyAfterSale(data) {
return request.post("after_sale/add", data)
}
// 获取商品信息
export function getGoodsInfo(params) {
return request.get("after_sale/goodsInfo", {params})
}
// 填写快递信息
export function inputExpressInfo(data) {
return request.post("after_sale/express", data)
}
// 撤销申请
export function cancelApply(data) {
return request.post("after_sale/cancel", data)
}
// 售后详情
export function afterSaleDetail(params) {
return request.get("after_sale/detail", {params})
}
// 重新申请
export function applyAgain(data) {
return request.post("after_sale/again", data)
}
// 佣金提现
export function applyWithdraw(data) {
return request.post("withdraw/apply", data);
}
// 提现记录列表
export function getWithdrawRecords(params) {
return request.get("withdraw/records", {params})
}
// 提现详情
export function getWithdrawDetail(params) {
return request.get("withdraw/info", {params})
}
// 提现页信息
export function getWithdrawConfig() {
return request.get("withdraw/config")
}
// 邀请海报
export function getUserPoster(data) {
return request.get("share/userPoster", {params: data})
}
// 退出登录
export function userLogout(data) {
return request.post('account/logout', data)
}
// 海报背景
export function apiDistributionPoster(data) {
return request.get("distribution/getPoster", {params: data})
}
// 聊天记录
export function chatRecord(data) {
return request.get('user/chatRecord', {params: data})
}
// 用户vip
export function getUserShip(data) {
return request.get('user/userShip', {params: data})
}
// 用户vip
export function getUserRight(data) {
return request.get('user/userRight', {params: data})
}
// 用户vip时间
export function getUserVipTime(data) {
return request.get('user/userVipTime', {params: data})
}
//获取投诉类型列表
export function getComplainCategory() {
return request.get('user/getComplainCategoryList')
}
// 投诉驻
export function complain(data) {
return request.post('user/complain', data)
}
// 投诉记录
export function complainRecord(params) {
return request.get('user/complainRecord', {params})
}
// 投诉记录详情
export function complainDetail(id) {
return request.get('user/complainDetail', {params:{id}})
}

11
apple-app-site-association

@ -0,0 +1,11 @@
{
"applinks": {
"apps": [],
"details": [
{
"appID": "8656MXP6VT.com.gzyx.likemall",
"paths": [ "/ulink/*"]
}
]
}
}

17
autoRelease.sh

@ -0,0 +1,17 @@
#!/bin/bash
# 文件原路径
srcPath="./unpackage/dist/build/h5"
# 发布路径文件夹
releasePath="../server/public/mobile"
#删除发布目录下的mobile文件
rm -r $releasePath
echo "已删除 ==> $releasePath 下的目录文件"
mkdir $releasePath
echo "已新建 ==> $releasePath 目录"
# 复制打包目录内的文件到发布目录
cp -r $srcPath/* $releasePath
echo "已复制 $srcPath/* ==> $releasePath"
cp $releasePath/../favicon.ico $releasePath

118
bundle/pages/activity_detail/activity_detail.vue

@ -0,0 +1,118 @@
<template>
<mescroll-body ref="mescrollRef" @init="mescrollInit" @up="upCallback" :up="upOption" @down="downCallback">
<view class="activity-detail">
<view class="header" v-if="goodsList.length">
<image class="header-bg" src="/bundle/static/activity_detail_bg.png"></image>
<view class="header-con flex-col col-center">
<view class="title white">{{name}}</view>
<view class="desc white sm br60">{{title}}</view>
</view>
</view>
<view class="content">
<view class="goods-container">
<goods-list :list="goodsList" type="activity"></goods-list>
</view>
</view>
</view>
</mescroll-body>
</template>
<script>
import {
getActivityGoodsLists
} from "@/api/activity";
import MescrollMixin from "@/components/mescroll-uni/mescroll-mixins.js";
export default {
mixins: [MescrollMixin], // 使mixin
data() {
return {
upOption: {
empty: {
icon: '/static/images/goods_null.png',
tip: '暂无商品', //
}
},
goodsList: [],
name: '',
title: ''
};
},
onLoad: function(options) {
const {
id,
title,
name
} = this.$Route.query
this.id = id;
this.title = title
this.name = name
uni.setNavigationBarTitle({
title: name
});
},
methods: {
upCallback(page) {
const pageNum = page.num; // , 1
const pageSize = page.size; // , 10
getActivityGoodsLists({
page_size: pageSize,
page_no: pageNum,
id: this.id
}).then(({
data
}) => {
if (page.num == 1) this.goodsList = [];
const curPageData = data.list;
const curPageLen = curPageData.length;
const hasNext = !!data.more;
this.goodsList = this.goodsList.concat(curPageData);
this.mescroll.endSuccess(curPageLen, hasNext);
}).catch(() => {
this.mescroll.endErr()
})
},
}
};
</script>
<style lang="scss">
.activity-detail {
overflow: hidden;
.header {
height: 410rpx;
width: 100%;
position: relative;
.header-bg {
position: absolute;
width: 100%;
height: 100%;
}
.header-con {
position: relative;
padding-top: 50rpx;
.title {
font-size: 60rpx;
}
.desc {
margin-top: 30rpx;
background-color: rgba(256, 203, 203, 0.5);
padding: 4rpx 40rpx;
}
}
}
.content {
position: relative;
margin-top: -140rpx;
padding: 0 20rpx;
}
}
</style>

209
bundle/pages/address_edit/address_edit.vue

@ -0,0 +1,209 @@
<template>
<view class="address-edit">
<view class="form bg-white">
<u-field v-model="addressObj.contact" label="收货人" placeholder="请填写收货人姓名">
</u-field>
<u-field v-model="addressObj.telephone" label="联系方式" placeholder="请填写手机号码">
</u-field>
<view @click="showRegion = true">
<u-field v-model="region" :disabled="true" label="所在地区" placeholder="请选择省、市、区" right-icon="arrow-right">
</u-field>
</view>
<view>
<u-field v-model="addressObj.address" type="textarea" label="详细地址" placeholder="请填写小区、街道、门牌号等信息"
:field-style="{flex: 1, height: '200rpx'}" />
</view>
</view>
<view class="m-t-10 m-b-10 bg-white p-20">
<u-checkbox @click="changeDefault" v-model="addressObj.is_default" shape="circle">
<text class="xs">设置为默认</text>
</u-checkbox>
</view>
<button class="my-btn bg-primary white br60" @tap="formSubmit">完成</button>
<u-select v-model="showRegion" mode="mutil-column-auto" @confirm="regionChange" :list="lists"></u-select>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | likeshop
// +----------------------------------------------------------------------
// |
// | giteehttps://gitee.com/likeshop_gitee
// | githubhttps://github.com/likeshop-github
// | 访https://www.likeshop.cn
// | 访https://home.likeshop.cn
// | 访http://doc.likeshop.cn
// | likeshop
// | likeshopgiteegithub
// | likeshop
// |
// | likeshop
// +----------------------------------------------------------------------
// | author: likeshop.cn.team
// +----------------------------------------------------------------------
import {
editAddress,
getOneAddress,
hasRegionCode,
addAddress
} from '@/api/user';
import area from '@/utils/area'
export default {
data() {
return {
addressObj: {
contact: '',
telephone: '',
province: '',
city: '',
district: '',
address: '',
is_default: false
},
region: '',
addressId: '',
defaultRegion: ['广东省', '广州市', '番禺区'],
defaultRegionCode: '440113',
showRegion: false,
lists: []
};
},
onLoad: function(options) {
this.addressId = parseInt(options.id)
if (options.id) {
uni.setNavigationBarTitle({
title: '编辑地址'
});
this.getOneAddressFun();
} else {
uni.setNavigationBarTitle({
title: '添加地址'
});
this.getWxAddressFun();
}
this.$nextTick(() => {
this.lists = area
})
},
onUnload: function() {
uni.removeStorageSync('wxAddress');
},
methods: {
async formSubmit() {
let {
addressObj: {
contact,
telephone,
province_id,
city_id,
district_id,
is_default,
address
},
addressId,
region,
} = this;
if (!contact) return this.$toast({
title: '请填写收货人姓名'
});
if (!telephone) return this.$toast({
title: '请填写手机号码'
});
if (!region) return this.$toast({
title: '请选择省、市、区'
});
if (!address) return this.$toast({
title: '请填写小区、街道、门牌号等信息'
});
const params = {
contact,
telephone,
province_id: parseInt(province_id),
city_id: parseInt(city_id),
district_id: parseInt(district_id),
is_default: is_default ? 1 : 0,
id: addressId,
address
}
const {code, msg} = addressId ? await editAddress(params) : await addAddress(params)
if (code == 1) {
this.$toast({
title: msg
}, {
tab: 3,
url: 1
});
}
},
regionChange(region) {
this.addressObj.province_id = region[0].value;
this.addressObj.city_id = region[1].value;
this.addressObj.district_id = region[2].value;
this.region = region[0].label + " " + region[1].label + " " + region[2].label
},
getOneAddressFun() {
getOneAddress(this.addressId).then(res => {
if (res.code == 1) {
let {
city,
province,
district
} = res.data;
this.addressObj = res.data;
this.region = `${province} ${city} ${district}`
}
});
},
getWxAddressFun() {
let wxAddress = uni.getStorageSync('wxAddress');
if (!wxAddress) return;
wxAddress = JSON.parse(wxAddress)
let {
userName: contact,
telNumber: telephone,
provinceName: province,
cityName: city,
detailInfo: address
} = wxAddress;
let district = wxAddress.countryName || wxAddress.countyName
hasRegionCode({
province,
city,
district
}).then(res => {
if (res.code == 1) {
if (res.data.province && res.data.city && res.data.district) {
this.region = `${province} ${city} ${district}`;
this.addressObj.province_id = res.data.province;
this.addressObj.city_id = res.data.city;
this.addressObj.district_id = res.data.district;
}
this.addressObj.contact = contact;
this.addressObj.telephone = telephone
this.addressObj.address = address
}
});
}
}
};
</script>
<style lang="scss">
.address-edit {
padding-top: 10rpx;
.my-btn {
margin: 30rpx 26rpx;
text-align: center;
}
}
</style>

43
bundle/pages/after_sales/after_sales.vue

@ -0,0 +1,43 @@
<template>
<view class="post-sale">
<view class="contain">
<tabs :current="active" :bar-width="80" @change="onChange" :is-scroll="false">
<tab v-for="(item, index) in afterSale" :key="index" :name="item.name">
<after-sales-list :type="item.type" :i="index" :index="active"></after-sales-list>
</tab>
</tabs>
</view>
</view>
</template>
<script>
import { afterSaleType } from "@/utils/type";
export default {
data() {
return {
active: 0,
afterSale: [{
name: '售后申请',
type: afterSaleType.NORMAL
}, {
name: '处理中',
type: afterSaleType.HANDLING
}, {
name: '已处理',
type: afterSaleType.FINISH
}]
};
},
methods: {
onChange(index) {
this.active = index
},
}
};
</script>
<style lang="scss">
</style>

235
bundle/pages/after_sales_detail/after_sales_detail.vue

@ -0,0 +1,235 @@
<template>
<view>
<view class="after-sales-detail">
<view class="after-sales-header">
<view class="after-sales-status white lg">
{{afterSale.status_text}}
</view>
</view>
<view class="return-address-contain flex bg-white m-t-20">
<view class="address-title">退货地址</view>
<view class="sm address flex-1">{{afterSale.shop.address}}, {{afterSale.shop.contact}},
{{afterSale.shop.mobile}}</view>
<view class="xs copy-btn flex-none row-center" @tap="onCopy">复制</view>
</view>
<view class="goods-container bg-white m-t-20">
<view class="m-l-20">
<shop-title :shop="{name: afterSale.shop_name, id: afterSale.sid}"></shop-title>
</view>
<view class="goods-item flex">
<view class="goods-img">
<u-image width="180rpx" height="180rpx" border-radius="10rpx"
:src="afterSale.order_goods.image"></u-image>
</view>
<view class="goods-info flex-1 m-l-24">
<view class="line-2">{{afterSale.order_goods.goods_name}}</view>
<view class="m-t-10 xs line-1 muted">{{afterSale.order_goods.spec_value}}</view>
<view class="flex row-between m-t-20">
<price-format :price="afterSale.order_goods.goods_price" :first-size="30" :second-size="30"
:subscript-size="30" />
<view>x{{afterSale.order_goods.goods_num}}</view>
</view>
</view>
</view>
</view>
<view class="return-goods-container bg-white m-t-20">
<view class="return-goods-item flex sm">
<view class="return-title">退款方式</view>
<view class="return-explain">{{afterSale.refund_type_text}}</view>
</view>
<view class="return-goods-item flex sm m-t-20">
<view class="return-title">退款原因</view>
<view class="return-explain">{{afterSale.refund_reason}}</view>
</view>
<view class="return-goods-item flex sm m-t-20">
<view class="return-title">退款金额</view>
<view class="return-explain primary">¥{{afterSale.refund_price}}</view>
</view>
<view class="return-goods-item flex sm m-t-20">
<view class="return-title">退款编号</view>
<view class="return-explain">{{afterSale.sn}}</view>
</view>
<view class="return-goods-item flex sm m-t-20">
<view class="return-title">申请时间</view>
<view class="return-explain">{{afterSale.create_time}}</view>
</view>
</view>
<view class="btn-group fixed bg-white flex row-right" v-if="afterSale.status != 6">
<view class="m-r-20 btn br60" @tap="confirmDialog=true">撤销申请</view>
<router-link :to="{path: '/bundle/pages/apply_refund/apply_refund', query: {after_sale_id: afterSale.id,
order_id: afterSale.order_goods.order_id,
item_id: afterSale.order_goods.item_id}}">
<view class="m-r-20 btn br60 primary" v-if="(afterSale.status == 4 || afterSale.status == 1)">重新申请
</view>
</router-link>
<router-link
:to="{path: '/bundle/pages/input_express_info/input_express_info', query: {id: afterSale.id}}">
<view class="m-r-20 btn br60" v-if="afterSale.status == 2">
填写快递单号
</view>
</router-link>
</view>
</view>
<u-modal v-model="confirmDialog" confirm-text="确定" :showCancelButton="true" :confirm-color="colorConfig.primary"
@confirm="cancelApplyFun">
<view class="flex-col col-center tips-dialog" style="padding: 30rpx 0;">
<image class="icon-lg" src="/static/images/icon_warning.png"></image>
<view class="m-t-30">是否要撤销申请</view>
</view>
</u-modal>
</view>
</template>
<script>
import {
afterSaleDetail,
cancelApply
} from "@/api/user";
import {
trottle,
copy
} from "@/utils/tools.js";
export default {
data() {
return {
afterSale: {
shop: {},
order_goods: {}
},
confirmDialog: false
};
},
onLoad(options) {
},
onShow() {
this.id = this.$Route.query.id
this.afterSaleDetailFun();
},
methods: {
onCopy() {
const {
afterSale
} = this;
const {
address,
contact,
mobile
} = afterSale.shop;
copy(`${address},${contact},${mobile}`)
},
cancelApplyFun() {
cancelApply({
id: this.id
}).then(res => {
if (res.code == 1) {
uni.$emit("refreshsale")
this.$toast({
title: res.msg
}, {
tab: 3,
url: 1
});
}
});
},
afterSaleDetailFun() {
afterSaleDetail({
id: this.id
}).then(res => {
if (res.code == 1) {
this.afterSale = res.data
}
});
}
}
};
</script>
<style lang="scss">
.after-sales-detail {
padding-bottom: calc(120rpx + env(safe-area-inset-bottom));
.after-sales-header {
.after-sales-status {
padding: 48rpx 30rpx;
background-color: #555555;
}
.after-sales-explain {
padding: 20rpx 30rpx 24rpx;
}
}
.return-goods-container {
padding: 20rpx 24rpx 55rpx;
.return-goods-item {
line-height: 40rpx;
}
}
.btn-group {
padding: 0rpx 24rpx;
position: fixed;
left: 0;
right: 0;
bottom: 0;
height: 100rpx;
padding-bottom: env(safe-area-inset-bottom);
box-sizing: content-box;
.btn {
padding: 10rpx 34rpx;
border: 1px solid #999999;
&.primary {
border-color: $-color-primary;
}
}
}
.goods-container {
.goods-item {
padding: 25rpx 24rpx;
.goods-info {
min-width: 500rpx;
}
}
}
}
.return-address-contain {
padding: 20rpx 24rpx 28rpx 30rpx;
.address {
flex: 1;
line-height: 38rpx;
}
.address-title {
width: 150rpx;
align-self: flex-start;
line-height: 40rpx;
}
.copy-btn {
background-color: #F4F4F4;
color: #555555;
padding: 3rpx 16rpx;
margin-left: 12rpx;
border-radius: 4rpx;
}
}
.tips-dialog {
height: 230rpx;
width: 100%;
}
</style>

200
bundle/pages/all_comments/all_comments.vue

@ -0,0 +1,200 @@
<template>
<view>
<mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback" :up="upOption">
<view class="all-comments">
<view class="header bg-white" v-if="!isEmpty">
<view class="title xs">
<text class="lighter m-r-10">商品好评率</text>
<text class="primary">{{percent}}</text>
</view>
<view class="tab flex flex-wrap">
<view v-for="(item, index) in categoryList"
:class="'tab-item xs m-r-10 br60 m-b-20 ' + (type == item.id ? 'bg-primary white' : 'bg-gray' )"
:key="index" @tap="onChangType(index)" v-show="item.count">
{{item.name}}({{item.count}})
</view>
</view>
</view>
<view class="main bg-white">
<view class="evaluation-list">
<view v-for="(item, index) in commentList" :key="index" class="evaluation-item">
<view class="user-info flex">
<image class="avatar m-r-20" :src="item.avatar"></image>
<view class="user-name md m-r-10">{{item.nickname}}</view>
<u-rate disabled size="26rpx" :color="colorConfig.primary" v-model="item.goods_comment">
</u-rate>
</view>
<view class="muted xs m-t-10">
<text class="m-r-20">{{item.create_time}}</text>
<text v-show="item.spec_value_str">{{item.spec_value_str}}</text>
</view>
<view v-if="item.comment" class="dec m-t-20">{{item.comment}}</view>
<view class="img m-t-20 flex flex-wrap" v-if="item.image.length">
<view v-for="(imgitem, imgindex) in item.image" :key="imgindex"
class="img-item m-r-20 m-b-20" :data-current="imgitem" :data-uri="item.image"
@tap="previewImage">
<u-image width="160rpx" fit="cover" height="160rpx" radius="6rpx" lazy-load
class="goods-img" :src="imgitem" />
</view>
</view>
<view class="seller-recall-container bg-gray m-t-10" v-if="item.reply">
<view class="lighter">
商家回复
<text class="normal">{{item.reply}}</text>
</view>
</view>
</view>
</view>
</view>
</view>
</mescroll-body>
</view>
</template>
<script>
import {
getCommentList,
getCommentCategory
} from '@/api/store';
import MescrollMixin from "@/components/mescroll-uni/mescroll-mixins";
export default {
mixins: [MescrollMixin],
data() {
return {
active: 0,
type: '',
commentList: [],
categoryList: [],
percent: '',
isEmpty: true,
upOption:{
auto: false,
empty: {
icon: '/static/images/goods_null.png',
tip : "暂无评价",
}
},
};
},
onLoad(options) {
this.id = this.$Route.query.id;
},
onShow() {
this.id = this.$Route.query.id;
},
methods: {
async downCallback(page) {
await this.getCommentCategoryFun()
this.mescroll.resetUpScroll();
},
upCallback(page) {
let pageNum = page.num; // , 1
let pageSize = page.size; // , 10
getCommentList({
type: this.type,
goods_id: this.id,
page_no: pageNum,
page_size: pageSize
}).then(res => {
if (res.code == 1) {
let curPageData = res.data.lists;
let curPageLen = curPageData.length;
let hasNext = !!res.data.more;
if (page.num == 1) this.commentList = [];
this.commentList = this.commentList.concat(curPageData);
this.mescroll.endSuccess(curPageLen, hasNext);
}
})
},
onChangType(index) {
this.active = index
this.type = this.categoryList[index].id
this.commentList = []
this.mescroll.resetUpScroll();
},
getCommentCategoryFun() {
return new Promise(resolve => {
getCommentCategory(this.id).then(res => {
let {
code,
data: {
comment,
percent
}
} = res;
if (code == 1) {
this.categoryList = comment;
this.percent = percent;
this.type = comment[this.active].id
this.isEmpty = !comment[0].count
this.$nextTick(() => resolve());
}
});
});
},
previewImage(e) {
const {
current,
uri
} = e.currentTarget.dataset;
let urls = uri;
uni.previewImage({
current,
// http
urls // http
});
}
}
};
</script>
<style lang="scss">
.all-comments {
padding-top: 20rpx;
.header {
.title {
padding: 24rpx 26rpx;
border-bottom: var(--border);
}
.tab {
padding: 30rpx 0 10rpx 20rpx;
flex-wrap: wrap;
.tab-item {
padding: 9rpx 29rpx;
}
}
}
.main {
.evaluation-list {
.evaluation-item {
padding: 20rpx;
&:not(:last-of-type) {
border-bottom: $-solid-border;
}
.avatar {
width: 60rpx;
height: 60rpx;
border-radius: 50%;
}
.seller-recall-container {
padding: 24rpx 20rpx;
border-radius: 12rpx;
}
}
}
}
}
</style>

260
bundle/pages/apply_refund/apply_refund.vue

@ -0,0 +1,260 @@
<template>
<view class="apply-refund">
<view class="goods bg-white m-t-20">
<view class="flex">
<u-image width="160rpx" height="160rpx" border-radius="6rpx" lazy-load :src="goods.image" />
<view class="goods-info">
<view class="line-2">{{goods.goods_name}}</view>
<view class="xs muted m-t-10">{{goods.spec_value}}</view>
</view>
</view>
</view>
<view class="opt-box m-t-20 bg-white">
<view v-show="!hiddenOpt">
<view class="opt-item flex row-between border-line" @tap="onlyRefund">
<view>
<view class="lg">仅退款</view>
<view class="muted xs m-t-10">未收到货与卖家协商同意无需退货只需退款</view>
</view>
<u-icon class="m-l-10" name="arrow-right" size="28" />
</view>
<view class="opt-item flex row-between" @tap="allRefunds">
<view>
<view class="lg">退货退款</view>
<view class="muted xs m-t-10">已收到货需退还收到的实物</view>
</view>
<u-icon class="m-l-10" name="arrow-right" size="28" />
</view>
</view>
<view v-show="hiddenOpt">
<view class="refund-info flex row-between m-t-20">
<view class="lable">数量</view>
<view>{{goods.goods_num}}</view>
</view>
<view class="refund-info flex row-between">
<view class="lable">退款金额</view>
<price-format :color="colorConfig.primary" :price="goods.total_pay_price" />
</view>
<view class="refund-info flex row-between" @tap="showPop=true">
<view class="lable">退款原因</view>
<view class="flex">
<text :class="{muted: !reasonString}">{{reasonString ? reasonString : '请选择' }}</text>
<u-icon class="m-l-10" name="arrow-right" size="28" />
</view>
</view>
<view class="refund-info flex col-top">
<view class="label">备注说明</view>
<view class="flex-1" style="background-color: #F8F8F8;">
<u-input v-model="remark" type="textarea" placeholder="请描述申请售后的具体原因,100字以内" :border="false"
:height="160" />
</view>
</view>
<view class="upload bg-white">
<view class="title flex row-between">
<view>上传凭证</view>
<view class="muted">选填最多可上传1张</view>
</view>
<u-upload ref="uUpload" :show-progress="false" :header="{token: $store.getters.token}"
:max-count="1" width="160" height="160" :action="action" upload-text="上传图片"
@on-success="onSuccess" @on-remove="onRemove" />
</view>
</view>
</view>
<button v-show="hiddenOpt" class="btn br60" type="primary" size="lg" @tap="onSubmit">申请退款</button>
<u-select v-model="showPop" mode="single-column" value-name="index" label-name="name" :list="reason"
@confirm="confirmSelect"></u-select>
</view>
</template>
<script>
import {
refundOptType
} from "@/utils/type";
import {
baseURL
} from '@/config/app';
import {
getGoodsInfo,
applyAfterSale,
applyAgain
} from "@/api/user";
import {
uploadFile,
trottle
} from '@/utils/tools.js';
export default {
data() {
return {
action: baseURL + '/api/file/formimage',
hiddenOpt: false,
optTyle: refundOptType.ONLY_REFUND,
goods: {},
reason: [],
showPop: false,
reasonString: '',
fileList: [],
remark: ""
};
},
onLoad(options) {
const {
order_id,
item_id,
after_sale_id
} = this.$Route.query
this.orderId = order_id;
this.itemId = item_id;
this.afterSaleId = after_sale_id;
this.getGoodsInfoFun();
this.onSubmit = trottle(this.onSubmit, 1000, this)
},
methods: {
confirmSelect(e) {
this.reasonString = e[0].label
},
onlyRefund() {
this.optTyle = refundOptType.ONLY_REFUND
this.hiddenOpt = true
},
allRefunds() {
this.optTyle = refundOptType.REFUNDS;
this.hiddenOpt = true;
},
onSuccess(e) {
this.fileList.push(e.data.base_uri)
},
onRemove(index) {
this.fileList.splice(index, 1)
console.log(index)
},
async onSubmit() {
const {
reason,
reasonString,
optTyle,
remark,
fileList
} = this;
if (!reasonString) {
return this.$toast({
title: '请选择退款原因'
});
}
const params = {
reason: reasonString,
refund_type: optTyle,
remark: remark,
img: fileList.length ? fileList[0] : ''
};
if (this.afterSaleId) {
params.id = this.afterSaleId
} else {
params.item_id = this.itemId
params.order_id = this.orderId
}
const {
data,
code,
msg
} = this.afterSaleId ? await applyAgain(params) : await applyAfterSale(params)
if (code == 1) {
this.$toast({
title: msg
});
uni.$emit("refreshsale")
setTimeout(() => {
this.$Router.replace({
path: '/bundle/pages/after_sales_detail/after_sales_detail',
query: {
id: data.after_sale_id
}
})
}, 1000)
}
},
getGoodsInfoFun() {
let {
orderId,
itemId
} = this;
getGoodsInfo({
order_id: orderId,
item_id: itemId
}).then(res => {
if (res.code == 1) {
this.goods = res.data.goods;
this.reason = res.data.reason.map((item, index) => ({
name: item,
index
}));
}
});
}
}
};
</script>
<style lang="scss">
.apply-refund {
padding-bottom: 50rpx;
.goods {
padding: 20rpx 24rpx;
.goods-info {
margin-left: 24rpx;
flex: 1;
}
}
}
.opt-box {
.opt-item {
padding: 20rpx 20rpx 30rpx;
}
}
.apply-refund {
.refund-info {
padding: 24rpx 20rpx;
border-bottom: $-solid-border;
.label {
width: 140rpx;
margin-top: 19rpx;
}
textarea {
flex: 1;
height: 172rpx;
border-radius: 10rpx;
padding: 20rpx;
box-sizing: border-box;
}
}
.upload {
padding: 0 20rpx 30rpx;
.title {
padding: 24rpx 0;
}
}
.btn {
margin: 30rpx 26rpx
}
}
</style>

161
bundle/pages/bargain/bargain.vue

File diff suppressed because one or more lines are too long

77
bundle/pages/bargain_code/bargain_code.vue

@ -0,0 +1,77 @@
<template>
<view class="bargain-code-container">
<tabs :active="active" @change="onChange" :isScroll="false">
<tab v-for="(item, index) in bargain" :key="item.type" :name="item.name" >
<bargain-list :ref="item.ref_name" :bargainType="item.type" v-if="item.isShow" />
</tab>
</tabs>
</view>
</template>
<script>
import {bargainType} from "@/utils/type"
export default {
data() {
return {
active: 0,
bargainCodeType: bargainType.ALL,
bargain: [{
name: '全部',
type: bargainType.ALL,
ref_name: 'all',
isShow: true
}, {
name: '砍价中',
type: bargainType.BARGINNING,
ref_name: 'barginning',
isShow: false
}, {
name: "砍价成功",
type: bargainType.SUCCESS,
ref_name: 'success',
isShow: false
}, {
name: '砍价失败',
type: bargainType.FAIL,
ref_name: 'fail',
isShow: false
}]
}
},
onLoad(options) {
},
onReachBottom: function () {
const {
active, bargain
} = this;
let type = bargain[active].ref_name;
let myComponent = this.$refs[type][0];
if (myComponent.$getBargainActivityList) {
myComponent.$getBargainActivityList();
}
},
methods: {
onChange(active) {
const {bargain} = this;
console.log(active)
let type = bargain[active].ref_name
let index = bargain.findIndex(item => {
return item.ref_name == type;
});
if (index != -1) {
this.bargain[index].isShow = true;
this.active = index;
}
this.$nextTick(() => {
console.log(this.$refs, "refs", type)
console.log('this.$refs[all]', this.$refs['all'])
if(this.$refs[type] && this.$refs[type][0].$getBargainActivityList) {
this.$refs[type][0].$getBargainActivityList();
}
})
}
}
}
</script>

734
bundle/pages/bargain_process/bargain_process.vue

File diff suppressed because one or more lines are too long

637
bundle/pages/chat/chat.vue

@ -0,0 +1,637 @@
<template>
<view class="chat flex-col">
<view class="content" @tap="showEmoji = false">
<scroll-view style="height: 100%;" :scroll-y="true" :scroll-top="scrollTop" :scroll-into-view="intoView"
@scrolltoupper="scrollToupper">
<view class="loading flex row-center" v-if="pageStatus == 'loading'">
<u-loading mode="flower" size="40"></u-loading>
</view>
<view class="chat-lists">
<view class="chat-item" v-for="(item,index) in recoreds" :id="`chat-item_${item.id}`" :key="item.id"
:class="{
'right': item.from_type == 'user',
'left': item.from_type == 'kefu',
'visibility': showIndex > index
} ">
<!-- 普通聊天记录 -->
<template v-if="item.type == 1">
<!-- 时间 -->
<view class="text-center m-b-30 white" v-if="timeFormat(item,index)">
<view class="chat-tips xs">{{timeFormat(item,index)}}</view>
</view>
<view class="chat-info">
<image class="avatar" :src="$getImageUri(item.from_avatar)">
</image>
<!-- 文本 -->
<view class="text-box" v-if="item.msg_type == 1">
<rich-text :nodes="replaceEmoji(item.msg)" space="nbsp"></rich-text>
</view>
<!-- 图片 -->
<view class="image-box" v-if="item.msg_type == 2">
<image class="image" mode="widthFix" :src="$getImageUri(item.msg)"
@tap="previewImage($getImageUri(item.msg))">
</image>
</view>
<!-- 商品 -->
<view class="goods m-r-20 goods-box" v-if="item.msg_type == 3">
<view class="goods-img m-r-20">
<image style="width: 140rpx;height: 140rpx;"
:src="$getImageUri(item.goods.image)">
</image>
</view>
<view class="goods-info flex-1">
<view class="line-2">
{{item.goods.name}}
</view>
<view class="flex m-t-10 row-between">
<price-format :color="colorConfig.primary" :subscript-size="26"
:first-size="38" :second-size="26" :price="item.goods.min_price">
</price-format>
</view>
</view>
</view>
</view>
</template>
<!-- 通知类型记录 -->
<template v-else>
<view class="text-center white">
<view class="muted xs">{{item.msg}}</view>
</view>
</template>
</view>
</view>
<view class="error" v-if="isError">
<view class="error-msg text-center xs">{{errorMsg}}</view>
</view>
<view id="bottom"></view>
</scroll-view>
</view>
<view class="footer" @tap="showGoods = false">
<view class="footer-input flex">
<view class="album" @tap="uploadFile">
<image class="icon" src="@/static/images/icon_album.png"></image>
</view>
<view class="input-contain flex">
<input v-model="msg" class="text-area" confirm-type="send" maxlength="-1"
@focus="scrollToBottom" @confirm="sendText" />
<image class="icon" src="@/static/images/icon_emoji.png" @tap="handleEmojiShow"></image>
</view>
<button size="sm" class="send-btn" @tap="sendText">发送</button>
</view>
<view class="emoji-wrap" :class="{'emoji-show': showEmoji}">
<scroll-view style="height:100%;" scroll-y="true">
<emoji @input="handleEmojiInput"></emoji>
</scroll-view>
</view>
</view>
<view class="goods" v-if="showGoods">
<view class="close" @tap="showGoods = false">
<u-icon name="close-circle-fill" color="#ccc" size="40"></u-icon>
</view>
<view class="goods-img m-r-20">
<u-image width="140rpx" height="140rpx" :src="goodsInfo.image"></u-image>
</view>
<view class="goods-info flex-1">
<view class="line-2">
{{goodsInfo.name}}
</view>
<view class="flex m-t-10 row-between">
<price-format :color="colorConfig.primary" :subscript-size="26" :first-size="38" :second-size="26"
:price="goodsInfo.min_price">
</price-format>
<view class="send-btn" @tap="sendGoods">发送链接</view>
</view>
</view>
</view>
</view>
</template>
<script>
import Socket from '@/utils/socket'
import {
chatRecord
} from '@/api/user'
import {
getChatConfig
} from '@/api/app'
import {
getGoodsDetail
} from '@/api/store'
import {
client,
uploadFile,
getRect,
debounce
} from '@/utils/tools'
import {
timeFormatChat
} from '@/utils/date'
import {
mapMutations
} from 'vuex';
export default {
data() {
return {
pageStatus: 'loading',
scrollTop: '',
intoView: '',
page: 1,
msg: '',
socket: {},
kefu: {},
showEmoji: false,
recoreds: [],
errorMsg: '',
goodsInfo: {},
isError: false,
showGoods: false,
showIndex: -1
}
},
computed: {
//
timeFormat() {
return (item, index) => {
let timeFmt = timeFormatChat(item.create_time_stamp)
if (index && item.create_time_stamp - this.recoreds[index - 1].create_time_stamp < 300 && !item
.show_time) {
timeFmt = ''
}
return timeFmt
}
},
//
replaceEmoji() {
return (str) => str.replace(/\[em-([a-z_]+)\]/g, `<span class="em em-$1"></span>`)
},
//
$getImageUri() {
return (url) => this.$store.state.app.config.base_domain + url
}
},
watch: {
kefu(val) {
if (val.id) {
this.setTitle(val.nickname)
}
}
},
methods: {
//
init() {
this.shopId = this.$Route.query.shop_id || 0
this.goodsId = this.$Route.query.goods_id
this.socket = new Socket(this.appConfig.ws_domain, {
token: this.$store.getters.token,
type: 'user',
client,
shop_id: this.shopId,
})
this.socket.addEvent('connect', () => {
this.setTitle('连接中...')
})
this.socket.addEvent('open', () => {
this.setTitle(this.kefu.nickname)
this.isError = false
})
this.socket.addEvent('message', (data) => {
switch (data.event) {
case 'login':
this.loginEvent(data.data)
break;
case 'chat':
this.chatEvent(data.data)
break;
case 'transfer':
this.transferEvent(data.data)
break;
case 'error':
this.errorEvent(data.data)
break;
}
})
this.socket.addEvent('error', (data) => {
this.setTitle('连接失败')
})
},
showTips(msg) {
if (!msg) {
setTimeout(() => {
this.$Router.replace({
path: `/bundle/pages/contact_offical/contact_offical?id=${this.shopId}`
});
}, 200)
return
}
uni.showModal({
title: '温馨提示',
content: msg,
success: (res) => {
if (res.confirm) {
this.$Router.replace({
path: `/bundle/pages/contact_offical/contact_offical?id=${this.shopId}`
});
} else if (res.cancel) {
this.$Router.back()
}
}
});
},
getConfig() {
return getChatConfig({
shop_id: this.shopId
}).then(res => {
return Promise.resolve(res)
}).catch(() => {
return Promise.reject()
})
},
//
async getData() {
try {
const res = await this.getConfig()
if (res.code == 0) return this.showTips(res.msg)
await this.getChatRecord()
this.getGoods()
this.scrollToBottom()
if (!this.kefu.id) {
this.setTitle('客服不在线')
return
}
this.socket.connect()
} catch (e) {
}
},
getGoods() {
if (!this.goodsId) return
getGoodsDetail({
goods_id: this.goodsId
}).then(res => {
if (res.code == 1) {
this.goodsInfo = res.data
if (this.kefu.id) {
this.showGoods = true
}
}
})
},
//
previewImage(url) {
uni.previewImage({
urls: [url]
});
},
//
async uploadFile() {
const [error, success] = await uni.chooseImage({
count: 1
})
if (error) {
return
}
uni.showLoading({
title: '上传中...'
})
try {
const file = await uploadFile(success.tempFilePaths[0])
this.send(file.base_uri, 2)
uni.hideLoading()
} catch (e) {
this.$toast({
title: '上传失败,请稍后再试'
})
uni.hideLoading()
}
},
//
sendText() {
if (!this.msg) return
this.send(this.msg, 1)
this.msg = ''
},
//
sendGoods() {
this.showGoods = false
this.send(this.goodsId, 3)
},
//
async getChatRecord() {
const {
page,
pageStatus
} = this
if (pageStatus == 'finish') return
const res = await chatRecord({
shop_id: this.shopId,
page_no: page
})
if (res.code == 1) {
let toid = 0
this.page++
const {
kefu,
record
} = res.data
this.kefu = kefu
this.showIndex = record.list.length
if (this.recoreds.length) {
toid = this.recoreds[0].id
this.recoreds[0].show_time = true
}
this.recoreds.unshift(...record.list)
this.$nextTick(() => {
if (!record.more) {
this.pageStatus = 'finish'
}
this.scrollToItem(toid)
this.showIndex = -1
})
}
},
//
send(msg, type) {
this.socket.send({
event: 'chat',
data: {
msg,
msg_type: type, // 1=>2=>3=>
to_id: this.kefu.id, // iduser_id, kefu_id
to_type: "kefu"
}
})
},
//
handleEmojiShow() {
this.showEmoji = !this.showEmoji
if (!this.showEmoji) return
setTimeout(() => {
this.scrollToBottom()
}, 300)
},
scrollToupper() {
this.getChatRecord()
},
scrollToBottom() {
this.intoView = 'bottom'
this.$nextTick(() => {
this.intoView = ''
})
},
scrollToItem(id) {
this.intoView = `chat-item_${id}`
this.$nextTick(() => {
this.intoView = ''
})
},
handleEmojiInput(val) {
this.msg = this.msg + val
},
chatEvent(data) {
this.isError = false
if (data.from_type == 'kefu') {
uni.vibrateLong({
success: function() {
console.log('success');
}
});
}
if (data.shop_id != this.shopId) {
return
}
this.recoreds.push(data)
this.$nextTick(() => {
getRect('#bottom').then(res => {
if (res.bottom < 1000) {
this.scrollToItem(data.id)
}
})
})
},
errorEvent(data) {
this.errorMsg = data.msg
this.isError = true
this.$nextTick(() => {
this.scrollToBottom()
})
},
loginEvent(data) {
// 线
this.socket.send({
event: 'user_online',
data: {
kefu_id: this.kefu.id
}
})
},
transferEvent(data) {
this.kefu = data
},
setTitle(title) {
uni.setNavigationBarTitle({
title
})
}
},
async onLoad() {
this.scrollToupper = debounce(this.scrollToupper, 500, this)
this.init()
this.getData()
},
onUnload() {
this.socket.close()
},
onReady() {
}
}
</script>
<style lang="scss">
page {
pading: 0;
height: 100%;
}
.chat {
height: 100%;
.goods {
display: flex;
position: fixed;
width: 600rpx;
right: 20rpx;
bottom: calc(120rpx + env(safe-area-inset-bottom));
border-radius: 14rpx;
background: #fff;
padding: 20rpx;
.close {
position: absolute;
left: -20rpx;
top: -20rpx;
}
.send-btn {
padding: 8rpx 22rpx;
}
}
.content {
transition: all .3s;
flex: 1;
min-height: 0;
.loading {
padding: 20rpx;
height: 40px;
}
.chat-lists {
padding: 0 20rpx 30rpx;
overflow: hidden;
position: relative;
.chat-tips {
padding: 4rpx 20rpx;
border-radius: 21rpx;
display: inline-block;
text-align: center;
background-color: rgba(0, 0, 0, 0.2);
}
.chat-item {
padding-top: 30rpx;
&.visibility {
visibility: hidden;
}
.chat-info {
display: flex;
align-items: flex-start;
}
&.right {
.chat-info {
flex-direction: row-reverse;
.text-box {
background-color: #ED5349;
color: #fff;
}
}
}
.avatar {
width: 78rpx;
height: 78rpx;
border-radius: 14rpx;
flex: none;
}
.text-box {
max-width: 500rpx;
min-width: 80rpx;
background-color: #fff;
border-radius: 14rpx;
padding: 16rpx 20rpx;
margin: 0 20rpx;
word-break: break-word;
line-height: 40rpx;
}
.image-box {
max-width: 300rpx;
margin: 0 20rpx;
.image {
max-width: 100%;
}
}
.goods-box {
position: static;
width: 510rpx;
}
}
}
}
.error {
padding: 0 30rpx 30rpx;
.error-msg {
color: #bbb;
word-break: break-word;
}
}
.footer {
background: #f2f2f2;
padding-bottom: env(safe-area-inset-bottom);
.footer-input {
height: 100rpx;
padding: 0 20rpx;
.icon {
width: 52rpx;
height: 52rpx;
}
.input-contain {
margin: 0 20rpx;
background-color: #fff;
height: 68rpx;
border-radius: 60rpx;
flex: 1;
overflow: hidden;
padding: 0 10rpx 0 30rpx;
.text-area {
flex: 1;
height: 100rpx;
word-break: break-all;
}
}
}
}
.emoji-wrap {
height: 0;
transition: all .3s;
&.emoji-show {
height: 200px;
}
}
.send-btn {
padding: 0 25rpx;
color: #fff;
background-color: #ED5349;
border-radius: 60rpx;
}
}
</style>

63
bundle/pages/commission_details/commission_details.vue

@ -0,0 +1,63 @@
<template>
<view class="commission-details">
<mescroll-body ref="mescrollRef" @init="mescrollInit" @up="upCallback" :up="upOption" :down="downOption" @down="downCallback">
<view class="p-t-20" >
<view class="bg-white" v-for="(item, index) in list" :key="index" >
<record-cell :remark="item.source_type" :date="item.create_time" :money="item.change_amount" :type="item.change_type" />
</view>
</view>
</mescroll-body>
</view>
</template>
<script>
import MescrollMixin from "@/components/mescroll-uni/mescroll-mixins.js";
import {getCommission} from "@/api/user"
export default {
mixins: [MescrollMixin], // 使mixin
data() {
return {
// Tabs
upOption: {
empty: {
icon: '/static/images/order_null.png',
tip: '暂无记录', //
}
},
list: [], // --
};
},
methods: {
//
upCallback(page) {
const pageNum = page.num; // , 1
const pageSize = page.size; // , 10
getCommission({
page_size: pageSize,
page_no: pageNum,
}).then(({
data
}) => {
if (page.num == 1) this.list = [];
const curPageData = data.list;
const curPageLen = curPageData.length;
const hasNext = !!data.more;
this.list = this.list.concat(curPageData);
this.mescroll.endSuccess(curPageLen, hasNext);
}).catch(() => {
this.mescroll.endErr()
})
}
},
}
</script>
<style scoped>
</style>

158
bundle/pages/contact_offical/contact_offical.vue

@ -0,0 +1,158 @@
<template>
<view class="contact-offical" v-show="isShow" :class="{'shop-contact': shopId}">
<template v-if="shopId">
<view class="header white" >
<view class="title font-size-50 text-center">店铺客服</view>
<view class="line m-t-36"></view>
</view>
<view class="content flex-col col-center">
<view class="content-view flex-col col-center bg-white text-center">
<view class="flex col-center m-b-40 m-l-40" style="align-self: flex-start;">
<u-image width="88rpx" height="88rpx" border-radius="50%" :src="server.shop.logo" />
<view class="lg m-l-20">{{server.shop.name}}</view>
</view>
<u-image width="360rpx" height="360rpx" :src="server.config.image" />
<view v-if="server.config.wechat" class="flex row-center copy-btn white lg br60 m-t-50 m-b-40" @click="onCopy(server.config.wechat)">
复制去微信添加
</view>
<view class="lighter xs">营业时间{{server.config.business_time}}</view>
<view class="xs lighter m-t-10 flex">
客服电话{{server.config.phone}}
<view class="phone-btn m-l-30" @tap="showPhoneCall=true">拨打</view>
</view>
</view>
</view>
<u-modal :content="'即将打电话给'+ server.config.phone" v-model="showPhoneCall" show-cancel-button confirm-text='呼叫'
:confirm-color="colorConfig.primary" @confirm="onCall">
</u-modal>
</template>
<template v-else>
<view class="header white" >
<view class="title font-size-50 text-center">平台客服</view>
<view class="line m-t-36"></view>
</view>
<view class="content flex-col col-center">
<view class="content-view flex-col col-center bg-white text-center">
<u-image width="360rpx" height="360rpx" :src="server.image" />
<view v-if="server.wechat" class="flex row-center copy-btn lg br60 white m-t-50 m-b-40" @click="onCopy(server.wechat)">
复制去微信添加
</view>
<view class="lighter xs">营业时间{{server.business_time}}</view>
<view class="xs lighter m-t-10 flex">
平台电话{{server.phone}}
<view class="phone-btn m-l-30" @tap="showPhoneCall=true">拨打</view>
</view>
</view>
</view>
<u-modal :content="'即将打电话给'+ server.phone" v-model="showPhoneCall" show-cancel-button confirm-text='呼叫'
:confirm-color="colorConfig.primary" @confirm="onCall">
</u-modal>
</template>
</view>
</template>
<script>
import {
getService,
getChatConfig
} from "@/api/app"
import {
getShopService
} from "@/api/shop"
import {
copy
} from '@/utils/tools'
export default {
name: 'contactOffical',
data() {
return {
server: {
config: {},
shop: {}
},
showPhoneCall: false,
shopId: 0,
isShow: false
}
},
onLoad() {
this.shopId = Number(this.$Route.query.id)
this.getServiceFun()
},
methods: {
async getServiceFun() {
const {data, code} = this.shopId ? await getShopService(this.shopId) : await getService()
if(code == 1) {
this.server = data
this.isShow = true
}
},
onCopy(str) {
copy(str);
},
onCall() {
wx.makePhoneCall({
phoneNumber: String(this.server.config && this.server.config.phone || this.server.phone),
success(e) {
console.log('成功', e)
},
fail(err) {
console.log('失败', err)
}
})
}
}
}
</script>
<style lang="scss">
page {
padding: 0;
}
.contact-offical {
min-height: 100vh;
background-image: url(../../static/contact_official_bg.png);
background-position: center;
background-size: cover;
background-repeat: no-repeat;
&.shop-contact {
background-image: url(../../static/shop_official_bg.png);
.header{
.line {
background:#3A67E4;
}
}
}
.header {
padding: 80rpx 50rpx 0;
.line {
height: 25rpx;
background: #BE000E;
border-radius: 20rpx;
}
}
.content {
margin-top: -10rpx;
.content-view {
width: 620rpx;
padding: 80rpx 20rpx 40rpx;
}
.phone-btn {
padding: 2rpx 19rpx;
border: 1px solid #D7D7D7;
border-radius: 10rpx;
}
.copy-btn {
background: linear-gradient(#12c96e 0%, #0abd57 50.76%, #03b240 100%);
width: 460rpx;
height: 84rpx;
box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.16);
}
}
}
</style>

61
bundle/pages/exchange_order/exchange_order.vue

@ -0,0 +1,61 @@
<template>
<view class="user-order">
<tabs :current="active" @change="changeShow" bar-width="60" :is-scroll="true">
<tab v-for="(item, index) in order" :key="index" :name="item.name">
<exchange-order-list :order-type="item.type" :i="index" :index="active"></exchange-order-list>
</tab>
</tabs>
<float-tab></float-tab>
</view>
</template>
<script>
export default {
data() {
return {
active: -1,
order: [{
name: '全部',
type: ''
}, {
name: '待付款',
type: 0
}, {
name: '待发货',
type: 1
}, {
name: '待收货',
type: 2
}, {
name: '已完成',
type: 3
}, {
name: '已关闭',
type: 4
}]
};
},
methods: {
changeShow(index) {
if (index != -1) {
this.$nextTick(() => {
this.active = index
})
}
},
},
onLoad(options) {
const {
order
} = this
let type = this.$Route.query.type || '';
let index = order.findIndex(item => item.type == type)
this.changeShow(index);
},
};
</script>
<style>
</style>

369
bundle/pages/exchange_order_details/exchange_order_details.vue

@ -0,0 +1,369 @@
<template>
<view>
<view class="order-details">
<view class="header-bg"></view>
<view class="main">
<view class="header">
<view class="item" v-if="orderDetail.order_status == 0">
<view class="white lg m-b-10">等待买家付款</view>
</view>
<view class="item" v-if="orderDetail.order_status == 1">
<view class="white lg m-b-10">待发货</view>
<view class="white sm">您的商品正在打包中请耐心等待</view>
</view>
<view class="item" v-if="orderDetail.order_status == 2">
<view class="white lg m-b-10">待收货</view>
<view class="white sm">您的商品正在路中请耐心等待</view>
</view>
<view class="item" v-if="orderDetail.order_status == 3">
<view class="white lg m-b-10">已完成</view>
<view class="white sm">商品已签收期待再次购买</view>
</view>
<view class="item" v-if="orderDetail.order_status == 4">
<view class="white lg m-b-10">订单已关闭</view>
<!-- <view class="white sm">原因超时未支付</view> -->
</view>
</view>
<view class="address-wrap flex contain">
<image class="icon-md m-r-20" src="/static/images/icon_address.png"></image>
<view class="address">
<view>
<text class="name md m-r-10">{{orderDetail.consignee}}</text>
<text class="phone md">{{orderDetail.mobile}}</text>
<view class="area sm m-t-10 lighter">{{orderDetail.delivery_address}}</view>
</view>
</view>
</view>
<view class="goods contain">
<view class="flex">
<u-image :src="orderDetail.goods.image" border-radius="10" width="160" height="160"></u-image>
<view class="goods-info flex-1 m-l-20">
<view class="goods-name line-2">{{ orderDetail.goods.name }}</view>
<view class="flex row-between">
<view class="goods-price primary m-t-10">
<price-format :show-subscript="false" :first-size="36" :second-size="24"
:price="orderDetail.goods.need_integral" />
<text class="xs">积分</text>
<block v-if="orderDetail.goods.exchange_way === 2">
<text>+</text>
<price-format :show-subscript="false" :first-size="36" :second-size="24"
:price="orderDetail.goods.need_money" />
<text class="xs"></text>
</block>
</view>
<view class="lighter">×{{orderDetail.total_num}}</view>
</view>
</view>
</view>
</view>
<view class="price contain">
<view class="flex row-between">
<view>商品金额</view>
<view class="black">
<price-format :show-subscript="false" :price="orderDetail.order_integral" />
<text class="xs">积分</text>
<block v-if="orderDetail.goods_price > 0">
<text>+</text>
<price-format :show-subscript="false" :price="orderDetail.goods_price" />
<text class="xs"></text>
</block>
</view>
</view>
<view class="flex row-between" v-if="orderDetail.shipping_price">
<view>运费</view>
<view class="black">+
<price-format :price="orderDetail.shipping_price"></price-format>
</view>
</view>
<view class="flex row-right">
<view class="lighter">实付金额</view>
<view class="primary">
<price-format :show-subscript="false" :first-size="36" :second-size="24"
:price="orderDetail.order_integral" />
<text class="xs">积分</text>
<block v-if="orderDetail.order_amount > 0">
<text>+</text>
<price-format :show-subscript="false" :first-size="36" :second-size="24"
:price="orderDetail.order_amount" />
<text class="xs"></text>
</block>
</view>
</view>
</view>
<view class="order-info contain">
<view class="item flex" style="align-items: flex-start;">
<view class="title">买家留言</view>
<view class="black">{{orderDetail.user_remark || '无'}}</view>
</view>
</view>
<view class="order-info contain">
<view class="item flex">
<view class="title">订单编号</view>
<view class="black">{{orderDetail.order_sn}}</view>
</view>
<view class="item flex">
<view class="title">支付方式</view>
<view class="black">{{orderDetail.pay_way}}</view>
</view>
<view class="item flex">
<view class="title">下单时间</view>
<view class="black">{{orderDetail.create_time}}</view>
</view>
<view v-if="orderDetail.pay_time" class="item flex">
<view class="title">付款时间</view>
<view class="black">{{orderDetail.pay_time}}</view>
</view>
<view v-if="orderDetail.shipping_time" class="item flex">
<view class="title">发货时间</view>
<view class="black">{{orderDetail.shipping_time }}</view>
</view>
<view v-if="orderDetail.confirm_take_time" class="item flex">
<view class="title">成交时间</view>
<view class="black">{{orderDetail.confirm_take_time }}</view>
</view>
<view v-if="orderDetail.cancel_time" class="item flex">
<view class="title">关闭时间</view>
<view class="black">{{orderDetail.cancel_time}}</view>
</view>
</view>
<view class="footer bg-white flex fixed"
v-if="orderDetail.btns.cancel_btn || orderDetail.btns.delivery_btn || orderDetail.btns.confirm_btn || orderDetail.btns.del_btn || orderDetail.btns.pay_btn">
<view class="flex-1"></view>
<view v-if="orderDetail.btns.cancel_btn">
<button size="sm" class="plain br60" hover-class="none" @tap="handleOrder(0)">取消订单</button>
</view>
<router-link
v-if="orderDetail.btns.delivery_btn"
:to="{path: '/bundle/pages/goods_logistics/goods_logistics', query: {id: orderDetail.id, type: 'integral'}}">
<button size="sm" class="plain br60" hover-class="none">查看物流</button>
</router-link>
<view v-if="orderDetail.btns.confirm_btn" class="m-l-20">
<button size="sm" class="plain br60 primary red" hover-class="none"
@tap.stop="handleOrder(2)">确认收货</button>
</view>
<view v-if="orderDetail.btns.del_btn">
<button size="sm" class="plain br60" hover-class="none" @tap="handleOrder(1)">删除订单</button>
</view>
<view class="m-l-20" v-if="orderDetail.btns.pay_btn">
<button size="sm" class="bg-primary br60 white" @tap="payNow">立即付款</button>
</view>
</view>
</view>
</view>
<loading-view v-if="isFirstLoading"></loading-view>
<order-dialog ref="orderDialog" :orderId="orderDetail.id" :type="type" @confirm="confirmDialog"></order-dialog>
<float-tab></float-tab>
</view>
</template>
<script>
import {
getIntegralOrderDetail,
cancelIntegralOrder,
delIntegralOrder,
confirmIntegralOrder
} from '@/api/activity';
export default {
data() {
return {
orderDetail: {
goods: {},
btns: {}
},
team: {},
isFirstLoading: true,
type: 0,
showCancel: "",
showLoading: false
};
},
onLoad: function(options) {
const {
id
} = this.$Route.query;
this.id = id;
this.getOrderDetailFun();
uni.$on('payment', this.payCallback)
},
onUnload() {
uni.$off('payment', this.payCallback)
},
methods: {
payCallback(params) {
setTimeout(() => {
if (params.result) {
this.$toast({
title: "支付成功"
})
this.getOrderDetailFun()
} else {
this.$toast({
title: "支付失败"
})
}
}, 500)
},
async confirmDialog() {
const {
type,
id
} = this
let res = null
switch (type) {
case 0:
res = await cancelIntegralOrder(id);
break;
case 1:
res = await delIntegralOrder(id);
break;
case 2:
res = await confirmIntegralOrder(id);
break;
}
if (res.code == 1) {
uni.$emit("refreshorder")
if ([0, 2].includes(type)) {
this.getOrderDetailFun();
} else if (type == 1) {
setTimeout(() => {
uni.navigateBack()
}, 2000)
}
}
},
dialogOpen() {
this.$refs.orderDialog.open()
},
handleOrder(type) {
this.type = type
this.$nextTick(() => {
this.dialogOpen();
});
},
payNow() {
this.$Router.push({
path: '/pages/payment/payment',
query: {
from: 'integral',
order_id: this.id
}
})
},
getOrderDetailFun() {
getIntegralOrderDetail(this.id).then(res => {
if (res.code == 1) {
this.orderDetail = res.data
this.$nextTick(() => {
this.isFirstLoading = false
});
} else {
setTimeout(() => uni.navigateBack(), 1500)
}
});
},
},
computed: {
}
};
</script>
<style lang="scss">
.order-details {
position: relative;
padding-bottom: calc(120rpx + env(safe-area-inset-bottom));
.contain {
margin: 0 20rpx 20rpx;
border-radius: 14rpx;
background-color: #fff;
}
.header-bg {
position: absolute;
top: 0;
width: 100%;
height: 200rpx;
background-color: $-color-primary;
z-index: 0;
}
.header {
padding: 24rpx 40rpx;
}
.main {
position: relative;
z-index: 1;
}
.goods {
padding: 30rpx 24rpx;
.goods-name {
line-height: 40rpx;
height: 80rpx;
}
}
.address-wrap {
height: 164rpx;
padding: 0 24rpx;
}
.order-info {
padding: 12rpx 0;
.item {
padding: 12rpx 24rpx;
.title {
width: 180rpx;
flex: none;
}
}
}
.price {
padding: 24rpx 0;
&>view {
height: 60rpx;
padding: 0 24rpx;
}
}
.footer {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 100rpx;
padding: 0 24rpx;
box-sizing: content-box;
padding-bottom: env(safe-area-inset-bottom);
.plain {
border: 1px solid #BBBBBB;
&.red {
border: 1px solid $-color-primary;
}
}
}
}
</style>

174
bundle/pages/goods_combination/goods_combination.vue

File diff suppressed because one or more lines are too long

240
bundle/pages/goods_logistics/goods_logistics.vue

@ -0,0 +1,240 @@
<template>
<view>
<view class="goods-logistics p-t-20">
<view class="header flex bg-white">
<view class="goods m-r-20">
<image class="goods-img" :src="order.image"></image>
<view class="count xs white br60">{{order.count}}件商品</view>
</view>
<view class="info sm">
<view class="bold lg">{{order.tips}}</view>
<view class="black m-t-10 m-b-10">物流公司{{order.shipping_name}}</view>
<view class="row">
<text class="black">快递单号{{order.invoice_no}}</text>
<text class="primary m-l-20" @tap="onCopy">复制</text>
</view>
</view>
</view>
<view class="main m-t-20 bg-white column">
<!-- 物流时间轴 -->
<view class="express">
<!-- 顶部收货地址 -->
<view class="express-address row" v-if="take.contacts">
<view class="express-left flex-col col-center">
<image class="express-icon" :src="finish.tips ? '/bundle/static/logistics_address.png' : '/bundle/static/logistics_address_gray.png'"></image>
<view class="express-line"></view>
</view>
<view class="express-right">
<view class="name bold mb10 sm">{{take.contacts}} {{take.mobile}}</view>
<view class="address sm lighter line2">{{take.address}}</view>
</view>
</view>
<view class="express-item row" v-if="finish.tips">
<view class="express-left flex-col col-center">
<image class="express-icon" src="/bundle/static/logistics_success.png"></image>
<view class="express-line"></view>
</view>
<view class="express-right">
<view class="title bold sm">{{finish.title}}</view>
<view class="dec sm">{{finish.tips}}</view>
<view class="time xs muted">{{finish.time}}</view>
</view>
</view>
<view class="express-item row" v-if="delivery.traces && delivery.traces.length">
<view class="express-left flex-col col-center">
<image class="express-icon" src="/bundle/static/logistics_transit.png"></image>
<view class="express-line"></view>
</view>
<view class="express-right muted">
<view class="title bold sm ">{{delivery.title}}</view>
<view class="xs" v-if="delivery.traces[0][0]">
{{delivery.traces[0][0]}}
</view>
<view class="xs" v-if="delivery.traces[0][1]">
{{delivery.traces[0][1]}}
</view>
<view class="xs" v-if="delivery.traces[0][2]">
{{delivery.traces[0][2]}}
</view>
</view>
</view>
<block v-for="(item, index) in delivery.traces" :key="index">
<view class="express-item row" v-if="index >= 1">
<view class="express-left flex-col col-center">
<view class="express-doted"></view>
<view class="express-line"></view>
</view>
<view class="express-right muted">
<view class="sm" v-if="item[0]">{{item[0]}}</view>
<view class="sm" v-if="item[1]">{{item[1]}}</view>
<view class="sm" v-if="item[2]">{{item[2]}}</view>
</view>
</view>
</block>
<view class="express-item row" v-if="shipment.tips">
<view class="express-left flex-col col-center">
<image class="express-icon" src="/bundle/static/logistics_delivered.png"></image>
<view class="express-line"></view>
</view>
<view class="express-right muted">
<view class="title bold sm">{{shipment.title}}</view>
<view class="dec xs">{{shipment.tips}}</view>
<view class="time xs muted">{{shipment.time}}</view>
</view>
</view>
<view class="express-item row" v-if="buy.tips">
<view class="express-left flex-col col-center">
<image class="express-icon" src="/bundle/static/logistics_pay.png"></image>
<view class="express-line"></view>
</view>
<view class="express-right muted">
<view class="title bold sm">{{buy.title}}</view>
<view class="dec xs">{{buy.tips}}</view>
<view class="time xs muted">{{buy.time}}</view>
</view>
</view>
</view>
</view>
</view>
<recommend></recommend>
<loading-view v-if="isFirstLoading"></loading-view>
</view>
</template>
<script>
import {
orderTraces
} from '@/api/order';
import { getIntegralOrderTraces } from '@/api/activity'
import {copy} from '@/utils/tools'
export default {
data() {
return {
shipment: {},
buy: {},
delivery: {},
finish: {},
order: {},
take: {},
isFirstLoading: true
};
},
onLoad () {
this.id = this.$Route.query.id
this.type = this.$Route.query.type
this.orderTracesFun();
},
methods: {
async orderTracesFun() {
const {
code,
data: {
shipment,
buy,
delivery,
finish,
order,
take
}
} = this.type == 'integral' ? await getIntegralOrderTraces(this.id) : await orderTraces(this.id)
if (code == 1) {
this.shipment = shipment
this.buy = buy
this.delivery = delivery
this.finish = finish
this.order = order
this.take = take
this.isFirstLoading = false
} else {
setTimeout(() => uni.navigateBack(), 1000);
}
},
onCopy() {
copy(this.order.invoice_no)
}
}
};
</script>
<style lang="scss">
.goods-logistics {
padding-top: 20rpx;
.header {
padding: 20rpx;
.goods-img {
width: 160rpx;
height: 160rpx;
flex: none;
border-radius: 10rpx;
}
}
.goods {
position: relative;
.count {
position: absolute;
bottom: 0;
width: 100%;
text-align: center;
background-color: rgba(0, 0, 0, 0.6);
padding: 4rpx 0;
}
}
.express {
width: 700rpx;
padding-top: 30rpx;
padding-bottom: 100rpx;
margin: 0 auto;
border-radius: 10rpx;
}
.express-address,
.express-item {
align-items: flex-start;
position: relative;
padding: 20rpx 0;
}
.express-left {
margin-top: 10rpx;
margin-right: 24rpx;
height: 100%;
position: absolute;
width: 40rpx;
flex: none;
.express-icon {
width: 40rpx;
height: 40rpx;
}
.express-line {
flex: 1;
border-left: 1px dotted #E5E5E5;
}
.express-doted {
width: 16rpx;
height: 16rpx;
border-radius: 50%;
background-color: #E5E5E5;
}
}
.express-right {
padding-left: 60rpx;
& .title,
& .dec {
margin-bottom: 5rpx;
}
}
.express-item:last-of-type .express-left .express-line {
border: none;
}
}
</style>

193
bundle/pages/goods_reviews/goods_reviews.vue

@ -0,0 +1,193 @@
<template>
<view class="goods-reviews">
<view class="bg-white flex p-20">
<u-image width="160rpx" height="160rpx" border-radius="6rpx" :src="goodsInfo.goods_item.image"></u-image>
<view class="goods-desc flex-1 m-l-24">
<view class="goods-name line-2">{{goodsInfo.goods_name}}</view>
<view class="m-t-10 xs muted" >{{goodsInfo.goods_item.spec_value_str}}</view>
<view class="flex row-between m-t-20">
<price-format :price="goodsInfo.goods_price" :subscript-size="26"
:first-size="30" :second-size="30" />
<view class="nr">x{{goodsInfo.goods_num}}</view>
</view>
</view>
</view>
<view class="goods-evaluate bg-white flex">
<view class="lable">商品评价</view>
<u-rate name="goodsRate" :count="5" :size="42" active-color="#FF2C3C" v-model="goodsRate"
@change="goodsRateChange" />
<view :class="'desc ' + ((goodsRate<=2)? 'muted': 'primary') + ' '" v-show="!(goodsRate == 0)">
{{goodsRateDesc}}
</view>
</view>
<view class="bg-white p-20 lighter">{{goodsInfo.shop.name}}</view>
<view class="rate bg-white">
<view class="item flex m-b-20">
<view class="lable">描述相符</view>
<u-rate name="descRate" :size="42" active-color="#FF2C3C" v-model="descRate" />
</view>
<view class="item flex m-b-20">
<view class="lable">服务态度</view>
<u-rate name="serverRate" :size="42" active-color="#FF2C3C" v-model="serverRate" />
</view>
<view class="item flex m-b-20">
<view class="lable">配送服务</view>
<u-rate name="deliveryRate" :size="42" active-color="#FF2C3C" v-model="deliveryRate" />
</view>
</view>
<view class="goods-dec bg-white m-t-20">
<view class="title m-b-20 md bold">商品描述</view>
<view class="p-20" style="background-color: #F8F8F8;">
<u-input v-model="comment" type="textarea" placeholder="宝贝收到还满意吗,说说你的使用心得。分享给想买的他们吧!!" :border="false"
:height="160" />
</view>
<view class="m-t-20">
<u-upload ref="uUpload" :show-progress="false" :header="{token: $store.getters.token}"
:max-count="8" width="150" height="150" :action="action" upload-text="上传图片"
@on-success="onSuccess" @on-remove="onRemove" />
</view>
<view class="muted m-t-20 m-b-10">支持jpgpngjpeg格式的图片最多可上传8张</view>
</view>
<button class="btn br60" type="primary" size="lg" @tap="onSubmit">立即评价</button>
</view>
</template>
<script>
import {
baseURL
} from '@/config/app.js';
import {
goodsComment,
getCommentInfo
} from '@/api/user';
import {
uploadFile
} from '@/utils/tools.js';
export default {
data() {
return {
action: baseURL + '/api/file/formimage',
goodsRate: 0,
descRate: 0,
serverRate: 0,
deliveryRate: 0,
goodsRateDesc: "",
fileList: [],
goodsInfo: {
shop: {},
goods_item: {}
},
comment: '',
type: ""
};
},
onLoad() {
this.id = this.$Route.query.id
this.getCommentInfoFun();
},
methods: {
onSuccess(e) {
this.fileList.push(e.data.base_uri)
},
onRemove(index) {
this.fileList.splice(index, 1)
},
goodsRateChange(e) {
let goodsRateDesc = "";
if (e <= 2) {
goodsRateDesc = "差评";
} else if (e == 3) {
goodsRateDesc = "中评";
} else {
goodsRateDesc = "好评";
}
this.goodsRateDesc = goodsRateDesc;
},
onSubmit() {
let {
goodsRate,
fileList,
comment,
deliveryRate,
descRate,
serverRate
} = this;
if (!goodsRate) return this.$toast({
title: '请对商品进行评分'
});
if (!descRate) return this.$toast({
title: '请对描述相符进行评分'
});
if (!serverRate) return this.$toast({
title: '请对服务态度进行评分'
});
if (!deliveryRate) return this.$toast({
title: '请对配送服务进行评分'
});
goodsComment({
order_goods_id: parseInt(this.id),
goods_comment: goodsRate,
service_comment: serverRate,
express_comment: deliveryRate,
description_comment: descRate,
comment,
image: fileList
}).then(res => {
if (res.code == 1) {
this.$toast({
title: '评价成功'
}, {
tab: 3,
url: 1
});
uni.$emit('refreshcomment')
}
});
},
getCommentInfoFun() {
getCommentInfo({
order_goods_id: this.id
}).then(res => {
if (res.code == 1) {
this.goodsInfo = res.data
}
});
},
}
};
</script>
<style>
.goods-reviews {
padding: 20rpx 0 40rpx;
}
.goods-reviews .rate {
padding: 20rpx 20rpx;
}
.goods-reviews .lable {
width: 170rpx;
}
.goods-reviews .goods-dec {
padding: 30rpx 20rpx;
}
.goods-reviews .btn {
width: 698rpx;
margin: 30rpx 26rpx 0;
}
.goods-reviews .goods-evaluate {
padding: 20rpx;
border: 1rpx solid #F2F2F2;
}
</style>

219
bundle/pages/goods_seckill/goods_seckill.vue

@ -0,0 +1,219 @@
<template>
<mescroll-body ref="mescrollRef" @init="mescrollInit" :up="upOption" @down="downCallback" @up="upCallback">
<view class="goods-seckill">
<view class="banner">
<ad-swipers :pid="20" height="340rpx"></ad-swipers>
</view>
<view class="time-list">
<scroll-view style="height: 120rpx; white-space: nowrap;" :scroll-into-view="'item-' + (active - 2)"
scroll-x="true" scroll-with-animation="true">
<view v-for="(item, index) in seckillTime" :key="index" :id="'item-' + index"
class="time-item flex-col row-center col-center" :class="{active: index == active}"
@tap="exchangeTime(index)">
<view :class="'xl bold time'">{{ item.start_time }}</view>
<view :class="'sm br60 state ' + ( item.status === 2 ? 'muted': '' )">
{{ item.tips }}
</view>
</view>
</scroll-view>
</view>
<view class="goods-list">
<router-link v-for="(item, index) in seckillGoods" :key="index"
:to="{path: '/pages/goods_details/goods_details', query: {id: item.goods_id}}">
<view class="goods-item flex bg-white">
<u-image width="180rpx" height="180rpx" border-radius="10rpx" :src="item.goods_image" />
<view class="goods-info m-l-20">
<view style="width: 490rpx" class="goods-name line-2 m-b-10">{{item.goods_name}}</view>
<label class="sale-info xs primary br60">
已抢{{item.seckill_total}}
</label>
<view class="info-footer flex row-between m-t-5">
<view class="price">
<price-format class="m-r-10" :price="item.seckill_price"
:color="colorConfig.primary" :first-ize="34" :second-ize="26"
:subscript-ize="26" />
<price-format class="line-through" :price="item.goods_min_price"
:color="colorConfig.muted" :first-ize="24" :second-ize="24"
:subscript-ize="24" />
</view>
<button :class="'br60 white ' + (currentStatus == 2? ' bg-gray' : currentStatus == 1
? 'primary-btn' : 'border-btn' )" size="sm">
{{currentStatus == 2? '已结束': currentStatus == 1 ? '立即抢购' : '未开始'}}</button>
</view>
</view>
</view>
</router-link>
</view>
</view>
</mescroll-body>
</template>
<script>
import {
getSeckillTime,
getSeckillGoods
} from "@/api/activity";
import MescrollMixin from "@/components/mescroll-uni/mescroll-mixins";
export default {
mixins: [MescrollMixin],
data() {
return {
active: 0,
upOption: {
auto: false,
empty: {
use: true,
icon: '/static/images/goods_null.png',
tip: "暂无秒杀商品~",
},
},
seckillTime: [],
seckillGoods: []
};
},
methods: {
async downCallback(page) {
this.seckillGoods = []
await this.getSeckillTimeFun()
this.mescroll.resetUpScroll();
},
upCallback(page) {
let pageNum = page.num;
let pageSize = page.size;
const {seckillTime, active} = this
if(!seckillTime.length) return this.mescroll.endSuccess(0,false)
let id = seckillTime[active].id
getSeckillGoods({
page_no: pageNum,
page_size: pageSize,
seckill_id:id
}).then(res => {
let curPageData = res.data.lists;
let hasNext = !!res.data.more;
let curPageLen = curPageData.length;
if (pageNum == 1) this.seckillGoods = [];
this.seckillGoods = this.seckillGoods.concat(curPageData);
this.mescroll.endSuccess(curPageLen, hasNext);
}).catch(() => {
this.mescroll.endErr()
})
},
//
getSeckillTimeFun() {
return new Promise((resolve) => {
getSeckillTime().then(({code, data}) => {
if (code == 1) {
//
let index = data.findIndex(item => item.status == 1);
if (index == -1) {
//
index = data.findIndex(item => item.status == 0);
}
if(index == -1) {
//
index = data.length - 1
}
this.seckillTime = data;
this.$nextTick(function(){
this.active = index
resolve()
})
}
})
})
},
//
exchangeTime(index) {
this.active = index
this.seckillGoods = []
this.mescroll.resetUpScroll();
},
},
computed: {
currentStatus() {
const {active, seckillTime} = this
return seckillTime[active] && seckillTime[active].status
}
}
};
</script>
<style lang="scss">
.bg-gray {
background-color: #CCCCCC !important;
}
.goods-seckill {
.time-list {
.time-item {
display: inline-flex;
width: 160rpx;
height: 100%;
&.active {
.time {
color: $-color-primary;
}
.state {
color: $-color-white;
background-color: $-color-primary;
}
}
.state {
padding: 0 10rpx;
}
}
}
.endtime-box {
height: 100rpx;
.line {
width: 100rpx;
height: 2rpx;
background-color: #CCC;
}
}
.goods-list {
.goods-item {
padding: 30rpx;
.goods-info {
flex: 1;
width: 470rpx;
.sale-info {
padding: 4rpx 16rpx;
background-color: #FFE9EB;
}
.info-footer {
.btn {
padding: 0 30rpx;
}
}
}
}
}
}
.primary-btn {
padding: 0 30rpx;
background: linear-gradient(270deg,
rgba(255, 44, 60, 1) 0%,
rgba(249, 95, 47, 1) 100%);
}
.border-btn {
padding: 0 30rpx;
border: 1px solid $-color-primary;
color: $-color-primary;
}
</style>

128
bundle/pages/input_express_info/input_express_info.vue

@ -0,0 +1,128 @@
<template>
<view class="input-express-info p-t-20">
<view class="input-contain bg-white">
<u-field v-model="formInfo.express" :border-bottom="false" label="物流公司" placeholder="请输入物流公司名称">
</u-field>
<u-field v-model="formInfo.number" :border-bottom="false" label="快递单号" placeholder="请输入快递单号">
</u-field>
<u-field v-model="formInfo.remark" :border-bottom="false" label="备注说明" placeholder="选填">
</u-field>
</view>
<view class="upload-contain bg-white m-t-20">
<view class="header flex">
<view class="normal">上传凭证</view>
<view class="sm muted m-l-20">(请上传快递单号凭证</view>
</view>
<view class="upload">
<u-upload ref="uUpload" :show-progress="false" :header="{token: $store.getters.token}"
:max-count="1" width="160" height="160" :action="action" upload-text="上传图片"
@on-success="onSuccess" @on-remove="onRemove" />
</view>
</view>
<view class="submit-btn">
<button size="lg" class=" br60 bg-primary white lg" @tap="formSubmit">提交</button>
</view>
</view>
</template>
<script>
import {
inputExpressInfo
} from '@/api/user';
import {
baseURL
} from '@/config/app.js';
export default {
data() {
return {
action: baseURL + '/api/file/formimage',
fileList: [],
formInfo: {
express: '',
number: '',
remark: ''
}
};
},
onLoad() {
this.id = this.$Route.query.id
},
methods: {
onSuccess(e) {
this.fileList.push(e.data.base_uri)
},
onRemove(index) {
this.fileList.splice(index, 1)
},
formSubmit(e) {
const {
fileList,
formInfo: {
express,
number,
remark
}
} = this;
if (!express) return this.$toast({
title: '请填写物流公司名称'
});
if (!number) return this.$toast({
title: '请填写快递单号'
});
let data = {
id: this.id,
express_name: express,
invoice_no: number,
express_remark: remark,
express_image: fileList.length ? fileList[0] : ''
};
inputExpressInfo(data).then(res => {
if (res.code == 1) {
this.$toast({
title: '提交成功'
}, {
tab: 3,
url: 1
});
uni.$emit("refreshsale")
}
});
},
}
};
</script>
<style>
.input-contain .input-item {
padding: 24rpx;
}
.input-item .label {
width: 152rpx;
}
.input-item .input {
flex: 1;
}
.upload-contain {
padding: 24rpx 20rpx 44rpx;
}
.upload-contain .header {
margin-bottom: 30rpx;
}
.submit-btn {
margin-top: 50rpx;
margin-left: 26rpx;
margin-right: 26rpx;
}
</style>

83
bundle/pages/integral_details/integral_details.vue

@ -0,0 +1,83 @@
<template>
<view class="integral-details">
<mescroll-body ref="mescrollRef" :up="{
noMoreSize: 10,
empty: {
icon: '/static/images/order_null.png',
tip: '暂无积分明细~',
fixed: false
}
}" @init="mescrollInit" @down="downCallback" @up="upCallback">
<view class="integral-lists">
<view class="item flex row-between bg-white" v-for="(item, index) in integralList" :key="index">
<view class="">
<view class="nr">
{{item.source_type}}
</view>
<view class="xs muted m-t-10">
{{item.create_time}}
</view>
</view>
<view :class="'lg ' +(item.change_type == 1 ? 'primary' : '')">
{{item.change_amount_format}}
</view>
</view>
</view>
</mescroll-body>
</view>
</template>
<script>
import {
getAccountLog
} from "@/api/user";
import MescrollMixin from "@/components/mescroll-uni/mescroll-mixins.js";
export default {
mixins: [MescrollMixin], // 使mixin
data() {
return {
integralList: [],
};
},
methods: {
//
upCallback({
num,
size
}) {
getAccountLog({
page_no: num,
page_size: size,
source: 2, //
}).then(({
data,
code
}) => {
if(code != 1) return this.mescroll.endErr()
if (num === 1) this.integralList = []
this.integralList = [...this.integralList, ...data.list]
this.mescroll.endSuccess(data.list.length, !!data.more)
}).catch(err => {
this.mescroll.endErr()
})
}
},
}
</script>
<style lang="scss">
.integral-lists {
padding-top: 20rpx;
.item {
padding: 18rpx 30rpx;
position: relative;
&:not(:last-of-type) {
border-bottom: $-solid-border;
}
}
}
</style>

256
bundle/pages/integral_goods_details/integral_goods_details.vue

@ -0,0 +1,256 @@
<template>
<view class="integral-goods-details">
<!-- 商品图片 -->
<view class="goods-image" @tap="previewImage(goodsDetails.image)">
<u-image :src="goodsDetails.image" width="100%" height="750rpx"></u-image>
</view>
<!-- 商品信息 -->
<view class="goods-info bg-white">
<view class="info-header flex">
<view class="price flex flex-1">
<view class="primary m-r-10">
<price-format :first-size="38" :second-size="24" :price="goodsDetails.need_integral"
:weight="500" :show-subscript="false"></price-format>
<text class="xs">积分</text>
<block v-if="goodsDetails.exchange_way === 2">
<text>+</text>
<price-format :show-subscript="false" :first-size="38"
:second-size="24" :weight="500" :price="goodsDetails.need_money" />
<text class="xs"></text>
</block>
</view>
<view class="muted xs" v-if="goodsDetails.market_price > 0">
市场价 <price-format :first-size="24" :second-size="24" :subscript-size="24"
:price="goodsDetails.market_price"></price-format>
</view>
</view>
<view class="muted xs">
已兑换{{ goodsDetails.sales }}
</view>
</view>
<view class="name lg bold">{{ goodsDetails.name }}</view>
</view>
<!-- 商品规格选择 -->
<view class="goods-spec flex bg-white m-t-20" @tap="showSpec = true">
<view class="label muted">已选</view>
<view class="line-1 m-r-20 flex-1">数量x{{ count }}</view>
<u-icon name="arrow-right" :color="colorConfig.muted"></u-icon>
</view>
<!-- 商品详情 -->
<view class="goods-details m-t-20 bg-white">
<view class="details-title lg">商品详情</view>
<view class="details-content">
<u-parse :html="goodsDetails.content" :lazy-load="true" :show-with-animation="true"></u-parse>
</view>
</view>
<!-- 底部按钮 -->
<view class="goods-footer bg-white flex">
<button type="primary" class="right-btn flex-1 br60" :disabled="!goodsDetails.stock" @tap="toSettlement">
立即兑换
</button>
</view>
<!-- 悬浮按钮 -->
<float-tab></float-tab>
<!-- 规格弹窗 -->
<view class="spec-popup">
<u-popup v-model="showSpec" mode="bottom" border-radius="14" :closeable="true"
:safe-area-inset-bottom="true">
<view class="bg-white spec-contain">
<view class="spec-header flex">
<u-image width="160rpx" height="160rpx" class="m-r-20" border-radius="10rpx"
@click="previewImage(goodsDetails.image)" :src="goodsDetails.image"></u-image>
<view class="goods-info">
<view class="primary flex">
<price-format :first-size="38" :second-size="24" :price="goodsDetails.need_integral"
:weight="500" :show-subscript="false">
</price-format>
<text class="xs">积分</text>
<block v-if="goodsDetails.exchange_way === 2">
<text>+</text>
<price-format :show-subscript="false" :weight="500" :first-size="38" :second-size="24"
:price="goodsDetails.need_money" />
<text class="xs"></text>
</block>
</view>
<view class="sm">
库存{{goodsDetails.stock}}
</view>
</view>
</view>
<view class="spec-main" style="height: 400rpx;">
<view class="good-num flex row-between m-l-20 m-r-20">
<view class="label">数量</view>
<u-number-box :disabled="!goodsDetails.stock" v-model="count" :min="1" :max="goodsDetails.stock">
</u-number-box>
</view>
</view>
<view class="spec-footer">
<button type="primary" class="right-btn flex-1 br60" :disabled="!goodsDetails.stock" @tap="toSettlement">
立即兑换
</button>
</view>
</view>
</u-popup>
</view>
<loading-view v-if="isFirstLoading"></loading-view>
</view>
</template>
<script>
import {
getIntegralGoodsDetail
} from '@/api/activity'
export default {
data() {
return {
isFirstLoading: true,
goodsDetails: {},
count: 1,
showSpec: false
}
},
methods: {
//
getGoodsDetails() {
getIntegralGoodsDetail({
id: this.id
}).then((res) => {
if (res.code == 1) {
this.goodsDetails = res.data
}
}).finally(() => {
this.isFirstLoading = false
})
},
//
previewImage(current) {
uni.previewImage({
current,
urls: [current] // http
});
},
//
toSettlement() {
this.$Router.push({
path: '/bundle/pages/integral_settlement/integral_settlement',
query: {
id: this.id,
count: this.count
}
})
}
},
onLoad() {
this.id = this.$Route.query.id
this.getGoodsDetails()
},
onShareAppMessage() {
const {
goodsDetails
} = this;
return {
title: goodsDetails.name,
imageUrl: goodsDetails.image,
path: '/bundle/pages/integral_goods_details/integral_goods_details?id=' + this.id + "&invite_code=" + this.$store.getters.inviteCode
};
},
}
</script>
<style lang="scss">
.integral-goods-details {
padding-bottom: calc(120rpx + env(safe-area-inset-bottom));
.goods-info {
position: relative;
.info-header {
padding: 20rpx 24rpx 0;
.price {
align-items: baseline;
}
}
.name {
padding: 20rpx 24rpx;
flex: 1;
}
}
.goods-details {
// overflow: hidden;
.details-title {
line-height: 88rpx;
text-align: center;
}
&>.details-content {
padding: 0 20rpx 20rpx;
::v-deep image {
vertical-align: middle;
}
// #ifdef H5
::v-deep img {
vertical-align: middle;
}
// #endif
// #ifdef MP-WEIXIN || APP-PLUS
::v-deep ._img {
display: block;
}
// #endif
}
}
.goods-spec {
padding: 24rpx 24rpx;
.label {
width: 100rpx;
}
}
.goods-footer {
height: 100rpx;
position: fixed;
bottom: 0;
left: 0;
right: 0;
box-sizing: content-box;
padding: 0 24rpx;
padding-bottom: env(safe-area-inset-bottom);
}
.spec-popup {
.spec-contain {
overflow: hidden;
position: relative;
.spec-header {
padding: 30rpx;
padding-right: 70rpx;
align-items: flex-start;
border: $-solid-border;
}
.spec-main, .spec-footer {
padding: 24rpx;
}
}
}
.right-btn {
height: 80rpx;
line-height: 80rpx;
}
}
</style>

265
bundle/pages/integral_mall/integral_mall.vue

@ -0,0 +1,265 @@
<template>
<view class="integral-mall">
<mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback" :up="upOption">
<view class="header bg-primary flex row-between white">
<router-link to="/bundle/pages/integral_sign/integral_sign">
<view class="user-integral flex">
<u-icon class="m-r-16" :name="require('@/bundle/static/icon_integral.png')" :size="44"></u-icon>
我的积分<text class="xxl bold">{{ integral }}</text>
</view>
</router-link>
<router-link to="/bundle/pages/exchange_order/exchange_order">
兑换订单 <u-icon name="arrow-right"></u-icon>
</router-link>
</view>
<view class="main">
<view class="sort-bar flex bg-white">
<view class="sort-bar-item flex-2 flex row-center" v-for="(item, index) in sortConfig" :key="index"
@tap="handleSort(item)">
<text :class="item.value ? 'primary' : ''">{{ item.name }}</text>
<view class="arrow-icon flex-col col-center row-center" v-if="!item.setValue">
<u-icon name="arrow-up-fill"
:color="item.value == 'asc' ? colorConfig.primary : colorConfig.normal"></u-icon>
<u-icon name="arrow-down-fill"
:color="item.value == 'desc' ? colorConfig.primary : colorConfig.normal"></u-icon>
</view>
</view>
<view class="flex-1 flex row-center" @tap="changeGoodsType">
<image class="icon-sm"
:src="goodsType === 'one' ? '/static/images/icon_double.png' : '/static/images/icon_one.png'">
</image>
</view>
</view>
<view class="goods-lists" :class="{
'goods-lists--one': goodsType === 'one'
}">
<view class="goods-item" v-for="(item, index) in goodsLists" :key="index">
<router-link :to="`/bundle/pages/integral_goods_details/integral_goods_details?id=${item.id}`">
<view class="goods-item-info">
<view class="goods-image">
<view class="image-wrap">
<u-image :src="item.image" width="100%" height="100%"></u-image>
</view>
</view>
<view class="goods-info">
<view class="goods-name line-2">
{{ item.name }}
</view>
<view class="goods-price primary m-t-10">
<price-format :color="colorConfig.primary" :show-subscript="false"
:first-size="36" :second-size="24" :price="item.need_integral" />
<text class="xs">积分</text>
<block v-if="item.exchange_way === 2">
<text>+</text>
<price-format :color="colorConfig.primary" :show-subscript="false"
:first-size="36" :second-size="24" :price="item.need_money" />
<text class="xs"></text>
</block>
</view>
</view>
</view>
</router-link>
</view>
</view>
</view>
</mescroll-body>
</view>
</template>
<script>
import {
getIntegralGoods
} from '@/api/activity'
import MescrollMixin from "@/components/mescroll-uni/mescroll-mixins";
import {trottle} from '@/utils/tools'
export default {
mixins: [MescrollMixin],
data() {
return {
sortConfig: [{
name: '最新',
type: 'sort_by_new',
value: 'desc',
setValue: 'desc'
},
{
name: '积分',
type: 'sort_by_integral',
value: ''
},
{
name: '兑换量',
type: 'sort_by_sales',
value: '',
setValue: 'desc'
}
],
goodsType: 'double',
upOption: {
noMoreSize: 2,
auto: false,
empty: {
icon: '/static/images/goods_null.png',
tip: "暂无商品",
}
},
goodsLists: [],
integral: ''
}
},
methods: {
changeGoodsType() {
this.goodsType = this.goodsType === 'one' ? 'double' : 'one'
},
handleSort(current) {
this.sortConfig.forEach((item) => {
if(current.type != item.type) {
item.value = ''
return
}
if(item.setValue) {
item.value = item.setValue
return
}
if(item.value == 'asc') {
item.value = 'desc'
}else{
item.value ='asc'
}
})
},
upCallback(page) {
const pageNum = page.num; // , 1
const pageSize = page.size; // , 10
const sort = this.sortConfig.find((item) => item.value) || {}
getIntegralGoods({
[sort.type]: sort.value,
page_no: pageNum,
page_size: pageSize
}).then(res => {
if (res.code == 1) {
const {
goods,
integral
} = res.data
this.integral = integral
let curPageData = goods.lists;
let curPageLen = curPageData.length;
let hasNext = !!goods.more;
if (pageNum == 1) this.goodsLists = [];
this.goodsLists = this.goodsLists.concat(curPageData);
this.mescroll.endSuccess(curPageLen, hasNext);
}else{
this.mescroll.endErr();
}
}).catch(() => {
this.mescroll.endErr();
})
},
},
watch: {
sortConfig: {
handler(val) {
this.goodsLists = []
this.mescroll.resetUpScroll()
},
deep: true
}
},
onLoad() {
this.handleSort = trottle(this.handleSort, 500, this);
}
}
</script>
<style lang="scss">
page {
padding: 0;
}
$goods-margin: 8rpx;
.integral-mall {
.header {
padding: 22rpx 24rpx;
}
.main {
.sort-bar {
height: 80rpx;
.sort-bar-item {
height: 100%;
}
.arrow-icon {
transform: scale(0.4);
}
}
.goods-lists {
padding: 20rpx 20rpx 0;
margin: -$goods-margin;
display: flex;
flex-wrap: wrap;
.goods-item {
width: 50%;
.goods-item-info {
margin: $goods-margin;
border-radius: 14rpx;
background: #fff;
overflow: hidden;
.goods-image {
flex: none;
position: relative;
height: 0;
padding-top: 100%;
.image-wrap {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
}
.goods-info {
padding: 14rpx;
.goods-name {
line-height: 40rpx;
height: 80rpx;
}
}
}
}
&--one {
.goods-item {
width: 100%;
.goods-item-info {
display: flex;
.goods-image {
width: 200rpx;
padding-top: 200rpx;
}
.goods-info {
padding: 24rpx 20rpx;
}
}
}
}
}
}
}
</style>

266
bundle/pages/integral_settlement/integral_settlement.vue

@ -0,0 +1,266 @@
<template>
<view class="integral-settlement">
<view class="settlement-main">
<router-link to="/bundle/pages/user_address/user_address?type=1">
<view class="address flex contain">
<image class="icon-md m-r-20" src="/static/images/icon_address.png"></image>
<view class="flex-1 m-r-20">
<view class="black md" v-if="!address.contact">设置收货地址</view>
<view v-else>
<text class="name md m-r-10">{{address.contact}}</text>
<text class="phone md">{{address.telephone}}</text>
<view class="area sm m-t-10 lighter">
{{address.province}} {{address.city}} {{address.district}} {{address.address}}
</view>
</view>
</view>
<u-icon name="arrow-right"></u-icon>
</view>
</router-link>
<view class="order-goods contain">
<view class="flex goods">
<u-image :src="goods.image" border-radius="10" width="160" height="160"></u-image>
<view class="goods-info flex-1 m-l-20">
<view class="goods-name line-2">{{ goods.name }}</view>
<view class="flex row-between">
<view class="goods-price primary m-t-10">
<price-format :show-subscript="false" :first-size="36" :second-size="24"
:price="goods.need_integral" />
<text class="xs">积分</text>
<block v-if="goods.exchange_way === 2">
<text>+</text>
<price-format :show-subscript="false" :first-size="36" :second-size="24"
:price="goods.need_money" />
<text class="xs"></text>
</block>
</view>
<view class="lighter">×{{orderInfo.total_num}}</view>
</view>
</view>
</view>
<view class="buyer-message">
<u-field v-model="remark" type="textarea" :border-bottom="false" :auto-height="false" label="买家留言"
placeholder="请添加备注(150字以内)" maxlength="150" :field-style="{ height: '240rpx' }">
</u-field>
</view>
</view>
<view class="total-goods contain">
<view class="flex row-between ">
<view>商品总额</view>
<view class="primary">
<price-format :show-subscript="false" :first-size="36" :second-size="24"
:price="orderInfo.order_integral" />
<text class="xs">积分</text>
<block v-if="orderInfo.exchange_way === 2">
<text>+</text>
<price-format :show-subscript="false" :first-size="36" :second-size="24"
:price="orderInfo.goods_price" />
<text class="xs"></text>
</block>
</view>
</view>
<view class="flex row-between m-t-20">
<view>运费</view>
<view>
<price-format :first-size="28" :subscript-size="24" :second-size="24"
:price="orderInfo.shipping_price" />
</view>
</view>
</view>
</view>
<view class="settlement-footer bg-white flex row-between">
<view class="all-price lg flex">
<text>合计</text>
<view class="primary">
<price-format :show-subscript="false" :first-size="36" :second-size="24"
:price="orderInfo.order_integral" />
<text class="xs">积分</text>
<block v-if="orderInfo.order_amount > 0">
<text>+</text>
<price-format :show-subscript="false" :first-size="36" :second-size="24"
:price="orderInfo.order_amount" />
<text class="xs"></text>
</block>
</view>
</view>
<button type="primary" class="br60" size="md" hover-class="none" @tap="orderBuy">
提交订单
</button>
</view>
<loading-view v-show="showLoading" :background-color="hasBg ? '#fff' : ''"></loading-view>
</view>
</template>
<script>
import {
integralSettlement,
integralSubmitOrder
} from '@/api/activity'
export default {
data() {
return {
showLoading: true,
hasBg: true,
address: {},
goods: {},
orderInfo: {},
addressId: '',
remark: ''
}
},
methods: {
//
getOrderInfo() {
integralSettlement({
id: this.goodsId,
num: this.count,
address_id: this.addressId
}).then(res => {
if (res.code == 1) {
const {
address,
goods
} = res.data
this.address = address
this.orderInfo = res.data
this.goods = goods
}
}).finally(() => {
this.showLoading = false
})
},
//
orderBuy() {
this.hasBg = false
this.showLoading = true
const address_id = this.addressId || this.address.id
integralSubmitOrder({
id: this.goodsId,
num: this.count,
address_id,
user_remark: this.remark
}).then(res => {
if (res.code == 1) {
const {
type,
order_id
} = res.data
if(!this.orderInfo.need_pay) {
this.$Router.replace({
path: '/pages/pay_result/pay_result',
query: {
id: order_id,
from: type
}
})
return
}
uni.$on('payment', params => {
setTimeout(() => {
if (params.result) {
this.$Router.replace({
path: '/pages/pay_result/pay_result',
query: {
id: params.order_id,
from: params.from
}
})
}else {
this.$Router.replace({
path: '/bundle/pages/exchange_order/exchange_order',
query: {
id: params.order_id,
from: params.from
}
})
}
}, 1 * 1000)
})
this.$Router.push({
path: '/pages/payment/payment',
query: {
order_id: order_id,
from: type
}
})
}
}).finally(() => {
setTimeout(() => {
this.showLoading = false
}, 200)
})
}
},
onLoad(options) {
uni.$on("selectaddress", (e) => {
this.addressId = e.id
})
},
onUnload() {
uni.$off("selectaddress")
uni.$off("payment")
},
onShow() {
const {
count,
id
} = this.$Route.query
this.goodsId = id
this.count = count
this.getOrderInfo()
}
}
</script>
<style lang="scss">
.integral-settlement {
overflow: hidden;
padding-bottom: calc(120rpx + env(safe-area-inset-bottom));
.contain {
background-color: #fff;
border-radius: 14rpx;
margin: 20rpx 20rpx 0;
}
.settlement-main {
.address {
min-height: 164rpx;
padding: 20rpx 24rpx;
}
.order-goods {
.goods {
padding: 30rpx 24rpx;
border-bottom: $-solid-border;
.goods-info {
.goods-name {
line-height: 40rpx;
height: 80rpx;
}
}
}
.buyer-message {}
}
.total-goods {
padding: 20rpx 24rpx;
}
}
.settlement-footer {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 100rpx;
padding: 0 30rpx;
box-sizing: content-box;
padding-bottom: env(safe-area-inset-bottom);
}
}
</style>

357
bundle/pages/integral_sign/integral_sign.vue

@ -0,0 +1,357 @@
<template>
<view class="integral-sign" v-show="user.id">
<view class="user-sgin">
<view class="header">
<view class="flex">
<!-- 头像 -->
<view class="flex m-l-40">
<u-avatar :src="user.avatar" :size="110"></u-avatar>
</view>
<!-- 积分和明细按钮 -->
<view class="m-l-30 flex row-between flex-1">
<!-- 积分 -->
<view>
<view class="white" style="font-size: 56rpx">{{user.user_integral}}</view>
<router-link to="/bundle/pages/sign_rule/sign_rule">
<view class="sm flex white">
我的积分
<image src="../../static/jifen_icon_help.png" class="m-l-10"
style="height: 30rpx; width: 30rpx;"></image>
</view>
</router-link>
</view>
<!-- 明细按钮 -->
<router-link to="/bundle/pages/integral_details/integral_details">
<view class="score-detail-entry flex">
<image style="width: 26rpx;height: 26rpx;flex: none; margin-right: 7rpx"
src="../../static/jifen_icon_data.png"></image>
<text class="sm white">积分明细</text>
</view>
</router-link>
</view>
</view>
</view>
<view class="main">
<!-- 签到列表 -->
<view class="contain bg-white">
<view class="title">已累积签到 {{user.days}}</view>
<view class="day-list flex flex-wrap">
<view v-for="(item, index) in signList" :key="index"
class="item flex-col col-center">
<view :class="'circle flex row-center ' + (item.status == 1 ? 'active-circle' : '')">
<view class="num xs lighter" v-if="item.status == 0">+{{item.integral}}</view>
<image class="num" src="../../static/jifen_icon_select.png" v-if="item.status == 1">
</image>
</view>
<view class="day m-t-10 lighter sm">{{item.day}}</view>
</view>
</view>
<view class="right-sgin">
<button :class="'lighter br60 ' + (user.today_sign ? 'gray' : 'primary-button')"
@tap="userSignFun" size="md">{{user.today_sign ? '已签到' : '立即签到' }}</button>
</view>
</view>
<!-- 赚积分 -->
<view class="contain bg-white m-t-20" v-if="integralTips.length > 0">
<view class="title flex">
<view class="line br60 m-r-20"></view>
<view class="bold xl">赚积分</view>
</view>
<view class="task">
<view v-for="(item, index) in integralTips" :key="index" class="item flex">
<image class="img m-r-20" :src="item.image">
</image>
<view class="con">
<view class="md">{{item.name}}</view>
</view>
<button hover-class="none" :class="'btn br60 ' + (item.status ? 'muted' : 'primary' )"
:style="'border-color: ' + (item.status ? '#BBBBBB' : '#FF2C3C') + ';'"
size="xs">{{item.status ? '已完成' : '未完成'}}</button>
</view>
</view>
</view>
</view>
</view>
<u-popup v-model="showPop" mode="center">
<view class="pop-container">
<view class="header-score flex row-center">+{{signInfo.integral}}</view>
<view class="box column-center">
<view class="desc m-t-20 sm flex row-center">
<view class="">
获得
</view>
<image style="width: 28rpx; height: 30rpx;margin-right: 8rpx; margin-left: 8rpx"
src="../../static/icon_jifen.png"></image>
<view class="">
{{signInfo.integral}}
</view>
<view class="m-l-20 flex" v-if="signInfo.growth">
+ {{ signInfo.growth }}成长值
</view>
</view>
<view class="bottom-box">
<view class="md" style="line-height: 36rpx">
您已累积签到 <text style="font-size: 36rpx; color: #FF2C3C;">{{signInfo.days}}</text>
</view>
</view>
<view class="white br60 primary-btn" style="margin-top: 26rpx" @tap="showPop = false">确定</view>
</view>
</view>
</u-popup>
</view>
</template>
<script>
import {
getSignLists,
userSignIn
} from "@/api/activity";
import {
trottle
} from "@/utils/tools"
export default {
data() {
return {
//
user: {
},
//
signList: [],
//
integralTips: [],
//
showPop: false,
//
signInfo: {
}
};
},
onLoad() {
this.getSignListsFun()
this.userSignFun = trottle(this.userSignFun, 1000, this)
},
methods: {
//
getSignListsFun() {
getSignLists()
.then((res) => {
if (res.code == 1) {
const {
user,
sign_list,
integral_tips
} = res.data
this.user = user
this.signList = sign_list
this.integralTips = integral_tips
}
}).catch((err) => {
})
},
//
userSignFun() {
if(this.user.today_sign) return
userSignIn().then((res) => {
if(res.code == 1) {
this.showPop = true;
this.signInfo = res.data
this.getSignListsFun()
}
})
}
}
};
</script>
<style lang="scss">
.user-sgin {
padding-bottom: 100rpx;
}
.user-sgin .header {
background-image: url(../../static/bg_sgin.png);
background-repeat: no-repeat;
background-size: 100%;
height: 400rpx;
width: 750rpx;
padding-top: 40rpx;
box-sizing: border-box;
}
.user-sgin .header .avatar {
border-radius: 50%;
border: 4rpx solid #fff;
}
.user-sgin .main {
z-index: 100;
margin-top: -200rpx;
width: 100%;
top: 186rpx;
padding: 0 20rpx;
box-sizing: border-box;
}
.user-sgin .main .contain {
border-radius: 10rpx;
}
.user-sgin .main .contain .title {
padding: 24rpx 30rpx;
}
.user-sgin .main .contain .title .line {
width: 6rpx;
height: 34rpx;
background-color: #ff2c3c;
}
.user-sgin .main .day-list {
width: 100%;
}
.user-sgin .main .day-list .item {
width: 14.2%;
margin-bottom: 10rpx;
}
.user-sgin .main .day-list .item .num {
width: 68rpx;
height: 68rpx;
line-height: 58rpx;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
background-color: #f2f2f2;
}
.user-sgin .main .day-list .item .circle {
position: relative;
}
.user-sgin .main .day-list .item .circle::before {
content: "";
height: 6rpx;
background-color: #f2f2f2;
width: 34rpx;
position: absolute;
right: 68rpx;
top: 34rpx;
}
.user-sgin .main .day-list .item:nth-of-type(7n+1) .circle::before {
background-color: rgba(0, 0, 0, 0);
}
.user-sgin .main .day-list .item .active-circle::before {
background-color: #FFBD40;
}
.user-sgin .main .right-sgin {
padding: 35rpx 145rpx;
}
.user-sgin .main .right-sgin .primary-button {
color: #fff;
background: linear-gradient(270deg, rgba(249, 95, 47, 1) 0%, rgba(252, 67, 54, 1) 55%, rgba(255, 44, 60, 1) 100%);
}
.user-sgin .main .contain .task {
border-top: 1px solid $-color-border;
}
.user-sgin .main .contain .task .item {
padding: 23rpx 30rpx;
}
.user-sgin .main .contain .task .item .img {
width: 74rpx;
height: 74rpx;
border-radius: 22rpx;
}
.user-sgin .main .contain .task .item .con {
flex: 1;
}
.user-sgin .main .contain .task .item .btn {
width: 154rpx;
border: 1px solid #FF2C3C;
}
.user-sgin .main .contain .task .item .con .num {
color: #FF2C3C;
}
.user-sgin .main .contain .task .item .primary {
color: #FF2C3C;
}
.score-detail-entry {
background-color: rgba(255, 255, 255, 0.3);
border-radius: 100rpx 0rpx 0rpx 100rpx;
padding: 12rpx 19rpx 12rpx 16rpx;
align-self: flex-end;
}
.van-popup {
background-color: rgba(0, 0, 0, 0) !important;
}
.pop-container {
background-repeat: no-repeat;
background-size: 100%;
height: 626rpx;
width: 560rpx;
position: relative;
background-image: url('../../static/jifen_popBg.png');
}
.u-mode-center-box {
background-color: rgba(0, 0, 0, 0) !important;
}
.header-score {
font-size: 46rpx;
line-height: 36rpx;
font-weight: bold;
padding-top: 90rpx;
padding-bottom: 150rpx;
// color: #FF2C3C;
color: #FF8412;
}
.desc {
color: white;
background: linear-gradient(82deg, rgba(250, 81, 50, 1) 0%, rgba(236, 60, 34, 1) 49%, rgba(250, 83, 50, 1) 100%);
padding: 16rpx 22rpx 16rpx 42rpx;
text-align: center;
}
.bottom-box {
margin-top: 84rpx;
text-align: center;
}
.primary-btn {
margin: 0 60rpx;
width: 440rpx;
height: 74rpx;
border-radius: 37rpx;
padding: 16rpx 190rpx;
// background: linear-gradient(#f95f2f 0%, #ff2c3c 100%);
background: linear-gradient(#f95f2f 0%, #ff2c3c 100%);
}
.gray {
background-color: #f2f2f2 !important;
}
</style>

160
bundle/pages/invite_fans/invite_fans.vue

@ -0,0 +1,160 @@
<template>
<view class="pages">
<view class="invite-fans flex-col col-center">
<image :src="path" mode="widthFix" class="poster"></image>
<invite-poster v-if="showPoster" :config="{
avatar: userInfo.avatar,
nickname: userInfo.nickname,
code: inviteCode,
link: link,
qrCode: qrCode,
poster: poster
}" @success="handleSuccess" />
<view class="bg-white footer flex-1">
<view class="m-b-40">
<view class="m-b-10 sm lighter">我的邀请码</view>
<view class="flex row-between">
<view class="font-size-44">{{inviteCode}}</view>
<view class="sm m-r-30 copy-btn" @tap="onCopy(inviteCode)">点击复制</view>
</view>
</view>
<!-- #ifndef H5 -->
<button class="save-btn br60" size="lg" @tap="saveImageToAlbum">保存到相册</button>
<!-- #endif -->
<!-- #ifdef H5 -->
<button class="save-btn br60" size="lg">长按保存到相册</button>
<!-- #endif -->
</view>
</view>
<loading-view v-show="loading"></loading-view>
</view>
</template>
<script>
import {
apiMnpQrCode
} from '@/api/app'
import {
baseURL,
basePath
} from '@/config/app'
import {
mapGetters
} from 'vuex'
import {
apiDistributionPoster
} from '@/api/user'
import {
copy
} from '@/utils/tools.js'
export default {
data() {
return {
path: '',
qrCode: '',
loading: true,
showPoster: false,
poster: ''
};
},
async onLoad() {
await this.getPoster()
// #ifdef MP-WEIXIN
this.getMnpQrCode()
// #endif
// #ifdef APP-PLUS || H5
this.showPoster = true
// #endif
},
methods: {
onCopy(text) {
copy(text)
},
async getPoster() {
const res = await apiDistributionPoster()
this.poster = res.data.poster
},
getMnpQrCode() {
apiMnpQrCode({
type: 0,
url: 'pages/index/index'
}).then(res => {
console.log(res)
this.qrCode = res.data.qr_code
this.showPoster = true
})
},
saveImageToAlbum() {
// #ifndef H5
uni.saveImageToPhotosAlbum({
filePath: this.path,
success: res => {
this.$toast({
title: "保存成功"
});
},
fail: err => {
this.$toast({
title: '保存失败'
});
}
});
// #endif
// #ifdef H5
this.$toast({
title: '请长按图片保存'
})
// #endif
},
handleSuccess(val) {
this.path = val
this.loading = false
}
},
computed: {
...mapGetters(['inviteCode', 'userInfo']),
link() {
return `${baseURL}${basePath}?invite_code=${this.inviteCode}`
}
}
};
</script>
<style lang="scss">
page {
padding: 0
}
.invite-fans {
min-height: 100vh;
overflow: hidden;
.poster {
width: 600rpx;
margin: 40rpx 0;
}
.footer {
padding: 30rpx;
width: 100%;
}
.copy-btn {
color: $-color-primary;
}
.save-btn {
color: #fff;
background-color: $-color-primary;
;
}
}
</style>

379
bundle/pages/invoice/invoice.vue

@ -0,0 +1,379 @@
<template>
<view class="invoice">
<view class="box bg-white">
<!-- 发票类型 -->
<view class="item flex row-between" @click="handleOpenInvoiceType">
<view class="label">发票类型</view>
<view class="content flex-1 flex row-right">
<text>{{ type == 0 ? '增值税电子普通发票' : '增值税专用发票' }}</text>
<u-icon name="arrow-right" size="22" v-if="formData.header_type == 1"></u-icon>
</view>
</view>
<!-- 抬头类型 -->
<view class="item flex row-between">
<view class="label">抬头类型</view>
<view class="content flex-1 flex row-right">
<u-radio-group v-model="formData.header_type">
<u-radio v-for="(item, index) in list" :key="index" :name="item.header_type"
:disabled="item.disabled" :active-color="colorConfig.primary">
{{item.name}}
</u-radio>
</u-radio-group>
</view>
</view>
<!-- 发票抬头 -->
<view class="item flex row-between">
<view class="label">发票抬头</view>
<view class="content">
<u-input v-model="formData.name" input-align="right" placeholder="填写需要开具发票的姓名" />
</view>
</view>
<!-- 税号 -->
<view class="item flex row-between" v-show="formData.header_type === 1">
<view class="label">税号</view>
<view class="content flex-1 flex row-right">
<u-input v-model="formData.duty_number" input-align="right" placeholder="纳税人识别号" />
</view>
</view>
<!-- 邮箱 -->
<view class="item flex row-between">
<view class="label">邮箱</view>
<view class="content flex-1 flex row-right">
<u-input v-model="formData.email" input-align="right" placeholder="您的联系邮箱" />
</view>
</view>
<!-- 企业地址 -->
<view class="item flex row-between" v-show="type == 1 && formData.header_type == 1">
<view class="label">企业地址</view>
<view class="content flex-1 flex row-right">
<u-input v-model="formData.address" input-align="right" placeholder="必填" />
</view>
</view>
<!-- 企业电话 -->
<view class="item flex row-between" v-show="type == 1 && formData.header_type == 1">
<view class="label">企业电话</view>
<view class="content flex-1 flex row-right">
<u-input v-model="formData.mobile" input-align="right" placeholder="必填" />
</view>
</view>
<!-- 开户银行 -->
<view class="item flex row-between" v-show="type == 1 && formData.header_type == 1">
<view class="label">开户银行</view>
<view class="content flex-1 flex row-right">
<u-input v-model="formData.bank" input-align="right" placeholder="必填" />
</view>
</view>
<!-- 银行账号 -->
<view class="item flex row-between" v-show="type == 1 && formData.header_type == 1">
<view class="label">银行账号</view>
<view class="content flex-1 flex row-right">
<u-input v-model="formData.bank_account" input-align="right" placeholder="必填" />
</view>
</view>
</view>
<view class="footer">
<view class="" v-if="order_id && shop_id">
<button class="submit-btn br60 white btn" size="lg" @click="handleInvoiceAdd">提交申请</button>
</view>
<view class="" v-if="invoice_id && shop_id">
<button class="submit-btn br60 white btn" size="lg" @click="handleInvoiceEdit">提交编辑</button>
</view>
<view class="" v-if="shop_id && !invoice_id && !order_id">
<button class="submit-btn br60 white btn" size="lg" @click="handleConfirm">确定</button>
</view>
<view class="m-t-40">
<button class="cancel-btn br60 white btn" size="lg" @click="handleCancel">不开发票</button>
</view>
</view>
<!-- 发票类型选择 -->
<u-popup v-model="showCoupon" border-radius="14" mode="bottom" closeable :safe-area-inset-bottom="true" @open="type=formData.type" @close="handleCloseInvoiceType">
<view class="p-30 bg-body">
<view class="text-center">发票类型选择</view>
</view>
<view class="invoice-type bg-body">
<!-- 普票 -->
<view class="invoice-type--item bg-white flex row-between" @click="type=0">
<view>
<view class="nr black">增值税电子普通发票</view>
<view class="xs lighter m-t-14">默认发送至所提供的电子邮件</view>
</view>
<u-checkbox :value="type==0" shape="circle"
name="0"></u-checkbox>
</view>
<!-- 专票 -->
<view class="invoice-type--item bg-white flex row-between" @click="type=1" v-show="spec_invoice">
<view>
<view class="nr black">增值税专用发票</view>
<view class="xs lighter m-t-14">纸质发票开出后将以邮寄形式交付</view>
</view>
<u-checkbox :value="type==1" shape="circle"
name="1"></u-checkbox>
</view>
<!-- 底部确认按钮 -->
<view class="invoice-type-confirm-btn">
<button class="confirm br60 white btn" size="lg" @click="handleChoise">确定</button>
</view>
</view>
</u-popup>
</view>
</template>
<script>
import {
getInvoiceSetting,
apiInvoiceAdd,
apiInvoiceEdit,
apiInvoiceDetail
} from "@/api/shop.js"
import { invoiceType } from "@/utils/type.js"
export default {
data() {
return {
shop_id: '', // ID
invoice_id: '', // ID
order_id: '', // ID
showCoupon: false,
list: [{
name: '个人',
header_type: 0,
disabled: false
},
{
name: '企业',
header_type: 1,
disabled: false
}
],
formData: {
id: '', // int id
order_id: '', // int id
type: 0, // int 0- 1-
header_type: 0, // int 0- 1-
name: '', // string
duty_number: '',// string
email: '', // string
mobile: '', // string
address: '', // string
bank: '', // string
bank_account: ''// string
},
type: 0, //
open_invoice: 0, // 0- 1-
spec_invoice: 0 // 0- 1-
};
},
methods: {
//
initInvoiceSetting() {
getInvoiceSetting({
shop_id: this.shop_id,
}).then(res => {
this.spec_invoice = res.data.spec_invoice
if ( res.data.open_invoice ) this.open_invoice = res.data.open_invoice
else this.$toast({ title: '当前店铺暂未开启发票' })
})
},
//
getInvoiceDetail() {
apiInvoiceDetail({ id: this.invoice_id }).then(res => {
for (const key in res.data) {
if (!this.formData.hasOwnProperty(key)) continue
this.formData[key] = res.data[key]
}
})
},
initRules() {
const form = this.formData
if(!this.open_invoice) {
this.$toast({title: '当前店铺暂未开启发票'})
return false
}
if(!form.name) {
this.$toast({title: '请输入发票抬头'})
return false
}
if(!form.duty_number && form.header_type == 1) {
this.$toast({title: '请输入税号'})
return false
}
if(!form.email) {
this.$toast({title: '请输入邮箱地址'})
return false
}
if(!/^[0-9a-zA-Z_.-]+[@][0-9a-zA-Z_.-]+([.][a-zA-Z]+){1,2}$/.test(form.email)) {
this.$toast({title: '邮箱输入有误,请重新输入'})
return false
}
if(!form.address && form.header_type == 1 && form.type == 1) {
this.$toast({title: '请输入企业地址'})
return false
}
if(!form.mobile && form.type == 1) {
this.$toast({title: '请输入手机号码'})
return false
}
if(!form.bank && form.header_type == 1 && form.type == 1) {
this.$toast({title: '请输入开户银行'})
return false
}
if(!form.bank_account && form.header_type == 1 && form.type == 1) {
this.$toast({title: '请输入银行账号'})
return false
}
return true
},
//
handleOpenInvoiceType() {
if( this.formData.header_type == 0 ) return
this.showCoupon=true
},
//
handleCloseInvoiceType() {
if( this.type != this.formData.type ) {
this.type = this.type == 1 ? 0 : 1
}
},
//
handleChoise() {
this.formData.type = this.type
this.showCoupon = false
},
//
handleConfirm() {
if(!this.initRules()) return
uni.$emit('invoice', {...this.formData, shop_id: this.shop_id});
uni.navigateBack()
},
//
handleInvoiceAdd() {
if(!this.initRules()) return
apiInvoiceAdd({...this.formData, order_id: this.order_id}).then(res => {
if(res.code == 1) {
setTimeout(() => {
uni.navigateBack()
}, 500)
}
})
},
//
handleInvoiceEdit() {
if(!this.initRules()) return
apiInvoiceEdit({...this.formData}).then(res => {
if(res.code == 1) {
setTimeout(() => {
uni.navigateBack()
}, 500)
}
})
},
//
handleCancel() {
if ( !this.order_id && !this.invoice_id ) {
uni.$emit('invoice', {del: true, shop_id: this.shop_id});
}
uni.navigateBack()
}
},
onLoad() {
const query = this.$Route.query;
switch (query.type * 1) {
case invoiceType['SETTLEMENT']:
this.shop_id = query.shop_id || ''
if( query.invoice != '{}') {
this.formData = JSON.parse(query.invoice)
this.type = this.formData.type
}
break;
case invoiceType['ORDERDETAILEdit']:
this.invoice_id = query.invoice_id || ''
this.shop_id = query.shop_id || ''
this.getInvoiceDetail()
break;
case invoiceType['ORDERDETAILADD']:
this.order_id = query.order_id || ''
this.shop_id = query.shop_id || ''
break;
}
//
this.initInvoiceSetting()
}
};
</script>
<style lang="scss">
.invoice {
height: calc(100vh - env(safe-area-inset-bottom));
padding: 24rpx;
position: relative;
.box {
padding: 20rpx 0;
border-radius: 16rpx;
.item {
padding: 16rpx 30rpx;
.label {
font-size: 28rpx;
color: $-color-black;
}
.content {
min-width: 440rpx;
}
}
}
.footer {
left: 0;
bottom: 0;
width: 100%;
padding: 24rpx;
position: absolute;
.btn {
height: 88rpx;
}
.submit-btn {
color: $-color-white;
background-color: #E39B37;
}
.cancel-btn {
color: #E39B37;
background-color: $-color-white;
}
}
.invoice-type {
padding: 40rpx;
padding-bottom: 0;
.invoice-type--item {
padding: 28rpx 36rpx;
border-radius: 40rpx;
margin-bottom: 30rpx;
}
.invoice-type-confirm-btn {
padding: 90rpx 0 50rpx 0;
.confirm {
background-color: #FF9E1E;
}
}
}
}
</style>

212
bundle/pages/invoice_detail/invoice_detail.vue

@ -0,0 +1,212 @@
<template>
<view class="invoice-detail">
<!-- Header Start -->
<view class="header white text-center flex-col row-center">
<view class="flex row-center lg bold">
<image v-if="!invoiceInfo.status" src="../../static/invoice_wait.png" mode=""></image>
<image v-else src="../../static/invoice_success.png" mode=""></image>
{{ invoiceInfo.status_text || '' }}
</view>
<view class="sm m-t-10" v-if="!invoiceInfo.status">正在开具发票中请耐心等候</view>
<view class="sm m-t-10" v-else>已开发票金额{{ invoiceInfo.invoice_amount }}</view>
</view>
<!-- Header End -->
<!-- Main Start -->
<view class="main">
<view class="card bg-white">
<view class="lg bold p-l-30 p-b-18">发票信息</view>
<view class="form-item">
<view class="label">发票金额</view>
<view class="content">{{ invoiceInfo.invoice_amount || '' }}</view>
</view>
<view class="form-item">
<view class="label">发票类型</view>
<view class="content">{{ invoiceInfo.type == 0 ? '普通' : '专用' }}</view>
</view>
<view class="form-item">
<view class="label">抬头类型</view>
<view class="content">{{ invoiceInfo.header_type_text }}</view>
</view>
<view class="form-item">
<view class="label">抬头名称</view>
<view class="content">{{ invoiceInfo.name || '' }}</view>
</view>
<view class="form-item" v-if="invoiceInfo.duty_number">
<view class="label">税号</view>
<view class="content">{{ invoiceInfo.duty_number || '' }}</view>
</view>
<view class="form-item">
<view class="label">邮箱</view>
<view class="content">{{ invoiceInfo.email || '' }}</view>
</view>
<view class="form-item" v-if="invoiceInfo.address">
<view class="label">企业地址</view>
<view class="content">{{ invoiceInfo.address || '' }}</view>
</view>
<view class="form-item" v-if="invoiceInfo.mobile">
<view class="label">企业电话</view>
<view class="content">{{ invoiceInfo.mobile || '' }}</view>
</view>
<view class="form-item" v-if="invoiceInfo.bank">
<view class="label">开户银行</view>
<view class="content">{{ invoiceInfo.bank || '' }}</view>
</view>
<view class="form-item" v-if="invoiceInfo.bank_account">
<view class="label">银行账号</view>
<view class="content">{{ invoiceInfo.bank_account || '' }}</view>
</view>
<view class="form-item">
<view class="label">申请时间</view>
<view class="content">{{ invoiceInfo.create_time || '' }}</view>
</view>
</view>
<view class="card bg-white m-t-20">
<view class="m-l-20">
<shop-title :shop="shopInfo" :is-link="false"></shop-title>
</view>
<order-goods :list="goodsInfo"></order-goods>
<view class="form-item">
<view class="label">订单状态</view>
<view class="content">{{ order_status_text }}</view>
</view>
<view class="form-item">
<view class="label">订单编号</view>
<view class="content">{{ order_sn }}</view>
</view>
<view class="form-item">
<view class="label">下单时间</view>
<view class="content">{{ create_time }}</view>
</view>
</view>
</view>
<!-- Main End -->
<!-- Footer Start -->
<view class="footer" v-if="!invoiceInfo.status">
<view class="btn br60">
<button class="btn br60" size="lg" @click="toEditInvoice">编辑发票</button>
</view>
</view>
<!-- Footer End -->
</view>
</template>
<script>
import { apiOrderInvoiceDetail } from "@/api/shop.js"
import { invoiceType } from "@/utils/type.js"
export default {
data() {
return {
invoiceInfo: {},//
goodsInfo: {}, //
shopInfo: {}, //
orderId: '', // ID
create_time: '',
order_status_text: '',
order_sn: ''
}
},
methods: {
//
initInvoiceInfoFunc() {
apiOrderInvoiceDetail({ id: this.orderId }).then(res => {
this.invoiceInfo = res.data.invoice;
this.goodsInfo = res.data.order_goods;
this.shopInfo = res.data.shop;
this.create_time = res.data.create_time;
this.order_status_text = res.data.order_status_text;
this.order_sn = res.data.order_sn;
})
},
//
toEditInvoice() {
this.$Router.push({
path: '/bundle/pages/invoice/invoice',
query: {
invoice_id: this.invoiceInfo.id,
shop_id: this.shopInfo.id,
type: invoiceType['ORDERDETAILEdit']
}
})
}
},
onLoad() {
const query = this.$Route.query;
this.orderId = query.id || ''
},
onShow() {
this.initInvoiceInfoFunc();
}
}
</script>
<style lang="scss">
.invoice-detail {
padding-bottom: 120rpx;
background: linear-gradient(to bottom, $-color-primary 230rpx, transparent 0);
.header {
height: 140rpx;
image {
width: 44rpx;
height: 44rpx;
}
}
.main {
.card {
padding: 24rpx 0 30rpx 0;
border-radius: 14rpx;
}
.form-item {
display: flex;
padding: 12rpx 30rpx;
color: $-color-normal;
font-size: 28rpx;
.label {
width: 120rpx;
text-align: right;
margin-right: 40rpx;
}
.content {
flex: 1;
}
}
}
.footer {
left: 0;
bottom: 20rpx;
width: 100%;
padding: 24rpx;
position: fixed;
.btn {
height: 88rpx;
color: $-color-white;
background-color: $-color-primary;
}
}
}
</style>

72
bundle/pages/license/license.vue

@ -0,0 +1,72 @@
<template>
<view class="license">
<view class="box bg-white">
<template v-if="images.length">
<view v-for="(item, index) in images" :key="index" class="m-b-25" @click="viewImage(index)">
<u-image :src="item" width="100%" height="348rpx">
</u-image>
</view>
</template>
<template v-else>
<view class="data-null xs muted">
<image src="../../../static/images/order_null.png" mode=""></image>
<view>
商家暂时还没有上传资质哦~
</view>
</view>
</template>
</view>
</view>
</template>
<script>
import {
getCopyright
} from "@/api/user";
export default {
data() {
return {
images: []
}
},
methods: {
getCopyrightFunc(id) {
getCopyright({shop_id: id}).then(res => {
this.images = res.data
})
},
viewImage(current) {
uni.previewImage({
current,
urls: this.images// http
});
}
},
onLoad() {
const id = this.$Route.query.id;
this.getCopyrightFunc(id)
}
}
</script>
<style lang="scss">
.license {
padding: 30rpx;
.box {
padding: 30rpx;
border-radius: 16rpx;
.data-null {
padding-top: 200rpx;
height: 700rpx;
text-align: center;
image {
width: 200rpx;
height: 200rpx;
}
}
}
}
</style>

102
bundle/pages/monthly_bill/monthly_bill.vue

@ -0,0 +1,102 @@
<template>
<view class="month-bill">
<mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback"
:up="upOption">
<view v-for="(item, index) in orderList" :key="index">
<view class="bill-time flex sm">
{{item.date}}
</view>
<view class="show-panel flex">
<view class="panel-item flex-col col-center">
<price-format :price="item.total_money" :subscript-size="26" :color="colorConfig.primary"
:first-size="36" :second-size="36" />
<view class="lighter label m-t-10">预估收入</view>
</view>
<view class="panel-item flex-col col-center">
<view class="xxl">{{item.order_num}}</view>
<view class="lighter label m-t-10">成交笔数</view>
</view>
<view class="panel-item flex-col col-center">
<router-link :to="{path: '/bundle/pages/monthly_bill_detail/monthly_bill_detail', query: {year: item.year, month: item.month}}">
<view class="flex lighter">
查看详情
<u-icon name="arrow-right" size="28rpx" color="#666666" />
</view>
</router-link>
</view>
</view>
</view>
</mescroll-body>
</view>
</template>
<script>
import {
getMonthBill
} from "@/api/user";
import MescrollMixin from "@/components/mescroll-uni/mescroll-mixins";
export default {
mixins: [MescrollMixin],
data() {
return {
orderList: [],
upOption: {
empty: {
icon: '/static/images/order_null.png',
tip: '暂无数据~', //
}
},
};
},
onLoad: function(options) {
},
methods: {
upCallback(page) {
let pageNum = page.num; // , 1
let pageSize = page.size; // , 10
getMonthBill({
page_size: pageSize,
page_no: pageNum,
}).then(({
data
}) => {
if (page.num == 1) this.orderList = [];
let curPageData = data.list;
let curPageLen = curPageData.length;
let hasNext = !!data.more;
this.orderList = this.orderList.concat(curPageData);
this.mescroll.endSuccess(curPageLen, hasNext);
}).catch(() => {
this.mescroll.endErr()
})
},
}
};
</script>
<style lang="scss">
.month-bill {
.bill-time {
padding: 20rpx;
line-height: 34rpx;
}
.show-panel {
background-color: white;
padding: 36rpx 0 26rpx;
}
.show-panel {
.panel-item {
flex: 1;
line-height: 34rpx;
}
}
}
.data-null {
padding-top: 200rpx;
}
</style>

156
bundle/pages/monthly_bill_detail/monthly_bill_detail.vue

@ -0,0 +1,156 @@
<template>
<view class="monthly-bill-detail">
<mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback"
:up="upOption">
<view class="content">
<view class="order-container">
<view v-for="(item, index) in orderList" :key="index" class="order-item bg-white m-t-20">
<view class="order-header flex row-between">
<view>订单编号{{item.order_sn}}</view>
</view>
<view class="order-content flex">
<view>
<u-image width="180rpx" height="180rpx" border-radius="6px" :src="item.goods_image" />
</view>
<view class="order-goods-info flex-1 m-l-20">
<view class="name sm line-2">{{item.goods_name}}</view>
<view class="flex row-between m-t-6">
<view class="xs muted">
<text class="m-r-10">
数量
</text>
<text class="normal nr">{{item.goods_num}}</text></view>
<view class="xs">
<text class="muted m-r-10">付款金额</text>
<price-format :subscript-size="28" :first-size="28" :second-size="28"
:price="item.pay_price" />
</view>
</view>
<view class="pre-income muted sm m-t-10">
<text class="m-r-10">预估收益</text>
<price-format :subscript-size="28" :first-size="28" :second-size="28"
:color="colorConfig.primary" :price="item.money" />
</view>
</view>
</view>
<view class="order-footer flex row-between">
<view class="time muted">{{item.create_time}}</view>
<view class="static sm" :style="'color: ' + (item.status == 1 ? '#F95F2F' : '#07CE1B')">
{{item.statusDesc}}</view>
</view>
</view>
</view>
</view>
<u-select v-model="showPop" :list="months" mode="single-column" @confirm="changeMonths"></u-select>
</mescroll-body>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | likeshop
// +----------------------------------------------------------------------
// |
// | giteehttps://gitee.com/likeshop_gitee
// | githubhttps://github.com/likeshop-github
// | 访https://www.likeshop.cn
// | 访https://home.likeshop.cn
// | 访http://doc.likeshop.cn
// | likeshop
// | likeshopgiteegithub
// | likeshop
// |
// | likeshop
// +----------------------------------------------------------------------
// | author: likeshop.cn.team
// +----------------------------------------------------------------------
import {
getMonthOrderDetail
} from "@/api/user";
import MescrollMixin from "@/components/mescroll-uni/mescroll-mixins";
export default {
mixins: [MescrollMixin],
data() {
return {
orderList: [],
upOption: {
empty: {
icon: '/static/images/order_null.png',
tip: '暂无数据~', //
}
},
};
},
onLoad() {
const {month, year} = this.$Route.query
this.year = year;
this.month = Number(month)
uni.setNavigationBarTitle({
title: this.month + '月账单明细'
})
},
methods: {
upCallback(page) {
let pageNum = page.num; // , 1
let pageSize = page.size; // , 10
let {
year,
month
} = this;
getMonthOrderDetail({
page_size: pageSize,
page_no: pageNum,
year: year,
month: month
}).then(({
data
}) => {
if (page.num == 1) this.orderList = [];
let curPageData = data.list;
let curPageLen = curPageData.length;
let hasNext = !!data.more;
this.orderList = this.orderList.concat(curPageData);
this.mescroll.endSuccess(curPageLen, hasNext);
}).catch(() => {
this.mescroll.endErr()
})
},
}
};
</script>
<style lang="scss">
.monthly-bill-detail .content {
padding: 0 20rpx;
.order-item {
border-radius: 14rpx;
.order-header {
padding: 20rpx 30rpx;
border-bottom: $-solid-border;
.guide-shop-btn {
background: linear-gradient(80deg, #F95F2F 0%, #FF2C3C 100%);
border-radius: 4rpx;
width: 134rpx;
height: 42rpx;
}
}
.order-content {
padding: 20rpx 30rpx 20rpx 20rpx;
border-bottom: $-solid-border;
}
.order-footer {
padding: 20rpx 30rpx 20rpx 20rpx;
.static {
color: #F95F2F;
}
}
}
}
</style>

553
bundle/pages/order_details/order_details.vue

@ -0,0 +1,553 @@
<template>
<view>
<view class="order-details">
<view class="header-bg"></view>
<view class="main">
<view class="header">
<view class="item" v-if="orderDetail.order_status == 0">
<view class="white lg m-b-10">等待买家付款</view>
<view class="white sm flex" v-if="cancelTime > 0">支付剩余 <u-count-down separator="zh"
:timestamp="cancelTime" separator-color="#fff" color="#fff" :separator-size="26"
:font-size="26" bg-color="transparent" @end="getOrderDetailFun"></u-count-down>
</view>
</view>
<view class="item" v-if="orderDetail.order_status == 1 && !orderDetail.pickup_code">
<view class="white lg m-b-10">等待商家发货</view>
<view class="white sm">您的商品正在打包中请耐心等待</view>
</view>
<view class="item" v-if="orderDetail.order_status == 1 && orderDetail.pickup_code">
<view class="white lg m-b-10">待取货</view>
<view class="white sm">请前往门店取货</view>
</view>
<view class="item" v-if="orderDetail.order_status == 2">
<view class="white lg m-b-10">已发货</view>
<view class="white sm">您的商品正在路中请耐心等待</view>
</view>
<view class="item" v-if="orderDetail.order_status == 3">
<view class="white lg m-b-10">已完成</view>
<view class="white sm">商品已签收期待再次购买</view>
</view>
<view class="item" v-if="orderDetail.order_status == 4">
<view class="white lg m-b-10">订单已关闭</view>
<!-- <view class="white sm">原因超时未支付</view> -->
</view>
</view>
<view class="address-wrap flex contain">
<image class="icon-md m-r-20" src="/static/images/icon_address.png"></image>
<view class="address">
<view>
<text class="name md m-r-10">{{orderDetail.consignee}}</text>
<text class="phone md">{{orderDetail.mobile}}</text>
<view class="area sm m-t-10 lighter">{{orderDetail.delivery_address}}</view>
</view>
</view>
</view>
<view class="order-info contain" v-if="team.status_text">
<view class="item flex" style="align-items: flex-start;">
<view class="title">拼购状态</view>
<view class="bt">{{team.status_text}}</view>
</view>
</view>
<view class="goods contain">
<view class="m-l-20">
<shop-title :shop="orderDetail.shop"></shop-title>
</view>
<order-goods :team="team" :link="true" :isJumpGoods="true" :list="orderDetail.order_goods"></order-goods>
</view>
<!-- 虚拟发货内容 -->
<template v-if="orderDetail.delivery_content">
<view class="order-info contain" @click="copy(orderDetail.delivery_content)">
<view class="item">
<view class="black" style="word-break: break-all;">{{orderDetail.delivery_content || '无'}}</view>
<view class="flex row-right m-t-30">
<view class="copy-btn">复制</view>
</view>
</view>
</view>
</template>
<!-- 扫码收货 -->
<view v-if="orderDetail.delivery_type == 2 " class="contain receive">
<!-- <view v-if="orderDetail.verification_status" class="delivery--die">
<u-image src="/static/images/delivery_die.png" width="134" height="98" mode="scaleFill" />
</view>
-->
<view class="receive-qr" v-if="orderDetail.show_pickup_code">
<text class="xs lighter">请凭二维码取货</text>
<view class="m-t-20 qr-contain" :class="{'qr-contain--die': orderDetail.verification_status}" ref="qr-image">
<tki-qrcode
ref="qrcode"
uni="px"
:val="orderDetail.pickup_code"
:size="118 * 2"
:showLoading="false"
/>
</view>
<view class="m-t-30 xs black qr-code">提货码{{ orderDetail.pickup_code }}</view>
</view>
<view class="p-30 flex col-top">
<view style="width: 140rpx;" class="bold">店铺地址: </view>
<view style="width: 500rpx;">
{{ orderDetail.shop_address }}
</view>
</view>
</view>
<view class="price contain">
<view class="flex row-between">
<view>商品金额</view>
<view class="black">
<price-format :price="orderDetail.goods_price"></price-format>
</view>
</view>
<view class="flex row-between">
<view>运费</view>
<view class="black">+
<price-format :price="orderDetail.shipping_price"></price-format>
</view>
</view>
<view v-if="orderDetail.discount_amount != 0" class="flex row-between">
<view>优惠券</view>
<view class="primary">-
<price-format :price="orderDetail.discount_amount"></price-format>
</view>
</view>
<view v-if="orderDetail.member_amount" class="flex row-between">
<view>会员抵扣</view>
<view class="primary">-
<price-format :price="orderDetail.member_amount"></price-format>
</view>
</view>
<view class="flex row-right">
<view class="lighter">实付金额</view>
<view class="primary xl">
<price-format weight="500" :first-size="34" :second-size="34"
:price="orderDetail.order_amount"></price-format>
</view>
</view>
</view>
<view class="order-info contain">
<view class="item flex" style="align-items: flex-start;">
<view class="title">买家留言</view>
<view class="black">{{orderDetail.user_remark || '无'}}</view>
</view>
</view>
<view class="order-info contain">
<view class="item flex">
<view class="title">订单编号</view>
<view class="black">{{orderDetail.order_sn}}</view>
</view>
<view class="item flex">
<view class="title">订单类型</view>
<view class="black">{{orderDetail.order_type}}</view>
</view>
<view class="item flex">
<view class="title">支付方式</view>
<view class="black">{{orderDetail.pay_way}}</view>
</view>
<view class="item flex">
<view class="title">下单时间</view>
<view class="black">{{orderDetail.create_time}}</view>
</view>
<view v-if="orderDetail.pay_time" class="item flex">
<view class="title">付款时间</view>
<view class="black">{{orderDetail.pay_time}}</view>
</view>
<view v-if="orderDetail.shipping_time" class="item flex">
<view class="title">发货时间</view>
<view class="black">{{orderDetail.shipping_time }}</view>
</view>
<view v-if="orderDetail.confirm_take_time" class="item flex">
<view class="title">成交时间</view>
<view class="black">{{orderDetail.confirm_take_time }}</view>
</view>
<view v-if="orderDetail.cancel_time" class="item flex">
<view class="title">关闭时间</view>
<view class="black">{{orderDetail.cancel_time}}</view>
</view>
</view>
<view class="footer bg-white flex fixed row-right"
v-if="orderDetail.cancel_btn || orderDetail.delivery_btn || orderDetail.take_btn || orderDetail.del_btn || orderDetail.pay_btn || orderDetail.view_invoice_btn || orderDetail.save_invoice_btn">
<!-- 左侧更多 -->
<!-- <view class="more">
<view class="flex" v-if="orderDetail.view_invoice_btn || orderDetail.save_invoice_btn" @click="moreStatus=!moreStatus">
<text class="m-r-10">更多</text>
<u-icon name="arrow-up" size="22"></u-icon>
</view>
<view class="more-container bg-white" v-show="moreStatus">
<navigator v-if="orderDetail.view_invoice_btn" hover-class="none"
:url="'/bundle/pages/invoice_detail/invoice_detail?id=' + orderDetail.id">
<view class="more-item" >查看发票</view>
</navigator>
<navigator v-if="orderDetail.save_invoice_btn" hover-class="none"
:url="'/bundle/pages/invoice/invoice?shop_id=' + orderDetail.shop.id + '&order_id=' + orderDetail.id + '&type=' + invoiceType">
<view class="more-item">申请开票</view>
</navigator>
</view>
</view> -->
<!-- 右侧订单操作按钮组 -->
<view class="flex">
<view v-if="orderDetail.cancel_btn">
<button size="sm" class="plain br60" hover-class="none" @tap="cancelOrder">取消订单</button>
</view>
<navigator v-if="orderDetail.view_invoice_btn && orderDetail.shop.open_invoice" hover-class="none" class="m-l-20"
:url="'/bundle/pages/invoice_detail/invoice_detail?id=' + orderDetail.id">
<button size="sm" class="plain br60" hover-class="none">查看发票</button>
</navigator>
<navigator v-if="orderDetail.save_invoice_btn && orderDetail.shop.open_invoice" hover-class="none" class="m-l-20"
:url="'/bundle/pages/invoice/invoice?shop_id=' + orderDetail.shop.id + '&order_id=' + orderDetail.id + '&type=' + invoiceType">
<button size="sm" class="plain br60" hover-class="none">申请开票</button>
</navigator>
<navigator v-if="orderDetail.delivery_btn" hover-class="none" class="m-l-20"
:url="'/bundle/pages/goods_logistics/goods_logistics?id=' + orderDetail.id">
<button size="sm" class="plain br60" hover-class="none">查看物流</button>
</navigator>
<view v-if="orderDetail.take_btn" class="m-l-20">
<button size="sm" class="plain br60 primary red" hover-class="none"
@tap.stop="comfirmOrder">确认收货</button>
</view>
<view v-if="orderDetail.del_btn" class="m-l-20">
<button size="sm" class="plain br60" hover-class="none" @tap="delOrder">删除订单</button>
</view>
<view class="m-l-20" v-if="orderDetail.pay_btn">
<button size="sm" class="bg-primary br60 white" @tap="payNow">立即付款</button>
</view>
</view>
</view>
</view>
</view>
<loading-view v-if="isFirstLoading"></loading-view>
<order-dialog ref="orderDialog" :orderId="orderDetail.id" :type="type" @confirm="confirmDialog"></order-dialog>
<loading-view v-if="showLoading" background-color="transparent" :size="50"></loading-view>
<float-tab></float-tab>
</view>
</template>
<script>
import {
getOrderDetail,
cancelOrder,
delOrder,
confirmOrder
} from '@/api/order';
import {
copy
} from "@/utils/tools.js"
import { invoiceType } from "@/utils/type.js"
export default {
data() {
return {
orderDetail: {
shop: {}
},
team: {},
isFirstLoading: true,
type: 0,
cancelTime: 0,
showCancel: "",
showLoading: false,
moreStatus: false, //
invoiceType: invoiceType['ORDERDETAILADD']
};
},
onLoad: function(options) {
const {
id
} = this.$Route.query;
this.id = id;
},
onShow() {
this.moreStatus = false;
this.getOrderDetailFun();
},
methods: {
async confirmDialog() {
const { type, id } = this
let res = null
switch (type) {
case 0:
res = await cancelOrder(id);
break;
case 1:
res = await delOrder(id);
break;
case 2:
res = await confirmOrder(id);
break;
}
if(res.code == 1) {
uni.$emit("refreshorder")
if ([0, 2].includes(type)) {
this.getOrderDetailFun();
} else if (type == 1) {
setTimeout(() => {
uni.navigateBack()
}, 2000)
}
}
},
//
dialogOpen() {
this.$refs.orderDialog.open()
},
//
delOrder() {
this.type = 1
this.$nextTick(() => {
this.dialogOpen();
});
},
//
comfirmOrder() {
this.type = 2
this.$nextTick(() => {
this.dialogOpen();
});
},
//
cancelOrder() {
this.type = 0
this.$nextTick(() => {
this.dialogOpen();
});
},
//
payNow() {
uni.$on('payment', params => {
setTimeout(() => {
if (params.result) {
this.$toast({ title: "支付成功" })
this.getOrderDetailFun();
uni.$emit("refreshorder")
uni.$off("payment")
} else {
this.$toast({ title: "支付失败" })
}
}, 500)
})
uni.navigateTo({
url: `/pages/payment/payment?from=${'order'}&order_id=${this.id}`
})
},
//
getOrderDetailFun() {
getOrderDetail(this.id).then(res => {
console.log(res)
if (res.code == 1) {
this.cancelTime = res.data.order_cancel_time - Date.now() / 1000;
this.orderDetail = res.data
this.team = res.data.team || {}
this.$nextTick(() => {
this.isFirstLoading = false
if (res.data.delivery_type === 2) {
const refQR = this.$refs['qrcode']
refQR._makeCode()
}
});
} else {
setTimeout(() => uni.navigateBack(), 1500)
}
});
},
//
copy(content) {
copy(content)
}
}
};
</script>
<style lang="scss">
.bt {
width: 100%;
text-align: right;
}
.order-details {
position: relative;
padding-bottom: calc(120rpx + env(safe-area-inset-bottom));
}
.order-details .header-bg {
position: absolute;
top: 0;
width: 100%;
height: 200rpx;
background-color: $-color-primary;
z-index: 0;
}
.order-details .goods .status {
height: 88rpx;
padding: 0 20rpx;
}
.order-details .main {
position: relative;
z-index: 1;
}
.order-details .contain {
margin: 0 20rpx 20rpx;
border-radius: 14rpx;
background-color: #fff;
}
.order-details .header {
padding: 24rpx 40rpx;
box-sizing: border-box;
}
.order-details .img-line {
height: 1.5px;
width: 100%;
display: block;
}
.order-details .address-wrap {
height: 164rpx;
padding: 0 24rpx;
}
.order-details .order-info {
padding: 12rpx 0;
}
.order-details .order-info .item {
padding: 12rpx 24rpx;
}
.order-details .order-info .copy-btn {
font-size: 24rpx;
padding: 6rpx 18rpx;
border-radius: 8rpx;
color: $-color-primary;
background: rgba($color: $-color-primary, $alpha: .1);
}
.order-details .order-info .item .title {
width: 180rpx;
flex: none;
}
.receive-qr {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 460rpx;
}
.qr-contain {
box-sizing: border-box;
display: flex;
justify-content: center;
align-items: center;
width: 140px;
height: 140px;
padding: 8px;
// border: 1px solid #CCCCCC;
border-radius: 5px;
}
.qr-contain--die {
position: relative;
}
.qr-contain--die::before {
position: absolute;
z-index: 99;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: block;
content: '';
background-color: rgba(255, 255, 255, .5);
}
.qr-code {
padding: 8rpx 30rpx;
border-radius: 60px;
background-color: #F6F6F6;
}
.order-details .price>view {
height: 60rpx;
padding: 0 24rpx;
}
.order-details .footer {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 100rpx;
padding: 0 24rpx;
box-sizing: content-box;
padding-bottom: env(safe-area-inset-bottom);
}
.footer .plain {
border: 1px solid #BBBBBB;
}
.footer .plain.red {
border: 1px solid $-color-primary;
}
.tips-dialog {
height: 230rpx;
width: 100%;
}
.order-details .invite-btn {
background: linear-gradient(270deg, #FF2C3C 0%, #F95F2F 100%);
margin: 30rpx 26rpx 40rpx;
}
//
.more {
position: relative;
.more-container {
width: 200rpx;
bottom: 70rpx;
left: -20rpx;
position: absolute;
border: 1px solid #e9e9e9;
.more-item {
padding: 10rpx 20rpx;
text-align: center;
border-top: 1px solid #e9e9e9;
}
.more-item:first-child {
border-top: 0;
}
}
}
</style>

63
bundle/pages/recharge_record/recharge_record.vue

@ -0,0 +1,63 @@
<!-- 账户明细 -->
<template>
<view class="user-growth">
<mescroll-body ref="mescrollRef" @init="mescrollInit" @up="upCallback" :up="upOption" @down="downCallback">
<view class="p-t-20" >
<view class="bg-white" v-for="(item, index) in list" :key="index" >
<record-cell :remark="item.desc" :date="item.create_time" :money="item.total" :type="1" />
</view>
</view>
</mescroll-body>
</view>
</template>
<script>
import MescrollMixin from "@/components/mescroll-uni/mescroll-mixins.js";
import {getRechargeRecord} from "@/api/user"
export default {
mixins: [MescrollMixin], // 使mixin
data() {
return {
// Tabs
upOption: {
empty: {
icon: '/static/images/order_null.png',
tip: '暂无记录', //
}
},
list: [], // --
};
},
methods: {
//
upCallback(page) {
const pageNum = page.num; // , 1
const pageSize = page.size; // , 10
getRechargeRecord({
page_size: pageSize,
page_no: pageNum
}).then(({
data
}) => {
if (page.num == 1) this.list = [];
const curPageData = data.lists;
const curPageLen = curPageData.length;
const hasNext = !!data.more;
this.list = this.list.concat(curPageData);
this.mescroll.endSuccess(curPageLen, hasNext);
}).catch(() => {
this.mescroll.endErr()
})
}
},
}
</script>
<style scoped>
</style>

72
bundle/pages/server_explan/server_explan.vue

@ -0,0 +1,72 @@
<template>
<view>
<view class="main">
<u-parse :html="content" />
</view>
</view>
</template>
<script>
import {
getServerProto,
getPrivatePolicy,
getAfterSaleGuar
} from '@/api/app';
import {
getTreaty
} from '@/api/shop'
export default {
data() {
return {
content: ""
};
},
onLoad() {
this.type = Number(this.$Route.query.type)
// 0 ==> 1 ==> 2 ==>
this.getData()
},
methods: {
async getData() {
let res = {}
switch (this.type) {
case 0:
uni.setNavigationBarTitle({
title: '服务协议'
});
res = await getServerProto();
break;
case 1:
uni.setNavigationBarTitle({
title: '隐私政策'
});
res = await getPrivatePolicy();
break;
case 2:
uni.setNavigationBarTitle({
title: '售后保障'
});
res = await getAfterSaleGuar();
break;
case 3:
uni.setNavigationBarTitle({
title: '入驻协议'
});
res = await getTreaty();
break;
}
if(res.code == 1) {
this.content = res.data.content;
}
}
}
};
</script>
<style lang="scss">
.main {
padding: 20rpx;
}
</style>

97
bundle/pages/settled_recode/settled_recode.vue

@ -0,0 +1,97 @@
<template>
<mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback" :down="downOption"
:up="upOption">
<view class="settled-recode">
<view class="settled-list">
<router-link v-for="(item, index) in list" :key="index" :to="{path: '/bundle/pages/settled_result/settled_result', query: {id: item.id}}">
<view class="settled-item bg-white m-t-20">
<!-- Title -->
<view class="settled-title md bold">{{item.name}}</view>
<view class="settled-info">
<!-- Time -->
<view class="sm muted m-t-26">
提交时间{{item.apply_time}}
</view>
<!-- Status -->
<view class="flex row-between m-t-20">
<view class="muted sm" style="align-self: flex-end;">
<text>申请状态</text>
<text :class="{primary: item.audit_status == 3}">{{item.audit_status_desc}}</text>
</view>
<view class="watch-btn br60 flex row-center" @tap="onShowDetail">查看</view>
</view>
</view>
</view>
</router-link>
</view>
</view>
</mescroll-body>
</template>
<script>
import MescrollMixin from "@/components/mescroll-uni/mescroll-mixins";
import {
shopApplyRecord
} from '@/api/shop'
export default {
mixins: [MescrollMixin],
data() {
return {
upOption: {
empty: {
icon: '/static/images/order_null.png',
tip: "暂无记录",
}
},
list: []
};
},
methods: {
upCallback(page) {
shopApplyRecord({
page_size: page.size,
page_no: page.num
}).then(({
data
}) => {
if (page.num == 1) this.list = [];
let curPageData = data.lists;
let curPageLen = curPageData.length;
let hasNext = !!data.more;
this.list = this.list.concat(curPageData);
this.mescroll.endSuccess(curPageLen, hasNext);
}).catch(() => {
this.mescroll.endErr()
})
},
}
}
</script>
<style lang="scss">
.settled-recode {
.settled-list {
padding: 20rpx;
.settled-item {
border-radius: 10rpx;
padding: 20rpx 30rpx 30rpx;
.settled-title {
padding: 21rpx 0 25rpx;
border-bottom: $-solid-border;
}
.settled-info {
.watch-btn {
border: $-solid-border;
height: 52rpx;
width: 124rpx;
}
}
}
}
}
</style>

192
bundle/pages/settled_result/settled_result.vue

@ -0,0 +1,192 @@
<template>
<view class="settled-result">
<view class="result-box">
<!-- Header -->
<view class="result-header bg-white flex-col col-center">
<u-image width="165rpx" height="165rpx" class="m-t-42" :src="getStatus.img" />
<view class="m-t-32 lg bold">{{getStatus.text}}</view>
<view>
<!-- 地址账号 -->
<view v-if="applyDetail.audit_status == 2">
<view class="m-t-40 flex flex-wrap">
<view class="m-r-20">PC管理后台地址<text class="lighter">{{applyDetail.admin_address}}</text>
</view>
<view class="btn-copy br60 text-center" @tap="onCopy(applyDetail.admin_address)">复制</view>
</view>
<view class="m-t-30 flex flex-wrap">
<view class="m-r-20">商家账号<text class="lighter">{{applyDetail.account}}</text></view>
<view class="btn-copy br60 text-center" @tap="onCopy(applyDetail.account)">复制</view>
</view>
</view>
<view class="m-t-20 muted sm text-center">{{getStatus.desc}}</view>
<view class="flex" v-if="applyDetail.audit_status !=2">
<router-link v-if="applyDetail.audit_status == 3" class="flex-1 m-r-20" to="/bundle/pages/store_settled/store_settled" >
<view class="br60 flex row-center primary back-btn m-t-60 md">重新提交</view>
</router-link>
<router-link class="flex-1" to="/pages/index/index" navType="pushTab">
<view class="br60 flex row-center back-btn m-t-60 md">返回首页</view>
</router-link>
</view>
</view>
</view>
<!-- Content -->
<view class="result-content bg-white m-t-20 p-20">
<view class="apply-form-item flex row-between">
<view><text class="primary m-r-10">*</text>商家名称</view>
<view>{{applyDetail.name}}</view>
</view>
<!-- 主营行业 -->
<view class="apply-form-item flex row-between">
<view><text class="primary m-r-10">*</text>主营类目</view>
<view>{{applyDetail.cid_desc}}</view>
</view>
<!-- 联系人姓名 -->
<view class="apply-form-item flex row-between">
<view><text class="primary m-r-10">*</text>联系人姓名</view>
<view>{{applyDetail.nickname}}</view>
</view>
<!-- 手机号码 -->
<view class="apply-form-item flex row-between">
<view><text class="primary m-r-10">*</text>手机号码</view>
<view>{{applyDetail.mobile}}</view>
</view>
<!-- 商家账号 -->
<view class="apply-form-item flex row-between">
<view><text class="primary m-r-10">*</text>商家账号</view>
<view>{{applyDetail.account}}</view>
</view>
<!-- 图片 -->
<view class="apply-form-item">
<view><text class="primary m-r-10">*</text>营业执照</view>
<view class="license-list flex m-t-10 flex-wrap">
<view v-for="(item,index) in license" class="m-r-14 m-t-20" @tap="previewImage(index)"
:key="index">
<u-image width="152rpx" height="152rpx" :src="item" />
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import {
shopApplyDetail
} from '@/api/shop'
import {copy} from '@/utils/tools'
export default {
data() {
return {
applyDetail: {},
license: []
}
},
methods: {
async getShopApplyDetail() {
const {
data,
code
} = await shopApplyDetail(this.id)
if (code == 1) {
this.applyDetail = data
this.license = data.license
}
},
previewImage(current) {
uni.previewImage({
current,
urls: this.license
})
},
onCopy(text) {
copy(text)
}
},
onLoad(options) {
this.id = this.$Route.query.id
this.getShopApplyDetail()
},
computed: {
getStatus() {
const {
applyDetail: {
audit_status
}
} = this
switch (audit_status) {
case 1:
return {
img: '/static/images/img_store_submit.png',
text: '恭喜您,资料提交成功!',
desc: '预计在3个工作日内审核完毕,如通过我们将会发送短信通知您,请注意查收!'
}
case 2:
return {
img: '/static/images/img_store_success.png',
text: '恭喜您,审核已通过!',
desc: '温馨提示:密码是您在创建账号时设置的登录密码,如忘记密码可联系官方客服进行修改!'
}
case 3:
return {
img: '/static/images/img_store_fail.png',
text: '很遗憾,审核不通过!',
desc: '请尽量完善您的资料信息再重新提交!'
}
default:
return {}
}
}
}
}
</script>
<style lang="scss" scoped>
.settled-result {
padding: 20rpx;
.result-box {
.result-header {
padding: 0 75rpx 50rpx;
border-radius: 10rpx;
.btn-copy {
width: 96rpx;
height: 42rpx;
line-height: 42rpx;
border: $-solid-border;
}
}
.back-btn {
height: 88rpx;
border: 1px solid #CCC;
&.primary {
border-color: $-color-primary;
color: $-color-primary;
}
}
.result-content {
border-radius: 10rpx;
.apply-form-item {
padding: 30rpx 0;
&:not(:last-of-type) {
border-bottom: $-solid-border;
}
}
}
}
}
</style>

38
bundle/pages/sign_rule/sign_rule.vue

@ -0,0 +1,38 @@
<template>
<view class="m-t-20 m-l-20 m-r-20">
<text class="nr sign-rule">{{rules}}</text>
</view>
</template>
<script>
import { getSignRule } from "@/api/activity";
export default {
data() {
return {
rules: '',
};
},
methods: {
getSignRuleFun() {
getSignRule()
.then(res => {
if(res.code == 1) {
this.rules = res.data.rule
}
})
}
},
onLoad() {
this.getSignRuleFun()
}
}
</script>
<style lang="scss">
.sign-rule {
line-height: 36rpx;
}
</style>

257
bundle/pages/store_settled/store_settled.vue

@ -0,0 +1,257 @@
<template>
<view class="store-settled">
<view class="content">
<view class="apply-form bg-white">
<!-- 商家名称 -->
<view class="apply-form-item">
<u-field label="商家名称" v-model="form.name" label-width="160" placeholder="请输入商家名称" required />
</view>
<!-- 主营行业 -->
<view class="apply-form-item" @tap="showPop=true">
<u-field label="主营类目" v-model="form.clabel" label-width="160" style="flex: 1;" placeholder="请选择行业类目"
required disabled>
<u-icon name="arrow-right" slot="right" size="28" />
</u-field>
</view>
<!-- 联系人姓名 -->
<view class="apply-form-item">
<u-field label="联系人姓名" v-model="form.nickname" label-width="160" placeholder="请输入联系人姓名" required />
</view>
<!-- 手机号码 -->
<view class="apply-form-item">
<u-field label="手机号码" v-model="form.mobile" label-width="160" placeholder="请输入手机号码" required />
</view>
<!-- 验证码 -->
<view class="apply-form-item">
<u-field label="验证码" label-width="160" placeholder="请输入验证码" required v-model="form.code">
<view slot="right" class="primary send-code-btn br60 flex row-center" @tap="sendSmsFun">
<u-verification-code unique-key="store-settled" ref="uCode" @change="codeChange">
</u-verification-code>
<view class="xs">{{codeTips}}</view>
</view>
</u-field>
</view>
<!-- 验证码 -->
<view class="apply-form-item">
<u-field label="创建账号" v-model="form.account" label-width="160" placeholder="请设置登录账号(可用手机号代替)"
required />
</view>
<!-- 设置密码 -->
<view class="apply-form-item">
<u-field label="设置密码" :password="true" v-model="form.password" label-width="160"
placeholder="请设置登录密码" required />
</view>
<!-- 上传图片 -->
<view class="apply-form-item">
<u-field label="营业执照" label-width="160" placeholder="请上传营业执照及行业相关资质证明" :border-bottom="false"
required disabled />
<view>
<u-upload ref="uUpload" :show-progress="false" :header="{token: $store.getters.token}"
:max-count="10" width="150" height="150" :action="action" upload-text="上传图片"
@on-success="onSuccess" @on-remove="onRemove" />
</view>
<view class="muted m-t-20 m-b-30">支持jpgpngjpeg格式的图片最多可上传10张</view>
</view>
<!-- 同意协议 -->
<view class="apply-form-item flex">
<u-checkbox shape="circle" :active-color="colorConfig.primary" v-model="isAgree">
<text class="sm">已阅读并同意</text>
</u-checkbox>
<router-link :to="{path: '/bundle/pages/server_explan/server_explan', query: {type: 3}}">
<text class="primary sm">入驻协议</text>
</router-link>
</view>
<!-- 提交申请 -->
<view style="padding: 30rpx 20rpx 30rpx 0;">
<button type="primary" size="lg" class="br60" @tap="onSubmit">提交申请</button>
</view>
<!-- 查阅记录 -->
<router-link to="/bundle/pages/settled_recode/settled_recode">
<view class="flex row-center muted">
<u-icon name="order" size="32" />
<view class="m-l-10">查看提交记录</view>
</view>
</router-link>
</view>
</view>
<u-select v-model="showPop" mode="single-column" value-name="id" label-name="name" :list="shopCategory"
@confirm="confirmSelect"></u-select>
</view>
</template>
<script>
import {
getShopCategory,
shopApply
} from "@/api/shop"
import {
baseURL
} from '@/config/app'
import {
sendSms
} from '@/api/app'
import {
SMSType
} from '@/utils/type'
export default {
data() {
return {
isAgree: false,
//
form: {
cid: '',
clabel: '',
name: '',
nickname: '',
mobile: '',
account: '',
password: '',
code: ''
},
codeTips: '',
shopCategory: [],
showPop: false,
action: baseURL + '/api/file/formimage',
fileList: []
}
},
onLoad() {
this.getShopCategoryFun()
},
methods: {
async getShopCategoryFun() {
const {
code,
data
} = await getShopCategory()
if (code == 1) {
this.shopCategory = data
}
},
sendSmsFun() {
if(!this.$refs.uCode.canGetCode) return
if (!this.form.mobile) {
this.$toast({
title: '请填写手机号信息'
})
return;
}
sendSms({mobile: this.form.mobile, key: SMSType.SJSQYZ}).then(res => {
if(res.code == 1) {
this.$toast({title:res.msg});
this.$refs.uCode.start();
}
})
},
codeChange(tip) {
this.codeTips = tip
},
//
async onSubmit() {
const {
form,
isAgree,
fileList
} = this
const submitObj = {
...form,
license: fileList
}
delete submitObj.clabel
if (!isAgree) return this.$toast({
title: '请先同意《入驻协议》'
})
const {
data,
code,
msg
} = await shopApply(submitObj)
if(code == 1) {
this.$toast({
title: msg
})
setTimeout(() => {
this.$Router.replace({
path: '/bundle/pages/settled_result/settled_result',
query: {
id: data.id
}
})
},1000)
}
},
confirmSelect(e) {
const {
value,
label
} = e[0]
this.form.cid = value
this.form.clabel = label
},
onSuccess(e) {
this.fileList.push(e.data.base_uri)
},
onRemove(index) {
this.fileList.splice(index, 1)
console.log(index)
},
},
}
</script>
<style lang="scss">
.store-settled {
background-color: #FA844C;
min-height: 100vh;
background-image: url(../../static/store_recruitment_bg.png);
background-repeat: no-repeat;
background-size: 100% auto;
overflow: hidden;
.content {
margin-top: 320rpx;
padding: 0 20rpx 31rpx;
.apply-form {
border-radius: 8px;
padding: 20rpx 0 30rpx 26rpx;
.apply-form-item {
.send-code-btn {
height: 56rpx;
width: 188rpx;
border: 1rpx solid $-color-primary;
}
}
.primary-btn {
width: 100%;
height: 88rpx;
background-color: $-color-primary;
}
}
}
// .pop-categories {
// .reason-item {
// padding: 24rpx 20rpx;
// .reason-desc {
// line-height: 46rpx;
// }
// }
// }
}
</style>

250
bundle/pages/user_address/user_address.vue

@ -0,0 +1,250 @@
<template>
<view class="user-address">
<view class="no-address flex-col col-center" v-if="!hasAddress">
<image class="img-null mt20" src="/static/images/address_null.png"></image>
<view class="sm muted">暂无添加地址请添加~</view>
</view>
<view class="address-list" v-else>
<u-radio-group v-model="currentId" class="radio-group" @change="radioChange" :active-color="colorConfig.primary">
<view v-for="(item, index) in addressList" :key="index" class="item bg-white m-b-20" @tap="onSelect(item.id)">
<view class="address">
<view class="consignee md bold">
{{item.contact}}
<text class="phone m-l-10">{{item.telephone}}</text>
</view>
<view class="lighter sm m-t-10">
{{item.province}} {{item.city}} {{item.district}} {{item.address}}
</view>
</view>
<view class="operation flex row-between">
<view @tap.stop="">
<u-radio class="radio flex" :name="item.id">
<text class="xs">{{currentId == item.id ? '默认' : '设为默认'}}</text>
</u-radio>
</view>
<view class="flex row-center">
<router-link :to="{path: '/bundle/pages/address_edit/address_edit', query: {id: item.id}}">
<view class="flex m-r-20">
<image class="icon-md m-r-10" src="/static/images/icon_edit.png"></image>
编辑
</view>
</router-link>
<view class="flex m-l-20" @tap.stop="showSurePop(item.id)">
<image class="icon-md m-r-10" src="/static/images/icon_del_1.png"></image>
删除
</view>
</view>
</view>
</view>
</u-radio-group>
</view>
<u-modal
id="delete-dialog"
v-model="deleteSure"
:show-cancel-button="true"
confirm-text="狠心删除"
:confirm-color="colorConfig.primary"
:show-title="false"
@confirm="delAddressFun">
<view class="flex-col col-center tips-dialog p-t-40">
<image class="icon-lg" src="/static/images/icon_warning.png"></image>
<view style="margin-top:30rpx">确认删除该地址吗</view>
</view>
</u-modal>
<view class="footer flex row-between fixed bg-white">
<!-- #ifdef H5 || MP-WEIXIN -->
<view class="btn flex row-center bg-gray br60 m-r-20" @click="getWxAddressFun" v-if="isWeixin">
<image class="icon-lg m-r-10" src="/static/images/icon_wechat.png"></image>
<text class="md">微信导入</text>
</view>
<!-- #endif -->
<router-link class="flex-1" :to="{path: '/bundle/pages/address_edit/address_edit'}">
<view class="btn bg-primary white md flex row-center br60">新增收货地址</view>
</router-link>
</view>
</view>
</template>
<script>
import { getAddressLists, delAddress, setDefaultAddress } from '@/api/user';
import wechath5 from '@/utils/wechath5'
import {isWeixinClient} from '@/utils/tools'
export default {
data() {
return {
addressList: [],
hasAddress: true,
deleteSure: false,
currentId: 0,
isWeixin: true
};
},
onLoad (options) {
this.type = this.$Route.query.type;
//#ifdef H5
this.isWeixin = isWeixinClient()
//#endif
},
onShow() {
this.getAddressListsFun();
},
methods: {
onSelect(id) {
if (this.type) {
uni.$emit('selectaddress', {
id
});
uni.navigateBack();
}
},
getAddressListsFun() {
getAddressLists().then(res => {
if (res.code == 1) {
if (res.data.length) {
this.addressList = res.data;
const defaultA = res.data.find((item) => item.is_default)
this.currentId = defaultA ? defaultA.id : 0
this.hasAddress = true;
} else {
this.hasAddress = false;
}
} else {
this.hasAddress = false
}
});
},
async radioChange(id) {
const {code, msg} = await setDefaultAddress(id)
if (code == 1) {
this.$toast({
title: msg
})
this.getAddressListsFun();
}
},
onLoadFun() {
this.getAddressListsFun();
},
delAddressFun() {
delAddress(this.delectId).then(res => {
if (res.code == 1) {
this.$toast({
title: res.msg
});
this.deleteSure = false
this.getAddressListsFun();
}
});
},
getWxAddressFun() {
// #ifdef H5
wechath5.getWxAddress().then((res) => {
uni.setStorageSync('wxAddress', JSON.stringify(res));
setTimeout(() => {
this.$Router.push({
path: '/bundle/pages/address_edit/address_edit'
})
}, 200);
})
// #endif
// #ifdef MP-WEIXIN
uni.authorize({
scope: 'scope.address',
success: (res) => {
uni.chooseAddress({
success: (res) => {
uni.setStorageSync('wxAddress', JSON.stringify(res));
setTimeout(() => {
this.$Router.push({
path: '/bundle/pages/address_edit/address_edit'
})
}, 200);
},
fail: (res) => {
if (res.errMsg == 'chooseAddress:cancel') return this.$toast({
title: '取消选择'
});
}
});
},
fail: (res) => {
uni.showModal({
title: '您已拒绝导入微信地址权限',
content: '是否进入权限管理,调整授权?',
success:(res) => {
if (res.confirm) {
uni.openSetting({
success: (res) => {}
});
} else if (res.cancel) {
return this.$toast({
title: '已取消!'
});
}
}
});
}
});
// #endif
},
showSurePop(id) {
this.deleteSure = true;
this.delectId = id;
},
}
};
</script>
<style lang="scss">
.user-address {
padding-bottom: calc(140rpx + env(safe-area-inset-bottom));
.no-address {
padding-top: 300rpx;
text-align: center;
}
.address-list {
padding: 10rpx 0;
.item {
padding: 0 30rpx;
.address {
padding: 20rpx 0;
border-bottom: $-solid-border;
}
.operation {
height: 80rpx;
}
}
.u-radio-group {
display: block;
}
}
.footer {
position: fixed;
left: 0;
right: 0;
bottom: 0;
height: 118rpx;
padding: 0 30rpx;
box-sizing: content-box;
padding-bottom: env(safe-area-inset-bottom);
.btn {
flex: 1;
height: 80rpx;
}
}
}
.tips-dialog {
height: 230rpx;
width: 100%;
}
</style>

85
bundle/pages/user_bill/user_bill.vue

@ -0,0 +1,85 @@
<!-- 账户明细 -->
<template>
<view class="user-bill">
<mescroll-body ref="mescrollRef" @init="mescrollInit" @up="upCallback" :up="upOption" @down="downCallback">
<u-tabs :list="tabsList" :is-scroll="false" :current="currentTab" :bold="false" :active-color="colorConfig.primary"
@change="changeTab" />
<view class="p-t-20" >
<view class="bg-white" v-for="(item, index) in list" :key="index" >
<record-cell :remark="item.source_type" :date="item.create_time_format" :money="item.change_amount_format" :type="item.change_type" />
</view>
</view>
</mescroll-body>
</view>
</template>
<script>
import MescrollMixin from "@/components/mescroll-uni/mescroll-mixins.js";
import {getAccountLog} from "@/api/user"
export default {
mixins: [MescrollMixin], // 使mixin
data() {
return {
// Tabs
tabsList: [{
name: '全部'
}, {
name: '收入'
}, {
name: '支出'
}],
upOption: {
empty: {
icon: '/static/images/order_null.png',
tip: '暂无记录', //
}
},
currentTab: 0,
list: [], // --
};
},
methods: {
// Tabs
changeTab(index) {
this.currentTab = index;
this.list = []
this.mescroll.resetUpScroll();
},
//
upCallback(page) {
const pageNum = page.num; // , 1
const pageSize = page.size; // , 10
getAccountLog({
page_size: pageSize,
page_no: pageNum,
source: 1,
type: this.currentTab
}).then(({
data
}) => {
if (page.num == 1) this.list = [];
const curPageData = data.list;
const curPageLen = curPageData.length;
const hasNext = !!data.more;
this.list = this.list.concat(curPageData);
this.mescroll.endSuccess(curPageLen, hasNext);
}).catch(() => {
this.mescroll.endErr()
})
}
},
onLoad(options) {
console.log(options, "option")
this.currentTab = options.mode || 0;
}
}
</script>
<style scoped>
</style>

51
bundle/pages/user_collection/user_collection.vue

@ -0,0 +1,51 @@
<template>
<view class="user-collection">
<tabs :is-scroll="false" :current="active" @change="onChange">
<tab name="商品">
<collection-list :type="1" :i="0" :index="active"></collection-list>
</tab>
<tab name="店铺">
<collection-list :type="2" :i="1" :index="active"></collection-list>
</tab>
</tabs>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | likeshop
// +----------------------------------------------------------------------
// |
// | giteehttps://gitee.com/likeshop_gitee
// | githubhttps://github.com/likeshop-github
// | 访https://www.likeshop.cn
// | 访https://home.likeshop.cn
// | 访http://doc.likeshop.cn
// | likeshop
// | likeshopgiteegithub
// | likeshop
// |
// | likeshop
// +----------------------------------------------------------------------
// | author: likeshop.cn.team
// +----------------------------------------------------------------------
export default {
data() {
return {
active: 0
};
},
methods: {
onChange(index) {
this.active = index
}
}
};
</script>
<style lang="scss">
</style>

35
bundle/pages/user_comment/user_comment.vue

@ -0,0 +1,35 @@
<template>
<view class="goods-comment-list">
<tabs :current="active" :is-scroll="false" @change="changeActive">
<tab name="待评价">
<comment-list type="1" :i="0" :index="active"></comment-list>
</tab>
<tab name="已评价">
<comment-list type="2" :i="1" :index="active"></comment-list>
</tab>
</tabs>
</view>
</template>
<script>
export default {
data() {
return {
active: -1
};
},
onLoad() {
this.type = this.$Route.query.type || 0;
this.active = parseInt(this.type)
},
methods: {
changeActive(e) {
this.active = e
}
}
};
</script>
<style>
</style>

41
bundle/pages/user_coupon/user_coupon.vue

@ -0,0 +1,41 @@
<template>
<view class="user-coupon">
<tabs :current="active" @change="onChange" :is-scroll="false">
<tab v-for="(item, index) in coupons" :key="index" :name="item.title">
<my-coupons :type="item.type" :btn-type="item.btnType" :i="index" :index="active"></my-coupons>
</tab>
</tabs>
</view>
</template>
<script>
export default {
data() {
return {
active: 0,
coupons: [{
title: '可使用',
btnType: 0,
type: 'valid'
}, {
title: '已使用',
btnType: 1,
type: 'used'
}, {
title: '已过期',
btnType: 2,
type: 'expired'
}]
};
},
methods: {
onChange(index) {
this.active = index
}
}
};
</script>
<style>
</style>

253
bundle/pages/user_fans/user_fans.vue

@ -0,0 +1,253 @@
<template>
<mescroll-body ref="mescrollRef" @init="mescrollInit" @up="upCallback" :up="upOption" :down="downOption"
@down="downCallback">
<view class="user-fans">
<view class="header">
<u-search v-model="keyword" shape="round" background="white" placeholder="请输入搜索关键词" @search="changeTab"
@custom="changeTab" />
<view class="top-bar flex bg-white md">
<view class="bar-item flex" :class="{'item-active': active == 'all'}" @tap="changeTab('all')">全部粉丝
</view>
<view class="bar-item flex" :class="{'item-active': active == 'first'}" @tap="changeTab('first')">
一级粉丝</view>
<view class="bar-item flex" :class="{'item-active': active == 'second'}" @tap="changeTab('second')">
二级粉丝</view>
</view>
<view class="sort-bar flex bg-white">
<view class="sort-bar-item flex row-center" @tap="sortChange(0)">
<view :class="sortType == 0 ? 'item-active' : ''">团队排序</view>
<view class="arrow-icon flex-col col-center row-center">
<u-icon name="arrow-up-fill"
:color="fansSort == 'asc' ? colorConfig.primary : colorConfig.normal"></u-icon>
<u-icon name="arrow-down-fill"
:color="fansSort == 'desc' ? colorConfig.primary : colorConfig.normal"></u-icon>
</view>
</view>
<view class="sort-bar-item flex row-center" @tap="sortChange(1)">
<view :class="sortType == 1 ? 'item-active' : ''">金额排序</view>
<view class="arrow-icon flex-col col-center row-center">
<u-icon name="arrow-up-fill"
:color="moneySort == 'asc' ? colorConfig.primary : colorConfig.normal"></u-icon>
<u-icon name="arrow-down-fill"
:color="moneySort == 'desc' ? colorConfig.primary : colorConfig.normal"></u-icon>
</view>
</view>
<view class="sort-bar-item flex row-center" @tap="sortChange(2)">
<view :class="sortType == 2 ? 'item-active' : ''">订单排序</view>
<view class="arrow-icon flex-col col-center row-center">
<u-icon name="arrow-up-fill"
:color="orderSort == 'asc' ? colorConfig.primary : colorConfig.normal"></u-icon>
<u-icon name="arrow-down-fill"
:color="orderSort == 'desc' ? colorConfig.primary : colorConfig.normal"></u-icon>
</view>
</view>
</view>
</view>
<view class="content">
<view class="card-box p-t-20">
<view v-for="(item, index) in fansList" :key="index" class="card-item flex row-between bg-white p-20">
<view class="flex">
<u-image :src="item.avatar" border-radius="50%" width="100rpx" height="100rpx" />
<view class="fans-info m-l-20">
<view class="fans-name bold line-1">{{item.nickname}}</view>
<view class="flex lighter m-t-20">
<view v-if="item.mobile" class="m-r-20">{{item.mobile}}</view>
<view>{{item.create_time}}</view>
</view>
</view>
</view>
<view class="flex-col xs flex-none m-l-20">
<view class="msg"><span class="primary">{{item.fans_team}} </span></view>
<view class="m-t-5 msg"><span>{{item.fans_order}} </span></view>
<view class="m-t-5 msg"><span>{{item.fans_money}} </span></view>
</view>
</view>
</view>
</view>
</view>
</mescroll-body>
</template>
<script>
import {
sortType,
} from '@/utils/type';
import {
getUserFans
} from '@/api/user';
import MescrollMixin from "@/components/mescroll-uni/mescroll-mixins.js";
export default {
mixins: [MescrollMixin], // 使mixin
data() {
return {
upOption: {
empty: {
icon: '/static/images/order_null.png',
tip: '暂无相关数据', //
}
},
active: 'all',
sortType: -1,
keyword: "",
fansSort: sortType.NONE,
moneySort: sortType.NONE,
orderSort: sortType.NONE,
fansList: []
};
},
methods: {
onRefresh() {
this.fansList = []
this.mescroll.resetUpScroll();
},
//
upCallback(page) {
const {
fansSort,
moneySort,
orderSort,
active,
keyword,
} = this;
const params = {
type: active,
keyword,
fans: fansSort,
money: moneySort,
order: orderSort,
page_size: page.size,
page_no: page.num,
};
getUserFans(params).then(({
data
}) => {
if (page.num == 1) this.fansList = [];
const curPageData = data.list;
const curPageLen = curPageData.length;
const hasNext = !!data.more;
this.fansList = this.fansList.concat(curPageData);
this.mescroll.endSuccess(curPageLen, hasNext);
}).catch(() => {
this.mescroll.endErr()
})
},
changeTab(val) {
this.active = val
this.onRefresh()
},
//
sortChange(type) {
let {
fansSort,
moneySort,
orderSort
} = this;
this.sortType = parseInt(type)
switch (this.sortType) {
case 0:
//
if (fansSort == sortType.DESC || fansSort == sortType.NONE) {
this.fansSort = sortType.ASC;
this.moneySort = sortType.NONE
this.orderSort = sortType.NONE
} else if (fansSort == sortType.ASC) {
this.fansSort = sortType.DESC;
this.moneySort = sortType.NONE;
this.orderSort = sortType.NONE;
}
break;
case 1:
//
if (moneySort == sortType.DESC || moneySort == sortType.NONE) {
this.moneySort = sortType.ASC;
this.fansSort = sortType.NONE;
this.orderSort = sortType.NONE
} else if (moneySort == sortType.ASC) {
this.moneySort = sortType.DESC;
this.fansSort = sortType.NONE;
this.orderSort = sortType.NONE;
}
break;
case 2:
//
if (orderSort == sortType.DESC || orderSort == sortType.NONE) {
this.orderSort = sortType.ASC;
this.moneySort = sortType.NONE;
this.fansSort = sortType.NONE;
} else if (orderSort == sortType.ASC) {
this.orderSort = sortType.DESC;
this.moneySort = sortType.NONE;
this.fansSort = sortType.NONE;
}
break;
}
this.onRefresh()
}
}
};
</script>
<style lang="scss">
.user-fans {
.header {
.top-bar {
padding: 18rpx 50rpx;
height: 100rpx;
.bar-item {
flex: 1;
padding: 0 30rpx;
height: 58rpx;
&:not(:last-of-type) {
margin-right: 54rpx;
}
}
.item-active {
color: white;
background-color: $-color-primary;
border-radius: 100rpx;
}
}
.sort-bar {
height: 80rpx;
.sort-bar-item {
flex: 1;
.arrow-icon {
transform: scale(0.36);
}
.item-active {
color: $-color-primary;
}
}
}
}
}
.content {
.card-box {
.card-item {
.fans-name {
width: 500rpx;
}
&:not(:last-of-type) {
border-bottom: $-solid-border;
}
}
}
}
</style>

59
bundle/pages/user_group/user_group.vue

@ -0,0 +1,59 @@
<template>
<view class="user-group">
<tabs :active="active" @change="changeShow" :isScroll="false">
<tab v-for="(item, index) in group" :key="index" :name="item.name">
<group-list v-if="item.isShow" :ref="'group' + item.type" :groupType="item.type"></group-list>
</tab>
</tabs>
</view>
</template>
<script>
import {groupType} from "@/utils/type";
export default {
data() {
return {
active: "",
group: [{
name: '全部',
type: groupType.ALL,
isShow: true
}, {
name: '拼团中',
type: groupType.PROGESS,
isShow: false
}, {
name: '拼团成功',
type: groupType.SUCCESS,
isShow: false
}, {
name: '拼团失败',
type: groupType.FAIL,
isShow: false
}]
};
},
onLoad: function(options) {
const {
group
} = this
let type = options.type || groupType.ALL;
let index = group.findIndex(item => item.type == type)
this.changeShow(index);
},
methods: {
changeShow(index) {
if (index != -1) {
this.active = index
this.group[index].isShow = true
}
},
}
};
</script>
<style>
</style>

64
bundle/pages/user_growth/user_growth.vue

@ -0,0 +1,64 @@
<!-- 账户明细 -->
<template>
<view class="user-growth">
<mescroll-body ref="mescrollRef" @init="mescrollInit" @up="upCallback" :up="upOption" :down="downOption" @down="downCallback">
<view class="p-t-20" >
<view class="bg-white" v-for="(item, index) in list" :key="index" >
<record-cell :remark="item.source_type" :date="item.create_time_format" :money="item.change_amount_format" :type="item.change_type" />
</view>
</view>
</mescroll-body>
</view>
</template>
<script>
import MescrollMixin from "@/components/mescroll-uni/mescroll-mixins.js";
import {getAccountLog} from "@/api/user"
export default {
mixins: [MescrollMixin], // 使mixin
data() {
return {
// Tabs
upOption: {
empty: {
icon: '/static/images/order_null.png',
tip: '暂无记录', //
}
},
list: [], // --
};
},
methods: {
//
upCallback(page) {
const pageNum = page.num; // , 1
const pageSize = page.size; // , 10
getAccountLog({
page_size: pageSize,
page_no: pageNum,
source: 3,
}).then(({
data
}) => {
if (page.num == 1) this.list = [];
const curPageData = data.list;
const curPageLen = curPageData.length;
const hasNext = !!data.more;
this.list = this.list.concat(curPageData);
this.mescroll.endSuccess(curPageLen, hasNext);
}).catch(() => {
this.mescroll.endErr()
})
}
},
}
</script>
<style scoped>
</style>

58
bundle/pages/user_order/user_order.vue

@ -0,0 +1,58 @@
<template>
<view class="user-order">
<tabs :current="active" @change="changeShow" bar-width="60" :is-scroll="false">
<tab v-for="(item, index) in order" :key="index" :name="item.name">
<order-list :order-type="item.type" :i="index" :index="active"></order-list>
</tab>
</tabs>
<float-tab></float-tab>
</view>
</template>
<script>
import { orderType } from '@/utils/type';
export default {
data() {
return {
active: -1,
order: [{
name: '全部',
type: orderType.ALL
}, {
name: '待付款',
type: orderType.PAY
}, {
name: '待收货',
type: orderType.DELIVERY
}, {
name: '已完成',
type: orderType.FINISH
}, {
name: '已关闭',
type: orderType.CLOSE
}]
};
},
onLoad (options) {
const{order} = this
let type = this.$Route.query.type || orderType.ALL;
let index = order.findIndex(item => item.type == type)
this.changeShow(index);
},
methods: {
changeShow(index) {
if(index != -1) {
this.$nextTick(() => {
this.active = index
})
}
},
}
};
</script>
<style>
</style>

336
bundle/pages/user_payment/user_payment.vue

@ -0,0 +1,336 @@
<template>
<view>
<view class="user-payment">
<!-- 充值 -->
<form report-submit="true">
<view class="payment bg-white">
<view class="md normal flex" style="padding: 66rpx 66rpx 0">
充值金额
</view>
<view class="input flex">
<text style="font-size: 46rpx"></text>
<input :placeholder="placeholder" type="digit" @focus="setPlaceholder"
@blur="setPlaceholderStatus" :value="number" @input="onInput" />
</view>
<view class="tip muted m-t-20 flex">
提示当前余额为
<text class="primary">{{wallet.user_money || 0}}</text>
</view>
</view>
<button size="lg" class="btn white br60" @tap="rechargeRights">
立即充值
</button>
</form>
<!-- 推荐充值 -->
<view class="fast-payment-container" v-if="rechargeObj.length">
<view class="title bold normal flex">推荐充值</view>
<view class="fast-pay flex flex-wrap">
<view v-for="(item, index) in rechargeObj" :key="index"
class="fast-pay-item bg-white flex-col col-center row-center" @tap="temRecharge(item.id)">
<view class="hot-recharge white" v-if="item.is_recommend">热门充值</view>
<view class="price bold">
<price-format weight="bold" :firstSize="42" :price="item.money"></price-format>
<text class="xxl" style="font-weight: 400"></text>
</view>
<view class="preferential primary xs">{{item.tips}}</view>
</view>
</view>
</view>
</view>
<!-- 充值成功 -->
<u-popup class="pay-popup" v-model="showPopup" closeable round mode="center">
<view class="content bg-white">
<image class="img-icon" src="/static/images/icon_success.png"></image>
<view class="xxl bold m-t-10">充值成功</view>
<view v-if="rechargeInfo.give_growth" class="lg" style="margin-top: 50rpx">恭喜您获得 <text
v-if="rechargeInfo.give_growth">+ <text
class="primary">{{rechargeInfo.give_growth}}</text>成长值</text></view>
<button class="br60 btn" type="primary" size="md" @tap="onShowPopup">好的谢谢</button>
</view>
</u-popup>
<loading-view id="van-toast" v-if="showLoading" backgroundColor="rgba(0, 0, 0, 0)"></loading-view>
<float-tab></float-tab>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | likeshop
// +----------------------------------------------------------------------
// |
// | giteehttps://gitee.com/likeshop_gitee
// | githubhttps://github.com/likeshop-github
// | 访https://www.likeshop.cn
// | 访https://home.likeshop.cn
// | 访http://doc.likeshop.cn
// | likeshop
// | likeshopgiteegithub
// | likeshop
// |
// | likeshop
// +----------------------------------------------------------------------
// | author: likeshop.cn.team
// +----------------------------------------------------------------------
import {
rechargeTemplate,
recharge,
getWallet
} from '@/api/user';
import {
prepay
} from '@/api/app';
import {
wxpay
} from '@/utils/pay';
export default {
data() {
return {
navRecharge: ['账户充值', '佣金转入'],
active: 0,
number: '',
placeholder: "0.00",
rechargeObj: [],
showPopup: false,
rechargeInfo: {},
wallet: {},
showLoading: false
};
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function(options) {
this.rechargeTemplateFun();
this.getWalletFun();
},
onUnload() {
uni.$off('payment')
},
methods: {
onShowPopup() {
this.showPopup = !this.showPopup
},
setPlaceholderStatus: function(event) {
if (event.detail.value.length == 0) {
this.placeholder = '0.00'
}
},
setPlaceholder: function() {
this.placeholder = ''
},
getWalletFun() {
getWallet().then(res => {
if (res.code == 1) {
this.wallet = res.data
}
});
},
rechargeTemplateFun() {
rechargeTemplate().then(res => {
if (res.code == 1) {
this.rechargeObj = res.data
}
});
},
rechargeRights() {
const {
number
} = this;
this.rechargeFun({
money: Number(number)
});
},
temRecharge(id) {
this.rechargeFun({
id
});
},
rechargeFun(obj) {
if (!obj.id && obj.money == 0) {
return this.$toast({
title: '请输入金额'
})
}
this.showLoading = true
recharge(obj).then(({ code, data, msg }) => {
if (code != 1) throw new Error(msg)
this.rechargeInfo = data
uni.$on('payment', params => {
setTimeout(() => {
if (params.result) {
this.$toast({ title: "支付成功" })
this.onShowPopup();
this.getWalletFun();
} else {
this.$toast({ title: "支付失败" })
}
}, 500)
})
uni.navigateTo({
url: `/pages/payment/payment?from=${'recharge'}&order_id=${data.id}`
})
}).catch(err => {
console.log(err)
}).finally(() => {
this.showLoading = false
})
},
checkInputText: function(text) {
var reg = /^(\.*)(\d+)(\.?)(\d{0,2}).*$/g;
if (reg.test(text)) {
//
text = text.replace(reg, '$2$3$4');
} else {
//
text = '';
}
return text; //2
},
onInput(e) {
let number = e.detail.value;
number = this.checkInputText(number);
this.number = number
}
}
};
</script>
<style lang="scss">
.user-payment {
padding: 20rpx 30rpx;
.payment {
text-align: center;
border-radius: 20rpx;
overflow: hidden;
padding-bottom: 74rpx;
.nav {
margin: 20rpx 95rpx 80rpx;
.item {
flex: 1;
.line {
width: 110rpx;
height: 2px;
}
}
}
.line {
width: 110rpx;
height: 2px;
}
.input {
margin-left: 66rpx;
margin-top: 35rpx;
margin-right: 30rpx;
input {
height: 94rpx;
text-align: left;
font-size: 66rpx;
margin-left: 30rpx;
}
border-bottom: $-solid-border;
}
.tip {
margin: 25rpx 66rpx;
}
}
.btn {
background: linear-gradient(79deg, rgba(249, 95, 47, 1) 0%, rgba(255, 44, 60, 1) 100%);
margin: 70rpx 0 30rpx;
}
.fast-payment-container {
margin-top: 72rpx;
.title {
font-size: 38rpx;
line-height: 53rpx;
}
.fast-pay {
margin-top: 40rpx;
.fast-pay-item {
position: relative;
width: 214rpx;
height: 150rpx;
border-radius: 10rpx;
margin-bottom: 16rpx;
&:not(:nth-of-type(3n)) {
margin-right: 24rpx;
}
.hot-recharge {
position: absolute;
padding: 2rpx 10rpx;
height: 30rpx;
background: linear-gradient(180deg, #FF2C3C 0%, #F95F2F 100%);
border-radius: 0 20rpx 0 20rpx;
font-size: 20rpx;
top: 0;
right: 0;
}
.price {
font-size: 42rpx;
line-height: 50rpx;
}
.preferential {
line-height: 32rpx;
}
}
}
}
}
.pay-popup {
.content {
padding: 40rpx 0;
text-align: center;
width: 560rpx;
border-radius: 20rpx;
}
.img-icon {
width: 112rpx;
height: 112rpx;
display: inline-block;
}
.btn {
margin: 80rpx 60rpx 0;
}
}
</style>

612
bundle/pages/user_profile/user_profile.vue

@ -0,0 +1,612 @@
<template>
<view class="user-profile p-t-10">
<view class="content">
<view class="bg-white">
<view class="user-avatar-box flex-col col-center">
<button class="column column-center" hover-class="none" open-type="chooseAvatar"
@chooseavatar="onChooseAvatar" @click="onChooseAvatar">
<image class="user-avatar"
:src="userInfo.avatar1!= '' ? userInfo.avatar:'/static/images/portrait_empty.png'">
</image>
<view class="muted xs">点击修改头像</view>
</button>
</view>
<view class="row-info flex bdb-line" @tap="changeName">
<view class="label md">昵称</view>
<view class="md flex-1">{{ userInfo.nickname }}</view>
<u-icon name="arrow-right" />
</view>
<view class="row-info flex bdb-line" @tap="changeSex">
<view class="label md">性别</view>
<view class="md flex-1" :class="userInfo.sex == 0 ? 'muted' : ''">{{ userInfo.sex }}</view>
<u-icon name="arrow-right" />
</view>
<view class="row-info flex bdb-line">
<view class="label md">手机号</view>
<view
class="md flex-1"
:class="{ 'muted': !userInfo.mobile }"
>{{ userInfo.mobile ? userInfo.mobile : "未绑定" }}</view>
<!-- #ifdef H5 || APP-PLUS -->
<view
class="bd-btn br60 flex row-center"
@tap="showModifyMobile"
>{{ userInfo.mobile ? '更换手机号' : '绑定手机号' }}</view>
<!-- #endif -->
<!-- #ifdef MP-WEIXIN -->
<button
class="bd-btn br60 flex row-center"
size="sm"
open-type="getPhoneNumber"
@getphonenumber="getPhoneNumber"
>{{ userInfo.mobile ? '更换手机号' : '绑定手机号' }}</button>
<!-- #endif -->
</view>
<!-- #ifndef MP-WEIXIN-->
<view class="row-info flex row-between" @tap="showPwdPop">
<view class="label md">登录密码</view>
<view class="flex">
<view class="muted">点击设置</view>
<u-icon name="arrow-right" />
</view>
</view>
<!-- #endif -->
<view class="row-info flex row-between bdb-line mt10" @tap="goToExplain(0)">
<view class="label md">服务协议</view>
<u-icon name="arrow-right" />
</view>
<view class="row-info flex row-between bdb-line" @tap="goToExplain(1)">
<view class="label md">隐私政策</view>
<u-icon name="arrow-right" />
</view>
<view class="row-info flex row-between bdb-line" @tap="goLicense()">
<view class="label md">资质信息</view>
<u-icon name="arrow-right" />
</view>
<view class="row-info flex row-between">
<view class="label md">关于我们</view>
<view>v{{ version }}</view>
</view>
</view>
</view>
<!-- #ifndef MP-WEIXIN -->
<view class="bg-primary white save-btn flex row-center lg" @tap="logout">退出登录</view>
<!-- #endif -->
<!-- 版权信息 -->
<view class="license xs text-center" v-if="appConfig.copyright_info">
<view>{{ appConfig.copyright_info }}</view>
<view>{{ appConfig.icp_number }}</view>
</view>
<!-- #ifndef MP-WEIXIN -->
<u-popup type="center" closeable v-model="showMobile" mode="center" border-radius="14">
<view class="modify-container bg-white" v-show="showMobile">
<view class="title xl text-center">{{ userInfo.mobile ? '更换手机号' : '绑定手机号' }}</view>
<u-field
label="+86"
v-if="userInfo.mobile"
label-width="100"
disabled
v-model="userInfo.mobile"
></u-field>
<u-field label="+86" v-else label-width="140" v-model="new_mobile" placeholder="请输入手机号"></u-field>
<u-field v-model="mobileCode" label="验证码" label-width="140" placeholder="请输入验证码">
<view slot="right" class="primary send-code-btn br60 flex row-center" @tap="sendSmsFun">
<u-verification-code
:keep-running="true"
unique-key="mobile"
ref="uCode"
@change="codeChange"
></u-verification-code>
<view class="sm">{{ codeTips }}</view>
</view>
</u-field>
<u-field
label="新手机号"
v-if="userInfo.mobile"
label-width="140"
placeholder="请输入新的手机号码"
v-model="new_mobile"
></u-field>
<view class="primary m-t-10 xs">{{ userInfo.mobile ? '更改' : '绑定' }}手机号码成功后您的账号将会变更为该设置号码</view>
<view class="btn bg-primary white flex row-center" @tap="changeUserMobileFun">确定</view>
</view>
</u-popup>
<!-- #endif -->
<u-popup v-model="showNickName" :closeable="true" :maskCloseAble="false" mode="center" border-radius="14">
<view class="modify-container bg-white" style="width: 70vw;padding: 24rpx">
<view class="title xl text-center">修改用户名</view>
<form @submit="changeNameConfirm">
<u-form-item label="新昵称" :labelWidth="120">
<input style="height: 60rpx;" class="nr" :value="userInfo.nickname" name="nickname"
type="nickname" placeholder="请输入新的昵称">
</input>
</u-form-item>
<button class="btn bg-primary white flex row-center" form-type="submit">确定</button>
</form>
</view>
</u-popup>
<!-- #ifndef MP-WEIXIN -->
<u-popup v-model="showPwd" closeable mode="center" border-radius="14">
<view class="modify-container bg-white">
<view class="title xl text-center">设置密码</view>
<u-field label="+86" disabled label-width="100" v-model="userInfo.mobile"></u-field>
<u-field v-model="pwdCode" label="验证码" label-width="140" placeholder="请输入验证码">
<view slot="right" class="primary send-code-btn br60 flex row-center" @tap="sendSmsFun">
<u-verification-code
unique-key="password"
:keep-running="true"
ref="uCode"
@change="codeChange"
></u-verification-code>
<view class="sm">{{ codeTips }}</view>
</view>
</u-field>
<u-field label="设置密码" label-width="140" type="password" placeholder="请输入新密码" v-model="pwd"></u-field>
<u-field
label="确认密码"
label-width="140"
type="password"
placeholder="再次输入新密码确认"
v-model="comfirmPwd"
></u-field>
<view class="btn bg-primary white flex row-center" @tap="forgetPwdFun">确定</view>
</view>
</u-popup>
<!-- #endif -->
<u-picker
mode="selector"
v-model="showPicker"
:default-selector="[0]"
:range="sexList"
@confirm="onConfirm"
/>
</view>
</template>
<script>
import {
userLogout,
getUserInfo,
getWxMnpMobile,
setUserInfo,
setWechatInfo,
changeUserMobile
} from "@/api/user";
import {
baseURL,
version
} from '@/config/app';
import {
sendSms,
forgetPwd,
} from '@/api/app'
import {
SMSType
} from '@/utils/type'
import {
mapGetters
} from 'vuex'
import {
uploadFile,
isWeixinClient,
trottle,
} from '@/utils/tools'
import {
getWxCode,
getUserProfile
} from '@/utils/login'
const FieldType = {
NONE: '',
SEX: 'sex',
NICKNAME: 'nickname',
AVATAR: 'avatar',
MOBILE: 'mobile'
}
export default {
name: 'userProfile',
data() {
return {
action: baseURL + '/api/file/formimage',
fileList: [],
userInfo: {},
new_mobile: '',
pwdCode: '',
mobileCode: '',
newNickname: '',
sexList: ['男', '女'],
fieldType: FieldType.NONE,
showPicker: false,
showMobile: false,
showPwd: false,
showNickName: false,
codeTips: '',
canSendSms: true,
pwd: '',
comfirmPwd: '',
smsType: '',
code: '',
version
}
},
methods: {
codeChange(text) {
this.codeTips = text;
},
onSuccess(e) {
console.log(e)
},
uploadImage(path) {
uni.showLoading({
title: '正在上传中...',
mask: true
});
uploadFile(path).then(res => {
uni.hideLoading()
this.setUserInfoFun(res.uri)
}).catch(() => {
uni.hideLoading()
this.$toast({
title: "上传失败"
})
})
},
onChooseAvatar(e) {
this.fieldType = FieldType.AVATAR;
// #ifndef MP-WEIXIN
// uView"-JS"uniuni.navigateTo
uni.$u.route({
// ""
url: '/components/uview-ui/components/u-avatar-cropper/u-avatar-cropper',
//
params: {
// px
destWidth: 300,
// px
rectWidth: 200,
// 'png'"jpg"
fileType: 'jpg',
}
})
// #endif
// #ifdef MP-WEIXIN
if (e.detail.avatarUrl) {
this.uploadImage(e.detail.avatarUrl)
}
// #endif
},
//
async changeNameConfirm(e) {
this.fieldType = FieldType.NICKNAME;
this.newNickname = e.detail.value.nickname
if (!this.newNickname) return this.$toast({
title: '请输入新的昵称'
})
await this.setUserInfoFun(this.newNickname)
this.showNickName = false;
},
//
async getUserProfileFun() {
const {
userInfo
} = await getUserProfile()
const {
avatarUrl,
nickName,
gender
} = userInfo
const {
msg,
code
} = await setWechatInfo({
nickname: nickName,
avatar: avatarUrl,
sex: gender
})
if (code == 1) {
this.$toast({
title: msg
});
this.getUserInfoFun()
}
},
// end
logout() {
//  退
userLogout().then(res => {
if (res.code == 1) {
this.$store.commit("logout");
this.$toast({
title: '退出成功'
})
setTimeout(() => {
this.$Router.replaceAll('/pages/index/index')
}, 500)
}
})
},
goToExplain(value) {
this.$Router.push({
path: '/bundle/pages/server_explan/server_explan',
query: {
type: value
}
})
},
goLicense() {
this.$Router.push({
path: '/bundle/pages/license/license',
query: {
id: ''
}
})
},
//
sendSmsFun(type) {
if (!this.$refs.uCode.canGetCode) return
sendSms({
mobile: this.userInfo.mobile || this.new_mobile,
key: this.smsType
}).then(res => {
if (res.code == 1) {
this.$toast({
title: res.msg
});
this.$refs.uCode.start();
}
})
},
getUserInfoFun() {
getUserInfo().then(res => {
if (res.code == 1) {
this.userInfo = res.data;
}
})
},
//
showModifyMobile() {
this.new_mobile = '';
this.showMobile = true
this.smsType = this.userInfo.mobile ? SMSType.CHANGE_MOBILE : SMSType.BIND
},
changeUserMobileFun() {
if (!this.mobileCode) {
this.$toast({
title: '请输入验证码'
})
return;
}
if (!this.new_mobile) {
this.$toast({
title: '请输入新的手机号码'
})
return;
}
changeUserMobile({
mobile: this.userInfo.mobile,
new_mobile: this.new_mobile,
code: this.mobileCode,
action: this.userInfo.mobile ? 'change' : 'binding'
}).then(res => {
if (res.code == 1) {
this.showMobile = false;
this.$toast({
title: res.msg
})
this.getUserInfoFun();
}
})
},
//
async setUserInfoFun(value) {
const res = await setUserInfo({
field: this.fieldType,
value: value
})
if (res.code == 1) {
this.$toast({
title: res.msg
});
this.getUserInfoFun()
}
},
onConfirm(value) {
this.setUserInfoFun(value[0] + 1);
this.showPicker = false;
},
changeSex(e) {
this.showPicker = true;
this.fieldType = FieldType.SEX;
},
//
showPwdPop() {
if (!this.userInfo.mobile) {
this.$toast({
title: '请绑定手机后再设置密码'
})
return;
}
this.smsType = SMSType.FINDPWD
this.showPwd = true
},
forgetPwdFun() {
let {
pwdCode,
pwd,
comfirmPwd
} = this;
if (!pwdCode) {
this.$toast({
title: '请输入短信验证码'
});
return;
}
if (!pwd) {
this.$toast({
title: '请输入新密码'
});
return;
}
if (!comfirmPwd) {
this.$toast({
title: '再次输入新密码确认'
});
return;
}
if (pwd != comfirmPwd) {
this.$toast({
title: '两次密码输入不一致'
});
return;
}
let data = {
mobile: this.userInfo.mobile,
code: pwdCode,
password: pwd,
repassword: comfirmPwd
};
forgetPwd(data).then(res => {
if (res.code == 1) {
this.showPwd = false;
this.$toast({
title: '设置密码成功'
});
this.getUserInfoFun();
}
})
},
//
changeName() {
this.fieldType = FieldType.NICKNAME;
this.newNickname = '';
this.showNickName = true;
},
//
// #ifdef MP-WEIXIN
async getPhoneNumber(e) {
console.log(e, this.code)
const {
encryptedData,
iv
} = e.detail;
const params = {
code: this.code,
encrypted_data: encryptedData,
iv
}
this.fieldType = FieldType.MOBILE
if (encryptedData) {
const {
data,
code,
msg
} = await getWxMnpMobile(params)
if (code == 1) {
this.$toast({
title: msg
});
// #ifdef MP-WEIXIN
getWxCode().then(res => {
this.code = res
})
// #endif
this.getUserInfoFun()
}
}
},
// #endif
},
onLoad() {
this.getUserInfoFun()
// #ifdef MP-WEIXIN
getWxCode().then(res => {
this.code = res
})
// #endif
uni.$on('uAvatarCropper', path => {
console.log(path)
this.uploadImage(path)
})
this.getUserProfileFun = trottle(this.getUserProfileFun, 500, this)
},
onUnload() {
uni.$off('uAvatarCropper')
},
computed: {
...mapGetters(['token', 'appConfig'])
}
}
</script>
<style lang="scss">
.user-profile {
min-height: calc(100vh - env(safe-area-inset-bottom));
display: flex;
flex-direction: column;
.content {
// flex: 1;
border-top-left-radius: 28rpx;
border-top-right-radius: 28rpx;
.user-avatar-box {
padding: 30rpx;
.user-avatar {
width: 120rpx;
height: 120rpx;
border-radius: 50%;
}
}
.row-info {
padding: 30rpx 20rpx;
.label {
width: 180rpx;
}
.bd-btn {
padding: 8rpx 24rpx;
border: 1px solid $-color-primary;
color: $-color-primary;
}
}
.bdb-line {
border-bottom: 1rpx solid #e5e5e5;
}
}
.license {
margin-top: 80rpx;
color: #a7a7a7;
}
.save-btn {
margin: 40rpx 54rpx 0;
height: 88rpx;
border-radius: 10rpx;
}
.modify-container {
padding: 30rpx;
width: 620rpx;
border-radius: 30rpx;
.title {
padding: 26rpx 0rpx;
}
.btn {
height: 80rpx;
border-radius: 20rpx;
margin: 60rpx 50rpx 0;
}
}
}
</style>

690
bundle/pages/user_spread/user_spread.vue

@ -0,0 +1,690 @@
<template>
<view>
<loading-view v-if="showLoading"></loading-view>
<u-notice-bar :show="showTips" mode="horizontal" :list="list" :font-size="26" :close-icon="true" :speed="100"
@close="showTips=false"></u-notice-bar>
<view class="user-spread">
<view class="header p-t-40 m-b-50">
<view class="user-info flex m-l-30">
<view class="user-avatar">
<u-image width="110rpx" height="110rpx" border-radius="60" :src="userInfo.user.avatar" />
</view>
<view class="user-message m-l-20 white">
<view class="m-b-10">
<view class="xxl bold m-r-20">{{userInfo.user.nickname}}</view>
</view>
<view class="avatar-tag white xxs text-center m-b-10" v-if="distributionInfo.level_name">{{distributionInfo.level_name}}</view>
<view class="xs flex">
上级分销商{{userInfo.leader.nickname ? userInfo.leader.nickname : '无'}}
<view v-if="!userInfo.leader.nickname"
class="br60 white write-btn flex row-center m-l-30 xxs" @tap="showInvitePop">填写
</view>
</view>
</view>
</view>
</view>
<view class="main">
<!-- 填表格 -->
<view v-if="vipState == 0" class="user-apply-box">
<view class="user-apply-vip flex-col col-center">
<view class="user-apply-header flex-col col-center">
<view class="title xxl normal">申请成为分销会员</view>
</view>
<view class="vip-form">
<view class="form-item">
<u-field v-model="realName" :label-width="150" label="真实姓名:" :border-bottom="false"
placeholder="请输入您的真实姓名">
</u-field>
</view>
<view class="form-item">
<u-field v-model="mobile" :label-width="150" label="手机号码:" :border-bottom="false"
placeholder="请输入您的手机号码">
</u-field>
</view>
<view class="form-item" @tap="showRegion=true">
<u-field v-model="region" disabled right-icon="arrow-right" :label-width="150"
label="现住省份:" :border-bottom="false" placeholder="请选择省、市、区">
</u-field>
</view>
<view class="form-item">
<u-field v-model="reason" :label-width="150" type="textarea" label="申请原因:"
placeholder="(必填)" :field-style="{ height: '250rpx'}" />
</view>
</view>
</view>
<button class="apply-btn bg-primary white md m-t-20 flex row-center br60" @tap="formSubmit">
立即申请
</button>
<view class="m-t-20 xxs lighter flex row-center">提交成功后我们将会在1-2个工作日内给您回复</view>
</view>
<!-- 申请状态 -->
<view v-if="vipState==1" class="user-result-box">
<view class="user-result flex-col col-center">
<view class="user-result-header flex-col col-center">
<view class="title xxl normal">申请成为分销会员</view>
</view>
<view class="user-result-content flex-col col-center">
<image class="apply-result-img"
:src="applyObject.status == 2 ? '/static/images/icon_fail.png' : '/static/images/icon_success.png'" />
<view class="m-t-10 nr" style="line-height: 40rpx">{{applyObject.status_str}}</view>
<view class="apply-fail-reason sm"
:style="applyObject == 2 ? 'visibility: none' : 'visibility: hidden'">
{{applyObject.reason}}
</view>
</view>
<view class="user-result-info">
<view class="info-item flex nr">
<view class="label">真实姓名</view>
<view class="info-text ml20">{{applyObject.real_name}}</view>
</view>
<view class="info-item flex nr">
<view class="label">手机号码</view>
<view class="info-text ml20">{{applyObject.mobile}}</view>
</view>
<view class="info-item flex nr">
<view class="label">现住省份</view>
<view class="info-text ml20">{{applyObject.province}} {{applyObject.city}}
{{applyObject.district}}
</view>
</view>
<view class="info-item flex nr">
<view class="label">申请原因</view>
<view class="info-text ml20">{{applyObject.reason ? applyObject.reason : '-'}}</view>
</view>
</view>
</view>
<view :class="'white m-t-20 br60 apply-btn flex row-center md bg-primary'" @tap="reApply">重新申请
</view>
<view class="m-t-20 xxs lighter flex row-center">提交成功后我们将会在1-2个工作日内给您回复</view>
</view>
<!-- 已申请 -->
<view v-if="vipState==2" class="user-vip">
<view class="user-assets-box">
<view class="user-assets-header flex row-between">
<view class="flex nr bold" style="line-height: 80rpx;color: #8F430E;">
可提现佣金
<price-format weight="bold" :first-size="36" :subscript-size="26" :second-size="36"
:price="distributionInfo.able_withdrawal" :color="colorConfig.primary" />
</view>
<navigator hover-class="none" class="primary-btn white flex row-center"
url="/bundle/pages/user_withdraw/user_withdraw">立即提现</navigator>
</view>
<view class="user-assets-content flex flex-wrap">
<view class="user-item flex-col col-center">
<tool-tip v-if="false" class="m-t-20" id="today-profit" content="今日预估收益金额"
style="position: absolute;right: -66rpx;"></tool-tip>
<view class="nr user-assets-name flex" style="color: #8F430E">
今日预估收益
<!-- <u-icon class="ml10" name="question-circle" size="30rpx" color="#D88D5A" /> -->
</view>
<view class="assets m-l-20">
<price-format weight="bold" :first-size="36" :subscript-size="26" :second-size="36"
:price="distributionInfo.today_earnings" :color="colorConfig.primary" />
</view>
</view>
<view class="user-item flex-col col-center">
<view class="nr user-assets-name flex" style="color: #8F430E">
本月预估收益
<!-- <u-icon class="ml10" name="question-circle" size="30rpx" color="#D88D5A" /> -->
</view>
<view class="assets m-l-20">
<price-format weight="bold" :first-size="36" :subscript-size="26" :second-size="36"
:price="distributionInfo.month_earnings" :color="colorConfig.primary" />
</view>
</view>
<view class="user-item flex-col col-center">
<view class="nr user-assets-name flex" style="color: #8F430E">
累计获得收益
<!-- <u-icon class="ml10" name="question-circle" size="30rpx" color="#D88D5A" /> -->
</view>
<view class="assets">
<price-format weight="bold" :first-size="36" :subscript-size="26" :second-size="36"
:price="distributionInfo.history_earnings" :color="colorConfig.primary" />
</view>
</view>
</view>
</view>
<view class="mt20 fans-msg-box flex bg-white md">
<router-link class="flex-1" to="/bundle/pages/user_fans/user_fans">
<view class="my-fans flex row-center normal">
我的粉丝 <view class="primary m-l-10">{{distributionInfo.fans}}</view>
<u-icon class="m-l-10" name="arrow-right" size="28rpx" color="#666" />
</view>
</router-link>
</view>
<view class="my-invite-box m-t-20 bg-white flex-col col-center">
<view class="my-invite-title sm normal">我的邀请码</view>
<view class="flex bold m-t-20" style="font-size: 42rpx;line-height: 30rpx">
{{userInfo.user.distribution_code}}
<view class="invite-copy-btn m-l-10 xxs" @click="onCopy">点击复制</view>
</view>
<!-- <view class="row-center my-promote-banner bg-primary white">我的推广海报</view> -->
</view>
<view class="usual-tools-box bg-white m-t-20">
<view class="usual-tools-header flex lg bold">
常用工具
</view>
<view class="usual-content flex">
<router-link class="usual-item" to="/bundle/pages/user_spread_order/user_spread_order">
<view class="flex-col col-center">
<image src="/bundle/static/icon_fenxiao.png" class="usual-item-img"></image>
<view class="nr normal m-t-20" style="line-height: 40rpx">分销订单</view>
</view>
</router-link>
<router-link class="usual-item" to="/bundle/pages/commission_details/commission_details">
<view class="flex-col col-center">
<image src="/bundle/static/icon_yongjin.png" class="usual-item-img"></image>
<view class="nr normal m-t-20" style="line-height: 40rpx">佣金明细</view>
</view>
</router-link>
<router-link class="usual-item" to="/bundle/pages/monthly_bill/monthly_bill">
<view class="flex-col col-center">
<image src="/bundle/static/icon_zhangdan.png" class="usual-item-img"></image>
<view class="nr normal m-t-20" style="line-height: 40rpx">月度账单</view>
</view>
</router-link>
</view>
</view>
</view>
</view>
<u-popup v-model="showPop" mode="center" closeable border-radius="30">
<view class="inviteform-contain flex-col col-center">
<view class="title xl">填写邀请人</view>
<view class="input-row flex">
<view style="width: 140rpx;">邀请码</view>
<u-input :clearable="false" v-model="inviteCode" placeholder="请输入邀请码" ></u-input>
</view>
<view class="btn bg-primary white flex row-center" @tap="bindSuperiorFun">确定</view>
</view>
</u-popup>
<u-select v-model="showRegion" mode="mutil-column-auto" @confirm="regionChange" :list="regionLists">
</u-select>
</view>
</view>
</template>
<script>
import {
bindSuperior,
applyDistribute,
applyDetail,
getSuperiorInfo,
getDistribution,
veryfiyDistribute
} from "@/api/user";
import area from '@/utils/area'
import {
copy
} from '@/utils/tools'
export default {
data() {
return {
list: ['成为分销会员,推广下级可获得额外收益,推广越多收益越多'],
showTips: true,
showLoading: true,
//
showPop: false,
inviteCode: '',
mobile: '',
realName: '',
reason: '',
region: '',
// id
provinceId: -1,
// id
cityId: -1,
// ID
districtId: -1,
// 0 ==> 1 ==> 2 ==>
vipState: 0,
userInfo: {
user: {},
leader: {}
},
//
applyObject: {},
//
inviteStatus: false,
showRegion: false,
regionLists: area,
distributionInfo: {}
};
},
onLoad(options) {
//
this.getSuperiorInfoFun()
//
this.veryfiyDistributeFun()
},
methods: {
//
async getDistributionFun() {
const {
data,
code
} = await getDistribution()
if (code == 1) {
this.showLoading = false
this.distributionInfo = data
}
},
veryfiyDistributeFun() {
veryfiyDistribute().then(res => {
if (res.code == 10001) {
//
this.vipState = 2
this.getDistributionFun()
} else if (res.code == 20001) {
//
this.vipState = 0;
this.applyDetailFun()
} else if (res.code == 0) {
//
setTimeout(() => {
uni.navigateBack()
}, 500)
}
})
},
//
async applyDetailFun() {
const {
data,
code
} = await applyDetail()
if (code == 1) {
this.showLoading = false
switch (data.status) {
case 0:
//
case 2:
//
this.vipState = 1;
this.applyObject = data
break;
}
}
},
reApply() {
this.vipState = 0
},
regionChange(region) {
this.region = region[0].label + " " + region[1].label + " " + region[2].label
this.provinceId = region[0].value;
this.cityId = region[1].value;
this.districtId = region[2].value
},
async formSubmit() {
let {
provinceId,
cityId,
districtId,
reason,
mobile,
realName,
region
} = this;
if (!realName) {
this.$toast({
title: "请填写真实姓名"
});
return;
}
if (!region.length) {
this.$toast({
title: "请选择省市区"
});
return;
}
let params = {
real_name: realName,
province: provinceId,
city: cityId,
district: districtId,
reason: reason,
mobile
};
const {
data,
code,
msg
} = await applyDistribute(params)
if (code == 1) {
this.$toast({
title: msg
});
this.applyDetailFun();
}
},
//
bindSuperiorFun() {
bindSuperior({
code: this.inviteCode
}).then(res => {
this.$toast({
title: res.msg
})
if (res.code == 1) {
this.showPop = false
this.getSuperiorInfoFun();
}
});
},
showInvitePop() {
this.showPop = true;
},
//
async getSuperiorInfoFun() {
const {
data,
code
} = await getSuperiorInfo()
if (code == 1) {
this.userInfo = data
}
},
onCopy() {
copy(this.userInfo.user.distribution_code)
},
}
};
</script>
<style lang="scss">
.user-spread {
background-image: url(../../static/spread_top_bg.png);
background-repeat: no-repeat;
background-size: 100% auto;
.header {
.user-info {
.user-avatar {
position: relative;
}
.avatar-tag {
display: inline-block;
background-color: #F79C0C;
border: 1rpx solid #FFFFFF;
border-radius: 100rpx;
line-height: 32rpx;
padding: 0 10rpx;
}
.user-message {
.write-btn {
height: 42rpx;
width: 100rpx;
background-color: #FF838D;
}
}
}
}
.main {
padding: 0 20rpx;
.user-vip {
.user-assets-box {
background-color: #fff;
border-radius: 20rpx;
padding: 10rpx 20rpx 22rpx;
background: linear-gradient(90deg, #FBEFDB 0%, #FED09E 100%);
.user-assets-header {
border-bottom: 1rpx dashed #8F430E;
padding-bottom: 4rpx;
.primary-btn {
height: 54rpx;
border-radius: 120rpx;
width: 144rpx;
background: linear-gradient(180deg, #FF3067 0%, #FF2C3C 100%);
}
}
.user-assets-content {
margin-top: 30rpx;
.user-item {
flex: 1;
position: relative;
.user-assets-name {
text-align: left;
align-self: flex-start;
}
.assets {
margin-top: 14rpx;
text-align: left;
align-self: flex-start;
}
}
}
}
.fans-msg-box {
border-radius: 10rpx;
line-height: 42rpx;
.my-fans {
height: 120rpx;
}
.line {
width: 3rpx;
height: 60rpx;
background-color: #E5E5E5;
}
.invite-fans {
height: 120rpx;
}
}
.my-invite-box {
padding: 26rpx 0 57rpx;
border-radius: 10rpx;
.invite-copy-btn {
line-height: 30rpx;
padding: 10rpx;
background: linear-gradient(90deg, #FEE4B4 0%, #FBCB96 100%);
color: #8F430E;
border-radius: 4rpx;
}
.my-promote-banner {
margin-top: 30rpx;
height: 148rpx;
width: 542rpx;
border-radius: 10rpx;
}
}
.usual-tools-box {
border-radius: 10rpx;
padding: 0 25rpx;
.usual-tools-header {
height: 100rpx;
line-height: 44rpx;
border-bottom: $-solid-border;
}
.usual-content {
padding: 40rpx 0;
.usual-item {
width: 25%;
.usual-item-img {
width: 56rpx;
height: 56rpx;
flex: none;
}
}
}
}
}
.user-apply-box {
.user-apply-vip {
background-color: white;
padding: 40rpx 0 0rpx;
border-radius: 20rpx;
.title {
line-height: 30rpx;
font-weight: bold;
}
.explain {
margin-top: 20rpx;
image {
width: 24rpx;
height: 24rpx;
flex: none;
}
span {
font-size: 20rpx;
line-height: 30rpx;
}
}
.vip-form {
width: 100%;
margin-top: 60rpx;
.form-item {
border: $-solid-border;
margin: 0 30rpx 30rpx;
}
}
}
.apply-btn {
line-height: 30rpx;
height: 82rpx;
}
}
.user-result-box {
.user-result {
background-color: white;
padding: 36rpx 14rpx 50rpx;
border-radius: 20rpx;
.user-result-header {
.title {
line-height: 30rpx;
font-weight: bold;
}
}
.user-result-content {
padding: 60rpx 0 22rpx;
width: 100%;
border-bottom: $-solid-border;
.apply-result-img {
width: 100rpx;
height: 100rpx;
}
}
.user-result-info {
margin-top: 42rpx;
width: 100%;
.info-item {
margin-left: 60rpx;
margin-bottom: 28rpx;
line-height: 30rpx;
.label {
width: 140rpx;
}
}
}
}
.apply-btn {
line-height: 30rpx;
height: 82rpx;
}
.bg-gray {
background-color: #CCCCCC;
}
}
}
}
.main .user-apply-box .apply-btn {
line-height: 30rpx;
height: 82rpx;
}
.main .user-result-box .user-result-content .apply-fail-reason {
color: $-color-primary;
line-height: 36rpx;
margin-top: 10rpx;
}
/* 弹窗 */
.inviteform-contain {
padding-left: 30rpx;
padding-right: 30rpx;
padding-bottom: 30rpx;
width: 580rpx;
border-radius: 6rpx;
background-color: $-color-white;
}
.inviteform-contain .title {
padding: 26rpx 0rpx;
}
.inviteform-contain .modify-row {
padding: 32rpx 0px;
width: 100%;
border-bottom: 1rpx solid #E5E5E5;
}
.inviteform-contain .btn {
height: 80rpx;
padding: 0 180rpx;
border-radius: 10rpx;
margin-top: 60rpx;
}
</style>

48
bundle/pages/user_spread_order/user_spread_order.vue

@ -0,0 +1,48 @@
<template>
<view class="user-promote-order">
<tabs :current="active" @change="onChange" bar-width="60" :is-scroll="false">
<tab v-for="(item, index) in order" :key="index" :name="item.name">
<spread-order :type="item.type" :i="index" :index="active"></spread-order>
</tab>
</tabs>
</view>
</template>
<script>
import { distributionOrder } from "@/utils/type";
export default {
data() {
return {
order: [{
name: "全部",
type: distributionOrder.ALL,
}, {
name: "待返佣",
type: distributionOrder.WAIT_RETURN,
}, {
name: "已结算",
type: distributionOrder.HANDLED,
}, {
name: "已失效",
type: distributionOrder.INVALED,
}],
active: distributionOrder.ALL
};
},
onLoad: function (options) {
},
methods: {
onChange(index) {
this.active = index
},
}
};
</script>
<style>
</style>

253
bundle/pages/user_vip/user_vip.vue

@ -0,0 +1,253 @@
<template>
<view>
<view class="user-vip">
<view class="header">
<view class="user-vip-info flex">
<u-image width="110rpx" height="110rpx" border-radius="50%" :src="userInfo.avatar"></u-image>
<view class="m-l-20">
<view class="user-text white xxl flex">{{userInfo.nickname}}</view>
<view class="flex">
<view class="user-level white xs flex row-center m-t-10">当前等级{{userInfo.level_name || "无"}}</view>
</view>
</view>
</view>
</view>
<view class="content m-t-50">
<view class="vip-swiper-container">
<swiper class="swiper" style="height: 360rpx" previous-margin="30rpx"
:current="currentIndex" @change="bindchange">
<swiper-item v-for="(item, index) in levelList" :key="index">
<view class="vip-card-item" :style="'background-image: url(' + item.background_image + ');'">
<view class="flex row-between">
<view class="flex grade white sm">
{{item.lock_desc}}
<!-- <view v-if="item.current_level_status == 1" class="flex grade white sm">当前等级</view>
<view v-else-if="item.current_level_status == -1" class="flex white sm ml20">未解锁</view>
<view v-else-if="item.current_level_status == 0" class="flex white sm ml20">已解锁</view> -->
</view>
<image class="grade-icon m-r-34" :src="item.image"></image>
</view>
<view class="flex row-between vip-name white">
<view class="bold">{{item.name}}</view>
<!-- <view class="sm">{{item.tips2}}</view> -->
</view>
<view class="flex row-center m-l-30 m-r-30" v-if="item.diff_growth_percent">
<view class="vip-progress bg-white flex">
<view class="vip-progress-bar" :style="'width: ' + (item.diff_growth_percent*100) + '%'"></view>
</view>
</view>
<view class="flex row-between m-t-30" style="padding: 0 30rpx">
<view class="sm white" style="line-height: 36rpx" v-if="item.current_level_status == 0">
{{item.tips1}}
</view>
<router-link to="/bundle/pages/user_growth/user_growth" class="flex" v-else>
<view class="sm white" style="line-height: 36rpx">
<!-- {{item.current_level_status == 0 ? '当前高于该等级' : item.current_growth_tips}} -->
{{item.tips1}} <u-icon name="arrow-right"></u-icon>
</view>
</router-link>
<view class="white">{{item.tips2}}</view>
</view>
</view>
</swiper-item>
</swiper>
</view>
<view class="vip-grade-rule">
<view class="title flex">
<view class="line br60"></view>
<view class="xl m-l-20 bold">说明</view>
</view>
<view class="p-t-20">
<text class="rule-content column lighter">
{{growthRule}}
</text>
</view>
</view>
<!-- <view class="vip-rights">
<view class="title flex">
<view class="line br60"></view>
<view class="xl ml20 bold">会员权益</view>
</view>
<view class="rights-list flex">
<view v-for="(item, index) in privilegeList" :key="index" class="rights-item column-center">
<image class="mb10" :src="item.image"></image>
<view class="sm">{{item.name}}</view>
</view>
</view>
</view> -->
</view>
</view>
<loading-view v-if="!userInfo.nickname"></loading-view>
</view>
</template>
<script>
import {
getLevelList
} from '@/api/user';
export default {
data() {
return {
userInfo: {},
currentIndex: 0,
levelList: [],
growthRule: "",
privilegeList: []
};
},
onLoad() {
this.getLevelListFun();
},
methods: {
bindchange(e) {
let {
current
} = e.detail;
let currentLevel = this.levelList[current];
this.currentIndex = current
},
getLevelListFun() {
getLevelList().then(res => {
const {
code,
data
} = res;
if (code != 1) return;
const {
user,
level_intro,
level
} = data;
let index = level.findIndex(item => item.current_level_status == 1);
if (index == -1) index = 0;
this.userInfo = user
this.growthRule = level_intro
this.levelList = level
this.currentIndex = index
});
},
}
};
</script>
<style lang="scss">
page {
background-color: #fff;
background-image: url(../../static/vip_grade_bg.png);
background-size: 100% auto;
background-repeat: no-repeat;
.user-vip {
.header {
padding-top: 40rpx;
.user-vip-info {
padding-left: 30rpx;
.user-level {
border: 1px solid white;
border-radius: 100rpx;
padding: 4rpx 20rpx;
line-height: 30rpx;
}
.user-text {
line-height: 50rpx;
font-weight: bold;
}
}
}
.content {
.vip-card-item {
height: 360rpx;
width: 690rpx;
position: relative;
background-size: 100% 100%;
.grade {
line-height: 36rpx;
background-color: rgba(0, 0, 0, 0.5);
border-top-right-radius: 100rpx;
border-bottom-right-radius: 100rpx;
height: 50rpx;
padding: 0 28rpx;
}
.user-grade {
line-height: 36rpx;
margin-left: 30rpx;
}
.grade-icon {
width: 160rpx;
height: 145rpx;
}
.vip-name {
padding: 10rpx 30rpx;
font-size: 46rpx;
text-align: center;
align-items: flex-end;
margin-bottom: 30rpx;
margin-top: -20rpx;
}
.vip-progress {
height: 8rpx;
border-radius: 8rpx;
width: 100%;
overflow: hidden;
.vip-progress-bar {
background-color: #f8d07c;
height: 100%;
}
}
}
.vip-grade-rule {
margin: 24rpx 40rpx;
.title {
.line {
width: 8rpx;
height: 34rpx;
background-color: #f79c0c;
}
}
}
.vip-rights {
margin: 24rpx 40rpx;
.title {
padding: 28rpx 0;
.line {
width: 8rpx;
height: 34rpx;
background-color: #f79c0c;
}
}
.rights-item {
width: 25%;
padding-bottom: 30rpx;
image {
width: 82rpx;
height: 82rpx;
}
}
}
}
}
}
</style>

212
bundle/pages/user_wallet/user_wallet.vue

@ -0,0 +1,212 @@
<template>
<view class="user-wallet">
<view class="contain bg-white m-b-20">
<!-- 资产总计 -->
<view class="header">
<view class="white m-b-20">
<view class="xs">总资产()</view>
<view style="font-size: 76rpx">{{wallet.user_money || '0.00'}}</view>
</view>
<view class="money white flex">
<view class="item">
<view class="xs">累计充值()</view>
<view style="font-size: 38rpx">{{wallet.total_recharge_amount || '0.00'}}</view>
</view>
<view class="item">
<view class="xs">累计消费()</view>
<view style="font-size: 38rpx">{{wallet.total_order_amount || '0.00'}}</view>
</view>
<template v-if="wallet.open_racharge">
<router-link style="height: 58rpx;" class="flex primary bg-white br60 btn" size="xs"
to="/bundle/pages/user_payment/user_payment">充值</router-link>
</template>
</view>
</view>
<!-- 资金明细 -->
<view class="nav flex">
<!-- <router-link class="nav-item">
<view class="flex-col col-center">
<image class="icon" src="../../static/icon_yezz.png"></image>
<view class="m-t-10 sm">余额转账</view>
</view>
</router-link> -->
<router-link class="nav-item" to="/bundle/pages/user_bill/user_bill">
<view class="flex-col col-center">
<image class="icon" src="../../static/icon_zhmx.png"></image>
<view class="m-t-10 sm">账户明细</view>
</view>
</router-link>
<!-- <router-link class="nav-item">
<view class="flex-col col-center">
<image class="icon" src="../../static/icon_zzjl.png"></image>
<view class="m-t-10 sm">转账记录</view>
</view>
</router-link> -->
<router-link class="nav-item" to="/bundle/pages/recharge_record/recharge_record">
<view class="flex-col col-center">
<image class="icon" src="../../static/icon_czjl.png"></image>
<view class="m-t-10 sm">充值记录</view>
</view>
</router-link>
</view>
<!-- 热门活动 -->
<view class="activity">
<view class="activity-title xl flex">
<view class="m-r-20 bg-primary" style="width: 6rpx;height: 30rpx;"></view>
<text>热门活动</text>
</view>
<block v-for="(item, index) in activityList" :key="item.title">
<view class="activity-item flex row-between" :style="{backgroundColor: item.background}">
<view>
<view class="xl normal" style="font-weight: 500;">{{ item.title }}</view>
<view class="muted sm m-t-10">{{ item.slogan }}</view>
<router-link style="display: inline-block;" :to="item.href">
<view :style="{backgroundColor: item.buttonColor}"
class="br60 white join-btn flex row-center">立即参与</view>
</router-link>
</view>
<image style="width:274rpx; height: 210rpx;" :src="item.image"></image>
</view>
</block>
</view>
</view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | likeshop
// +----------------------------------------------------------------------
// |
// | giteehttps://gitee.com/likeshop_gitee
// | githubhttps://github.com/likeshop-github
// | 访https://www.likeshop.cn
// | 访https://home.likeshop.cn
// | 访http://doc.likeshop.cn
// | likeshop
// | likeshopgiteegithub
// | likeshop
// |
// | likeshop
// +----------------------------------------------------------------------
// | author: likeshop.cn.team
// +----------------------------------------------------------------------
import {
getWallet
} from '@/api/user';
export default {
data() {
return {
wallet: {},
//
activityList: [
{
title: "领取优惠券",
slogan: "每日优惠券抢不停",
button: "立即抢购",
buttonColor: "#FC597A",
href: "/pages/get_coupon/get_coupon",
image: "/bundle/static/img_activity_coupon.png",
background: "rgba(252, 89, 122, 0.1)"
},
{
title: "超值商品 限时秒杀",
slogan: "最新商品秒杀中",
button: "立即抢购",
buttonColor: "#FF2C3C",
href: "/bundle/pages/goods_seckill/goods_seckill",
image: "/bundle/static/img_activity_seckill.png",
background: "rgba(236, 71, 37, 0.1)"
}
]
};
},
onShow() {
this.getWalletFun();
},
methods: {
getWalletFun() {
getWallet().then(res => {
if (res.code == 1) {
this.wallet = res.data
}
});
},
}
};
</script>
<style lang="scss">
.user-wallet {
.contain {
padding: 20rpx 30rpx 36rpx;
.header {
position: relative;
background: linear-gradient(180deg, rgba(255, 44, 60, 1) 0%, rgba(255, 49, 106, 1) 100%);
border-radius: 20rpx;
height: 320rpx;
padding: 50rpx 30rpx 30rpx;
box-sizing: border-box;
.money {
.item {
flex: 1;
}
}
.btn {
position: absolute;
right: 30rpx;
top: 50rpx;
padding: 0 51rpx;
}
}
.nav {
border-bottom: $-solid-border;
.nav-item {
width: 25%;
padding: 40rpx 0;
.icon {
width: 52rpx;
height: 52rpx;
}
}
}
}
}
.activity {
padding: 40rpx 0rpx;
.activity-title {
font-weight: bold;
}
.activity-item {
padding: 15rpx 40rpx;
// box-shadow: 0px 0rpx 20rpx rgba(0, 0, 0, 0.16);
margin-top: 34rpx;
.join-btn {
height: 52rpx;
width: 156rpx;
margin-top: 24rpx;
}
}
}
</style>

250
bundle/pages/user_withdraw/user_withdraw.vue

@ -0,0 +1,250 @@
<!-- 提现 -->
<template>
<view class="user-withdraw">
<!-- Tabs -->
<view class="withdraw-tabs">
<u-tabs :list="tabsList" :is-scroll="true" :current="currentTab" :bold="true" height="100"
font-size="30rpx" active-color="#333333" inactive-color="#666666" :bar-style="styleTabsBarStyle"
@change="changeTab" />
</view>
<!-- 微信钱包 -->
<view v-if="currentValue == 3" class="withdraw-wechat m-t-20 bg-white">
<!-- Account -->
<u-field label-width="160" label="微信账号" v-model="form.account" placeholder="请输入微信账号" />
<!-- Name -->
<u-field label-width="160" label="真实姓名" v-model="form.real_name" placeholder="请输入真实姓名" />
<!-- Remark -->
<u-field label-width="160" label="备注" v-model="form.remark" placeholder="(选填)" />
<!-- 上传图片 -->
<view class="flex-col m-t-20">
<u-upload ref="uUpload" :header="{token: $store.getters.token}" :auto-upload="true" :show-progress="false" max-count="1" width="142" height="142" :custom-btn="true" :action="action" @on-success="onSuccess" @on-remove="onRemove" >
<view slot="addBtn" class="flex-col col-center row-center">
<view class="upload-image flex-col col-center row-center" >
<u-icon name="/bundle/static/icon_camera_line.png" width="54" />
</view>
<view class="xs m-t-10">微信收款码</view>
</view>
</u-upload>
</view>
</view>
<!-- 支付宝 -->
<view v-else-if="currentValue == 4" class="withdraw-alipay m-t-20 bg-white">
<!-- Account -->
<u-field label-width="160" label="支付宝账号" v-model="form.account" placeholder="请输入支付宝账号" />
<!-- Name -->
<u-field label-width="160" label="真实姓名" v-model="form.real_name" placeholder="请输入真实姓名" />
<!-- Remark -->
<u-field label-width="160" label="备注" v-model="form.remark" placeholder="(选填)" />
<!-- 上传图片 -->
<view class="flex-col m-t-20">
<u-upload ref="uUpload" :header="{token: $store.getters.token}" :auto-upload="true" :show-progress="false" max-count="1" width="142" height="142" :custom-btn="true" :action="action" @on-success="onSuccess" @on-remove="onRemove" >
<view slot="addBtn" class="flex-col col-center row-center">
<view class="upload-image flex-col col-center row-center" >
<u-icon name="/bundle/static/icon_camera_line.png" width="54" />
</view>
<view class="xs m-t-10">支付宝收款码</view>
</view>
</u-upload>
</view>
</view>
<!-- 银行卡 -->
<view v-else-if="currentValue == 5" class="withdraw-alipay m-t-20 bg-white">
<!-- Account -->
<u-field label-width="160" label="银行卡账号" v-model="form.account" placeholder="请输入银行卡账号" />
<!-- Name -->
<u-field label-width="160" label="持卡人姓名" v-model="form.real_name" placeholder="请输入持卡人姓名" />
<!-- Name -->
<u-field label-width="160" label="提现银行" v-model="form.bank" placeholder="请输入银行名称" />
<!-- Remark -->
<u-field label-width="160" label="银行支行" v-model="form.subbank" placeholder="如:金湾支行" />
<!-- Remark -->
<u-field label-width="160" label="备注" v-model="form.remark" placeholder="(选填)" />
</view>
<!-- 提现金额 -->
<view class="withdraw-money-wrap m-t-20 bg-white">
<view class="flex withdraw-money p-b-20">
<view class="flex flex-1">
<text class="font-size-46 m-r-10 normal">¥</text>
<u-input v-model="form.money" placeholder="0.00" :custom-style="{
'font-size': '66rpx'
}" />
</view>
<view class="flex-col flex-1 text-right">
<text class="xs primary" @tap="form.money=widthDrawConfig.able_withdraw">全部提现</text>
<text class="xs muted m-t-10">可提现金额 ¥ {{widthDrawConfig.able_withdraw}}</text>
</view>
</view>
<view class="muted xs m-t-30" v-if="widthDrawConfig.poundage_percent && currentValue != 1">提示提现需扣除服务费{{widthDrawConfig.poundage_percent}}%</view>
</view>
<!-- 确认提交 -->
<button class="withdraw-submit m-t-30 white br60" @tap="onSubmit" size="lg">确认提交</button>
<!-- 提现记录 -->
<router-link to="/bundle/pages/user_withdraw_code/user_withdraw_code">
<view class="withdraw-log m-t-40 text-center muted">提现记录</view>
</router-link>
</view>
</template>
<script>
import {
applyWithdraw,
getWithdrawConfig
} from "@/api/user";
import {
trottle
} from "@/utils/tools";
import {
baseURL
} from '@/config/app';
export default {
data() {
return {
action: baseURL + '/api/file/formimage',
currentTab: 0, // Tabs
// Tabs
tabsList: [],
// Tabs
styleTabsBarStyle: {
bottom: '12rpx',
width: '50rpx',
height: '6rpx',
background: 'green',
borderRadius: '50px',
backgroundImage: 'linear-gradient(to right, \#F79C0C, \#FF2C3C)'
},
//
form: {
money: '', //
account: '', //
real_name: '', //
money_qr_code: '', //
bank: '', //
subbank: '', //
remark: '', //
},
widthDrawConfig: {}
}
},
onLoad() {
this.getWithdrawConfigFun();
this.onSubmit = trottle(this.onSubmit, 1000, this)
},
methods: {
// Tabs
changeTab(index) {
this.currentTab = index;
this.form = {
money: '',
account: '',
real_name: '',
money_qr_code: '',
remark: '',
bank: '',
subbank: ''
};
},
async getWithdrawConfigFun() {
const {
code,
data
} = await getWithdrawConfig()
if (code == 1) {
this.widthDrawConfig = data
this.tabsList = data.type
}
},
//
onSubmit() {
const data = {
...this.form
}
data.type = this.currentValue
if (!data.money) {
this.$toast({
title: '请输入提现金额'
});
return;
}
applyWithdraw(data).then(res => {
if (res.code == 1) {
this.$toast({
title: '提交成功'
}, {
tab: 2,
url: '/bundle/pages/widthdraw_result/widthdraw_result?id=' + res.data.id
});
}
});
},
onSuccess(e) {
console.log(e)
this.form.money_qr_code = e.data.base_uri
},
onRemove(index) {
this.form.money_qr_code = ""
},
},
computed: {
currentValue(val) {
const {currentTab, tabsList} = this
return tabsList[currentTab] ? tabsList[currentTab].value : ''
}
}
}
</script>
<style lang="scss" scoped>
.user-withdraw {
padding: 20rpx 30rpx;
.withdraw-tabs {
border-radius: 10px;
overflow: hidden;
}
.withdraw-money-wrap {
padding: 50rpx 66rpx;
border-radius: 10px;
.withdraw-money {
border-bottom: $-solid-border;
}
}
.withdraw-wechat,
.withdraw-alipay {
padding: 0 36rpx 20rpx;
border-radius: 10px;
}
.upload-image {
width: 142rpx;
height: 142rpx;
border: 2rpx dashed #CCCCCC;
border-radius: 5px;
}
.withdraw-submit {
background: linear-gradient(11deg, #F95F2F, #FF2C3C);
}
::v-deep .u-field {
padding: 26rpx 0;
}
}
</style>

97
bundle/pages/user_withdraw_code/user_withdraw_code.vue

@ -0,0 +1,97 @@
<!-- 账户明细 -->
<template>
<view class="user-withdraw-code">
<mescroll-body ref="mescrollRef" @init="mescrollInit" @up="upCallback" :up="upOption"
@down="downCallback">
<view class="list p-t-20">
<view class="item bg-white" v-for="(item,index) in list" :key="index">
<router-link :to="{path: '/bundle/pages/widthdraw_result/widthdraw_result', query: {id: item.id}}">
<view class="flex row-between">
<view class="md ">{{item.desc}}</view>
<view>
<text class="xxl">-{{item.money}}</text>
</view>
</view>
<view class="flex row-between">
<view class="xs muted">{{item.create_time}}</view>
<view class="xs" :style="{color: [styleWithdrawStatus(item.status)]}">{{item.status_text}}</view>
</view>
<view class="m-t-10 sm primary" v-if="item.description && item.status == 4">
{{item.description}}
</view>
</router-link>
</view>
</view>
</mescroll-body>
</view>
</template>
<script>
import MescrollMixin from "@/components/mescroll-uni/mescroll-mixins.js";
import {
getWithdrawRecords
} from "@/api/user"
export default {
mixins: [MescrollMixin], // 使mixin
data() {
return {
upOption: {
empty: {
icon: '/static/images/order_null.png',
tip: '暂无记录', //
}
},
list: [], // --
};
},
methods: {
//
upCallback(page) {
const pageNum = page.num; // , 1
const pageSize = page.size; // , 10
getWithdrawRecords({
page_size: pageSize,
page_no: pageNum,
}).then(({
data
}) => {
if (page.num == 1) this.list = [];
const curPageData = data.list;
const curPageLen = curPageData.length;
const hasNext = !!data.more;
this.list = this.list.concat(curPageData);
this.mescroll.endSuccess(curPageLen, hasNext);
}).catch(() => {
this.mescroll.endErr()
})
},
styleWithdrawStatus(status) {
switch(status) {
case 1: return '#0CC21E';
case 2: return '#666666';
case 3: return '#FF2C3C';
case 4: return '#FF2C3C';
}
}
},
onLoad(options) {
}
}
</script>
<style lang="scss" scoped>
.user-withdraw-code {
.item {
padding: 22rpx 30rpx;
&:not(:last-of-type) {
border-bottom: $-solid-border;
}
}
}
</style>

127
bundle/pages/widthdraw_result/widthdraw_result.vue

@ -0,0 +1,127 @@
<template>
<view class="widthdraw-result">
<view class="contain bg-white">
<view class="header flex-col col-center">
<view>
<image class="tips-icon" :src="getTipsIcon(widthdrawInfo.status)"></image>
</view>
<view class="xl m-t-20 bold">{{widthdrawInfo.statusDesc}}</view>
<view class="flex-col col-center">
<price-format :price="widthdrawInfo.money" :color="colorConfig.primary" subscript-size="30" first-size="46" second-size="46" weight="bold" />
</view>
</view>
<view class="info">
<view class="flex row-between m-t-20">
<view>流水号</view>
<view>
{{widthdrawInfo.sn}}
</view>
</view>
<view class="flex row-between m-t-20">
<view>提交时间</view>
<view>{{widthdrawInfo.create_time}}</view>
</view>
<view class="flex row-between m-t-20">
<view>提现至</view>
<view>{{widthdrawInfo.typeDesc}}</view>
</view>
<view class="flex row-between m-t-20">
<view>服务费</view>
<view>
<price-format :price="widthdrawInfo.poundage"></price-format>
</view>
</view>
<view class="flex row-between m-t-20">
<view>实际到账</view>
<view>
<price-format :price="widthdrawInfo.left_money"></price-format>
</view>
</view>
</view>
<view class="line m-t-40"></view>
<view class="m-t-40 flex-col row-center">
<router-link to="/bundle/pages/user_withdraw_code/user_withdraw_code">
<button type="primary" size="lg" class="br60">查看历史提现记录</button>
</router-link>
<router-link navType="pushTab" to="/pages/index/index">
<button size="lg" class="br60 plain primary m-t-30">返回首页</button>
</router-link>
</view>
</view>
<view class="muted m-t-20 xs text-center">* 审核通过后约72小时内到账请留意账户明细</view>
</view>
</view>
</template>
<script>
import { getWithdrawDetail } from '@/api/user';
export default {
data() {
return {
widthdrawInfo: {}
};
},
onLoad () {
this.id = this.$Route.query.id
this.getWithdrawDetailFun();
},
methods: {
getWithdrawDetailFun() {
getWithdrawDetail({
id: this.id
}).then(res => {
if (res.code == 1) {
this.widthdrawInfo = res.data
}
});
},
getTipsIcon(status) {
// status 1-2-3-4-
switch(status) {
case 1:
case 2: return '/static/images/icon_wait.png'
case 3: return '/static/images/icon_success.png'
case 4: return '/static/images/icon_fail.png'
}
}
}
};
</script>
<style lang="scss">
.widthdraw-result {
.contain {
border-radius: 10rpx;
padding: 0 30rpx 40rpx;
position: relative;
margin: 78rpx 20rpx 0;
.tips-icon {
width: 112rpx;
height: 112rpx;
}
.header {
position: absolute;
left: 50%;
transform: translateX(-50%);
top: -50rpx;
}
.info {
padding-top: 180rpx;
}
.line {
border-top: $-solid-border;
}
.plain {
border: 1px solid $-color-primary;
}
}
}
</style>

BIN
bundle/static/No.0.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
bundle/static/activity_detail_bg.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

BIN
bundle/static/bg_sgin.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

BIN
bundle/static/contact_official_bg.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

BIN
bundle/static/icon_camera_line.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 520 B

BIN
bundle/static/icon_czjl.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 619 B

BIN
bundle/static/icon_fenxiao.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
bundle/static/icon_integral.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
bundle/static/icon_invite.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
bundle/static/icon_jifen.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
bundle/static/icon_wait.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
bundle/static/icon_yezz.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 691 B

BIN
bundle/static/icon_yongjin.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
bundle/static/icon_zhangdan.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
bundle/static/icon_zhmx.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 B

BIN
bundle/static/icon_zzjl.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 760 B

BIN
bundle/static/img_activity_coupon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
bundle/static/img_activity_jifen.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
bundle/static/img_activity_pintuan.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
bundle/static/img_activity_seckill.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
bundle/static/invoice_success.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
bundle/static/invoice_wait.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
bundle/static/jifen_icon_data.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 B

BIN
bundle/static/jifen_icon_help.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 653 B

BIN
bundle/static/jifen_icon_select.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
bundle/static/jifen_popBg.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
bundle/static/logistics_address.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
bundle/static/logistics_address_gray.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 848 B

BIN
bundle/static/logistics_delivered.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
bundle/static/logistics_pay.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
bundle/static/logistics_success.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
bundle/static/logistics_transit.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

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

Loading…
Cancel
Save