wangfukang 13 hours ago
parent
commit
c63a4dba8b
  1. 15
      components/tab-bar/delivery.vue
  2. 2
      components/tab-bar/myCenter.vue
  3. 209
      components/tab-bar/release.vue

15
components/tab-bar/delivery.vue

@ -615,6 +615,15 @@
}
},
methods: {
getCurrentRegionId() {
try {
const area = uni.getStorageSync('area')
if (!area) return ''
return (typeof area == 'string' ? JSON.parse(area) : area).id || ''
} catch (e) {
return ''
}
},
getPickupPictures(item) {
const pictures = item && item.getPictures
if (!pictures) return []
@ -721,7 +730,7 @@
this.isOnLine = uni.getStorageSync('worker').isOnLine
this.zhipaiCheck = uni.getStorageSync('worker').getPushOrder == 1 ? true : false
if (uni.getStorageSync('area')) {
this.searchForm.regionId = JSON.parse(uni.getStorageSync('area')).id;
this.searchForm.regionId = this.getCurrentRegionId();
}
if (uni.getStorageSync('worker')) {
this.searchForm.workerId = uni.getStorageSync('worker').workerId
@ -792,8 +801,9 @@
loadWorkerRules(openAfterLoad) {
const worker = uni.getStorageSync('worker')
if (!worker || !worker.workerId) return
const regionId = this.getCurrentRegionId()
let that = this
that.tui.request("/app/workerRelaPrice/getByWorkerId?workerId=" + worker.workerId,
that.tui.request("/app/workerRelaPrice/getByWorkerId?workerId=" + worker.workerId + "&regionId=" + regionId,
"GET", {}, false, true).then((res) => {
if (res.code == 200) {
let list = res.result && res.result.workerRelaPriceList ? res.result.workerRelaPriceList : []
@ -1019,6 +1029,7 @@
}
let submitData = {
userId: uni.getStorageSync('id'),
regionId: this.getCurrentRegionId(),
workerRelaPriceList: this.selectRuleList,
getPushOrder: this.zhipaiCheck ? 1 : 0
};

2
components/tab-bar/myCenter.vue

@ -516,7 +516,7 @@
},
submitProfile(nickname) {
this.profileSaving = true
this.tui.request('/user/profile', 'POST', {
this.tui.request('/user/miniProfile', 'POST', {
nickname,
avatar: this.editAvatar || ''
}, false, false).then((res) => {

209
components/tab-bar/release.vue

@ -21,6 +21,17 @@
<text style="margin-top: 6rpx;">发布</text>
</view>
</view>
</view>
<scroll-view
class="page-scroll"
scroll-y
refresher-enabled
:refresher-triggered="refreshing"
:style="{ paddingTop: headerHeight + 'px' }"
:lower-threshold="120"
@refresherrefresh="onPullRefresh"
@scrolltolower="loadMore"
>
<view class="category-row">
<view
class="category-card"
@ -30,15 +41,13 @@
@tap="selectCategory(item.tone)"
>
<view class="hot-category-icon">
<image class="hot-category-img" :src="item.icon" mode="aspectFit"></image>
<image class="hot-category-img" :src="getReleaseChannelIcon(item)" mode="aspectFit"></image>
</view>
<view class="category-badge" v-if="item.tone === 'mine' && myCircleUnread > 0">{{formatBadge(myCircleUnread)}}</view>
<view class="hot-category-name">{{item.name}}</view>
<view class="hot-category-desc">{{item.desc}}</view>
</view>
</view>
</view>
<scroll-view class="page-scroll" scroll-y :style="{ paddingTop: headerHeight + 'px' }" :lower-threshold="120" @scrolltolower="loadMore">
<view class="sub-category-scroll" v-if="activeCategory !== 'mine'">
<view
class="sub-category"
@ -98,30 +107,40 @@
<image class="avatar" :src="displayAvatar(item)" mode="aspectFill"></image>
<view class="author-main">
<view class="author">{{displayName(item)}}</view>
<view class="time">{{item.createTime || ''}} · {{item.categoryName || '本校'}}</view>
<view class="time">{{item.createTime || ''}} · <text class="time-category">{{item.categoryName || '本校'}}</text></view>
</view>
<view class="partner-action" v-if="canUsePartnerChat(item)" @tap.stop="goChat(item)">搭一下</view>
</view>
<view class="title">{{item.title}}</view>
<view class="content">{{item.contentText || stripHtml(item.content)}}</view>
<view v-if="getImages(item).length" class="image-grid" :class="'image-grid--' + Math.min(getImages(item).length, 3)">
<view v-if="getImages(item).length === 1" class="image-grid image-grid--1">
<image
v-for="(pic, index) in getImages(item).slice(0, 3)"
:key="pic"
:src="pic"
:mode="getImages(item).length === 1 ? 'aspectFit' : 'aspectFill'"
:style="getPostImageStyle(pic, getImages(item).length)"
@load="onPostImageLoad(pic, $event)"
@tap.stop="previewImages(item, index)"
:src="getImages(item)[0]"
mode="aspectFit"
:style="getPostImageStyle(getImages(item)[0], 1)"
@load="onPostImageLoad(getImages(item)[0], $event)"
@tap.stop="previewImages(item, 0)"
></image>
</view>
<scroll-view v-else-if="getImages(item).length > 1" scroll-x class="image-scroll" @tap.stop>
<view class="image-scroll-inner">
<image
class="image-scroll-item"
v-for="(pic, index) in getImages(item)"
:key="pic"
:src="pic"
mode="aspectFill"
@tap.stop="previewImages(item, index)"
></image>
</view>
</scroll-view>
<view class="tag-row" v-if="getTags(item).length">
<text v-for="tag in getTags(item)" :key="tag">{{tag}}</text>
</view>
<view class="partner-info" v-if="item.postType === 'partner'">
<text>{{item.location || '地点待定'}}</text>
<text>{{item.activityTime || '时间可商量'}}</text>
<text>{{item.joinedCount || 0}}/{{item.targetCount || '不限'}} 人联系</text>
<text>人数 {{item.targetCount ? item.targetCount + '人' : '不限'}}</text>
</view>
<view class="contact-row" v-if="item.contactWechat || item.contactPhone">
<text v-if="item.contactWechat">微信 {{item.contactWechat}}</text>
@ -223,12 +242,17 @@
{ tone: 'sport', name: '运动搭子', desc: '约球夜跑', icon: 'https://jewel-shop.oss-cn-beijing.aliyuncs.com/01444d0812c544fe9cde7cbbb919b473.png' },
{ tone: 'mine', name: '我的圈子', desc: '消息动态', icon: 'https://jewel-shop.oss-cn-beijing.aliyuncs.com/430e4ae880574845b7d028bd96abde02.jpg' }
]
const RELEASE_ICON_CACHE_KEY = 'release_channel_icon_cache_v1'
const RELEASE_ICON_CACHE_TTL = 30 * 24 * 60 * 60 * 1000
const RELEASE_ICON_CACHE_LIMIT = 12
const releaseIconDownloading = {}
export default {
data() {
return {
statusBarHeight: 24,
channels: CHANNELS,
releaseChannelIcons: {},
activeCategory: 'wall',
activeCategoryId: '',
keyword: '',
@ -239,6 +263,7 @@
pageSize: 10,
totalPages: 1,
loading: false,
refreshing: false,
inited: false,
matching: false,
showMatchPanel: false,
@ -260,7 +285,7 @@
},
computed: {
headerHeight() {
return this.statusBarHeight + (uni.upx2px ? uni.upx2px(424) : 212)
return this.statusBarHeight + (uni.upx2px ? uni.upx2px(204) : 102)
},
hasMore() {
return this.pageNum < this.totalPages
@ -289,6 +314,9 @@
return '支持关键词和热门标签模糊匹配'
}
},
created() {
this.applyCachedReleaseChannelIcons()
},
mounted() {
if (uni.getMenuButtonBoundingClientRect) {
this.statusBarHeight = uni.getMenuButtonBoundingClientRect().top || this.statusBarHeight
@ -302,6 +330,136 @@
if (this.reactionBurstTimer) clearTimeout(this.reactionBurstTimer)
},
methods: {
getReleaseChannelIcon(item) {
if (!item) return ''
return this.releaseChannelIcons[item.tone] || item.icon || ''
},
getReleaseIconCache() {
const cache = uni.getStorageSync(RELEASE_ICON_CACHE_KEY)
return cache && typeof cache === 'object' ? cache : {}
},
saveReleaseIconCache(cache) {
uni.setStorageSync(RELEASE_ICON_CACHE_KEY, cache)
},
isSavedFileExists(filePath) {
if (!filePath || filePath.indexOf('__tmp__') !== -1) return false
try {
const fs = (uni.getFileSystemManager && uni.getFileSystemManager())
|| (typeof wx !== 'undefined' && wx.getFileSystemManager ? wx.getFileSystemManager() : null)
if (fs && fs.accessSync) {
fs.accessSync(filePath)
return true
}
} catch (e) {
return false
}
return true
},
isReleaseIconCacheValid(cacheItem) {
return !!(cacheItem
&& Date.now() - Number(cacheItem.savedAt || 0) < RELEASE_ICON_CACHE_TTL
&& this.isSavedFileExists(cacheItem.path))
},
applyCachedReleaseChannelIcons() {
const cache = this.getReleaseIconCache()
CHANNELS.forEach((item) => {
const imageUrl = item.icon
const cacheItem = cache[imageUrl]
if (this.isReleaseIconCacheValid(cacheItem)) {
this.$set(this.releaseChannelIcons, item.tone, cacheItem.path)
return
}
if (cacheItem && cacheItem.path) {
delete cache[imageUrl]
}
this.$set(this.releaseChannelIcons, item.tone, imageUrl)
this.cacheReleaseChannelIcon(item.tone, imageUrl)
})
this.pruneReleaseIconCache(cache, CHANNELS.map(item => item.icon))
},
cacheReleaseChannelIcon(tone, imageUrl) {
if (releaseIconDownloading[imageUrl]) return
releaseIconDownloading[imageUrl] = true
uni.downloadFile({
url: imageUrl,
success: (downloadRes) => {
if (downloadRes.statusCode !== 200 || !downloadRes.tempFilePath) {
this.$set(this.releaseChannelIcons, tone, imageUrl)
delete releaseIconDownloading[imageUrl]
return
}
uni.saveFile({
tempFilePath: downloadRes.tempFilePath,
success: (saveRes) => {
const cache = this.getReleaseIconCache()
const oldCacheItem = cache[imageUrl]
if (oldCacheItem && oldCacheItem.path && oldCacheItem.path !== saveRes.savedFilePath) {
uni.removeSavedFile({
filePath: oldCacheItem.path,
fail: () => {}
})
}
cache[imageUrl] = {
path: saveRes.savedFilePath,
savedAt: Date.now()
}
this.saveReleaseIconCache(cache)
this.$set(this.releaseChannelIcons, tone, saveRes.savedFilePath)
},
fail: () => {
this.$set(this.releaseChannelIcons, tone, imageUrl)
},
complete: () => {
delete releaseIconDownloading[imageUrl]
}
})
},
fail: () => {
this.$set(this.releaseChannelIcons, tone, imageUrl)
delete releaseIconDownloading[imageUrl]
},
complete: (downloadRes) => {
if (!downloadRes || downloadRes.statusCode !== 200) {
this.$set(this.releaseChannelIcons, tone, imageUrl)
delete releaseIconDownloading[imageUrl]
}
}
})
},
pruneReleaseIconCache(cache, activeUrls) {
const activeUrlMap = activeUrls.reduce((result, url) => {
result[url] = true
return result
}, {})
const now = Date.now()
Object.keys(cache).forEach((url) => {
const item = cache[url]
const isExpired = !this.isReleaseIconCacheValid(item)
if (isExpired && !activeUrlMap[url]) {
item && item.path && uni.removeSavedFile({
filePath: item.path,
fail: () => {}
})
delete cache[url]
}
})
const urls = Object.keys(cache).sort((a, b) => Number(cache[a].savedAt || now) - Number(cache[b].savedAt || now))
while (urls.length > RELEASE_ICON_CACHE_LIMIT) {
const url = urls.shift()
if (activeUrlMap[url]) {
urls.push(url)
if (urls.every(itemUrl => activeUrlMap[itemUrl])) break
continue
}
const item = cache[url]
item && item.path && uni.removeSavedFile({
filePath: item.path,
fail: () => {}
})
delete cache[url]
}
this.saveReleaseIconCache(cache)
},
init() {
if (this.inited && this.loading) return
this.inited = true
@ -354,6 +512,10 @@
this.myCircleUnread = Number(summary.myCircleUnread || summary.campusUnread) || 0
},
selectCategory(tone) {
if (tone === 'mine') {
uni.navigateTo({ url: '/package1/campus/myCampusPosts' })
return
}
if (this.activeCategory === tone) return
this.activeCategory = tone
this.activeCategoryId = ''
@ -427,6 +589,16 @@
this.posts = []
this.loadPosts()
},
onPullRefresh() {
if (this.refreshing) return
if (this.loading) return
this.refreshing = true
this.loadUnread()
this.pageNum = 1
this.totalPages = 1
this.posts = []
this.loadPosts()
},
loadMore() {
if (this.loading || !this.hasMore) return
this.pageNum += 1
@ -459,6 +631,7 @@
this.posts = this.pageNum === 1 ? records : this.posts.concat(records)
}).finally(() => {
this.loading = false
this.refreshing = false
})
},
getImages(item) {
@ -515,7 +688,7 @@
return item && item.userAvatar ? item.userAvatar : this.defaultAvatar
},
canUsePartnerChat(item) {
return !!(item && item.postType === 'partner' && item.partnerType !== 'game')
return false
},
getReactionCount(item, emoji) {
if (!item || !item.reactionCounts) return 0
@ -617,7 +790,7 @@
.search-input { flex: 1; height: 62rpx; margin-left: 9rpx; color: #26302c; font-size: 22rpx; line-height: 62rpx; }
.placeholder { color: #a0a6a4; }
.search-button { width: 94rpx; height: 56rpx; margin-right: 5rpx; border-radius: 30rpx; background: linear-gradient(135deg, #2bd398, #0db779); box-shadow: 0 7rpx 15rpx rgba(20, 182, 123, .24); color: #fff; font-size: 21rpx; font-weight: 800; line-height: 56rpx; text-align: center; }
.category-row { display: grid; grid-template-columns: repeat(5, 1fr); gap: 14rpx; margin-top: 18rpx; padding: 10rpx 24rpx 20rpx; }
.category-row { display: grid; grid-template-columns: repeat(5, 1fr); gap: 14rpx; padding: 10rpx 24rpx 20rpx; }
.category-card { position: relative; height: 170rpx; display: flex; flex-direction: column; align-items: center; justify-content: center; border-radius: 24rpx; background: linear-gradient(145deg, #ffffff, #edf5ff); text-align: center; box-shadow: 0 10rpx 24rpx rgba(35, 74, 61, 0.075); border: 2rpx solid transparent; box-sizing: border-box; }
.category-card.active { border-color: rgba(34, 191, 134, 0.55); box-shadow: 0 14rpx 30rpx rgba(34, 191, 134, 0.14); transform: translateY(-3rpx); }
.category-badge { position: absolute; right: 8rpx; top: 8rpx; min-width: 32rpx; height: 32rpx; line-height: 32rpx; padding: 0 8rpx; border-radius: 999rpx; background: #ff5b5b; color: #fff; font-size: 19rpx; box-sizing: border-box; }
@ -677,6 +850,7 @@
.author-main { flex: 1; margin-left: 14rpx; min-width: 0; }
.author { font-size: 26rpx; font-weight: 700; color: #263d38; }
.time { margin-top: 4rpx; font-size: 21rpx; color: #93a09c; }
.time-category { color: #56cfa4; font-weight: 800; }
.partner-action { padding: 10rpx 18rpx; border-radius: 999rpx; background: #34c7a2; color: #fff; font-size: 23rpx; }
.title { margin-top: 20rpx; font-size: 31rpx; font-weight: 800; color: #162d28; }
.content { margin-top: 12rpx; font-size: 26rpx; color: #51645f; line-height: 1.6; }
@ -686,6 +860,9 @@
.image-grid--3 { grid-template-columns: repeat(3, 1fr); }
.image-grid image { width: 100%; height: 190rpx; max-width: 100%; border-radius: 20rpx; background: #eef5f3; }
.image-grid--1 image { max-width: 560rpx; max-height: 360rpx; background: transparent; }
.image-scroll { width: 100%; margin-top: 18rpx; white-space: nowrap; }
.image-scroll-inner { display: inline-flex; gap: 8rpx; padding-right: 4rpx; }
.image-scroll-item { flex: 0 0 208rpx; width: 208rpx; height: 190rpx; border-radius: 20rpx; background: #eef5f3; }
.tag-row { margin-top: 16rpx; display: flex; flex-wrap: wrap; gap: 10rpx; }
.tag-row text { padding: 8rpx 16rpx; border-radius: 999rpx; background: #eefaf6; color: #2f9a81; font-size: 22rpx; }
.partner-info { margin-top: 14rpx; display: flex; flex-wrap: wrap; gap: 12rpx; color: #71807c; font-size: 22rpx; }

Loading…
Cancel
Save