Files
dvcp_v2_wxcp_app/src/apps/AppVillageDiscuss/Detail.vue
yanran200730 80fda72314 bug
2022-01-07 18:20:48 +08:00

653 lines
16 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="Detail" v-if="pageShow" :class="[isAnnouncer && data.status === '0' && data.type === '0' ? 'detail-active' : '']">
<div class="detail-top">
<div flex class="w-100">
<div class="avatar" v-text="data.avatar" />
<div flex class="column start fill">
<b class="color-333" v-text="data.createUserName" />
<span class="color-999" v-text="data.createTime" />
</div>
<div class="statusTag" :class="{ over: data.status > 0 }" v-text="data.status == 0 ? (data.type == 0 ? '征集中' : '投票中') : $dict.getLabel('discussStatus', data.status)" />
</div>
<div class="header-middle">
<div class="contsnts">
<u-parse :html="data.content || data.title"></u-parse>
</div>
</div>
<div class="img-list" v-if="data.images && data.images.length">
<img :src="item.url" alt="" v-for="(item, index) in data.images" :key="index" @click="previewImage(data.images, item.url)" />
</div>
</div>
<div v-if="data.type == 0" class="comments">
<span class="totalCount">
<span class="total" v-text="`全部评论(${commentCount})`" />
<span class="rightCount">
<u-icon name="clock" v-if="data.status === '0'"></u-icon>
<u-count-down v-if="data.status === '0'" :timestamp="timestamp" separator="zh" show-days show-hours show-minutes show-seconds></u-count-down>
<span style="color: #999" v-else>已截止</span>
</span>
</span>
<div v-for="op in data.messages" :key="op.id">
<div flex class="header">
<u-avatar :src="op.avatar" size="48" />
<div flex class="fill">
<b v-text="op.createUserName" />
<span class="tags">{{ data.createUserId === op.createUserId ? '话事人' : '居民' }}</span>
</div>
<u-icon name="thumb-up" :label="op.suport" :color="op.isSuport ? 'red' : '#ccc'" @click="like(op.id)" />
</div>
<div class="content" v-text="op.content" @click="adddeleShow(op.id)" />
<div class="content color-999" v-text="op.createTime" />
</div>
<AiEmpty v-if="!data.messages.length"></AiEmpty>
</div>
<div v-else-if="data.type == 1" class="comments">
<span class="totalCount">
<span class="total">{{ data.voteType === '1' ? '投票清单(可多选)' : '投票清单' }}</span>
<span class="rightCount">
<u-icon name="clock" v-if="data.status === '0'"></u-icon>
<u-count-down v-if="data.status === '0'" :timestamp="timestamp" separator="zh" show-days show-hours show-minutes show-seconds></u-count-down>
<span style="color: #999" v-else>已截止</span>
</span>
</span>
<div class="comments-vote">
<div class="vote-item" v-for="(item, index) in data.voteList" :key="index">
<div class="left">
<span>{{ item.item }}</span>
<span>{{ item.content }}</span>
</div>
<i>{{ item.count }}</i>
<em :style="{ width: item.percentage }"></em>
</div>
</div>
</div>
<div class="votePeople">
<div class="leftPeople">共23人参与投票</div>
<div class="right">
<span>查看详情</span>
<u-icon name="arrow-right" color="#999" @click="toUserList"></u-icon>
</div>
</div>
<div class="bottomInput" v-if="isAnnouncer && data.status === '0' && data.type === '0'">
<div class="leftInput" @click="showBottomInput = true">我来说两句...</div>
</div>
<u-popup v-model="showBottomInput" height="auto" mode="bottom">
<div class="comments-wrapper">
<u-input v-model="content" placeholder="写下你的想法" type="textarea" auto-height height="180" maxlength="140"> </u-input>
<div class="words">字数{{ content.length }}/140</div>
<div class="bottombtn">
<div class="emptys" @click="content = ''">清空内容</div>
<div class="publishs" @click="publish">发表</div>
</div>
</div>
</u-popup>
<u-popup v-model="deleShow" mode="bottom" class="popupdele">
<div class="dele" @click="modalShow = true">删除</div>
<div @click="deleShow = false">取消</div>
</u-popup>
<u-modal v-model="modalShow" content="确定删除该留言" @confirm="confirmDelete"></u-modal>
<div class="end-btn" hover-class="text-hover" v-if="data.status === '1'" @click="handleComplete">结束公示</div>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
name: 'Detail',
props: {},
data() {
return {
data: {},
id: '',
timestamp: '',
showBottomInput: false,
content: '',
flag: false,
pageShow: false,
isAnnouncer: false,
deleShow: false,
modalShow: false,
deleId: '',
isAnnouncer: false,
}
},
computed: {
...mapState(['user']),
commentCount() {
return this.data.messages?.length || 0
},
},
onLoad(o) {
this.id = o.id
this.getDetail()
this.$dict.load('discussStatus')
},
onShow() {
document.title = '议事详情'
},
methods: {
getDetail() {
this.$loading()
this.$http
.post(`/app/appvillagediscuss/queryDetailById?id=${this.id}`)
.then((res) => {
if (res?.data) {
this.data = {
...res.data,
avatar: res.data.createUserName?.substr(0, 2) || '游客',
messages: res.data.messages
? res.data.messages.map((v) => {
return {
...v,
isSuport: v.suportUser ? v.suportUser.indexOf(this.user.id) > -1 : false,
}
})
: [],
}
this.data.images = res.data.images ? JSON.parse(res.data.images) : []
this.isAnnouncer = this.user.id === res.data.createUserId
var discussTime = (new Date(res.data.discussDeadline).getTime() * 1) / 1000
var nowTime = (new Date().getTime() * 1) / 1000
if (discussTime >= nowTime) {
this.timestamp = discussTime - nowTime
}
if (res.data.type === '1' && res.data.statistic) {
const total = Object.values(res.data.statistic).reduce((x, y) => {
return x + y
})
this.data.voteList = res.data.voteItems.map((v) => {
return {
...v,
count: res.data.statistic[v.item],
percentage: (res.data.statistic[v.item] / total) * 100 + '%',
}
})
}
this.pageShow = true
this.$hideLoading()
} else {
this.$hideLoading()
this.pageShow = true
}
})
.catch(() => {
this.$hideLoading()
})
},
like(id) {
this.$loading()
this.$http.post(`/app/appvillagediscussmessage/suport?id=${id}&userId=${this.user.id}`).then((res) => {
this.$hideLoading()
if (res.code === 0) {
this.$u.toast('点赞成功')
this.$nextTick(() => {
this.getDetail()
})
} else {
this.$u.toast(res.msg)
}
})
},
adddeleShow(id) {
if (this.user.id == this.data.createUserId) {
this.deleId = id
this.deleShow = true
}
},
confirmDelete() {
this.$http
.post(`/app/appvillagediscussmessage/delete?ids=${this.deleId}`)
.then((res) => {
if (res?.data) {
this.deleShow = false
this.modalShow = false
this.deleId = ''
this.getDetail()
}
})
.catch((e) => {
this.$hideLoading()
this.$u.toast(e)
})
},
publish() {
if (this.flag) return
if (!this.content) {
return this.$u.toast('请输入你的想法')
}
this.$http
.post(`/app/appvillagediscussmessage/addOrUpdate`, {
content: this.content,
avatar: this.user.avatar,
createUserId: this.user.id,
createUserName: this.user.name,
discussId: this.id,
})
.then((res) => {
if (res?.code == 0) {
this.$u.toast('留言成功')
this.flag = false
this.content = ''
this.showBottomInput = false
this.getDetail()
}
})
},
praise() {
console.log('点赞')
this.$http.post(`/app/appvillagediscussmessage/suport?id=${this.id}&userId=${this.user.id}`).then((res) => {
if (res?.code == 0) {
this.$u.toast('点赞成功!')
this.getDetail()
}
})
},
previewImage(images, img) {
uni.previewImage({
urls: images.map((v) => v.url),
current: img,
})
},
handleSubmitComment(content) {
if (!!content) {
let { id } = this
this.$http
.post('/app/appvillagediscussmessage/addOrUpdate', {
id,
content,
})
.then((res) => {
if (res?.code == 0) {
this.$u.toast('提交成功!')
this.getDetail()
}
})
} else {
this.$u.toast('不能提交空评论!')
}
},
handleComplete() {
this.$confirm('是否要结束公示')
.then(() => {
this.$http
.post('/app/appvillagediscuss/finishPublic', {
status: '2',
id: this.id,
})
.then((res) => {
if (res?.code == 0) {
this.$u.toast('结束公示成功!')
this.getDetail()
}
})
})
.catch(() => 0)
},
toUserList() {
uni.navigateTo({ url: `./userList` })
},
},
}
</script>
<style scoped lang="scss">
.Detail {
padding-bottom: 40px;
background: #F6F7F9;
.end-btn {
position: fixed;
bottom: 0;
left: 0;
z-index: 11;
width: 100%;
height: 112px;
line-height: 112px;
text-align: center;
color: #fff;
font-size: 32px;
background: #1365dd;
}
&.detail-active {
padding-bottom: 132px;
}
.detail-top {
padding: 30px;
background: #fff;
border-bottom: 16px solid #f6f7f9;
.avatar {
height: 64px;
width: 64px;
color: #fff;
background: $uni-color-primary;
border-radius: 50%;
font-size: 24px;
text-align: center;
line-height: 64px;
margin-right: 16px;
}
.color-999 {
color: #999999;
}
.color-333 {
color: #333;
}
.w-100 {
width: 100%;
}
.statusTag {
padding: 0 12px;
line-height: 30px;
border: 1px solid #2573ff;
color: #2573ff;
font-size: 22px;
&.over {
border-color: #666;
color: #666;
}
}
.header-middle {
padding: 32px 0 48px 0;
.contsnts {
font-size: 26px;
line-height: 1.5;
word-break: break-all;
}
img {
margin-top: 30px;
width: 686px;
height: 486px;
}
}
.img-list {
img {
width: calc(33vw - 6px - 24px);
height: calc(33vw - 6px - 24px);
margin: 0 12px 12px 0;
&:nth-of-type(3n) {
margin-right: 0;
}
}
.title {
width: 100%;
line-height: 112px;
background: #fff;
font-size: 32px;
font-family: PingFangSC-Regular, PingFang SC;
color: #999;
}
}
}
.tags {
width: 80px;
height: 34px;
line-height: 34px;
margin-left: 16px;
text-align: center;
color: #fff;
font-size: 24px;
background: #1aaaff;
border-radius: 8px;
}
::v-deep uni-video {
width: 100%;
}
.comments {
padding: 0 32px 20px;
font-size: 28px;
background: #fff;
.vote-item {
display: flex;
position: relative;
align-items: center;
justify-content: space-between;
padding: 24px 32px;
margin-bottom: 16px;
background: #ffffff;
border-radius: 8px;
overflow: hidden;
border: 1px solid #95cbff;
.left {
display: flex;
flex: 1;
line-height: 1.2;
margin-right: 20px;
span {
word-break: break-word;
&:first-child {
flex-shrink: 1;
}
&:last-child {
flex: 1;
}
}
}
em {
position: absolute;
left: 0;
top: 0;
z-index: 0;
height: 100%;
background: #dce8f4;
}
span {
flex-shrink: 1;
position: relative;
z-index: 1;
color: #5b84b3;
font-size: 28px;
}
i {
position: relative;
z-index: 1;
font-style: normal;
color: #5b84b3;
font-size: 28px;
}
}
.totalCount {
display: flex;
justify-content: space-between;
.total {
display: block;
font-size: 30px;
height: 120px;
box-sizing: border-box;
padding-top: 44px;
}
.rightCount {
padding-top: 44px;
}
}
.u-avatar {
margin-right: 24px;
}
.content {
color: #333;
margin-left: 72px;
margin-top: 10px;
&.color-999 {
color: #999999;
font-size: 24px;
margin-bottom: 48px;
}
}
}
.votePeople {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 16px;
height: 112px;
padding: 0 32px 0 52px;
background: #fff;
.leftPeople {
font-size: 28px;
color: #333;
}
.right {
span {
color: #2573ff;
font-size: 28px;
}
}
}
.bottomInput {
position: fixed;
bottom: 0;
z-index: 11;
width: 100%;
background: #fff;
display: flex;
justify-content: space-between;
align-items: center;
padding: 24px 30px;
box-sizing: border-box;
border-top: 1px solid #eee;
.leftInput {
flex: 1;
height: 58px;
line-height: 58px;
text-align: center;
background: #f0f0f0;
border-radius: 30px;
}
// .righticon {
// .icontext {
// margin-left: 10px;
// }
// }
}
.comments-wrapper {
padding: 20px 0;
.u-input {
background: #f7f7f7;
border-radius: 8px 8px 0 0;
padding: 10px !important;
margin: 0 30px 0 30px;
.uni-textarea-placeholder {
padding: 16px 0 0 16px;
}
.uni-textarea-textarea {
padding: 16px 0 0 16px;
}
}
.words {
background: #f7f7f7;
border-radius: 0 0 8px 8px;
margin: 0 30px;
padding: 10px;
text-align: right;
font-size: 26px;
color: #999999;
}
.bottombtn {
display: flex;
justify-content: space-between;
align-items: center;
margin: 0 30px;
padding: 20px 0 0;
.emptys {
font-size: 26px;
color: #666666;
}
.publishs {
width: 144px;
height: 64px;
line-height: 64px;
text-align: center;
background: #1365dd;
border-radius: 32px;
color: #fff;
}
}
}
.popupdele {
::v-deep .u-drawer-content {
text-align: center;
div {
padding: 5px 0;
color: #666;
}
}
}
// ::v-deep .u-drawer {
// .u-drawer-content {
// .u-drawer__scroll-view {
// .uni-scroll-view {
// // overflow: hidden;
// overflow: inherit !important;
// }
// }
// }
// }
}
</style>