chore: 添加缺失的静态资源文件

添加多个前端界面所需的图片、字体、音频等静态资源文件,包括:
- 管理员后台的图标、背景图、组件图片
- 移动端页面的商品图片、用户中心图片、活动图标
- 第三方库的示例图片和字体文件
- 浏览器兼容性配置文件
- 图标字体文件(eot、ttf、woff、woff2格式)

这些资源是前端界面正常显示所必需的,之前可能因版本控制忽略或遗漏而缺失。
This commit is contained in:
2026-03-06 20:15:52 +08:00
parent c9a98f342c
commit 0060b2798f
7739 changed files with 1314791 additions and 0 deletions

View File

@@ -0,0 +1,697 @@
<template>
<view :style="colorStyle">
<view>
<view class="w-full notice flex-y-center pl-30 fs-26"
v-show="(configData.community_integral_num > 0 || configData.community_exp_num > 0) && !id">
完成本次发布,审核通过可得
<text class="font-num" v-show="configData.community_integral_num > 0">{{configData.community_integral_num}}积分</text>
<text class="font-num" v-show="configData.community_integral_num > 0 && configData.community_exp_num > 0">+</text>
<text class="font-num" v-show="configData.community_exp_num > 0">{{configData.community_exp_num}}经验值</text>奖励
</view>
<view class="px-30">
<view class="pt-30 grid-column-3 grid-gap-20rpx">
<view class="relative w-full h-214" v-for="(item, index) in formData.slider_image" :key="index"
@tap="proviewPic(item)">
<image :src="item" mode="aspectFill" class="w-full h-214 rd-16rpx"></image>
<view class="abs-rt w-32 h-32 del-pic flex-center" @tap.stop="DelPic(index)">
<text class="iconfont icon-ic_close text--w111-fff fs-20"></text>
</view>
<view class="abs-lt poster-badge flex-center fs-18" v-if="index == 0">封面</view>
</view>
<view
class="w-full h-214 flex-col flex-center upload bg--w111-f5f5f5 rd-16rpx text--w111-999"
@click="uploadpic"
v-if="!formData.video_url && formData.slider_image.length < 9"
>
<text class="iconfont icon-ic_camera fs-60"></text>
<text class="fs-28 lh-40rpx pt-20">添加照片</text>
</view>
<view
class="w-full h-214 flex-col flex-center upload bg--w111-f5f5f5 rd-16rpx text--w111-999"
@click="uploadVideo"
v-if="!formData.slider_image.length && !formData.video_url"
>
<text class="iconfont icon-icon_video fs-60"></text>
<text class="fs-28 lh-40rpx pt-20">添加视频</text>
</view>
<block v-if="formData.video_url">
<view class="w-full h-214 flex-col flex-center video-bg rd-16rpx relative" @tap="openVideoPopup">
<view class="abs-rt w-32 h-32" @tap.stop="delVideo()"></view>
<view class="video-player flex-center">
<text class="iconfont icon-ic_right2 fs-28 text--w111-fff relative"></text>
</view>
<text class="pt-22 fs-18 text--w111-fff">点击可预览视频</text>
</view>
<view class="w-full h-214 flex-col flex-center upload bg--w111-f5f5f5 rd-16rpx text--w111-999" @click="uploadPoster" v-if="!formData.image">
<text class="iconfont icon-ic_camera fs-60"></text>
<text class="fs-28 lh-40rpx pt-12">添加封面</text>
</view>
<view class="w-full h-214 flex-col flex-center upload bg--w111-f5f5f5 rd-16rpx relative text--w111-999" @click="uploadPoster" v-if="formData.image">
<image :src="formData.image" mode="aspectFill" class="w-full h-214 rd-16rpx"></image>
<view class="abs-lt poster-badge flex-center fs-18">封面</view>
<view class="poster-huan flex-center text--w111-fff fs-18">更换封面</view>
</view>
</block>
</view>
<view class="py-32 bb-e">
<input class="fs-30 fw-500" placeholder="填写标题会有更多赞噢~" placeholder-class="text--w111-999" v-model="formData.title" maxlength="20" />
</view>
<view class="pt-18 pb-46 bb-e textarea">
<textarea
class="w-full fs-28 h-280"
placeholder="分享你的体验和心得,你的文字我们都很喜欢~"
name="comment"
placeholder-class="text--w111-999"
v-model="formData.content"
:maxlength="600"
></textarea>
</view>
<view class="h-100 flex-between-center" @tap="openDrawer(0)">
<view class="flex-y-center">
<text class="iconfont icon-icon_talk_2-2"></text>
<view class="pl-8">添加话题</view>
</view>
<view class="fs-28 text--w111-999 flex-y-center" v-show="!topicSelectedList.length">
<text>去添加</text>
<text class="iconfont icon-ic_rightarrow"></text>
</view>
<view class="fs-28 flex-y-center" v-show="topicSelectedList.length">
<view class="w-428 line1 text-right">
<text class="pl-8" v-for="(item, index) in topicSelectedList" :key="index">#{{ item.name }}</text>
</view>
<text class="iconfont icon-ic_rightarrow text--w111-999"></text>
</view>
</view>
<view class="mt-30 flex-between-center" @tap="openDrawer(1)">
<view class="flex-y-center">
<text class="iconfont icon-icon_Link"></text>
<view class="pl-8">
关联商品
<!-- <text v-show="productNum">({{ productNum }})</text> -->
</view>
</view>
<view class="flex-y-center justify-end" v-show="productSelect.length">
<image class="w-60 h-60 rd-6rpx block mr-12" v-for="(item, index) in productSelect" :key="index" :src="item.image"></image>
<text class="iconfont icon-ic_rightarrow fs-32 text--w111-999"></text>
</view>
<view class="fs-28 text--w111-999 flex-y-center" v-show="!productSelect.length">
<text>请选择</text>
<text class="iconfont icon-ic_rightarrow"></text>
</view>
</view>
</view>
</view>
<view class="pb-safe">
<view class="h-200"></view>
</view>
<view class="fixed-lb w-full pb-safe bg--w111-fff z-100">
<view class="footer-box flex-center">
<view class="w-690 h-88 flex-center bg-color text--w111-fff fs-28 rd-44rpx" @tap="confirmSave">发布</view>
</view>
</view>
<base-drawer mode="bottom" :visible="visible" background-color="transparent" mask maskClosable @close="confirmProductDrawer">
<view class="w-full bg--w111-fff rd-t-40rpx py-32 relative">
<view class="close-btn flex-center" @tap="confirmProductDrawer">
<text class="iconfont icon-ic_close text--w111-666 fs-24"></text>
</view>
<view class="flex-center fs-30 text--w111-999">
<view :class="{ 'tab-active': tabActive == 0 }" @tap="changeTab(0, 'pay')">已购</view>
<view class="ml-70" :class="{ 'tab-active': tabActive == 1 }" @tap="changeTab(1, 'collect')">收藏</view>
<view class="ml-70" :class="{ 'tab-active': tabActive == 2 }" @tap="changeTab(2, 'visit')">浏览</view>
</view>
<view class="px-30 mt-50 flex-between-center">
<view class="flex-1 px-32 h-58 rd-30rpx bg--w111-f5f5f5 flex-y-center">
<text class="iconfont icon-ic_search text--w111-999 fs-28"></text>
<input type="text" class="flex-1 pl-20 fs-26" placeholder="输入关键字搜索" placeholder-class="text--w111-ccc" v-model="where.keyword" />
</view>
<text class="fs-28 pl-24" @tap="getSearch">搜索</text>
</view>
<view class="px-30">
<scroll-view scroll-y="true" @scrolltolower="getProductList" style="height: 780rpx">
<view class="flex-between-center" v-for="(item, index) in productList" :key="index">
<text
class="iconfont text--w111-ccc fs-36"
:class="item.isSelect ? 'icon-a-ic_CompleteSelect' : 'icon-ic_unselect'"
@tap="selectItem(item, index)"
></text>
<view class="flex-1 flex h-160 mt-30 pl-30">
<image class="w-160 h-160 rd-16rpx" :src="item.image" mode="aspectFill"></image>
<view class="h-160 flex-1 flex-col justify-between pl-30">
<view class="h-68 lh-34rpx fs-30 line2">{{ item.store_name }}</view>
<baseMoney :money="item.price" symbolSize="24" integerSize="40" decimalSize="24" weight></baseMoney>
</view>
</view>
</view>
<view v-if="!productList.length">
<emptyPage title="暂无商品,去看点别的吧~"></emptyPage>
</view>
</scroll-view>
</view>
<view class="mx-20 pb-safe bg--w111-fff">
<view class="mt-52 h-88 flex-center rd-44rpx bg-color fs-28 text--w111-fff mt-24" @tap="confirmProductDrawer">确定({{ productNum }}/5)</view>
</view>
</view>
</base-drawer>
<uni-popup ref="popup">
<view class="flex-center">
<view class="fixed-lt h-80 flex-y-center pl-20 z-999" :style="{ top: sysHeight + 'px' }" @tap="hideModal">
<text class="iconfont icon-ic_close fs-40 text--w111-fff"></text>
</view>
<!--#ifndef APP-PLUS-->
<video id="myVideo" autoplay loop muted :src="formData.video_url" :style="[videoStyle]"></video>
<!--#endif-->
<!--#ifdef APP-PLUS-->
<view v-html="videoHtml"></view>
<!--#endif-->
</view>
</uni-popup>
<canvas
canvas-id="canvas"
v-if="canvasStatus"
:style="{ width: canvasWidth + 'px', height: canvasHeight + 'px', position: 'absolute', left: '-100000px', top: '-100000px' }"
></canvas>
</view>
</template>
<script>
import colors from '@/mixins/color';
import store from '@/store';
import { mapState, mapGetters } from 'vuex';
import { toLogin } from '@/libs/login.js';
import { TOKENNAME, HTTP_REQUEST_URL } from '@/config/app.js';
import baseDrawer from '@/components/tui-drawer/tui-drawer.vue';
import emptyPage from '@/components/emptyPage.vue';
import { getProductslist } from '@/api/store.js';
import {
getTopicApi,
getProductApi,
communitySaveApi,
communityInfoApi,
communityUpdateApi,
getCommunityConfig ,
} from '@/api/community.js';
import { Debounce } from '@/utils/validate.js'
let app = getApp();
export default {
data() {
return {
sysHeight: app.globalData.sysHeight,
id: '',
canvasStatus: false,
visible: false,
tabActive: 0,
keyword: '',
topicList: [],
recommendTopic: [],
topicSelectedList: [],
productList: [],
productSelect: [],
loading: false,
where: {
page: 1,
limit: 20,
type: 'pay',
keyword: ''
},
formData: {
content_type: null, //内容类型1:图文2视频
title: '',
content: '',
image: '', //视频封面
video_url: '',
slider_image: [],
topic_name: [],
product_id: []
},
upload_max: 50,
uploadUrl: `${HTTP_REQUEST_URL}/api/upload/video`,
videoContext: '',
productNum: 0,
topicNum: 0,
canvasWidth: '',
canvasHeight: '',
configData:{
community_exp_num:0, //经验
community_integral_num:0 //积分
},
};
},
components: { baseDrawer, emptyPage },
computed: {
...mapGetters(['isLogin']),
videoHtml() {
return `<video autoplay loop muted controls="controls" width="100%" height="870px"><source src="${this.formData.video_url}" type="video/mp4"></video>`;
},
videoStyle() {
return {
width: uni.getWindowInfo().windowWidth + 'px',
height: uni.getWindowInfo().windowHeight + 'px'
};
},
popupHeight(){
return uni.getWindowInfo().windowHeight * 0.8
},
},
mixins: [colors],
onShow() {
let that = this;
uni.$on("topicSave", data => {
if (data) {
that.topicSelectedList = data;
}
// 清除监听
uni.$off('topicSave');
})
},
onLoad(options) {
if (this.isLogin) {
this.getConfig();
if (options.id) {
this.id = options.id;
this.getInfo();
}
if (options.topic_name) {
// this.topicName = options.topic_name;
this.topicSelectedList.push({name:options.topic_name})
}
this.getProductList();
// #ifndef APP-PLUS
this.videoContext = uni.createVideoContext('myVideo', this);
// #endif
} else {
toLogin();
}
},
methods: {
getConfig(){
getCommunityConfig().then(res=>{
this.configData = res.data;
})
},
proviewPic(url){
uni.previewImage({
urls: this.formData.slider_image,
current: url
});
},
DelPic(index) {
this.formData.slider_image.splice(index, 1);
},
delVideo() {
this.formData.video_url = '';
},
openVideoPopup() {
this.$refs.popup.open();
this.videoContext = uni.createVideoContext('myVideo', this);
this.$nextTick(() => {
this.videoContext.play();
});
},
hideModal() {
this.$refs.popup.close();
},
uploadPoster() {
let that = this;
this.canvasStatus = true;
that.$util.uploadImageChange(
{ count: 1, url: 'upload/image' },
function (res) {
that.formData.image = res.data.url;
},
(res) => {
this.canvasStatus = false;
},
(res) => {
this.canvasWidth = res.w;
this.canvasHeight = res.h;
}
);
},
uploadpic() {
let that = this;
this.canvasStatus = true;
that.$util.uploadImageChange(
{ count: 9, url: 'upload/image' },
function (res) {
if (that.formData.slider_image.length == 9)
return that.$util.Tips({
title: '最多上传9张'
});
that.formData.slider_image.push(res.data.url);
},
(res) => {
this.canvasStatus = false;
},
(res) => {
this.canvasWidth = res.w;
this.canvasHeight = res.h;
}
);
},
// 上传视频
uploadVideo() {
let that = this;
uni.chooseVideo({
sourceType: ['camera', 'album'],
success: (res) => {
uni.showLoading({
title: '视频上传中'
});
if (Math.ceil(res.size / 1024) < that.upload_max * 1024) {
uni.uploadFile({
url: that.uploadUrl,
filePath: res.tempFilePath,
name: 'file',
header: {
// #ifdef MP
'Content-Type': 'multipart/form-data',
// #endif
[TOKENNAME]: 'Bearer ' + store.state.app.token
},
success: (uploadFileRes) => {
uni.hideLoading();
let data = JSON.parse(uploadFileRes.data);
if (data.status == 200) {
that.formData.video_url = data.data.url;
} else {
return this.$util.Tips({
title: data.msg
});
}
},
complete: function (err) {
uni.hideLoading();
}
});
} else {
uni.hideLoading();
uni.showModal({
title: '提示',
showCancel: false,
content: `视频超出限制${that.upload_max}MB`
});
}
},
fail: (err) => {
that.$util.Tips({
title: err
});
}
});
},
confirmProductDrawer() {
this.visible = false;
},
openDrawer(type) {
if (type == 1) {
if (this.id) {
this.productList.map((itemA) => {
this.formData.product_id.forEach((itemB) => {
if (itemB === itemA.product_id) {
this.$set(itemA, 'isSelect', true);
}
});
});
}
this.visible = !this.visible;
} else {
let that = this;
// uni.$emit("topicOpen", that.topicSelectedList)
let jsonStr = '';
if(this.topicSelectedList.length){
jsonStr = JSON.stringify(this.topicSelectedList)
}
uni.navigateTo({
url: '/pages/discover/discoverCreate/topic?data=' + jsonStr
})
// this.showTopic = !this.showTopic;
// if (this.showTopic) {
// this.topicKeyword = '#';
// this.focus = true;
// }
}
},
getProductList() {
if (this.loading) return;
this.loading = true;
getProductApi(this.where)
.then((res) => {
res.data.map((item) => {
this.$set(item, 'isSelect', false);
this.formData.product_id.forEach((itemB) => {
if (itemB === item.product_id) {
this.$set(item, 'isSelect', true);
}
});
});
let list = res.data;
let loading = list.length < this.where.limit;
this.productList = this.productList.concat(list);
this.where.page++;
this.loading = loading;
})
.catch((err) => {
this.loading = false;
return this.$util.Tips({
title: err
});
});
},
getSearch() {
this.loading = false;
this.where.page = 1;
this.productList = [];
this.getProductList();
},
changeTab(val, type) {
this.tabActive = val;
this.where.type = type;
this.getSearch();
},
selectItem(item) {
if (item.isSelect) {
item.isSelect = false;
if (this.formData.product_id.includes(item.product_id)) {
let i = this.productSelect.findIndex((o) => o.id == item.product_id);
this.productSelect.splice(i, 1);
this.formData.product_id.splice(i, 1);
this.productNum--;
}
} else {
if (this.productSelect.length == 5)
return this.$util.Tips({
title: '最多选择5件商品'
});
item.isSelect = true;
let arr = [];
this.productSelect.forEach((k) => {
arr.push(k.id);
});
if (!arr.includes(item.product_id)) {
this.productNum++;
this.productSelect.push(item);
this.formData.product_id.push(item.product_id);
}
}
},
confirmSave() {
// if(!this.formData.title) return this.$util.Tips({
// title: '请输入标题'
// })
if (!this.formData.content)
return this.$util.Tips({
title: '请输入内容'
});
if (!this.formData.video_url && !this.formData.slider_image.length)
return this.$util.Tips({
title: '请上传要分享的图片'
});
if (this.formData.video_url && !this.formData.image)
return this.$util.Tips({
title: '请上传海报'
});
this.formData.topic_name = this.topicSelectedList.map(item => item.name);
this.formData.content_type = this.formData.slider_image.length ? 1 : 2;
uni.showLoading({
title: '正在提交...'
});
let funApi = '';
funApi = this.id ? communityUpdateApi(this.id, this.formData) : communitySaveApi(this.formData);
funApi
.then((res) => {
uni.hideLoading();
let exp = this.configData.community_exp_num;
let integral = this.configData.community_integral_num;
return this.$util.Tips(
{
title: res.msg
},
{
tab: 4,
url: '/pages/discoverIndex/index'
}
);
})
.catch((err) => {
uni.hideLoading();
return this.$util.Tips({
title: err
});
});
},
getInfo() {
communityInfoApi(this.id)
.then((res) => {
let info = res.data;
let keys = Object.keys(this.formData);
keys.map((i) => {
this.formData[i] = info[i];
});
if (this.formData.product_id == null) {
this.formData.product_id = [];
}
if (res.data.topic.length) {
this.topicSelectedList = res.data.topic;
}
if (res.data.product && res.data.product.length) {
this.productSelect = res.data.product;
}
this.productNum = res.data.product.length;
this.topicNum = res.data.topic.length;
})
.catch((err) => {
return this.$util.Tips({
title: err
});
});
},
}
};
</script>
<style>
page {
background-color: #ffffff;
}
</style>
<style lang="scss">
.notice {
height: 84rpx;
background: var(--view-minorColorT);
}
.del-pic {
background-color: #999;
border-radius: 0 16rpx 0 16rpx;
}
.close-btn {
position: absolute;
right: 28rpx;
top: 28rpx;
width: 36rpx;
height: 36rpx;
border-radius: 50%;
background-color: #eee;
}
.bb-e {
border-bottom: 1rpx solid #eee;
}
.b-e {
border: 1rpx solid #eee;
}
.b-d {
border: 1rpx solid #ddd;
}
.filter-cell ~ .filter-cell{
border-top: 1px solid #f5f5f5;
}
.textarea {
height: 100%;
}
.label-item {
color: var(--view-theme);
background: var(--view-minorColorT);
border: 1rpx solid transparent;
}
.icon-a-ic_CompleteSelect {
color: var(--view-theme);
}
.pro-cell {
padding: 36rpx 30rpx;
}
.add-btn {
width: 690rpx;
height: 88rpx;
background: var(--view-theme);
border-radius: 50rpx;
background-color: var(--view-theme);
margin-bottom: 32rpx;
}
.tab-active {
font-weight: 500;
color: #333;
position: relative;
&:after {
content: '';
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: -14rpx;
width: 40rpx;
height: 5rpx;
background: var(--view-theme);
border-radius: 4rpx;
}
}
.poster-badge {
width: 54rpx;
height: 29rpx;
background: var(--view-theme);
color: #fff;
border-radius: 16rpx 0rpx 16rpx 0rpx;
}
.video-bg {
background-image: url('@/static/img/video_bg.png');
background-repeat: no-repeat;
background-size: cover;
}
.video-player {
width: 50rpx;
height: 50rpx;
border-radius: 50%;
background: rgba(0, 0, 0, 0.5);
.iconfont {
left: 2rpx;
}
}
.poster-huan {
position: absolute;
bottom: 0;
width: 100%;
height: 40rpx;
background: rgba(0, 0, 0, 0.5);
border-radius: 0rpx 0rpx 16rpx 16rpx;
}
.canvas-box {
position: absolute;
left: -100px;
top: -100px;
width: 750px;
height: 1624px;
}
.footer-box {
height: 126rpx;
.w-690 {
width: 690rpx;
}
}
.mt-62{
margin-top: 62rpx;
}
.close-icon{
top: 36rpx;
right: 32rpx;
}
.overflow-scroll{
overflow-y: scroll;
}
</style>

