wangfukang 3 days ago
parent
commit
64acab6910
  1. 51
      components/common-loading/common-loading.vue
  2. 155
      components/ie-bottom-tab/ie-bottom-tab.vue
  3. 310
      components/tab-bar/delivery.vue
  4. 56
      components/tab-bar/tab-bar.vue

51
components/common-loading/common-loading.vue

@ -7,8 +7,10 @@
@tap.stop="noop"
>
<view class="common-loading__box">
<view class="common-loading__halo"></view>
<image class="common-loading__gif" src="/static/images/img/loading.gif" mode="aspectFit"></image>
<view v-if="title" class="common-loading__text">{{ title }}</view>
<view class="common-loading__hint">请稍候正在为你处理</view>
</view>
</view>
</template>
@ -63,7 +65,8 @@
align-items: center;
justify-content: center;
pointer-events: none;
background: rgba(0, 0, 0, 0.18);
background: rgba(13, 18, 34, 0.46);
backdrop-filter: blur(16rpx);
}
.common-loading--mask {
@ -71,29 +74,55 @@
}
.common-loading__box {
min-width: 180rpx;
min-height: 180rpx;
padding: 34rpx 36rpx 30rpx;
border-radius: 28rpx;
background: rgba(255, 255, 255, 0.96);
box-shadow: 0 18rpx 46rpx rgba(0, 0, 0, 0.16);
position: relative;
min-width: 280rpx;
min-height: 242rpx;
overflow: hidden;
padding: 44rpx 44rpx 36rpx;
border-radius: 40rpx;
background: linear-gradient(180deg, rgba(255,255,255,.98), rgba(245,249,255,.96));
border: 1rpx solid rgba(255,255,255,.86);
box-shadow: 0 28rpx 82rpx rgba(28, 35, 74, 0.28);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.common-loading__halo {
position: absolute;
top: -82rpx;
right: -74rpx;
width: 220rpx;
height: 220rpx;
border-radius: 50%;
background: rgba(169, 255, 231, .72);
}
.common-loading__gif {
position: relative;
width: 92rpx;
height: 92rpx;
}
.common-loading__text {
position: relative;
margin-top: 18rpx;
max-width: 320rpx;
font-size: 26rpx;
line-height: 36rpx;
color: #333;
max-width: 380rpx;
font-size: 28rpx;
line-height: 40rpx;
color: #11162a;
font-weight: 900;
white-space: pre-line;
text-align: center;
}
.common-loading__hint {
position: relative;
margin-top: 10rpx;
color: rgba(17, 22, 42, .48);
font-size: 22rpx;
line-height: 32rpx;
text-align: center;
}
</style>

155
components/ie-bottom-tab/ie-bottom-tab.vue

@ -1,155 +0,0 @@
<template>
<view>
<view class="safe-tip" v-if="showTip">请勿发送涉黄涉暴反动侮辱等内容违规会被封禁</view>
<view class="bottom-actions">
<view class="bottom-item" :class="{ active: active === 'index' }" @tap="goTab('index')">
<text class="tab-icon">🪐</text>
<text>此刻</text>
</view>
<view class="bottom-item message-tab" :class="{ active: active === 'messages' }" @tap="goTab('messages')">
<text class="tab-icon">💬</text>
<text>消息</text>
<text class="unread-badge" v-if="displayUnreadCount > 0">{{ unreadText }}</text>
</view>
<view class="bottom-item" :class="{ active: active === 'universe' }" @tap="goTab('universe')">
<text class="tab-icon">🌙</text>
<text>我的</text>
</view>
</view>
</view>
</template>
<script>
const TAB_PATHS = {
index: '/package1/ieBrowser/index',
messages: '/package1/ieBrowser/messages',
universe: '/package1/ieBrowser/universe'
}
export default {
name: 'IeBottomTab',
props: {
active: {
type: String,
default: 'index'
},
unreadCount: {
type: Number,
default: 0
},
showTip: {
type: Boolean,
default: true
}
},
computed: {
displayUnreadCount() {
return Number(this.unreadCount) || 0
},
unreadText() {
return this.displayUnreadCount > 99 ? '99+' : String(this.displayUnreadCount)
}
},
methods: {
goTab(tab) {
if (tab === this.active) return
const path = TAB_PATHS[tab]
if (!path) return
uni.redirectTo({
url: path + '?unreadCount=' + encodeURIComponent(String(this.displayUnreadCount))
})
}
}
}
</script>
<style lang="scss" scoped>
.safe-tip {
position: fixed;
left: 36rpx;
right: 36rpx;
bottom: 142rpx;
z-index: 10;
padding: 12rpx 18rpx;
border-radius: 22rpx;
text-align: center;
color: rgba(22, 27, 46, .5);
background: rgba(255, 255, 255, .74);
border: 1rpx solid rgba(255, 255, 255, .9);
backdrop-filter: blur(18rpx);
box-shadow: 0 14rpx 38rpx rgba(96, 112, 160, .1);
font-size: 20rpx;
line-height: 28rpx;
font-weight: 700;
}
.bottom-actions {
position: fixed;
left: 30rpx;
right: 30rpx;
bottom: 30rpx;
z-index: 10;
display: flex;
padding: 12rpx;
border: 1rpx solid rgba(255, 255, 255, .92);
border-radius: 999rpx;
overflow: hidden;
background: rgba(255, 255, 255, .92);
backdrop-filter: blur(24rpx);
box-shadow: 0 24rpx 80rpx rgba(96, 112, 160, .18);
}
.bottom-item {
position: relative;
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 80rpx;
border-radius: 999rpx;
color: rgba(22, 27, 46, .4);
font-size: 21rpx;
font-weight: 700;
transition: transform .16s ease, background .24s ease;
}
.bottom-item:active {
transform: scale(.94);
}
.bottom-item.active {
color: #161b2e;
background: linear-gradient(135deg, #eafff8, #a9ffe7);
box-shadow: 0 12rpx 30rpx rgba(169, 255, 231, .34), inset 0 1rpx 0 rgba(255, 255, 255, .95);
}
.tab-icon {
margin-bottom: 4rpx;
font-size: 30rpx;
filter: grayscale(1);
opacity: .55;
}
.bottom-item.active .tab-icon {
filter: none;
opacity: 1;
}
.unread-badge {
position: absolute;
right: 16rpx;
top: 2rpx;
min-width: 30rpx;
height: 30rpx;
line-height: 30rpx;
padding: 0 8rpx;
border-radius: 999rpx;
text-align: center;
color: #fff;
background: linear-gradient(135deg, #ff8ba0, #e85d75);
box-shadow: 0 8rpx 20rpx rgba(232, 93, 117, .28);
font-size: 18rpx;
font-weight: 900;
}
</style>

310
components/tab-bar/delivery.vue

@ -1,9 +1,10 @@
<template>
<view class="page1">
<common-loading />
<view class="title">
<view class="title-sreach">
<view style="position: absolute;display: flex;" :style="{'top': menuButtonInfo.top +'px'}">
<view class="sort-member" style="width: 260rpx;">
<view class="sort-member delivery-title-tabs">
<view class="tab1">
<view class="tabs1" @tap="checkTab1('daiqu')"
:style="{'color':tab1Checked == 'daiqu'?'#000':'#777','font-size':tab1Checked== 'daiqu'?'36rpx':'30rpx'}">
@ -30,11 +31,14 @@
style="width: 80rpx;height: 14rpx;position: absolute;bottom: 4rpx;left: 32rpx;" />
</view> -->
</view>
<view class="title-refresh" :class="{'title-refresh--loading': refreshLoading}" @tap.stop="refreshCurrentTab">
<uni-icons type="refresh" size="20" color="#0b6b5a" style="margin-top: 6rpx;"></uni-icons>
</view>
</view>
</view>
</view>
</view>
<view style="height: 50rpx;width: 95%;margin: -200rpx auto 0;display: flex;line-height: 50rpx;">
<view class="delivery-filter-row">
<view class="guize-box1"
:style="{'background':tab1Checked1 == 'fantuan'?'rgba(130, 255, 130, 1)':'rgba(247, 248, 248, 0.6)'}"
@ -54,14 +58,11 @@
<uni-icons type="info" size="10"></uni-icons>
跑腿
</view>
<view style="padding-right: 12rpx;">|</view>
<view class="filter-divider">|</view>
<view class="guize-box" @tap="openPopup()">
<uni-icons type="info" size="10"></uni-icons>
接单规则
</view>
<view class="refresh-box" @tap.stop="refreshCurrentTab">
刷新
</view>
<view class="">
<view @tap="changeOnline(0)" class="shangxia-btn shangxian-btn" v-if="isOnLine==1">
<text>已上线</text>
@ -201,20 +202,32 @@
用户申请退款中
</view>
</view>
<view v-else style="width: 100%;height: 100rpx;margin-top: 32rpx;">
<img v-if="item.status == 1 && item.arriveTime == null"
src="https://jewel-shop.oss-cn-beijing.aliyuncs.com/d649c22310874f19a74cf8dfbb1c7240.png"
alt="" style="width: 100%;height: 100rpx;background-size: 100%;"
@tap="changeStatus(index,item,1)" />
<view v-else class="order-action">
<view v-if="item.status == 1 && item.arriveTime == null"
class="order-action-btn order-action-btn--arrive"
@tap="changeStatus(index,item,1)">
<view class="order-action-icon">
<uni-icons type="hand-up-filled" size="24" color="#fff"></uni-icons>
</view>
<text>已到店</text>
</view>
<!-- <view style="width: 20%;" @tap="changeOthers(item,1)">转单</view> -->
<img v-if="item.status == 1 && item.arriveTime != null"
src="https://jewel-shop.oss-cn-beijing.aliyuncs.com/c318cf292a4f40b296995c30e5e539ea.png"
alt="" style="width: 100%;height: 100rpx;background-size: 100%;"
@tap="changeStatus(index,item,2)" />
<img v-if="item.status == 2 && item.arriveTime != null"
src="https://jewel-shop.oss-cn-beijing.aliyuncs.com/a8cdd6d86e9140df86d3c3c60356bd53.png"
alt="" style="width: 100%;height: 100rpx;background-size: 100%;"
@tap="changeStatus(index,item,3)" />
<view v-if="item.status == 1 && item.arriveTime != null"
class="order-action-btn order-action-btn--pickup"
@tap="changeStatus(index,item,2)">
<view class="order-action-icon">
<uni-icons type="hand-up-filled" size="24" color="#fff"></uni-icons>
</view>
<text>已取货</text>
</view>
<view v-if="item.status == 2 && item.arriveTime != null"
class="order-action-btn order-action-btn--complete"
@tap="changeStatus(index,item,3)">
<view class="order-action-icon">
<uni-icons type="hand-up-filled" size="24" color="#fff"></uni-icons>
</view>
<text>已送达</text>
</view>
</view>
</view>
<uni-load-more :status="loadStatus" @change="onChange" />
@ -402,6 +415,10 @@
selectRuleList: [],
totalPages: 1,
paotuiRuleList: [],
loginRedirecting: false,
refreshLoading: false,
refreshLoadingStartTime: 0,
refreshLoadingTimer: null,
lineStatus: [{
title: '上线',
value: 0
@ -422,6 +439,16 @@
onReachBottom() {
this.onReachPage();
},
beforeDestroy() {
if (this.refreshLoadingTimer) {
clearTimeout(this.refreshLoadingTimer)
this.refreshLoadingTimer = null
}
if (this.refreshLoading) {
this.refreshLoading = false
uni.hideLoading()
}
},
filters: {
formatHourMinute(value) {
if (!value) return '';
@ -484,10 +511,38 @@
urls: [url]
});
},
ensureLogin() {
const token = uni.getStorageSync('hiver_token')
if (token && typeof token === 'string' && token.trim() && token !== 'null' && token !== 'undefined') {
return true
}
if (this.loginRedirecting) return false
this.loginRedirecting = true
const pages = getCurrentPages()
const current = pages && pages.length ? pages[pages.length - 1] : null
const route = current ? '/' + current.route : '/pages/index/index'
const query = current && current.options
? Object.keys(current.options).map(key => key + '=' + encodeURIComponent(current.options[key])).join('&')
: ''
const target = route + (query ? '?' + query : '')
const redirectKey = 'login_redirect_' + Date.now()
uni.setStorageSync(redirectKey, target)
uni.navigateTo({
url: '/package2/login/login?redirect=' + redirectKey,
complete: () => {
setTimeout(() => {
this.loginRedirecting = false
}, 1200)
}
})
return false
},
init() {
if (!this.ensureLogin()) return
let worker = uni.getStorageSync('worker')
if (worker == '' || worker == undefined || worker == null) {
this.tui.toast('您还没有注册兼职')
return
}
this.menuButtonInfo = uni.getMenuButtonBoundingClientRect()
this.isOnLine = uni.getStorageSync('worker').isOnLine
@ -506,6 +561,7 @@
},
//
getUserLocation(item) {
if (!this.ensureLogin()) return
let that = this;
uni.getLocation({
type: 'gcj02',
@ -524,6 +580,7 @@
});
},
onReachPage() {
if (!this.ensureLogin()) return
if (this.isLoadingPage || this.searchForm.pageNum >= this.totalPages) return;
this.isLoadingPage = true;
this.searchForm.pageNum++;
@ -554,6 +611,7 @@
})
},
chooseType(type) {
if (!this.ensureLogin()) return
if (this.tab1Checked1 == type) {
this.tab1Checked1 = ''
this.searchForm.deliveryType = null
@ -587,6 +645,7 @@
return diffMs <= 0 || diffMs < 10 * 60 * 1000;
},
getDelivery() {
if (!this.ensureLogin()) return
let that = this
that.isLoadingPage = true;
this.tui.request("/mall/delivery/pagebyworker", "POST", this.searchForm, false, false).then((res) => {
@ -613,11 +672,17 @@
that.$forceUpdate();
} else {
that.tui.toast(res.message);
return;
}
uni.hideLoading();
if (that.refreshLoading) {
that.finishRefreshLoading()
} else {
uni.hideLoading();
}
}).catch((res) => {
that.isLoadingPage = false;
if (that.refreshLoading) {
that.finishRefreshLoading()
}
});
},
//
@ -686,6 +751,7 @@
workerRelaPriceList: this.selectRuleList,
getPushOrder: this.zhipaiCheck ? 1 : 0
};
if (!this.ensureLogin()) return
let that = this;
this.tui.request('/app/workerRelaPrice/batchUpdate', 'post', submitData).then(res => {
uni.hideLoading();
@ -725,12 +791,18 @@
}
},
openPopup() {
if (!this.ensureLogin()) return
const worker = uni.getStorageSync('worker')
if (!worker || !worker.workerId) {
this.tui.toast('您还没有注册兼职')
return
}
if (this.isOnLine != 1) {
this.tui.toast('请先上线后配置');
return;
}
let that = this
that.tui.request("/app/workerRelaPrice/getByWorkerId?workerId=" + uni.getStorageSync('worker').workerId,
that.tui.request("/app/workerRelaPrice/getByWorkerId?workerId=" + worker.workerId,
"GET", {}, false, true).then((res) => {
if (res.code == 200) {
if (res.result != null) {
@ -793,6 +865,7 @@
this.isArea = !this.isArea
},
changeStatus(index, item, status) {
if (!this.ensureLogin()) return
let regionId = JSON.parse(uni.getStorageSync('area')).id
let url = ''
if (status == 2) {
@ -857,6 +930,7 @@
}).catch((res) => {});
},
checkTab1(type) {
if (!this.ensureLogin()) return
this.tab1Checked = type
if (type == 'daiqu') {
this.searchForm.status = 1
@ -868,16 +942,46 @@
this.getDelivery()
},
refreshCurrentTab() {
if (!this.ensureLogin()) return
if (this.refreshLoading) return
this.refreshLoading = true
this.refreshLoadingStartTime = Date.now()
if (this.refreshLoadingTimer) {
clearTimeout(this.refreshLoadingTimer)
this.refreshLoadingTimer = null
}
uni.showLoading({
title: '刷新中...',
mask: true
})
this.searchForm.pageNum = 1
this.scrollToTop()
this.getDelivery()
},
finishRefreshLoading() {
const elapsed = Date.now() - this.refreshLoadingStartTime
const delay = Math.max(1000 - elapsed, 0)
if (this.refreshLoadingTimer) {
clearTimeout(this.refreshLoadingTimer)
}
this.refreshLoadingTimer = setTimeout(() => {
this.refreshLoading = false
this.refreshLoadingTimer = null
uni.hideLoading()
}, delay)
},
makeCall(phone) {
uni.makePhoneCall({
phoneNumber: phone
});
},
changeOnline(value) {
if (!this.ensureLogin()) return
const worker = uni.getStorageSync('worker')
if (!worker || !worker.workerId) {
this.tui.toast('您还没有注册兼职')
return
}
let url = ''
if (this.isOnLine == value) {
if (value == 0) {
@ -896,7 +1000,7 @@
}
this.tui.request(url, "POST", {
id: uni.getStorageSync('worker').workerId
id: worker.workerId
}, false, true).then((res) => {
if (res.code == 200) {
let worker = uni.getStorageSync('worker') || {}; //
@ -968,6 +1072,49 @@
height: 60rpx;
}
.delivery-title-tabs {
width: 380rpx;
display: flex;
align-items: center;
}
.delivery-title-tabs .tab1 {
width: 260rpx;
flex-shrink: 0;
}
.title-refresh {
width: 58rpx;
height: 58rpx;
margin-left: 18rpx;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
border: 2rpx solid rgba(166, 255, 234, 0.88);
border-radius: 50%;
background: rgba(255, 255, 255, 0.7);
box-shadow: 0 8rpx 20rpx rgba(0, 35, 28, 0.08);
}
.title-refresh:active {
opacity: 0.75;
}
.title-refresh--loading {
animation: refresh-rotate 0.8s linear infinite;
}
@keyframes refresh-rotate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.tab1 {
height: 60rpx;
line-height: 60rpx;
@ -982,6 +1129,22 @@
flex: 1;
}
.delivery-filter-row {
width: 95%;
height: 72rpx;
margin: -200rpx auto 0;
display: flex;
align-items: center;
line-height: 64rpx;
}
.filter-divider {
flex-shrink: 0;
padding: 0 14rpx 0 2rpx;
color: rgba(0, 35, 28, 0.72);
font-weight: 700;
}
.content {
flex: 1;
width: 95%;
@ -1094,6 +1257,64 @@
font-weight: 700;
}
.order-action {
width: 100%;
height: 104rpx;
margin-top: 32rpx;
}
.order-action-btn {
position: relative;
width: 100%;
height: 96rpx;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
border-radius: 48rpx;
color: #fff;
font-size: 34rpx;
font-weight: 900;
letter-spacing: 2rpx;
box-shadow: 0 14rpx 30rpx rgba(0, 70, 58, 0.18);
}
.order-action-btn::before {
content: '';
position: absolute;
top: 0;
left: -20%;
width: 56%;
height: 100%;
background: linear-gradient(90deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.22), rgba(255, 255, 255, 0));
transform: skewX(-18deg);
}
.order-action-btn:active {
transform: scale(0.98);
opacity: 0.9;
}
.order-action-btn--arrive,
.order-action-btn--pickup,
.order-action-btn--complete {
background:
radial-gradient(circle at 88% 45%, rgba(166, 255, 234, 0.52) 0, rgba(166, 255, 234, 0) 120rpx),
linear-gradient(90deg, #07372f 0%, #005849 52%, #0aa385 100%);
}
.order-action-icon {
position: relative;
width: 52rpx;
height: 52rpx;
margin-right: 12rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
background: rgba(255, 255, 255, 0.18);
}
.guize-list {
width: 600rpx;
padding: 20rpx 20rpx 0;
@ -1230,45 +1451,44 @@
}
.shangxia-btn {
width: 132rpx;
height: 50rpx;
background-size: 100%;
width: 150rpx;
height: 64rpx;
line-height: 64rpx;
flex-shrink: 0;
background-size: 132rpx 50rpx;
background-position: center;
font-size: 20rpx;
font-weight: 700;
box-sizing: border-box;
}
.guize-box {
font-size: 20rpx;
font-weight: 700;
background: rgba(166, 255, 234, 1);
width: 140rpx;
height: 50rpx;
border-radius: 50rpx;
margin-right: 15rpx;
padding-left: 10rpx;
}
.refresh-box {
font-size: 20rpx;
font-weight: 700;
background: rgba(223, 255, 176, 1);
color: #0b6b5a;
width: 90rpx;
height: 50rpx;
width: 132rpx;
height: 64rpx;
line-height: 64rpx;
border-radius: 50rpx;
margin-right: 15rpx;
margin-right: 12rpx;
padding: 0 4rpx;
text-align: center;
box-sizing: border-box;
flex-shrink: 0;
}
.guize-box1 {
font-size: 20rpx;
font-weight: 700;
text-align: center;
width: 140rpx;
height: 50rpx;
width: 110rpx;
height: 64rpx;
line-height: 64rpx;
border-radius: 50rpx;
margin-right: 15rpx;
padding-left: 10rpx;
margin-right: 12rpx;
padding: 0 4rpx;
box-sizing: border-box;
flex-shrink: 0;
}
.product-popup-content {

56
components/tab-bar/tab-bar.vue

@ -2,13 +2,13 @@
<view class="tabbar-box">
<view class="bar-box" @click="clickBar(index)" v-for="(item,index) in tabList" :key="index" :class="item.shaking?'shaking':''">
<view class="red-dot" v-if="index == 0 && indexZhipaiCount > 0">
{{indexZhipaiCount}}
{{formatBadgeCount(indexZhipaiCount)}}
</view>
<view class="red-dot" v-if="index == 1 && indexWorkerCount > 0">
{{indexWorkerCount}}
{{formatBadgeCount(indexWorkerCount)}}
</view>
<view class="red-dot" v-if="index == 4 && indexMyCount > 0">
{{indexMyCount}}
{{formatBadgeCount(indexMyCount)}}
</view>
<view class="img-box" v-if="index != 2">
<img :src="item.isCheck?item.tabIconSelect:item.tabIcon" alt="" />
@ -88,8 +88,27 @@
}
},
methods: {
hasLogin() {
const token = uni.getStorageSync('hiver_token')
return !!(token && typeof token === 'string' && token.trim() && token !== 'null' && token !== 'undefined')
},
goLogin(index) {
const redirectKey = 'login_redirect_' + Date.now()
uni.setStorageSync(redirectKey, '/pages/index/index?tabIndex=' + index)
uni.navigateTo({
url: '/package2/login/login?redirect=' + redirectKey
})
},
formatBadgeCount(count) {
const value = Number(count) || 0
return value > 99 ? '99+' : value
},
//tab
clickBar(index) {
if (index !== 0 && !this.hasLogin()) {
this.goLogin(index)
return
}
for (let i = 0; i < this.tabList.length; i++) {
if (index == i) {
@ -208,18 +227,27 @@
flex: 1;
position: relative;
}
.red-dot{
width: 15px;
height: 15px;
border-radius: 15px;
line-height: 15px;
text-align: center;
color: #fff;
.red-dot {
position: absolute;
top: 5px;
right: 10px;
background: red;
font-size: 10px;
top: 10rpx;
right: 24rpx;
z-index: 2;
min-width: 34rpx;
height: 34rpx;
padding: 0 10rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 999rpx;
box-sizing: border-box;
text-align: center;
color: #ffffff;
background: linear-gradient(135deg, #ff8a1f 0%, #ff3f5f 100%);
border: 4rpx solid rgba(255, 255, 255, 0.96);
box-shadow: 0 8rpx 18rpx rgba(255, 63, 95, 0.34);
font-size: 20rpx;
font-weight: 900;
font-family: Arial, 'PingFang SC', sans-serif;
}
.img-box {

Loading…
Cancel
Save