tianyi 7 days ago
parent
commit
d28e7fe158
  1. 12
      common/fishMarketApi.js
  2. 19
      components/tab-bar/postList.vue
  3. 35
      package1/address/addressList.vue
  4. 121
      package1/buyFood/buyFood.vue
  5. 25
      package1/components/delivery-time-op/delivery-time-op.vue
  6. 13
      package1/order/orderDetail.vue
  7. 9
      package1/runErrand/runErrand.vue
  8. 5
      package1/tabbar/fishRelease.vue
  9. 7
      package2/IdleTrad/chat.vue
  10. 270
      package2/IdleTrad/detail.vue
  11. 92
      package2/IdleTrad/sessionList.vue
  12. 2
      package2/group/groupBuyList.vue
  13. 7
      package2/group/groupBuySingle.vue
  14. 4
      package2/group/studentStoreList.vue
  15. 13
      package2/myCenter/myPost.vue
  16. 22
      package2/seckill/seckillGroup.vue

12
common/fishMarketApi.js

@ -86,6 +86,10 @@ export function getFishUnreadSummary() {
return tui.request('/app/fishmarket/unread/summary', 'GET', {}, false, true, true).then(unwrap)
}
export function markAllFishUnreadRead() {
return tui.request('/app/fishmarket/unread/read-all', 'POST', {}, false, false, true).then(unwrap)
}
export function deleteFishComment(id) {
return tui.request(`/app/fishmarket/comments/${id}`, 'DELETE', {}, false, false, true).then(unwrap)
}
@ -142,10 +146,18 @@ export function pageMyFishSessions(data = {}) {
return tui.request('/app/fishmarket/my/sessions', 'POST', data, false, false, true).then(unwrap)
}
export function deleteMyFishSessionMessage(id) {
return tui.request(`/app/fishmarket/my/sessions/${id}`, 'DELETE', {}, false, false, true).then(unwrap)
}
export function pageMyFishMessageComments(data = {}) {
return tui.request('/app/fishmarket/my/message-comments', 'POST', data, false, false, true).then(unwrap)
}
export function deleteMyFishCommentMessage(id) {
return tui.request(`/app/fishmarket/my/message-comments/${id}`, 'DELETE', {}, false, false, true).then(unwrap)
}
export function pageMyFishComments(data = {}) {
return tui.request('/app/fishmarket/my/comments', 'POST', data, false, false, true).then(unwrap)
}

19
components/tab-bar/postList.vue