View File

@@ -0,0 +1,185 @@
<template>
<view :style="colorStyle">
<view class="px-30">
<view class="topic-box pt-24 pb-10 bb-e w-full flex-y-center flex-wrap">
<view class="h-52 px-16 font-num bg-light rd-30rpx flex-center fs-26 mr-22 mb-20"
v-for="(item, index) in topicSelectedList" :key="index"
@tap="delTopic(index)">
<text class="pr-8">#{{item.name}} </text>
<text class="iconfont icon-ic_close fs-24"></text>
</view>
<input type="text" placeholder="新建或搜索话题" class="fs-28 lh-40rpx flex-1 mb-20 min-w-150"
:maxlength="10" :focus="focus" v-model.trim="topicKeyword"
@input="handleInput" @confirm="confirmCreate" />
</view>
<view class="flex-y-center flex-wrap pt-32">
<view class="h-52 px-16 bg--w111-f5f5f5 rd-30rpx flex-center fs-26 mr-22 mb-20"
v-for="(item, index) in recommendTopic" :key="index"
@tap="changeTopic(item)">#{{item.name}}</view>
</view>
<view class="w-full fixed-lt bg--w111-fff z-20" :style="[filterStyle]" v-show="showFilter">
<view class="relative mt-20 px-30 h-full overflow-scroll">
<view class="h-88 filter-cell flex-between-center"
v-for="(cell,i) in filterTopicList" :key="i"
@tap="changeTopic(cell)">
<text class="fs-28 fw-500 lh-40rpx">
<text>#</text>{{cell.name}}</text>
<text class="text--w111-999 fs-22" v-show="cell.community_count > 0">{{cell.community_count}}篇内容</text>
</view>
<view class="h-80"></view>
</view>
</view>
<view class="fixed-lb w-full pb-safe">
<view class="h-128 flex-center px-30">
<view class="w-full h-88 rd-44rpx bg-color text--w111-fff flex-center fs-28"
@tap="saveTopic">完成</view>
</view>
</view>
</view>
</view>
</template>
<script>
let sysHeight = uni.getWindowInfo().statusBarHeight;
import { getTopicApi } from "@/api/community.js"
import colors from '@/mixins/color';
import { Debounce } from '@/utils/validate.js'
export default {
name: "createTopic",
data(){
return {
sysHeight,
id: 0,
topicSelectedList:[],
topicKeyword:"",
showFilter: false,
filterTopicList:[],
focus: true,
recommendParams:{
page:1,
limit:10,
is_recommend: 1,
},
showMore: false,
recommendTopic: [],
boxHeight: 0
}
},
mixins: [colors],
computed:{
filterStyle(){
let windowHeight = uni.getWindowInfo().windowHeight;
return {
height: windowHeight - this.boxHeight + 'px',
top: this.boxHeight + 'px'
}
}
},
onLoad(options) {
if(options.data){
this.topicSelectedList = JSON.parse(options.data)
}
this.getTopic();
},
methods:{
getHeight() {
let that = this;
uni.createSelectorQuery().select('.topic-box').boundingClientRect(function(rect) {
that.boxHeight = rect.height;
}).exec();
},
handleInput: Debounce(function(e){
if(this.topicKeyword){
getTopicApi({is_community: 1,name: this.topicKeyword}).then(res => {
this.getHeight();
this.filterTopicList = res.data;
this.filterTopicList.unshift({name: this.topicKeyword})
this.showFilter = true;
});
}else{
this.showFilter = false;
}
}),
getTopic() {
getTopicApi(this.recommendParams).then((res) => {
this.showMore = res.data.length >= this.recommendParams.limit;
this.recommendTopic = this.recommendTopic.concat(res.data);
this.recommendParams.page++;
// 如果是从话题页面点进来,把url上携带的话题名称塞入已选择话题,并从推荐列表删除该话题
// if (this.topicName) {
// this.topicSelectedList.push({name: '#' + this.topicName});
// this.recommendTopic.splice(
// this.recommendTopic.findIndex((itemn) => itemn.name == this.topicName),
// 1
// );
// }
// 如果是编辑内容,添加的话题存在推荐话题中,从推荐话题中删除已添加的
let indicesToRemove = [];
this.recommendTopic.forEach((item, index) => {
this.topicSelectedList.forEach((itemn) => {
if (itemn.name.includes(item.name)) {
indicesToRemove.push(index);
}
});
});
// 去重并按降序排序,确保删除时不会影响后续索引
indicesToRemove = [...new Set(indicesToRemove)].sort((a, b) => b - a);
// 删除指定索引的元素
indicesToRemove.forEach((index) => {
this.recommendTopic.splice(index, 1);
});
});
},
changeTopic(item) {
this.showFilter = false;
this.topicKeyword = '';
if (this.topicSelectedList.length > 4) return this.$util.Tips({
title: '最多可选择5个话题'
});
this.focus = false;
let arr = this.topicSelectedList.map(item => item.name);
if(!arr.includes(item.name)){
this.topicSelectedList.push(item);
}
this.recommendTopic.splice(this.recommendTopic.findIndex((itemn) => itemn.id == item.id),1);
this.$nextTick(() => {
this.focus = true;
});
},
confirmCreate(){
if(!this.topicKeyword) return
this.changeTopic({name: this.topicKeyword});
},
saveTopic(){
let that = this;
uni.$emit("topicSave", that.topicSelectedList)
uni.navigateBack()
},
delTopic(index){
this.topicSelectedList.splice(index,1)
}
}
}
</script>
<style>
page{
background-color: #ffffff;
}
</style>
<style lang="scss">
.bg-light{
background-color: var(--view-minorColorT);
}
.bb-e {
border-bottom: 1rpx solid #eee;
}
.min-w-150{
min-width: 150rpx;
}
.filter-cell ~ .filter-cell{
border-top: 1px solid #f5f5f5;
}
.overflow-scroll{
overflow-y: scroll;
}
</style>

