index.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611
  1. <!-- 菜单悬浮的原理: 通过给菜单添加position:sticky实现, 用法超简单, 仅APP端的低端机不兼容 https://caniuse.com/#feat=css-sticky -->
  2. <template>
  3. <view class="order-page">
  4. <!-- 对于mescroll-body: 需设置:sticky="true", 此应避免在mescroll-body标签前面加其他非定位的元素, 否则下拉区域会被挤出, 无法会隐藏.-->
  5. <!-- 对于mescroll-uni: 则无需设置:sticky="true", 无其他限制和要求 -->
  6. <!-- sticky吸顶悬浮的菜单, 父元素必须是 mescroll -->
  7. <view class="sticky-tabs">
  8. <view class=" u-flex padding bg">
  9. <view class="u-m-r-10">
  10. <image :src="avatar" style="width: 100rpx;height: 100rpx;border-radius: 100rpx;"
  11. @click="goNav('/pages/my/userinfo')"></image>
  12. </view>
  13. <view class="u-flex-1 u-m-l-10 " v-if="!isLogin">
  14. <view class="u-font-18 text-bold">
  15. <view class="flex align-center">
  16. <view class="margin-left-sm ">{{userName}}</view>
  17. <view class="labe" @tap="stateSave">
  18. <text></text>
  19. <view v-if="isTrue">已上线</view>
  20. <view v-if="!isTrue">已下线</view>
  21. </view>
  22. </view>
  23. <view class="flex margin-left-sm margin-top-xs" style="font-size: 22rpx;font-weight: 500;">
  24. <view v-if="renzheng == 0" @click.stop="goNav('/my/renzheng/index?classify='+1)">
  25. 暂未实名认证
  26. </view>
  27. <view v-if="renzheng == 1" @click.stop="goNav('/my/renzheng/index?classify='+1)">
  28. 实名审核中
  29. </view>
  30. <view v-if="renzheng == 2">
  31. 已实名认证
  32. </view>
  33. <view v-if="renzheng == 3" @click.stop="goNav('/my/renzheng/index?classify='+1)">
  34. 实名已拒绝
  35. </view>
  36. </view>
  37. </view>
  38. </view>
  39. <view v-else class="text-xl u-p-l-20 text-bold" @click="goLogin('/pages/public/login')">
  40. 登录
  41. </view>
  42. </view>
  43. <!-- <view class="flex align-center padding-left bg">
  44. <image src="../../static/images/data.png" style="width: 26upx;height: 26upx;"></image>
  45. <view class="margin-left-xs flex align-center" style="color: #999999;">
  46. <view @click="bindData(1)">{{startTime?startTime:'开始时间'}}</view>
  47. <view @click="bindData(2)">{{endTime?endTime:'结束时间'}}</view>
  48. </view>
  49. </view> -->
  50. <!-- <me-tabs v-model="tabIndex" nameKey='title' :tabs="tabs" @change="tabChange"></me-tabs> -->
  51. <u-tabs :list="tabs" :is-scroll="true" :current="tabIndex" @change="tabChange" active-color="#222" inactive-color="#AAAAAA" font-size="32" :bar-height="12" bar-width="50"></u-tabs>
  52. </view>
  53. <mescroll-body :sticky="true" ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback">
  54. <!-- 数据列表 -->
  55. <!-- <view v-if="goods.length > 0" class="margin-sm padding-sm bg radius" v-for="(item,index) in goods"
  56. :key='index' @click="clickItem(item)"> -->
  57. <view class="margin-sm bgwhite margin-top-sm padding-bottom-sm " style="border-radius: 32rpx;" v-for="(item,index) in goods" :key='index' @click="goNav('/my/order/pay?ordersId='+item.ordersId)">
  58. <view class="flex justify-between padding-sm">
  59. <view class="text-green" v-if="item.status ==1">待付款...</view>
  60. <view class="text-green" v-if="item.status ==2">待服务</view>
  61. <view class="text-green" v-if="item.status ==5">已完成</view>
  62. <view class="text-green" v-if="item.status ==6">服务中</view>
  63. <view class="text-green" v-if="item.status ==7">已出发</view>
  64. <view class="text-green" v-if="item.status ==8">已到达</view>
  65. <view class="text-green" v-if="item.status ==3">待评价</view>
  66. <view class="text-green" v-if="item.status ==4" style="color: #999999;">已取消</view>
  67. <view v-if="item.overTimeOrders == 1" style="color: red;font-size:26rpx">(订单已超时)</view>
  68. <!-- <view class="text-green" v-if="item.state ==1 ||item.state ==2">待完成</view>
  69. <view class="text-green" v-if="item.state ==3||item.state ==4">已完成</view> -->
  70. <view class="time">预约时间:{{item.serveTime}}</view>
  71. </view>
  72. <view class="xian"></view>
  73. <view class=" u-flex u-p-t-30 padding-sm">
  74. <view class="u-m-r-10">
  75. <image style="width: 160rpx;height: 160rpx;border-radius: 32rpx;" :src="item.massageImg?item.massageImg: '../../static/logo.png'" mode=""></image>
  76. </view>
  77. <view class="u-flex-1 margin-left-xs">
  78. <view class="u-font-18 text-bold u-line-1" style="width: 560rpx;">
  79. <view class="margin-right-xs text-df margin-left-xs"
  80. style="font-weight: bold;font-size: 32rpx;color: #222222;margin-top: 0rpx;display: inline-block;width: 400rpx; overflow: hidden;white-space: nowrap;text-overflow: ellipsis;">
  81. {{item.title}}
  82. </view>
  83. </view>
  84. <view class="margin-left-xs text-cut" style="width:550upx;margin-top: 20rpx;">{{item.address}}</view>
  85. </view>
  86. </view>
  87. <view class="flex u-p-t-20 justify-between align-center padding-sm">
  88. <view class=" flex-sub " >
  89. 实收:<text class="text-df" style="color: #F24E4E;">¥</text><text style="color: #F24E4E;font-weight: bold;font-size: 40rpx;">{{item.sumArtificerMoney}}</text>
  90. </view>
  91. <view class="flex text-right">
  92. <u-button v-if="item.status == 1" :custom-style="customStyle" shape="circle" :plain="true"
  93. @click="cancelOrder(item)">取消订单</u-button>
  94. <!-- <u-button v-if="item.status == 1" :custom-style="customStyle1" shape="circle" :plain="true"
  95. @click="bindphone(item.phone)">联系TA</u-button> -->
  96. <u-button v-if=" item.state==1" :custom-style="customStyle1" shape="circle" :plain="true"
  97. @click="goNav('/my/order/pay?id='+item.ordersId+'&isTrue=1')">查看详情</u-button>
  98. <u-button v-if="item.status == 6" :custom-style="customStyle" shape="circle" :plain="true"
  99. @click="cancel(item)">服务完成</u-button>
  100. </view>
  101. </view>
  102. <view class="xian" v-if="item.endTime && item.endTime.day && item.status == 6"></view>
  103. <view class="pintuan_syrs flex justify-between"
  104. v-if="item.endTime && item.endTime.day && item.status == 6">
  105. <view style="font-size: 28rpx;font-family: PingFang SC;font-weight: bold;color: #2FB57A;">服务倒计时
  106. </view>
  107. <uni-countdown :day="item.endTime.day" :hour="item.endTime.hour" :minute="item.endTime.minute"
  108. :second="item.endTime.second" color="#20C675"/>
  109. <!-- <uni-countdown :day="item.endTime.day" :hour="item.endTime.hour" :minute="item.endTime.minute"
  110. :second="item.endTime.second">
  111. </uni-countdown> -->
  112. </view>
  113. </view>
  114. <empty v-if="goods.length == 0"></empty>
  115. <!-- 开始时间 -->
  116. <u-picker v-model="startshow" mode="time" :params="paramsStart" @confirm="startData"></u-picker>
  117. <!-- 结束时间 -->
  118. <u-picker v-model="endshow" mode="time" :params="paramsEnd" @confirm="endData"></u-picker>
  119. </mescroll-body>
  120. </view>
  121. </template>
  122. <script>
  123. import MescrollMixin from "@/components/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
  124. import mescrollBody from "@/components/mescroll-uni/components/mescroll-body/mescroll-body.vue";
  125. import meTabs from "@/components/mescroll-uni/me-tabs/me-tabs.vue";
  126. import empty from '@/components/empty.vue'
  127. export default {
  128. mixins: [MescrollMixin], // 使用mixin
  129. components: {
  130. mescrollBody,
  131. meTabs,
  132. empty
  133. },
  134. data() {
  135. return {
  136. goods: [], // 数据列表
  137. game: [],
  138. tabs: [{
  139. name: '今日订单',
  140. status: '1'
  141. }, {
  142. name: '待服务',
  143. status: '2'
  144. }, {
  145. name: '已完成',
  146. status: '3'
  147. }, {
  148. name: '历史订单',
  149. status: '4'
  150. }],
  151. tabIndex: 0, // tab下标
  152. isTrue: true,
  153. page: 1,
  154. limit: 10,
  155. userId: 0,
  156. status: 1,
  157. nickName: '',
  158. avatar: '',
  159. customStyle: {
  160. color: '#999999',
  161. border: '2rpx solid #999999',
  162. // backgroundColor: '#1E1F31',
  163. border: "8rpx",
  164. width: '180rpx',
  165. height: '54rpx',
  166. margin: "0 0 0 20rpx"
  167. },
  168. customStyle1: {
  169. color: '#2FB57A',
  170. border: '2rpx solid #2FB57A',
  171. border: "8rpx",
  172. width: '180rpx',
  173. height: '54rpx',
  174. margin: "0 0 0 20rpx"
  175. },
  176. latitude:'',
  177. longitude:'',
  178. avatar: '../../static/logo.png',
  179. isLogin: true,
  180. userName: '匿名',
  181. renzheng: 0,
  182. startshow: false,
  183. endshow: false,
  184. paramsStart: {
  185. year: true,
  186. month: true,
  187. day: true,
  188. hour: false,
  189. minute: false,
  190. second: false
  191. },
  192. paramsEnd: {
  193. year: true,
  194. month: true,
  195. day: true,
  196. hour: false,
  197. minute: false,
  198. second: false
  199. },
  200. startTime: '',
  201. endTime: ''
  202. }
  203. },
  204. onLoad() {
  205. this.$queue.showLoading("加载中...");
  206. this.userId = uni.getStorageSync('userId')
  207. this.nickName = uni.getStorageSync('nickName')
  208. },
  209. onShow() {
  210. let that = this;
  211. this.userId = uni.getStorageSync('userId')
  212. if (this.userId) {
  213. //是否开启技师端实时定位 375
  214. this.$Request.get('/app/common/type/375').then(res => {
  215. if (res.code == 0 && res.data) {
  216. if (res.data.value === '是') {
  217. let renzheng = uni.getStorageSync('renzheng')
  218. if (renzheng && renzheng == 2) {
  219. uni.getLocation({
  220. type: 'wgs84',
  221. success: function(res) {
  222. console.log('当前位置的经度:' + res.longitude);
  223. console.log('当前位置的纬度:' + res.latitude);
  224. that.$queue.setData('longitude',res.longitude);
  225. that.$queue.setData('latitude',res.latitude);
  226. that.latitude = res.latitude
  227. that.longitude = res.longitude
  228. }
  229. });
  230. }
  231. }
  232. }
  233. });
  234. this.getArtificer()
  235. this.isLogin = false
  236. this.getUserInfo()
  237. } else {
  238. this.isLogin = true
  239. this.userName = '匿名'
  240. this.browse = 0
  241. this.fans = 0
  242. this.follow = 0
  243. this.visitor = 0
  244. this.avatar = '../../static/logo.png'
  245. }
  246. setTimeout(d => {
  247. this.mescroll.resetUpScroll()
  248. }, 1000)
  249. },
  250. methods: {
  251. //获取技师的信息
  252. getArtificer() {
  253. this.$Request.getT("/app/artificer/selectArtificer").then(res => {
  254. if (res.code == 0) {
  255. if (res.data) {
  256. if (res.data.status == 1) {
  257. this.isTrue = true
  258. } else if (res.data.status == 2) {
  259. this.isTrue = false
  260. }
  261. } else {
  262. this.isTrue = false
  263. }
  264. uni.setStorageSync('artificerId', res.data.artificerId)
  265. }
  266. });
  267. },
  268. stateSave() {
  269. this.$Request.postT('/app/artificer/updateArtificer').then(res => {
  270. if (res.code == 0) {
  271. this.getArtificer();
  272. this.$queue.showToast('切换成功!')
  273. } else {
  274. this.$queue.showToast(res.msg);
  275. }
  276. });
  277. },
  278. // 拨打电话
  279. bindphone(phone) {
  280. let that = this
  281. uni.showModal({
  282. title: '提示',
  283. content: '是否拨打电话',
  284. success: function(res) {
  285. if (res.confirm) {
  286. console.log('用户点击确定', phone);
  287. uni.makePhoneCall({
  288. phoneNumber: phone //仅为示例
  289. });
  290. } else if (res.cancel) {
  291. console.log('用户点击取消');
  292. }
  293. }
  294. });
  295. },
  296. /*下拉刷新的回调 */
  297. downCallback() {
  298. // 这里加载你想下拉刷新的数据, 比如刷新轮播数据
  299. // loadSwiper();
  300. // 下拉刷新的回调,默认重置上拉加载列表为第一页 (自动执行 page.num=1, 再触发upCallback方法 )
  301. this.mescroll.resetUpScroll()
  302. },
  303. timeFormat(param) {
  304. return param < 10 ? '0' + param : param;
  305. },
  306. /*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */
  307. upCallback(page) {
  308. if(this.isLogin){
  309. uni.hideLoading();
  310. return;
  311. }
  312. let curTab = this.tabs[this.tabIndex].status
  313. let data = {
  314. type: curTab,
  315. page: page.num,
  316. limit: page.size,
  317. startTime: this.startTime,
  318. endTime: this.endTime
  319. }
  320. this.$Request.get('/app/artificer/selectTodayOrder', data).then(res => {
  321. uni.hideLoading();
  322. this.mescroll.endBySize(res.data.list.length, res.data.totalCount)
  323. if (page.num == 1) this.goods = []; //如果是第一页需手动制空列表
  324. this.goods = [...this.goods, ...res.data.list]; //追加新数据
  325. this.goods.forEach(ret => {
  326. switch (ret.state) {
  327. case '1':
  328. ret.statusName = '今日订单'
  329. break;
  330. case '2':
  331. ret.statusName = '待完成'
  332. break;
  333. case '3':
  334. ret.statusName = '已完成'
  335. break;
  336. case '4':
  337. ret.statusName = '历史订单'
  338. break;
  339. }
  340. if (ret.status == 6 && ret.endTime) {
  341. let data = {}
  342. data.day = 0;
  343. data.hour = 0;
  344. data.minute = 0;
  345. data.second = 0;
  346. var now = new Date().getTime();
  347. var endDate = new Date(ret.endTime).getTime();
  348. let time = (endDate - now) / 1000;
  349. data.day = this.timeFormat(parseInt(time / (60 * 60 * 24)));
  350. data.hour = this.timeFormat(parseInt(time % (60 * 60 * 24) / 3600));
  351. data.minute = this.timeFormat(parseInt(time % (60 * 60 * 24) % 3600 / 60));
  352. data.second = this.timeFormat(parseInt(time % (60 * 60 * 24) % 3600 % 60));
  353. ret.endTime = data;
  354. }
  355. })
  356. this.mescroll.endSuccess(res.data.list.length); // 隐藏加载状态栏
  357. }).catch(() => {
  358. //联网失败, 结束加载
  359. this.mescroll.endErr();
  360. });
  361. },
  362. // 切换菜单
  363. tabChange(index) {
  364. this.tabIndex = index
  365. this.goods = []; // 置空列表,显示加载进度条
  366. this.mescroll.resetUpScroll()
  367. },
  368. // 取消订单
  369. cancelOrder(e) {
  370. let that = this
  371. uni.showModal({
  372. title: '提示',
  373. content: '确认取消订单吗?取消订单将会被扣除信用分!',
  374. success: function(res) {
  375. if (res.confirm) {
  376. let data = {
  377. ordersId: e.ordersId,
  378. }
  379. that.$queue.showLoading('提交中...')
  380. that.$Request.post('/app/artificer/deleteOrders', data).then(res => {
  381. uni.hideLoading();
  382. if (res.code == 0) {
  383. that.mescroll.resetUpScroll()
  384. } else {
  385. that.$queue.showToast(res.msg);
  386. }
  387. })
  388. } else if (res.cancel) {
  389. console.log('用户点击取消');
  390. }
  391. }
  392. });
  393. },
  394. // 完成订单
  395. cancel(e) {
  396. let that = this
  397. uni.showModal({
  398. title: '提示',
  399. content: '如果服务未完成点击完成订单会遭到平台违规处理,请确认服务是否完毕?',
  400. success: function(res) {
  401. if (res.confirm) {
  402. let data = {
  403. ordersId: e.ordersId,
  404. accomplishLongitude: that.longitude,
  405. accomplishLatitude: that.latitude
  406. }
  407. that.$queue.showLoading('提交中...')
  408. that.$Request.post('/app/artificer/accomplishOrders', data).then(res => {
  409. uni.hideLoading();
  410. if (res.code == 0) {
  411. that.mescroll.resetUpScroll()
  412. } else {
  413. that.$queue.showToast(res.msg);
  414. }
  415. })
  416. } else if (res.cancel) {
  417. console.log('用户点击取消');
  418. }
  419. }
  420. });
  421. },
  422. //时间弹框开关
  423. bindData(index) {
  424. console.log(index, 1111)
  425. if (index == 1) {
  426. this.startshow = true
  427. } else if (index == 2) {
  428. this.endshow = true
  429. }
  430. },
  431. //开始时间
  432. startData(e) {
  433. // console.log(e)
  434. this.startTime = e.year + ' ' + e.month + '-' + e.day
  435. },
  436. // 结束时间
  437. endData(e) {
  438. this.endTime = e.year + ' ' + e.month + '-' + e.day
  439. // console.log(this.endTime)
  440. this.mescroll.resetUpScroll()
  441. },
  442. goNav(e, name) {
  443. console.log(e)
  444. if (this.userId) {
  445. uni.navigateTo({
  446. url: e
  447. })
  448. } else {
  449. uni.showModal({
  450. title: '提示',
  451. content: '您还未登录,请先登录',
  452. success: function(res) {
  453. if (res.confirm) {
  454. console.log('用户点击确定');
  455. uni.navigateTo({
  456. url: '/pages/public/login'
  457. })
  458. } else if (res.cancel) {
  459. console.log('用户点击取消');
  460. }
  461. }
  462. })
  463. }
  464. },
  465. getUserInfo() {
  466. this.$Request.get("/app/user/selectUserById").then(res => {
  467. if (res.code == 0) {
  468. this.userName = res.data.userName
  469. this.invitationCode = res.data.invitationCode
  470. this.avatar = res.data.avatar ? res.data.avatar : '../../static/logo.png'
  471. this.isAuthentication = res.data.isAuthentication
  472. // uni.setStorageSync('isAuthentication', res.data.isAuthentication)
  473. uni.setStorageSync('avatar', res.data.avatar)
  474. uni.setStorageSync('invitationCode', res.data.invitationCode)
  475. uni.setStorageSync('zhiFuBao', res.data.zhiFuBao)
  476. uni.setStorageSync('zhiFuBaoName', res.data.zhiFuBaoName)
  477. if (res.data.isAuthentication == 0 || res.data.isAuthentication == null) {
  478. this.renzheng = 0
  479. uni.setStorageSync("renzheng", this.renzheng)
  480. } else if (res.data.isAuthentication == 1) {
  481. this.renzheng = 1
  482. uni.setStorageSync("renzheng", this.renzheng)
  483. } else if (res.data.isAuthentication == 2) {
  484. this.renzheng = 2
  485. uni.setStorageSync("renzheng", this.renzheng)
  486. } else if (res.data.isAuthentication == 3) {
  487. this.renzheng = 3
  488. uni.setStorageSync("renzheng", this.renzheng)
  489. } else if (res.data.isAuthentication == 4) {
  490. this.renzheng = 4
  491. uni.setStorageSync("renzheng", this.renzheng)
  492. } else if (res.data.isAuthentication == 5) {
  493. this.renzheng = 5
  494. uni.setStorageSync("renzheng", this.renzheng)
  495. } else if (res.data.isAuthentication == 6) {
  496. this.renzheng = 6
  497. uni.setStorageSync("renzheng", this.renzheng)
  498. }
  499. }
  500. });
  501. },
  502. }
  503. }
  504. </script>
  505. <style lang="scss">
  506. /*
  507. sticky生效条件:
  508. 1、父元素不能overflow:hidden或者overflow:auto属性。(mescroll-body设置:sticky="true"即可, mescroll-uni本身没有设置overflow)
  509. 2、必须指定top、bottom、left、right4个值之一,否则只会处于相对定位
  510. 3、父元素的高度不能低于sticky元素的高度
  511. 4、sticky元素仅在其父元素内生效,所以父元素必须是 mescroll
  512. */
  513. .sticky-tabs {
  514. z-index: 990;
  515. position: sticky;
  516. top: var(--window-top);
  517. // background-color: #fff;
  518. }
  519. // 使用mescroll-uni,则top为0
  520. .mescroll-uni,
  521. /deep/.mescroll-uni {
  522. .sticky-tabs {
  523. top: 300upx;
  524. }
  525. }
  526. .demo-tip {
  527. padding: 18upx;
  528. font-size: 24upx;
  529. text-align: center;
  530. }
  531. .order-page {
  532. background-color: #F7F7F7;
  533. .text-green{
  534. font-size: 32rpx;
  535. color: #1EDA94;
  536. }
  537. .time{
  538. font-size: 28rpx;
  539. color: #AAAAAA;
  540. }
  541. }
  542. .bg {
  543. background-color: #FFFFFF;
  544. }
  545. .bgwhite {
  546. background-color: #FFFFFF;
  547. }
  548. .xian {
  549. width: 100%;
  550. height: 1rpx;
  551. border: 1rpx solid #f8f8f8;
  552. // margin-top: 20rpx;
  553. }
  554. .pintuan_syrs {
  555. color: #999999;
  556. font-size: 20upx;
  557. margin: 20rpx 20rpx 0rpx;
  558. display: flex;
  559. padding-right: 18upx;
  560. }
  561. .labe {
  562. background: #DCFFF2;
  563. display: inline-flex;
  564. align-items: center;
  565. border-radius: 39rpx;
  566. color: #1A1B1B;
  567. font-size: 22rpx;
  568. font-weight: 400;
  569. width: 134rpx;
  570. height: 40rpx;
  571. line-height: 40rpx;
  572. justify-content: center;
  573. margin-left: 20rpx;
  574. text {
  575. width: 10rpx;
  576. height: 10rpx;
  577. background: #1EDA94;
  578. border-radius: 50%;
  579. margin-right: 12rpx;
  580. }
  581. }
  582. </style>