@ -120,6 +120,10 @@
></uni-icons>
<text>{{item.xiangyao}}</text>
</view>
<view class="browse-count">
<uni-icons type="eye" size="18" color="#a5aeab"></uni-icons>
<text>{{item.browseCount}}</text>
</view>
</view>
</view>
</view>
@ -208,7 +212,7 @@
imageKey: 'graduation',
action: 'mine'
}],
baseCategories: ['推荐', '最新'],
baseCategories: ['推荐', '最新', '热门'],
categoryList: [],
goodsList: [],
pageNum: 1,
@ -518,7 +522,7 @@
const category = this.categories[this.categoryIndex]
const categoryItem = this.categoryList.find(item => item.name == category)
const area = this.getArea()
const sortType = this.sortType || (category == '附近' ? 'school' : (category == '最新' ? 'latest' : 'hot'))
const sortType = category == '热门' ? 'favorite' : (category == '最新' ? 'latest' : (this.sortType || (category == '附近' ? 'school' : 'hot')))
const query = {
pageNum: this.pageNum,
pageSize: this.pageSize,
@ -553,6 +557,7 @@
price: isWant ? (item.expectedPrice || 0) : (item.price || 0),
originalPrice: item.originPrice,
xiangyao: item.likeCount || 0,
browseCount: item.browseCount || 0,
distance: item.distance || '本校',
icon: item.userAvatar || '/static/images/img/songshu.png',
shopName: item.userName || '校园同学',
@ -985,6 +990,7 @@
}
.category-row {
margin-top: -15rpx;
height: 80rpx;
display: flex;
align-items: center;
@ -1193,6 +1199,15 @@
font-size: 17rpx;
}
.browse-count {
margin-left: 10rpx;
display: flex;
align-items: center;
gap: 3rpx;
color: #a1aaa6;
font-size: 17rpx;
}
.page-like-effect {
position: fixed;
top: 0;

35
package1/address/addressList.vue

@ -39,9 +39,10 @@
</view>
<!-- 新增地址弹出层 -->
<uni-popup ref="addBookPopup" background-color="#fff">
<view class="book-popup-content">
<view style="height: 80rpx;line-height: 80rpx;font-size: 36rpx;font-weight: 700;text-align: center;">
<view class="book-popup-content" @tap.stop @touchmove.stop>
<view class="book-popup-title">
{{addressForm.id ? '编辑地址' : '填写地址'}}
<uni-icons type="closeempty" size="24" color="#333" class="book-popup-close" @tap="closeAddBookPopup"></uni-icons>
</view>
<view class="area-select" @tap="openAreaPopup">
<text v-if="areaTitleInput">{{areaTitleInput}}</text>
@ -70,7 +71,7 @@
</view>
</uni-popup>
<uni-popup ref="areaPopup" type="center" background-color="#fff">
<view class="area-popup-content">
<view class="area-popup-content" @tap.stop @touchmove.stop.prevent>
<view class="area-popup-title">
<text>选择楼座区域</text>
<uni-icons type="closeempty" size="22" color="#333" @tap="closeAreaPopup"></uni-icons>
@ -86,7 +87,7 @@
:cursor-spacing="160"
/>
</view>
<scroll-view scroll-y class="area-result-list">
<scroll-view scroll-y class="area-result-list" @touchmove.stop>
<view v-if="filteredAreaTitleList.length === 0" class="area-result-empty">
未找到匹配的楼座
</view>
@ -264,16 +265,19 @@
this.$refs.addBookPopup.open('bottom');
},
openAreaPopup() {
this.areaSearchInput = this.areaTitleInput;
this.areaSearchInput = '';
this.getAreaList();
this.$refs.areaPopup.open();
},
closeAreaPopup() {
this.$refs.areaPopup.close();
},
closeAddBookPopup() {
this.$refs.addBookPopup.close();
},
selectAreaTitle(title) {
this.areaTitleInput = title;
this.areaSearchInput = title;
this.areaSearchInput = '';
this.closeAreaPopup();
},
onFloorInput(e) {
@ -464,6 +468,25 @@
padding-top: 40rpx;
}
.book-popup-title {
height: 80rpx;
line-height: 80rpx;
font-size: 36rpx;
font-weight: 700;
text-align: center;
position: relative;
}
.book-popup-close {
position: absolute;
right: 0;
top: 0;
width: 80rpx;
height: 80rpx;
line-height: 80rpx;
text-align: center;
}
.area-select {
margin-bottom: 20rpx;
display: flex;

121
package1/buyFood/buyFood.vue

@ -1,52 +1,56 @@
<template>
<!-- 代买饭页 -->
<view class="page1" :class="{'store-group-checkout': isStoreGroupOrder}">
<view class="title">
<view class="title-sreach">
<view class="back-btn" @tap="back" :style="{'top': menuButtonInfo.top +'px'}">
<uni-icons type="left" size="28"></uni-icons>
</view>
</view>
<view class="store-hero-effect" v-if="isStoreGroupOrder">
<view class="store-orb orb-a"></view>
<view class="store-orb orb-b"></view>
<view class="store-hero-copy">
<view class="store-hero-badge">团购到店</view>
<view class="store-hero-title">约上同学一起省</view>
<view class="store-hero-sub">支付后到店核销拼团更划算</view>
<page-meta :page-style="addressBookVisible ? 'overflow: hidden;' : 'overflow: visible;'"></page-meta>
<view class="page1" :class="{'store-group-checkout': isStoreGroupOrder, 'page1--locked': addressBookVisible}">
<view class="checkout-fixed-header" :class="{'checkout-fixed-header--store': isStoreGroupOrder}">
<view class="title">
<view class="title-sreach">
<view class="back-btn" @tap="back" :style="{'top': menuButtonInfo.top +'px'}">
<uni-icons type="left" size="28"></uni-icons>
</view>
</view>
<view class="store-verify-card">
<view class="verify-icon"></view>
<view>
<view class="verify-title">到店核销</view>
<view class="verify-sub">同校热拼</view>
<view class="store-hero-effect" v-if="isStoreGroupOrder">
<view class="store-orb orb-a"></view>
<view class="store-orb orb-b"></view>
<view class="store-hero-copy">
<view class="store-hero-badge">团购到店</view>
<view class="store-hero-title">约上同学一起省</view>
<view class="store-hero-sub">支付后到店核销拼团更划算</view>
</view>
<view class="store-verify-card">
<view class="verify-icon"></view>
<view>
<view class="verify-title">到店核销</view>
<view class="verify-sub">同校热拼</view>
</view>
</view>
<!-- <view class="store-float-tag tag-a">拼团价</view>
<view class="store-float-tag tag-b">同校热拼</view> -->
</view>
<!-- <view class="store-float-tag tag-a">拼团价</view>
<view class="store-float-tag tag-b">同校热拼</view> -->
</view>
</view>
<view class="tab-wrap" v-if="!isStoreGroupOrder">
<view class="tab1" v-if="isPaotui">
<img src="https://jewel-shop.oss-cn-beijing.aliyuncs.com/6b3a4d4c61ee42feb29e69d6fcfd2c1e.png" alt=""
class="tab-bg" />
<img src="https://jewel-shop.oss-cn-beijing.aliyuncs.com/1cbed0734a154a70b75cb84a811bd0b7.png" alt="" />
<view class="tab-hit-area">
<view class="tab-hit-item"></view>
<view class="tab-hit-item" @tap="isPaotui=!isPaotui"></view>
<view class="tab-wrap" v-if="!isStoreGroupOrder">
<view class="tab1" v-if="isPaotui">
<img src="https://jewel-shop.oss-cn-beijing.aliyuncs.com/6b3a4d4c61ee42feb29e69d6fcfd2c1e.png" alt=""
class="tab-bg" />
<img src="https://jewel-shop.oss-cn-beijing.aliyuncs.com/1cbed0734a154a70b75cb84a811bd0b7.png" alt="" />
<view class="tab-hit-area">
<view class="tab-hit-item"></view>
<view class="tab-hit-item" @tap="isPaotui=!isPaotui"></view>
</view>
</view>
</view>
<view class="tab1" v-else>
<img src="https://jewel-shop.oss-cn-beijing.aliyuncs.com/3b98dfb370eb4ddcb942b7942dedced2.png" alt=""
class="tab-bg" />
<img src="https://jewel-shop.oss-cn-beijing.aliyuncs.com/82627e6cedcf409a932d6afaafa19a4b.png" alt=""
class="tab-bg" />
<view class="tab-hit-area">
<view class="tab-hit-item" @tap="isPaotui=!isPaotui"></view>
<view class="tab-hit-item"></view>
<view class="tab1" v-else>
<img src="https://jewel-shop.oss-cn-beijing.aliyuncs.com/3b98dfb370eb4ddcb942b7942dedced2.png" alt=""
class="tab-bg" />
<img src="https://jewel-shop.oss-cn-beijing.aliyuncs.com/82627e6cedcf409a932d6afaafa19a4b.png" alt=""
class="tab-bg" />
<view class="tab-hit-area">
<view class="tab-hit-item" @tap="isPaotui=!isPaotui"></view>
<view class="tab-hit-item"></view>
</view>
</view>
</view>
</view>
<view class="checkout-header-holder" :class="{'checkout-header-holder--store': isStoreGroupOrder}"></view>
<view class="ziqu-box" v-if="isPaotui==false">
<view class="ziqu-xuanfu">
{{isStoreGroupOrder ? '到店信息' : '取餐信息'}}
@ -346,7 +350,7 @@
</view>
<!-- 地址簿弹出层 -->
<uni-popup ref="bookPopup" background-color="#fff" @change="onAddressPopupChange">
<view class="book-popup-content">
<view class="book-popup-content" @tap.stop>
<address-list v-if="addressBookVisible" @selectAddress="handleSelectAddress" @syncAddress="handleSyncAddress"
@close="closeAddressBook"></address-list>
</view>
@ -603,7 +607,8 @@
freeOrderEffectVisible: false,
freeOrderAmount: '0.00',
navigatingFromPayPopup: false,
isNavigatingToWorkerList: false
isNavigatingToWorkerList: false,
isSeckillOrder: false
}
},
components: {
@ -641,6 +646,7 @@
if (option.packageFee) {
this.totalPackageFee = parseFloat(option.packageFee) || 0;
}
this.isSeckillOrder = option.seckillOrder == 1 || option.seckillOrder === '1';
if (this.isStoreGroupOrder) {
this.isPaotui = false;
this.nowMake = false;
@ -1386,6 +1392,9 @@
if(this.isStoreGroupOrder){
payload.otherOrder = 2
}
if(this.isSeckillOrder){
payload.seckillOrder = 1
}
payload.regionId = JSON.parse(uni.getStorageSync('area')).id
this.tui.request("/mall/order/create", "POST", payload, false, false).then(res => {
uni.hideLoading();
@ -1526,11 +1535,41 @@
#F5F8F5;
}
.page1--locked {
height: 100vh;
overflow: hidden;
}
.checkout-fixed-header {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 344rpx;
z-index: 100;
overflow: hidden;
background: #F5F8F5;
}
.checkout-fixed-header--store {
height: 360rpx;
background: #fff0df;
}
.title {
background: url('https://jewel-shop.oss-cn-beijing.aliyuncs.com/8bc15960c2dc40268e295d6dd23aecce.png') no-repeat;
width: 100%;
height: 340rpx;
background-size: 100% 100%;
position: relative;
}
.checkout-header-holder {
height: 344rpx;
}
.checkout-header-holder--store {
height: 360rpx;
}
.title-sreach {

25
package1/components/delivery-time-op/delivery-time-op.vue

@ -10,7 +10,10 @@
:class="{ add: model }"
@tap.stop
>
<view class="title-model">{{ title }} <text @tap="close">x</text></view>
<view class="title-model">
{{ title }}
<text class="title-close" @tap.stop="close">×</text>
</view>
<view class="cont" :style="{ height: barHidth - 80 + 'rpx' }">
<!-- -->
<scroll-view class="day" :scroll-y="true">
@ -208,15 +211,21 @@ export default {
border-bottom: 2rpx solid #eee;
}
.title-model > text {
.title-close {
position: absolute;
right: 14rpx;
width: 46rpx;
height: 46rpx;
line-height: 38rpx;
background-color: #ccc;
color: #fff;
top: 50%;
right: 24rpx;
display: flex;
align-items: center;
justify-content: center;
width: 48rpx;
height: 48rpx;
background-color: #f2f5f3;
border-radius: 50%;
color: #9aa5a0;
font-size: 32rpx;
line-height: 1;
transform: translateY(-50%);
}
.cont {

13
package1/order/orderDetail.vue

@ -230,10 +230,10 @@
@tap="makeMeal" style="background: rgba(0, 35, 28, 1);color:rgba(166, 255, 234, 1);">
立即备餐
</view>
<view class="btn" style="width: 40%;" v-if="orderDetail.status == 2 && orderDetail.shopDelivery != 1" @tap="openAddFeePopup">
<view class="btn" :class="{'btn-full': isErrandDeliveryOrder(orderDetail)}" v-if="orderDetail.status == 2 && orderDetail.shopDelivery != 1" @tap="openAddFeePopup">
增加配送佣金
</view>
<view class="btn" style="width: 40%;" v-if="orderDetail.status == 2 && orderDetail.shopDelivery != 1" @tap="goAssignWorker">
<view class="btn" v-if="orderDetail.status == 2 && orderDetail.shopDelivery != 1 && !isErrandDeliveryOrder(orderDetail)" @tap="goAssignWorker">
改派配送员
</view>
<!-- <view class="btn">
@ -1421,6 +1421,9 @@
hasNoDeliveryWorker(item) {
return !item || !item.deliveryInfo || !item.deliveryInfo.workerId || item.deliveryInfo.status === 0;
},
isErrandDeliveryOrder(item) {
return item && item.deliveryInfo && item.deliveryInfo.deliveryType == 3;
},
isGroupSuccess(item) {
return item && item.groupInfo && (item.groupInfo.status == 1 || item.groupInfo.successTime);
},
@ -2689,6 +2692,12 @@
box-shadow: 0 14rpx 28rpx rgba(0, 191, 160, 0.12);
}
.btn-full {
flex-basis: 100%;
width: 100%;
min-width: 100%;
}
.box1 > view[style*="rgba(247, 248, 248"] {
background: linear-gradient(180deg, rgba(250, 255, 252, 0.96) 0%, rgba(255, 255, 255, 0.9) 100%) !important;
border: 1px solid rgba(166, 255, 234, 0.34);

9
package1/runErrand/runErrand.vue

@ -1,5 +1,6 @@
<template>
<!-- 代跑腿/快递页 -->
<page-meta :page-style="isBookPopupOpen ? 'overflow: hidden;' : 'overflow: visible;'"></page-meta>
<view class="page1">
<view class="title">
<view class="title-sreach">
@ -32,7 +33,7 @@
</view>
</view>
</view>
<view class="content">
<view class="content" :class="{'content--locked': isBookPopupOpen}">
<view class="" style="background: #fff;padding: 20rpx;">
<!-- 取货地址 -->
<view v-if="isKuaidi" class="dizhi" style="border-bottom: 1px solid #eee; padding-bottom: 20rpx; margin-bottom: 20rpx;">
@ -253,7 +254,7 @@
<!-- 收货/取货地址簿弹出层 -->
<uni-popup ref="bookPopup" background-color="#fff" @change="onBookPopupChange">
<view class="book-popup-content">
<view class="book-popup-content" @tap.stop>
<address-list v-if="addressBookVisible" @selectAddress="handleSelectAddress"
@syncAddress="handleSyncAddress" @shopAreaList="updateArea" @close="closeAddressBook"></address-list>
</view>
@ -1144,6 +1145,10 @@
height: 100%;
}
.content--locked {
overflow: hidden;
}
.tab1 {
width: 100%;
height: 160rpx;

5
package1/tabbar/fishRelease.vue

@ -16,7 +16,7 @@
<view class="form-card">
<view class="field" id="fieldTitle">
<view class="label">标题</view>
<input v-model.trim="form.title" maxlength="10" placeholder="最多10个字" />
<input v-model.trim="form.title" maxlength="30" placeholder="最多30个字" />
</view>
<view class="field price-row" id="fieldPrice">
@ -423,11 +423,12 @@
const phone = String(this.form.phone || '').trim()
if (!title) return '请填写标题'
if (title.length < 2) return '标题至少2个字'
if (title.length > 10) return '标题最多10个字'
if (title.length > 30) return '标题最多30个字'
if (this.selectedCategoryIndex < 0) return '请选择分类'
if (!price) return this.publishType == 'sell' ? '请填写售价' : '请填写预算'
if (!this.isValidPrice(price)) return this.publishType == 'sell' ? '售价必须大于0且最多2位小数' : '预算必须大于0且最多2位小数'
if (originPrice && !this.isValidAmount(originPrice)) return '原价最多2位小数'
if (this.publishType == 'sell' && originPrice && Number(price) > Number(originPrice)) return '售价不得大于原价'
if (this.publishType == 'sell' && this.form.images.length == 0) return '请至少上传1张商品图片'
if (this.publishType == 'want' && this.form.images.length > 1) return '求购最多上传1张图片'
if (!contentText) return this.publishType == 'sell' ? '请填写商品介绍' : '请填写求购内容'

7
package2/IdleTrad/chat.vue

@ -34,7 +34,7 @@
:key="item.id"
:id="'msg-' + item.id"
>
<image class="avatar" :src="item.mine ? myAvatar : peerAvatar" mode="aspectFill"></image>
<image class="avatar" :src="defaultAvatar" mode="aspectFill"></image>
<view class="message-main">
<view class="bubble text-bubble" :class="{ failed: item.localState == 'failed' }" v-if="item.messageType == 1">{{item.content}}</view>
<view class="bubble image-bubble" :class="{ failed: item.localState == 'failed' }" v-else>
@ -88,8 +88,7 @@
draft: '',
scrollIntoView: 'chat-bottom',
selfId: String(uni.getStorageSync('id') || ''),
myAvatar: uni.getStorageSync('avatar') || 'https://jewel-shop.oss-cn-beijing.aliyuncs.com/801c569079da4540990c1cc634186fdd.png',
defaultAvatar: 'https://jewel-shop.oss-cn-beijing.aliyuncs.com/801c569079da4540990c1cc634186fdd.png',
defaultAvatar: '/static/images/img/songshu.png',
socketReady: false
}
},
@ -117,7 +116,7 @@
return this.selfId == String(this.session.sellerId) ? '买家同学' : (this.goods.userName || '卖家同学')
},
peerAvatar() {
return (this.goods && this.goods.userAvatar) || this.defaultAvatar
return this.defaultAvatar
}
},
onLoad(options) {

270
package2/IdleTrad/detail.vue

@ -3,7 +3,7 @@
<view class="nav" :style="{ paddingTop: statusBarTop + 'px' }">
<view class="nav-btn" @tap="back"><uni-icons type="left" size="24" color="#18372f"></uni-icons></view>
<view class="nav-title">{{isWant ? '求购详情' : '闲置详情'}}</view>
<view class="nav-btn" @tap="share"><uni-icons type="redo" size="22" color="#18372f"></uni-icons></view>
<view class="nav-btn"></view>
</view>
<scroll-view scroll-y class="content-scroll" :style="{ paddingTop: navHeight + 'px' }">
@ -31,6 +31,9 @@
<view class="price">{{isWant ? '预算 ¥' : '¥'}}{{displayPrice}}</view>
<view class="origin" v-if="!isWant && goods.originPrice">¥{{goods.originPrice}}</view>
<view class="sale-status">{{saleStatusText}}</view>
<button class="card-share-btn" open-type="share">
<uni-icons type="redo" size="18" color="#21b886"></uni-icons>
</button>
</view>
<view class="title">{{goods.title}}</view>
<view class="meta">
@ -79,17 +82,18 @@
<image :src="item.userAvatar || defaultAvatar" mode="aspectFill"></image>
<view class="comment-main">
<view class="comment-name">
{{item.userName || '校园同学'}}
半径同学
<text v-if="item.sellerReply">卖家</text>
</view>
<view class="comment-content">{{item.content}}</view>
<view class="reply-list" v-if="item.replies && item.replies.length">
<view class="reply-item" v-for="reply in item.replies" :key="reply.id">
<text class="reply-name">{{reply.userName || '校园同学'}}</text>
<text class="reply-name">半径同学</text>
<text class="seller-badge" v-if="reply.sellerReply">卖家</text>
<text class="reply-target" v-if="reply.replyToUserName"> 回复 {{reply.replyToUserName}}</text>
<text>{{reply.content}}</text>
<text class="reply-action" @tap="replyComment(item, reply)">回复</text>
<text class="reply-action reply-delete" v-if="reply.userId == currentUserId" @tap="deleteComment(reply)">删除</text>
</view>
</view>
<view class="comment-actions">
@ -137,7 +141,7 @@
</view>
<view class="bar-action" v-if="!isWant" @tap="favorite">
<uni-icons :type="goods && goods.favorited ? 'star-filled' : 'star'" size="22" :color="goods && goods.favorited ? '#ffb22d' : '#59706a'"></uni-icons>
<text>收藏</text>
<text>收藏 {{favoriteCountText}}</text>
</view>
<view class="bar-action" @tap="reportGoods">
<uni-icons type="flag" size="22" color="#59706a"></uni-icons>
@ -145,6 +149,17 @@
</view>
<view class="consult-btn" @tap="consult">{{isWant ? '我有货' : '立即咨询'}}</view>
</view>
<view class="page-like-effect" v-if="pageLikeEffects.length">
<view
class="page-like-heart"
:class="effect.className"
:style="effect.style"
v-for="effect in pageLikeEffects"
:key="effect.id"
>
<view class="page-like-heart-shape"></view>
</view>
</view>
<ie-auth-dialog />
</view>
</template>
@ -164,6 +179,7 @@
} from '@/common/fishMarketApi.js'
import { getIeProfile } from '@/common/ieApi.js'
import { ensureIeVerifiedBeforeAction } from '@/common/ieRealNameAuth.js'
import { buildHomeSharePath } from '@/utils/sharePath.js'
import IeAuthDialog from '@/package2/components/ie-auth-dialog/ie-auth-dialog.vue'
export default {
@ -184,9 +200,13 @@
commentSubmitting: false,
replyTarget: {},
defaultAvatar: '',
defaultShareImage: '/static/images/img/songshu.png',
currentUserId: uni.getStorageSync('id') || '',
currentImageIndex: 0,
imageHeights: {}
imageHeights: {},
likeEffectSeq: 0,
likeEffectTimers: {},
pageLikeEffects: []
}
},
computed: {
@ -238,19 +258,47 @@
},
commentPlaceholder() {
return this.replyTarget && this.replyTarget.id ? '回复 ' + (this.replyTarget.userName || '校园同学') : '写下你的评论'
},
favoriteCountText() {
return this.goods && this.goods.favoriteCount ? this.goods.favoriteCount : 0
}
},
onLoad(options) {
this.id = options && options.id ? options.id : ''
this.detailType = options && options.type == 'want' ? 'want' : 'goods'
if (uni.getMenuButtonBoundingClientRect) {
this.statusBarTop = uni.getMenuButtonBoundingClientRect().top || this.statusBarTop
const rect = uni.getMenuButtonBoundingClientRect()
this.statusBarTop = rect.top || this.statusBarTop
}
this.load()
},
onShareAppMessage() {
return this.buildShareInfo()
},
onShareTimeline() {
const info = this.buildShareInfo()
return {
title: info.title,
query: info.path.split('?')[1] || '',
imageUrl: info.imageUrl
}
},
onUnload() {
Object.keys(this.likeEffectTimers || {}).forEach(key => {
clearTimeout(this.likeEffectTimers[key])
})
this.likeEffectTimers = {}
},
methods: {
back() {
uni.navigateBack()
const pages = getCurrentPages ? getCurrentPages() : []
if (pages && pages.length > 1) {
uni.navigateBack()
return
}
uni.reLaunch({
url: '/pages/index/index?tabIndex=3'
})
},
load() {
if (!this.id) return
@ -381,19 +429,48 @@
})
},
likeComment(item) {
const shouldAnimate = !item.liked
if (shouldAnimate) {
this.playLikeEffect()
}
toggleFishLike({ commentId: item.id, likeType: 'comment' }).then(res => {
if (!res) return
this.$set(item, 'liked', !!res.liked)
item.likeCount = Number(res.count) || 0
})
},
favorite() {
if (!this.goods) return
const shouldAnimate = !this.goods.favorited
if (shouldAnimate) {
this.playLikeEffect()
}
toggleFishFavorite(this.id).then(res => {
if (!res) return
this.$set(this.goods, 'favorited', !!res.favorited)
this.$set(this.goods, 'favoriteCount', Number(res.count) || 0)
})
},
playLikeEffect() {
const burstId = Date.now() + '-' + (++this.likeEffectSeq)
const tracks = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight']
const effects = tracks.map((name, index) => ({
id: burstId + '-' + index,
className: 'page-like-heart--' + name,
style: `left:${6 + ((index * 59) % 86)}%; animation-delay:${index * 95}ms;`
}))
this.pageLikeEffects = effects
const timerKey = 'page'
if (this.likeEffectTimers[timerKey]) {
clearTimeout(this.likeEffectTimers[timerKey])
}
this.likeEffectTimers[timerKey] = setTimeout(() => {
if (this.pageLikeEffects.length && String(this.pageLikeEffects[0].id).indexOf(burstId) === 0) {
this.pageLikeEffects = []
}
delete this.likeEffectTimers[timerKey]
}, 3050)
},
reportGoods() {
this.report({ complaintType: this.isWant ? 'want' : 'goods', goodsId: this.id })
},
@ -434,7 +511,27 @@
})
},
share() {
// #ifdef MP-WEIXIN
uni.showShareMenu({
withShareTicket: true,
menus: ['shareAppMessage', 'shareTimeline']
})
uni.showToast({ title: '请点击右上角分享', icon: 'none' })
// #endif
// #ifndef MP-WEIXIN
uni.showToast({ title: '请使用右上角分享', icon: 'none' })
// #endif
},
buildShareInfo() {
const title = this.goods && this.goods.title ? this.goods.title : (this.isWant ? '校园二手求购' : '校园二手商品')
const prefix = this.isWant ? '同学正在求购:' : '校园二手好物:'
const typeQuery = this.isWant ? '&type=want' : ''
const targetPath = `/package2/IdleTrad/detail?id=${this.id || ''}${typeQuery}`
return {
title: prefix + title,
path: buildHomeSharePath(targetPath),
imageUrl: this.imageList.length ? this.imageList[0] : this.defaultShareImage
}
},
copyText(text, title) {
if (!text) return
@ -554,6 +651,25 @@
font-weight: 800;
}
.card-share-btn {
width: 48rpx;
height: 48rpx;
margin: 0 0 0 12rpx;
padding: 0;
display: flex;
align-items: center;
justify-content: center;
border: 0;
border-radius: 24rpx;
background: #e8fbf3;
line-height: 48rpx;
flex-shrink: 0;
}
.card-share-btn::after {
border: 0;
}
.title {
margin-top: 16rpx;
font-size: 34rpx;
@ -752,6 +868,10 @@
font-weight: 900;
}
.reply-delete {
color: #ef4c3f;
}
.comment-actions {
margin-top: 10rpx;
display: flex;
@ -881,6 +1001,142 @@
line-height: 82rpx;
}
.page-like-effect {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow: hidden;
pointer-events: none;
z-index: 99999;
}
.page-like-heart {
position: absolute;
bottom: -230rpx;
width: 120rpx;
height: 120rpx;
opacity: 0;
transform-origin: center;
animation-duration: 2600ms;
animation-timing-function: cubic-bezier(.14, .66, .22, 1);
animation-fill-mode: forwards;
}
.page-like-heart-shape {
position: absolute;
left: 50%;
top: 50%;
width: 72%;
height: 72%;
background: linear-gradient(135deg, rgba(255, 176, 207, .72), rgba(255, 88, 148, .36));
border-radius: 18rpx 18rpx 10rpx 18rpx;
box-shadow:
0 18rpx 42rpx rgba(255, 104, 164, .28),
inset 14rpx 18rpx 28rpx rgba(255, 255, 255, .32);
filter: blur(.2rpx);
transform: translate(-50%, -50%) rotate(45deg);
}
.page-like-heart-shape::before,
.page-like-heart-shape::after {
content: '';
position: absolute;
width: 100%;
height: 100%;
border-radius: 50%;
background: inherit;
box-shadow: inherit;
}
.page-like-heart-shape::before {
left: -50%;
top: 0;
}
.page-like-heart-shape::after {
left: 0;
top: -50%;
}
.page-like-heart--one { width: 154rpx; height: 154rpx; animation-name: pageHeartFloatOne; }
.page-like-heart--two { width: 112rpx; height: 112rpx; animation-name: pageHeartFloatTwo; }
.page-like-heart--three { width: 188rpx; height: 188rpx; animation-name: pageHeartFloatThree; }
.page-like-heart--four { width: 92rpx; height: 92rpx; animation-name: pageHeartFloatFour; }
.page-like-heart--five { width: 136rpx; height: 136rpx; animation-name: pageHeartFloatFive; }
.page-like-heart--six { width: 82rpx; height: 82rpx; animation-name: pageHeartFloatSix; }
.page-like-heart--seven { width: 166rpx; height: 166rpx; animation-name: pageHeartFloatSeven; }
.page-like-heart--eight { width: 104rpx; height: 104rpx; animation-name: pageHeartFloatEight; }
.page-like-heart--three .page-like-heart-shape,
.page-like-heart--seven .page-like-heart-shape {
background: linear-gradient(135deg, rgba(255, 198, 220, .66), rgba(255, 103, 158, .28));
filter: blur(1rpx);
}
.page-like-heart--four .page-like-heart-shape,
.page-like-heart--six .page-like-heart-shape,
.page-like-heart--eight .page-like-heart-shape {
background: linear-gradient(135deg, rgba(255, 211, 226, .74), rgba(255, 126, 174, .32));
}
@keyframes pageHeartFloatOne {
0% { opacity: 0; transform: translate3d(0, 0, 0) scale(.68) rotate(-8deg); }
14% { opacity: .82; transform: translate3d(-18rpx, -92rpx, 0) scale(1) rotate(5deg); }
62% { opacity: .52; transform: translate3d(-72rpx, -370rpx, 0) scale(.94) rotate(-12deg); }
100% { opacity: 0; transform: translate3d(-112rpx, -650rpx, 0) scale(.72) rotate(-22deg); }
}
@keyframes pageHeartFloatTwo {
0% { opacity: 0; transform: translate3d(0, 0, 0) scale(.62) rotate(6deg); }
16% { opacity: .7; transform: translate3d(28rpx, -112rpx, 0) scale(.92) rotate(-6deg); }
64% { opacity: .44; transform: translate3d(96rpx, -350rpx, 0) scale(.82) rotate(12deg); }
100% { opacity: 0; transform: translate3d(146rpx, -600rpx, 0) scale(.62) rotate(22deg); }
}
@keyframes pageHeartFloatThree {
0% { opacity: 0; transform: translate3d(0, 0, 0) scale(.64) rotate(-4deg); }
12% { opacity: .64; transform: translate3d(8rpx, -86rpx, 0) scale(.94) rotate(7deg); }
60% { opacity: .38; transform: translate3d(-36rpx, -420rpx, 0) scale(.78) rotate(-12deg); }
100% { opacity: 0; transform: translate3d(-68rpx, -710rpx, 0) scale(.58) rotate(-24deg); }
}
@keyframes pageHeartFloatFour {
0% { opacity: 0; transform: translate3d(0, 0, 0) scale(.58) rotate(12deg); }
18% { opacity: .68; transform: translate3d(-26rpx, -124rpx, 0) scale(.86) rotate(-6deg); }
66% { opacity: .4; transform: translate3d(-112rpx, -320rpx, 0) scale(.72) rotate(14deg); }
100% { opacity: 0; transform: translate3d(-166rpx, -560rpx, 0) scale(.54) rotate(26deg); }
}
@keyframes pageHeartFloatFive {
0% { opacity: 0; transform: translate3d(0, 0, 0) scale(.64) rotate(-10deg); }
14% { opacity: .72; transform: translate3d(34rpx, -96rpx, 0) scale(.96) rotate(6deg); }
62% { opacity: .44; transform: translate3d(68rpx, -380rpx, 0) scale(.78) rotate(-10deg); }
100% { opacity: 0; transform: translate3d(104rpx, -650rpx, 0) scale(.58) rotate(-20deg); }
}
@keyframes pageHeartFloatSix {
0% { opacity: 0; transform: translate3d(0, 0, 0) scale(.52) rotate(8deg); }
20% { opacity: .64; transform: translate3d(6rpx, -132rpx, 0) scale(.8) rotate(-8deg); }
68% { opacity: .36; transform: translate3d(44rpx, -290rpx, 0) scale(.64) rotate(12deg); }
100% { opacity: 0; transform: translate3d(70rpx, -500rpx, 0) scale(.48) rotate(22deg); }
}
@keyframes pageHeartFloatSeven {
0% { opacity: 0; transform: translate3d(0, 0, 0) scale(.62) rotate(-8deg); }
13% { opacity: .62; transform: translate3d(-28rpx, -82rpx, 0) scale(.88) rotate(6deg); }
58% { opacity: .38; transform: translate3d(-86rpx, -390rpx, 0) scale(.72) rotate(-12deg); }
100% { opacity: 0; transform: translate3d(-132rpx, -680rpx, 0) scale(.52) rotate(-22deg); }
}
@keyframes pageHeartFloatEight {
0% { opacity: 0; transform: translate3d(0, 0, 0) scale(.56) rotate(10deg); }
18% { opacity: .66; transform: translate3d(38rpx, -118rpx, 0) scale(.84) rotate(-8deg); }
64% { opacity: .4; transform: translate3d(122rpx, -338rpx, 0) scale(.68) rotate(14deg); }
100% { opacity: 0; transform: translate3d(178rpx, -580rpx, 0) scale(.5) rotate(26deg); }
}
.bottom-space {
height: 170rpx;
}