View File

@@ -0,0 +1,798 @@
<template>
<view :style="colorStyle">
<view>
<view v-show="[0,-1,-2].includes(infoData.is_verify)">
<view class="error pt-26 pb-24 pl-32" v-if="infoData.is_verify == -2">
<view class="flex-y-center fs-28 fw-500">
<text class="iconfont icon-a-ic_tanhao1 fs-30"></text>
<text class="pl-16">平台强制下架,内容仅自己可见</text>
</view>
<view class="fs-22 text--w111-666 pt-16 pl-46">{{infoData.refusal}}!</view>
</view>
<view class="error pt-26 pb-24 pl-32" v-if="infoData.is_verify == -1">
<view class="flex-y-center fs-28 fw-500">
<text class="iconfont icon-a-ic_tanhao1 fs-30"></text>
<text class="pl-16">审核未通过,内容仅自己可见</text>
</view>
<view class="fs-22 text--w111-666 pt-16 pl-46">{{infoData.refusal}}</view>
</view>
<view class="warning pt-26 pb-24 pl-32" v-if="infoData.is_verify == 0">
<view class="flex-y-center fs-28 fw-500">
<text class="iconfont icon-icon_clock1 fs-30"></text>
<text class="pl-16">正在审核,内容仅自己可见</text>
</view>
<view class="fs-22 text--w111-666 pt-16 pl-46">发布的内容审核通过后,将在展示首页展示!</view>
</view>
</view>
<view class="load-box w-full" v-show="!imageH"></view>
<swiper
class="swiper"
circular
:indicator-dots="infoData.slider_image.length > 1"
indicator-color="rgba(255, 255, 255, 0.4)"
indicator-active-color="#f5f5f5"
autoplay
:interval="3000"
:duration="500"
:style="{height:imageH + 'px'}"
v-show="imageH">
<swiper-item v-for="(item,index) in infoData.slider_image" :key="index">
<view class="swiper-item flex-center">
<image class="w-full"
show-menu-by-longpress
:src="item"
:mode="isAuto ? 'aspectFill' : 'heightFix'"
:style="{height:imageH + 'px'}"
@tap="proview(item)"></image>
</view>
</swiper-item>
</swiper>
<view class="px-20">
<view class="fs-32 lh-42rpx fw-500 pt-24">{{infoData.title}}</view>
<view class="pt-12 fs-28 lh-42rpx space-line">{{infoData.content}}</view>
<view class="text--w111-133667 fs-28 lh-42rpx pt-10">
<text class="pr-10" v-for="(topic,i) in infoData.topic" :key="i"
@tap="authTo('/pages/discover/discoverTopic/index?id=' + topic.id + '&name=' + topic.name)">#{{topic.name}}</text>
</view>
<view class="pt-36 pb-26rpx fs-22 text--w111-999">{{infoData.add_time}}</view>
<view class="w-full pb-40 bb-f5" v-if="infoData.product && infoData.product.length > 1">
<scroll-view scroll-x="true" class="white-nowrap vertical-middle w-full" show-scrollbar="false">
<view class="inline-block mr-30" v-for="(item,index) in infoData.product" :key="index">
<view class="w-536 rd-24rpx p-20 bg--w111-f9f9f9 flex-between-center" @tap="authTo('/pages/goods_details/index?id=' + item.id)">
<image :src="item.image" class="w-160 h-160 rd-16rpx"></image>
<view class="flex-1 h-160 flex-col justify-between pl-20">
<view class="w-308 h-80 lh-40rpx line2 break_word fs-28 text--w111-333">{{item.store_name}}</view>
<baseMoney :money="item.price" symbolSize="32" integerSize="40" decimalSize="32" color="#333" weight></baseMoney>
</view>
</view>
</view>
</scroll-view>
</view>
<view class="w-full pb-40" v-else-if="infoData.product && infoData.product.length == 1">
<view class="w-full rd-16rpx p-20 bg--w111-f9f9f9 flex-between-center" @tap="authTo('/pages/goods_details/index?id=' + infoData.product[0].id)">
<image :src="infoData.product[0].image" class="w-160 h-160 rd-16rpx"></image>
<view class="flex-1 h-160 flex-col justify-between pl-20">
<view class="w-486 h-80 lh-40rpx line2 break_word fs-26">{{infoData.product[0].store_name}}</view>
<view class="flex-between-center">
<baseMoney :money="infoData.product[0].price" symbolSize="32" integerSize="40" decimalSize="32" color="#333" weight></baseMoney>
<view class="w-92 h-40 rd-20rpx flex-center fs-22 font-num theme-border">购买</view>
</view>
</view>
</view>
</view>
</view>
<view class="px-30 bt-f5" v-if="configData.community_comment_status">
<view class="pt-40 fs-26">评论 {{infoData.comment_num}}</view>
<view class="reply-list" v-if="replyList.length">
<view class="flex mt-22" v-for="(item,index) in replyList" :key="index"
v-show="(item.uid == uid && item.is_show == 0) || item.is_show == 1">
<image class="w-74 h-74 rd-50-p111-" :src="item.author_image"
@tap="authTo('/pages/discover/discoverUser/index?id=' + item.uid)"></image>
<view class="flex-1 ml-20">
<view class="w-full">
<view class="fs-26 text--w111-999">{{item.author}}</view>
<view class="fs-28 lh-42rpx text--w111-333" @tap="showReply(item.id,item.author,item.is_show)">{{item.content}}
<text class="pl-8 text--w111-999" v-show="!item.is_show && item.uid == uid">(该评论已被屏蔽)</text>
</view>
<view class="lh-36rpx flex-between-center pt-4">
<view class="flex-y-center fs-24">
<text class="text--w111-ccc">{{item.time_text}}</text>
<text class="pl-24 text--w111-999" @tap="delReply(item.id,item.comment_num)"
v-show="isLogin && uid == item.uid">删除</text>
</view>
<view class="flex-y-center text--w111-999" @tap="replyLike(item)">
<text class="iconfont fs-30" :class="item.isLike ? 'icon-icon_Like_2' : 'icon-ic_Like'"></text>
<text class="fs-24 lh-36rpx pl-10">{{item.like_num}}</text>
</view>
</view>
</view>
<view class="mt-12 w-full" v-if="item.show">
<view class="child-reply w-full flex justify-between"
v-for="(reply,i) in item.children" :key="i"
v-show="(reply.uid == uid && reply.is_show == 0) || reply.is_show == 1">
<view class="flex w-full" >
<image :src="reply.author_image" class="w-36 h-36 rd-50-p111-"
@tap="authTo('/pages/discover/discoverUser/index?id=' + reply.reply_uid)"></image>
<view class="ml-20 flex-1">
<view class="text--w111-999 fs-26 lh-40rpx">{{reply.author}}</view>
<view class="w-full fs-26 lh-42 flex-y-center flex-wrap" @tap="showReply(reply.id, reply.author,reply.is_show)">
<view v-if="reply.comment_author">
回复<text class="comment-author"
@tap="authTo('/pages/discover/discoverUser/index?id=' + reply.comment_reply_uid)">@{{reply.comment_author}}</text>
</view>
{{reply.content}}<text class="pl-8 text--w111-999" v-show="!item.is_show && item.uid == uid">(该评论已被屏蔽)</text>
</view>
<view class="flex-between-center pt-4">
<view class="fs-24 text--w111-ccc lh-36rpx flex-y-center">
<text>{{reply.time_text}}</text>
<text class="pl-24 text--w111-999" @tap="delReply(reply.id,reply.comment_num)"
v-show="isLogin && uid == reply.uid">删除</text>
</view>
<view class="flex-y-center text--w111-999" @tap.stop="replyLike(reply)">
<text class="iconfont fs-30" :class="reply.isLike ? 'icon-icon_Like_2' : 'icon-ic_Like'"></text>
<text class="fs-24 lh-36rpx pl-10">{{reply.like_num}}</text>
</view>
</view>
</view>
</view>
</view>
</view>
<view class="mt-14 flex-y-center text--w111-666 fs-26"
v-if="item.comment_num > 0 && !item.show" @tap="showMore(item,index,1)">
<text class="more-line"></text>
<text class="pl-16">展开{{item.comment_num}}条回复</text>
<text class="iconfont icon-ic_downarrow fs-28"></text>
</view>
<view class="mt-14 flex-y-center text--w111-666 fs-26"
v-if="item.comment_num > 0 && item.show" @tap="showMore(item,index,0)">
<text class="more-line"></text>
<text class="pl-16">收起回复</text>
<text class="iconfont icon-ic_uparrow fs-28"></text>
</view>
</view>
</view>
</view>
<view v-else>
<emptyPage title="暂无评论" src="/statics/images/noActivity.gif"></emptyPage>
</view>
</view>
<view class="h-200"></view>
<view class="fixed-lb w-full bg--w111-fff pb-safe z-999">
<view class="h-90 pl-20 pr-24 flex-between-center" v-show="!showInput">
<view class="flex-y-center">
<image :src="infoData.author_image || '/static/images/f.png'" class="w-60 h-60 rd-50-p111-"
@tap="authTo('/pages/discover/discoverUser/index?id=' + infoData.relation_id)"></image>
<view class="max-w-200 line1 ml-20 fs-28 fw-500"
@tap="authTo('/pages/discover/discoverUser/index?id=' + infoData.relation_id)">{{infoData.author || '用户已注销'}}</view>
<view class="flex-y-center pl-12">
<view class="relative" v-if="infoData.is_self && isLogin">
<view class="w-124 h-52 rd-30rpx b-e flex-center fs-24" @tap="()=>{showBubble = !showBubble}">管理</view>
<view class="bubble_box">
<view class="bubble flex-col justify-between" v-if="showBubble">
<view class="flex-y-center pl-16" @tap="authTo('/pages/discover/discoverCreate/index?id=' + community_id)">
<text class="iconfont icon-ic_edit"></text>
<text class="fs-26 pl-18">编辑</text>
</view>
<view class="x-line"></view>
<view class="flex-y-center pl-16" @tap="delContent">
<text class="iconfont icon-ic_delete"></text>
<text class="fs-26 pl-18">删除</text>
</view>
</view>
</view>
</view>
<view v-else>
<view class="flex-y-center" v-show="!infoData.is_follow" @tap="followChange">
<view class="h-44 px-24 rd-30rpx theme-border font-num flex-center fs-20">
<text class="iconfont icon-ic_increase fs-20" ></text>关注
</view>
</view>
<view class="flex-y-center" v-show="infoData.is_follow" @tap="followChange">
<view class="h-44 px-24 rd-30rpx b-e flex-center fs-20 text--w111-999">已关注</view>
</view>
</view>
</view>
</view>
<view class="flex-y-center">
<view class="text-primary-con flex-y-center" @tap="contentLike">
<text class="iconfont fs-40" :class="infoData.is_like ? 'icon-ic_love_2' : 'icon-ic_love'"></text>
<text class="fs-26 pl-10">{{infoData.like_num}}</text>
</view>
<view class="pl-32 flex-y-center" @tap="openInput">
<text class="iconfont icon-ic_daipingjia1 fs-40"></text>
<text class="fs-26 pl-10">{{infoData.comment_num}}</text>
</view>
<!-- #ifdef H5 || APP-PLUS -->
<text class="iconfont icon-ic_share fs-40 pl-32" @tap="openShare"></text>
<!-- #endif -->
<!-- #ifdef MP-WEIXIN -->
<button class="iconfont icon-ic_share fs-40 pl-32" open-type="share" hover-class="none"></button>
<!-- #endif -->
</view>
<!-- v-if="configData.community_comment_status && configData.community_comment_add" -->
</view>
<view class="h-90 pl-20 pr-24 flex-between-center" v-show="showInput">
<input type="text"
v-model="comment"
:placeholder="placeholder"
:focus="focus"
placeholder-class="text--w111-999"
class="flex-1 h-64 rd-32rpx bg--w111-f5f5f5 pl-30 fs-26 text--w111-333" />
<view class="w-112 h-64 rd-32rpx flex-center bg-gradient text--w111-fff fs-24 ml-24"
@tap="sendText">发送</view>
</view>
</view>
</view>
<view class="bubble-mask" v-if="showBubble" @tap="()=>{showBubble = false}"></view>
<view class="mask" v-if="showInput" @tap="()=>{showInput = false}"></view>
<!-- 确认框 -->
<tuiModal
:show="showModal"
:title="modalTitle"
:maskClosable="false"
@click="handleClick"></tuiModal>
<home></home>
</view>
</template>
<script>
import { HTTP_REQUEST_URL } from '@/config/app';
import colors from "@/mixins/color";
import {
getCommunityConfig,
communityInfoApi,
communityReplySaveApi,
communityReplyListApi,
communityReplyLikeApi,
communitySetInsterestApi,
communityLikeApi,
communityDeleteApi,
communityShareApi,
communityReplyDeleteApi,
communityBrowseApi
} from "@/api/community.js";
import { mapState, mapGetters } from 'vuex';
import { toLogin } from '@/libs/login.js';
import emptyPage from '@/components/emptyPage.vue';
import tuiModal from "@/components/tui-modal/index.vue"
let app = getApp();
export default {
data() {
return {
sysHeight: app.globalData.sysHeight,
infoData:{
userInfo:{
avatar:'',
nickname:''
},
author_image:'',
author:'',
title:'',
content:'',
content_type:1,
slider_image:[],
productList:[],
topicList:[],
video_url:'',
comment_num:0
},
imageH:0,
videoHeight:0,
community_id:'',
comment_reply_id:'',
replyIndex:'',
showBubble:false,
showInput:false,
comment:'',
replyList:[],
modalTitle:'',
showModal:false,
modalType:0,
placeholder:'说说你的看法吧~',
commentNum:0,
configData:{},
focus:false,
configData:{
community_status:1,
community_comment_add:1,
community_comment_status:1
},
isAuto:true
};
},
components: {
emptyPage,
tuiModal,
},
mixins: [colors],
computed: {
...mapGetters(['isLogin','uid']),
},
onLoad(options) {
if(options.id){
this.community_id = options.id;
this.getConfig();
this.getInfo();
this.getReply();
if(this.isLogin){
communityBrowseApi(options.id).catch(err=>{
console.error(err);
})
}
}else{
return this.$util.Tips({
title: '缺少参数无法查看内容'
}, {
tab: 3
});
}
},
onShow() {
this.showBubble = false;
},
onPageScroll() {
this.showBubble = false;
uni.$emit('scroll');
},
methods:{
getConfig(){
getCommunityConfig().then(res=>{
this.configData = res.data;
})
},
proview(url){
uni.previewImage({
urls: this.infoData.slider_image,
current: url,
});
},
computedHeight(){
let that = this;
if(this.infoData.slider_image.length){
let windowWidth = uni.getWindowInfo().windowWidth;
uni.getImageInfo({
src: that.setDomain(this.infoData.slider_image[0]),
success: (image) => {
let imageH = parseInt(image.height * windowWidth / image.width);
if(imageH > 500){
this.isAuto = false;
this.imageH = 500;
}else{
this.imageH = imageH;
}
}
})
}
},
openShare(){
// #ifdef H5
let that = this;
uni.setClipboardData({
data: `${HTTP_REQUEST_URL}/pages/discover/discoverDetails/index?id=${this.community_id}&spid=${this.uid}`,
success: () =>{
communityShareApi(that.community_id).catch(err=>{
console.error(err);
})
uni.showToast({
title: '链接已复制'
})
}
})
// #endif
// #ifdef APP-PLUS
let that = this
uni.share({
provider: "weixin",
scene: 'WXSceneSession',
type: 0,
href: `${HTTP_REQUEST_URL}/pages/discover/discoverDetails/index?id=${this.community_id}&spid=${this.uid}`,
title: that.infoData.title,
summary: that.infoData.content,
imageUrl: this.infoData.image,
fail: function(err) {
uni.showToast({
title: '分享失败',
icon: 'none',
duration: 2000
})
}
});
// #endif
},
delContent(){
this.modalTitle = '确认删除该内容';
this.modalType = 1;
this.showModal = true;
this.showBubble = false;
},
delReply(id,num){
this.modalTitle = '确认删除该评论';
this.commentNum = num;
this.modalType = 2;
this.comment_reply_id = id;
this.showModal = true;
},
authTo(url){
uni.navigateTo({
url: url
});
},
getInfo(){
communityInfoApi(this.community_id).then(res=>{
this.infoData = res.data;
// #ifdef H5
this.ShareInfo();
// #endif
if(res.data.slider_image.length){
this.computedHeight();
}
}).catch(err => {
return this.$util.Tips({
title: err
});
});
},
setDomain(url) {
url = url ? url.toString() : '';
//本地调试打开,生产请注销
if (url.indexOf("https://") > -1) return url;
else return url.replace('http://', 'https://');
},
onVideoLoad(event) {
console.log(`${710 * (event.detail.height / event.detail.width)}rpx`)
this.videoHeight = `${710 * (event.detail.height / event.detail.width)}rpx`
},
getReply(){
let params = {
community_id:this.community_id,
reply_id:'',
};
communityReplyListApi(params).then(res=>{
if(res.data.list.length){
res.data.list.map(item=>{
this.$set(item,'show',false);
})
this.replyList = res.data.list;
}
}).catch(err => {
return this.$util.Tips({
title: err
});
});
},
sendText(){
if(this.comment == '') return this.$util.Tips({
title: '请输入评论内容'
});
let data = {
community_id:this.community_id,
comment_reply_id:this.comment_reply_id,
content:this.comment
};
communityReplySaveApi(data).then(res=>{
this.comment_reply_id = '';
this.infoData.comment_num++;
this.showInput = false;
this.focus = false;
this.comment = '';
this.placeholder = '说说你的看法吧~'
this.getReply();
return this.$util.Tips({
title: res.msg
});
}).catch(err => {
return this.$util.Tips({
title: err
});
});
},
showReply(id,author,is_show){
if(is_show == 0) return this.$util.Tips({
title: '该评论已被屏蔽,禁止回复'
});
this.comment_reply_id = id;
this.placeholder = `回复:${author}`
this.showInput = true;
},
replyLike(item){
let id = item.id;
let status = item.isLike == 1 ? 0 : 1;
let that = this;
communityReplyLikeApi(id,{status}).then(res=>{
item.isLike = status;
if(status == 1){
item.like_num++
}else{
item.like_num--
}
return that.$util.Tips({
title: res.msg
});
}).catch(err=>{
return that.$util.Tips({
title: err
});
})
},
showMore(item,index,type){
this.replyIndex = index;
if(type){
let params = {
community_id:this.community_id,
reply_id:item.id,
};
communityReplyListApi(params).then(res=>{
this.$set(this.replyList[index],'children',res.data.list);
this.$set(item,'show',true);
}).catch(err => {
return this.$util.Tips({
title: err
});
});
}else{
this.$set(item,'show',false);
}
},
followChange(){
if(this.infoData.is_follow == 0){
communitySetInsterestApi(this.infoData.relation_id,{status:1}).then(res=>{
this.infoData.is_follow = 1;
return this.$util.Tips({
title: res.msg
});
}).catch(err => {
return this.$util.Tips({
title: err
});
});
}else{
this.modalTitle = '确认取消关注';
this.modalType = 0;
this.showModal = true;
}
},
handleClick(e){
let index = e.index;
let that = this;
if(index == 1){
if(this.modalType == 0){
communitySetInsterestApi(this.infoData.relation_id,{status:0}).then(res=>{
this.infoData.is_follow = 0;
this.showModal = false;
return this.$util.Tips({
title: res.msg
});
}).catch(err => {
this.showModal = false;
return this.$util.Tips({
title: err
});
});
}else if(this.modalType == 1){
communityDeleteApi(this.community_id).then(res=>{
this.showModal = false;
return this.$util.Tips({
title: res.msg
},{
tab:4,
url:'/pages/discoverIndex/index'
});
}).catch(err => {
this.showModal = false;
return this.$util.Tips({
title: err
});
});
}else if(this.modalType == 2){
communityReplyDeleteApi(this.comment_reply_id).then(res=>{
this.showModal = false;
this.replyList = [];
this.reply_id = '';
this.comment_reply_id = '';
this.infoData.comment_num = this.infoData.comment_num - (1 + this.commentNum);
this.getReply();
}).catch(err => {
this.showModal = false;
return this.$util.Tips({
title: err
});
});
}
}else{
this.showModal = false;
}
},
contentLike(){
let status = this.infoData.is_like == 1 ? 0 : 1;
let that = this;
communityLikeApi(this.infoData.id,{status}).then(res=>{
this.infoData.is_like = status;
if(status == 1){
this.infoData.like_num++
}else{
this.infoData.like_num--
}
}).catch(err=>{
return this.$util.Tips({
title: err
});
})
},
openInput(){
this.showInput = true;
this.focus = true;
},
ShareInfo() {
if (this.$wechat.isWeixin()) {
let configAppMessage = {
desc: this.infoData.content,
title: this.infoData.title,
link: `${HTTP_REQUEST_URL}/pages/discover/discoverDetails/index?id=${this.community_id}&spid=${this.uid}`,
imgUrl: this.infoData.image
};
this.$wechat
.wechatEvevt([
'updateAppMessageShareData',
'updateTimelineShareData',
'onMenuShareAppMessage',
'onMenuShareTimeline'
], configAppMessage)
.then(res => {})
.catch(err => {});
}
},
},
/**
* 用户点击右上角分享
*/
// #ifdef MP
onShareAppMessage() {
let that = this;
communityShareApi(that.community_id).catch(err=>{
console.error(err);
})
return {
title: that.infoData.title || that.infoData.content,
imageUrl: that.infoData.slider_image[0],
path: '/pages/discover/discoverDetails/index?id=' + that.community_id + '&spid=' + that.uid
};
},
onShareTimeline() {
let that = this;
communityShareApi(that.community_id).catch(err=>{
console.error(err);
})
return {
title: that.infoData.title || that.infoData.content,
imageUrl: that.infoData.slider_image[0],
path: '/pages/discover/discoverDetails/index?id=' + that.community_id + '&spid=' + that.uid
};
},
// #endif
}
</script>
<style>
page{
background-color: #ffffff;
}
</style>
<style lang="scss">
.b-e{
border: 1rpx solid #eee;
}
.bt-f5{
border-top: 1px solid #f5f5f5;
}
.swiper, .swiper-item{
width: 100%;
height: 100%;
}
.error{
background-color: #FDF3F2;
color: #E93323;
}
.theme-border{
border: 1px solid var(--view-theme);
}
.warning{
background-color: #FFF4EB;
color: #FC8327;
}
.theme-border{
border: 1rpx solid var(--view-theme);
}
.bubble_box{
position: absolute;
bottom: 74rpx;
left: -24rpx;
width: 184rpx;
z-index: 999;
.bubble{
width: 184rpx;
height: 198rpx;
background: #FFFFFF;
box-shadow: 0rpx 2rpx 15rpx 0rpx rgba(0,0,0,0.102);
border-radius: 16rpx;
padding: 36rpx 16rpx 26rpx 16rpx;
position: relative;
&:before{
content: '';
position: absolute;
left: 70rpx;
bottom: -20rpx;
width: 0;
height: 0;
border-style: solid;
border-width: 10px 10px 0 10px;
border-color: #fff transparent transparent transparent;
}
}
.x-line{
border-bottom: 1rpx solid rgba(238, 238, 238, 0.4);
}
}
.drawer-text{
padding-bottom: calc(32rpx + env(safe-area-inset-bottom));
}
.child-reply ~ .child-reply{
margin-top: 22rpx;
}
.more-line{
width: 40rpx;
height: 2rpx;
background: #D8D8D8;
}
.max-w-200{
max-width: 200rpx;
}
.comment-author{
color: #4A8AC9;
padding: 0 4rpx;
}
.icon-ic_love_2,.icon-icon_Like_2{
color: #e93323;
}
.load-box{
height: 750rpx;
animation: looming-gray 1s infinite linear;
background-color: #e3e3e3;
}
.bubble-mask{
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 5;
}
@keyframes looming-gray {
0% {
background-color: #e3e3e3aa;
}
50% {
background-color: #e3e3e3;
}
100% {
background-color: #e3e3e3aa;
}
}
// #ifdef APP-PLUS || H5
/deep/uni-swiper .uni-swiper-dots-horizontal .uni-swiper-dot{
width: 12rpx;
height: 12rpx;
border-radius: 50%;
}
// #endif
// #ifdef MP
swiper /deep/.wx-swiper-dot{
width: 12rpx;
height: 12rpx;
border-radius: 50%;
}
/* #endif */
</style>

