You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
yanzong_qianduan/pages/squareDynamic/index.vue

722 lines
18 KiB

8 months ago
<template>
<view class="container">
<view class="head">
<image :src="$picUrl+'/static/dynamic-banner.png'" mode="aspectFill"></image>
8 months ago
</view>
<view class="box">
<view class="tab-list">
<view v-for="(item, index) in tabList" :key="index" class="tab-item" :class="{ 'active': activeTab === item }" @click="activeTab = item">{{ item }}</view>
</view>
<view class="list">
<view v-for="(item, index) in dynamicList" :key="index" class="dynamic-item" :style="{ 'visibility': !item.contH ? 'hidden' : 'visible'}">
8 months ago
<view class="user">
7 months ago
<image v-if="item.avatar_url && item.avatar_url[0]" :src="item.avatar_url[0].external_url" mode="aspectFill"></image>
8 months ago
<image v-else src="/static/touxiang.png" mode="aspectFill"></image>
<view class="user-info">
7 months ago
<view class="name">{{ item.real_name }}</view>
<view class="time">{{ item.update_time }}</view>
8 months ago
</view>
</view>
<view class="cont" :class="[`cont${index}`, { 'close': item.contH > 120 && !showFullCont.includes(index)}]">
{{ item.content }}
8 months ago
</view>
<view v-if="item.contH > 120" class="show-more" @click="toggleFullCont(index)">{{ showFullCont.includes(index) ? '收起' : '全文' }}</view>
7 months ago
<view v-if="item.imgs && item.imgs.length > 0" class="pic-list">
<image v-for="(pic, k) in item.imgs" :key="k" :src="pic.external_url" mode="aspectFill" @click="previewImages(k, item.imgs)"></image>
8 months ago
</view>
<view v-if="item.files && item.files.length > 0" class="file-list">
<view v-for="(file, index) in item.files" :key="index" class="file-box" @click="previewFile(file.external_url)">
<image src="/static/xls.jpeg" mode="aspectFill"></image>
<text>{{ solveFileName(file.file_name) }}</text>
</view>
</view>
<view v-if="item.goodsInfo" class="goods">
<view class="goods-box">
<image :src="item.goodsInfo.goods_image" mode="aspectFill"></image>
<view class="goods-info">
<view class="name">{{ item.goodsInfo.goods_name }}</view>
<view class="price">
<text>{{ item.goodsInfo.goods_price_min>0?Number(item.goodsInfo.goods_price_min):0.00 }}</text>
7 months ago
<text @click="toGoodsDetail(item)">立即购买</text>
</view>
</view>
</view>
</view>
8 months ago
<view class="btns">
<view class="btn" v-if="item.content" @click="clipCont(item.content)">
<image src="/static/copy.png" mode="aspectFill"></image>
<view>复制文案</view>
</view>
<view class="btn" v-if="userInfo.user_type == 40" @click="handleDelete(item)">
<image src="/static/trash.png" mode="aspectFill"></image>
<view>删除文案</view>
</view>
<view class="btn" v-if="item.imgs && item.imgs.length > 0" @click="downloadMultipleImages(item.imgs)">
8 months ago
<image src="/static/download.png" mode="aspectFill"></image>
<view>下载图片</view>
</view>
7 months ago
<view class="btn" @click="togggleLike(item, index)">
8 months ago
<image v-if="!item.isLike" src="/static/nolike.png" mode="aspectFill"></image>
<image v-else src="/static/like.png" mode="aspectFill"></image>
<view>{{ item.likeNum }}</view>
</view>
</view>
</view>
</view>
<view v-if="dynamicList.length && !loading" class="finished">{{ loadTitle }}</view>
<view v-if="finished && !dynamicList.length" class="empty">
<image mode="aspectFill" src="@/static/empty.png" alt="暂无动态" />
<view>暂无动态</view>
</view>
7 months ago
<view
7 months ago
v-if="userInfo.user_type == 40"
7 months ago
id="publish"
class="publish"
:style="{'left': left === 0 ? '626rpx' : left + 'px', 'top': top === 0 ? 'calc(100% - 300rpx)' : top + 'px'}"
@touchmove.stop.prevent="touchmove"
@touchend="touchend"
@click="publish"
:class="{transition: !isMove }"
>
8 months ago
<image src="/static/publish.png" mode="aspectFill"></image>
<text>发布</text>
</view>
</view>
</view>
</template>
<script>
7 months ago
import * as Api from '@/api/squareDynamic/index.js'
7 months ago
import {
checkLogin
} from '@/core/app'
import * as UserApi from '@/api/user';
7 months ago
8 months ago
export default {
7 months ago
components: {
},
8 months ago
data() {
return {
tabList: ['推荐', '精选', '晒单', '日常', '文章'],
activeTab: '推荐',
7 months ago
dynamicList: [],
8 months ago
page: 1,
limit: 10,
loadTitle: '',
loading: false,
finished: false,
showFullCont: [],
7 months ago
top:0,
left:0,
width: 0,
height: 0,
offsetWidth: 0,
offsetHeight: 0,
windowWidth: 0,
windowHeight: 0,
isMove: true,
edge: 20,
7 months ago
userInfo: {},
isLogin: false,
isPreview: false
8 months ago
};
},
7 months ago
watch: {
activeTab() {
this.loading = false;
this.finished = false;
this.page = 1;
this.dynamicList = [];
7 months ago
this.getDynamicList();
},
},
8 months ago
onLoad() {
uni.setNavigationBarColor({
frontColor: '#000000',
8 months ago
backgroundColor: '#E7F1FC',
7 months ago
});
7 months ago
const sys = uni.getSystemInfoSync();
this.windowWidth = sys.windowWidth;
this.windowHeight = sys.windowHeight;
if (sys.windowTop) {
this.windowHeight += sys.windowTop;
}
},
onReady() {
7 months ago
const query = uni.createSelectorQuery().in(this);
query.select('#publish').boundingClientRect(data => {
if (data) {
this.width = data.width;
this.height = data.height;
this.offsetWidth = data.width / 2;
this.offsetHeight = data.height / 2;
}
7 months ago
}).exec();
8 months ago
},
7 months ago
onShow() {
if (!this.isPreview) {
this.loading = false;
this.finished = false;
this.page = 1;
this.dynamicList = [];
this.getDynamicList();
7 months ago
} else {
this.isPreview = false;
7 months ago
}
if (uni.getStorageSync("userInfo").user_id) {
this.isLogin = true
this.onRefreshPage()
} else {
this.userInfo = {}
}
7 months ago
},
6 months ago
onReachBottom() {
this.getDynamicList();
},
8 months ago
methods: {
7 months ago
// 刷新页面
onRefreshPage() {
this.isLogin = checkLogin()
// 获取页面数据
this.getUserInfo();
},
// 获取当前用户信息
getUserInfo() {
const that = this
return new Promise((resolve, reject) => {
!that.isLogin ? resolve(null) : UserApi.info({}, {
load: false
})
.then(result => {
let data = result.data.userInfo
that.userInfo = data
uni.setStorageSync('userInfo', that.userInfo)
resolve(that.userInfo)
})
.catch(err => {
if (err.result && err.result.status == 401) {
that.isLogin = false
resolve(null)
} else {
reject(err)
}
})
})
},
getDynamicList() {
7 months ago
if (this.loading || this.finished) {
return;
}
this.loadTitle = "";
Api.getDynamic({
cate: this.activeTab,
page: this.page++,
pageSize: this.limit,
})
.then(result => {
const data = result.data.data;
this.dynamicList = this.dynamicList.concat(data);
this.$nextTick(() => {
if (this.dynamicList) {
this.dynamicList.forEach((item, index) => {
if (!item.contH) {
this.getHeight(item, index);
}
})
}
})
7 months ago
this.finished = data.length < this.limit;
this.loadTitle = this.finished ? "已全部加载完" : "上拉加载更多";
})
.finally(() => this.loading = false)
},
getHeight(item, index) {
this.$nextTick(() => {
const query = uni.createSelectorQuery().in(this);
query.select(`.cont${index}`).boundingClientRect(data => {
if (data) {
// data.height 就是元素的高度
item.contH = data.height;
8 months ago
}
}).exec();
})
},
toggleFullCont(index) {
if (this.showFullCont.includes(index)) {
const idx = this.showFullCont.findIndex(v => v == index);
this.showFullCont.splice(idx, 1);
} else {
this.showFullCont.push(index);
8 months ago
}
},
clipCont(cont) {
uni.setClipboardData({
data: cont
});
},
downloadSingleImage(url) {
  return new Promise((resolve, reject) => {
    uni.downloadFile({
      url: url,
      success: (res) => {
        if (res.statusCode === 200) {
          resolve(res.tempFilePath)
        } else {
          reject(new Error('下载失败'))
        }
      },
      fail: (err) => {
        reject(new Error('下载失败'))
      }
    })
  })
},
downloadMultipleImages(urls) {
  let tasks = []
  urls.forEach((url, k) => {
    tasks.push(this.downloadSingleImage(url.external_url).then(e => {
uni.saveImageToPhotosAlbum({
filePath: e,
});
if (k === urls.length - 1) {
uni.showToast({
icon: 'success',
title: '下载成功!'
})
}
}));
8 months ago
  })
  return Promise.all(tasks)
6 months ago
},
6 months ago
previewFile(url) {
6 months ago
uni.downloadFile({
6 months ago
      url,
6 months ago
      success: (res) => {
        if (res.statusCode === 200) {
this.isPreview = true;
uni.openDocument({
filePath: res.tempFilePath,
});
        } else {
        uni.showToast({
icon: 'error',
title: '下载失败!'
})
        }
      },
      fail: (err) => {
        uni.showToast({
icon: 'error',
title: '下载失败!'
})
      }
    })
8 months ago
},
solveFileName(name) {
6 months ago
if (name.indexOf('.xlsx')) {
return name.replace('.xlsx', '');
}
6 months ago
return name.replace('.xls', '');
},
7 months ago
togggleLike(item, index) {
Api.dynamicLike({
id: item.square_id,
})
.then(res => {
if (item.isLike) {
item.isLike = false;
item.likeNum -= 1;
} else {
item.isLike = true;
item.likeNum += 1;
}
})
.catch((e) => {
console.log(e);
})
8 months ago
},
publish() {
uni.navigateTo({
url: '/pages/squareDynamic/publish',
})
},
7 months ago
spred(e){
const animation = uni.createAnimation({
duration: 200,
timingFunction: 'ease',
});
this.animationData = animation.export();
if(this.isShow){
animation.rotate(135).step();
}
else{
animation.rotate(0).step();
}
this.animationData = animation.export();
},
touchmove(e) {
// 单指触摸
if (e.touches.length !== 1) {
return false;
}
this.isMove = true;
this.isShow=false
this.spred()
this.left = e.touches[0].clientX - this.offsetWidth;
let clientX = e.touches[0].clientX;
let clientY = e.touches[0].clientY - this.offsetHeight;
let edgeBottom = this.windowHeight - this.height - this.edge;
// 左右触及边界
if (clientX < this.edge) {
this.left = this.edge;
} else if (clientX > this.windowWidth - this.offsetWidth - this.edge) {
this.left = this.windowWidth - this.width - this.edge;
} else {
this.left = clientX - this.offsetWidth;
}
// 上下触及边界
if (clientY < this.edge) {
this.top = this.edge;
} else if (clientY > edgeBottom) {
this.top = edgeBottom;
} else {
this.top = clientY
}
},
touchend(e) {
if (this.isDock) {
let edgeRigth = this.windowWidth - this.width - this.edge;
if (this.left < this.windowWidth / 2 - this.offsetWidth) {
this.left = this.edge;
} else {
this.left = edgeRigth;
}
if(this.left>200){
this.postitionName=false
}else{
this.postitionName=true
}
}
this.isMove = false;
},
7 months ago
previewImages(idx, images) {
7 months ago
const arr = [];
images.forEach(v => {
arr.push(v.external_url);
})
uni.previewImage({
current: idx,
urls: arr,
})
this.isPreview = true;
7 months ago
},
toGoodsDetail(item) {
this.$navTo('pages/goods/detail', {
goodsId: item.goods_id
})
},
// 删除动态
handleDelete(item) {
const app = this;
uni.showModal({
title: '提示',
content: '您确定要删除该动态吗?',
showCancel: true,
success({
confirm
}) {
// 确认删除
confirm && app.deleteDynamic(item)
}
})
},
deleteDynamic(item) {
6 months ago
Api.deleteDynamic({
squareId: item.square_id
})
.then(result => {
uni.showToast({
icon: 'success',
title: '删除成功',
});
this.finished = false;
this.page = 1;
this.dynamicList = [];
this.getDynamicList();
})
.finally(() => {})
},
8 months ago
},
};
</script>
<style lang="scss" scoped>
.container {
background: #F7F8FA;
padding-top: 292rpx;
.head {
height: 450rpx;
width: 100%;
position: absolute;
top: -88rpx;
background: linear-gradient(0deg, #F7F8FA, #E0EFFD);
z-index: 0;
>image {
position: absolute;
top: 138rpx;
left: 50%;
transform: translateX(-50%);
width: 669rpx;
height: 221rpx;
}
}
.box {
position: relative;
width: 100%;
// top: 292rpx;
padding: 24rpx;
.tab-list {
display: flex;
justify-content: space-between;
.tab-item {
width: 130rpx;
height: 80rpx;
background: #FFFFFF;
border-radius: 10rpx;
opacity: 0.7;
font-size: 30rpx;
color: #999999;
line-height: 80rpx;
text-align: center;
&.active {
box-shadow: 0rpx 4rpx 12rpx 0rpx rgba(32,39,76,0.1);
opacity: 1;
color: #333333;
}
}
}
.list {
margin-top: 30rpx;
.dynamic-item {
width: 100%;
background: #FFFFFF;
border-radius: 20rpx;
padding: 30rpx;
margin-bottom: 20rpx;
&:last-child {
margin-bottom: 0;
}
.user {
display: flex;
>image {
width: 80rpx;
height: 80rpx;
margin-right: 24rpx;
}
.user-info {
.name {
font-size: 30rpx;
color: #222222;
line-height: 30rpx;
margin-bottom: 26rpx;
}
.time {
font-size: 24rpx;
color: #999999;
line-height: 24rpx;
}
}
}
.cont {
margin-top: 30rpx;
font-size: 28rpx;
line-height: 40rpx;
position: relative;
color: #222222;
7 months ago
word-break: break-word;
white-space: pre-line;
&.close {
max-height: 240rpx;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 6;
-webkit-box-orient: vertical;
8 months ago
}
}
.show-more {
font-size: 28rpx;
line-height: 40rpx;
color: #F34A40;
text-align: right;
}
8 months ago
.pic-list {
margin-top: 24rpx;
>image {
width: 210rpx;
height: 210rpx;
margin-right: 6rpx;
margin-bottom: 6rpx;
border-radius: 10rpx;
&:nth-child(3n) {
margin-right: 0;
}
}
}
.file-list {
display: block;
padding: 30rpx 0;
height: fit-content;
.file-box {
border-bottom: 1px solid #ddd;
display: flex;
align-items: center;
position: relative;
padding: 10rpx 20rpx;
height: 80rpx;
margin-bottom: 20rpx;
&:last-child {
border-bottom: none;
}
>image {
width: 60rpx;
height: 60rpx;
margin: 0 10rpx 0 0;
flex-shrink: 0;
}
>text {
width: calc(100% - 70rpx);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
.goods {
background: #f5f5f5;
padding: 20rpx;
margin-top: 24rpx;
}
.goods-box {
display: flex;
background: #fff;
padding: 20rpx 0;
>image {
width: 100rpx;
height: 100rpx;
margin-right: 20rpx;
}
.goods-info {
width: calc(100% - 120rpx);
display: flex;
flex-direction: column;
justify-content: space-between;
.name {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.price {
display: flex;
>text {
&:first-child {
color: #F34A40;
}
&:last-child {
height: 40rpx;
line-height: 40rpx;
text-align: center;
padding: 0 20rpx;
background: #F34A40;
border-radius: 20rpx;
margin-left: auto;
color: #FFFFFF;
font-size: 22rpx;
flex-shrink: 0;
}
}
}
}
}
8 months ago
.btns {
margin-top: 20rpx;
display: flex;
justify-content: flex-end;
.btn {
display: flex;
flex-direction: column;
align-items: center;
font-size: 24rpx;
line-height: 24rpx;
color: #999999;
margin-left: 40rpx;
image {
width: 40rpx;
height: 40rpx;
margin-bottom: 10rpx;
}
::v-deep {
.delete {
margin-bottom: 10rpx;
.uni-icons {
font-size: 40rpx!important;
font-weight: bold;
line-height: 40rpx;
}
}
}
8 months ago
}
}
}
}
.finished,
.loading {
font-size: 28rpx;
line-height: 100rpx;
text-align: center;
color: #bbb;
}
.empty {
margin-top: 100rpx;
font-size: 28rpx;
text-align: center;
color: #bbb;
}
.empty image {
display: block;
width: 414rpx;
height: 305rpx;
margin: 0 auto 20rpx;
8 months ago
pointer-events: none;
}
.publish {
position: fixed;
7 months ago
left: 626rpx;
top: calc(100% - 300rpx);
8 months ago
width: 100rpx;
height: 100rpx;
background: #F34A40;
border-radius: 50%;
color: #fff;
font-size: 24rpx;
line-height: 24rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
>image {
width: 35rpx;
height: 28rpx;
margin-bottom: 10rpx;
}
}
}
}
</style>