修改
@@ -1,6 +1,6 @@
|
|||||||
// const baseUrl = "https://api.collect.hs.hnzhwlkj.club/"; //这里放置url域名32044
|
// const baseUrl = "https://api.collect.hs.hnzhwlkj.club/"; //这里放置url域名32044
|
||||||
// const baseUrl = "https://api.collect.xyh.muzili.top/"; //这里放置url域名32044
|
// const baseUrl = "https://api.collect.xyh.muzili.top/"; //这里放置url域名32044
|
||||||
const baseUrl = "https://bsh.info.hb.hnzhwlkj.cn/"; //这里放置url域名32044
|
const baseUrl = "https://cb.hnxinyouhe.com/"; //这里放置url域名32044
|
||||||
// const baseUrl = "https://114.215.24.240:8106/api/v1/"; //这里放置url域名32044
|
// const baseUrl = "https://114.215.24.240:8106/api/v1/"; //这里放置url域名32044
|
||||||
export function request(options){//封装的requset
|
export function request(options){//封装的requset
|
||||||
let { url,data,method } = options;
|
let { url,data,method } = options;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ export default {
|
|||||||
home: 'home',
|
home: 'home',
|
||||||
square: 'square',
|
square: 'square',
|
||||||
publish: 'publish',
|
publish: 'publish',
|
||||||
message: 'message',
|
classify: 'classify',
|
||||||
mine: 'mine'
|
mine: 'mine'
|
||||||
},
|
},
|
||||||
navbar: {
|
navbar: {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ export default {
|
|||||||
home: '首页',
|
home: '首页',
|
||||||
square: '广场',
|
square: '广场',
|
||||||
publish: '发布',
|
publish: '发布',
|
||||||
message: '消息',
|
classify: '分类',
|
||||||
mine: '我的'
|
mine: '我的'
|
||||||
},
|
},
|
||||||
navbar: {
|
navbar: {
|
||||||
|
|||||||
@@ -0,0 +1,111 @@
|
|||||||
|
<template>
|
||||||
|
<view class="card">
|
||||||
|
<view class="card-left" @click="$emit('view', item)">
|
||||||
|
<image class="card-img" :src="thumb" mode="aspectFit"></image>
|
||||||
|
</view>
|
||||||
|
<view class="card-right">
|
||||||
|
<view class="card-title line2" @click="$emit('view', item)">{{ item.content}}</view>
|
||||||
|
<view class="sku" @click="$emit('view', item)">{{ item.sku.model }}</view>
|
||||||
|
<view class="meta" @click="$emit('view', item)">
|
||||||
|
<text class="tag">#{{ item.age}}</text>
|
||||||
|
</view>
|
||||||
|
<view class="price-row">
|
||||||
|
<view @click="$emit('view', item)">
|
||||||
|
<text class="price">¥{{ item.price}}</text>
|
||||||
|
<text class="origin">¥{{ item.sku.price }}</text>
|
||||||
|
</view>
|
||||||
|
<uni-icons @click="$emit('start', item)" :type="item.is_favorite ? 'star-filled' : 'star'" :color="item.is_favorite ? '#05b3a8' : '#333'" size="18"></uni-icons>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'ClassifyCard',
|
||||||
|
props: {
|
||||||
|
item: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
default: () => ({})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
thumb() {
|
||||||
|
const img = this.item.media?.[0]?.url_pull || this.item.cover || this.item.image?.[0]?.url_pull
|
||||||
|
return img || '/static/image/cp.png'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.card {
|
||||||
|
display: flex;
|
||||||
|
gap: 16rpx;
|
||||||
|
padding: 16rpx;
|
||||||
|
background: #fff;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
}
|
||||||
|
.card-left {
|
||||||
|
width: 180rpx;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.card-img {
|
||||||
|
width: 180rpx;
|
||||||
|
height: 180rpx;
|
||||||
|
background: #f5f5f5;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
}
|
||||||
|
.card-right {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10rpx;
|
||||||
|
}
|
||||||
|
.card-title {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #111;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
.line2 {
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.sku {
|
||||||
|
font-size: 22rpx;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
.price-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 10rpx;
|
||||||
|
}
|
||||||
|
.price {
|
||||||
|
font-size: 38rpx;
|
||||||
|
color: #00bfb2;
|
||||||
|
font-weight: 700;
|
||||||
|
margin-right: 10rpx;
|
||||||
|
}
|
||||||
|
.origin {
|
||||||
|
font-size: 22rpx;
|
||||||
|
color: #ccc;
|
||||||
|
text-decoration: line-through;
|
||||||
|
}
|
||||||
|
.meta {
|
||||||
|
display: flex;
|
||||||
|
gap: 10rpx;
|
||||||
|
}
|
||||||
|
.tag {
|
||||||
|
font-size: 22rpx;
|
||||||
|
color: #3BC6BD;
|
||||||
|
padding: 4rpx 28rpx;
|
||||||
|
background: rgb(59 198 189 / 0.1);
|
||||||
|
border-radius: 6rpx;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
@@ -0,0 +1,257 @@
|
|||||||
|
<template>
|
||||||
|
<view class="card-item">
|
||||||
|
<view class="user" @click="handleUserClick">
|
||||||
|
<image :src="item.user.avatar_pull || '/static/image/user.png'" class="avatar"></image>
|
||||||
|
<view class="info">
|
||||||
|
<view class="name">{{ item.user.nickname || '用户名' }}</view>
|
||||||
|
<view class="time">{{ item.created_at }}</view>
|
||||||
|
</view>
|
||||||
|
<button v-if="!ismysq" class="chat-btn" @click.stop="handleContact">联系门店</button>
|
||||||
|
<button
|
||||||
|
v-else
|
||||||
|
class="chat-btn"
|
||||||
|
:class="item.status==1 ? 'chat-btn1' : item.status==2 ? 'chat-btn2' : item.status==3 ? 'chat-btn3' : 'chat-btn4'"
|
||||||
|
@click.stop="handleContact"
|
||||||
|
>
|
||||||
|
{{ item.status==1 ? '已发布' : item.status==2 ? '审核中' : item.status==3 ? '未通过' : '已过期' }}
|
||||||
|
</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="content" @click="handleView">
|
||||||
|
<u-read-more :showHeight="80" ref="uReadMore" color="#999999" closeText="查看更多">
|
||||||
|
<rich-text :nodes="item.content" @load="handleContentLoad"></rich-text>
|
||||||
|
</u-read-more>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- <view class="tags" v-if="item.tag && item.tag.length">
|
||||||
|
<text v-for="(tag, index) in item.tag" :key="index">{{ tag }}</text>
|
||||||
|
</view> -->
|
||||||
|
<view class="tags">
|
||||||
|
<text>#{{ item.age}}</text>
|
||||||
|
</view>
|
||||||
|
<view class="imgs" v-if="item.media && item.media.length">
|
||||||
|
<image
|
||||||
|
v-for="(img, index) in item.media"
|
||||||
|
:key="index"
|
||||||
|
:src="getImgUrl(img)"
|
||||||
|
class="img"
|
||||||
|
mode="aspectFill"
|
||||||
|
@click.stop="previewImage(index)"
|
||||||
|
@longpress.stop="downloadImage(img)"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="location" v-if="item.location_name">
|
||||||
|
<uni-icons type="location" color="#999" size="18"></uni-icons>
|
||||||
|
<text>{{ item.location_name }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="comment" @click="handleComment">
|
||||||
|
评论({{ item.comment || 0 }})
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import uReadMore from '@/uni_modules/uview-ui/components/u-read-more/u-read-more.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'PostCard',
|
||||||
|
components: {
|
||||||
|
uReadMore
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
item: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
default: () => ({})
|
||||||
|
},
|
||||||
|
ismysq:{
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getImgUrl(img) {
|
||||||
|
if (!img) return '';
|
||||||
|
if (typeof img === 'string') return img;
|
||||||
|
return img.img_src || img.url_pull || img.url || '';
|
||||||
|
},
|
||||||
|
handleContentLoad() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.$refs.uReadMore) {
|
||||||
|
this.$refs.uReadMore.init();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
handleUserClick() {
|
||||||
|
this.$emit('userClick', this.item);
|
||||||
|
},
|
||||||
|
handleContact() {
|
||||||
|
this.$emit('contact', this.item);
|
||||||
|
},
|
||||||
|
handleView() {
|
||||||
|
this.$emit('view', this.item);
|
||||||
|
},
|
||||||
|
previewImage(index) {
|
||||||
|
if (!this.item.media || !this.item.media.length) return;
|
||||||
|
const urls = this.item.media.map(m => this.getImgUrl(m)).filter(Boolean);
|
||||||
|
uni.previewImage({
|
||||||
|
current: index,
|
||||||
|
urls
|
||||||
|
});
|
||||||
|
},
|
||||||
|
downloadImage(img) {
|
||||||
|
const url = this.getImgUrl(img);
|
||||||
|
if (!url) return;
|
||||||
|
uni.showActionSheet({
|
||||||
|
itemList: ['保存图片'],
|
||||||
|
success: (res) => {
|
||||||
|
if (res.tapIndex === 0) {
|
||||||
|
uni.showLoading({ title: '下载中...', mask: true });
|
||||||
|
uni.downloadFile({
|
||||||
|
url,
|
||||||
|
success: (downloadRes) => {
|
||||||
|
if (downloadRes.statusCode === 200) {
|
||||||
|
uni.saveImageToPhotosAlbum({
|
||||||
|
filePath: downloadRes.tempFilePath,
|
||||||
|
success: () => {
|
||||||
|
uni.hideLoading();
|
||||||
|
uni.showToast({ title: '保存成功', icon: 'success' });
|
||||||
|
},
|
||||||
|
fail: () => {
|
||||||
|
uni.hideLoading();
|
||||||
|
uni.showToast({ title: '保存失败', icon: 'none' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
uni.hideLoading();
|
||||||
|
uni.showToast({ title: '下载失败', icon: 'none' });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: () => {
|
||||||
|
uni.hideLoading();
|
||||||
|
uni.showToast({ title: '下载失败', icon: 'none' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
handleComment() {
|
||||||
|
this.$emit('comment', this.item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.card-item {
|
||||||
|
margin-bottom: 40rpx;
|
||||||
|
background: #fff;
|
||||||
|
padding: 20rpx;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user {
|
||||||
|
flex-direction: row;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
width: 110rpx;
|
||||||
|
height: 110rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
.info {
|
||||||
|
margin-left: 20rpx;
|
||||||
|
flex: 1;
|
||||||
|
.name {
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.time {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #777;
|
||||||
|
margin-top: 6rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.chat-btn {
|
||||||
|
padding: 0 26rpx;
|
||||||
|
height: 45rpx;
|
||||||
|
line-height: 45rpx;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
background: #3BC6BD;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 22rpx;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
.chat-btn1{
|
||||||
|
background:rgb(59 198 189 / 20%);
|
||||||
|
color: #3BC6BD;
|
||||||
|
}
|
||||||
|
.chat-btn2{
|
||||||
|
background: rgb(255 0 0 / 20%);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.chat-btn3{
|
||||||
|
background: rgb(62 94 215 / 20%);
|
||||||
|
color: #3E5ED7;
|
||||||
|
}
|
||||||
|
.chat-btn4{
|
||||||
|
background: rgb(105 105 105 / 20%);
|
||||||
|
color: #696969;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
margin-top: 20rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags {
|
||||||
|
margin-top: 20rpx;
|
||||||
|
|
||||||
|
text {
|
||||||
|
margin-right: 20rpx;
|
||||||
|
padding: 10rpx 20rpx;
|
||||||
|
border-radius: 30rpx;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #3BC6BD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.imgs {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
|
||||||
|
.img {
|
||||||
|
width: 30%;
|
||||||
|
margin-right: 3%;
|
||||||
|
margin-bottom: 3%;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
height: 190rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.location {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
color: #666666;
|
||||||
|
font-size: 22rpx;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
gap: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment {
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 66rpx;
|
||||||
|
border-radius: 34rpx;
|
||||||
|
margin: 20rpx 0;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
<template>
|
||||||
|
<view class="danmu-container" v-if="visible">
|
||||||
|
<view
|
||||||
|
v-for="item in danmuItems"
|
||||||
|
:key="item.id"
|
||||||
|
class="danmu-item"
|
||||||
|
:style="{
|
||||||
|
top: item.top + 'rpx',
|
||||||
|
animationDuration: item.speed + 's',
|
||||||
|
color: item.color
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
{{ item.text }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
list: Array,
|
||||||
|
visible: { type: Boolean, default: true },
|
||||||
|
row: { type: Number, default: 5 } // 轨道数
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
danmuItems: [],
|
||||||
|
laneBusy: [] // 轨道是否被占用
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.laneBusy = Array(this.row).fill(false)
|
||||||
|
this.startDanmu()
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
startDanmu() {
|
||||||
|
let index = 0
|
||||||
|
setInterval(() => {
|
||||||
|
const text = this.list[index].content
|
||||||
|
this.createDanmu(text)
|
||||||
|
index = (index + 1) % this.list.length
|
||||||
|
}, 1500)
|
||||||
|
},
|
||||||
|
|
||||||
|
createDanmu(text) {
|
||||||
|
const lane = this.getFreeLane()
|
||||||
|
const id = Date.now() + Math.random()
|
||||||
|
|
||||||
|
const item = {
|
||||||
|
id,
|
||||||
|
text,
|
||||||
|
top: lane * 100, // 每条轨道高度 60rpx
|
||||||
|
speed: 6 + Math.random()*2,
|
||||||
|
color: this.randomColor(),
|
||||||
|
lane
|
||||||
|
}
|
||||||
|
|
||||||
|
this.danmuItems.push(item)
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
this.finishDanmu(id, lane)
|
||||||
|
}, item.speed * 1000)
|
||||||
|
},
|
||||||
|
|
||||||
|
getFreeLane() {
|
||||||
|
// 找到第一个空轨道
|
||||||
|
for (let i = 0; i < this.row; i++) {
|
||||||
|
if (!this.laneBusy[i]) {
|
||||||
|
this.laneBusy[i] = true
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 如果都满了,就随机一个
|
||||||
|
return Math.floor(Math.random() * this.row)
|
||||||
|
},
|
||||||
|
|
||||||
|
finishDanmu(id, lane) {
|
||||||
|
this.danmuItems = this.danmuItems.filter(i => i.id !== id)
|
||||||
|
|
||||||
|
// 整个动画跑完后释放轨道
|
||||||
|
this.laneBusy[lane] = false
|
||||||
|
},
|
||||||
|
|
||||||
|
randomColor() {
|
||||||
|
const colors = ["#fff", "#00F6FF", "#FFEA00", "#FF66C4"]
|
||||||
|
return colors[Math.floor(Math.random() * colors.length)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.danmu-container {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 88rpx;
|
||||||
|
width: 100%;
|
||||||
|
height: 600rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.danmu-item {
|
||||||
|
position: absolute;
|
||||||
|
right: -400rpx;
|
||||||
|
font-size: 26rpx;
|
||||||
|
white-space: nowrap;
|
||||||
|
animation-name: danmu-move;
|
||||||
|
animation-timing-function: linear;
|
||||||
|
animation-fill-mode: forwards;
|
||||||
|
background: rgb(0 0 0 / 60%);
|
||||||
|
padding: 5px 14px;
|
||||||
|
border-radius: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes danmu-move {
|
||||||
|
from { transform: translateX(0); }
|
||||||
|
to { transform: translateX(-1200rpx); }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -100,8 +100,17 @@
|
|||||||
"minified" : true,
|
"minified" : true,
|
||||||
"postcss" : true
|
"postcss" : true
|
||||||
},
|
},
|
||||||
|
"permission": {
|
||||||
|
"scope.userFuzzyLocation": {
|
||||||
|
"desc": "用于为你推荐附近内容/门店"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requiredPrivateInfos": [
|
||||||
|
"getFuzzyLocation",
|
||||||
|
"chooseLocation",
|
||||||
|
"chooseAddress"
|
||||||
|
],
|
||||||
"usingComponents" : true,
|
"usingComponents" : true,
|
||||||
"permission" : {},
|
|
||||||
"uniStatistics" : {
|
"uniStatistics" : {
|
||||||
"enable" : true
|
"enable" : true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,7 +83,17 @@
|
|||||||
"enablePullDownRefresh": false,
|
"enablePullDownRefresh": false,
|
||||||
"navigationStyle":"custom"// 去掉微信小程序顶部导航
|
"navigationStyle":"custom"// 去掉微信小程序顶部导航
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path" : "pages/classify/classify",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText" : "分类",
|
||||||
|
"enablePullDownRefresh": false,
|
||||||
|
"navigationStyle":"custom"// 去掉微信小程序顶部导航
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
],
|
],
|
||||||
"subPackages":[
|
"subPackages":[
|
||||||
{
|
{
|
||||||
@@ -124,6 +134,15 @@
|
|||||||
"enablePullDownRefresh": false,
|
"enablePullDownRefresh": false,
|
||||||
"navigationStyle":"custom"// 去掉微信小程序顶部导航
|
"navigationStyle":"custom"// 去掉微信小程序顶部导航
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path" : "my_reply",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText" : "回复我的",
|
||||||
|
"enablePullDownRefresh": false,
|
||||||
|
"navigationStyle":"custom"// 去掉微信小程序顶部导航
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -147,7 +166,7 @@
|
|||||||
},
|
},
|
||||||
"tabBar": {
|
"tabBar": {
|
||||||
"color": "#7A7E83",
|
"color": "#7A7E83",
|
||||||
"selectedColor": "#0071FC",
|
"selectedColor": "#3BC6BD",
|
||||||
"borderStyle": "white",
|
"borderStyle": "white",
|
||||||
"backgroundColor": "#fff",
|
"backgroundColor": "#fff",
|
||||||
"list": [
|
"list": [
|
||||||
@@ -158,10 +177,10 @@
|
|||||||
"text": "首页"
|
"text": "首页"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"pagePath": "pages/square/index",
|
"pagePath": "pages/classify/classify",
|
||||||
"iconPath": "/static/image/square1.png",
|
"iconPath": "/static/image/classify1.png",
|
||||||
"selectedIconPath": "/static/image/square.png",
|
"selectedIconPath": "/static/image/classify.png",
|
||||||
"text": "广场"
|
"text": "分类"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"pagePath": "pages/publish/index",
|
"pagePath": "pages/publish/index",
|
||||||
@@ -169,6 +188,12 @@
|
|||||||
"selectedIconPath": "/static/image/publish.png",
|
"selectedIconPath": "/static/image/publish.png",
|
||||||
"text": "发布"
|
"text": "发布"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"pagePath": "pages/square/index",
|
||||||
|
"iconPath": "/static/image/square1.png",
|
||||||
|
"selectedIconPath": "/static/image/square.png",
|
||||||
|
"text": "广场"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"pagePath": "pages/index/mine",
|
"pagePath": "pages/index/mine",
|
||||||
"iconPath": "/static/image/mine1.png",
|
"iconPath": "/static/image/mine1.png",
|
||||||
|
|||||||
@@ -0,0 +1,630 @@
|
|||||||
|
<template>
|
||||||
|
<view class="page">
|
||||||
|
<uni-nav-bar leftText=" " :fixed="true" :border="false" @clickLeft="leftClick" color="#000" backgroundColor="#fff" :statusBar="true" title="样机分类"></uni-nav-bar>
|
||||||
|
|
||||||
|
<!-- 顶部 tabs -->
|
||||||
|
<view class="tabs">
|
||||||
|
<view :class="['tab', currentTab==='latest'?'on':'']" @click="switchTab('latest')">最新发布</view>
|
||||||
|
<view class="divider"></view>
|
||||||
|
<view :class="['tab', currentTab==='near'?'on':'']" @click="switchTab('near')">距离最近</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="content-con">
|
||||||
|
<!-- 左侧分类 -->
|
||||||
|
<scroll-view scroll-y class="left-aside">
|
||||||
|
<view
|
||||||
|
v-for="item in flist"
|
||||||
|
:key="item.id"
|
||||||
|
class="f-item"
|
||||||
|
:class="{active: item.id === currentCategoryId}"
|
||||||
|
@click="onCategoryChange(item.id)"
|
||||||
|
>
|
||||||
|
<view class="cat-text">{{ item.name }}</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
|
||||||
|
<!-- 右侧列表 -->
|
||||||
|
<scroll-view
|
||||||
|
scroll-y
|
||||||
|
class="right-aside"
|
||||||
|
refresher-enabled
|
||||||
|
:refresher-triggered="refreshing"
|
||||||
|
@refresherrefresh="onRefresh"
|
||||||
|
:lower-threshold="100"
|
||||||
|
@scrolltolower="onLoadMore"
|
||||||
|
>
|
||||||
|
<view class="list">
|
||||||
|
<classify-card
|
||||||
|
v-for="item in slist"
|
||||||
|
:key="item.id"
|
||||||
|
:item="item"
|
||||||
|
@view="navToList"
|
||||||
|
@start="startLink"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<view v-if="hasMore" class="load-more">
|
||||||
|
<text v-if="loadingMore">加载中...</text>
|
||||||
|
<text v-else>上拉加载更多</text>
|
||||||
|
</view>
|
||||||
|
<view v-else-if="slist.length > 0" class="load-more">
|
||||||
|
<text>没有更多了</text>
|
||||||
|
</view>
|
||||||
|
<view class="empty" v-if="slist.length === 0 && !loading">
|
||||||
|
<image src="/static/image/empty.png" mode="aspectFit"></image>
|
||||||
|
<view>暂无数据!</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 加载提示 -->
|
||||||
|
<view v-if="loading" class="loading-mask">
|
||||||
|
<view class="loading-text">加载中...</view>
|
||||||
|
</view>
|
||||||
|
<u-popup :show="showlogin" :closeOnClickOverlay="false" :round="20" mode="center">
|
||||||
|
<view class="popupcontent">
|
||||||
|
<image class="log1" src="/static/image/log1.png"></image>
|
||||||
|
<view class="title">{{$t('home.loginmsg')}}</view>
|
||||||
|
<view class="yhxy">
|
||||||
|
<checkbox-group name="" style="width: 28px;display: inline-block;">
|
||||||
|
<label @tap="selfChangde()">
|
||||||
|
<checkbox :checked="selfChecked" activeBackgroundColor="#3F435B"
|
||||||
|
style="transform:scale(0.7);border-radius: 50%" />
|
||||||
|
</label>
|
||||||
|
</checkbox-group>
|
||||||
|
{{$t('home.argin')}}<text class="xy" @click="gouser">{{$t('home.UserAgreement')}}</text>{{$t('home.and')}}<text
|
||||||
|
class="xy" @click="goprivacy">{{$t('home.Privacy')}}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="cent">
|
||||||
|
<button class="btn1" @click="showlogin = !showlogin">{{$t('cancel')}}</button>
|
||||||
|
<button v-if="selfChecked" class="btn" open-type="getPhoneNumber" @click="showlogin = !showlogin"
|
||||||
|
@getphonenumber="getPhoneNumber">{{$t('login')}}</button>
|
||||||
|
<button v-else class="btn" @click="loginbtn">{{$t('login')}}</button>
|
||||||
|
</view>
|
||||||
|
</u-popup>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { request } from '@/api/apiT.js'
|
||||||
|
import SquarePostCard from '@/components/SquarePostCard.vue'
|
||||||
|
import ClassifyCard from '@/components/ClassifyCard.vue'
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
SquarePostCard,
|
||||||
|
ClassifyCard
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
showlogin: false,
|
||||||
|
tabs: [
|
||||||
|
{ key: 'latest', label: '最新发布' },
|
||||||
|
{ key: 'near', label: '距离最近' }
|
||||||
|
],
|
||||||
|
currentTab: 'latest',
|
||||||
|
flist: [],
|
||||||
|
slist: [],
|
||||||
|
selfChecked: false,
|
||||||
|
currentCategoryId: '', // 当前选中的分类id
|
||||||
|
loading: false, // 加载状态
|
||||||
|
refreshing: false, // 下拉刷新状态
|
||||||
|
loadingMore: false, // 上拉加载状态
|
||||||
|
page: 1, // 当前页码
|
||||||
|
pageSize: 10, // 每页数量
|
||||||
|
hasMore: true, // 是否还有更多数据
|
||||||
|
categoriesLoaded: false // 分类是否已加载完成
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad() {
|
||||||
|
// 加载第一级分类列表
|
||||||
|
|
||||||
|
},
|
||||||
|
onShow() {
|
||||||
|
this.loadCategoryList();
|
||||||
|
// this.syncTabbar()
|
||||||
|
// // 从详情页返回后,重新拉取当前分类数据
|
||||||
|
// if (this.categoriesLoaded) {
|
||||||
|
// this.refreshCurrentCategory()
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
goprivacy(){
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/login/agreement',// 替换为你要跳转的页面路径
|
||||||
|
});
|
||||||
|
},
|
||||||
|
selfChangde(e) {
|
||||||
|
this.selfChecked = !this.selfChecked;
|
||||||
|
},
|
||||||
|
loginbtn(){
|
||||||
|
if(!this.selfChecked){
|
||||||
|
uni.showToast({
|
||||||
|
title:this.$t('home.arginimg'),
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getPhoneNumber(e) {
|
||||||
|
let that = this;
|
||||||
|
request({
|
||||||
|
url:'miniapp/phone',
|
||||||
|
method:'POST',
|
||||||
|
data:{
|
||||||
|
phone_code: e.detail.code,
|
||||||
|
}
|
||||||
|
}).then(res => {
|
||||||
|
if (res.data.code == -1) {
|
||||||
|
uni.showToast({
|
||||||
|
title: res.data.msg,
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
|
||||||
|
} else if (res.data.code == 200) {
|
||||||
|
//返回数据接收成功
|
||||||
|
uni.setStorageSync('is_login', true);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 加载第一级分类列表
|
||||||
|
loadCategoryList() {
|
||||||
|
// TODO: 替换为实际的后端接口
|
||||||
|
let that = this;
|
||||||
|
|
||||||
|
request({
|
||||||
|
url:'common/post/category/list',
|
||||||
|
method:'GET'
|
||||||
|
}).then(res => {
|
||||||
|
if (res.data.code == 200) {
|
||||||
|
const records = res.data.data.records || [];
|
||||||
|
this.flist = [{
|
||||||
|
id: '',
|
||||||
|
name: '全部分类'
|
||||||
|
}, ...records];
|
||||||
|
this.categoriesLoaded = true;
|
||||||
|
// 默认加载第一个分类的数据
|
||||||
|
if (this.flist.length > 0) {
|
||||||
|
this.onCategoryChange(this.flist[0].id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 重新加载当前分类数据
|
||||||
|
refreshCurrentCategory() {
|
||||||
|
const targetCategory = this.currentCategoryId !== undefined ? this.currentCategoryId : (this.flist[0] && this.flist[0].id) || '';
|
||||||
|
this.loadCategoryData(targetCategory, false);
|
||||||
|
},
|
||||||
|
|
||||||
|
// 分类切换事件
|
||||||
|
onCategoryChange(categoryId) {
|
||||||
|
// 如果点击的是当前分类且已有数据,不重复加载
|
||||||
|
if (this.currentCategoryId === categoryId && this.slist.length > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 切换分类时,重置所有状态
|
||||||
|
this.currentCategoryId = categoryId;
|
||||||
|
this.page = 1;
|
||||||
|
this.hasMore = true;
|
||||||
|
this.loading = false;
|
||||||
|
this.loadingMore = false;
|
||||||
|
this.refreshing = false;
|
||||||
|
this.slist = []; // 先清空数据
|
||||||
|
this.loadCategoryData(categoryId, false);
|
||||||
|
},
|
||||||
|
|
||||||
|
// 根据分类id加载分类下的内容
|
||||||
|
loadCategoryData(categoryId, isLoadMore = false) {
|
||||||
|
// 防止重复请求:如果是加载更多,需要检查所有加载状态
|
||||||
|
if (isLoadMore) {
|
||||||
|
if (this.loadingMore || this.loading || this.refreshing) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 下拉刷新或初次加载,检查加载状态
|
||||||
|
if (this.loading || this.loadingMore) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLoadMore) {
|
||||||
|
this.loadingMore = true;
|
||||||
|
this.page += 1;
|
||||||
|
} else {
|
||||||
|
this.loading = true;
|
||||||
|
this.page = 1;
|
||||||
|
this.hasMore = true;
|
||||||
|
this.slist = []; // 清空之前的数据
|
||||||
|
}
|
||||||
|
|
||||||
|
request({
|
||||||
|
url:'common/post/list',
|
||||||
|
method:'GET',
|
||||||
|
data:{
|
||||||
|
category_id:categoryId,
|
||||||
|
current: this.page,
|
||||||
|
size: this.pageSize
|
||||||
|
}
|
||||||
|
}).then(res => {
|
||||||
|
this.loading = false;
|
||||||
|
this.loadingMore = false;
|
||||||
|
this.refreshing = false;
|
||||||
|
|
||||||
|
if (res.data.code == 200) {
|
||||||
|
const records = res.data.data.records || [];
|
||||||
|
const total = res.data.data.total || 0;
|
||||||
|
|
||||||
|
if (isLoadMore) {
|
||||||
|
// 上拉加载更多,追加数据并去重
|
||||||
|
const existingIds = new Set(this.slist.map(item => item.id));
|
||||||
|
const newRecords = records.filter(item => !existingIds.has(item.id));
|
||||||
|
this.slist = [...this.slist, ...newRecords];
|
||||||
|
} else {
|
||||||
|
// 下拉刷新或初次加载,替换数据
|
||||||
|
this.slist = records;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断是否还有更多数据
|
||||||
|
this.hasMore = this.slist.length < total;
|
||||||
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
this.loading = false;
|
||||||
|
this.loadingMore = false;
|
||||||
|
this.refreshing = false;
|
||||||
|
if (isLoadMore) {
|
||||||
|
this.page -= 1; // 加载失败,页码回退
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 下拉刷新
|
||||||
|
onRefresh() {
|
||||||
|
// 如果正在加载中,不执行刷新
|
||||||
|
if (this.loading || this.loadingMore) {
|
||||||
|
this.refreshing = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.refreshing = true;
|
||||||
|
this.loadCategoryData(this.currentCategoryId, false);
|
||||||
|
},
|
||||||
|
// 上拉加载更多
|
||||||
|
onLoadMore() {
|
||||||
|
if (!this.hasMore || this.loadingMore || this.loading || this.refreshing) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.loadCategoryData(this.currentCategoryId, true);
|
||||||
|
},
|
||||||
|
// tab 切换
|
||||||
|
switchTab(key) {
|
||||||
|
if (this.currentTab === key) return
|
||||||
|
this.currentTab = key
|
||||||
|
this.onRefresh()
|
||||||
|
},
|
||||||
|
|
||||||
|
// 点击商品项
|
||||||
|
navToList(item) {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/square/detiles?id='+item.id
|
||||||
|
});
|
||||||
|
},
|
||||||
|
islogin(){
|
||||||
|
if(uni.getStorageSync('is_login')){
|
||||||
|
return true
|
||||||
|
}else{
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
//收藏
|
||||||
|
startLink(item){
|
||||||
|
if(!this.islogin()){
|
||||||
|
this.showlogin = true
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const targetIndex = this.slist.findIndex(post => post.id === item.id)
|
||||||
|
if(targetIndex === -1){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const target = this.slist[targetIndex]
|
||||||
|
const collectUrl = item.is_favorite ? 'common/post/favorite/destroy' : 'common/post/favorite/store'
|
||||||
|
const method = item.is_favorite ? 'GET' : 'POST'
|
||||||
|
const data = {
|
||||||
|
post_id: item.id
|
||||||
|
}
|
||||||
|
if (item.is_favorite) {
|
||||||
|
data.user_id = item.user_id
|
||||||
|
}
|
||||||
|
request({
|
||||||
|
url: collectUrl,
|
||||||
|
method,
|
||||||
|
data
|
||||||
|
}).then(res => {
|
||||||
|
if(res.data.code === 200){
|
||||||
|
const newTarget = { ...target }
|
||||||
|
if(newTarget.is_favorite){
|
||||||
|
newTarget.is_favorite = 0
|
||||||
|
uni.showToast({
|
||||||
|
title: '取消收藏成功',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
newTarget.is_favorite = 1
|
||||||
|
uni.showToast({
|
||||||
|
title: '收藏成功',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.$set(this.slist, targetIndex, newTarget)
|
||||||
|
}else{
|
||||||
|
uni.showToast({
|
||||||
|
title:res.data.message,
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
//点赞
|
||||||
|
navTozan(item){
|
||||||
|
const targetIndex = this.slist.findIndex(post => post.id === item.id)
|
||||||
|
if(targetIndex === -1){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const target = this.slist[targetIndex]
|
||||||
|
const isLiked = Number(target.is_like) === 1
|
||||||
|
const likeUrl = isLiked ? 'common/post/like/destroy' : 'common/post/like/store'
|
||||||
|
const method = isLiked ? 'GET' : 'POST'
|
||||||
|
const data = {
|
||||||
|
post_id: target.id
|
||||||
|
}
|
||||||
|
if (isLiked) {
|
||||||
|
data.user_id = target.user_id
|
||||||
|
}
|
||||||
|
request({
|
||||||
|
url: likeUrl,
|
||||||
|
method,
|
||||||
|
data
|
||||||
|
}).then(res => {
|
||||||
|
if(res.data.code === 200){
|
||||||
|
const newTarget = { ...target }
|
||||||
|
if(isLiked){
|
||||||
|
newTarget.is_like = 0
|
||||||
|
newTarget.like = Math.max(0, (Number(newTarget.like) || 0) - 1)
|
||||||
|
uni.showToast({
|
||||||
|
title: '取消成功',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
newTarget.is_like = 1
|
||||||
|
newTarget.like = (Number(newTarget.like) || 0) + 1
|
||||||
|
uni.showToast({
|
||||||
|
title: '点赞成功',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.$set(this.slist, targetIndex, newTarget)
|
||||||
|
}else{
|
||||||
|
uni.showToast({
|
||||||
|
title:res.data.message,
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
//消息
|
||||||
|
navTomsg(item){
|
||||||
|
request({
|
||||||
|
url:'common/like/store',
|
||||||
|
method:'GET',
|
||||||
|
data:{
|
||||||
|
post_id:item.id
|
||||||
|
}
|
||||||
|
}).then(res => {
|
||||||
|
})
|
||||||
|
},
|
||||||
|
leftClick(){
|
||||||
|
uni.navigateBack()
|
||||||
|
},
|
||||||
|
syncTabbar(){
|
||||||
|
uni.setTabBarItem({ index:0, text:this.$t('tabbar.home') })
|
||||||
|
uni.setTabBarItem({ index:1, text:this.$t('tabbar.square') })
|
||||||
|
uni.setTabBarItem({ index:2, text:this.$t('tabbar.publish') })
|
||||||
|
uni.setTabBarItem({ index:3, text:this.$t('tabbar.mine') })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped>
|
||||||
|
page,
|
||||||
|
.page {
|
||||||
|
height: 100%;
|
||||||
|
/* background: #f7f7f7; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs {
|
||||||
|
height: 80rpx;
|
||||||
|
background: #fff;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-around;
|
||||||
|
gap: 24rpx;
|
||||||
|
position: relative;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
.tab {
|
||||||
|
position: relative;
|
||||||
|
padding: 12rpx 20rpx 18rpx;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.tab::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
bottom: 4rpx;
|
||||||
|
width: 50rpx;
|
||||||
|
height: 4rpx;
|
||||||
|
background: #05b3a8;
|
||||||
|
border-radius: 4rpx;
|
||||||
|
transform: translateX(-50%) scaleX(0);
|
||||||
|
transition: transform 0.2s;
|
||||||
|
}
|
||||||
|
.tab.on {
|
||||||
|
color: #05b3a8;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
.tab.on::after {
|
||||||
|
transform: translateX(-50%) scaleX(1);
|
||||||
|
}
|
||||||
|
.divider {
|
||||||
|
width: 1px;
|
||||||
|
height: 26rpx;
|
||||||
|
background: #dcdcdc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-con {
|
||||||
|
height: calc(100% - 80rpx);
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-aside {
|
||||||
|
width: 200rpx;
|
||||||
|
background: #3BC6BD;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
.f-item {
|
||||||
|
height: 96rpx;
|
||||||
|
/* padding-left: 28rpx; */
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 12rpx;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
.category-icon image {
|
||||||
|
width: 32rpx;
|
||||||
|
height: 32rpx;
|
||||||
|
}
|
||||||
|
.cat-text {
|
||||||
|
font-size: 26rpx;
|
||||||
|
width: 80%;
|
||||||
|
text-align: center;
|
||||||
|
padding: 14rpx 0;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
}
|
||||||
|
.f-item.active .cat-text{
|
||||||
|
background: #F5F6FA;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
.right-aside {
|
||||||
|
flex: 1;
|
||||||
|
/* background: #fff; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.list {
|
||||||
|
padding: 16rpx 16rpx 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.load-more {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
padding: 30rpx 0;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
.empty {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
padding: 80rpx 0;
|
||||||
|
}
|
||||||
|
.empty image {
|
||||||
|
width: 200rpx;
|
||||||
|
height: 140rpx;
|
||||||
|
margin-bottom: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-mask {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: rgba(0, 0, 0, 0.3);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 999;
|
||||||
|
|
||||||
|
.loading-text {
|
||||||
|
color: #fff;
|
||||||
|
font-size: 28upx;
|
||||||
|
background-color: rgba(0, 0, 0, 0.7);
|
||||||
|
padding: 20upx 40upx;
|
||||||
|
border-radius: 8upx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.popupcontent{
|
||||||
|
background-size: 100% 100%;
|
||||||
|
padding: 26px 15px;
|
||||||
|
text-align: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
.title{
|
||||||
|
color: #333333;
|
||||||
|
font-size: 15px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.log1{
|
||||||
|
width: 180px;
|
||||||
|
height: 180px;
|
||||||
|
}
|
||||||
|
.yhxy{
|
||||||
|
color: #999999;
|
||||||
|
font-size: 12px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
.xy{
|
||||||
|
color: #3BC6BD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.share{
|
||||||
|
background-color: #fff;
|
||||||
|
border: 1px solid #fff;
|
||||||
|
height: 34px;
|
||||||
|
line-height: 34px;
|
||||||
|
width: 30px;
|
||||||
|
position: absolute;
|
||||||
|
right: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
top: 8px;
|
||||||
|
}
|
||||||
|
.share:after{
|
||||||
|
border: 1px solid #fff;
|
||||||
|
}
|
||||||
|
.share image{
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
.cent{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-around;
|
||||||
|
padding: 0px 10px 20px;
|
||||||
|
.btn1{
|
||||||
|
background-color: #fff;
|
||||||
|
border: 1px solid #3BC6BD;
|
||||||
|
color: #3BC6BD;
|
||||||
|
border-radius: 50px;
|
||||||
|
width: 46%;
|
||||||
|
margin: 10px 0px 20px;
|
||||||
|
height: 50px;
|
||||||
|
line-height: 50px;
|
||||||
|
}
|
||||||
|
.btn{
|
||||||
|
background-color: #3BC6BD;
|
||||||
|
color: white;
|
||||||
|
border-radius: 50px;
|
||||||
|
width: 46%;
|
||||||
|
margin: 10px 0px 20px;
|
||||||
|
height: 50px;
|
||||||
|
line-height: 50px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,489 +1,347 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="home-page">
|
<view class="page">
|
||||||
<z-paging ref="paging" :auto="false" v-model="contList" @query="queryList" empty-view-text="暂无数据!">
|
<z-paging ref="paging" :auto="false" v-model="list" @query="queryList" empty-view-text="暂无数据!">
|
||||||
<!-- <template #top> -->
|
<!-- 顶部背景 -->
|
||||||
<!-- 轮播Banner -->
|
<view class="header">
|
||||||
<swiper class="banner-swiper" circular autoplay :interval="4000" indicator-dots indicator-color="rgba(255,255,255,.4)"
|
<image src="/static/image/homebg.png" mode="aspectFill" class="bg"></image>
|
||||||
indicator-active-color="#3F435B">
|
|
||||||
<swiper-item v-for="(banner,index) in bannerList" :key="index">
|
<!-- 弹幕组件 -->
|
||||||
<image class="banner-img" :src="banner.image_url_pull" mode="aspectFill"></image>
|
<danmu :list="danmuList" :row="5" :visible="danmuVisible"></danmu>
|
||||||
<!-- <view class="banner-desc">
|
|
||||||
<text class="slogan-text">{{banner.slogan}}</text>
|
<!-- 标题 -->
|
||||||
</view> -->
|
<view class="title">
|
||||||
</swiper-item>
|
<view>西门子样机</view>
|
||||||
</swiper>
|
<view>福利平台</view>
|
||||||
<!-- </template> -->
|
</view>
|
||||||
<!-- 内容网格 -->
|
|
||||||
<view class="content-grid">
|
<!-- 右侧按钮 -->
|
||||||
<square-post-card
|
<view class="right-btns">
|
||||||
class="grid-item"
|
<view class="circle-btn" :class="{ active: danmuVisible }" @click="toggleDanmu">
|
||||||
v-for="sitem in contList"
|
<image v-if="danmuVisible" src="/static/image/dan1.png" mode=""></image>
|
||||||
:key="sitem.id"
|
<image v-else src="/static/image/danm.png" mode=""></image>
|
||||||
:item="sitem"
|
</view>
|
||||||
:isshow="false"
|
<view class="circle-btn">
|
||||||
@view="navToList"
|
<image src="/static/image/shares.png" class="share" mode=""></image>
|
||||||
@comment="viewPost"
|
</view>
|
||||||
@like="viewPost" />
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 主体内容 -->
|
||||||
|
|
||||||
|
<view class="main-box">
|
||||||
|
<view class="titles">
|
||||||
|
样机广场
|
||||||
|
</view>
|
||||||
|
<view class="tabs">
|
||||||
|
<view :class="['tab',activeTab==0?'on':'']" @tap="tabclick(0)">
|
||||||
|
<text>最新发布</text>
|
||||||
|
</view>
|
||||||
|
<view class="divider"></view>
|
||||||
|
<view :class="['tab',activeTab==1?'on':'']" @tap="tabclick(1)">
|
||||||
|
<text>距离最近</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 用户卡片 -->
|
||||||
|
<view class="card">
|
||||||
|
<post-card
|
||||||
|
v-for="sitem in list"
|
||||||
|
:key="sitem.id || sitem.username"
|
||||||
|
:item="sitem"
|
||||||
|
@userClick="goto"
|
||||||
|
@view="goto"
|
||||||
|
@contact="handleContact"
|
||||||
|
@comment="handleComment">
|
||||||
|
</post-card>
|
||||||
|
</view>
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
</z-paging>
|
</z-paging>
|
||||||
|
|
||||||
<u-popup :show="show" :closeOnClickOverlay="false" :round="20" mode="center">
|
|
||||||
<view class="popupcontent">
|
|
||||||
<image class="log1" src="/static/image/log1.png"></image>
|
|
||||||
<view class="title">{{$t('home.loginmsg')}}</view>
|
|
||||||
<view class="yhxy">
|
|
||||||
<checkbox-group name="" style="width: 28px;display: inline-block;">
|
|
||||||
<label @tap="selfChangde()">
|
|
||||||
<checkbox :checked="selfChecked" activeBackgroundColor="#3F435B"
|
|
||||||
style="transform:scale(0.7);border-radius: 50%" />
|
|
||||||
</label>
|
|
||||||
</checkbox-group>
|
|
||||||
{{$t('home.argin')}}<text class="xy" @click="gouser">{{$t('home.UserAgreement')}}</text>{{$t('home.and')}}<text
|
|
||||||
class="xy" @click="goprivacy">{{$t('home.Privacy')}}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="cent">
|
|
||||||
<button class="btn1" @click="show = !show">{{$t('cancel')}}</button>
|
|
||||||
<button v-if="selfChecked" class="btn" open-type="getPhoneNumber" @click="show = !show"
|
|
||||||
@getphonenumber="getPhoneNumber">{{$t('login')}}</button>
|
|
||||||
<button v-else class="btn" @click="loginbtn">{{$t('login')}}</button>
|
|
||||||
</view>
|
|
||||||
</u-popup>
|
|
||||||
|
|
||||||
<u-picker :immediateChange="true" :cancel-text="$t('cancel')" :confirm-text="$t('confirm')" @close="close('showlang')"
|
|
||||||
:show="showlang" :columns="columns" @cancel="cancellang" @confirm="confirmlang" :title="$t('home.langbtn')" keyName="label"></u-picker>
|
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { request,showToast } from '@/api/apiT.js'
|
import danmu from '@/components/danmu/danmu.vue';
|
||||||
import SquarePostCard from '@/components/SquarePostCard.vue'
|
import PostCard from '@/components/PostCard.vue'
|
||||||
export default {
|
import { request,showToast } from '@/api/apiT.js'
|
||||||
components: {
|
export default {
|
||||||
SquarePostCard
|
components: { danmu, PostCard },
|
||||||
},
|
data() {
|
||||||
data() {
|
return {
|
||||||
return {
|
activeTab: 0,
|
||||||
title: 'Hello',
|
danmuVisible:true,
|
||||||
selfChecked: false,
|
content:'',
|
||||||
home: this.$t('tabbar.home'),
|
list:[],
|
||||||
is_login:uni.getStorageSync('is_login'),
|
danmuList: [],
|
||||||
show: false,
|
latitude:'',
|
||||||
showlang: false,
|
longitude:''
|
||||||
searchKeyword: '',
|
};
|
||||||
bannerList: [],
|
},
|
||||||
contList: [],
|
onLoad() {
|
||||||
columns: [
|
// 数据加载逻辑
|
||||||
[{
|
if (!uni.getStorageSync('token')) {
|
||||||
label: this.$t('zh'),
|
this.mini_login().then(() => {
|
||||||
id: 'zh'
|
this.barragelist()
|
||||||
}, {
|
|
||||||
label: this.$t('en'),
|
|
||||||
id: 'en'
|
|
||||||
},{
|
|
||||||
label: this.$t('ru'),
|
|
||||||
id: 'ru'
|
|
||||||
}]
|
|
||||||
],
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onLoad() {
|
|
||||||
// if(uni.getStorageSync('token')){
|
|
||||||
// // this.$refs.paging && this.$refs.paging.reload()
|
|
||||||
// }else{
|
|
||||||
// this.mini_login()
|
|
||||||
// }
|
|
||||||
if (!uni.getStorageSync('token')) {
|
|
||||||
this.mini_login().then(() => {
|
|
||||||
this.bannerListfn()
|
|
||||||
this.$refs.paging && this.$refs.paging.reload()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onShow() {
|
|
||||||
uni.setTabBarItem({
|
|
||||||
index: 0,
|
|
||||||
text: this.$t('tabbar.home')
|
|
||||||
})
|
|
||||||
uni.setTabBarItem({
|
|
||||||
index:1,
|
|
||||||
text: this.$t('tabbar.square')
|
|
||||||
})
|
|
||||||
uni.setTabBarItem({
|
|
||||||
index: 2,
|
|
||||||
text: this.$t('tabbar.publish')
|
|
||||||
})
|
|
||||||
uni.setTabBarItem({
|
|
||||||
index: 3,
|
|
||||||
text: this.$t('tabbar.mine')
|
|
||||||
})
|
|
||||||
if(uni.getStorageSync('token')){
|
|
||||||
this.bannerListfn()
|
|
||||||
this.$refs.paging && this.$refs.paging.reload()
|
this.$refs.paging && this.$refs.paging.reload()
|
||||||
}
|
})
|
||||||
|
}else{
|
||||||
|
this.barragelist()
|
||||||
|
this.$refs.paging && this.$refs.paging.reload()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onShow() {
|
||||||
|
this.getFuzzy().then(res => {
|
||||||
|
this.latitude = res.latitude
|
||||||
|
this.longitude = res.longitude
|
||||||
|
console.log(res);
|
||||||
|
}).catch(err => console.error(err));
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getFuzzy() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
wx.getSetting({
|
||||||
|
success: (st) => {
|
||||||
|
const ok = st.authSetting['scope.userFuzzyLocation'];
|
||||||
|
const run = () => wx.getFuzzyLocation({
|
||||||
|
type: 'wgs84',
|
||||||
|
success: resolve,
|
||||||
|
fail: reject
|
||||||
|
});
|
||||||
|
|
||||||
|
if (ok) return run();
|
||||||
|
|
||||||
|
wx.authorize({
|
||||||
|
scope: 'scope.userFuzzyLocation',
|
||||||
|
success: run,
|
||||||
|
fail: () => wx.openSetting({ success: () => reject(new Error('未授权')) })
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fail: reject
|
||||||
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
methods: {
|
tabclick(item){
|
||||||
async initPage(){
|
this.activeTab = item;
|
||||||
await this.mini_login()
|
this.$refs.paging && this.$refs.paging.reload()
|
||||||
await this.bannerListfn()
|
},
|
||||||
},
|
//获取弹幕
|
||||||
bannerListfn(){
|
barragelist(){
|
||||||
request({
|
request({
|
||||||
url:'common/banner/list',
|
url: 'admin/barrage/list',
|
||||||
method:'get',
|
method: 'GET',
|
||||||
data:{
|
}).then(res => {
|
||||||
module:'home_module'
|
if (res.data.code === 200) {
|
||||||
}
|
this.danmuList = res.data.data.records
|
||||||
}).then(res => {
|
}
|
||||||
this.bannerList = res.data.data
|
})
|
||||||
})
|
},
|
||||||
},
|
toggleDanmu() {
|
||||||
// 点击商品项
|
this.danmuVisible = !this.danmuVisible;
|
||||||
navToList(item) {
|
},
|
||||||
uni.navigateTo({
|
goto(item){
|
||||||
url: '/pages/square/detiles?id='+item.id
|
uni.navigateTo({
|
||||||
});
|
url: '/pages/square/detiles?id='+item.id
|
||||||
},
|
});
|
||||||
viewPost(item){
|
},
|
||||||
if(uni.getStorageSync('is_login')){
|
handleContact(item) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '联系门店功能',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
},
|
||||||
|
handleComment(item) {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/square/detiles?id=' + (item?.id || 1)
|
||||||
|
});
|
||||||
|
},
|
||||||
|
queryList(pageNo, pageSize, from) {
|
||||||
|
this.loading = true;
|
||||||
|
var that = this;
|
||||||
|
const params = {
|
||||||
|
current:pageNo,
|
||||||
|
size:10
|
||||||
|
};
|
||||||
|
const collectUrl = this.activeTab==0 ? 'common/post/list' : 'common/post/nearby'
|
||||||
|
// 添加排序参数(如果后端支持)
|
||||||
|
if(this.activeTab==1){
|
||||||
|
params.lng = this.longitude;
|
||||||
|
params.lat = this.latitude;
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
request({
|
||||||
|
url:collectUrl,
|
||||||
|
method:'get',
|
||||||
|
data: params
|
||||||
|
}).then(res => {
|
||||||
|
if(res.data.code ==200){
|
||||||
|
var datas = res.data.data.records;
|
||||||
|
this.$refs.paging.complete(datas);
|
||||||
}else{
|
}else{
|
||||||
this.show = true
|
}
|
||||||
}
|
uni.stopPullDownRefresh();
|
||||||
},
|
//
|
||||||
cancellang() {
|
})
|
||||||
this.showlang = false
|
},
|
||||||
},
|
mini_login() {
|
||||||
close(value){
|
return new Promise((resolve, reject) => {
|
||||||
this[value] = false
|
uni.login({
|
||||||
},
|
provider: 'weixin',
|
||||||
queryList(pageNo, pageSize) {
|
success: loginRes => {
|
||||||
this.loading = true;
|
|
||||||
var that = this;
|
// 一定要 return,不然 Promise 不会等待
|
||||||
request({
|
return request({
|
||||||
url:'common/post/list',
|
url:'miniapp/login',
|
||||||
method:'get',
|
method:'POST',
|
||||||
data: {
|
data:{ code: loginRes.code }
|
||||||
current:pageNo,
|
}).then(res => {
|
||||||
size:10
|
if (res.data.code === 200) {
|
||||||
}
|
|
||||||
}).then(res => {
|
uni.setStorageSync('openid', res.data.data.openid);
|
||||||
if(res.data.code ==200){
|
uni.setStorageSync('token', res.data.data.token);
|
||||||
var datas = res.data.data.records;
|
|
||||||
this.$refs.paging.complete(datas);
|
if (res.data.data.mobile) {
|
||||||
}else{
|
uni.setStorageSync('is_login', true);
|
||||||
// this.$refs.paging.complete(null);
|
} else {
|
||||||
// that.listlength=0
|
uni.setStorageSync('is_login', false);
|
||||||
}
|
}
|
||||||
uni.stopPullDownRefresh();
|
|
||||||
//
|
resolve(true); // 👍 一定在 Promise 中
|
||||||
})
|
} else {
|
||||||
},
|
uni.showToast({
|
||||||
//语言切换事件
|
title: res.data.msg,
|
||||||
confirmlang(e) {
|
icon: 'none'
|
||||||
var that = this
|
});
|
||||||
this.$i18n.locale = e.value[0].id
|
reject(res);
|
||||||
uni.setLocale(e.value[0].id)
|
}
|
||||||
uni.setStorageSync('i18locale', e.value[0].id);
|
})
|
||||||
this.columns =[
|
},
|
||||||
[{
|
fail: (err) => {
|
||||||
label: this.$t('zh'),
|
uni.showToast({
|
||||||
id: 'zh'
|
title: '获取 code 失败',
|
||||||
}, {
|
icon: 'none'
|
||||||
label: this.$t('en'),
|
});
|
||||||
id: 'en'
|
reject(err); // 👍 必须 reject
|
||||||
},{
|
}
|
||||||
label: this.$t('ru'),
|
});
|
||||||
id: 'ru'
|
});
|
||||||
}]
|
|
||||||
];
|
|
||||||
uni.setTabBarItem({
|
|
||||||
index: 0,
|
|
||||||
text: this.$t('tabbar.square')
|
|
||||||
})
|
|
||||||
uni.setTabBarItem({
|
|
||||||
index: 1,
|
|
||||||
text: this.$t('tabbar.publish')
|
|
||||||
})
|
|
||||||
uni.setTabBarItem({
|
|
||||||
index: 2,
|
|
||||||
text: this.$t('tabbar.mine')
|
|
||||||
})
|
|
||||||
this.showlang = false
|
|
||||||
var languages = e.value[0].id
|
|
||||||
if(e.value[0].id=='zh'){
|
|
||||||
languages= 'zh_CN'
|
|
||||||
}
|
|
||||||
request({
|
|
||||||
url:'user/update',
|
|
||||||
method:'POST',
|
|
||||||
data:{
|
|
||||||
language:languages
|
|
||||||
}
|
|
||||||
}).then(res => {
|
|
||||||
uni.showToast({
|
|
||||||
title: res.data.message,
|
|
||||||
icon: 'none'
|
|
||||||
});
|
|
||||||
})
|
|
||||||
},
|
|
||||||
goprivacy(){
|
|
||||||
uni.navigateTo({
|
|
||||||
url: '/pages/login/agreement',// 替换为你要跳转的页面路径
|
|
||||||
});
|
|
||||||
},
|
|
||||||
gouser(){
|
|
||||||
uni.navigateTo({
|
|
||||||
url: '/pages/login/agreementuser',// 替换为你要跳转的页面路径
|
|
||||||
});
|
|
||||||
},
|
|
||||||
addCar(){
|
|
||||||
if(uni.getStorageSync('is_login')){
|
|
||||||
uni.removeStorageSync('draftid')
|
|
||||||
uni.removeStorageSync('carinfo')
|
|
||||||
uni.navigateTo({
|
|
||||||
url: '/pages/carinfo/index'
|
|
||||||
});
|
|
||||||
}else{
|
|
||||||
this.show = true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
selfChangde(e) {
|
|
||||||
this.selfChecked = !this.selfChecked;
|
|
||||||
},
|
|
||||||
loginbtn(){
|
|
||||||
if(!this.selfChecked){
|
|
||||||
uni.showToast({
|
|
||||||
title:this.$t('home.arginimg'),
|
|
||||||
icon: 'none'
|
|
||||||
});
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getPhoneNumber(e) {
|
|
||||||
let that = this;
|
|
||||||
request({
|
|
||||||
url:'miniapp/phone',
|
|
||||||
method:'POST',
|
|
||||||
data:{
|
|
||||||
phone_code: e.detail.code,
|
|
||||||
}
|
|
||||||
}).then(res => {
|
|
||||||
if (res.data.code == -1) {
|
|
||||||
uni.showToast({
|
|
||||||
title: res.data.msg,
|
|
||||||
icon: 'none'
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if (res.data.code == 200) {
|
|
||||||
//返回数据接收成功
|
|
||||||
uni.setStorageSync('is_login', true);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
mini_login() {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
uni.login({
|
|
||||||
provider: 'weixin',
|
|
||||||
success: loginRes => {
|
|
||||||
|
|
||||||
// 一定要 return,不然 Promise 不会等待
|
|
||||||
return request({
|
|
||||||
url:'miniapp/login',
|
|
||||||
method:'POST',
|
|
||||||
data:{ code: loginRes.code }
|
|
||||||
}).then(res => {
|
|
||||||
|
|
||||||
if (res.data.code === 200) {
|
|
||||||
|
|
||||||
uni.setStorageSync('openid', res.data.data.openid);
|
|
||||||
uni.setStorageSync('token', res.data.data.token);
|
|
||||||
|
|
||||||
if (res.data.data.mobile) {
|
|
||||||
uni.setStorageSync('is_login', true);
|
|
||||||
} else {
|
|
||||||
uni.setStorageSync('is_login', false);
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve(true); // 👍 一定在 Promise 中
|
|
||||||
} else {
|
|
||||||
uni.showToast({
|
|
||||||
title: res.data.msg,
|
|
||||||
icon: 'none'
|
|
||||||
});
|
|
||||||
reject(res);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
fail: (err) => {
|
|
||||||
uni.showToast({
|
|
||||||
title: '获取 code 失败',
|
|
||||||
icon: 'none'
|
|
||||||
});
|
|
||||||
reject(err); // 👍 必须 reject
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss" scoped>
|
||||||
.home-page{
|
.page {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
background: #F5F6FA;
|
}
|
||||||
box-sizing: border-box;
|
|
||||||
padding-bottom: 120rpx;
|
.header {
|
||||||
}
|
position: relative;
|
||||||
.brand-header{
|
height: 720rpx;
|
||||||
display: flex;
|
}
|
||||||
justify-content: space-between;
|
.bg {
|
||||||
align-items: center;
|
width: 100%;
|
||||||
padding: 20rpx 30rpx;
|
height: 100%;
|
||||||
background: #F5F6FA;
|
border-bottom-left-radius: 30rpx;
|
||||||
}
|
border-bottom-right-radius: 30rpx;
|
||||||
.brand-left{
|
}
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
.title {
|
||||||
}
|
position: absolute;
|
||||||
.brand-text{
|
left: 40rpx;
|
||||||
font-size: 28rpx;
|
top: 300rpx;
|
||||||
color: #333;
|
font-size: 68rpx;
|
||||||
margin-right: 10rpx;
|
line-height: 1.2;
|
||||||
}
|
color: #fff;
|
||||||
.sun-icon{
|
font-weight: bold;
|
||||||
width: 24rpx;
|
}
|
||||||
height: 24rpx;
|
|
||||||
background: #FFB800;
|
.right-btns {
|
||||||
|
position: absolute;
|
||||||
|
right: 40rpx;
|
||||||
|
bottom: 100rpx;
|
||||||
|
|
||||||
|
.circle-btn {
|
||||||
|
margin-top: 20rpx;
|
||||||
|
width: 80rpx;
|
||||||
|
height: 80rpx;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
}
|
|
||||||
.brand-right{
|
|
||||||
font-size: 32rpx;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #3F435B;
|
|
||||||
}
|
|
||||||
.banner-swiper{
|
|
||||||
width: 100%;
|
|
||||||
height: 430rpx;
|
|
||||||
}
|
|
||||||
.banner-img{
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
.banner-desc{
|
|
||||||
position: absolute;
|
|
||||||
left: 30rpx;
|
|
||||||
bottom: 60rpx;
|
|
||||||
right: 30rpx;
|
|
||||||
}
|
|
||||||
.slogan-text{
|
|
||||||
display: block;
|
|
||||||
font-size: 48rpx;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #51B6FF;
|
|
||||||
text-shadow: 0 2rpx 8rpx rgba(0,0,0,0.2);
|
|
||||||
}
|
|
||||||
.content-grid{
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
padding: 20rpx;
|
|
||||||
justify-content: space-between;
|
|
||||||
background: #fff;
|
background: #fff;
|
||||||
}
|
|
||||||
.grid-item{
|
|
||||||
width: 48%;
|
|
||||||
overflow: hidden;
|
|
||||||
margin-bottom: 20rpx;
|
|
||||||
}
|
|
||||||
.grid-image{
|
|
||||||
width: 100%;
|
|
||||||
height: 320rpx;
|
|
||||||
background: #E5E5E5;
|
|
||||||
border-radius: 10rpx;
|
|
||||||
}
|
|
||||||
.grid-footer{
|
|
||||||
padding: 20rpx;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
image{
|
||||||
|
width: 48rpx;
|
||||||
|
height: 48rpx;
|
||||||
|
}
|
||||||
|
.share{
|
||||||
|
width: 36rpx;
|
||||||
|
height: 36rpx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.grid-avatar{
|
}
|
||||||
width: 48rpx;
|
/* 激活状态(弹幕开启) */
|
||||||
height: 48rpx;
|
.circle-btn.active {
|
||||||
border-radius: 50%;
|
background: #00c28a;
|
||||||
margin-right: 12rpx;
|
color: #fff;
|
||||||
flex-shrink: 0;
|
}
|
||||||
object-fit: cover;
|
.main-box {
|
||||||
display: block;
|
margin: 20rpx 30rpx;
|
||||||
}
|
margin-top: -60rpx;
|
||||||
.grid-info{
|
position: relative;
|
||||||
flex: 1;
|
background: #fff;
|
||||||
display: flex;
|
border-radius: 30rpx;
|
||||||
flex-direction: column;
|
.titles{
|
||||||
width: 87%;
|
font-size: 34rpx;
|
||||||
}
|
|
||||||
.grid-tag{
|
|
||||||
font-size: 24rpx;
|
|
||||||
color: #3F435B;
|
|
||||||
margin-bottom: 4rpx;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
width: 95%;
|
|
||||||
}
|
|
||||||
.grid-name{
|
|
||||||
font-size: 22rpx;
|
|
||||||
color: #8A8D97;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
width: 88%;
|
|
||||||
}
|
|
||||||
.popupcontent{
|
|
||||||
background-size: 100% 100%;
|
|
||||||
padding: 26px 15px;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background-repeat: no-repeat;
|
color: #000;
|
||||||
.title{
|
font-weight: bold;
|
||||||
color: #333333;
|
line-height: 88rpx;
|
||||||
font-size: 15px;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.log1{
|
}
|
||||||
width: 180px;
|
|
||||||
height: 180px;
|
.tabs {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-around;
|
||||||
|
gap: 20rpx;
|
||||||
|
margin-bottom: 30rpx;
|
||||||
|
|
||||||
|
.tab {
|
||||||
|
position: relative;
|
||||||
|
padding: 12rpx 24rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #000;
|
||||||
}
|
}
|
||||||
.yhxy{
|
.tab::after {
|
||||||
color: #999999;
|
content: '';
|
||||||
font-size: 12px;
|
position: absolute;
|
||||||
margin-bottom: 5px;
|
left: 50%;
|
||||||
.xy{
|
bottom: -10rpx;
|
||||||
color: #297EFF;
|
width: 60rpx;
|
||||||
}
|
height: 4rpx;
|
||||||
|
background: #3BC6BD;
|
||||||
|
border-radius: 4rpx;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.2s;
|
||||||
}
|
}
|
||||||
.cent{
|
.tab.on {
|
||||||
display: flex;
|
color: #3BC6BD;
|
||||||
align-items: center;
|
font-weight: 600;
|
||||||
justify-content: space-around;
|
|
||||||
padding: 0px 10px 20px;
|
|
||||||
.btn1{
|
|
||||||
background-color: #fff;
|
|
||||||
border: 1px solid #206ff4;
|
|
||||||
color: #206ff4;
|
|
||||||
border-radius: 50px;
|
|
||||||
width: 46%;
|
|
||||||
margin: 10px 0px 20px;
|
|
||||||
height: 50px;
|
|
||||||
line-height: 50px;
|
|
||||||
}
|
|
||||||
.btn{
|
|
||||||
background-color: #206ff4;
|
|
||||||
color: white;
|
|
||||||
border-radius: 50px;
|
|
||||||
width: 46%;
|
|
||||||
margin: 10px 0px 20px;
|
|
||||||
height: 50px;
|
|
||||||
line-height: 50px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
.tab.on::after {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
width: 1px;
|
||||||
|
height: 24rpx;
|
||||||
|
background: #dcdcdc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
padding: 10rpx;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -13,10 +13,41 @@
|
|||||||
<view class="cell1">
|
<view class="cell1">
|
||||||
<view>{{$t('mine.nickname')}}</view>
|
<view>{{$t('mine.nickname')}}</view>
|
||||||
<view class="right select">
|
<view class="right select">
|
||||||
<input :placeholder="$t('mine.nickinput')" v-model="userinfo.nickname"></input>
|
<input :placeholder="$t('mine.nickinput')" v-model="userinfo.nickname" />
|
||||||
<uni-icons type="right" size="18"></uni-icons>
|
<uni-icons type="right" size="18"></uni-icons>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
<view class="cell1">
|
||||||
|
<view>店铺名称</view>
|
||||||
|
<view class="right select">
|
||||||
|
<input placeholder="请填写名称" v-model="userinfo.shop_name" />
|
||||||
|
<uni-icons type="right" size="18"></uni-icons>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="cell1">
|
||||||
|
<view>店铺电话</view>
|
||||||
|
<view class="right select">
|
||||||
|
<input placeholder="请填写店铺电话" v-model="userinfo.mobile" />
|
||||||
|
<uni-icons type="right" size="18"></uni-icons>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="cell1">
|
||||||
|
<view>店铺位置</view>
|
||||||
|
<view class="right select">
|
||||||
|
<input placeholder="请选择店铺位置" v-model="userinfo.location_name" disabled="disabled" @focus="showMap = true" @click="showMap = true" />
|
||||||
|
<uni-icons type="right" size="18"></uni-icons>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view v-show="showMap" style="height: 300px; margin: 0 20px 20px 20px;">
|
||||||
|
<map
|
||||||
|
style="width: 100%; height: 100%;"
|
||||||
|
:latitude="centerLat"
|
||||||
|
:longitude="centerLng"
|
||||||
|
:markers="markers"
|
||||||
|
scale="14"
|
||||||
|
@tap="onMapTap"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="foot">
|
<view class="foot">
|
||||||
<button class="btn" @click="bcFn">{{$t('button.save')}}</button>
|
<button class="btn" @click="bcFn">{{$t('button.save')}}</button>
|
||||||
@@ -28,6 +59,12 @@
|
|||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
centerLat: 39.9042,
|
||||||
|
centerLng: 116.4074,
|
||||||
|
markers: [],
|
||||||
|
// 若需逆地理,请配置腾讯地图 key(可存储在此或通过 storage 注入)
|
||||||
|
qqMapKey: 'HQBBZ-SC76W-YUNRZ-34IAD-ARN6K-TZBZ4',
|
||||||
|
showMap: false,
|
||||||
imageStyles: {
|
imageStyles: {
|
||||||
width: 40,
|
width: 40,
|
||||||
height: 40,
|
height: 40,
|
||||||
@@ -38,8 +75,12 @@
|
|||||||
userinfo:{
|
userinfo:{
|
||||||
nickname:'',
|
nickname:'',
|
||||||
avatar:'',
|
avatar:'',
|
||||||
company:'',
|
|
||||||
phone:'',
|
phone:'',
|
||||||
|
shop_name:'',
|
||||||
|
mobile:'',
|
||||||
|
location_name:'',
|
||||||
|
latitude: null,
|
||||||
|
longitude: null
|
||||||
},
|
},
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -48,13 +89,124 @@
|
|||||||
this.getinfo()
|
this.getinfo()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
getFuzzy() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
wx.getSetting({
|
||||||
|
success: (st) => {
|
||||||
|
const ok = st.authSetting['scope.userFuzzyLocation'];
|
||||||
|
const run = () => wx.getFuzzyLocation({
|
||||||
|
type: 'wgs84',
|
||||||
|
success: resolve,
|
||||||
|
fail: reject
|
||||||
|
});
|
||||||
|
|
||||||
|
if (ok) return run();
|
||||||
|
|
||||||
|
wx.authorize({
|
||||||
|
scope: 'scope.userFuzzyLocation',
|
||||||
|
success: run,
|
||||||
|
fail: () => wx.openSetting({ success: () => reject(new Error('未授权')) })
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fail: reject
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 地图点选:更新“选点位置”marker
|
||||||
|
onMapTap(e) {
|
||||||
|
const { latitude, longitude } = e.detail || {};
|
||||||
|
if (typeof latitude !== 'number' || typeof longitude !== 'number') return;
|
||||||
|
|
||||||
|
// 用 id 2 表示“选点”
|
||||||
|
const picked = {
|
||||||
|
id: 2,
|
||||||
|
latitude,
|
||||||
|
longitude,
|
||||||
|
title: '选点位置'
|
||||||
|
};
|
||||||
|
|
||||||
|
// 只保留当前选点作为唯一标记
|
||||||
|
this.markers = [picked];
|
||||||
|
|
||||||
|
// 也可以把地图中心移动到选点
|
||||||
|
this.centerLat = latitude;
|
||||||
|
this.centerLng = longitude;
|
||||||
|
this.userinfo.latitude = latitude
|
||||||
|
this.userinfo.longitude = longitude
|
||||||
|
this.reverseGeocode(latitude, longitude)
|
||||||
|
},
|
||||||
getinfo(){
|
getinfo(){
|
||||||
var that= this;
|
|
||||||
request({
|
request({
|
||||||
url:'common/user/info',
|
url:'common/user/info',
|
||||||
method:'POST',
|
method:'POST',
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
this.userinfo=res.data.data.user
|
this.userinfo = res.data.data.user || {}
|
||||||
|
|
||||||
|
const lat = parseFloat(this.userinfo.latitude)
|
||||||
|
const lng = parseFloat(this.userinfo.longitude)
|
||||||
|
|
||||||
|
if (!isNaN(lat) && !isNaN(lng)) {
|
||||||
|
this.centerLat = lat
|
||||||
|
this.centerLng = lng
|
||||||
|
this.markers = [{
|
||||||
|
id: 1,
|
||||||
|
latitude: lat,
|
||||||
|
longitude: lng,
|
||||||
|
title: this.userinfo.location_name || '店铺位置'
|
||||||
|
}]
|
||||||
|
} else {
|
||||||
|
this.initFuzzyLocation()
|
||||||
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
this.initFuzzyLocation()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 优先使用接口位置,没有时回退到模糊定位
|
||||||
|
initFuzzyLocation() {
|
||||||
|
try {
|
||||||
|
this.getFuzzy().then(res => {
|
||||||
|
this.centerLat = res.latitude;
|
||||||
|
this.centerLng = res.longitude;
|
||||||
|
console.log(res)
|
||||||
|
// 默认给一个“当前位置(模糊)”标记
|
||||||
|
this.markers = [{
|
||||||
|
id: 1,
|
||||||
|
latitude: res.latitude,
|
||||||
|
longitude: res.longitude,
|
||||||
|
title: '当前位置(模糊)'
|
||||||
|
}];
|
||||||
|
}).catch(err => console.error(err));
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 逆地理:将经纬度转为位置文本,失败则回退为经纬度字符串
|
||||||
|
reverseGeocode(lat, lng) {
|
||||||
|
const key = this.qqMapKey || uni.getStorageSync('qqMapKey') || ''
|
||||||
|
if (!key) {
|
||||||
|
this.userinfo.location_name = `${lat.toFixed(6)}, ${lng.toFixed(6)}`
|
||||||
|
return
|
||||||
|
}
|
||||||
|
uni.request({
|
||||||
|
url: 'https://apis.map.qq.com/ws/geocoder/v1/',
|
||||||
|
method: 'GET',
|
||||||
|
data: {
|
||||||
|
location: `${lat},${lng}`,
|
||||||
|
key
|
||||||
|
},
|
||||||
|
success: (res) => {
|
||||||
|
if (res.data && res.data.status === 0) {
|
||||||
|
const result = res.data.result || {}
|
||||||
|
const formatted = (result.formatted_addresses && result.formatted_addresses.recommend) || result.address
|
||||||
|
this.userinfo.location_name = formatted || `${lat.toFixed(6)}, ${lng.toFixed(6)}`
|
||||||
|
} else {
|
||||||
|
this.userinfo.location_name = `${lat.toFixed(6)}, ${lng.toFixed(6)}`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: () => {
|
||||||
|
this.userinfo.location_name = `${lat.toFixed(6)}, ${lng.toFixed(6)}`
|
||||||
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
uploadfn(imgUrl){
|
uploadfn(imgUrl){
|
||||||
@@ -71,7 +223,7 @@
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
delfn(){
|
delfn(){
|
||||||
that.userinfo.avatar =''
|
this.userinfo.avatar =''
|
||||||
},
|
},
|
||||||
select(e){
|
select(e){
|
||||||
const tempFilePaths = e.tempFilePaths;
|
const tempFilePaths = e.tempFilePaths;
|
||||||
@@ -87,7 +239,12 @@
|
|||||||
method:'POST',
|
method:'POST',
|
||||||
data:{
|
data:{
|
||||||
nickname:this.userinfo.nickname,
|
nickname:this.userinfo.nickname,
|
||||||
avatar:this.userinfo.avatar
|
avatar:this.userinfo.avatar,
|
||||||
|
mobile:this.userinfo.mobile,
|
||||||
|
shop_name:this.userinfo.shop_name,
|
||||||
|
location_name:this.userinfo.location_name,
|
||||||
|
latitude:this.userinfo.latitude,
|
||||||
|
longitude:this.userinfo.longitude
|
||||||
}
|
}
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
|
|||||||
@@ -1,407 +1,232 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="content">
|
<view class="page">
|
||||||
<uni-nav-bar leftText=" " :fixed="true" :border="false" leftIcon="back" @clickLeft="leftClick" color="#000000" backgroundColor="#fff" :statusBar="true" title="我的发布"></uni-nav-bar>
|
<uni-nav-bar leftText=" " :fixed="true" :border="false" leftIcon="back" @clickLeft="leftClick" color="#000000" backgroundColor="#fff" :statusBar="true" title="我的发布"></uni-nav-bar>
|
||||||
|
<view>
|
||||||
<view class="year-selector" @click="showYearPicker">
|
<view class="tabs">
|
||||||
<text class="year-text">{{selectedYear}}年</text>
|
<u-tabs :list="list1" @click="click" lineColor="#3BC6BD" :scrollable="false"></u-tabs>
|
||||||
<uni-icons type="arrowdown" size="14" color="#666"></uni-icons>
|
</view>
|
||||||
</view>
|
<scroll-view
|
||||||
|
scroll-y
|
||||||
<scroll-view scroll-y class="scroll-container"
|
class="list-scroll"
|
||||||
refresher-enabled
|
refresher-enabled
|
||||||
:refresher-triggered="refreshing"
|
:refresher-triggered="refreshing"
|
||||||
@refresherrefresh="onRefresh"
|
@refresherrefresh="onRefresh"
|
||||||
:lower-threshold="100"
|
:lower-threshold="100"
|
||||||
@scrolltolower="onLoadMore">
|
@scrolltolower="onLoadMore"
|
||||||
<view class="post-list">
|
>
|
||||||
<view v-for="(group, dateKey) in groupedPosts" :key="dateKey" class="date-group">
|
<view class="feed-list">
|
||||||
<view class="date-item">
|
<post-card
|
||||||
<view class="date-label">
|
v-for="sitem in slist"
|
||||||
<text class="date-day">{{group.day}}</text>
|
:key="sitem.id"
|
||||||
<text class="date-month">{{group.month}}月</text>
|
:item="sitem"
|
||||||
</view>
|
:ismysq="true"
|
||||||
<view class="posts-container">
|
@userClick="goto"
|
||||||
<view v-for="post in group.posts" :key="post.id" class="post-item" @click="viewPost(post)">
|
@view="goto"
|
||||||
<image class="post-image" :src="post.media && post.media[0] ? post.media[0].url_pull : '/static/image/placeholder.png'" mode="aspectFill"></image>
|
@contact="handleContact"
|
||||||
<text class="post-tag">{{post.content || ''}}</text>
|
@comment="handleComment">
|
||||||
</view>
|
</post-card>
|
||||||
</view>
|
|
||||||
</view>
|
<!-- 状态提示 -->
|
||||||
</view>
|
<view v-if="hasMore" class="load-more">
|
||||||
|
<text v-if="loadingMore">加载中...</text>
|
||||||
<!-- 加载更多提示 -->
|
<text v-else>上拉加载更多</text>
|
||||||
<view v-if="hasMore && postList.length > 0" class="load-more">
|
</view>
|
||||||
<text v-if="loadingMore">加载中...</text>
|
<view v-else-if="slist.length > 0" class="load-more">
|
||||||
<text v-else>上拉加载更多</text>
|
<text>没有更多了</text>
|
||||||
</view>
|
</view>
|
||||||
<view v-else-if="!hasMore && postList.length > 0" class="load-more">
|
<view class="empty" v-if="slist.length === 0 && !loading">
|
||||||
<text>没有更多了</text>
|
<image src="/static/image/empty.png" mode="aspectFit"></image>
|
||||||
</view>
|
<view>暂无数据!</view>
|
||||||
|
</view>
|
||||||
<view v-if="postList.length === 0 && !loading && !loadingMore" class="empty-view">
|
</view>
|
||||||
<text>暂无发布内容</text>
|
</scroll-view>
|
||||||
</view>
|
|
||||||
|
<!-- 加载提示 -->
|
||||||
|
<view v-if="loading" class="loading-mask">
|
||||||
|
<view class="loading-text">加载中...</view>
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
|
||||||
|
|
||||||
<!-- 年份选择器 -->
|
|
||||||
<u-picker
|
|
||||||
:show="showYearSelect"
|
|
||||||
:columns="yearColumns"
|
|
||||||
:defaultIndex="defaultYearIndex"
|
|
||||||
keyName="label"
|
|
||||||
@confirm="onYearConfirm"
|
|
||||||
@cancel="showYearSelect = false"
|
|
||||||
title="选择年份">
|
|
||||||
</u-picker>
|
|
||||||
|
|
||||||
<!-- 加载提示 -->
|
|
||||||
<view v-if="loading" class="loading-mask">
|
|
||||||
<view class="loading-text">加载中...</view>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { request } from '@/api/apiT.js'
|
import { request } from '@/api/apiT.js'
|
||||||
export default {
|
import PostCard from '@/components/PostCard.vue'
|
||||||
data() {
|
import uTabs from '@/uni_modules/uview-ui/components/u-tabs/u-tabs.vue'
|
||||||
// 生成年份列表(当前年份前后5年)
|
export default {
|
||||||
const currentYear = new Date().getFullYear();
|
components: { PostCard,uTabs },
|
||||||
const years = [];
|
data() {
|
||||||
for (let i = currentYear - 5; i <= currentYear + 5; i++) {
|
return {
|
||||||
years.push({ label: i.toString(), value: i });
|
list1: [{
|
||||||
}
|
name: '全部',
|
||||||
|
value:''
|
||||||
return {
|
}, {
|
||||||
selectedYear: currentYear,
|
name: '已发布',
|
||||||
showYearSelect: false,
|
value:'1'
|
||||||
yearColumns: [years],
|
}, {
|
||||||
postList: [],
|
name: '审核中',
|
||||||
groupedPosts: {},
|
value:'2'
|
||||||
loading: false,
|
}, {
|
||||||
refreshing: false,
|
name: '未通过',
|
||||||
loadingMore: false, // 上拉加载状态
|
value:'3'
|
||||||
page: 1, // 当前页码
|
}, {
|
||||||
pageSize: 10, // 每页数量
|
name: '已过期',
|
||||||
hasMore: true, // 是否还有更多数据
|
value:'4'
|
||||||
total: 0, // 总数据量
|
}],
|
||||||
}
|
status:'',
|
||||||
},
|
slist:[],
|
||||||
computed: {
|
loading: false,
|
||||||
// 计算当前年份在选择器中的默认索引
|
refreshing: false,
|
||||||
defaultYearIndex() {
|
loadingMore: false,
|
||||||
const currentYear = new Date().getFullYear();
|
page: 1,
|
||||||
const startYear = currentYear - 5;
|
pageSize: 10,
|
||||||
return [currentYear - startYear]; // 当前年份在数组中的索引
|
hasMore: true,
|
||||||
}
|
defaultTags: ['样机机', '9成新']
|
||||||
},
|
}
|
||||||
onLoad() {
|
},
|
||||||
this.loadPostList();
|
onShow() {
|
||||||
},
|
this.loadList()
|
||||||
methods: {
|
// this.syncTabbar()
|
||||||
leftClick() {
|
},
|
||||||
// uni.navigateBack()
|
methods: {
|
||||||
uni.reLaunch({
|
leftClick() {
|
||||||
url: '/pages/index/mine',// 替换为你要跳转的页面路径
|
// uni.navigateBack()
|
||||||
});
|
uni.reLaunch({
|
||||||
},
|
url: '/pages/index/mine',// 替换为你要跳转的页面路径
|
||||||
showYearPicker() {
|
});
|
||||||
this.showYearSelect = true;
|
},
|
||||||
},
|
goto(item){
|
||||||
onYearConfirm(e) {
|
uni.navigateTo({
|
||||||
if (e.value && e.value[0]) {
|
url: '/pages/square/detiles?id='+item.id
|
||||||
const selectedItem = typeof e.value[0] === 'object' ? e.value[0] : { value: e.value[0], label: e.value[0].toString() };
|
});
|
||||||
this.selectedYear = selectedItem.value || parseInt(selectedItem.label);
|
},
|
||||||
this.showYearSelect = false;
|
click(item) {
|
||||||
// 切换年份时重置分页
|
this.page = 1
|
||||||
this.page = 1;
|
this.hasMore = true
|
||||||
this.hasMore = true;
|
this.slist = []
|
||||||
this.postList = [];
|
this.status=item.value
|
||||||
this.groupedPosts = {};
|
this.loadList()
|
||||||
this.loadPostList(false);
|
},
|
||||||
}
|
loadList(isLoadMore = false) {
|
||||||
},
|
if (isLoadMore) {
|
||||||
// 加载帖子列表
|
if (this.loadingMore || this.loading || this.refreshing || !this.hasMore) return
|
||||||
loadPostList(isLoadMore = false) {
|
this.loadingMore = true
|
||||||
// 防止重复请求
|
this.page += 1
|
||||||
if (isLoadMore) {
|
} else {
|
||||||
if (this.loadingMore || this.loading || this.refreshing || !this.hasMore) {
|
if (this.loading || this.loadingMore) return
|
||||||
return;
|
this.loading = true
|
||||||
}
|
this.page = 1
|
||||||
this.loadingMore = true;
|
this.hasMore = true
|
||||||
this.page += 1;
|
this.slist = []
|
||||||
} else {
|
}
|
||||||
if (this.loading && !this.refreshing) {
|
request({
|
||||||
return;
|
url: 'common/post/list',
|
||||||
}
|
method: 'GET',
|
||||||
this.loading = true;
|
data: {
|
||||||
this.page = 1;
|
current: this.page,
|
||||||
this.hasMore = true;
|
size: this.pageSize,
|
||||||
if (!isLoadMore && !this.refreshing) {
|
status: this.status
|
||||||
this.postList = [];
|
}
|
||||||
this.groupedPosts = {};
|
}).then(res => {
|
||||||
}
|
this.loading = false
|
||||||
}
|
this.loadingMore = false
|
||||||
|
this.refreshing = false
|
||||||
// 获取当前用户发布的帖子列表
|
if (res.data.code === 200) {
|
||||||
request({
|
const records = res.data.data.records || []
|
||||||
url: 'common/post/list',
|
const total = res.data.data.total || 0
|
||||||
method: 'GET',
|
if (isLoadMore) {
|
||||||
data: {
|
this.slist = [...this.slist, ...records]
|
||||||
// 只获取当前用户发布的帖子,后端应该根据token自动过滤
|
} else {
|
||||||
current: this.page,
|
this.slist = records
|
||||||
size: this.pageSize,
|
}
|
||||||
scene:'self',
|
this.hasMore = this.slist.length < total
|
||||||
year:this.selectedYear
|
}
|
||||||
}
|
}).catch(() => {
|
||||||
}).then(res => {
|
this.loading = false
|
||||||
this.loading = false;
|
this.loadingMore = false
|
||||||
this.loadingMore = false;
|
this.refreshing = false
|
||||||
this.refreshing = false;
|
if (isLoadMore) {
|
||||||
|
this.page -= 1
|
||||||
if (res.data.code == 200) {
|
}
|
||||||
const records = res.data.data.records || [];
|
})
|
||||||
const total = res.data.data.total || 0;
|
},
|
||||||
this.total = total;
|
onRefresh() {
|
||||||
|
if (this.loading || this.loadingMore) {
|
||||||
// 过滤出当前年份的数据
|
this.refreshing = false
|
||||||
const yearFilteredRecords = records.filter(post => {
|
return
|
||||||
if (!post.created_at) return false;
|
}
|
||||||
const dateStr = post.created_at;
|
this.refreshing = true
|
||||||
const postYear = new Date(dateStr).getFullYear();
|
this.loadList(false)
|
||||||
return postYear === this.selectedYear;
|
},
|
||||||
});
|
onLoadMore() {
|
||||||
|
this.loadList(true)
|
||||||
if (isLoadMore) {
|
},
|
||||||
// 上拉加载更多,追加数据并去重
|
navToList(item) {
|
||||||
const existingIds = new Set(this.postList.map(item => item.id));
|
uni.navigateTo({
|
||||||
const newRecords = yearFilteredRecords.filter(item => !existingIds.has(item.id));
|
url: '/pages/square/detiles?id=' + item.id
|
||||||
this.postList = [...this.postList, ...newRecords];
|
})
|
||||||
} else {
|
},
|
||||||
// 下拉刷新或初次加载,替换数据
|
leftClick() {
|
||||||
this.postList = yearFilteredRecords;
|
uni.navigateBack()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// 重新分组
|
}
|
||||||
this.groupPostsByDate();
|
|
||||||
|
|
||||||
// 判断是否还有更多数据
|
|
||||||
// 如果当前页返回的原始数据少于pageSize,说明没有更多了
|
|
||||||
// 或者已经加载到最后一页
|
|
||||||
if (records.length < this.pageSize) {
|
|
||||||
this.hasMore = false;
|
|
||||||
} else {
|
|
||||||
// 计算理论上最多能加载多少页
|
|
||||||
const maxPages = Math.ceil(total / this.pageSize);
|
|
||||||
this.hasMore = this.page < maxPages;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).catch(() => {
|
|
||||||
this.loading = false;
|
|
||||||
this.loadingMore = false;
|
|
||||||
this.refreshing = false;
|
|
||||||
if (isLoadMore) {
|
|
||||||
this.page -= 1; // 加载失败,页码回退
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
// 按日期分组帖子
|
|
||||||
groupPostsByDate() {
|
|
||||||
const grouped = {};
|
|
||||||
|
|
||||||
this.postList.forEach(post => {
|
|
||||||
const dateStr = post.created_at || post.create_time || post.createdAt;
|
|
||||||
if (!dateStr) return;
|
|
||||||
|
|
||||||
const date = new Date(dateStr);
|
|
||||||
const month = date.getMonth() + 1; // 月份从0开始,需要+1
|
|
||||||
const day = date.getDate();
|
|
||||||
|
|
||||||
// 生成日期key,格式:MM-DD,用于排序
|
|
||||||
const dateKey = `${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
|
|
||||||
|
|
||||||
if (!grouped[dateKey]) {
|
|
||||||
grouped[dateKey] = {
|
|
||||||
day: day,
|
|
||||||
month: month,
|
|
||||||
posts: []
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
grouped[dateKey].posts.push(post);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 按日期倒序排序(最新的在前)
|
|
||||||
const sortedKeys = Object.keys(grouped).sort((a, b) => {
|
|
||||||
// 按完整日期排序(年-月-日)
|
|
||||||
const dateA = new Date(this.selectedYear, parseInt(a.split('-')[0]) - 1, parseInt(a.split('-')[1]));
|
|
||||||
const dateB = new Date(this.selectedYear, parseInt(b.split('-')[0]) - 1, parseInt(b.split('-')[1]));
|
|
||||||
return dateB - dateA; // 倒序:最新的在前
|
|
||||||
});
|
|
||||||
|
|
||||||
// 重新构建分组对象,保持顺序
|
|
||||||
const sortedGrouped = {};
|
|
||||||
sortedKeys.forEach(key => {
|
|
||||||
sortedGrouped[key] = grouped[key];
|
|
||||||
});
|
|
||||||
|
|
||||||
this.groupedPosts = sortedGrouped;
|
|
||||||
},
|
|
||||||
// 下拉刷新
|
|
||||||
onRefresh() {
|
|
||||||
// 如果正在加载中,不执行刷新
|
|
||||||
if (this.loading || this.loadingMore) {
|
|
||||||
this.refreshing = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.refreshing = true;
|
|
||||||
this.page = 1;
|
|
||||||
this.hasMore = true;
|
|
||||||
this.loadPostList(false);
|
|
||||||
},
|
|
||||||
// 上拉加载更多
|
|
||||||
onLoadMore() {
|
|
||||||
if (!this.hasMore || this.loadingMore || this.loading || this.refreshing) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.loadPostList(true);
|
|
||||||
},
|
|
||||||
// 查看帖子详情
|
|
||||||
viewPost(post) {
|
|
||||||
// TODO: 跳转到帖子详情页
|
|
||||||
uni.navigateTo({
|
|
||||||
url: '/pages/square/detiles?id='+post.id
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
page,
|
page,
|
||||||
.content {
|
.page {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: #fff;
|
background: #f8f8f8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.year-selector {
|
.tabs{
|
||||||
display: flex;
|
background: #fff;
|
||||||
align-items: center;
|
}
|
||||||
justify-content: space-between;
|
|
||||||
padding: 20rpx 30rpx;
|
.list-scroll {
|
||||||
background-color: #F5F5F5;
|
height: calc(100vh - 120rpx);
|
||||||
|
}
|
||||||
.year-text {
|
|
||||||
font-size: 28rpx;
|
.feed-list {
|
||||||
color: #333;
|
// padding: 20rpx;
|
||||||
}
|
margin: 20rpx 30rpx;
|
||||||
|
}
|
||||||
.arrow-icon {
|
.load-more {
|
||||||
width: 24rpx;
|
width: 100%;
|
||||||
height: 24rpx;
|
text-align: center;
|
||||||
}
|
padding: 30rpx 0;
|
||||||
}
|
font-size: 26rpx;
|
||||||
|
color: #999;
|
||||||
.scroll-container {
|
}
|
||||||
height: calc(100% - 168rpx); // 减去导航栏和年份选择器高度
|
.empty {
|
||||||
}
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
.post-list {
|
padding: 100rpx 0;
|
||||||
padding: 20rpx 0;
|
}
|
||||||
}
|
.empty image {
|
||||||
|
width: 252rpx;
|
||||||
.date-group {
|
height: 164rpx;
|
||||||
margin-bottom: 40rpx;
|
margin-bottom: 20rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.date-item {
|
.loading-mask {
|
||||||
display: flex;
|
position: fixed;
|
||||||
padding: 0 30rpx;
|
top: 0;
|
||||||
}
|
left: 0;
|
||||||
|
right: 0;
|
||||||
.date-label {
|
bottom: 0;
|
||||||
display: flex;
|
background-color: rgba(0, 0, 0, 0.3);
|
||||||
// flex-direction: column;
|
display: flex;
|
||||||
// align-items: center;
|
align-items: center;
|
||||||
margin-right: 30rpx;
|
justify-content: center;
|
||||||
min-width: 120rpx;
|
z-index: 999;
|
||||||
|
|
||||||
.date-day {
|
.loading-text {
|
||||||
font-size: 48rpx;
|
color: #fff;
|
||||||
font-weight: bold;
|
font-size: 28upx;
|
||||||
color: #333;
|
background-color: rgba(0, 0, 0, 0.7);
|
||||||
line-height: 1;
|
padding: 20upx 40upx;
|
||||||
}
|
border-radius: 8upx;
|
||||||
|
}
|
||||||
.date-month {
|
}
|
||||||
font-size: 24rpx;
|
|
||||||
color: #666;
|
|
||||||
margin-top: 8rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.posts-container {
|
|
||||||
flex: 1;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 20rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.post-item {
|
|
||||||
display: flex;
|
|
||||||
// align-items: center;
|
|
||||||
margin-bottom: 30rpx;
|
|
||||||
|
|
||||||
.post-image {
|
|
||||||
width: 200rpx;
|
|
||||||
height: 200rpx;
|
|
||||||
background-color: #E5E5E5;
|
|
||||||
border-radius: 10rpx;
|
|
||||||
margin-right: 30rpx;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.post-tag {
|
|
||||||
font-size: 28rpx;
|
|
||||||
color: #333;
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.empty-view {
|
|
||||||
text-align: center;
|
|
||||||
padding: 100rpx 0;
|
|
||||||
color: #999;
|
|
||||||
font-size: 28rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.load-more {
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
padding: 30rpx 0;
|
|
||||||
font-size: 26rpx;
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loading-mask {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background-color: rgba(0, 0, 0, 0.3);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
z-index: 999;
|
|
||||||
|
|
||||||
.loading-text {
|
|
||||||
color: #fff;
|
|
||||||
font-size: 28rpx;
|
|
||||||
background-color: rgba(0, 0, 0, 0.7);
|
|
||||||
padding: 20rpx 40rpx;
|
|
||||||
border-radius: 8rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
@@ -2,21 +2,23 @@
|
|||||||
<view class="home-page">
|
<view class="home-page">
|
||||||
<z-paging ref="paging" v-model="contList" @query="queryList" empty-view-text="暂无消息">
|
<z-paging ref="paging" v-model="contList" @query="queryList" empty-view-text="暂无消息">
|
||||||
<template #top>
|
<template #top>
|
||||||
<uni-nav-bar leftText=" " :fixed="true" :border="false" leftIcon="back" @clickLeft="leftClick" color="#000000" backgroundColor="#fff" :statusBar="true" title="最新消息"></uni-nav-bar>
|
<uni-nav-bar leftText=" " :fixed="true" :border="false" leftIcon="back" @clickLeft="leftClick" color="#000000" backgroundColor="#fff" :statusBar="true" title="我的信息"></uni-nav-bar>
|
||||||
</template>
|
</template>
|
||||||
<view class="msg-list">
|
<view class="msg-list">
|
||||||
<view class="msg-item" v-for="item in contList" :key="item.id">
|
<view class="msg-item" v-for="item in contList" :key="item.id">
|
||||||
<image class="msg-avatar" :src="item.sender_user.avatar_pull" mode="aspectFill"></image>
|
<view class="msg-cont">
|
||||||
<view class="msg-body">
|
<image class="msg-avatar" :src="item.sender_user.avatar_pull" mode="aspectFill"></image>
|
||||||
<view class="msg-header">
|
<view class="msg-body">
|
||||||
<text class="msg-name">{{item.sender_user.nickname}}</text>
|
<view class="msg-header">
|
||||||
<text class="msg-time">{{item.created_at}}</text>
|
<text class="msg-name">{{item.sender_user.nickname}}</text>
|
||||||
|
<!-- <text class="msg-time">{{item.created_at}}</text> -->
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<text class="msg-text">
|
|
||||||
<text>{{ item.type==1?'点赞了': item.type==2?'收藏了':'评论了' }} </text>
|
|
||||||
<text>{{ formatContent(item.post && item.post.content) }}</text>
|
|
||||||
</text>
|
|
||||||
</view>
|
</view>
|
||||||
|
<view class="msg-text">
|
||||||
|
<text>{{ formatContent(item.post && item.post.content) }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</z-paging>
|
</z-paging>
|
||||||
@@ -80,15 +82,18 @@
|
|||||||
padding: 20rpx;
|
padding: 20rpx;
|
||||||
}
|
}
|
||||||
.msg-item{
|
.msg-item{
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 24rpx 20rpx;
|
padding: 24rpx 20rpx;
|
||||||
margin-bottom: 20rpx;
|
margin-bottom: 20rpx;
|
||||||
border-bottom: 1px solid #e4e4e4;
|
background: #fff;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
}
|
||||||
|
.msg-cont{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
.msg-avatar{
|
.msg-avatar{
|
||||||
width: 96rpx;
|
width: 60rpx;
|
||||||
height: 96rpx;
|
height: 60rpx;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
margin-right: 20rpx;
|
margin-right: 20rpx;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,15 +6,12 @@
|
|||||||
</template>
|
</template>
|
||||||
<!-- 内容网格 -->
|
<!-- 内容网格 -->
|
||||||
<view class="content-grid">
|
<view class="content-grid">
|
||||||
<square-post-card
|
<classify-card
|
||||||
class="grid-item"
|
v-for="item in contList"
|
||||||
v-for="sitem in contList"
|
:key="item.id"
|
||||||
:key="sitem.id"
|
:item="item.post"
|
||||||
:item="sitem.post"
|
@view="navToList"
|
||||||
:isshow="false"
|
/>
|
||||||
@view="navToList"
|
|
||||||
@comment="viewPost"
|
|
||||||
@like="viewPost" />
|
|
||||||
</view>
|
</view>
|
||||||
</z-paging>
|
</z-paging>
|
||||||
</view>
|
</view>
|
||||||
@@ -22,10 +19,10 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { request,showToast } from '@/api/apiT.js'
|
import { request,showToast } from '@/api/apiT.js'
|
||||||
import SquarePostCard from '@/components/SquarePostCard.vue'
|
import ClassifyCard from '@/components/ClassifyCard.vue'
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
SquarePostCard
|
ClassifyCard
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -87,11 +84,7 @@
|
|||||||
padding-bottom: 120rpx;
|
padding-bottom: 120rpx;
|
||||||
}
|
}
|
||||||
.content-grid{
|
.content-grid{
|
||||||
display: flex;
|
margin-top: 20rpx;
|
||||||
flex-wrap: wrap;
|
|
||||||
padding: 20rpx;
|
|
||||||
justify-content: space-between;
|
|
||||||
background: #fff;
|
|
||||||
}
|
}
|
||||||
.grid-item{
|
.grid-item{
|
||||||
width: 48%;
|
width: 48%;
|
||||||
|
|||||||
@@ -0,0 +1,154 @@
|
|||||||
|
<template>
|
||||||
|
<view class="container">
|
||||||
|
<uni-nav-bar leftText=" " :fixed="true" :border="false" leftIcon="back" @clickLeft="leftClick" color="#000000" backgroundColor="#fff" :statusBar="true" title="回复我的"></uni-nav-bar>
|
||||||
|
|
||||||
|
<view class="reply-list">
|
||||||
|
<view class="reply-card" v-for="(reply, index) in replyList" :key="index">
|
||||||
|
<!-- 主回复 -->
|
||||||
|
<view class="reply-item">
|
||||||
|
<view class="reply-heard">
|
||||||
|
<image :src="reply.avatar" class="avatar"></image>
|
||||||
|
<view class="reply-content">
|
||||||
|
<view class="username">{{ reply.username }}</view>
|
||||||
|
<view class="time">{{ reply.time }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="reply-content">
|
||||||
|
<text class="reply-text">{{ reply.content }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
<!-- 子回复 -->
|
||||||
|
<view class="sub-reply" v-for="(subReply, subIndex) in reply.subReplies" :key="subIndex">
|
||||||
|
<view class="reply-heard">
|
||||||
|
<image :src="subReply.avatar" class="avatar"></image>
|
||||||
|
<view class="reply-header">
|
||||||
|
<view class="username">{{ subReply.username }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="reply-content">
|
||||||
|
<text class="reply-text">{{ subReply.content }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
replyList: [
|
||||||
|
{
|
||||||
|
avatar: '/static/image/user.png',
|
||||||
|
username: '用户名用户名',
|
||||||
|
time: '2025年12月04日10:56:44',
|
||||||
|
content: '这是回复这是回复这是回复这是回复这是回复这是回复这是回复这是回复这是回复这是回复这是回复这是回复',
|
||||||
|
subReplies: [
|
||||||
|
{
|
||||||
|
avatar: '/static/image/user.png',
|
||||||
|
username: '田户名田户名',
|
||||||
|
time: '2025年12月04日10:56:44',
|
||||||
|
content: '西门子全新款饮机品牌西门子全新款饮机品牌西门子全新...'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
avatar: '/static/image/user.png',
|
||||||
|
username: '用户名用户名',
|
||||||
|
time: '2025年12月04日10:56:44',
|
||||||
|
content: '这是回复这是回复这是回复这是回复这是回复这是回复这是回复这是回复这是回复这是回复这是回复这是回复',
|
||||||
|
subReplies: [
|
||||||
|
{
|
||||||
|
avatar: '/static/image/user.png',
|
||||||
|
username: '用户名用户名',
|
||||||
|
time: '2025年12月04日10:56:44',
|
||||||
|
content: '西门子全新款饮机品牌西门子全新款饮机品牌西门子全新...'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
leftClick() {
|
||||||
|
uni.reLaunch({
|
||||||
|
url: '/pages/index/mine',// 替换为你要跳转的页面路径
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.container {
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reply-list {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reply-card {
|
||||||
|
background-color: #fff;
|
||||||
|
margin: 10px;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 12px;
|
||||||
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.reply-item {
|
||||||
|
/* display: flex; */
|
||||||
|
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
.reply-heard{
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
.sub-reply {
|
||||||
|
/* margin-left: 30px; */
|
||||||
|
padding:8px 12px;
|
||||||
|
background-color: #F5F6FA;
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 50%;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reply-content {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reply-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.username {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #333;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reply-text {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #666;
|
||||||
|
line-height: 1.5;
|
||||||
|
word-break: break-all;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,68 +1,87 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="publish-page">
|
<view class="publish-page">
|
||||||
<uni-nav-bar leftText=" " :fixed="true" :border="false" @clickLeft="leftClick" color="#000000" backgroundColor="#fff" :statusBar="true" title="发布页"></uni-nav-bar>
|
<uni-nav-bar leftText=" " :fixed="true" :border="false" @clickLeft="leftClick" color="#000000" backgroundColor="#fff" :statusBar="true" title="样机发布"></uni-nav-bar>
|
||||||
<view class="form-card">
|
<view class="form-card">
|
||||||
<view class="section-label">选择发布标签</view>
|
<view class="select-input gradient-bg" @click="showSelect1 = true">
|
||||||
<picker mode="selector" :range="categoryOptions" range-key="name" @change="onCategoryChange">
|
<view class="category-content">
|
||||||
<view class="select-input gradient-bg">
|
<text class="category-text">{{form.category || '请输入/选择型号'}}</text>
|
||||||
<view class="category-content">
|
|
||||||
<view class="fridge-icon">
|
|
||||||
<image :src="iconurl" mode=""></image>
|
|
||||||
</view>
|
|
||||||
<text class="category-text">{{form.category || '请选择发布标签'}}</text>
|
|
||||||
</view>
|
|
||||||
<u-icon name="arrow-down" color="#fff" size="20"></u-icon>
|
|
||||||
</view>
|
</view>
|
||||||
</picker>
|
<u-icon name="arrow-down" color="#3BC8BE" size="20"></u-icon>
|
||||||
<view class="mag-top">
|
|
||||||
<textarea v-model="form.content" class="content-textarea" placeholder="请输入文字内容"
|
|
||||||
:maxlength="maxWords" @input="handleContentInput" />
|
|
||||||
</view>
|
</view>
|
||||||
|
<view class="conts mag-top">
|
||||||
<view class="media-upload-wrapper mag-top">
|
<view class="">
|
||||||
<uni-file-picker fileMediatype="image" limit="9" @select="selectMedia" @delete="delfn" :imageStyles="imageStyles">
|
<textarea v-model="form.content" class="content-textarea" placeholder="请输入文字内容"
|
||||||
<view class="upload-icon-wrapper">
|
:maxlength="maxWords" @input="handleContentInput" />
|
||||||
<image src="/static/image/photo.png" mode="" class="addimg"></image>
|
</view>
|
||||||
<text class="upload-text">添加图片</text>
|
|
||||||
</view>
|
<view class="media-upload-wrapper">
|
||||||
</uni-file-picker>
|
<uni-file-picker fileMediatype="image" limit="9" @select="selectMedia" @delete="delfn" :imageStyles="imageStyles">
|
||||||
<!-- <view class="upload-area" @click="selectMedia" v-if="form.media.length < maxMedia">
|
<view class="upload-icon-wrapper">
|
||||||
<view class="upload-icon-wrapper">
|
<image src="/static/image/photo.png" mode="" class="addimg"></image>
|
||||||
<view class="camera-icon">
|
|
||||||
<image src="/static/image/photo.png" mode=""></image>
|
|
||||||
</view>
|
</view>
|
||||||
<text class="upload-text">添加图片</text>
|
</uni-file-picker>
|
||||||
</view>
|
</view>
|
||||||
</view> -->
|
<view class="help-text">
|
||||||
<!-- <view class="media-preview" v-for="(item, index) in form.media" :key="index">
|
<u-icon name="info-circle" size="18" color="#A6ABB7"></u-icon>
|
||||||
<image :src="item.url" mode="aspectFill" class="preview-image"></image>
|
<text>文字不多于2000字,图片不多于9张</text>
|
||||||
<view class="delete-btn" @click.stop="deleteMedia(index)">
|
</view>
|
||||||
<u-icon name="close" size="18" color="#fff"></u-icon>
|
|
||||||
</view>
|
|
||||||
</view> -->
|
|
||||||
</view>
|
</view>
|
||||||
<view class="help-text">
|
<view class="mag-top">
|
||||||
<u-icon name="info-circle" size="18" color="#A6ABB7"></u-icon>
|
<picker mode="selector" :range="conditionOptions" range-key="name" @change="onCategoryChange">
|
||||||
<text>文字不多于2000字,图片不多于9张</text>
|
<view class="select-input gradient-bg">
|
||||||
|
<view class="category-content">
|
||||||
|
<text class="category-text">{{form.agename || '请选择样机新旧程度'}}</text>
|
||||||
|
</view>
|
||||||
|
<u-icon name="arrow-down" color="#3BC8BE" size="20"></u-icon>
|
||||||
|
</view>
|
||||||
|
</picker>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
<view class="mag-top">
|
||||||
|
<input class="uni-input" focus v-model="form.price" placeholder="请输入折扣价格" />
|
||||||
<view class="agreement">
|
</view>
|
||||||
<label class="agree-label" @click="toggleAgreement">
|
<view class="detils">
|
||||||
<checkbox :checked="agree" style="transform:scale(0.8)"></checkbox>
|
<view v-html="productcontents">
|
||||||
<text>我已阅读并同意</text>
|
|
||||||
<text class="link" @click.stop="viewAgreement">《发布协议》</text>
|
|
||||||
</label>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- <button class="primary-btn gradient-btn" :class="{disabled: !canSubmit}" :disabled="!canSubmit" @click="submitForm">立即发布</button> -->
|
|
||||||
<button class="primary-btn gradient-btn" @click="submitForm">立即发布</button>
|
|
||||||
<u-popup :show="show" :closeOnClickOverlay="false" :round="10" mode="center">
|
|
||||||
<view class="cont-text" >
|
|
||||||
<view class="" v-html="viewAgreementcont">
|
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 型号选择弹层 -->
|
||||||
|
<view v-if="showSelect1" class="select-popup">
|
||||||
|
<view class="popup-mask" @click="showSelect1=false"></view>
|
||||||
|
<view class="popup-panel">
|
||||||
|
<view class="popup-header">
|
||||||
|
<input class="popup-search" v-model="searchKey1" placeholder="搜索型号" />
|
||||||
|
<text class="popup-close" @click="showSelect1=false">取消</text>
|
||||||
|
</view>
|
||||||
|
<scroll-view scroll-y class="popup-list">
|
||||||
|
<view
|
||||||
|
v-for="item in filteredCategories"
|
||||||
|
:key="item.id"
|
||||||
|
class="popup-item"
|
||||||
|
@click="selectCategory(item)"
|
||||||
|
>
|
||||||
|
{{ item.model }}
|
||||||
|
</view>
|
||||||
|
<view v-if="!filteredCategories.length" class="popup-empty">暂无数据</view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="foot">
|
||||||
|
<view class="agreement">
|
||||||
|
<label class="agree-label" @click="toggleAgreement">
|
||||||
|
<checkbox :checked="agree" style="transform:scale(0.8)"></checkbox>
|
||||||
|
<text>我已阅读并同意</text>
|
||||||
|
<text class="link" @click.stop="viewAgreement">《发布协议》</text>
|
||||||
|
</label>
|
||||||
|
<button class="primary-btn gradient-btn" @click="submitForm">立即发布</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<u-popup :show="show" :closeOnClickOverlay="false" :round="10" mode="center">
|
||||||
|
<view class="cont-text" >
|
||||||
|
<rich-text :nodes="viewAgreementcont"></rich-text>
|
||||||
|
</view>
|
||||||
<view class="cent">
|
<view class="cent">
|
||||||
<button class="btn1" @click="show = !show">取消</button>
|
<button class="btn1" @click="show = !show">取消</button>
|
||||||
<button class="btn" @click="agreementbtn">确定</button>
|
<button class="btn" @click="agreementbtn">确定</button>
|
||||||
@@ -94,17 +113,36 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { request,showToast } from '@/api/apiT.js'
|
import { request,showToast } from '@/api/apiT.js'
|
||||||
export default {
|
export default {
|
||||||
name: 'PublishPage',
|
name: 'PublishPage',
|
||||||
data(){
|
data(){
|
||||||
return {
|
return {
|
||||||
|
showSelect1:false,
|
||||||
|
showSelect2:false,
|
||||||
|
searchKey1:'',
|
||||||
|
productcontents:'',
|
||||||
categoryOptions:[],
|
categoryOptions:[],
|
||||||
|
conditionOptions:[
|
||||||
|
{name:'全新',value:'10'},
|
||||||
|
{name:'9成新',value:'9'},
|
||||||
|
{name:'8成新',value:'8'},
|
||||||
|
{name:'7成新',value:'7'},
|
||||||
|
{name:'6成新',value:'6'},
|
||||||
|
{name:'5成新',value:'5'},
|
||||||
|
{name:'4成新',value:'4'},
|
||||||
|
{name:'3成新',value:'3'},
|
||||||
|
{name:'2成新',value:'2'},
|
||||||
|
{name:'1成新',value:'1'},
|
||||||
|
],
|
||||||
form:{
|
form:{
|
||||||
|
agename:'',
|
||||||
|
age:'',
|
||||||
category:'',
|
category:'',
|
||||||
category_id:'',
|
sku_id:'',
|
||||||
content:'',
|
content:'',
|
||||||
media:[]
|
media:[],
|
||||||
|
price:''
|
||||||
},
|
},
|
||||||
selfChecked: false,
|
selfChecked: false,
|
||||||
showlogin:false,
|
showlogin:false,
|
||||||
@@ -119,16 +157,38 @@ export default {
|
|||||||
computed:{
|
computed:{
|
||||||
canSubmit(){
|
canSubmit(){
|
||||||
return this.agree && this.form.content.trim().length>0 && this.form.media.length>0
|
return this.agree && this.form.content.trim().length>0 && this.form.media.length>0
|
||||||
}
|
},
|
||||||
|
filteredCategories(){
|
||||||
|
if(!this.searchKey1) return this.categoryOptions
|
||||||
|
return this.categoryOptions.filter(i => (i.model || '').toLowerCase().includes(this.searchKey1.toLowerCase()))
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onLoad() {
|
onLoad() {
|
||||||
this.getcategory()
|
this.getcategory()
|
||||||
},
|
},
|
||||||
onShow() {
|
onShow() {
|
||||||
|
// this.getset()
|
||||||
this.syncTabbar()
|
// this.syncTabbar()
|
||||||
},
|
},
|
||||||
methods:{
|
methods:{
|
||||||
|
getlocation(){
|
||||||
|
wx.getFuzzyLocation({
|
||||||
|
type: 'wgs84',
|
||||||
|
success(res) {
|
||||||
|
console.log("模糊定位:", res)
|
||||||
|
},
|
||||||
|
fail(err) {
|
||||||
|
console.log("模糊定位失败:", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
selectCategory(item){
|
||||||
|
this.form.category = item.model || ''
|
||||||
|
this.form.sku_id = item.id || ''
|
||||||
|
this.productcontents = item.desc || ''
|
||||||
|
console.log(this.productcontents)
|
||||||
|
this.showSelect1 = false
|
||||||
|
},
|
||||||
goprivacy(){
|
goprivacy(){
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: '/pages/login/agreement',// 替换为你要跳转的页面路径
|
url: '/pages/login/agreement',// 替换为你要跳转的页面路径
|
||||||
@@ -176,16 +236,14 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
//商品下拉
|
||||||
getcategory(){
|
getcategory(){
|
||||||
request({
|
request({
|
||||||
url:'common/post/category/list',
|
url:'common/sku/preset',
|
||||||
method:'GET'
|
method:'GET'
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
if (res.data.code == 200) {
|
if (res.data.code == 200) {
|
||||||
this.categoryOptions = res.data.data.records || [];
|
this.categoryOptions = res.data.data|| [];
|
||||||
this.form.category = res.data.data.records[0].name
|
|
||||||
this.form.category_id = res.data.data.records[0].id
|
|
||||||
this.iconurl = res.data.data.records[0].icon_preset_pull
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -201,10 +259,9 @@ export default {
|
|||||||
onCategoryChange(e){
|
onCategoryChange(e){
|
||||||
console.log(e)
|
console.log(e)
|
||||||
const index = e.detail.value; // picker 返回的 index
|
const index = e.detail.value; // picker 返回的 index
|
||||||
const selectCity = this.categoryOptions[index]; // 直接取整条数据
|
const selectCity = this.conditionOptions[index]; // 直接取整条数据
|
||||||
this.iconurl = selectCity.icon_preset_pull
|
this.form.agename = selectCity.name
|
||||||
this.form.category = selectCity.name
|
this.form.age = selectCity.name
|
||||||
this.form.category_id = selectCity.id
|
|
||||||
},
|
},
|
||||||
handleContentInput(e){
|
handleContentInput(e){
|
||||||
if(e.detail.value.length>this.maxWords){
|
if(e.detail.value.length>this.maxWords){
|
||||||
@@ -214,7 +271,7 @@ export default {
|
|||||||
uploadfn(imgUrl){
|
uploadfn(imgUrl){
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
uni.uploadFile({
|
uni.uploadFile({
|
||||||
url: 'https://bsh.info.hb.hnzhwlkj.cn/upload/image?scene=postlist',
|
url: 'https://cb.hnxinyouhe.com/upload/image?scene=postlist',
|
||||||
filePath: imgUrl,
|
filePath: imgUrl,
|
||||||
name: 'image',
|
name: 'image',
|
||||||
header:{'content-type': 'application/x-www-form-urlencoded','Fdesk-Auth-Token': 'Bearer ' + uni.getStorageSync('token'),'Fdesk-Language': uni.getStorageSync('i18locale')?uni.getStorageSync('i18locale'):'zh','Fdesk-Login-Type': 'wechat','Fdesk-System-Code':'wechat'},
|
header:{'content-type': 'application/x-www-form-urlencoded','Fdesk-Auth-Token': 'Bearer ' + uni.getStorageSync('token'),'Fdesk-Language': uni.getStorageSync('i18locale')?uni.getStorageSync('i18locale'):'zh','Fdesk-Login-Type': 'wechat','Fdesk-System-Code':'wechat'},
|
||||||
@@ -314,6 +371,9 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
.detils{
|
||||||
|
margin-top: 40rpx;
|
||||||
|
}
|
||||||
.cent{
|
.cent{
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -356,7 +416,7 @@ export default {
|
|||||||
.form-card{
|
.form-card{
|
||||||
background: #fff;
|
background: #fff;
|
||||||
padding: 30rpx;
|
padding: 30rpx;
|
||||||
margin-bottom: 24rpx;
|
margin-bottom: 400rpx;
|
||||||
box-shadow: 0 12rpx 30rpx rgba(0,0,0,0.04);
|
box-shadow: 0 12rpx 30rpx rgba(0,0,0,0.04);
|
||||||
}
|
}
|
||||||
.section-label{
|
.section-label{
|
||||||
@@ -374,7 +434,19 @@ export default {
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
.gradient-bg{
|
.gradient-bg{
|
||||||
background: linear-gradient(90deg, #206ff4 0%, #42e0a2 100%);
|
background: #F4F4F4;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
.conts{
|
||||||
|
background: #F4F4F4;
|
||||||
|
color: #999999;
|
||||||
|
padding: 20rpx;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
}
|
||||||
|
.uni-input{
|
||||||
|
background: #F4F4F4;
|
||||||
|
padding: 20rpx 25rpx;
|
||||||
|
border-radius: 10rpx;
|
||||||
}
|
}
|
||||||
.category-content{
|
.category-content{
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -418,7 +490,7 @@ export default {
|
|||||||
}
|
}
|
||||||
.category-text{
|
.category-text{
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
color: #fff;
|
color: #999999;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
.mag-top{
|
.mag-top{
|
||||||
@@ -458,8 +530,8 @@ export default {
|
|||||||
margin-bottom: 12rpx;
|
margin-bottom: 12rpx;
|
||||||
}
|
}
|
||||||
.addimg{
|
.addimg{
|
||||||
width: 26px;
|
width: 215rpx;
|
||||||
height: 22px;
|
height: 215rpx;
|
||||||
}
|
}
|
||||||
.upload-text{
|
.upload-text{
|
||||||
font-size: 26rpx;
|
font-size: 26rpx;
|
||||||
@@ -496,10 +568,14 @@ export default {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 8rpx;
|
gap: 8rpx;
|
||||||
}
|
}
|
||||||
.agreement{
|
.foot{
|
||||||
margin: 20rpx 0 40rpx;
|
|
||||||
padding: 20px 12px;
|
|
||||||
background: #fff;
|
background: #fff;
|
||||||
|
position: fixed;
|
||||||
|
bottom: 1rpx;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.agreement{
|
||||||
|
margin: 20px 12px;
|
||||||
}
|
}
|
||||||
.agree-label{
|
.agree-label{
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -515,15 +591,83 @@ export default {
|
|||||||
}
|
}
|
||||||
.primary-btn{
|
.primary-btn{
|
||||||
color: #fff;
|
color: #fff;
|
||||||
border-radius: 999px;
|
border-radius: 20rpx;
|
||||||
height: 88rpx;
|
height: 88rpx;
|
||||||
line-height: 88rpx;
|
line-height: 88rpx;
|
||||||
font-size: 32rpx;
|
font-size: 32rpx;
|
||||||
border: none;
|
border: none;
|
||||||
margin: 40px 12px;
|
|
||||||
}
|
}
|
||||||
.gradient-btn{
|
.gradient-btn{
|
||||||
background: linear-gradient(180deg, #206ff4 0%, #42e0a2 100%);
|
background: #3BC8BE;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
}
|
||||||
|
.select-popup{
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
z-index: 999;
|
||||||
|
}
|
||||||
|
.popup-mask{
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background: rgba(0,0,0,0.35);
|
||||||
|
}
|
||||||
|
.popup-panel{
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background: #fff;
|
||||||
|
border-top-left-radius: 20rpx;
|
||||||
|
border-top-right-radius: 20rpx;
|
||||||
|
max-height: 40vh; /* 控制整体可视高度 */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 20rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.popup-header{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 16rpx;
|
||||||
|
}
|
||||||
|
.popup-search{
|
||||||
|
flex: 1;
|
||||||
|
height: 72rpx;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
background: #f4f4f4;
|
||||||
|
padding: 0 20rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333;
|
||||||
|
margin-right: 12rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.popup-title{
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.popup-close{
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #3BC8BE;
|
||||||
|
}
|
||||||
|
.popup-list{
|
||||||
|
flex: 1;
|
||||||
|
max-height: calc(40vh - 140rpx); /* 预留头部高度,保证可滚动 */
|
||||||
|
}
|
||||||
|
.popup-item{
|
||||||
|
padding: 20rpx 12rpx;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.popup-item:last-child{
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
.popup-empty{
|
||||||
|
text-align: center;
|
||||||
|
color: #999;
|
||||||
|
font-size: 26rpx;
|
||||||
|
padding: 30rpx 0;
|
||||||
}
|
}
|
||||||
.cont-text{
|
.cont-text{
|
||||||
max-width: 350px;
|
max-width: 350px;
|
||||||
|
|||||||
@@ -1,449 +1,307 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="content">
|
<view class="page">
|
||||||
<uni-nav-bar leftText=" " :fixed="true" :border="false" @clickLeft="leftClick" color="#000000" backgroundColor="#fff" :statusBar="true" title="广场"></uni-nav-bar>
|
<uni-nav-bar :fixed="true" :border="false" color="#000" backgroundColor="#fff" :statusBar="true" title="广场" />
|
||||||
<view class="content-con">
|
<!-- Tabs -->
|
||||||
<scroll-view scroll-y class="left-aside">
|
<view class="tabs">
|
||||||
<view v-for="item in flist" :key="item.id" class="f-item b-b" :class="{active: item.id === currentCategoryId}"
|
<view :class="['tab', currentTab==='latest'?'on':'']" @click="changeTab('latest')">最新发布</view>
|
||||||
@click="onCategoryChange(item.id)">
|
<view class="divider"></view>
|
||||||
<view class="category-icon" v-if="item.icon_active_pull">
|
<view :class="['tab', currentTab==='near'?'on':'']" @click="changeTab('near')">距离最近</view>
|
||||||
<image :src="item.id === currentCategoryId?item.icon_active_pull:item.icon_inactive_pull" mode=""></image>
|
|
||||||
️</view>
|
|
||||||
{{item.name}}
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
<scroll-view scroll-y class="right-aside"
|
|
||||||
refresher-enabled
|
|
||||||
:refresher-triggered="refreshing"
|
|
||||||
@refresherrefresh="onRefresh"
|
|
||||||
:lower-threshold="100"
|
|
||||||
@scrolltolower="onLoadMore">
|
|
||||||
<view class="t-lists">
|
|
||||||
<square-post-card
|
|
||||||
class="t-item"
|
|
||||||
v-for="sitem in slist"
|
|
||||||
:key="sitem.id"
|
|
||||||
:item="sitem"
|
|
||||||
:isshow="true"
|
|
||||||
@view="navToList"
|
|
||||||
@comment="navTomsg"
|
|
||||||
@like="navTozan" />
|
|
||||||
<!-- 加载更多提示 -->
|
|
||||||
<view v-if="hasMore" class="load-more">
|
|
||||||
<text v-if="loadingMore">加载中...</text>
|
|
||||||
<text v-else>上拉加载更多</text>
|
|
||||||
</view>
|
|
||||||
<view v-else-if="slist.length > 0" class="load-more">
|
|
||||||
<text>没有更多了</text>
|
|
||||||
</view>
|
|
||||||
<view class="empty" v-if="slist.length==0">
|
|
||||||
<image src="/static/image/empty.png" mode=""></image>
|
|
||||||
<view class="">
|
|
||||||
暂无数据!
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
</view>
|
|
||||||
<!-- 加载提示 -->
|
|
||||||
<view v-if="loading" class="loading-mask">
|
|
||||||
<view class="loading-text">加载中...</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
</template>
|
|
||||||
|
|
||||||
|
<!-- Feed list -->
|
||||||
|
<scroll-view
|
||||||
|
scroll-y
|
||||||
|
class="list-scroll"
|
||||||
|
refresher-enabled
|
||||||
|
:refresher-triggered="refreshing"
|
||||||
|
@refresherrefresh="onRefresh"
|
||||||
|
:lower-threshold="100"
|
||||||
|
@scrolltolower="onLoadMore"
|
||||||
|
>
|
||||||
|
<view class="feed-list">
|
||||||
|
<post-card
|
||||||
|
v-for="sitem in slist"
|
||||||
|
:key="sitem.id || sitem.username"
|
||||||
|
:item="sitem"
|
||||||
|
@userClick="goto"
|
||||||
|
@view="goto"
|
||||||
|
@contact="handleContact"
|
||||||
|
@comment="handleComment">
|
||||||
|
</post-card>
|
||||||
|
|
||||||
|
<!-- 状态提示 -->
|
||||||
|
<view v-if="hasMore" class="load-more">
|
||||||
|
<text v-if="loadingMore">加载中...</text>
|
||||||
|
<text v-else>上拉加载更多</text>
|
||||||
|
</view>
|
||||||
|
<view v-else-if="slist.length > 0" class="load-more">
|
||||||
|
<text>没有更多了</text>
|
||||||
|
</view>
|
||||||
|
<view class="empty" v-if="slist.length === 0 && !loading">
|
||||||
|
<image src="/static/image/empty.png" mode="aspectFit"></image>
|
||||||
|
<view>暂无数据!</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
|
||||||
|
<!-- 加载提示 -->
|
||||||
|
<view v-if="loading" class="loading-mask">
|
||||||
|
<view class="loading-text">加载中...</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import { request,showToast } from '@/api/apiT.js'
|
import { request } from '@/api/apiT.js'
|
||||||
import SquarePostCard from '@/components/SquarePostCard.vue'
|
import PostCard from '@/components/PostCard.vue'
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: { PostCard },
|
||||||
SquarePostCard
|
data() {
|
||||||
},
|
return {
|
||||||
data() {
|
tabs: [
|
||||||
return {
|
{ key: 'latest', label: '最新发布' },
|
||||||
flist: [],
|
{ key: 'near', label: '距离最近' }
|
||||||
slist: [],
|
],
|
||||||
currentCategoryId: '', // 当前选中的分类id
|
currentTab: 'latest',
|
||||||
loading: false, // 加载状态
|
slist:[
|
||||||
refreshing: false, // 下拉刷新状态
|
{
|
||||||
loadingMore: false, // 上拉加载状态
|
username:'用户名用户名',
|
||||||
page: 1, // 当前页码
|
time:'2025 年 12 月 4 日 10:56',
|
||||||
pageSize: 10, // 每页数量
|
content:`西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子
|
||||||
hasMore: true, // 是否还有更多数据
|
西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子西门子全新嵌饮机品牌
|
||||||
categoriesLoaded: false // 分类是否已加载完成
|
西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子`,
|
||||||
}
|
tag:['#散饮机','#9成新'],
|
||||||
},
|
location:'门店位置',
|
||||||
onLoad() {
|
image:[
|
||||||
// 加载第一级分类列表
|
{img_src:'/static/image/bx.jpg'},
|
||||||
|
{img_src:'/static/image/bx.jpg'},
|
||||||
},
|
{img_src:'/static/image/bx.jpg'},
|
||||||
onShow() {
|
{img_src:'/static/image/bx.jpg'},
|
||||||
this.loadCategoryList();
|
{img_src:'/static/image/bx.jpg'},
|
||||||
this.syncTabbar()
|
{img_src:'/static/image/bx.jpg'}
|
||||||
// // 从详情页返回后,重新拉取当前分类数据
|
]
|
||||||
// if (this.categoriesLoaded) {
|
},{
|
||||||
// this.refreshCurrentCategory()
|
username:'用户名用户名',
|
||||||
// }
|
time:'2025 年 12 月 4 日 10:56',
|
||||||
},
|
content:`西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子
|
||||||
methods: {
|
西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子西门子全新嵌饮机品牌
|
||||||
// 加载第一级分类列表
|
西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子`,
|
||||||
loadCategoryList() {
|
tag:['#散饮机','#9成新'],
|
||||||
// TODO: 替换为实际的后端接口
|
location:'门店位置',
|
||||||
let that = this;
|
image:[
|
||||||
|
{img_src:'/static/image/bx.jpg'},
|
||||||
request({
|
{img_src:'/static/image/bx.jpg'},
|
||||||
url:'common/post/category/list',
|
{img_src:'/static/image/bx.jpg'}
|
||||||
method:'GET'
|
]
|
||||||
}).then(res => {
|
},{
|
||||||
if (res.data.code == 200) {
|
username:'用户名用户名',
|
||||||
const records = res.data.data.records || [];
|
time:'2025 年 12 月 4 日 10:56',
|
||||||
this.flist = [{
|
content:`西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子
|
||||||
id: '',
|
西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子西门子全新嵌饮机品牌
|
||||||
name: '全部分类'
|
西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子全新嵌饮机品牌西门子`,
|
||||||
}, ...records];
|
tag:['#散饮机','#9成新'],
|
||||||
this.categoriesLoaded = true;
|
location:'门店位置',
|
||||||
// 默认加载第一个分类的数据
|
image:[
|
||||||
if (this.flist.length > 0) {
|
{img_src:'/static/image/bx.jpg'},
|
||||||
this.onCategoryChange(this.flist[0].id);
|
{img_src:'/static/image/bx.jpg'}
|
||||||
}
|
]
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
// 重新加载当前分类数据
|
|
||||||
refreshCurrentCategory() {
|
|
||||||
const targetCategory = this.currentCategoryId !== undefined ? this.currentCategoryId : (this.flist[0] && this.flist[0].id) || '';
|
|
||||||
this.loadCategoryData(targetCategory, false);
|
|
||||||
},
|
|
||||||
|
|
||||||
// 分类切换事件
|
|
||||||
onCategoryChange(categoryId) {
|
|
||||||
// 如果点击的是当前分类且已有数据,不重复加载
|
|
||||||
if (this.currentCategoryId === categoryId && this.slist.length > 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 切换分类时,重置所有状态
|
|
||||||
this.currentCategoryId = categoryId;
|
|
||||||
this.page = 1;
|
|
||||||
this.hasMore = true;
|
|
||||||
this.loading = false;
|
|
||||||
this.loadingMore = false;
|
|
||||||
this.refreshing = false;
|
|
||||||
this.slist = []; // 先清空数据
|
|
||||||
this.loadCategoryData(categoryId, false);
|
|
||||||
},
|
|
||||||
|
|
||||||
// 根据分类id加载分类下的内容
|
|
||||||
loadCategoryData(categoryId, isLoadMore = false) {
|
|
||||||
// 防止重复请求:如果是加载更多,需要检查所有加载状态
|
|
||||||
if (isLoadMore) {
|
|
||||||
if (this.loadingMore || this.loading || this.refreshing) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 下拉刷新或初次加载,检查加载状态
|
|
||||||
if (this.loading || this.loadingMore) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isLoadMore) {
|
|
||||||
this.loadingMore = true;
|
|
||||||
this.page += 1;
|
|
||||||
} else {
|
|
||||||
this.loading = true;
|
|
||||||
this.page = 1;
|
|
||||||
this.hasMore = true;
|
|
||||||
this.slist = []; // 清空之前的数据
|
|
||||||
}
|
|
||||||
|
|
||||||
request({
|
|
||||||
url:'common/post/list',
|
|
||||||
method:'GET',
|
|
||||||
data:{
|
|
||||||
category_id:categoryId,
|
|
||||||
current: this.page,
|
|
||||||
size: this.pageSize
|
|
||||||
}
|
|
||||||
}).then(res => {
|
|
||||||
this.loading = false;
|
|
||||||
this.loadingMore = false;
|
|
||||||
this.refreshing = false;
|
|
||||||
|
|
||||||
if (res.data.code == 200) {
|
|
||||||
const records = res.data.data.records || [];
|
|
||||||
const total = res.data.data.total || 0;
|
|
||||||
|
|
||||||
if (isLoadMore) {
|
|
||||||
// 上拉加载更多,追加数据并去重
|
|
||||||
const existingIds = new Set(this.slist.map(item => item.id));
|
|
||||||
const newRecords = records.filter(item => !existingIds.has(item.id));
|
|
||||||
this.slist = [...this.slist, ...newRecords];
|
|
||||||
} else {
|
|
||||||
// 下拉刷新或初次加载,替换数据
|
|
||||||
this.slist = records;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 判断是否还有更多数据
|
|
||||||
this.hasMore = this.slist.length < total;
|
|
||||||
}
|
|
||||||
}).catch(() => {
|
|
||||||
this.loading = false;
|
|
||||||
this.loadingMore = false;
|
|
||||||
this.refreshing = false;
|
|
||||||
if (isLoadMore) {
|
|
||||||
this.page -= 1; // 加载失败,页码回退
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
// 下拉刷新
|
|
||||||
onRefresh() {
|
|
||||||
// 如果正在加载中,不执行刷新
|
|
||||||
if (this.loading || this.loadingMore) {
|
|
||||||
this.refreshing = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.refreshing = true;
|
|
||||||
this.loadCategoryData(this.currentCategoryId, false);
|
|
||||||
},
|
|
||||||
// 上拉加载更多
|
|
||||||
onLoadMore() {
|
|
||||||
if (!this.hasMore || this.loadingMore || this.loading || this.refreshing) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.loadCategoryData(this.currentCategoryId, true);
|
|
||||||
},
|
|
||||||
|
|
||||||
// 点击商品项
|
|
||||||
navToList(item) {
|
|
||||||
uni.navigateTo({
|
|
||||||
url: '/pages/square/detiles?id='+item.id
|
|
||||||
});
|
|
||||||
},
|
|
||||||
//点赞
|
|
||||||
navTozan(item){
|
|
||||||
const targetIndex = this.slist.findIndex(post => post.id === item.id)
|
|
||||||
if(targetIndex === -1){
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const target = this.slist[targetIndex]
|
|
||||||
const isLiked = Number(target.is_like) === 1
|
|
||||||
const likeUrl = isLiked ? 'common/post/like/destroy' : 'common/post/like/store'
|
|
||||||
const method = isLiked ? 'GET' : 'POST'
|
|
||||||
const data = {
|
|
||||||
post_id: target.id
|
|
||||||
}
|
|
||||||
if (isLiked) {
|
|
||||||
data.user_id = target.user_id
|
|
||||||
}
|
|
||||||
request({
|
|
||||||
url: likeUrl,
|
|
||||||
method,
|
|
||||||
data
|
|
||||||
}).then(res => {
|
|
||||||
if(res.data.code === 200){
|
|
||||||
const newTarget = { ...target }
|
|
||||||
if(isLiked){
|
|
||||||
newTarget.is_like = 0
|
|
||||||
newTarget.like = Math.max(0, (Number(newTarget.like) || 0) - 1)
|
|
||||||
uni.showToast({
|
|
||||||
title: '取消成功',
|
|
||||||
icon: 'none'
|
|
||||||
});
|
|
||||||
}else{
|
|
||||||
newTarget.is_like = 1
|
|
||||||
newTarget.like = (Number(newTarget.like) || 0) + 1
|
|
||||||
uni.showToast({
|
|
||||||
title: '点赞成功',
|
|
||||||
icon: 'none'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this.$set(this.slist, targetIndex, newTarget)
|
|
||||||
}else{
|
|
||||||
uni.showToast({
|
|
||||||
title:res.data.message,
|
|
||||||
icon: 'none'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
//消息
|
|
||||||
navTomsg(item){
|
|
||||||
request({
|
|
||||||
url:'common/like/store',
|
|
||||||
method:'GET',
|
|
||||||
data:{
|
|
||||||
post_id:item.id
|
|
||||||
}
|
|
||||||
}).then(res => {
|
|
||||||
})
|
|
||||||
},
|
|
||||||
leftClick(){
|
|
||||||
uni.navigateBack()
|
|
||||||
},
|
|
||||||
syncTabbar(){
|
|
||||||
uni.setTabBarItem({ index:0, text:this.$t('tabbar.home') })
|
|
||||||
uni.setTabBarItem({ index:1, text:this.$t('tabbar.square') })
|
|
||||||
uni.setTabBarItem({ index:2, text:this.$t('tabbar.publish') })
|
|
||||||
uni.setTabBarItem({ index:3, text:this.$t('tabbar.mine') })
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
],
|
||||||
|
loading: false,
|
||||||
|
refreshing: false,
|
||||||
|
loadingMore: false,
|
||||||
|
page: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
hasMore: true,
|
||||||
|
defaultTags: ['样机机', '9成新']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onShow() {
|
||||||
|
this.loadList()
|
||||||
|
// this.syncTabbar()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
syncTabbar() {
|
||||||
|
uni.setTabBarItem({ index: 0, text: this.$t('tabbar.home') })
|
||||||
|
uni.setTabBarItem({ index: 1, text: this.$t('tabbar.square') })
|
||||||
|
uni.setTabBarItem({ index: 2, text: this.$t('tabbar.publish') })
|
||||||
|
uni.setTabBarItem({ index: 3, text: this.$t('tabbar.mine') })
|
||||||
|
},
|
||||||
|
changeTab(key) {
|
||||||
|
if (this.currentTab === key) return
|
||||||
|
this.currentTab = key
|
||||||
|
this.page = 1
|
||||||
|
this.hasMore = true
|
||||||
|
this.slist = []
|
||||||
|
this.loadList()
|
||||||
|
},
|
||||||
|
loadList(isLoadMore = false) {
|
||||||
|
if (isLoadMore) {
|
||||||
|
if (this.loadingMore || this.loading || this.refreshing || !this.hasMore) return
|
||||||
|
this.loadingMore = true
|
||||||
|
this.page += 1
|
||||||
|
} else {
|
||||||
|
if (this.loading || this.loadingMore) return
|
||||||
|
this.loading = true
|
||||||
|
this.page = 1
|
||||||
|
this.hasMore = true
|
||||||
|
this.slist = []
|
||||||
|
}
|
||||||
|
|
||||||
|
const sortKey = this.currentTab === 'near' ? 'distance' : 'latest'
|
||||||
|
|
||||||
|
request({
|
||||||
|
url: 'common/post/list',
|
||||||
|
method: 'GET',
|
||||||
|
data: {
|
||||||
|
current: this.page,
|
||||||
|
size: this.pageSize,
|
||||||
|
sort: sortKey
|
||||||
|
}
|
||||||
|
}).then(res => {
|
||||||
|
this.loading = false
|
||||||
|
this.loadingMore = false
|
||||||
|
this.refreshing = false
|
||||||
|
if (res.data.code === 200) {
|
||||||
|
const records = res.data.data.records || []
|
||||||
|
const total = res.data.data.total || 0
|
||||||
|
if (isLoadMore) {
|
||||||
|
this.slist = [...this.slist, ...records]
|
||||||
|
} else {
|
||||||
|
this.slist = records
|
||||||
|
}
|
||||||
|
this.hasMore = this.slist.length < total
|
||||||
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
this.loading = false
|
||||||
|
this.loadingMore = false
|
||||||
|
this.refreshing = false
|
||||||
|
if (isLoadMore) {
|
||||||
|
this.page -= 1
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onRefresh() {
|
||||||
|
if (this.loading || this.loadingMore) {
|
||||||
|
this.refreshing = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.refreshing = true
|
||||||
|
this.loadList(false)
|
||||||
|
},
|
||||||
|
onLoadMore() {
|
||||||
|
this.loadList(true)
|
||||||
|
},
|
||||||
|
navToList(item) {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/square/detiles?id=' + item.id
|
||||||
|
})
|
||||||
|
},
|
||||||
|
leftClick() {
|
||||||
|
uni.navigateBack()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
underlineTransform() {
|
||||||
|
const index = this.tabs.findIndex(t => t.key === this.currentTab)
|
||||||
|
return `translateX(${index * 50}%)`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang='scss'>
|
<style lang="scss">
|
||||||
.empty{
|
page,
|
||||||
text-align: center;
|
.page {
|
||||||
margin-top: 30%;
|
height: 100%;
|
||||||
width: 100%;
|
background: #f8f8f8;
|
||||||
}
|
}
|
||||||
.empty image{
|
|
||||||
width: 252px;
|
|
||||||
height: 164px;
|
|
||||||
}
|
|
||||||
page,
|
|
||||||
.content {
|
|
||||||
height: 100%;
|
|
||||||
background-color: #f8f8f8;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loading-mask {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background-color: rgba(0, 0, 0, 0.3);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
z-index: 999;
|
|
||||||
|
|
||||||
.loading-text {
|
|
||||||
color: #fff;
|
|
||||||
font-size: 28upx;
|
|
||||||
background-color: rgba(0, 0, 0, 0.7);
|
|
||||||
padding: 20upx 40upx;
|
|
||||||
border-radius: 8upx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.content-con {
|
|
||||||
height: calc(100% - 128rpx);
|
|
||||||
background-color: #f8f8f8;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.left-aside {
|
|
||||||
flex-shrink: 0;
|
|
||||||
width: 200upx;
|
|
||||||
height: 100%;
|
|
||||||
background-color: #F7F7F7;
|
|
||||||
}
|
|
||||||
|
|
||||||
.f-item {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-start;
|
|
||||||
width: 100%;
|
|
||||||
height: 90rpx;
|
|
||||||
font-size: 26rpx;
|
|
||||||
color: #666;
|
|
||||||
position: relative;
|
|
||||||
padding-left: 24rpx;
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
color: #0071FC;
|
|
||||||
background: #fff;
|
|
||||||
|
|
||||||
&:before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
top: 50%;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
height: 36upx;
|
|
||||||
width: 8upx;
|
|
||||||
background-color: #0071FC;
|
|
||||||
border-radius: 0 4px 4px 0;
|
|
||||||
opacity: .8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.iconview{
|
|
||||||
margin-right: 10px;
|
|
||||||
display: inline-block;
|
|
||||||
font-size: 22rpx;
|
|
||||||
}
|
|
||||||
.icons {
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
margin-right: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.right-aside {
|
|
||||||
flex: 1;
|
|
||||||
overflow: hidden;
|
|
||||||
/* padding-left: 20upx; */
|
|
||||||
/* padding-top: 20upx; */
|
|
||||||
background: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.t-lists {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
padding: 20rpx;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
.t-item{
|
|
||||||
width: 48%;
|
|
||||||
/* background: #fff; */
|
|
||||||
/* border-radius: 24rpx; */
|
|
||||||
overflow: hidden;
|
|
||||||
margin-bottom: 20rpx;
|
|
||||||
/* box-shadow: 0 8rpx 24rpx rgba(0,0,0,0.06); */
|
|
||||||
}
|
|
||||||
.grid-image{
|
|
||||||
width: 100%;
|
|
||||||
height: 320rpx;
|
|
||||||
background: #E5E5E5;
|
|
||||||
border-radius: 10rpx;
|
|
||||||
}
|
|
||||||
.grid-footer{
|
|
||||||
padding: 20rpx;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.grid-avatar{
|
|
||||||
width: 48rpx;
|
|
||||||
height: 48rpx;
|
|
||||||
border-radius: 50%;
|
|
||||||
margin-right: 12rpx;
|
|
||||||
}
|
|
||||||
.grid-info{
|
|
||||||
flex: 1;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
width: 70%;
|
|
||||||
}
|
|
||||||
.grid-tag{
|
|
||||||
font-size: 24rpx;
|
|
||||||
color: #3F435B;
|
|
||||||
margin-bottom: 4rpx;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
width: 87%;
|
|
||||||
}
|
|
||||||
.category-icon image{
|
|
||||||
height: 16px;
|
|
||||||
width: 16px;
|
|
||||||
margin-right: 10rpx;
|
|
||||||
}
|
|
||||||
.load-more{
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
padding: 30rpx 0;
|
|
||||||
font-size: 26rpx;
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
.tabs {
|
||||||
|
height: 80rpx;
|
||||||
|
background: #fff;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-around;
|
||||||
|
gap: 24rpx;
|
||||||
|
position: relative;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
.tab {
|
||||||
|
position: relative;
|
||||||
|
padding: 12rpx 20rpx 18rpx;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.tab::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
bottom: 4rpx;
|
||||||
|
width: 50rpx;
|
||||||
|
height: 4rpx;
|
||||||
|
background: #05b3a8;
|
||||||
|
border-radius: 4rpx;
|
||||||
|
transform: translateX(-50%) scaleX(0);
|
||||||
|
transition: transform 0.2s;
|
||||||
|
}
|
||||||
|
.tab.on {
|
||||||
|
color: #05b3a8;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
.tab.on::after {
|
||||||
|
transform: translateX(-50%) scaleX(1);
|
||||||
|
}
|
||||||
|
.divider {
|
||||||
|
width: 1px;
|
||||||
|
height: 26rpx;
|
||||||
|
background: #dcdcdc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-scroll {
|
||||||
|
height: calc(100vh - 120rpx);
|
||||||
|
}
|
||||||
|
|
||||||
|
.feed-list {
|
||||||
|
// padding: 20rpx;
|
||||||
|
margin: 20rpx 30rpx;
|
||||||
|
// background: #fff;
|
||||||
|
}
|
||||||
|
.load-more {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
padding: 30rpx 0;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
.empty {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
padding: 100rpx 0;
|
||||||
|
}
|
||||||
|
.empty image {
|
||||||
|
width: 252rpx;
|
||||||
|
height: 164rpx;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-mask {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: rgba(0, 0, 0, 0.3);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 999;
|
||||||
|
|
||||||
|
.loading-text {
|
||||||
|
color: #fff;
|
||||||
|
font-size: 28upx;
|
||||||
|
background-color: rgba(0, 0, 0, 0.7);
|
||||||
|
padding: 20upx 40upx;
|
||||||
|
border-radius: 8upx;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
Before Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 894 B After Width: | Height: | Size: 726 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 618 B |
|
After Width: | Height: | Size: 246 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 881 B After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 953 B |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 640 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 93 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1013 B After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 5.1 KiB |