View File

@@ -0,0 +1,228 @@
<template>
<view :style="colorStyle">
<view class="bg--w111-fff">
<view :style="{'padding-top': sysHeight + 'px'}">
<view class="flex-between-center h-80 px-20" >
<text class="iconfont icon-ic_leftarrow fs-40" @tap="backPage"></text>
<view class="h-80 flex-y-center fs-32 text--w111-999">
<view :class="{'tab-active': tabActive == 0}" @tap="changeTab(0)">好友</view>
<view class="ml-48" :class="{'tab-active': tabActive == 1}" @tap="changeTab(1)">关注</view>
<view class="ml-48" :class="{'tab-active': tabActive == 2}" @tap="changeTab(2)">粉丝</view>
</view>
<text class="w-40"></text>
</view>
</view>
<view class="h-180 p-30 flex-between-center" v-for="(item,index) in userList" :key="index">
<view class="flex-y-center" @tap="authTo('/pages/discover/discoverUser/index?id=' + item.relation_id)">
<image :src="item.author_image" mode="aspectFill" class="w-120 h-120 rd-50-p111-"></image>
<view class="pl-20">
<view class="fs-30">{{item.author}}</view>
<view class="flex-y-center mt-16 fs-24 text--w111-999">
<text>内容·{{item.community_num}}</text>
<text class="pl-30">粉丝·{{item.fans_num}}</text>
</view>
</view>
</view>
<view class="w-124 h-52 rd-30rpx flex-center bg-color text--w111-fff fs-24" v-show="item.is_follow == 0 && item.is_fans == 0"
@tap="followChange(item)">关注</view>
<view class="w-124 h-52 rd-30rpx flex-center bg--w111-fff text--w111-999 b-d fs-24" v-show="item.is_follow == 1 && item.is_fans == 0"
@tap="openModal(item,index)">已关注</view>
<view class="w-124 h-52 rd-30rpx flex-center bg-color text--w111-fff fs-24" v-show="item.is_follow == 0 && item.is_fans == 1"
@tap="followChange(item)">回关</view>
<view class="w-124 h-52 rd-30rpx flex-center bg--w111-fff text--w111-999 b-d fs-24" v-show="item.is_follow == 1 && item.is_fans == 1"
@tap="openModal(item,index)">互相关注</view>
</view>
<view v-show="!userList.length">
<emptyPage :title="emptyText()" src="/statics/images/video/no_friend.png"></emptyPage>
</view>
</view>
<!-- 确认框 -->
<tuiModal
:show="showModal"
title="确认取消关注"
:maskClosable="false"
@click="handleClick"></tuiModal>
<home></home>
</view>
</template>
<script>
let sysHeight = uni.getWindowInfo().statusBarHeight;
import { communityFlowListApi, communitySetInsterestApi, communityFriendListApi } from "@/api/community.js" ;
import colors from "@/mixins/color";
import emptyPage from '@/components/emptyPage.vue';
import tuiModal from "@/components/tui-modal/index.vue"
export default {
data() {
return {
sysHeight,
tabActive:0,
params:{
page:1,
limit:20,
},
type:'follow',
loading:false,
userList:[],
showModal:false,
uid:'',
index:0
};
},
mixins: [colors],
components:{ emptyPage, tuiModal },
computed:{
menuBoxStyle(){
let res = wx.getMenuButtonBoundingClientRect();
return {
width: res.left + 'px'
}
}
},
onLoad(options) {
if(options.type && options.type == 0){
this.tabActive = 1;
this.type = 'follow';
this.getList()
}else if(options.type && options.type == 1){
this.tabActive = 0;
this.getFriend();
}else if(options.type && options.type == 2){
this.tabActive = 2;
this.type = 'fans';
this.getList()
}else{
this.tabActive = 0;
this.getFriend();
}
},
methods:{
changeTab(val){
if(this.tabActive == val) return
this.tabActive = val;
this.loading = false;
this.userList = [];
this.params.page = 1;
if(val == 1){
this.type = 'follow';
this.getList()
}else if(val == 2){
this.type = 'fans';
this.getList()
}else if(val == 0){
this.getFriend();
}
},
authTo(url){
uni.navigateTo({
url
})
},
backPage(){
uni.navigateBack()
},
getList(){
if (this.loading) return;
this.loading = true;
communityFlowListApi(this.type,this.params).then(res=>{
let list = res.data;
let loading = list.length < this.params.limit;
this.userList = this.userList.concat(list);
this.params.page++;
this.loading = loading;
}).catch(err => {
return this.$util.Tips({
title: err
});
});
},
getFriend(){
if (this.loading) return;
this.loading = true;
communityFriendListApi(this.params).then(res=>{
let list = res.data;
let loading = list.length < this.params.limit;
this.userList = this.userList.concat(list);
this.params.page++;
this.loading = loading;
}).catch(err => {
return this.$util.Tips({
title: err
});
});
},
openModal(item, index){
this.uid = item.relation_id;
this.index = index;
this.showModal = true;
},
handleClick(e){
let index = e.index;
let that = this;
if(index == 1){
communitySetInsterestApi(this.uid,{status:0}).then(res=>{
this.userList[this.index].is_follow = 0;
this.showModal = false;
}).catch(err => {
this.showModal = false;
uni.showToast({
title:err,
icon:'none',
duration:2000
})
});
}else{
this.showModal = false;
}
},
followChange(item){
communitySetInsterestApi(item.relation_id,{status:1}).then(res=>{
item.is_follow = 1;
return this.$util.Tips({
title: res.msg
});
}).catch(err => {
return this.$util.Tips({
title: err
});
});
},
emptyText(){
let obj = {
0:'您还没有好友哦~',
1:'您还没有关注任何人哦~',
2:'您还没有粉丝哦~'
};
return obj[this.tabActive]
}
},
onReachBottom() {
this.getList()
},
onPageScroll() {
uni.$emit('scroll');
}
}
</script>
<style lang="scss">
.tab-active{
font-weight: 500;
color: #333;
position: relative;
&:after{
content: '';
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: -14rpx;
width: 64rpx;
height: 5rpx;
background: var(--view-theme);
border-radius: 4rpx;
}
}
.b-d{
border: 1px solid #ddd
}
</style>