92
package2/IdleTrad/sessionList.vue

@ -2,7 +2,10 @@
<view class="session-page">
<view class="header" :style="{ paddingTop: statusBarTop + 'px' }">
<view class="back" @tap="back"><uni-icons type="left" size="22" color="#15362f"></uni-icons></view>
<view class="title">我的咨询</view>
<view class="title-row">
<view class="title">我的咨询</view>
<view class="read-all-btn" v-if="chatUnread + commentUnread > 0" @tap="markAllRead">一键已读</view>
</view>
<view class="subtitle">我咨询的和咨询我的都在这里</view>
<view class="message-tabs">
<view class="message-tab" :class="{ active: activeTab == 'chat' }" @tap="switchTab('chat')">
@ -27,10 +30,11 @@
</view>
<view class="goods-meta">
<text v-if="item.goodsPrice !== ''">¥{{item.goodsPrice}}</text>
<text>{{item.lastChatTime || item.firstConsultTime || item.createTime || ''}}</text>
<text>{{item.displayTime}}</text>
</view>
<view class="session-desc">{{item.desc}}</view>
</view>
<view class="delete-btn" @tap.stop="deleteItem(item)">删除</view>
</view>
<view class="empty" v-if="!list.length && !loading">暂无咨询记录</view>
@ -45,7 +49,10 @@
import {
pageMyFishSessions,
pageMyFishMessageComments,
getFishUnreadSummary
deleteMyFishSessionMessage,
deleteMyFishCommentMessage,
getFishUnreadSummary,
markAllFishUnreadRead
} from '@/common/fishMarketApi.js'
export default {
@ -127,6 +134,42 @@
})
}).catch(() => {})
},
markAllRead() {
if (this.loading) return
uni.showModal({
title: '一键已读',
content: '确定将所有消息和留言标记为已读吗?',
confirmText: '已读',
success: (res) => {
if (!res.confirm) return
markAllFishUnreadRead().then(() => {
this.chatUnread = 0
this.commentUnread = 0
uni.$emit('fishUnreadChange', { chatUnread: 0, commentUnread: 0, fishUnread: 0 })
uni.showToast({ title: '已全部标记已读', icon: 'none' })
this.reload()
})
}
})
},
deleteItem(item) {
if (!item || !item.id) return
const isComment = this.activeTab == 'comment'
uni.showModal({
title: '删除记录',
content: isComment ? '确定删除这条留言提醒吗?' : '确定删除这条消息记录吗?',
confirmText: '删除',
confirmColor: '#e34d59',
success: (res) => {
if (!res.confirm) return
const request = isComment ? deleteMyFishCommentMessage : deleteMyFishSessionMessage
request(item.id).then(() => {
uni.showToast({ title: '删除成功', icon: 'none' })
this.reload()
})
}
})
},
formatBadgeCount(count) {
const value = Number(count) || 0
return value > 99 ? '99+' : value
@ -143,6 +186,7 @@
goodsTitle: session.displayTitle || '',
goodsCover: session.displayCover || '',
goodsPrice: session.displayPrice !== undefined && session.displayPrice !== null ? session.displayPrice : '',
displayTime: this.formatDisplayTime(session.lastChatTime || session.firstConsultTime || session.createTime),
desc: isWant ? (role == 'seller' ? '你正在响应这条求购' : '同学正在响应你的求购') : (role == 'seller' ? '买家正在咨询这件商品' : '你正在咨询这件商品')
}
})
@ -157,10 +201,18 @@
goodsTitle: comment.displayTitle || '',
goodsCover: comment.displayCover || '',
goodsPrice: comment.displayPrice !== undefined && comment.displayPrice !== null ? comment.displayPrice : '',
displayTime: this.formatDisplayTime(comment.createTime),
desc: (comment.replyToUserName ? (comment.userName || '校园同学') + ' 回复 ' + comment.replyToUserName + ':' : '') + (comment.content || '')
}
})
},
formatDisplayTime(value) {
if (!value) return ''
const text = String(value).replace(/T/g, ' ')
const match = text.match(/^(\d{4})-(\d{2})-(\d{2})\s+(\d{2}):(\d{2})/)
if (!match) return text
return `${match[1]}-${match[2]}-${match[3]} ${match[4]}:${match[5]}`
},
openItem(item) {
if (this.activeTab == 'comment') {
if (!item.goodsId) return
@ -202,12 +254,35 @@
align-items: center;
}
.title-row {
margin-top: 8rpx;
display: flex;
align-items: center;
justify-content: space-between;
}
.title {
flex: 1;
margin-top: 8rpx;
font-size: 42rpx;
font-weight: 900;
}
.title-row .title {
margin-top: 0;
}
.read-all-btn {
margin-left: 20rpx;
padding: 10rpx 20rpx;
border-radius: 24rpx;
background: #e8fbf3;
color: #18a878;
font-size: 22rpx;
font-weight: 900;
white-space: nowrap;
}
.subtitle {
margin-top: 8rpx;
color: #71857f;
@ -293,6 +368,17 @@
margin-left: 18rpx;
}
.delete-btn {
margin-left: 16rpx;
padding: 12rpx 18rpx;
border-radius: 22rpx;
background: #fff1f2;
color: #e34d59;
font-size: 22rpx;
font-weight: 900;
flex-shrink: 0;
}
.top-row {
display: flex;
align-items: center;

2
package2/group/groupBuyList.vue

@ -152,7 +152,7 @@
<text v-else>{{item._groupTip}}</text>
</view>
<view class="shop-deal1">
<text>{{item.saleCount != null ? item.saleCount : 0}}</text>人跟拼
已售{{item.saleCount != null ? item.saleCount : 0}}
</view>
</view>
<view class="self-delivery-row" v-if="item.supportShopDelivery == 1">

7
package2/group/groupBuySingle.vue

@ -46,7 +46,7 @@
<text :class="{'shop-status-disabled': !hasOpenKitchenVideo(shopItem)}" @tap.stop="goDetail('openKitchen')">
{{getOpenKitchenText(shopItem)}}
</text>
<text>{{getDineInText(shopItem)}}</text>
<text :class="{'shop-status-disabled': shopItem.supportDineIn != 1}">{{getDineInText(shopItem)}}</text>
</view>
<view class="shop-content-center">
<view class="shop-rate">
@ -3465,11 +3465,6 @@
white-space: nowrap;
}
text:last-child {
background: rgba(255, 116, 77, 0.12);
color: #ff744d;
}
.shop-status-disabled {
background: rgba(225, 231, 228, 0.72) !important;
color: #87938f !important;

4
package2/group/studentStoreList.vue

@ -85,7 +85,7 @@
<view @tap.stop="buyingye" v-if="item.status === 0" class="closed-mask">
<view class="closed-text">休息中</view>
</view>
<view class="rank-tag">热度 {{index + 1}}</view>
<view class="rank-tag">销量 {{item.saleCount != null ? item.saleCount : 0}}</view>
<view class="live-dot"></view>
<view class="shop-sticker">{{item.uiLiveText}}</view>
<view class="shop-top">
@ -1603,7 +1603,7 @@
border-radius: 999rpx;
background: #fff0dc;
color: #e96632;
font-size: 18rpx;
font-size: 20rpx;
font-weight: 900;
}

13
package2/myCenter/myPost.vue

@ -128,6 +128,11 @@
if (this.loadedOnce) {
this.reload()
}
if (uni.$off) uni.$off('fishMarketChanged', this.reload)
if (uni.$on) uni.$on('fishMarketChanged', this.reload)
},
onUnload() {
if (uni.$off) uni.$off('fishMarketChanged', this.reload)
},
methods: {
back() {
@ -194,8 +199,7 @@
const request = this.activeTab == 'goods'
? updateMyFishGoodsStatus({ goodsId: item.id, status })
: updateMyFishWantStatus({ wantId: item.id, status })
return request.then(res => {
if (!res && res !== true) return
return request.then(() => {
uni.showToast({ title: status == 3 ? '已删除' : (status == 2 ? '已下架' : '已上架'), icon: 'none' })
this.reload()
})
@ -280,7 +284,7 @@
if (item.saleStatus == 2) return '已预定'
if (item.saleStatus == 3) return '已卖出'
if (item.status == 2) return '已下架'
return '正常'
return '已上架'
},
handleCardAction(item) {
if (this.activeTab == 'favorites') {
@ -300,8 +304,7 @@
confirmColor: '#ef4c3f',
success: (res) => {
if (!res.confirm) return
toggleFishFavorite(item.goodsId).then(result => {
if (!result && result !== false) return
toggleFishFavorite(item.goodsId).then(() => {
uni.showToast({ title: '已取消收藏', icon: 'none' })
this.reload()
})

22
package2/seckill/seckillGroup.vue

@ -18,7 +18,7 @@
<view class="hero-sub">限时开抢 · 拼着更划算</view>
</view>
<view class="hero-card">
<view class="hero-bowl"></view>
<!-- <view class="hero-bowl"></view> -->
<view class="hero-badge">立即抢</view>
</view>
</view>
@ -269,6 +269,7 @@
shopPhone: item.shopPhone,
shopAddress: item.shopAddress,
getAreaId: item.getAreaId,
shoArea: item.shoArea,
attributeList: item.attributeList,
raw: item
}
@ -409,11 +410,11 @@
contactPhone: item.shopPhone,
shopPhone: item.shopPhone,
shopAddress: item.shopAddress,
shopArea: item.getAreaId
shopArea: item.shoArea || item.getAreaId
}
uni.navigateTo({
url: '/package1/buyFood/buyFood?cart=' + encodeURIComponent(JSON.stringify(cart)) +
'&shopItem=' + encodeURIComponent(JSON.stringify(shopItem)) + '&packageFee=0'
'&shopItem=' + encodeURIComponent(JSON.stringify(shopItem)) + '&packageFee=0&seckillOrder=1'
})
},
back() {
@ -576,20 +577,21 @@
}
.hero-card {
width: 230rpx;
height: 210rpx;
margin-top: 30rpx;
width: 200rpx;
height: 180rpx;
position: relative;
animation: heroFloat 3s ease-in-out infinite;
}
.hero-bowl {
width: 138rpx;
height: 138rpx;
margin: 24rpx auto 0;
width: 120rpx;
height: 120rpx;
margin: 14rpx auto 0;
border-radius: 50%;
background: linear-gradient(145deg, #fff 0%, #ffe8b9 100%);
color: #ff5630;
font-size: 60rpx;
font-size: 50rpx;
font-weight: 900;
line-height: 138rpx;
text-align: center;
@ -607,7 +609,7 @@
line-height: 48rpx;
text-align: center;
position: absolute;
right: 8rpx;
right: 42rpx;
bottom: 14rpx;
box-shadow: 0 10rpx 18rpx rgba(169, 40, 0, 0.18);
animation: badgeBeat 1.4s ease-in-out infinite;

Loading…
Cancel
Save