View File

@@ -0,0 +1,182 @@
<template>
<view :style="colorStyle">
<view class="h-full h-90 bb-f5 px-120 flex-between-center fs-32 fw-500">
<view class="h-90 tab flex-y-center" :class="{'active-tab': current == 0,}" @tap="changeTab(0)">点赞</view>
<view class="h-90 tab flex-y-center" :class="{'active-tab': current == 1,'show-dot':isViewed.comment && current != 1}" @tap="changeTab(1)">评论</view>
<view class="h-90 tab flex-y-center" :class="{'active-tab': current == 2,'show-dot':isViewed.follow && current != 2}" @tap="changeTab(2)">关注</view>
</view>
<view v-show="current == 0">
<view class="h-180 p-30 flex-between-center" v-for="(item, index) in messageList" :key="index"
@tap="toPage(item)">
<view class="flex-y-center">
<image class="w-120 h-120 rd-50-p111-" :src="item.relation_author_image"></image>
<view class="ml-20 w-398">
<view class="fs-28 lh-40rpx">{{item.relation_author || '用户已注销'}}</view>
<view class="flex-y-center fs-26 lh-36rpx text--w111-666 pt-8">
赞了你的内容 <text class="text--w111-999 fs-22 pl-8">{{item.time_text}}</text>
</view>
</view>
</view>
<image :src="item.image" class="w-108 h-108 rd-8rpx" mode="aspectFill"></image>
</view>
</view>
<view v-show="current == 1">
<view class="h-180 p-30 flex-between-center" v-for="(item, index) in messageList" :key="index"
@tap="toPage(item)">
<view class="flex-y-center">
<image class="w-120 h-120 rd-50-p111-" :src="item.relation_author_image"></image>
<view class="ml-20 w-398">
<view class="fs-28 lh-40rpx">{{item.relation_author || '用户已注销'}}</view>
<view class="fs-26 lh-36rpx text--w111-666 mt-8 w-400 line1">
评论了你:{{item.content}}
</view>
<view class="text--w111-999 fs-22 mt-8">{{item.time_text}}</view>
</view>
</view>
<image :src="item.image" class="w-108 h-108 rd-8rpx" mode="aspectFill"></image>
</view>
</view>
<view v-show="current == 2">
<view class="h-180 p-30 flex-between-center" v-for="(item, index) in messageList" :key="index"
@tap="toAuthor(item)">
<view class="flex-y-center">
<image class="w-120 h-120 rd-50-p111-" :src="item.relation_author_image"></image>
<view class="ml-20 w-398">
<view class="fs-28 lh-40rpx">{{item.relation_author || '用户已注销'}}</view>
<view class="flex-y-center fs-26 lh-36rpx text--w111-666 pt-8">
关注了你 <text class="text--w111-999 fs-22 pl-8">{{item.time_text}}</text>
</view>
</view>
</view>
<!-- <view class="w-124 h-52 rd-30rpx flex-center bg-color text--w111-fff fs-24"
@tap="followChange(item)">回关</view> -->
<!-- <view class="w-124 h-52 rd-30rpx flex-center bg--w111-fff text--w111-999 b-d fs-24" v-show="item.is_follow == 1 && item.is_fans == 1"
@tap="openModal(item,index)">互相关注</view> -->
</view>
</view>
<view v-show="!messageList.length">
<emptyPage title="暂无内容~" src="/statics/images/video/no_friend.png"></emptyPage>
</view>
</view>
</template>
<script>
import colors from "@/mixins/color";
import { mapState, mapGetters } from 'vuex';
import { communityMessageApi } from "@/api/community.js";
import emptyPage from '@/components/emptyPage.vue';
export default {
data() {
return {
current: 0,
params:{
page:1,
limit:20,
type:1
},
loading: false,
messageList: [],
isViewed:{
comment: 0,
follow: 0,
like: 0
}
};
},
mixins: [colors],
components:{ emptyPage },
computed: {
...mapGetters(['isLogin','uid']),
},
onLoad(options) {
this.getList()
},
onReachBottom() {
this.getList()
},
methods:{
changeTab(val){
this.current = val;
this.loading = false;
this.params.page = 1;
this.params.type = val + 1;
this.messageList = [];
this.getList();
},
getList(){
if (this.loading) return;
this.loading = true;
communityMessageApi(this.params).then(res=>{
let list = res.data.list;
this.isViewed = res.data.isViewed;
let loading = list.length < this.params.limit;
this.messageList = this.messageList.concat(list);
this.params.page++;
this.loading = loading;
}).catch(err=>{
return this.$util.Tips({
title: err
});
})
},
toPage(item){
if(item.content_type == 1){
uni.navigateTo({
url: `/pages/discover/discoverDetails/index?id=${item.link_id}`
})
}else{
uni.navigateTo({
url: `/pages/discover/discoverVideo/index?id=${item.link_id}`
})
}
},
toAuthor(item){
uni.navigateTo({
url: `/pages/discover/discoverUser/index?id=${item.relation_id}`
})
}
}
}
</script>
<style>
page{
background-color: #ffffff;
}
</style>
<style lang="scss">
.bb-f5{
border-bottom: 1px solid #f5f5f5;
}
.px-120{
padding: 0 120rpx;
}
.tab{
border-bottom: 4rpx solid transparent;
}
.active-tab{
position: relative;
&:after{
content: '';
position: absolute;
bottom: -4rpx;
left: 0;
width: 64rpx;
height: 4rpx;
background: #E93323;
}
}
.show-dot{
position: relative;
&:after{
content: '';
position: absolute;
top: 18rpx;
right: -6rpx;
width: 12rpx;
height: 12rpx;
background: #E93323;
border-radius: 8rpx;
}
}
</style>

View File

@@ -0,0 +1,163 @@
<template>
<view :style="colorStyle">
<view class="gradient-box">
<view class="flex-between-center">
<view class="search-box flex-y-center pl-24 pr-20">
<text class="iconfont icon-ic_search fs-32 text--w111-999"></text>
<input type="text" v-model="params.keyword" placeholder="请输入关键词" class="fs-26 ml-16 flex-1" />
<text class="iconfont icon-ic_close2 fs-28 text--w111-999 pl-20" v-if="params.keyword" @tap="clearWord"></text>
</view>
<text class="fs-26 pl-24" @tap="getSearch">搜索</text>
</view>
<view class="flex-y-center">
<scroll-view scroll-x="true" scroll-with-animation :scroll-into-view="intoindex" class="white-nowrap vertical-middle w-676 pl-30" show-scrollbar="false">
<view class="inline-block mr-52">
<view class="flex-y-center h-100 fs-28" :class="{ 'cate-active': cateActive == '' }" @tap="changeCate(-1, '')">全部</view>
</view>
<view class="inline-block mr-52" v-for="(item, index) in topicList" :key="index" :id="'sort' + index">
<view class="flex-y-center h-100 fs-28" :class="{ 'cate-active': cateActive == item.id }" @tap="changeCate(index, item.id)">{{ item.name }}</view>
</view>
</scroll-view>
</view>
</view>
<view class="px-20" v-if="contentList.length">
<waterfallsFlow :wfList="contentList" @onFlowLike="flowLike"></waterfallsFlow>
</view>
<view class="px-20" v-if="contentList.length == 0 && !loading">
<emptyPage
:title="params.keyword ? '无搜索结果,换个词试试吧' : '暂无内容,去看点别的吧~'"
:src="params.keyword ? '/statics/images/noSearch.gif' : '/statics/images/empty-box.gif'"
></emptyPage>
</view>
<home></home>
</view>
</template>
<script>
import colors from "@/mixins/color";
import { communityListApi, getTopicApi } from "@/api/community.js";
import waterfallsFlow from "@/components/discoverWaterfall/WaterfallsFlow.vue";
import emptyPage from '@/components/emptyPage.vue';
export default {
data() {
return {
keyword:'',
cateActive:'',
topicList:[],
contentList:[],
noMore:false,
loading: false,
intoindex:'',
params:{
page:1,
limit:20,
topic_id:'', //话题
keyword:'',
is_interest:0, //是否关注
},
};
},
components:{
waterfallsFlow,
emptyPage
},
mixins: [colors],
provide() {
return {
flowLike: this.flowLike
}
},
onPageScroll(object) {
uni.$emit('scroll');
},
onLoad() {
this.getTopic();
this.getList();
},
methods:{
clearWord(){
this.params.keyword = ''
},
changeCate(index,id){
this.cateActive = id;
this.$nextTick(()=>{
this.intoindex = 'sort' + index;
})
this.params.page = 1;
this.params.topic_id = id;
this.contentList = [];
this.noMore = false;
this.getList();
},
getSearch(){
this.params.page = 1;
this.contentList = [];
this.noMore = false;
this.getList();
},
getTopic(){
getTopicApi().then(res=>{
this.topicList = res.data;
})
},
getList(){
if (this.noMore) return;
this.noMore = true;
this.loading = true
communityListApi(this.params).then(res=>{
let list = res.data;
let noMore = list.length < this.params.limit;
this.contentList = this.contentList.concat(list);
this.params.page++;
this.noMore = noMore;
}).finally(()=>{
this.loading = false
})
},
flowLike(data){
let index = this.contentList.findIndex(item=> data.id == item.id);
this.contentList[index].is_like = data.status;
if(data.status == 1){
this.contentList[index].like_num++;
}else{
this.contentList[index].like_num--;
}
},
},
onReachBottom() {
this.getList()
}
}
</script>
<style lang="scss">
.gradient-box {
width: 750rpx;
height: 182rpx;
background: linear-gradient(180deg, #ffffff 0%, #f5f5f5 100%);
padding: 20rpx 30rpx 0;
.search-box {
width: 614rpx;
height: 64rpx;
background: #f3f3f3;
border-radius: 32rpx;
}
}
.cate-active {
font-weight: 500;
font-size: 34rpx;
color: var(--view-theme);
position: relative;
&:after {
content: '';
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: 14rpx;
width: 64rpx;
height: 5rpx;
background: var(--view-theme);
border-radius: 4rpx;
}
}
</style>

View File

@@ -0,0 +1,170 @@
<template>
<view :style="colorStyle">
<view class="w-full abs-lt gradient-box"></view>
<view class="topic-box relative z-10">
<view class="flex-between-center">
<view>
<view class="fs-34 fw-500">
<text class="iconfont icon-ic_talk_2 fs-36"></text>
<text class="pl-8">{{topicName}}</text>
</view>
<view class='fs-24 lh-36rpx pt-20 text--w111-666'>{{count}}篇内容</view>
</view>
<view class="w-162 h-60 rd-30rpx flex-center fs-24 text--w111-3d b-e" @tap="createTo()">
<text class="iconfont icon-ic_edit fs-24"></text>
<text class="pl-8">去发布</text>
</view>
</view>
<view class="pb-26rpx bb-e"></view>
</view>
<view class="nav-box w-full h-100 pl-30 fs-30 text--w111-999 flex-y-center" :style="[navStyle]">
<text :class="{'tab-active': tabActive == 0}" @tap="changeTab(0)">最热</text>
<text class="ml-52" :class="{'tab-active': tabActive == 1}" @tap="changeTab(1)">最新</text>
</view>
<view class="px-20">
<waterfallsFlow :wfList="contentList" @onFlowLike="flowLike"></waterfallsFlow>
</view>
<home></home>
</view>
</template>
<script>
import colors from "@/mixins/color";
import { communityListApi, getTopicApi, communityTopicCountApi } from "@/api/community.js";
import emptyPage from '@/components/emptyPage.vue';
import waterfallsFlow from "@/components/discoverWaterfall/WaterfallsFlow.vue";
export default {
data() {
return {
tabActive:0,
scrollStatus:false,
contentList:[],
loading:false,
params:{
page:1,
limit:20,
topic_id:'', //话题
keyword:'',
is_interest:0, //是否关注
order:2
},
topicName:'',
count:1
};
},
components:{ emptyPage, waterfallsFlow },
mixins: [colors],
computed:{
navStyle(){
return {
backgroundColor: this.scrollStatus ? '#fff' : 'transparent'
}
}
},
provide() {
return {
flowLike: this.flowLike
}
},
onPageScroll(object) {
if (object.scrollTop > 50) {
this.scrollStatus = true;
} else if (object.scrollTop < 50) {
this.scrollStatus = false;
}
uni.$emit('scroll');
},
onLoad(options) {
this.params.topic_id = options.id || '';
this.topicName = options.name || '';
this.getList();
this.getCount();
},
methods:{
createTo(){
uni.navigateTo({
url: '/pages/discover/discoverCreate/index?topic_name=' + this.topicName
})
},
changeTab(val){
this.tabActive = val;
if(val == 0){
this.params.order = 2;
}else{
this.params.order = 1;
}
this.loading = false;
this.params.page = 1;
this.contentList = [];
this.getList();
},
getList(){
if (this.loading) return;
this.loading = true;
communityListApi(this.params).then(res=>{
let list = res.data;
let loading = list.length < this.params.limit;
this.contentList = this.contentList.concat(list);
this.params.page++;
this.loading = loading;
})
},
getCount(){
communityTopicCountApi(this.params.topic_id).then(res=>{
this.count = res.data.count;
})
},
flowLike(data){
let index = this.contentList.findIndex(item=> data.id == item.id);
this.contentList[index].is_like = data.status;
if(data.status == 1){
this.contentList[index].like_num++;
}else{
this.contentList[index].like_num--;
}
},
},
onReachBottom() {
this.getList()
}
}
</script>
<style lang="scss">
.gradient-box{
height: 260rpx;
background: linear-gradient( 180deg, #FFFFFF 0%, #F5F5F5 100%);
z-index: 2;
}
.topic-box{
padding: 42rpx 32rpx 0;
}
.nav-box{
position: sticky;
left: 0;
top: 0;
z-index: 10;
}
.b-e{
border: 1rpx solid #eee;
}
.bb-e{
border-bottom: 1rpx solid #eee;
}
.tab-active{
font-weight: 500;
color: #333;
position: relative;
&:after{
content: '';
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: -14rpx;
width: 40rpx;
height: 5rpx;
background: var(--view-theme);
border-radius: 4rpx;
}
}
</style>

View File

@@ -0,0 +1,492 @@
<template>
<view :style="colorStyle">
<NavBar titleText="个人主页"
textSize="34rpx"
:isScrolling="pageScrollStatus"
:iconColor="pageScrollStatus ? '#333333' : '#ffffff'"
:textColor="pageScrollStatus ? '#333333' : '#ffffff'"
showBack
:showEmpty="false"></NavBar>
<!-- :style="{'height': 552 + (sysHeight * 2) + 'rpx'}" -->
<view class="info-card w-full relative" >
<view class="blur-bg w-full h-full abs-lt" :style="[headerStyle]"></view>
<view class="w-full h-full content" :style="[cardStyle]">
<view class="info">
<view class="flex-between-center">
<view class="flex-y-center">
<view class="w-140 h-140 rd-50-p111- relative" :class="userInfo.vip_status ? 'svip-border' : 'white-border'">
<image class="w-full h-full rd-50-p111- block" :src="userInfo.author_image" mode="aspectFill"></image>
<image class="vip-badge" src="@/static/img/svip_badge.png" v-show="userInfo.vip_status"></image>
</view>
<view class="pl-28 text--w111-fff">
<view class="w-260 flex-y-center flex-wrap">
<text class="fs-32 fw-500">{{userInfo.author}}</text>
<view class="vip flex-center" v-show="userInfo.level_name">
<text class="iconfont icon-huiyuandengji"></text>
V{{userInfo.level_name}}
</view>
</view>
<view class="fs-24 pt-22">ID:{{userInfo.relation_id}}</view>
</view>
</view>
<view class="flex-y-center">
<view class="w-154 h-58 rd-30rpx flex-center fs-24 text--w111-fff bg-white-01"
v-if="userInfo.is_self" @tap="authTo('/pages/discover/discoverCreate/index')">
<text class="iconfont icon-ic_edit fs-26"></text>
<text class="pl-8">去发布</text>
</view>
<view v-else class="w-124 h-58 rd-30rpx flex-center fs-24 text--w111-fff bg-white-01"
@tap="followChange">
<text v-show="!userInfo.is_follow" class="iconfont icon-ic_increase fs-24"></text>
<text>{{userInfo.is_follow ? '已关注' : '关注'}}</text>
</view>
<view class="w-58 h-58 rd-50-p111- ml-12 text--w111-fff bg-white-01 flex-center"
:class="{'msg-icon': is_view == 0}" v-if="userInfo.is_self" @tap="authTo('/pages/discover/discoverMessage/index')">
<text class="iconfont icon-ic_message2 w-32"></text>
</view>
</view>
</view>
<view class="fs-26 text--w111-fff lh-40rpx space-line user-desc mt-20">
<text v-show="userInfo.desc">{{userInfo.desc}} </text>
<text v-show="!userInfo.desc">此人很神秘,什么也没有留下~</text>
<text class="iconfont icon-ic_edit fs-26" v-if="userInfo.is_self" @tap="toggleModal"></text>
</view>
<view class="mt-48 px-28 flex-between-center text--w111-fff">
<view class="text-center" v-for="(item,index) in infoList" :key="index"
@tap="userTo('/pages/discover/discoverFollow/index?type=' + index)">
<view class="fs-30">{{item.count}}</view>
<view class="pt-10 fs-24">{{item.name}}</view>
</view>
</view>
<view class="h-56"></view>
</view>
</view>
</view>
<view class="list-box">
<view class="list-tab flex-between-center relative" :class="showSearch ? 'pt-28' : 'pt-42'" v-if="userInfo.is_self">
<text v-show="!showSearch"></text>
<view class="flex-y-center fs-34 text--w111-999 center-tabs" v-show="!showSearch">
<view :class="{'active-tab': active == 0}" @tap="changeTab(0)">作品</view>
<view class="ml-66" :class="{'active-tab': active == 1}" @tap="changeTab(1)">赞过</view>
</view>
<view class="w-608 h-58 rd-30rpx bg--w111-f1f1f1 flex-y-center ml-12 pl-20" v-show="showSearch">
<text class="iconfont icon-ic_search fs-30 text--w111-999"></text>
<input type="text" v-model="params.keyword" placeholder="搜索笔记/用户/商品" @confirm="searchSubmit"
class="flex-1 pl-14 fs-24" />
</view>
<text v-show="!showSearch && !params.keyword" class="iconfont icon-ic_search fs-40 pr-10" @tap="openSearch"></text>
<text v-show="showSearch && params.keyword" class="fs-26 text--w111-999 pr-10" @tap="searchSubmit">搜索</text>
<text v-show="showSearch && !params.keyword" class="fs-26 text--w111-999 pr-10" @tap="reset">取消</text>
</view>
<view class="list-tab" v-else></view>
<view class="pt-20 pl-20 pr-20 bg--w111-f5f5f5" v-show="contentList.length">
<waterfallsFlow :wfList="contentList" isSelf @onFlowLike="flowLike"></waterfallsFlow>
</view>
<view class="px-20 bg--w111-f5f5f5" v-show="!contentList.length">
<emptyPage title="暂无内容~"></emptyPage>
</view>
</view>
<!-- 确认框 -->
<tui-modal :show="showModal" maskClosable custom @cancel="toggleModal">
<view class="tui-modal-custom">
<view class="fs-32 fw-500 lh-44rpx text-center">编辑简介</view>
<view class="mt-24 bg--w111-f5f5f5 rd-16rpx p-30rpx h-342" @tap="openFocus">
<textarea class="w-full fs-26"
ref="myTextarea"
v-model="userInfo.desc"
auto-height
:focus="focus"
wrap-style="wrap"
:always-embed="true"
:adjust-position="true"
cursor-spacing="85rpx"
:maxlength="50"
name="desc" />
</view>
<view class="flex-between-center mt-40">
<view class="w-244 h-72 rd-36rpx flex-center fs-26 font-num close-btn" @tap="toggleModal">取消</view>
<view class="w-244 h-72 rd-36rpx flex-center bg-color text--w111-fff fs-26" @tap="saveDesc">保存</view>
</view>
</view>
</tui-modal>
<!-- 确认框 -->
<tuiModal
:show="showFollow"
title="确认取消关注"
:maskClosable="false"
@click="handleClick"></tuiModal>
<home></home>
</view>
</template>
<script>
let sysHeight = uni.getWindowInfo().statusBarHeight;
import colors from "@/mixins/color";
import emptyPage from '@/components/emptyPage.vue';
import NavBar from "@/components/NavBar.vue";
import waterfallsFlow from "@/components/discoverWaterfall/WaterfallsFlow.vue";
import tuiModal from "@/components/tui-modal/index.vue";
import {
communityListApi,
communityUserInfoApi,
communityUpdateDescApi,
communitySetInsterestApi,
communityLikeListApi
} from "@/api/community.js"
import {serviceRecord} from '@/api/user.js';
export default {
data() {
return {
sysHeight,
pageScrollStatus:false,
id:0,
params:{
page:1,
limit:20,
topic_id:'', //话题
keyword:'',
is_interest:0, //是否关注
relation_id:'',
},
infoList:[
{name:'关注',count:'0'},
{name:'好友',count:'0'},
{name:'粉丝',count:'0'},
{name:'获赞',count:'0'},
],
active:0,
contentList:[],
userInfo:{},
showSearch:false,
showModal:false,
showFollow:false,
focus:false,
is_view: 1
};
},
mixins: [colors],
components:{ emptyPage, NavBar, waterfallsFlow, tuiModal },
computed:{
headerStyle(){
return {
// 'height': 552 + (this.sysHeight * 2) + 'rpx',
'background-image':`url(${this.userInfo.author_image})`
}
},
cardStyle(){
return {
'padding-top':40 + this.sysHeight + 'px',
}
}
},
provide() {
return {
flowLike: this.flowLike
}
},
onPageScroll(object) {
if (object.scrollTop > 130) {
this.pageScrollStatus = true;
} else if (object.scrollTop < 130) {
this.pageScrollStatus = false;
}
uni.$emit('scroll');
},
onReachBottom() {
this.getList();
},
onLoad(options) {
this.id = options.id;
this.getList();
},
onShow() {
this.getUserInfo();
},
methods:{
openFocus(){
this.focus = true;
},
changeTab(val){
if(this.active == val) return
this.active = val;
this.loading = false;
this.contentList = [];
this.params.page = 1;
val == 1 ? this.getLike() : this.getList()
},
getList(){
if (this.loading) return;
this.loading = true;
this.$set(this.params,'relation_id',this.id);
communityListApi(this.params).then(res=>{
let list = res.data;
let loading = list.length < this.params.limit;
this.contentList = this.contentList.concat(list);
this.params.page++;
this.loading = loading;
}).catch(err => {
return this.$util.Tips({
title: err
});
});
},
getLike(){
if (this.loading) return;
this.loading = true;
communityLikeListApi().then(res=>{
let list = res.data.list;
let loading = list.length < this.params.limit;
this.contentList = this.contentList.concat(list);
this.params.page++;
this.loading = loading;
}).catch(err => {
return this.$util.Tips({
title: err
});
});
},
getUserInfo(){
communityUserInfoApi(this.id).then(res=>{
this.userInfo = res.data;
this.infoList[0].count = res.data.follow_num;
this.infoList[1].count = res.data.friend_count;
this.infoList[2].count = res.data.fans_num;
this.infoList[3].count = res.data.like_num;
serviceRecord({page: 1,limit: 1}).then(res => {
this.is_view = res.data.community.is_viewed;
})
}).catch(err => {
return this.$util.Tips({
title: err
},{
tab: 3
});
});
},
userTo(url){
if(this.userInfo.is_self){
if(url == '/pages/discover/discoverFollow/index?type=3') return
this.authTo(url);
}
},
authTo(url){
uni.navigateTo({
url
})
},
openSearch(){
this.showSearch = !this.showSearch;
if(!this.showSearch && this.params.keyword){
this.params.keyword = '';
this.params.page = 1;
this.contentList = [];
this.loading = false;
this.getList();
}
},
searchSubmit(){
this.params.page = 1;
this.contentList = [];
this.loading = false;
this.getList();
},
reset(){
this.params.keyword = '';
this.showSearch = false;
// this.searchSubmit();
},
toggleModal(){
this.showModal = !this.showModal;
},
saveDesc(){
if(this.userInfo.desc == '') return this.$util.Tips({
title: '请输入介绍'
});
communityUpdateDescApi({desc:this.userInfo.desc}).then(res=>{
this.showModal = false;
this.getUserInfo();
uni.showToast({
title:res.msg,
icon:'none'
})
}).catch(err=>{
return this.$util.Tips({
title: err
});
})
},
followChange(){
if(this.userInfo.is_follow == 0){
communitySetInsterestApi(this.id,{status:1}).then(res=>{
this.userInfo.is_follow = 1;
return this.$util.Tips({
title: res.msg
});
}).catch(err => {
return this.$util.Tips({
title: err
});
});
}else{
this.showFollow = true;
}
},
handleClick(e){
let index = e.index;
let that = this;
if(index == 1){
communitySetInsterestApi(this.id,{status:0}).then(res=>{
this.userInfo.is_follow = 0;
this.showFollow = false;
return this.$util.Tips({
title: res.msg
});
}).catch(err => {
this.showFollow = false;
return this.$util.Tips({
title: err
});
});
}else{
this.showFollow = false;
}
},
flowLike(data){
let index = this.contentList.findIndex(item=> data.id == item.id);
this.contentList[index].is_like = data.status;
if(data.status == 1){
this.contentList[index].like_num++;
}else{
this.contentList[index].like_num--;
}
},
}
}
</script>
<style lang="scss">
.info-card{
background-size: cover;
}
.blur-bg{
filter: blur(50rpx);
background-size: cover;
}
.content{
position: relative; /* 设置为相对定位 */
z-index: 2; /* 设置更高的层级以覆盖背景 */
filter: blur(0);
background: linear-gradient(180deg, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.1) 39%, rgba(0, 0, 0, 0.7) 100%);
}
.info{
padding: 38rpx 34rpx 0 30rpx;
}
.bg-white-01{
background-color:rgba(255, 255, 255, 0.1);
}
.bg--w111-f1f1f1{
background-color: #f1f1f1;
}
.border-white{
border: 1rpx solid #fff;
}
.list-box{
position: relative;
left: 0;
top: -24rpx;
border-radius: 24rpx 24rpx 0 0;
z-index: 90;
}
.list-tab{
background: linear-gradient( 180deg, #FFFFFF 0%, #F5F5F5 100%);
padding-left: 20rpx;
padding-right: 20rpx;
padding-bottom: 24rpx;
border-radius: 24rpx 24rpx 0 0;
}
.center-tabs{
position: absolute;
top: 38rpx;
left: 50%;
transform: translateX(-50%);
}
.active-tab{
font-weight: 500;
color: #333;
position: relative;
&:after{
content: '';
position: absolute;
left: 0;
bottom: -14rpx;
width: 64rpx;
height: 5rpx;
background: var(--view-theme);
border-radius: 4rpx;
}
}
.vip{
width: 64rpx;
height: 26rpx;
background: #FEF0D9;
border: 1px solid #FACC7D;
border-radius: 50rpx;
font-size: 18rpx;
font-weight: 500;
color: #DFA541;
margin-left: 10rpx;
.iconfont {
font-size: 16rpx;
margin-right: 4rpx;
}
}
.vip-badge{
position: absolute;
top: -20rpx;
right: 0;
width: 48rpx;
height: 46rpx;
}
.svip-border{
border: 2rpx solid #F1BB0D;
}
.tui-modal-custom{
height: 530rpx;
.h-342{
height: 342rpx;
}
}
.white-border{
border: 2rpx solid #FFFFFF;
}
.modal-btn{
width: 244rpx;
height: 72rpx;
border-radius: 36rpx;
}
.close-btn{
border: 1rpx solid var(--view-theme);
}
.confirm-btn{
background-color: var(--view-theme);
}
.msg-icon{
position: relative;
&:after{
content: '';
position: absolute;
right: 8rpx;
top: 10rpx;
width: 12rpx;
height: 12rpx;
border-radius: 6rpx;
background-color: #e93323;
}
}
.user-desc{
max-height: 200rpx;
overflow-y: scroll;
}
</style>

View File

@@ -0,0 +1,34 @@
<template>
<web-view class="web-view"
:webview-styles="webviewStyles"
:src="url" :style="[boxStyle]"></web-view>
</template>
<script>
export default {
data() {
return {
windowH: 0,
windowW: 0,
webviewStyles: {
progress: {
color: 'transparent'
}
},
url: ''
}
},
computed:{
boxStyle(){
const res = uni.getWindowInfo();
return {
'width':res.windowWidth + 'px',
'height':res.windowHeight + 'px'
}
}
},
onLoad(option) {
this.url = decodeURIComponent(option.url);
}
}
</script>

View File

@@ -0,0 +1,166 @@
<template>
<view :style="colorStyle">
<view class="full-page">
<swiperVideo
:swiperData="contentList"
:showFooter="false"
:replyStatus="configData.community_comment_status"
:addReply="configData.community_comment_add"
fullVideo
@onLike="likeFun"
@followChange="followUser"
@onSwiper="beforeRequest"
@onShare="resShare"></swiperVideo>
</view>
</view>
</template>
<script>
import colors from "@/mixins/color";
import swiperVideo from '@/components/discoverVideo/index.vue';
import { communityListApi, getCommunityConfig } from "@/api/community.js";
import { getUserInfo } from "@/api/user.js"
import {LOGIN_STATUS} from '@/config/cache';
import { mapGetters } from 'vuex';
export default {
name:'discoverVideo',
data() {
return {
contentList:[],
loading:false,
params:{
page:1,
limit:10,
topic_id:'', //话题
keyword:'',
is_interest:0, //是否关注
content_type:2,
start_id:'',
relation_id: ''
},
infoData:{},
configData:{
community_status:1,
community_comment_add:1,
community_comment_status:1
},
current: 0,
};
},
mixins: [colors],
components:{ swiperVideo },
provide() {
return {
flowLike: this.flowLike
}
},
onPageScroll(object) {
uni.$emit('scroll');
},
computed:{
...mapGetters(['isLogin','uid']),
},
onLoad(options) {
this.params.start_id = options.id;
if(options.relation_id){
this.$set(this.params,'relation_id',options.relation_id);
}
// #ifdef H5
if(options.content_type == 0){
this.$set(this.params,'content_type','');
}
if(options.token && !this.isLogin){
this.$store.commit("LOGIN", {
'token': options.token
});
getUserInfo().then(res => {
this.$store.commit("SETUID", res.data.uid);
this.$store.commit("UPDATE_USERINFO", res.data);
location.reload()
}).catch(error => {
return this.$util.Tips({
title:err
})
})
}
// #endif
this.getConfig();
this.getList();
},
methods:{
getConfig(){
getCommunityConfig().then(res=>{
this.configData = res.data;
})
},
getList(){
if (this.loading) return;
this.loading = true;
communityListApi(this.params).then(res=>{
let list = res.data;
let loading = list.length < this.params.limit;
this.contentList = this.contentList.concat(list);
this.params.page++;
this.loading = loading;
})
},
followUser(data){
this.contentList[data.index].is_follow = 1;
return this.$util.Tips({
title: '关注成功'
});
},
beforeRequest(current){
this.current = current;
if(this.contentList.length - 1 == current){
this.getList();
}
},
likeFun(data){
this.contentList[data.index].is_like = data.status;
if(data.status == 1){
this.contentList[data.index].like_num++;
}else{
this.contentList[data.index].like_num--;
}
},
resShare(data){
this.infoData = data;
},
},
onReachBottom() {
this.getList()
},
/**
* 用户点击右上角分享
*/
// #ifdef MP
onShareAppMessage() {
let that = this;
return {
title: that.contentList[that.current].title || that.contentList[that.current].content,
imageUrl: that.contentList[that.current].image,
path: `/pages/discover/${that.contentList[that.current].content_type == 1 ? 'discoverDetails' : 'discoverVideo'}/index?id=${that.contentList[that.current].id}&spid=${that.uid}&relation_id=${that.params.relation_id}`
};
},
onShareTimeline() {
let that = this;
return {
title: that.contentList[that.current].title || that.contentList[that.current].content,
imageUrl: that.contentList[that.current].image,
path: `/pages/discover/${that.contentList[that.current].content_type == 1 ? 'discoverDetails' : 'discoverVideo'}/index?id=${that.contentList[that.current].id}&spid=${that.uid}&relation_id=${that.params.relation_id}`
};
},
// #endif
}
</script>
<style lang="scss">
.full-page{
height:100vh;
background-color: #000000;
}
</style>