小程序产品库完成

This commit is contained in:
aixianling
2022-02-14 17:25:54 +08:00
parent cb5f434edb
commit 8d2905428e
145 changed files with 22037 additions and 0 deletions

View File

@@ -0,0 +1,353 @@
<template>
<div class="page">
<div class="fixed-top">
<div class="header-search">
<div class="search-input-content">
<img src="https://cdn.cunwuyun.cn/img/search-blue.svg" alt="" class="search-icon">
<input type="text" placeholder="请输入活动名称或地点" class="search-input" placeholder-style="color:#E2E8F1;"
v-model="inputValue" @confirm="getListInit" confirm-type="search"/>
</div>
</div>
<div class="header-select">
<div class="select-item" @click="activeStatusShow = true">
<span>{{ activeStatusLabel }}</span>
<img src="https://cdn.cunwuyun.cn/img/down.svg" alt="" class="down-icon">
</div>
<div class="select-item" @click="checkStatusShow = true">
<span>{{ checkStatusLabel }}</span>
<img src="https://cdn.cunwuyun.cn/img/down.svg" alt="" class="down-icon">
</div>
</div>
</div>
<div class="active-list">
<div class="item" v-for="(item, index) in list" :key="index" @click="isToken(`./detail?id=${item.id}`)">
<div class="item-top">
<p class="title">{{ item.title }}</p>
<div class="info">
<span class="label">活动时间</span>
<span class="value">{{ item.beginTime }} <br/>{{ item.endTime }}</span>
</div>
<div class="info">
<span class="label">活动地点</span>
<span class="value">{{ item.address }}</span>
</div>
</div>
<div class="item-btn">
<span class="phone-btn" @click.stop="callPhone(item.contactPhone)" v-if="item.contactPhone">呼叫联系人</span>
<span v-if="item.signupStatus == 0 && item.logStatus == null"
@click="isToken(`./toAdd?id=${item.id}`)">去报名</span>
<span v-if="item.actionStatus == 1 && item.logStatus == 0"
@click="isToken(`./addContent?id=${item.id}&reportId=${item.reportId}`)">填写日志</span>
<span v-if="item.logStatus == 2" @click="isToken(`./logDetail?id=${item.id}&title=${item.title}`)">查看日志</span>
</div>
<span class="item-status"
:class="'color'+item.actionStatus">{{
$dict.getLabel('partyReportActionStatus', item.actionStatus)
}}</span>
</div>
<AiEmpty v-if="!list.length" class="pad-t168"/>
</div>
<div class="fixed-bottom btn-footer">
<div :class="listType == 0 ? 'confirm-bg' : ''" @click="listTypeChange('0')">
<img src="https://cdn.cunwuyun.cn/dvcp/activityList/more-icon-fff.png" alt="" v-if="listType == 0">
<img src="https://cdn.cunwuyun.cn/dvcp/activityList/more-icon-999.png" alt="" v-else>
活动列表
</div>
<div :class="listType == 3 ? 'confirm-bg' : ''" @click="listTypeChange('3')">
<img src="https://cdn.cunwuyun.cn/dvcp/activityList/pen-icon-fff.png" alt="" v-if="listType == 3">
<img src="https://cdn.cunwuyun.cn/dvcp/activityList/pen-icon-999.png" alt="" v-else>
我的活动
</div>
</div>
<u-select v-model="activeStatusShow" :list="activeStatusList" @confirm="confirmActiveStatus"
confirm-color="#07c160"></u-select>
<u-select v-model="checkStatusShow" :list="checkStatusList" @confirm="confirmActiveStatus"
confirm-color="#07c160"></u-select>
<ai-login ref="login"></ai-login>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
name: "AppActivityList",
appName: "居民活动",
computed: {
...mapState(['user', 'token'])
},
data() {
return {
inputValue: '',
current: 1,
list: [],
activeStatus: '',
activeStatusLabel: '活动状态',
activeStatusShow: false,
activeStatusList: [],
checkStatusShow: false,
checkStatusList: [],
checkStatus: '',
checkStatusLabel: '报名状态',
listType: '0',
partyId: '',
areaId: ''
}
},
onLoad() {
this.areaId = uni.getStorageSync('areaId')
if (this.user.partyId) {
this.partyId = this.user.partyId
} else {
this.partyId = this.user.residentId
}
},
onShow() {
this.$dict.load('partyReportActionStatus', 'partyReportSignupStatus').then((res) => {
this.activeStatusList = this.getSelectList('partyReportActionStatus')
this.checkStatusList = this.getSelectList('partyReportSignupStatus')
this.getListInit()
})
},
methods: {
confirmActiveStatus(e) {
if (this.activeStatusShow) {
this.activeStatusLabel = e[0].label
this.activeStatus = e[0].value
}
if (this.checkStatusShow) {
this.checkStatusLabel = e[0].label
this.checkStatus = e[0].value
}
this.getListInit()
},
getListInit() {
this.current = 1
this.list = []
this.getList()
},
getList() {
this.$instance.post(`/app/apppartyreport/list-xcx?title=${this.inputValue}&size=10&current=${this.current}&listType=${this.listType}&actionStatus=${this.activeStatus}&signupStatus=${this.checkStatus}&partyId=${this.partyId}&areaId=${this.areaId}`).then(res => {
if (res.code == 0) {
if (this.current > res.data.pages) {
return
}
this.list = this.current > 1 ? [...this.list, ...res.data.records] : res.data.records;
}
})
},
isToken(url) {
if (this.token) {//判断是否登录
if (this.user.status == 0) {
if (!this.user.phone) {//判断已经绑定手机
this.$linkTo('/pages/phone/bingPhoneNumber?from=auth')
} else {
this.$linkTo('/pages/auth/authenticationInfo')
}
} else {
this.$linkTo(url)
}
} else {
// this.$getUserProfile().then((v) => {
// this.$autoLogin(v.userInfo).then(() => {
// this.isToken(url)
// })
// }).catch(() => {
// this.$toast('请先登录')
// })
this.login()
}
},
login() {
this.$refs.login.show()
},
// toDetail(id) {
// this.$linkTo(`./detail?id=${id}`)
// },
// toAddContent(id, reportId) {
// this.$linkTo(`./addContent?id=${id}&reportId=${reportId}`)
// },
// toAdd(id) {
// this.$linkTo(`./add?id=${id}`)
// },
// toLogDetail(id) {
// this.$linkTo(`./logDetail?id=${id}`)
// },
listTypeChange(type) {
this.listType = type
this.activeStatus = ''
this.activeStatusLabel = '活动状态'
this.checkStatus = ''
this.checkStatusLabel = '报名状态'
this.getListInit()
},
getSelectList(dictName) {
var list = []
this.$dict.getDict(dictName).map(i => {
var item = {
label: i.dictName,
value: i.dictValue
}
list.push(item)
})
list.unshift({label: '全部', value: ''})
return list
},
callPhone(phone) {
wx.makePhoneCall({
phoneNumber: phone,
})
}
},
onReachBottom() {
this.current = this.current + 1;
this.getList()
},
}
</script>
<style scoped lang="scss">
@import "../../common/common.scss";
.page {
width: 100%;
background-color: #F3F6F9;
.fixed-top {
z-index: 99;
}
.active-list {
padding: 234px 32px 112px;
margin-top: 8px;
background-color: #F3F6F9;
box-sizing: border-box;
.item {
width: 100%;
background: #FFF;
padding: 32px 0 0;
box-sizing: border-box;
margin-bottom: 34px;
position: relative;
overflow: hidden;
.item-top {
padding: 0 32px;
}
.title {
width: 576px;
font-size: 32px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333;
line-height: 44px;
word-break: break-all;
margin-bottom: 32px;
}
.info {
font-size: 30px;
line-height: 42px;
margin-bottom: 8px;
.label {
display: inline-block;
width: 150px;
color: #999;
vertical-align: top;
}
.value {
display: inline-block;
width: calc(100% - 150px);
color: #343D65;
}
}
.item-btn {
margin-top: 32px;
padding: 20px 32px;
border-top: 2px solid #eee;
text-align: right;
span {
display: inline-block;
padding: 0 24px;
line-height: 56px;
border-radius: 28px;
border: 2px solid #1365DD;
color: #1365DD;
font-size: 28px;
margin-left: 32px;
}
.phone-btn {
border: 2px solid #E1E1E1;
color: #606060;
}
}
.item-status {
width: 160px;
height: 40px;
line-height: 36px;
font-size: 26px;
font-weight: 500;
position: absolute;
right: -38px;
top: 24px;
-webkit-transform: rotate(90deg);
transform: rotate(45deg);
text-align: center;
}
.color0 {
background: #FFF3E9;
color: #FF8822;
}
.color1 {
background: #EEF5FF;
color: #5A98F2;
}
.color2 {
background: #F2F2F2;
color: #999;
}
}
}
.btn-footer {
display: flex;
height: 112px;
line-height: 112px;
background-color: #fff;
border-top: 2px solid #ddd;
box-sizing: border-box;
div {
flex: 1;
text-align: center;
font-size: 32px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #666;
img {
width: 36px;
height: 36px;
margin-right: 8px;
vertical-align: sub;
}
}
.confirm-bg {
background-color: #197DF0;
color: #fff;
}
}
}
</style>

View File

@@ -0,0 +1,205 @@
<template>
<div class="page">
<div class="add-form">
<div class="form-item">
<span class="item-tips">*</span>
<span class="label">活动报名类型</span>
<span :class="reportType ? 'value color-333' : 'value color-999'"
@click="reportTypeShow = true">{{ reportTypeList[reportType].label || '请选择' }}</span>
<img src="https://cdn.cunwuyun.cn/img/right-icon-999.png" alt="" class="right-icon">
</div>
<div class="form-item">
<span class="item-tips">*</span>
<span class="label">联系手机</span>
<div class="item-input">
<input type="tel" placeholder="请输入手机号码" placeholder-style="color:#999;" maxlength="11" v-model="phone">
</div>
</div>
<div class="form-item">
<span class="item-tips"></span>
<span class="label">报名备注</span>
<div class="item-input fs-32">
<u-input type="textarea" height="140" placeholder="填写报名备注1000字以内" placeholder-style="color:#999;"
maxlength="1000" v-model="remark"/>
</div>
</div>
</div>
<div class="tips-content">
<p>报到类型说明</p>
<p>1单位联系社区报到服务党员所属单位联系的社区参与活动到社区服务</p>
<p>2居住地社区报到服务党员所在本人居住的社区参与活动到社区服务</p>
<p>3其他村(社区)报到服务党员所在除单位联系社区与居住社区以外的其他社区参与活动到社区服务</p>
</div>
<u-select v-model="reportTypeShow" :list="reportTypeList" @confirm="confirmReportType"
confirm-color="#07c160"></u-select>
<div class="fixed-bottom confirm-btn" @click="confirm">提交</div>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
name: "add",
computed: {
...mapState(['user'])
},
data() {
return {
reportType: '',
title: '',
content: '',
reportTypeList: [],
reportTypeShow: false,
flag: false,
id: '',
phone: ''
}
},
onLoad(option) {
this.id = option.id
this.$dict.load('partyReportSignupReportType').then((res) => {
this.$nextTick(() => {
this.$dict.getDict('partyReportSignupReportType').map(i => {
var item = {
label: i.dictName,
value: i.dictValue
}
this.reportTypeList.push(item)
})
})
})
this.phone = this.user.phone
},
methods: {
confirm() {
if (this.flag) return
this.$loading()
var params = {
reportType: this.reportType,
phone: this.phone,
remark: this.remark,
reportId: this.id,
avatar: this.user.avatarUrl,
partyId: this.user.partyId || this.user.residentId
}
if (!params.reportType) {
return this.$toast('请选择活动报名类型')
}
if (!params.phone) {
return this.$toast('请输入联系手机')
}
this.flag = true
this.$instance.post(`/app/apppartyreport/signup`, params).then(res => {
if (res && res.code == 0) {
this.$hideLoading()
this.$toast('活动报名成功!')
setTimeout(() => {
uni.navigateBack()
}, 1000)
} else {
this.flag = false
}
}).catch(err => {
console.log(err)
this.flag = false
})
},
confirmReportType(e) {
this.reportType = e[0].value
}
}
}
</script>
<style scoped lang="scss">
@import "../../common/common.scss";
.page {
width: 100%;
background-color: #F3F6F9;
.form-item {
padding: 34px 32px 34px 12px;
line-height: 44px;
background-color: #fff;
border-bottom: 2px solid #ddd;
.item-tips {
display: inline-block;
width: 12px;
font-size: 32px;
color: #FF4466;
}
.label {
display: inline-block;
min-width: 126px;
color: #333;
font-size: 32px;
margin-left: 8px;
.mini-label {
color: #999;
font-size: 28px;
}
}
.value {
display: inline-block;
width: 454px;
text-align: right;
}
.text {
display: inline-block;
width: 520px;
text-align: right;
}
.color-333 {
color: #333 !important;
}
.right-icon {
width: 32px;
height: 32px;
margin-left: 8px;
vertical-align: middle;
}
.item-input {
padding-bottom: 4px;
margin-left: 24px;
margin-top: 32px;
input {
line-height: 42px;
font-size: 32px;
}
}
.upload {
margin: 32px 0 024px;
}
}
.form-item:nth-last-child(1) {
border-bottom: none;
}
.mar-b8 {
margin-bottom: 16px;
}
.tips-content {
padding: 64px 32px 0;
p {
color: #999999;
line-height: 40px;
font-size: 28px;
word-break: break-all;
}
}
}
</style>

View File

@@ -0,0 +1,178 @@
<template>
<div class="page">
<div class="header-bg"></div>
<div class="add-form">
<div class="form-item">
<span class="item-tips">*</span>
<span class="label">活动总结</span>
<div class="item-input fs-32">
<u-input type="textarea" height="140" placeholder="填写本次活动参与心得体会1000字以内" placeholder-style="color:#999;"
maxlength="1000" v-model="content"/>
</div>
</div>
<div class="form-item">
<span class="item-tips"></span>
<span class="label">活动照片<span class="mini-label">最多9张</span></span>
<div class="upload">
<AiUploader :limit="9" v-model="files"></AiUploader>
</div>
</div>
</div>
<div class="fixed-bottom confirm-btn" @click="confirm">提交</div>
</div>
</template>
<script>
import AiUploader from '@/components/AiUploader/AiUploader'
import {mapState} from 'vuex'
export default {
name: "addContent",
components: {
AiUploader
},
computed: {
...mapState(['user'])
},
data() {
return {
content: '',
files: [],
flag: false,
id: '',
reportId: ''
}
},
onLoad(option) {
this.id = option.id
this.reportId = option.reportId
},
methods: {
confirm() {
if (this.flag) return
this.$loading()
var fileIds = []
if (this.files.length) {
this.files.map((item) => {
fileIds.push(item.id)
})
}
var params = {
reportId: this.reportId,
id: this.id,
content: this.content,
files: this.files,
fileIds: fileIds
}
if (!params.content) {
return this.$toast('请输入本次活动参与心得体会')
}
this.flag = true
this.$instance.post(`/app/apppartyreport/log-add`, params).then(res => {
if (res && res.code == 0) {
this.$hideLoading()
this.$toast('日志填写成功!')
setTimeout(() => {
uni.navigateBack()
}, 1000)
} else {
this.flag = false
}
}).catch(err => {
console.log(err)
this.flag = false
})
},
}
}
</script>
<style scoped lang="scss">
@import "../../common/common.scss";
.page {
width: 100%;
background-color: #F3F6F9;
.header-bg {
width: 100%;
height: 112px;
background: #197DF0;
}
.add-form {
margin: -96px 0 0 32px;
border-radius: 8px;
background-color: #fff;
width: 686px;
}
.form-item {
padding: 34px 32px 34px 12px;
line-height: 44px;
.item-tips {
display: inline-block;
width: 12px;
font-size: 32px;
color: #FF4466;
}
.label {
display: inline-block;
min-width: 126px;
color: #333;
font-size: 32px;
margin-left: 8px;
.mini-label {
color: #999;
font-size: 28px;
}
}
.value {
display: inline-block;
width: 518px;
text-align: right;
}
.text {
display: inline-block;
width: 520px;
text-align: right;
}
.color-333 {
color: #333 !important;
}
.right-icon {
width: 32px;
height: 32px;
margin-left: 8px;
vertical-align: middle;
}
.item-input {
padding-bottom: 4px;
margin-left: 24px;
margin-top: 32px;
input {
line-height: 42px;
font-size: 32px;
}
}
.upload {
margin: 32px 0 0 24px;
}
}
.mar-b8 {
margin-bottom: 16px;
}
}
</style>

View File

@@ -0,0 +1,238 @@
<template>
<div class="page">
<div class="header-info">
<p class="title">{{ info.title }}</p>
<div class="info">
<span class="label">联系人</span>
<span class="value">{{ info.contactPerson }}</span>
</div>
<div class="info">
<span class="label">联系电话</span>
<span class="value">{{ info.contactPhone }}</span>
</div>
<div class="info">
<span class="label">活动时间</span>
<span class="value">{{ info.beginTime }} {{ info.endTime }}</span>
</div>
<div v-if="viewMore">
<div class="info">
<span class="label">活动地点</span>
<span class="value">{{ info.address }}</span>
</div>
<div class="info">
<span class="label">参与名额</span>
<span class="value" v-if="info.total > 0">{{ info.total }}</span>
<span class="value" v-else>不限额</span>
</div>
<div class="info">
<span class="label">报名截止时间</span>
<span class="value">{{ info.stopSignupTime }}({{ info.timeRemaining }})</span>
</div>
<div class="info">
<span class="label">活动报名人数</span>
<span class="value">{{ info.signupCount }}人报名</span>
</div>
<div class="info">
<span class="label">活动状态</span>
<span class="value">{{ $dict.getLabel('partyReportActionStatus', info.actionStatus) }}</span>
</div>
</div>
<div class="view-btn" @click="viewMore = !viewMore">{{ viewMore ? '收起' : '展开' }}<img
:class="viewMore ? 'view-btn-active' : ''" src="https://cdn.cunwuyun.cn/img/down-icon-fff.png" alt=""/></div>
</div>
<div class="content">
<p class="title">活动介绍</p>
<!-- <div class="html" v-html="info.content"></div> -->
<u-parse :html="info.content"></u-parse>
</div>
<div class="fixed-bottom btn-footer">
<div @click="$linkTo(`./userList?id=${info.id}`)"><img
src="https://cdn.cunwuyun.cn/dvcp/activityList/more-icon-999.png" alt=""/>查看报名情况
</div>
<div class="confirm-bg" v-if="info.signupStatus == 0 && info.logStatus == null"
@click="$linkTo(`./add?id=${info.id}`)"><img src="https://cdn.cunwuyun.cn/dvcp/activityList/edit-icon"
alt=""/>立即报名
</div>
<!-- <div class="confirm-bg" v-if="info.logStatus != null && info.logStatus != 0" @click="cancel()">
<img src="https://cdn.cunwuyun.cn/dvcp/activityList/cancel-icon" alt="">取消报名
</div> -->
<div class="confirm-bg" v-if="info.actionStatus == 1 && info.logStatus == 0"
@click="$linkTo(`./addContent?id=${info.signupId}&reportId=${info.id}`)"><img
src="https://cdn.cunwuyun.cn/dvcp/activityList/edit-icon" alt=""/>填写活动日志
</div>
<div class="confirm-bg" v-if="info.logStatus == 2"
@click="$linkTo(`./logDetail?id=${info.id}&title=${info.title}`)"><img
src="https://cdn.cunwuyun.cn/dvcp/activityList/tips-icon" alt=""/>我的活动日志
</div>
</div>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
name: 'detail',
computed: {
...mapState(['user', 'token']),
},
data() {
return {
viewMore: false,
id: '',
info: {},
partyId: '',
}
},
onLoad(option) {
this.id = option.id
if (this.user.partyId) {
this.partyId = this.user.partyId
} else {
this.partyId = this.user.residentId
}
},
onShow() {
this.$dict.load('partyReportActionStatus').then((res) => {
this.getDetail()
})
},
methods: {
getDetail() {
this.$instance.post(`/app/apppartyreport/queryDetailById?id=${this.id}&partyId=${this.partyId}`).then((res) => {
if (res.code == 0) {
this.info = res.data
this.info.beginTime = this.info.beginTime.substring(0, 16)
this.info.endTime = this.info.endTime.substring(0, 16)
this.info.stopSignupTime = this.info.stopSignupTime.substring(0, 16)
}
})
},
cancel() {
this.$instance.post(`/app/apppartyreport/signup-cancel?id=${this.id}&partyId=${this.partyId}`).then((res) => {
if (res.code == 0) {
this.$toast('取消报名成功!')
this.getDetail()
}
})
},
},
onShareAppMessage() {
return {
title: this.info.title,
path: `/mods/AppActivityList/AppActivityList?id=${this.id}`,
}
},
}
</script>
<style scoped lang="scss">
@import '../../common/common.scss';
.page {
width: 100%;
background-color: #fff;
.header-info {
background-color: #197df0;
padding: 24px 32px 0;
.title {
width: 100%;
word-break: break-all;
font-size: 40px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #ffffff;
line-height: 64px;
letter-spacing: 2px;
margin-bottom: 16px;
}
.info {
margin-bottom: 16px;
font-size: 28px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
line-height: 40px;
.label {
display: inline-block;
color: #fff;
// width:192px; // text-align: justify;
// text-align-last:justify
}
.value {
color: #fff;
}
}
.view-btn {
font-size: 28px;
color: #fff;
line-height: 40px;
text-align: center;
padding: 52px 0 20px 0;
img {
width: 32px;
height: 32px;
vertical-align: middle;
margin-left: 4px;
transition: all 0.3s ease;
}
.view-btn-active {
transform: rotate(-180deg);
}
}
}
.content {
background-color: #fff;
padding-bottom: 112px;
.title {
width: 100%;
line-height: 96px;
background: #fff;
padding-left: 32px;
box-sizing: border-box;
color: #666;
}
.html {
padding: 16px 32px;
}
}
.btn-footer {
display: flex;
height: 112px;
line-height: 112px;
background-color: #fff;
border-top: 2px solid #ddd;
box-sizing: border-box;
div {
flex: 1;
text-align: center;
font-size: 32px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #666;
img {
width: 36px;
height: 36px;
margin-right: 8px;
vertical-align: sub;
}
}
.confirm-bg {
background-color: #197df0;
color: #fff;
}
}
}
</style>

View File

@@ -0,0 +1,160 @@
<template>
<div class="page">
<div class="header-info">
<p class="title">{{ title }}</p>
<div class="info">
<span class="label">提交时间</span>
<span class="value">{{ info.submitTime }}</span>
</div>
</div>
<div class="content">
<p class="title"><span class="title-line"></span>活动总结</p>
<div class="html" v-html="info.content"></div>
</div>
<div class="content" v-if="info.files.length">
<p class="title"><span class="title-line"></span>活动照片</p>
<div class="img-list">
<img :src="item.accessUrl" alt="" v-for="(item, index) in info.files" :key="index"
@click="$previewImage(info.files, index, 'accessUrl')"/>
</div>
</div>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
name: 'logDetail',
computed: {
...mapState(['user']),
},
data() {
return {
id: '',
info: {},
partyId: '',
title: ''
}
},
onLoad(option) {
if (this.user.partyId) {
this.partyId = this.user.partyId
} else {
this.partyId = this.user.residentId
}
this.id = option.id
this.title = option.title
this.getDetail()
},
methods: {
getDetail() {
this.$instance.post(`/app/apppartyreport/log-report?reportId=${this.id}&partyId=${this.partyId}`).then((res) => {
if (res.code == 0) {
this.info = res.data
this.info.submitTime = this.info.submitTime.substring(0, 16)
}
})
},
},
}
</script>
<style scoped lang="scss">
@import '../../common/common.scss';
.page {
width: 100%;
background-color: #f3f6f9;
.header-info {
background-color: #197df0;
padding: 24px 32px 48px;
margin-bottom: 16px;
.title {
width: 100%;
word-break: break-all;
font-size: 40px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #ffffff;
line-height: 64px;
letter-spacing: 2px;
margin-bottom: 16px;
}
.info {
margin-bottom: 16px;
font-size: 28px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
line-height: 40px;
.label {
display: inline-block;
color: #fff;
// width:192px; // text-align: justify;
// text-align-last:justify
}
.value {
color: #ffe8e8;
}
}
.view-btn {
font-size: 28px;
color: #fff;
line-height: 40px;
text-align: center;
padding: 52px 0 20px 0;
img {
width: 32px;
height: 32px;
vertical-align: middle;
margin-left: 4px;
transition: all 0.3s ease;
}
.view-btn-active {
transform: rotate(-180deg);
}
}
}
.content {
background-color: #fff;
margin-bottom: 16px;
.title {
width: 100%;
line-height: 96px;
background: #fff;
padding-left: 32px;
box-sizing: border-box;
color: #666;
.title-line {
display: inline-block;
width: 6px;
height: 32px;
background: #D7261E;
margin-right: 12px;
vertical-align: sub;
}
}
.html {
padding: 16px 32px;
}
.img-list {
img {
width: 686px;
height: 384px;
margin: 0 0 32px 32px;
}
}
}
}
</style>

View File

@@ -0,0 +1,119 @@
<template>
<div class="page">
<p class="title">报名记录已有<span>{{ list.length }}</span>人报名</p>
<div class="user-list">
<div class="item" v-for="(item, index) in list" :key="index">
<div class="left">
<img :src="item.avatar" alt="">
<span>{{ nameInit(item.partyName) }}</span>
</div>
<div class="time">{{ item.signupTime }}</div>
</div>
<AiEmpty v-if="!list.length" class="pad-t168"/>
</div>
</div>
</template>
<script>
export default {
name: "userList",
data() {
return {
id: '',
list: []
}
},
onLoad(option) {
this.id = option.id
this.getList()
},
methods: {
getList() {
this.$instance.post(`/app/apppartyreport/signup-info?id=${this.id}`).then(res => {
if (res.code == 0) {
this.list = res.data
if (this.list.length) {
this.list.map((item) => {
if (!item.partyName && item.residentName) {
item.partyName = item.residentName
}
})
}
}
})
},
nameInit(name) {
if (!name) {
return '-'
}
var newStr;
if (name.length === 2) {
newStr = '*' + name.substr(1, 2)
} else if (name.length > 2) {
var char = '';
for (var i = 0, len = name.length - 2; i < len; i++) {
char += '*';
}
newStr = char + name.substr(name.length - 2, name.length);
} else {
newStr = name;
}
return newStr;
}
}
}
</script>
<style scoped lang="scss">
@import "../../common/common.scss";
.page {
width: 100%;
background-color: #F3F6F9;
padding-top: 16px;
.title {
line-height: 96px;
background-color: #fff;
padding-left: 32px;
color: #333;
font-size: 32px;
margin-bottom: 4px span {
color: #D73D3D;
}
}
.user-list {
.item {
width: 100%;
height: 148px;
background: #FFFFFF;
display: flex;
justify-content: space-between;
font-size: 30px;
padding: 32px;
box-sizing: border-box;
box-shadow: 0 8px 34px -8px rgba(213, 213, 213, 0.5);
.left {
color: #2D2D2E;
line-height: 46px;
vertical-align: middle;
img {
width: 80px;
height: 80px;
border-radius: 50%;
vertical-align: middle;
margin-right: 16px;
}
}
.time {
color: #999;
line-height: 80px;
}
}
}
}
</style>

View File

@@ -0,0 +1,141 @@
<template>
<div class="wrapper">
<div class="areaSelection">
<div class="area">区域选择</div>
<div class="select">
<ai-area-picker ref="area" class="ai-area" :value="areaId" :name.sync="areaName" :areaId="$areaId"
@select="areaSelect">
<div class="ai-area__wrapper">
<span class="label" v-if="areaName">{{ areaName }}</span>
<span v-else>请选择</span>
<u-icon name="arrow-right"></u-icon>
</div>
</ai-area-picker>
</div>
</div>
<template v-if="list.length">
<u-index-list :scrollTop="scrollTop" :index-list="indexList">
<div v-for="(letter, index) in indexList" :key="index">
<u-index-anchor :index="letter"/>
<div class="item" hover-class="bg-hover" @click="phone(item)"
v-for="(item, index) in list.filter(e=>e.nameInitials==letter)" :key="index">
<label>{{ item.name }}</label>
<div class="info">
{{ item.type }}<span>{{ item.phone }}</span>
</div>
</div>
</div>
</u-index-list>
</template>
<AiEmpty v-else></AiEmpty>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
name: "AppAddressBook",
appName: "便民通讯录",
data() {
return {
scrollTop: 0,
indexList: [],
list: [],
userInfo: {},
areaId: '',
$areaId: '',
areaName: '',
}
},
onLoad() {
this.userInfo = uni.getStorageSync("userInfo");
this.areaId = this.$areaId
this.areaName = this.$areaName
this.getList();
},
computed: {
...mapState(['user'])
},
methods: {
phone({phone: phoneNumber}) {
uni.makePhoneCall({phoneNumber});
},
getList() {
this.$instance.post("/app/appconvenientaddressbook/list", null, {
params: {
isPublic: 1,
resource: "portal",
areaId: this.areaId,
size: 999
}
}).then(res => {
if (res?.data) {
this.indexList = [...new Set(res.data.records.map(e => e.nameInitials))];
this.list = res.data.records;
}
})
},
areaSelect(v) {
this.areaId = v
this.isMore = false
this.current = 0
this.list = []
this.$nextTick(() => {
this.getList()
})
},
},
onPageScroll(e) {
this.scrollTop = e.scrollTop;
},
}
</script>
<style lang="scss" scoped>
.areaSelection {
display: flex;
justify-content: space-between;
box-sizing: border-box;
padding: 0 30px;
width: 100%;
height: 120px;
line-height: 120px;
background-color: #FFFF;
.select {
text-align: right;
}
}
.item {
box-sizing: border-box;
padding: 32px 48px;
background: #FFFFFF;
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.02);
& > label {
font-size: 32px;
font-weight: 600;
color: #333333;
line-height: 44px;
}
.info {
display: flex;
align-items: center;
font-size: 26px;
color: #999999;
margin-top: 8px;
& > span {
color: #333333;
margin-left: 16px;
}
}
}
</style>

View File

@@ -0,0 +1,320 @@
<template>
<div class="wrapper padding">
<!-- <u-tabs :list="tabs" height="124" font-size="40" bg-color="#4181FF" inactive-color="rgba(255,255,255,0.75)"
:bar-style="{backgroundColor:'#fff'}" :active-item-style="active"
:is-scroll="true" :current="index" @change="onChange"></u-tabs> -->
<div class="tabs">
<u-tabs
:list="tabs"
font-size="36"
bg-color="transparent"
:bold="false"
inactive-color="#ccddff"
:is-scroll="true"
:gutter="16"
active-color="#fff"
:current="index"
@change="onChange">
</u-tabs>
</div>
<header>
<span @click="show=true">{{ !typeName ? '全部类型' : typeName }}
<u-icon name="arrow-down" size="28" color="#333333" :custom-style="{marginLeft:'8px'}"></u-icon>
</span>
<div class="total">
<em>{{ total }}</em>个农产品
</div>
</header>
<div class="card-list" v-if="list.length">
<div class="card" v-for="(item,index) in list" :key="index" @click="toDetail(item)">
<div class="top">
<div class="title">{{ item.title }}
</div>
<div class="ag-content">{{ item.content }}
</div>
<div class="phone-wrap">
<img class="img" :class="[item.files.length ==1 ? 'single' : '']" v-for="(photo,idx) in item.files"
:key="idx" :src="photo.url" alt="" @click.stop="preview(item.files,idx)">
</div>
<div class="ag-info">
<div class="tag">{{ $dict.getLabel('agriculturalType', item.type) }}</div>
<div class="date">{{ item.createTime }}</div>
</div>
</div>
<div class="phone" @click.stop="phone(item.phone)">
<u-icon name="phone-fill" size="32" color="#4181FF"></u-icon>
<span>{{ item.phone }}</span>
</div>
</div>
</div>
<AiEmpty v-else/>
<div class="btn-wrapper">
<div class="btn" @click="suport" hover-class="text-hover">我要发布</div>
</div>
<u-select v-model="show" :list="$dict.getDict('agriculturalTypeSearch')" value-name="dictValue"
label-name="dictName" @confirm="confirm"></u-select>
</div>
</template>
<script>
export default {
name: "AppAgProducts",
appName: "晒农产品",
data() {
return {
index: 0,
show: false,
current: 1,
type: "",
typeName: "",
list: [],
total: 0,
}
},
onLoad() {
this.$dict.load("agriculturalTypeSearch");
},
computed: {
active() {
return {
fontSize: "22px",
color: "#FFFFFF",
};
},
tabs() {
return [{
name: '全部'
}, {
name: '我的发布'
}]
},
},
methods: {
preview(photos, index) {
this.$previewImage(photos, index, "url");
},
onChange(val) {
this.index = val;
this.current = 1;
if (!!this.index) {
this.getMine();
} else this.getAll();
},
phone(phoneNumber) {
uni.makePhoneCall({phoneNumber});
},
confirm(val) {
this.type = val[0].value;
this.typeName = val[0].label;
this.current = 1;
if (!!this.index) {
this.getMine();
} else this.getAll();
},
getAll() {
this.$instance.post("/app/appshowagriculturalproduce/list", null, {
params: {
type: this.type,
current: this.current,
}
}).then(res => {
if (res?.data) {
this.list = this.current > 1 ? [...this.list, ...res.data.records] : res.data.records;
this.total = res.data.total;
}
})
},
getMine() {
this.$instance.post("/app/appshowagriculturalproduce/listByWx", null, {
params: {
type: this.type,
current: this.current,
}
}).then(res => {
if (res?.data) {
this.list = this.current > 1 ? [...this.list, ...res.data.records] : res.data.records;
this.total = res.data.total;
}
})
},
toDetail({id}) {
uni.navigateTo({
url: "./agDetail?id=" + id + "&type=" + this.index
})
},
suport() {
uni.navigateTo({
url: "./agAdd"
})
}
},
onShow() {
this.current = 1;
if (!!this.index) {
this.getMine();
} else {
this.getAll();
}
},
onReachBottom() {
this.current++;
if (!!this.index) {
this.getMine();
} else {
this.getAll();
}
}
}
</script>
<style lang="scss" scoped>
.padding {
padding-top: 100px;
padding-bottom: 156px;
.tabs {
position: fixed;
top: 0;
left: 0;
z-index: 11;
width: 100%;
padding: 10px 0 10px 16px;
box-sizing: border-box;
background: #4181FF;
}
header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 48px 32px 32px;
& > span {
font-size: 38px;
font-weight: 600;
color: #333333;
}
.total {
margin-left: auto;
font-size: 28px;
font-weight: 400;
color: #666666;
display: flex;
align-items: center;
& > em {
color: #4181FF;
}
}
}
.card-list {
display: flex;
flex-direction: column;
box-sizing: border-box;
padding: 0 32px;
.card {
background: #FFFFFF;
box-shadow: 0px -1px 0px 0px #DDDDDD;
border-radius: 16px 16px 0px 0px;
margin-bottom: 24px;
.top {
box-sizing: border-box;
padding: 32px;
border-bottom: 1px solid #DDDDDD;
.title {
font-size: 36px;
font-weight: 600;
color: #333333;
line-height: 50px;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow: hidden;
}
.ag-content {
font-size: 32px;
font-weight: 400;
color: #999999;
line-height: 44px;
margin-top: 8px;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow: hidden;
}
.phone-wrap {
gap: 4px;
display: flex;
align-items: center;
flex-wrap: wrap;
margin-top: 24px;
.img {
width: 203px;
height: 204px;
}
.single {
width: 100%;
height: 350px;
}
}
.ag-info {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 24px;
.tag {
width: 88px;
height: 48px;
background: #EEEEEE;
border-radius: 24px;
font-size: 28px;
font-weight: 400;
color: #999999;
text-align: center;
line-height: 50px;
}
.date {
font-size: 28px;
font-weight: 400;
color: #999999;
}
}
}
.phone {
height: 104px;
box-sizing: border-box;
display: flex;
align-items: center;
box-sizing: border-box;
padding: 32px;
& > img {
width: 32px;
height: 33px;
}
& > span {
font-size: 28px;
font-weight: 400;
color: #4181FF;
margin-left: 12px;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,192 @@
<template>
<div class="wrapper">
<div class="card">
<div class="form">
<em>*</em>
<label>标题</label>
</div>
<u-input type="textarea" trim placeholder="请输入标题" maxlength="100"
placeholder-style="color: #999999;font-size: 15px;" v-model="form.title"/>
<div class="form" style="border-top: 1px solid #dddddd;">
<em>*</em>
<label>详细描述</label>
</div>
<u-input type="textarea" trim placeholder="请输入详细描述信息" maxlength="500"
placeholder-style="color: #999999;font-size: 15px;" v-model="form.content"/>
</div>
<div class="card">
<div class="form">
<em>*</em>
<label>农产品类型</label>
<div class="right" @click="show=true">
<u-icon name="arrow-right" color="#999999" size="28"></u-icon>
<span class="value" style="color: #999999;font-weight:normal;" v-if="!form.typeName">请选择</span>
<span class="value" style="color: #333;font-weight:normal;" v-else>{{ form.typeName }}</span>
</div>
</div>
</div>
<div class="card" style="padding-bottom: 20px;">
<div class="form">
<label>图片上传
<span>(最多9张)</span>
</label>
</div>
<AiUploader :limit="9" v-model="form.files"></AiUploader>
</div>
<div class="card">
<div class="form border">
<em>*</em>
<label>联系人</label>
<div class="right">
<u-input trim placeholder="请输入" input-align="right"
placeholder-style="color:#999;font-size: 17px;" v-model="form.contactPerson"></u-input>
</div>
</div>
<div class="form border">
<em>*</em>
<label>联系方式</label>
<div class="right">
<u-input trim placeholder="请输入" input-align="right"
placeholder-style="color:#999;font-size: 17px;" v-model="form.phone"></u-input>
</div>
</div>
<div class="form">
<em>*</em>
<label>地址</label>
<div class="right">
<u-input trim placeholder="请输入" input-align="right" style="flex: 1;margin-left: 16px;"
placeholder-style="color:#999;font-size: 17px;" v-model="form.address"></u-input>
</div>
</div>
</div>
<div class="btn-wrapper">
<div class="btn" @click="submit" hover-class="text-hover">提交</div>
</div>
<u-select v-model="show" :list="$dict.getDict('agriculturalType')" value-name="dictValue"
label-name="dictName" @confirm="confirm"></u-select>
</div>
</template>
<script>
import AiUploader from '../../components/AiUploader/AiUploader'
export default {
name: "agAdd",
components: {AiUploader},
data() {
return {
show: false,
form: {
title: "",
content: "",
type: "",
typeName: "",
files: [],
contactPerson: "",
phone: "",
address: "",
},
flag: false
}
},
onLoad() {
this.$dict.load("agriculturalType");
},
methods: {
confirm(val) {
this.form.type = val[0].value;
this.form.typeName = val[0].label;
},
submit() {
if (!!!this.form.title) return this.$u.toast("请输入标题");
if (!!!this.form.content) return this.$u.toast("请输入详细描述");
if (!!!this.form.typeName) return this.$u.toast("请选择农产品类型");
if (!!!this.form.contactPerson) return this.$u.toast("请输入联系人")
if (!!!this.form.phone) return this.$u.toast("请输入联系方式");
if (!!!this.form.address) return this.$u.toast("请输入地址");
if (this.flag) return
this.flag = true
this.$loading()
this.$instance.post("/app/appshowagriculturalproduce/addOrUpdate", {
...this.form
}).then(res => {
this.$hideLoading()
this.flag = false
if (res.code == 0) {
this.$u.toast("提交成功");
setTimeout(_ => {
uni.navigateBack();
}, 500)
}
})
}
},
}
</script>
<style lang="scss" scoped>
.wrapper {
padding-bottom: 150px;
}
.card {
box-sizing: border-box;
padding-left: 32px;
background-color: #fff;
margin-bottom: 24px;
.form {
height: 112px;
background: #FFFFFF;
display: flex;
align-items: center;
& > em {
width: 16px;
height: 44px;
font-weight: 400;
color: #FF4466;
line-height: 54px;
font-style: normal;
margin-right: 8px;
}
& > label {
font-size: 32px;
font-weight: 500;
color: #666666;
& > span {
font-size: 28px;
font-weight: 400;
color: #999999;
}
}
.right {
flex: 1;
display: flex;
align-items: center;
flex-direction: row-reverse;
margin-right: 32px;
.value {
font-size: 34px;
font-weight: 600;
color: #333333;
}
}
}
.border {
border-bottom: 1px solid #DDDDDD;
}
}
</style>

View File

@@ -0,0 +1,200 @@
<template>
<div class="wrapper padding">
<div class="card">
<header>{{ detail.title }}</header>
<div class="date">{{ detail.createTime }}</div>
<div class="detail-content">{{ detail.content }}
</div>
<div class="photo-title">图片</div>
<div class="photo-wrap">
<img :src="item.url" alt=""
v-for="(item,index) in detail.files" :key="index" @click="preview(index)">
</div>
</div>
<div class="card">
<div class="item">
<div class="label">联系方式</div>
<div class="value" @click="phone">
<u-icon name="phone-fill" size="28" color="#4181FF" :custom-style="{marginRight:'6px'}"></u-icon>
{{ detail.phone }}
</div>
</div>
<div class="item">
<div class="label">地址</div>
<div class="address">{{ detail.address }}</div>
</div>
</div>
<div class="btn-wrapper" v-if="type==1">
<div class="btn" @click="unDo" hover-class="text-hover">撤销发布</div>
</div>
<!-- <div class="btn" @click="unDo" v-if="type==1">撤销发布</div> -->
</div>
</template>
<script>
export default {
name: "agDetail",
data() {
return {
id: null,
type: null,
detail: {},
}
},
onLoad(opt) {
this.id = opt.id;
this.type = opt.type;
this.getDetail();
},
methods: {
preview(index) {
this.$previewImage(this.detail.files, index, "url");
},
phone() {
uni.makePhoneCall({
phoneNumber: this.detail.phone
})
},
unDo() {
uni.showModal({
title: "提示",
content: "是否确定要撤销?",
success: res => {
if (res.confirm) {
this.$instance.post("/app/appshowagriculturalproduce/delete", null, {
params: {ids: this.id}
}).then(ret => {
if (ret.code == 0) {
this.$u.toast("撤销成功");
setTimeout(_ => {
uni.navigateBack();
}, 500)
}
})
}
}
})
},
getDetail() {
this.$instance.post("/app/appshowagriculturalproduce/queryDetailById", null, {
params: {id: this.id}
}).then(res => {
if (res?.data) {
this.detail = res.data;
}
})
}
},
}
</script>
<style lang="scss" scoped>
.padding {
padding-bottom: 156px;
.card {
background-color: #FFFFFF;
margin-bottom: 24px;
box-sizing: border-box;
padding: 40px 32px;
header {
font-size: 48px;
font-weight: 600;
color: #333333;
line-height: 66px;
}
.date {
font-size: 30px;
font-weight: 400;
color: #999999;
margin-top: 16px;
}
.detail-content {
font-size: 36px;
font-weight: 400;
color: #333333;
line-height: 64px;
margin-top: 64px;
padding-bottom: 48px;
}
.photo-title {
height: 112px;
display: flex;
align-items: center;
font-size: 32px;
font-weight: 400;
color: #999999;
}
.photo-wrap {
display: flex;
align-items: center;
gap: 4px;
flex-wrap: wrap;
& > img {
width: 225px;
height: 225px;
}
}
.item {
display: flex;
justify-content: space-between;
margin-bottom: 32px;
&:last-child {
margin-bottom: 0;
}
.label {
font-size: 32px;
font-weight: 400;
color: #999999;
}
.value {
font-size: 32px;
font-weight: 400;
color: #4181FF;
}
.address {
width: 480px;
font-size: 32px;
font-weight: 400;
color: #333333;
line-height: 44px;
text-align: right;
}
}
}
.btn-wrapper {
height: 100px;
line-height: 100px;
}
.btn {
width: 686px;
height: 88px;
background: #FFFFFF;
border-radius: 16px;
border: 1px solid #FF4466;
display: flex;
align-items: center;
justify-content: center;
font-size: 34px;
font-weight: 600;
position: fixed;
left: 50%;
bottom: 32px;
transform: translateX(-50%);
color: #FF4466;
}
}
</style>

View File

@@ -0,0 +1,232 @@
<template>
<div class="wrapper" :style="{ paddingTop: categorys.length ? '54px' : '10px' }" v-if="pageShow">
<div class="tabs">
<u-tabs
:list="categorys && categorys.map(e=>({name:e.categoryName}))"
font-size="36"
bg-color="transparent"
:bold="false"
inactive-color="#ccddff"
:is-scroll="true"
:gutter="16"
active-color="#fff"
:current="index"
@change="tabChange">
</u-tabs>
</div>
<div class="list-wrap" v-if="categoryList && categoryList.length">
<div class="list-card" hover-class="bg-hover" v-for="(category,index) in categoryList" :key="index"
@click="$linkTo('./contentDetail?id='+category.id)">
<div class="header">{{ category.title }}</div>
<div class="content-wrap" v-if="category.contentType==0 && category.files && category.files.length == 1">
<img class="img" :src="item.url" v-for="(item,index) in category.files" :key="index.id" alt="">
</div>
<div class="content-wrap" v-if="category.contentType==0 && category.files && category.files.length > 1">
<img class="min-img" :src="item.url" v-for="(item,index) in category.files && category.files.slice(0,3)"
:key="index.id" alt="">
</div>
<div class="content-wrap" v-if="category.contentType==1">
<img class="img" :src="category.pictureUrl" alt="">
<img class="play-icon" src="../../static/img/play.png" alt="">
</div>
<div class="bottom">
<div class="left">
<div class="tag">{{ category.categoryName || names }}</div>
{{ category.createTime }}
</div>
<div class="right">
<em>{{ category.viewCount }}</em>
人看过
</div>
</div>
</div>
</div>
<AiEmpty v-else></AiEmpty>
</div>
</template>
<script>
export default {
name: "AppContent",
appName: "内容管理",
data() {
return {
index: 0,
names: "",
moduleId: "",
categoryId: "",
categorys: [],
categoryList: [],
pageShow: false,
areaId: ''
}
},
onLoad(option) {
this.$loading()
this.names = option.names;
this.areaId = option.areaId
this.getName();
if (option.names) {
uni.setNavigationBarTitle({
title: option.names
})
}
},
computed: {
active() {
return {
fontSize: "22px",
color: "#fff",
};
},
},
methods: {
getName() {
this.$instance.post("/app/appcontentmoduleinfo/listByName", null, {
params: {names: this.names}
}).then(res => {
if (res.data && res.data.length) {
this.categorys = res.data[0]["categoryList"];
this.moduleId = res.data[0]["id"];
if (res.data[0]["categoryList"]?.length) {
this.categoryId = res.data[0]["categoryList"][0]["id"];
}
this.getCategoryList();
} else {
this.$hideLoading()
}
})
},
tabChange(e) {
this.index = e
this.$nextTick(() => {
this.getCategoryList(this.categorys[e]["id"]);
})
},
getCategoryList(e) {
this.$instance.post("/app/appcontentinfo/list", null, {
params: {
moduleId: this.moduleId,
categoryId: e ? e : (this.categoryId ? this.categoryId : ''),
size: 10,
areaId: this.areaId ? this.areaId : ''
}
}).then(res => {
if (res?.data) {
this.categoryList = this.current > 1 ? [...this.categoryList, ...res.data.records] : res.data.records;
}
this.pageShow = true
this.$hideLoading()
})
},
},
onReachBottom() {
this.current++;
this.getCategoryList();
}
}
</script>
<style lang="scss" scoped>
.wrapper {
padding-top: 100px;
.list-wrap {
box-sizing: border-box;
padding: 32px;
.list-card {
width: 100%;
min-height: 100px;
background: #FFFFFF;
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.02);
border-radius: 16px;
box-sizing: border-box;
padding: 32px;
margin-bottom: 24px;
.header {
font-size: 36px;
font-weight: 600;
color: #333333;
line-height: 50px;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
.content-wrap {
display: flex;
gap: 4px;
flex-wrap: wrap;
margin-top: 24px;
position: relative;
.img {
width: 100%;
height: 350px;
}
.min-img {
width: 204px;
height: 204px;
}
.play-icon {
width: 80px;
height: 80px;
border-radius: 50%;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
}
.bottom {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 24px;
.left {
display: flex;
align-items: center;
font-size: 28px;
font-weight: 400;
color: #999999;
.tag {
width: 144px;
height: 48px;
background: #EEEEEE;
border-radius: 24px;
display: flex;
align-items: center;
justify-content: center;
font-size: 28px;
font-weight: 400;
color: #999999;
margin-right: 16px;
}
}
.right {
font-size: 28px;
font-weight: 400;
color: #999999;
display: flex;
align-items: center;
em {
font-style: normal;
color: #4181FF;
}
}
}
}
}
}
</style>

View File

@@ -0,0 +1,52 @@
<template>
<section class="contentDetail">
<ai-detail :detail="detail" :props="props"/>
</section>
</template>
<script>
import AiDetail from "../../components/AiDetail/AiDetail";
export default {
name: "contentDetail",
components: {AiDetail},
data() {
return {
detail: {title: "内容详情"},
props: {
count: "viewCount"
},
id: "",
}
},
onLoad({id}) {
if (id) {
this.id = id;
this.getDetail(id);
}
},
methods: {
getDetail(id) {
this.$instance.post(`/app/appcontentinfo/queryDetailById`, null, {
params: {id}
}).then(res => {
if (res?.data) {
this.detail = res.data
}
})
},
},
onShareAppMessage() {
return {
title: detail.title,
path: '/mods/AppContent/contentDetail?id=' + this.id
};
}
}
</script>
<style lang="scss" scoped>
.contentDetail {
}
</style>

View File

@@ -0,0 +1,104 @@
<template>
<section class="AppContentManager">
<ai-news-list :list="list" :loadmore="loadmore" @select="showDetail">
<template #header>
<div class="search-wrap">
<div class="search">
<u-icon name="search" color="rgba(255,255,255,0.5)" size="40"></u-icon>
<input placeholder="请输入需要搜索的内容" class="desc" placeholder-style="color:rgba(255,255,255,0.5);"
confirm-type="search" @change="onChange"></input>
</div>
</div>
</template>
</ai-news-list>
</section>
</template>
<script>
import {mapState} from "vuex";
import AiNewsList from "../../components/AiNewsList/AiNewsList";
export default {
name: "contentManager",
components: {AiNewsList},
computed: {
...mapState(['user']),
loadmore() {
return this.pages <= this.current ? 'loading ' : 'nomore'
}
},
data() {
return {
list: [],
current: 1,
pages: 0,
name: "",
}
},
onLoad(params) {
if (params.moduleId) {
this.moduleId = params.moduleId
this.getData(params.moduleId)
}
},
methods: {
onChange(val) {
this.current = 1;
this.getData(val.detail.value);
},
getData(title = "") {
let {current, search} = this
this.moduleId && this.$instance.post("/app/appcontentinfo/list", null, {
params: {moduleId: this.moduleId, current, size: 10, title}
}).then(res => {
if (res?.data) {
this.list = current > 1 ? [...this.list, ...res.data.records] : res.data.records
this.pages = res.data.pages
}
})
},
handleSelectArea(e) {
this.search.areaId = e.id
this.getData()
},
showDetail(row) {
uni.navigateTo({url: `./contentDetail?id=${row.id}`})
},
},
onReachBottom() {
this.current++;
this.getData()
},
}
</script>
<style lang="scss" scoped>
::v-deep .search-wrap {
width: 750px;
height: 112px;
box-sizing: border-box;
padding: 0 32px;
display: flex;
align-items: center;
justify-content: center;
background-color: #4181FF;
.search {
width: 100%;
height: 64px;
background: rgba(0, 0, 0, .2);
border-radius: 32px;
box-sizing: border-box;
padding: 0 32px;
display: flex;
align-items: center;
.desc {
flex: 1;
font-size: 28px;
color: #FFFFFF;
margin-left: 16px;
}
}
}
</style>

View File

@@ -0,0 +1,424 @@
<template>
<div class="page">
<div class="credit-points">
<div class="fixed-top">
<div class="header-tab" style="background-color:#197DF0;">
<div class="tab-item" v-for="(item, index) in tabList" :key="index" @click="tabClick(index)">{{ item }}<span
class="active-line" v-if="tabIndex == index"></span></div>
</div>
<div class="bg-blue"></div>
<div class="header-content">
<div class="item">
<div class="num color-5AAD6A">{{ tabIndex == 0 ? info['家庭积分'] || '0' : Number(info['个人积分']) || '0' }}</div>
<div class="label">{{ tabIndex == 0 ? '家庭' : '个人' }}总分</div>
</div>
<div class="item" v-if="tabIndex != 1">
<div class="num color-4185F5">{{ tabIndex == 0 ? info['剩余总分'] || '0' : info['个人积分'] || '0' }}</div>
<div class="label">剩余总分</div>
</div>
<div class="item">
<div class="num color-CD413A">{{ tabIndex == 0 ? info['家庭排行'] || '0' : info['个人排行'] || '0' }}</div>
<div class="label">{{ tabIndex == 0 ? '家庭' : '个人' }}排名</div>
</div>
<img src="https://cdn.cunwuyun.cn/dvcp/credit/head.png" alt="">
</div>
</div>
<div v-if="!showDetail" style="padding-top:432rpx;">
<div class="ranking-content" v-if="info['列表'] && info['列表'].length">
<div class="item" v-if="info['列表'].length > 1">
<img src="https://cdn.cunwuyun.cn/dvcp/credit/2.png" alt="" class="top-img">
<img :src="info['列表'][1].photo" alt="" class="user-img mar-b4" v-if="info['列表'][1].photo">
<div class="user-name-bg mar-b4" v-else>{{ $formatName(info['列表'][1].name) }}</div>
<p class="user-name mar-b8">{{ info['列表'][1].name }}{{ tabIndex == 0 ? '家' : '' }}</p>
<p class="item-num">{{ info['列表'][1].integral }}</p>
</div>
<div class="item-top item" v-if="info['列表'].length > 0">
<img src="https://cdn.cunwuyun.cn/dvcp/credit/1.png" alt="" class="top-img-one">
<img :src="info['列表'][0].photo" alt="" class="user-img mar-b4" v-if="info['列表'][0].photo">
<div class="user-name-bg mar-b4" v-else>{{ $formatName(info['列表'][0].name) }}</div>
<p class="user-name mar-b8">{{ info['列表'][0].name }}{{ tabIndex == 0 ? '家' : '' }}</p>
<p class="item-num">{{ info['列表'][0].integral }}</p>
</div>
<div class="item" v-if="info['列表'].length > 2">
<img src="https://cdn.cunwuyun.cn/dvcp/credit/3.png" alt="" class="top-img">
<img :src="info['列表'][2].photo" alt="" class="user-img mar-b4" v-if="info['列表'][2].photo">
<div class="user-name-bg mar-b4" v-else>{{ $formatName(info['列表'][2].name) }}</div>
<p class="user-name mar-b8">{{ info['列表'][2].name }}{{ tabIndex == 0 ? '家' : '' }}</p>
<p class="item-num">{{ info['列表'][2].integral }}</p>
</div>
</div>
<div class="ranking-list" v-if="info['列表'] && info['列表'].length">
<div class="item" v-for="(item, index) in info['列表']" :key="index" v-if="index > 2">
<span class="item-num">{{ index + 1 }}</span>
<img :src="item.photo" alt="" class="user-img mar-b4" v-if="item.photo">
<div class="user-name-bg mar-b4 mar-r24" v-else>{{ $formatName(item.name) }}</div>
<span class="item-name">{{ item.name }}{{ tabIndex == 0 ? '家' : '' }}</span>
<span class="item-point">{{ item.integral }}</span>
</div>
</div>
</div>
<div class="detail-content" v-if="showDetail && list.length">
<div class="title">积分明细</div>
<div class="item" v-for="(item, index) in list" :key="index">
<div class="item-info">
<p>{{ tabIndex == 0 ? item.residentName + ':' : '' }}{{ item.description }}</p>
<span>&nbsp;&nbsp;&nbsp;{{ item.doTime }}</span>
</div>
<div class="item-num" :class="'color-'+ (item.changeIntegral >= 0 ? 0 : 1)">
{{ item.changeIntegral > 0 ? '+' + item.changeIntegral : item.changeIntegral }}
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
name: "AppCreditPoints",
appName: "信用积分",
computed: {
...mapState(['user', 'token'])
},
data() {
return {
tabList: ['家庭积分', '个人积分'],
tabIndex: 0,
showDetail: false, //是否显示积分明细
info: {},
current: 1,
list: [],
areaId: ''
}
},
onLoad(options) {
if (uni.getStorageSync('areaId')) {
this.areaId = uni.getStorageSync('areaId')
} else {
this.areaId = this.$areaId
}
if (options.type == 'detail') {
this.showDetail = true
this.getList()
}
uni.setNavigationBarTitle({
title: options.title
})
this.getInfo()
},
methods: {
tabClick(index) {
this.tabIndex = index
this.getInfo()
this.getList()
},
// 积分排行
getInfo() {
this.info = {}
// var url = `/app/appresident/rank?id=00255e188d1225f3fe022cb4eed44a84&type=${this.tabIndex}` //积分排行
var url = `/app/appresident/rank?id=${this.user.residentId}&type=${this.tabIndex}&areaId=${this.areaId}` //积分排行
this.$instance.post(url).then(res => {
if (res.code === 0) {
this.info = res.data
}
})
},
// 积分明细列表
getList() {
// var url = `/app/appvillagerintegraldetail/IntegralList?residentId=00255e188d1225f3fe022cb4eed44a84&type=${this.tabIndex}&current=${this.current}&size=10` //积分明细
var url = `/app/appvillagerintegraldetail/IntegralList?residentId=${this.user.residentId}&type=${this.tabIndex}&current=${this.current}&size=10` //积分明细
this.$instance.post(url).then(res => {
if (res.code === 0) {
if (this.current > res.data.pages) {
return
}
const records = this.current > 1 ? [...this.list, ...res.data.records] : res.data.records;
this.list = records
}
})
},
},
onReachBottom() {
if (!this.showDetail) return
this.current = this.current + 1;
this.getList()
},
}
</script>
<style scoped lang="scss">
@import "../../common/common.scss";
.page {
width: 100%;
background-color: #f3f6f9;
.credit-points {
.bg-blue {
width: 100%;
height: 176px;
background-color: #197DF0;
}
.header-content {
width: 690px;
height: 256px;
background: #FFF;
border-radius: 16px;
margin: -130px 0 40px 30px;
padding: 100px 60px 40px 60px;
box-sizing: border-box;
display: flex;
justify-content: space-between;
position: relative;
.item {
text-align: center;
z-index: 99;
.num {
font-family: DIN;
font-size: 52px;
font-weight: bold;
line-height: 60px;
}
.label {
font-size: 28px;
font-family: PingFangSC-Regular, PingFang SC;
color: #999;
line-height: 40px;
margin-top: 10px;
}
.color-5AAD6A {
color: #5AAD6A;
}
.color-4185F5 {
color: #4185F5;
}
.color-CD413A {
color: #CD413A;
}
}
img {
position: absolute;
width: 360px;
height: 250px;
top: -40px;
right: 0;
}
}
.ranking-content {
padding: 94px 30px 0;
background-color: #fff;
.item {
display: inline-block;
width: 216px;
box-shadow: 0 4px 20px 0 rgba(0, 0, 0, 0.12);
border-radius: 12px;
padding: 40px 0 76px 0;
text-align: center;
box-sizing: border-box;
position: relative;
.user-name {
font-size: 30px;
font-family: PingFang-SC-Medium, PingFang-SC;
font-weight: 500;
color: #333;
line-height: 42px;
}
.item-num {
font-size: 46px;
font-weight: 6000;
color: #2C51CE;
line-height: 54px;
}
.top-img {
width: 100%;
height: 34px;
position: absolute;
top: -11px;
left: 0;
}
}
.item-top {
margin: -46px 20px 0;
.user-img {
width: 104px;
height: 104px;
}
.user-name-bg {
width: 104px;
height: 104px;
border-radius: 50%;
background-color: #4E8EEE;
font-size: 28px;
line-height: 104px;
text-align: center;
color: #fff;
}
.top-img-one {
width: 100%;
position: absolute;
top: -22px;
left: 0;
height: 46px;
}
}
}
.ranking-list {
background-color: #fff;
.item {
width: 100%;
height: 120px;
line-height: 120px;
background: #FFF;
padding: 0 64px;
box-sizing: border-box;
.item-num {
display: inline-block;
width: 68px;
color: #858594;
font-size: 28px;
}
.user-img {
margin-right: 24px;
vertical-align: middle;
}
.item-name {
color: #333;
font-size: 30px;
display: inline-block;
width: 240px;
}
.item-point {
display: inline-block;
width: 210px;
text-align: right;
font-size: 30px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333;
}
.mar-r24 {
margin-right: 24px;
}
}
}
.user-img {
width: 80px;
height: 80px;
border-radius: 50%;
}
.user-name-bg {
display: inline-block;
width: 80px;
height: 80px;
border-radius: 50%;
background-color: #4E8EEE;
font-size: 28px;
line-height: 80px;
text-align: center;
color: #fff;
}
.mar-b4 {
margin-bottom: 8px;
}
.mar-b8 {
margin-bottom: 16px;
}
.detail-content {
width: 690px;
background: #FFF;
border-radius: 16px;
margin: 432px 0 0 32px;
padding: 30px 30px 94px;
box-sizing: border-box;
.title {
font-size: 34px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333;
line-height: 48px;
margin-bottom: 30px;
}
.item {
padding: 34px 0 32px 0;
border-bottom: 2px solid #ddd;
display: flex;
.item-info {
width: 500px;
p {
word-break: break-all;
font-size: 32px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #333;
line-height: 44px;
}
span {
display: inline-block;
margin-top: 8px;
font-size: 24px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #999;
line-height: 34px;
}
}
.item-num {
width: calc(100% - 500px);
text-align: right;
font-size: 36px;
font-family: PingFangSC-Semibold, PingFang SC;
font-weight: 600;
line-height: 50px;
}
}
}
}
.color-0 {
color: #2C51CE !important;
}
.color-1 {
color: #E6736E !important;
}
.fixed-top {
z-index: 999;
}
}
</style>

View File

@@ -0,0 +1,70 @@
<template>
<div class="service-result">
<image :src="type === '0' ? '/static/img/service-success.png' : '/static/img/error.png'"/>
<h2>{{ type === '1' ? '领取失败!请联系管理员处理' : '提交成功!' }}</h2>
<div class="text" v-if="type === '0'">请等待信用好超市管理员与您联系</div>
<div class="service-btn" hover-class="text-hover" @click="back">确定</div>
</div>
</template>
<script>
export default {
data() {
return {
type: '0'
}
},
onLoad(query) {
this.type = query.type
},
methods: {
back() {
uni.navigateBack({
delta: 2
})
}
}
}
</script>
<style lang="scss" scoped>
.service-result {
min-height: 100vh;
padding-top: 96px;
text-align: center;
background: #fff;
box-sizing: border-box;
.service-btn {
width: 558px;
height: 88px;
line-height: 88px;
margin: 64px auto 0;
text-align: center;
background: #197DF0;
font-size: 36px;
color: #fff;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.02);
border-radius: 8px;
}
h2 {
margin-bottom: 8px;
color: #333333;
font-size: 36px;
font-weight: 600;
}
.text {
font-size: 32px;
color: #666666;
}
image {
width: 192px;
height: 192px;
}
}
</style>

View File

@@ -0,0 +1,243 @@
<template>
<div class="order">
<div class="order-info">
<h2>{{ userName }}</h2>
<span>剩余积分:{{ familyIntegral }}</span>
</div>
<image class="line" src="/static/img/line.png"/>
<div class="order-list">
<div class="order-item" v-for="(item, index) in goods" :key="index">
<image :src="item.photo[0].url"/>
<div class="order-item__right flex1">
<h2>{{ item.merchandiseName }}</h2>
<div class="order-item__right--info">
<span>{{ item.costIntegral }}</span>
<i>积分</i>
</div>
<div class="item-bottom">
<div></div>
<div class="item-bottom__right">
<span>x {{ item.num }}</span>
</div>
</div>
</div>
</div>
</div>
<div class="goods-footer">
<div class="goods-footer__bottom">
<div class="goods-footer__bottom__left">
<h3>{{ total }}件商品</h3>
<div class="goods-footer__bottom--middle">
<span>合计 </span>
<i>{{ money }}</i>
<em>积分</em>
</div>
</div>
<div class="goods-footer__bottom--btn" @click="submit" hover-class="text-hover">确认提交</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
total: 0,
money: 0,
goods: [],
memberId: '',
userName: '',
familyId: '',
familyIntegral: 0
}
},
onLoad(query) {
this.userName = query.userName
this.total = query.total
this.familyIntegral = query.familyIntegral
this.money = query.money
this.memberId = query.memberId
this.familyId = query.familyId
this.goods = JSON.parse(query.goods)
},
methods: {
submit() {
this.$loading()
this.$instance.post(`/app/appvillagerintegralshoporder/createOrderForWx`, {
memberId: this.memberId,
familyId: this.familyId,
orderIntegral: this.money,
shopId: this.goods[0].shopId,
merchandiseList: this.goods.map(item => {
return {
merchandiseId: item.id,
merchandiseNumber: item.num
}
})
}).then(res => {
if (res.code === 0) {
uni.$emit('update')
this.$linkTo('./result?type=0')
} else {
this.$linkTo('./result?type=1')
}
})
}
},
}
</script>
<style lang="scss" scoped>
.order {
min-height: 100%;
background: #fff;
.line {
width: 100%;
height: 8px;
}
.order-item {
display: flex;
padding: 28px 30px 44px;
.order-item__right--info {
display: flex;
align-items: baseline;
span {
margin-right: 8px;
color: #FA4A51;
font-size: 40px;
}
i {
color: #FA4A51;
font-size: 24px;
}
}
h2 {
margin-top: 2px;
margin-bottom: 30px;
color: #333333;
font-size: 30px;
text-align: justify;
}
& > image {
width: 192px;
height: 192px;
margin-right: 30px;
}
}
.order-list {
margin-top: 20px;
padding-bottom: 110px;
}
.order-info {
display: flex;
align-items: center;
justify-content: space-between;
height: 128px;
padding: 030px;
color: #333333;
font-size: 32px;
}
.goods-footer {
position: fixed;
left: 0;
bottom: 0;
z-index: 11;
width: 100%;
box-shadow: 0px -1px 4px 0px rgba(214, 214, 214, 0.5);
background: #fff;
.goods-footer__bottom--btn {
width: 212px;
height: 104px;
line-height: 104px;
font-size: 36px;
color: #fff;
text-align: center;
background: #197DF0;
}
.goods-footer__bottom__left {
display: flex;
align-items: center;
justify-content: space-between;
flex: 1;
padding: 032px h3 {
color: #F94246;
font-size: 32px;
}
.goods-footer__bottom--middle {
display: flex;
align-items: baseline;
span {
color: #F94246;
font-size: 32px;
}
i {
position: relative;
top: 2px;
margin-right: 6px;
color: #FA444B;
font-size: 40px;
}
em {
color: #F94246;
font-size: 24px;
}
}
}
.goods-footer__bottom {
display: flex;
align-items: center;
justify-content: space-between;
height: 104px;
}
}
.item-bottom {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 28px;
.item-bottom__right {
display: flex;
align-items: center;
color: #666;
}
image {
width: 40px;
height: 40px;
}
input {
width: 90px;
height: 60px;
padding: 020px;
margin: 010px;
background: #F6F6F6;
border-radius: 10px;
font-size: 26px;
color: #666;
}
}
}
</style>

View File

@@ -0,0 +1,450 @@
<template>
<div class="page">
<div class="supermarket">
<div class="fixed-top title" @click="$linkTo(`./system?areaName=${areaName}`)"
v-if="propAreaId == '341021104000'">{{ areaName }}信用好超市管理制度点击查看 >>
</div>
<div class="goods-list" v-if="numList.length"
:style="propAreaId == '341021104000' ? 'padding-top:80px' : 'padding-top: 0;'">
<div class="left">
<div
:class="numIndex == index ? 'item active' : 'item'"
v-for="(item, index) in numList"
:key="index"
@click="numClick(index)">
<i v-show="item.total > 0">{{ item.total }}</i>
{{ item.type }}分区
</div>
</div>
<div class="right">
<div class="item" v-for="(item, index) in goodsList[numIndex]" :key="index">
<img :src="item.photo[0].url" alt="">
<div class="item-info">
<p class="item-name">{{ item.merchandiseName }}</p>
<div class="item-point"><span class="num">{{ item.costIntegral }}</span>积分</div>
<div class="item-bottom">
<div></div>
<div class="item-bottom__right">
<image v-show="item.num > 0" @click="cut(numIndex, index)" src="/static/img/cut.png"/>
<input v-show="item.num > 0" v-model="item.num">
<image src="/static/img/add.png" @click="add(numIndex, index)"/>
</div>
</div>
</div>
</div>
</div>
</div>
<AiEmpty v-else/>
<div class="goods-footer" v-if="numList.length">
<div class="goods-footer__top">
<h2>{{ userInfo.familyName || user.nickName }}{{ userInfo.familyName ? '家' : '' }}</h2>
<span>剩余积分:{{ userInfo.familyIntegral || 0 }}</span>
</div>
<div class="goods-footer__bottom">
<div class="goods-footer__bottom__left">
<h3>{{ total }}件商品</h3>
<div class="goods-footer__bottom--middle">
<span>合计 </span>
<i>{{ money }}</i>
<em>积分</em>
</div>
</div>
<div class="goods-footer__bottom--btn" @click="toOrder" hover-class="text-hover">去结算</div>
</div>
</div>
</div>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
name: 'supermarket',
data() {
return {
numList: [],
numIndex: 0,
goodsList: [],
areaId: '',
userInfo: {},
areaName: '',
propAreaId: ''
}
},
computed: {
...mapState(['global', 'user', 'token']),
total() {
let total = 0
if (!this.numList.length) {
return total
}
this.numList.forEach(item => {
total = item.total + total
})
return total
},
money() {
let money = 0
if (!this.goodsList.length) {
return money
}
this.goodsList.forEach(arr => {
arr.forEach(item => {
money = money + Number(item.num) * item.costIntegral
})
})
return money
}
},
onLoad() {
this.propAreaId = this.$areaId
uni.$on('update', () => {
this.getInfo()
})
if (uni.getStorageSync('areaId')) {
this.areaId = uni.getStorageSync('areaId')
}
this.getUserInfo()
this.getInfo()
},
onShow() {
this.getUserInfo()
},
methods: {
getInfo() {
this.$instance.post(`/admin/area/queryAreaByAreaid?id=${this.areaId}`, null, {}).then(res => {
if (res.code === 0) {
if (res.data) {
this.areaName = res.data.name
this.getList()
}
}
})
},
getUserInfo() {
this.$instance.post(`/app/appresident/queryFamilyById?id=${this.user.residentId}`, null, {}).then(res => {
if (res.code === 0) {
this.userInfo = res.data
}
})
},
toOrder() {
if (this.user.status == 0) {
if (!this.user.phone) {
return this.$linkTo('/pages/phone/bingPhoneNumber?from=auth')
} else {
return this.$linkTo('/pages/auth/authenticationInfo')
}
}
if (!this.total) {
return this.$toast('请选择商品')
}
if (this.money > this.userInfo.familyIntegral) {
return this.$toast('积分不足')
}
let goods = []
this.goodsList.forEach(arr => {
arr.forEach(item => {
if (item.num) {
goods.push(item)
}
})
})
this.$linkTo(`./submitOrder?familyId=${this.userInfo.familyId}&userName=${this.userInfo.familyName}&memberId=${this.userInfo.memberId}&goods=${JSON.stringify(goods)}&total=${this.total}&money=${this.money}&familyIntegral=${this.userInfo.familyIntegral}`)
},
getList() {
this.$instance.post(`/app/appvillagerintegralmerchandise/listByIntegral?areaId=${this.areaId}`, null, {}).then(res => {
if (res.code === 0) {
if (res.data) {
this.numList = Object.keys(res.data).map(item => {
return {
type: item,
total: 0
}
})
this.goodsList = Object.values(res.data).map((item) => {
item.map((items) => {
items.num = 0
items.photo = JSON.parse(items.photo)
return items
})
return item
})
}
}
})
},
add(index, i) {
this.$set(this.goodsList[index][i], 'num', Number(this.goodsList[index][i].num) + 1)
let total = 0
this.goodsList[index].forEach(item => {
total = total + item.num
})
this.$set(this.numList[index], 'total', total)
},
cut(index, i) {
this.$set(this.goodsList[index][i], 'num', Number(this.goodsList[index][i].num) - 1)
let total = 0
this.goodsList[index].forEach(item => {
total = total + item.num
})
this.$set(this.numList[index], 'total', total)
},
numClick(index) {
this.numIndex = index
}
},
}
</script>
<style scoped lang="scss">
@import "../../common/common.scss";
.item-bottom {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 28px;
.item-bottom__right {
display: flex;
align-items: center;
height: 60px;
}
image {
width: 27px;
height: 27px;
}
input {
width: 90px;
height: 60px;
padding: 020px;
margin: 010px;
background: #F6F6F6;
border-radius: 10px;
font-size: 26px;
color: #666;
text-align: center;
}
}
.goods-footer {
position: fixed;
left: 0;
bottom: 0;
z-index: 111;
width: 100%;
background: #fff;
.goods-footer__top {
display: flex;
align-items: center;
justify-content: space-between;
height: 80px;
padding: 030px;
background: #EFF4FF;
color: #333333;
font-size: 32px;
}
.goods-footer__bottom--btn {
width: 212px;
height: 104px;
line-height: 104px;
font-size: 36px;
color: #fff;
text-align: center;
background: #197DF0;
}
.goods-footer__bottom__left {
display: flex;
align-items: center;
justify-content: space-between;
flex: 1;
padding: 032px h3 {
color: #F94246;
font-size: 32px;
}
.goods-footer__bottom--middle {
display: flex;
align-items: baseline;
span {
color: #F94246;
font-size: 32px;
}
i {
position: relative;
top: 2px;
margin-right: 12px;
color: #FA444B;
font-size: 40px;
}
em {
color: #F94246;
font-size: 24px;
}
}
}
.goods-footer__bottom {
display: flex;
align-items: center;
justify-content: space-between;
height: 104px;
}
}
.page {
width: 100%;
background-color: #fff;
.supermarket {
height: 100%;
overflow-y: hidden;
.title {
width: 100%;
height: 80px;
line-height: 80px;
background: #EFF4FF;
padding-left: 30px;
color: #3A7EE2;
font-size: 28px;
}
.goods-list {
// padding-top:80px; padding-bottom: 184px;
height: 100%;
box-sizing: border-box;
overflow-y: hidden;
.left {
width: 168px;
height: 100%;
overflow-y: scroll;
overflow-x: hidden;
float: left;
background: #FAF9FB;
.item {
display: flex;
align-items: center;
justify-content: center;
position: relative;
width: 100%;
height: 104px;
line-height: 1.1;
border-bottom: 2px solid #D8E5FF;
text-align: center;
color: #333;
font-size: 28px;
border-left: 6px solid #FAF9FB;
i {
position: absolute;
right: 8px;
top: 8px;
height: 28px;
line-height: 28px;
padding: 012px;
color: #fff;
font-size: 20px;
border-radius: 13px;
background: #FB4E44;
}
}
.active {
border-left: 6px solid #1D58FE;
background: linear-gradient(270deg, #FFFFFF 0%, #FFFFFF 77%, #E7EAFA 100%);
}
}
.right {
float: left;
width: calc(100% - 168px);
height: 100%;
overflow-y: scroll;
.item {
width: 100%;
padding: 28px 30px 44px;
box-sizing: border-box;
img {
width: 192px;
height: 192px;
border: 2px solid #D7D5D5;
}
.item-info {
display: inline-block;
width: 276px;
padding-left: 30px;
vertical-align: top;
.item-name {
width: 100%;
word-break: break-all;
line-height: 42px;
margin-bottom: 30px;
font-size: 30px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
}
.item-point {
color: #FA4A51;;
font-size: 24px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #FA4A51;
line-height: 34px;
.num {
font-size: 40px;
font-family: PingFangSC-Semibold, PingFang SC;
font-weight: 600;
margin-right: 8px;
}
}
}
}
}
}
}
}
</style>

View File

@@ -0,0 +1,76 @@
<template>
<div class="page">
<div class="system">
<div class="title">信用好超市管理制度</div>
<p class="mini-title underline">为规范信用好超市管理流程保证信用好超市正常运行结合{{ areaName }}实际特制定本制度</p>
<p class="text">1每月15日30日各开放1次时间分别为<span class="underline">上午9:00-11:00下午14:30-16:30</span></p>
<p class="text">2信用好超市每月清点兑换物品及时补充兑换货物确保货物充足品类丰富</p>
<p class="text">3本超市管理人员应严格按照信用券兑换标准执行兑换并及时记录信用户的积分兑换记录</p>
<p class="text">4超市开放时间段管理员必须在岗在位热情开展兑换服务确保公平公正严禁态度蛮横弄虚作假</p>
<p class="text">5信用户凭借信用券根据自己的实际需要在本超市内自主选择所需的物品并由管理员登记确认</p>
<p class="text">6信用好超市内环境卫生干净整洁超市内禁止吸烟等其他不文明行为</p>
</div>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
name: "my",
computed: {
...mapState(['user', 'token'])
},
data() {
return {
areaName: ''
}
},
onLoad(options) {
this.areaName = options.areaName
},
}
</script>
<style scoped lang="scss">
@import "../../common/common.scss";
.page {
width: 100%;
background-color: #fff;
.system {
padding: 030px;
.title {
width: 100%;
font-size: 34px;
font-family: PingFangSC-Semibold, PingFang SC;
font-weight: 600;
color: #333;
line-height: 28px;
text-align: center;
padding: 40px 0;
}
.mini-title {
font-size: 30px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #222;
line-height: 48px;
margin-bottom: 32px;
width: 100%;
word-break: break-all;
}
.text {
width: 100%;
font-size: 30px;
font-family: PingFangSC-Regular, PingFang SC;
color: #333;
line-height: 40px;
margin-bottom: 20px;
word-break: break-all;
}
}
}
</style>

View File

@@ -0,0 +1,118 @@
<template>
<div class="page">
<template v-if="detail">
<header>{{ detail.areaName }}</header>
<div class="address">{{ detail.address }}</div>
<div class="desc">
<u-parse :html="detail.content"></u-parse>
</div>
</template>
<AiEmpty v-else></AiEmpty>
<div class="btn" @click="cancel" v-if="detail">
<div>解除入驻</div>
</div>
</div>
</template>
<script>
import {mapState} from "vuex";
export default {
name: "AppHometown",
appName: "我的家乡",
data() {
return {
detail: null,
}
},
onLoad() {
this.getDetail();
},
computed: {
...mapState(["user"])
},
methods: {
getDetail() {
if (!this.user.homeArea) return
this.$instance.post("/app/appcountrysidetourism/queryDetailByAreaIdForWX", null, {
params: {areaId: this.user.homeArea}
}).then(res => {
if (res?.data) {
this.detail = res.data;
}
})
},
cancel() {
this.$instance.post("/app/appwechatuser/unbindHome", {id: this.user.id}).then(res => {
if (res.code == 0) {
this.$u.toast('解除入驻成功')
setTimeout(() => {
uni.navigateBack()
}, 600)
}
})
}
},
}
</script>
<style lang="scss" scoped>
.page {
background-color: #fff;
box-sizing: border-box;
padding: 32px;
position: relative;
header {
font-size: 48px;
font-weight: 600;
color: #333333;
line-height: 66px;
}
.address {
font-size: 30px;
font-weight: 400;
color: #999999;
line-height: 42px;
margin-top: 16px;
}
.desc {
font-size: 36px;
font-weight: 400;
color: #333333;
line-height: 64px;
margin-top: 64px;
padding-bottom: 120px;
}
.btn {
width: 100%;
background-color: #fff;
position: fixed;
left: 50%;
bottom: 0;
padding-bottom: 16px;
z-index: 999;
transform: translateX(-50%);
div {
width: 686px;
height: 88px;
background: #FFFFFF;
border-radius: 16px;
border: 1px solid #FF4466;
font-size: 34px;
font-weight: 600;
color: #FF4466;
display: flex;
align-items: center;
justify-content: center;
margin-left: 32px;
}
}
}
</style>

352
src/mods/AppJob/AppJob.vue Normal file
View File

@@ -0,0 +1,352 @@
<template>
<div class="wrapper">
<div class="search-wrap">
<div class="left" @click="show=true">
<span>{{ search.typeName ? search.typeName : "全部" }}</span>
<u-icon name="arrow-down" color="#ffffff" size="20"></u-icon>
</div>
<div class="right">
<u-icon name="search" size="32" color="rgba(255,255,255,0.5)" :custom-style="{marginRight:'8px'}"></u-icon>
<input placeholder="请输入需要搜索的内容" style="flex: 1;color:#fff;" confirm-type="search"
placeholder-style="color:rgba(255,255,255,0.5)" v-model="search.title"
@confirm="current=1;getList()"></input>
</div>
</div>
<div class="job-list" v-if="list.length">
<header>
<span>招工就业列表</span>
<div class="right">
<em>{{ total }}</em>个职位
</div>
</header>
<div class="card" v-for="(item,index) in list" :key="index">
<template v-if="item.type == 1">
<div class="top" @click="toDetail(0,item)">
<div class="title">{{ item.title }}</div>
<div class="job-content">{{ item.remark || "" }}</div>
<div class="photo">
<img
:src="photo.url"
alt="" v-for="photo in item.files" :key="photo.id">
</div>
<div class="info">
<div class="tag">个人求职</div>
<div class="date">{{ item.createTime && item.createTime.slice(0, 16) }}</div>
</div>
</div>
<div class="bottom">
<span class="name">{{ item.linkName }}</span>
<div class="right" @click="phone(item)">
<u-icon name="phone-fill" size="36" color="#4181FF" :custom-style="{marginRight:'8px'}"></u-icon>
{{ item.linkPhone }}
</div>
</div>
</template>
<template v-if="item.type == 0">
<div class="top" @click="toDetail(1,item)">
<div class="post-info">
<div class="post">{{ item.title }}</div>
<div class="salary">{{ item.salary }}</div>
</div>
<div class="require">{{ item.remark || "" }}</div>
<div class="info">
<div class="tag" style="background-color:#1AAAFF">企业招工</div>
<div class="date">{{ item.createTime && item.createTime.slice(0, 16) }}</div>
</div>
</div>
<div class="bottom">
<div class="company">{{ item.companyName }}</div>
</div>
</template>
</div>
</div>
<AiEmpty v-else></AiEmpty>
<div class="btn-wrapper">
<div class="btn" @click="$linkTo('./pubJob')" hover-class="text-hover">我要找工作</div>
</div>
<u-select v-model="show" :list="selectList" @confirm="onConfirm"></u-select>
</div>
</template>
<script>
export default {
name: "AppJob",
appName: "招工就业",
data() {
return {
show: false,
current: 1,
list: [],
total: 0,
search: {
title: "",
type: "",
typeName: "",
}
}
},
computed: {
selectList() {
return [{
value: '',
label: '全部'
}, {
value: '0',
label: '企业招工'
},
{
value: '1',
label: '个人求职'
}];
}
},
methods: {
preview(index) {
this.$previewImage(this.list, index, "url");
},
phone({linkPhone: phoneNumber}) {
uni.makePhoneCall({phoneNumber});
},
onConfirm(val) {
this.search.typeName = val[0].label;
this.search.type = val[0].value;
this.current = 1;
this.getList();
},
getList() {
this.$instance.post("/app/appjob/list", null, {
params: {
...this.search,
current: this.current
}
}).then(res => {
if (res?.data) {
this.list = this.current > 1 ? [...this.list, ...res.data.records] : res.data.records;
this.total = res.data.total;
}
})
},
toDetail(val, {id}) {
uni.navigateTo({
url: !!val ? `./compJob?id=${id}` : `./persJob?id=${id}`
})
}
},
onShow() {
this.current = 1;
this.getList();
},
onReachBottom() {
this.current++;
this.getList();
}
}
</script>
<style lang="scss" scoped>
.wrapper {
padding-top: 124px;
}
.search-wrap {
position: fixed;
left: 0;
top: 0;
z-index: 11;
width: 100%;
height: 124px;
background: #4181FF;
box-sizing: border-box;
padding: 0 32px;
display: flex;
align-items: center;
box-sizing: border-box;
.left {
display: flex;
align-items: center;
& > span {
font-size: 40px;
font-weight: 500;
color: #FFFFFF;
margin-right: 16px;
}
}
.right {
flex: 1;
height: 64px;
background: rgba(0, 0, 0, .2);
border-radius: 32px;
margin-left: 32px;
box-sizing: border-box;
padding: 0 32px;
display: flex;
align-items: center;
}
}
.job-list {
box-sizing: border-box;
padding: 0 32px 156px;
& > header {
box-sizing: border-box;
padding: 48px 0 32px;
display: flex;
align-items: center;
justify-content: space-between;
& > span {
font-size: 38px;
font-weight: 600;
color: #333333;
}
.right {
font-size: 28px;
font-weight: 400;
color: #666666;
display: flex;
align-items: center;
& > em {
color: #4181FF;
}
}
}
.card {
background: #FFFFFF;
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.02);
border-radius: 16px;
margin-bottom: 24px;
.top {
box-sizing: border-box;
padding: 32px;
border-bottom: 1px solid #DDDDDD;
.title {
font-size: 36px;
font-weight: 600;
color: #333333;
line-height: 50px;
margin-bottom: 24px;
}
.job-content {
font-size: 32px;
font-weight: 400;
color: #999999;
line-height: 44px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
margin-bottom: 24px;
}
.photo {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 4px;
& > img {
width: 204px;
height: 204px;
}
}
.info {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 24px;
.tag {
width: 144px;
height: 48px;
background: #42D784;
border-radius: 24px;
font-size: 28px;
font-weight: 400;
color: #FFFFFF;
line-height: 50px;
text-align: center;
}
.date {
font-size: 28px;
font-weight: 400;
color: #999999;
}
}
.post-info {
display: flex;
align-items: center;
justify-content: space-between;
.post {
font-size: 36px;
font-weight: 600;
color: #333333;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-right: 16px;
}
.salary {
font-size: 36px;
font-weight: 600;
color: #FF3521;
}
}
.require {
font-size: 32px;
font-weight: 400;
color: #999999;
margin-top: 24px;
}
}
.bottom {
height: 104px;
display: flex;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
padding: 0 32px;
.name {
font-size: 28px;
font-weight: 400;
color: #333333;
}
.right {
display: flex;
align-items: center;
font-size: 28px;
font-weight: 400;
color: #4181FF;
}
.company {
font-size: 28px;
font-weight: 400;
color: #333333;
line-height: 40px;
}
}
}
}
</style>

150
src/mods/AppJob/compJob.vue Normal file
View File

@@ -0,0 +1,150 @@
<template>
<div class="wrapper">
<div class="card">
<div class="post-info">
<div class="post-name">
<span>{{ detail.title }}</span>
<span>{{ detail.salary }}</span>
</div>
<p>{{ detail.education }} | {{ detail.gender }} | {{ detail.age }}</p>
</div>
<div class="form">
<div class="label">招聘企业</div>
<div class="value">{{ detail.companyName }}</div>
</div>
<div class="form">
<div class="label">招聘联系人</div>
<div class="value">{{ detail.linkName }}</div>
</div>
<div class="form">
<div class="label">联系方式</div>
<div class="value phone" @click="phone">
<u-icon name="phone-fill" color="#4181FF" size="32" :custom-stype="{marginRight:'8px'}"></u-icon>
{{ detail.linkPhone }}
</div>
</div>
<template v-if="detail.remark">
<header>岗位要求</header>
<div class="post-require">{{ detail.remark }}
</div>
</template>
</div>
</div>
</template>
<script>
export default {
name: "compJob",
data() {
return {
id: null,
detail: {},
}
},
onLoad({id}) {
this.id = id;
this.getDetail();
},
methods: {
phone() {
uni.makePhoneCall({phoneNumber: this.detail.linkPhone});
},
getDetail() {
this.$instance.post("/app/appjob/detail", null, {
params: {id: this.id}
}).then(res => {
if (res?.data) {
this.detail = res.data;
}
})
}
},
onShareAppMessage() {
return {
title: "企业招工",
path: "/mods/AppJob/compJob?id=" + this.id
}
}
}
</script>
<style lang="scss" scoped>
.card {
padding: 32px 0 32px 32px;
background-color: #ffffff;
.post-info {
padding-right: 32px;
.post-name {
display: flex;
justify-content: space-between;
line-height: 56px;
& > span:first-child {
font-size: 40px;
font-weight: 600;
color: #333333;
}
& > span:last-child {
font-size: 36px;
font-weight: 600;
color: #FF3521;
flex-shrink: 0;
}
}
& > p {
font-size: 32px;
font-weight: 400;
color: #999999;
margin: 16px 0 32px;
}
}
.form {
height: 112px;
background: #FFFFFF;
border-bottom: 1px solid #DDDDDD;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid #DDDDDD;
padding-right: 32px;
.label {
font-size: 32px;
font-weight: 400;
color: #999999;
}
.value {
font-size: 32px;
font-weight: 400;
color: #333333;
}
.phone {
font-size: 28px;
color: #4181FF;
}
}
header {
font-size: 38px;
font-weight: 600;
color: #333333;
padding: 32px 0;
}
.post-require {
font-size: 32px;
font-weight: 400;
color: #333333;
line-height: 56px;
padding-right: 20px;
}
}
</style>

155
src/mods/AppJob/persJob.vue Normal file
View File

@@ -0,0 +1,155 @@
<template>
<div class="padding">
<div class="card">
<div class="post-info">{{ detail.title }}
</div>
<div class="date">{{ detail.createTime }}</div>
<div class="form border">
<div class="label">求职联系人</div>
<div class="value">{{ detail.linkName }}</div>
</div>
<div class="form border">
<div class="label">联系方式</div>
<div class="value phone" @click="phone">
<u-icon name="phone-fill" color="#4181FF" size="32" :custom-stype="{marginRight:'8px'}"></u-icon>
{{ detail.linkPhone }}
</div>
</div>
<div class="form">
<div class="label">图片</div>
</div>
<div class="photo border">
<img :src="item.url" alt=""
v-for="(item,index) in detail.files" :key="index" @click="preview(index)">
</div>
<header>详细描述</header>
<div class="post-require">{{ detail.remark }}
</div>
</div>
</div>
</template>
<script>
export default {
name: "persJob",
data() {
return {
id: null,
detail: {},
}
},
onLoad({id}) {
this.id = id;
this.getDetail();
},
methods: {
preview(index) {
this.$previewImage(this.detail.files, index, "url");
},
phone() {
uni.makePhoneCall({phoneNumber: this.detail.linkPhone});
},
getDetail() {
this.$instance.post("/app/appjob/detail", null, {
params: {id: this.id}
}).then(res => {
if (res?.data) {
this.detail = res.data;
}
})
}
},
onShareAppMessage() {
return {
title: "个人求职",
path: "/mods/AppJob/persJob?id=" + this.id
}
}
}
</script>
<style lang="scss" scoped>
.padding {
min-height: 100%;
background-color: #ffffff;
.card {
padding: 32px 0 32px 32px;
background-color: #ffffff;
.post-info {
font-size: 40px;
font-weight: 600;
color: #333333;
line-height: 56px;
padding-right: 32px;
}
.date {
font-size: 32px;
font-weight: 400;
color: #999999;
margin: 16px 0 32px;
}
.form {
height: 112px;
background: #FFFFFF;
display: flex;
align-items: center;
justify-content: space-between;
padding-right: 32px;
.label {
font-size: 32px;
font-weight: 400;
color: #999999;
}
.value {
font-size: 32px;
font-weight: 400;
color: #333333;
}
.phone {
font-size: 28px;
color: #4181FF;
}
}
.border {
border-bottom: 1px solid #DDDDDD;
}
.photo {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 4px;
padding-bottom: 48px;
& > img {
width: 225px;
height: 225px;
}
}
header {
font-size: 38px;
font-weight: 600;
color: #333333;
padding: 32px 0;
}
.post-require {
font-size: 32px;
font-weight: 400;
color: #333333;
line-height: 56px;
padding-right: 20px;
}
}
}
</style>

159
src/mods/AppJob/pubJob.vue Normal file
View File

@@ -0,0 +1,159 @@
<template>
<div class="wrapper">
<div class="card">
<div class="form">
<em>*</em>
<label>标题</label>
</div>
<u-input type="textarea" trim placeholder="请输入标题" maxlength="100" v-model="form.title"
placeholder-style="color: #999999;font-size: 17px;font-weight:normal;"
:custom-style="{color:'#333',fontSize:'17px',paddingLeft:'12px'}"/>
<div class="form border-top">
<em>*</em>
<label>详细描述</label>
</div>
<u-input type="textarea" trim placeholder="请输入详细描述信息…" maxlength="500" v-model="form.remark"
placeholder-style="color: #999999;font-size: 17px;font-weight:normal;"
:custom-style="{color:'#333',fontSize:'17px',paddingLeft:'12px'}"/>
</div>
<div class="card" style="padding-bottom: 20px">
<div class="form">
<label>图片上传
<span>(最多9张)</span>
</label>
</div>
<AiUploader :limit="9" v-model="form.files"></AiUploader>
</div>
<div class="card">
<div class="form border">
<em>*</em>
<label>联系人</label>
<div class="right">
<u-input trim placeholder="请输入" input-align="right"
placeholder-style="color:#999;font-size: 17px;font-weight:normal;" v-model="form.linkName"
:custom-style="{fontWeight:600,color:'#333',fontSize:'17px'}"></u-input>
</div>
</div>
<div class="form">
<em>*</em>
<label>联系方式</label>
<div class="right">
<u-input trim placeholder="请输入" input-align="right"
placeholder-style="color:#999;font-size: 17px;font-weight:normal;" v-model="form.linkPhone"
:custom-style="{fontWeight:600,color:'#333',fontSize:'17px'}"></u-input>
</div>
</div>
</div>
<div class="btn-wrapper">
<div class="btn" @click="submit" hover-class="text-hover">提交</div>
</div>
</div>
</template>
<script>
import AiUploader from '../../components/AiUploader/AiUploader'
export default {
name: "pubJob",
components: {AiUploader},
data() {
return {
form: {
title: "",
remark: "",
files: [],
linkName: "",
linkPhone: "",
type: 1,
},
flag: false
}
},
methods: {
submit() {
if (!!!this.form.title) return this.$u.toast("请输入标题");
if (!!!this.form.remark) return this.$u.toast("请输入详细描述");
if (!!!this.form.linkName) return this.$u.toast("请输入联系人");
if (!!!this.form.linkPhone) return this.$u.toast("请输入联系方式");
if (this.flag) return
this.flag = true
this.$loading()
this.$instance.post("/app/appjob/addOrUpdate", {
...this.form
}).then(res => {
this.$hideLoading()
this.flag = false
if (res.code == 0) {
this.$u.toast("提交成功");
setTimeout(_ => {
uni.navigateBack();
}, 500)
}
})
}
},
}
</script>
<style lang="scss" scoped>
.wrapper {
padding-bottom: 150px;
}
.card {
box-sizing: border-box;
padding-left: 32px;
background-color: #fff;
margin-bottom: 24px;
.form {
height: 112px;
background: #FFFFFF;
display: flex;
align-items: center;
& > em {
width: 16px;
height: 44px;
font-weight: 400;
color: #FF4466;
line-height: 54px;
font-style: normal;
margin-right: 8px;
}
& > label {
font-size: 32px;
font-weight: 600;
color: #666666;
& > span {
font-size: 28px;
font-weight: 400;
color: #999999;
}
}
.right {
flex: 1;
display: flex;
align-items: center;
flex-direction: row-reverse;
margin-right: 32px;
.value {
font-size: 34px;
font-weight: 600;
color: #333333;
}
}
}
.border-top {
border-top: 1px solid #DDDDDD;
}
.border {
border-bottom: 1px solid #DDDDDD;
}
}
</style>

View File

@@ -0,0 +1,216 @@
<template>
<div class="wrapper padding" v-if="pageShow">
<template v-if="list.length">
<header>
<span>婚丧嫁娶列表</span>
<div class="total">
<em>{{ list.length }}</em>
</div>
</header>
<div class="card" v-for="item in list" :key="item.id">
<div class="item">
<span class="label">事主姓名</span>
<span class="value">{{ item.name }}</span>
</div>
<div class="item">
<span class="label">联系方式</span>
<span class="value">{{ item.phone }}</span>
</div>
<div class="item">
<span class="label">上报时间</span>
<span class="value">{{ item.createTime }}</span>
</div>
<div class="item">
<span class="label">上报地点</span>
<span class="value">{{ item.address }}</span>
</div>
<div class="item" v-if="item.content.trim().length">
<span class="label">上报内容</span>
<span class="value">{{ item.content || '' }}</span>
</div>
<div class="tag" :style="{backgroundColor:$dict.getColor('marriageType',item.type)}">
{{ $dict.getLabel('marriageType', item.type) }}
</div>
<u-icon name="more-dot-fill" size="28" color="#999999" :custom-style="customStyle" @click="handleDel(item)"
v-if="item.openId == userInfo.openId"></u-icon>
</div>
</template>
<AiEmpty v-else/>
<div class="btn-wrapper">
<div class="btn" @click="suport" hover-class="text-hover">我要上报</div>
</div>
</div>
</template>
<script>
export default {
name: "AppMarFuneral",
appName: "婚丧嫁娶",
data() {
return {
current: 1,
pageShow: false,
list: [],
userInfo: {},
}
},
computed: {
customStyle() {
return {
position: "absolute",
top: "16px",
right: "24px",
transform: "rotate(90deg)"
};
},
},
onLoad() {
this.$loading()
this.userInfo = uni.getStorageSync("userInfo");
this.$dict.load("marriageType").then(() => {
this.getList()
})
uni.$on('update', () => {
this.current = 1
this.getList()
})
},
methods: {
handleDel({id}) {
uni.showModal({
title: "提示",
content: "是否确定要删除?",
success: ret => {
if (ret.confirm) {
this.$instance.post("/app/appmarriagefuneralinfo/delete", null, {
params: {ids: id}
}).then(res => {
if (res.code == 0) {
this.$u.toast("删除成功");
this.getList();
}
})
}
}
})
},
getList() {
this.$instance.post("/app/appmarriagefuneralinfo/list", null, {
params: {
current: this.current,
size: 10,
}
}).then(res => {
if (res?.data) {
this.list = this.current > 1 ? [...this.list, ...res.data.records] : res.data.records;
this.$nextTick(() => {
this.pageShow = true
})
}
this.$hideLoading()
}).catch(() => {
this.$hideLoading()
})
},
suport() {
uni.navigateTo({
url: "./marAdd"
})
}
},
onReachBottom() {
this.current++;
this.getList();
}
}
</script>
<style lang="scss" scoped>
.padding {
box-sizing: border-box;
padding: 48px 32px 156px;
header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 44px;
& > span {
font-size: 38px;
font-weight: 600;
color: #333333;
}
.total {
margin-left: auto;
font-size: 28px;
font-weight: 400;
color: #666666;
display: flex;
align-items: center;
& > em {
color: #4181FF;
}
}
}
.card {
min-height: 308px;
background: #FFFFFF;
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.02);
border-radius: 16px;
box-sizing: border-box;
padding: 32px;
display: flex;
flex-direction: column;
justify-content: space-between;
position: relative;
margin-bottom: 24px;
.item {
display: flex;
margin-bottom: 8px;
.label {
font-size: 26px;
font-weight: 400;
color: #999999;
flex-shrink: 0;
line-height: 36px;
}
.value {
font-size: 26px;
font-weight: 400;
color: #333333;
margin-left: 32px;
line-height: 36px;
}
}
.tag {
width: 70px;
height: 44px;
background: #FF883C;
border-radius: 8px;
font-size: 26px;
line-height: 40px;
font-weight: 400;
color: #FFFFFF;
text-align: center;
margin-top: 24px;
}
}
}
</style>

View File

@@ -0,0 +1,175 @@
<template>
<div class="wrapper">
<div class="card">
<div class="form">
<em>*</em>
<label>类型</label>
<div class="right" @click="show=true">
<u-icon name="arrow-right" color="#999999" size="28"></u-icon>
<span class="value" style="color: #999999;font-weight:normal;" v-if="!form.typeName">请选择</span>
<span class="value" style="color: #333333;font-weight:normal;" v-else>{{ form.typeName }}</span>
</div>
</div>
</div>
<div class="card">
<div class="form border">
<em>*</em>
<label>事主姓名</label>
<div class="right">
<u-input trim placeholder="请输入" input-align="right" v-model="form.name"
placeholder-style="color:#999;font-size: 16px;"></u-input>
</div>
</div>
<div class="form border">
<em>*</em>
<label>联系方式</label>
<div class="right">
<u-input trim placeholder="请输入" input-align="right" v-model="form.phone"
placeholder-style="color:#999;font-size: 16px;"></u-input>
</div>
</div>
<div class="form">
<em>*</em>
<label>活动地点</label>
<div class="right">
<u-input trim placeholder="请输入" input-align="right" v-model="form.address"
placeholder-style="color:#999;font-size: 16px;" style="flex: 1;margin-left: 16px;"></u-input>
</div>
</div>
</div>
<div class="card">
<div class="form">
<em></em>
<label>详细描述</label>
</div>
<u-input type="textarea" trim v-model="form.content" placeholder="请输入详细描述信息…" maxlength="500"
placeholder-style="color: #999999;font-size: 15px;"/>
</div>
<div class="card" style="padding-bottom: 20px">
<div class="form">
<label>图片上传
<span>(最多9张)</span>
</label>
</div>
<AiUploader :limit="9" v-model="form.files"></AiUploader>
</div>
<div class="btn-wrapper">
<div class="btn" @click="submit" hover-class="text-hover">提交</div>
</div>
<u-select v-model="show" :list="$dict.getDict('marriageType')" value-name="dictValue"
label-name="dictName" @confirm="confirm"></u-select>
</div>
</template>
<script>
import AiUploader from '../../components/AiUploader/AiUploader'
export default {
name: "marAdd",
components: {AiUploader},
data() {
return {
form: {
type: "",
typeName: "",
name: "",
phone: "",
address: "",
content: "",
personType: 0,
files: [],
},
show: false,
flag: false
}
},
methods: {
submit() {
if (!!!this.form.typeName) return this.$u.toast("请选择类型");
if (!!!this.form.name) return this.$u.toast("请输入事主姓名");
if (!!!this.form.phone) return this.$u.toast("请输入联系方式");
if (!!!this.form.address) return this.$u.toast("请输入活动地点");
if (this.flag) return
this.flag = true
this.$loading()
this.$instance.post("/app/appmarriagefuneralinfo/addOrUpdate", {
...this.form
}).then(res => {
this.$hideLoading()
this.flag = false
if (res.code == 0) {
uni.$emit('update')
this.$u.toast("提交成功");
setTimeout(_ => {
uni.navigateBack();
}, 500)
}
})
},
confirm(val) {
this.form.type = val[0].value;
this.form.typeName = val[0].label;
},
},
}
</script>
<style lang="scss" scoped>
.wrapper {
padding-bottom: 156px;
}
.card {
box-sizing: border-box;
padding-left: 32px;
background-color: #fff;
margin-bottom: 24px;
.form {
height: 112px;
background: #FFFFFF;
display: flex;
align-items: center;
& > em {
width: 16px;
height: 44px;
font-weight: 400;
color: #FF4466;
line-height: 54px;
font-style: normal;
margin-right: 8px;
}
& > label {
font-size: 32px;
font-weight: 500;
color: #666666;
& > span {
font-size: 28px;
font-weight: 400;
color: #999999;
}
}
.right {
flex: 1;
display: flex;
align-items: center;
flex-direction: row-reverse;
margin-right: 32px;
.value {
font-size: 34px;
font-weight: 600;
color: #333333;
}
}
}
.border {
border-bottom: 1px solid #DDDDDD;
}
}
</style>

View File

@@ -0,0 +1,110 @@
<template>
<div class="padding" v-if="pageShow">
<header>{{ detail.title }}</header>
<div class="info">
<span>{{ detail.publishUnitName }} {{ detail.createTime && detail.createTime.slice(0, 16) }}</span>
<div class="right">
<em>{{ detail.views }}</em>人看过
</div>
</div>
<div class="notice-content">
<u-parse :html="detail.content"/>
</div>
<div class="photo">
<img :src="item.url" alt="" v-for="(item,index) in images" :key="index" @click="preview(index)">
</div>
</div>
</template>
<script>
export default {
name: "AppNotice",
appName:"通知公告",
data() {
return {
id: null,
pageShow: false,
detail: {},
images: [],
}
},
onLoad({id}) {
this.$loading()
this.id = id;
this.getDetail();
},
methods: {
preview(index) {
this.$previewImage(this.images, index, 'path');
},
getDetail() {
this.$instance.post("/app/appmininotice/queryDetailById", null, {
params: {id: this.id}
}).then(res => {
if (res?.data) {
this.detail = res.data;
this.images = JSON.parse(res.data.images || '[]');
this.$nextTick(() => {
this.pageShow = true
})
}
this.$hideLoading()
})
}
},
}
</script>
<style lang="scss" scoped>
.padding {
min-height: 100%;
box-sizing: border-box;
padding: 40px 32px;
background-color: #fff;
header {
font-size: 48px;
font-weight: 600;
color: #333333;
line-height: 66px;
}
.info {
display: flex;
justify-content: space-between;
font-size: 30px;
font-weight: 400;
color: #999999;
padding: 16px 0 64px;
.right {
display: flex;
flex-shrink: 0;
margin-left: 16px;
& > em {
font-style: normal;
color: #4181FF;
}
}
}
.notice-content {
font-size: 28px;
// color: #333;
// line-height: 64px;
}
.photo {
display: flex;
flex-direction: column;
& > img {
width: 100%;
margin-top: 32px;
}
}
}
</style>

View File

@@ -0,0 +1,210 @@
<template>
<div class="order">
<div class="order-item" v-for="(item, index) in list" :key="index" hover-class="text-hover"
@click="$linkTo('./orderInfo?id=' + item.id)">
<div class="order-item__imgs">
<scroll-view scroll-x>
<image v-for="(goods, index) in item.merchandiseList" :key="index"
:src="JSON.parse(goods.merchandisePhoto)[0].url"/>
</scroll-view>
<div class="order-item__imgs--right">
<div class="top">
<span>{{ item.orderIntegral }}</span>
<i>积分</i>
</div>
<p>{{ item.total }}</p>
</div>
</div>
<div class="order-item__footer">
<span :style="{color: $dict.getColor('integralOrderStatus', item.orderStatus)}">{{
$dict.getLabel('integralOrderStatus', item.orderStatus)
}}</span>
<div class="order-item__footer--btn" v-if="item.orderStatus === '0'" @click.stop="cancel(item.id)">取消订单</div>
</div>
</div>
<AiEmpty v-if="!list.length"/>
<!-- <div class="loading" style="margin-top:20px">
<u-loadmore :status="loadingStatus" />
</div> -->
</div>
</template>
<script>
export default {
name: "AppOrderList",
appName: "超市订单",
data() {
return {
list: [],
current: 0,
loadingStatus: 'loadmore'
}
},
onLoad() {
this.$dict.load(['integralOrderStatus']).then(() => {
this.getList()
})
uni.$on('update', () => {
this.reset()
})
},
methods: {
reset() {
this.loadingStatus = 'loadmore'
this.current = 0
this.$loading()
this.$nextTick(() => {
this.getList()
})
},
cancel(id) {
this.$loading()
this.$instance.post(`/app/appvillagerintegralshoporder/overOrderForWx?orderId=${id}`).then(res => {
if (res.code === 0) {
this.$toast('取消成功')
this.reset()
}
})
},
getTotal(arr) {
let total = 0
arr.forEach(item => {
total = total + item.merchandiseNumber
})
return total
},
getList() {
if (this.loadingStatus === 'loading' || this.loadingStatus === 'nomore') return
this.loadingStatus = 'loading'
this.$instance.post(`/app/appvillagerintegralshoporder/listForWx?current=${this.current + 1}&size=10`).then(res => {
if (res.code === 0) {
if (this.current === 0) {
this.list = []
}
const data = res.data.records.map(item => {
item.total = this.getTotal(item.merchandiseList)
return item
})
this.list.push(...data)
this.current = this.current + 1
this.loadingStatus = 'loadmore'
if (!res.data.records.length || res.data.records.length < 10) {
this.loadingStatus = 'nomore'
}
} else {
this.loadingStatus = 'loadmore'
}
}).catch(() => {
this.loadingStatus = 'loadmore'
})
},
toDetail(id) {
this.$linkTo(`./newsDetail?id=${id}&areaId=${this.areaId}`)
}
},
onReachBottom() {
this.getList(this.areaId)
}
}
</script>
<style lang="scss" scoped>
.order {
padding: 30px 0;
}
.order-item {
width: 686px;
margin: 0px auto32px;
background: #FFFFFF;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.02);
border-radius: 8px;
.order-item__imgs--right {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
width: 144px;
height: 160px;
background: rgba(255, 255, 255, 0.98);
.top {
display: flex;
align-items: baseline;
color: #4185F5;
font-size: 40px i {
padding-left: 4px;
font-size: 24px;
}
}
p {
color: #ADADAD;
font-size: 26px;
}
}
.order-item__footer {
display: flex;
align-items: center;
justify-content: space-between;
height: 112px;
padding: 024px span {
color: #3078E1;
font-size: 28px;
}
.order-item__footer--btn {
width: 160px;
height: 56px;
line-height: 56px;
text-align: center;
color: #666666;
font-size: 26px;
background: #FFFFFF;
border-radius: 32px;
border: 1px solid #CCCCCC;
}
}
.order-item__imgs {
display: flex;
align-items: center;
flex: 1;
height: 208px;
padding: 0 0 024px;
border-bottom: 1px solid #DDDDDD;
scroll-view {
flex: 1;
height: 160px;
font-size: 0;
overflow: hidden;
white-space: nowrap;
}
image {
flex-shrink: 1;
width: 160px;
height: 160px;
margin-right: 10px;
border-radius: 8px;
border: 1px solid #DDDDDD;
}
}
}
</style>

View File

@@ -0,0 +1,234 @@
<template>
<div class="order" v-if="pageShow">
<h2>订单{{ $dict.getLabel('integralOrderStatus', info.orderStatus) }}</h2>
<p>{{ info.createTime }}</p>
<div class="order-info">
<div class="order-top">
<div class="goods-item" v-for="(item, index) in info.merchandiseList" :key="index">
<image :src="JSON.parse(item.merchandisePhoto)[0].url"/>
<div class="goods-item__middle">
<h2>{{ item.merchandiseName }}</h2>
<p>{{ item.merchandiseNumber }}</p>
</div>
<div class="goods-item__right">
<span>{{ item.costIntegral * item.merchandiseNumber }}</span>
<i>积分</i>
</div>
</div>
</div>
<div class="order-bottom">
<div class="order-bottom__top">
<div class="left">
<span>总数量 </span>
<i>{{ total }}</i>
<span></span>
</div>
<div class="right">
<span>共消耗</span>
<i>{{ info.orderIntegral }}</i>
<em>积分</em>
</div>
</div>
<div class="order-bottom__bottom" v-if="info.orderStatus === '0'">
<div></div>
<span @click="cancel">取消订单</span>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
info: {},
id: '',
total: 0,
pageShow: false
}
},
onLoad(query) {
this.id = query.id
this.getInfo()
},
methods: {
getInfo() {
this.$loading()
this.$instance.post(`/app/appvillagerintegralshoporder/queryDetailByIdForWx?id=${this.id}`).then(res => {
if (res.code === 0) {
this.info = res.data
this.total = this.getTotal(res.data.merchandiseList)
this.$nextTick(() => {
this.pageShow = true
})
}
})
},
getTotal(arr) {
let total = 0
arr.forEach(item => {
total = total + item.merchandiseNumber
})
return total
},
cancel() {
this.$loading()
this.$instance.post(`/app/appvillagerintegralshoporder/overOrderForWx?orderId=${this.id}`).then(res => {
if (res.code === 0) {
this.$toast('取消成功')
uni.$emit('update')
this.getInfo()
}
})
}
}
}
</script>
<style lang="scss" scoped>
.order {
padding: 48px 32px;
& > h2 {
margin-bottom: 8px;
color: #333333;
font-size: 40px;
}
.order-bottom {
.order-bottom__bottom {
display: flex;
align-items: center;
justify-content: space-between;
height: 120px span {
width: 160px;
height: 56px;
line-height: 56px;
text-align: center;
color: #666666;
font-size: 26px;
background: #FFFFFF;
border-radius: 32px;
border: 1px solid #CCCCCC;
}
}
.order-bottom__top {
display: flex;
align-items: center;
justify-content: space-between;
height: 120px;
& > div {
display: flex;
align-items: center;
}
.right {
align-items: baseline;
span {
color: #333333;
font-size: 28px;
}
i {
position: relative;
top: 2px;
padding: 08px;
color: #FA4A51;
font-size: 40px;
}
em {
color: #FA4A51;
font-size: 24px;
}
}
.left {
span {
color: #999999;
font-size: 28px;
}
i {
padding: 04px;
color: #333333;
font-size: 28px;
}
}
}
}
& > p {
color: #999999;
font-size: 28px;
}
.order-info {
margin-top: 48px;
padding: 24px 24px 0;
background: #fff;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.02);
border-radius: 8px;
.order-top {
border-bottom: 1px solid #DDDDDD;
}
.goods-item {
display: flex;
align-items: center;
margin-bottom: 24px;
.goods-item__right {
display: flex;
align-items: baseline;
span {
margin-right: 4px;
color: #4185F5;
font-size: 40px;
}
i {
color: #4185F5;
font-size: 24px;
}
}
.goods-item__middle {
flex: 1;
h2 {
line-height: 1.3;
color: #333333;
font-size: 32px;
}
p {
margin-top: 20px;
color: #ADADAD;
font-size: 26px;
}
}
image {
width: 160px;
height: 160px;
margin-right: 24px;
border-radius: 4px;
border: 1px solid #DDDDDD;
}
}
}
}
</style>

View File

@@ -0,0 +1,236 @@
<template>
<div class="page">
<div class="fixed-top">
<div class="header-search">
<div class="search-input-content">
<img src="https://cdn.cunwuyun.cn/img/search-blue.svg" alt="" class="search-icon">
<input type="text" placeholder="请输入标题" class="search-input" placeholder-style="color:#E2E8F1;"
v-model="inputValue" @confirm="getList" confirm-type="search"/>
</div>
</div>
<div class="header-select">
<div class="select-item" @click="leaveMessageTypeShow = true">
<span>{{ typeName || '提问类型' }}</span>
<img src="https://cdn.cunwuyun.cn/img/down.svg" alt="" class="down-icon">
</div>
<div class="select-item" @click="timeSelectShow = true">
<span>{{ searchTime || '提问时间' }}</span>
<img src="https://cdn.cunwuyun.cn/img/down.svg" alt="" class="down-icon">
</div>
</div>
</div>
<div class="please-list">
<div class="item" v-for="(item, index) in messageList" :key="index" @click="toDetail(item.id)">
<p class="item-title"><span class="item-type"
:class="'color-'+item.type">{{
$dict.getLabel('leaveMessageType', item.type)
}}</span>{{ item.title }}
</p>
<div>
<span>提问人{{ item.leaveName }}</span>
<span>{{ ittem.createTime }}</span>
</div>
</div>
<AiEmpty v-if="!messageList.length"/>
</div>
<div class="fixed-bottom bottom-btn">
<div @click="$linkTo('./questionList')">提问记录</div>
<div class="btn-active" @click="$linkTo('./add')">我要提问</div>
</div>
<u-select v-model="leaveMessageTypeShow" :list="leaveMessageTypeList" @confirm="confirmMessageType"
confirm-color="#07c160"></u-select>
<u-picker v-model="timeSelectShow" mode="time" :params="params" :start-year="startDate" :end-year="endDate"
:default-selector="defaultDate"
confirm-color="#07c160" @confirm="timeSelectConfirm"></u-picker>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
name: "AppPlease",
appName:"随心问",
computed: {
...mapState(['user', 'token']),
startDate() {
return this.getDate('start')
},
endDate() {
return this.getDate('end')
}
},
data() {
const currentDate = this.getDate({
format: true
})
return {
inputValue: '',
timeSelectShow: false,
params: {
year: true,
month: true,
day: false,
hour: false,
minute: false,
second: false,
},
startYear: '',
endYear: '',
defaultDate: [],
searchTime: '',
leaveMessageTypeShow: false,
leaveMessageTypeList: [],
type: '',
typeName: '',
messageList: []
}
},
onLoad() {
this.$dict.load('leaveMessageType').then((res) => {
this.$nextTick(() => {
this.$dict.getDict('leaveMessageType').map(i => {
var item = {
label: i.dictName,
value: i.dictValue
}
this.leaveMessageTypeList.push(item)
})
})
this.getList()
})
},
methods: {
getList() {
var searchParams = {
createTime: this.searchTime ? this.searchTime + '-' + "01" + ' ' + '00' + ":" + "00" + ":" + "00" : '',
title: this.inputValue,
type: this.type,
userType: 0,//小程序用户
}
this.$instance.post(`/app/appleavemessage/listForWx`, searchParams).then(res => {
if (res.data.records) {
res.data.records.map((item) => {
// var reg = new RegExp('(?<=.).', 'g')
// item.leaveName = item.leaveName.replace(reg, '*')
if (item.leaveName) {
item.leaveName = item.leaveName.substring(0, 1) + '**'
}
})
this.messageList = res.data.records
}
})
},
timeSelectConfirm(e) {
this.searchTime = e.year + '-' + e.month
this.getList()
},
confirmMessageType(e) {
this.typeName = e[0].label
this.type = e[0].value
this.getList()
},
getDate(type) {
const date = new Date();
let year = date.getFullYear();
if (type === 'start') {
year = year - 10;
} else if (type === 'end') {
year = year;
}
return `${year}`;
},
toDetail(id) {
this.$linkTo(`./detail?id=${id}`)
},
}
}
</script>
<style scoped lang="scss">
@import "../../common/common.scss";
.page {
width: 100%;
background-color: #F3F6F9;
.please-list {
padding: 240px 32px 144px;
.item {
width: 686px;
background: #FFF;
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.02);
border-radius: 8px;
padding: 32px;
box-sizing: border-box;
margin-bottom: 32px;
.item-title {
word-break: break-all;
line-height: 44px;
color: #333;
font-size: 32px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
margin-bottom: 16px;
.item-type {
border-radius: 8px;
padding: 8px 8px 4px;
font-size: 26px;
line-height: 36px;
margin-right: 16px;
}
}
div {
display: flex;
justify-content: space-between;
height: 40px;
line-height: 40px;
color: #999;
font-size: 28px;
}
}
}
.bottom-btn {
height: 112px;
line-height: 110px;
font-weight: 500;
color: #666;
font-size: 36px;
display: flex;
background-color: #fff;
border-top: 2px solid #ddd;
box-sizing: border-box;
div {
flex: 1;
text-align: center;
}
.btn-active {
background-color: #1365DD;
color: #fff;
}
}
.color-0 {
background: #FFEBEF;
color: #F46;
}
.color-1 {
background: #E8EFFF;
color: #26f;
}
.color-2 {
background: #E8EFFF;
color: #26f;
}
}
</style>

222
src/mods/AppPlease/add.vue Normal file
View File

@@ -0,0 +1,222 @@
<template>
<div class="page">
<div class="add-form">
<div class="form-item mar-b8">
<span class="item-tips">*</span>
<span class="label">提问类型</span>
<span :class="typeName ? 'value color-333' : 'value color-999'"
@click="leaveMessageTypeShow = true">{{ typeName || '请选择' }}</span>
<img src="https://cdn.cunwuyun.cn/img/right-icon-999.png" alt="" class="right-icon">
</div>
<div class="form-item mar-b8">
<span class="item-tips">*</span>
<span class="label">所在地区</span>
<span class="value color-999">
<AiAreaPicker v-model="areaId" class="picker" :name.sync="areaName">
<div :class="areaName == '请选择' ? 'text color-999' : 'text color-333' ">{{ areaName || "请选择" }}</div>
</AiAreaPicker>
</span>
<img src="https://cdn.cunwuyun.cn/img/right-icon-999.png" alt="" class="right-icon">
</div>
<div class="form-item title-line">
<span class="item-tips">*</span>
<span class="label">提问标题</span>
<div class="item-input">
<input type="text" placeholder="请输入标题30字以内" placeholder-style="color:#999;" maxlength="30" v-model="title">
</div>
</div>
<div class="form-item mar-b8">
<span class="item-tips">*</span>
<span class="label">提问内容</span>
<div class="item-input fs-32">
<u-input type="textarea" height="140" placeholder="请输入提问内容500字以内" placeholder-style="color:#999;"
maxlength="500" v-model="content"/>
</div>
</div>
<div class="form-item">
<span class="item-tips"></span>
<span class="label">图片上传<span class="mini-label">最多9张</span></span>
<div class="upload">
<AiUploader :limit="9" v-model="files"></AiUploader>
</div>
</div>
</div>
<u-select v-model="leaveMessageTypeShow" :list="leaveMessageTypeList" @confirm="confirmMessageType"
confirm-color="#07c160"></u-select>
<div class="fixed-bottom confirm-btn" @click="confirm">提交</div>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
name: "my",
computed: {
...mapState(['global'])
},
data() {
return {
type: '',
typeName: '',
areaId: '',
areaName: "",
areaRange: "",
title: '',
content: '',
files: [],
flag: false,
leaveMessageTypeList: [],
leaveMessageTypeShow: false
}
},
onLoad() {
this.$dict.load('leaveMessageType').then((res) => {
this.$nextTick(() => {
this.$dict.getDict('leaveMessageType').map(i => {
var item = {
label: i.dictName,
value: i.dictValue
}
this.leaveMessageTypeList.push(item)
})
})
})
},
methods: {
confirm() {
if (this.flag) return
this.$loading()
var params = {
type: this.type,
areaId: this.areaId,
title: this.title,
content: this.content,
images: JSON.stringify(this.files),
status: 0
}
if (!params.type) {
return this.$toast('请选择留言类型')
}
if (!params.areaId) {
return this.$toast('请选择所在地区')
}
if (!params.title) {
return this.$toast('请输入提问标题')
}
if (!params.content) {
return this.$toast('请输入提问内容')
}
this.flag = true
this.$instance.post(`/app/appleavemessage/addOrUpdate-wx`, params).then(res => {
if (res && res.code == 0) {
this.$hideLoading()
uni.showModal({
title: '您已成功提交留言',
confirmText: "查看记录",
confirmColor: "#197DF0",
showCancel: false,
success: (res) => {
if (res.confirm) {
this.flag = false
uni.redirectTo({
url: './questionList'
})
} else {
this.flag = false
}
}
})
} else {
this.flag = false
}
}).catch(err => {
console.log(err)
this.flag = false
})
},
confirmMessageType(e) {
this.typeName = e[0].label
this.type = e[0].value
}
}
}
</script>
<style scoped lang="scss">
@import "../../common/common.scss";
.page {
width: 100%;
background-color: #F3F6F9;
.add-form {
padding-bottom: 112px;
}
.form-item {
padding: 34px 32px 34px 12px;
line-height: 44px;
background-color: #fff;
.item-tips {
display: inline-block;
width: 12px;
font-size: 32px;
color: #FF4466;
}
.label {
display: inline-block;
min-width: 126px;
color: #333;
font-size: 32px;
margin-left: 8px;
.mini-label {
color: #999;
font-size: 28px;
}
}
.value {
display: inline-block;
width: 518px;
text-align: right;
}
.text {
display: inline-block;
width: 520px;
text-align: right;
}
.color-333 {
color: #333 !important;
}
.right-icon {
width: 32px;
height: 32px;
margin-left: 8px;
vertical-align: middle;
}
.item-input {
padding-bottom: 4px;
margin-left: 24px;
margin-top: 32px input {
line-height: 42px;
font-size: 32px;
}
}
.upload {
margin: 32px 0 024px;
}
}
.mar-b8 {
margin-bottom: 16px;
}
}
</style>

View File

@@ -0,0 +1,299 @@
<template>
<div class="page">
<div class="detail">
<div class="detail-header">
<p class="info-title">[{{ $dict.getLabel('leaveMessageType', detailInfo.type) }}] {{ detailInfo.title }}</p>
<div class="info-item">
<span class="label">留言编号</span>
<span class="value">{{ detailInfo.msgCode }}</span>
</div>
<div class="info-item">
<span class="label">留言时间</span>
<span class="value">{{ detailInfo.createTime }}</span>
</div>
<!-- <div class="info-item">
<span class="label">受理单位</span>
<span class="value">{{detailInfo.createTime}}</span>
</div> -->
<div class="info-item">
<span class="label">处理状态</span>
<span class="value">{{ $dict.getLabel('leaveMessageStatus', detailInfo.status) }}</span>
</div>
</div>
<div class="detail-content">
<p class="info-content">{{ detailInfo.content }}</p>
<div class="img-list" v-if="detailInfo.iamgeList.length">
<img :src="item.url" alt="" v-for="(item,index) in detailInfo.iamgeList" key="index"
@click="previewdealListImage(index, detailInfo.iamgeList)">
</div>
</div>
<div class="reply-content" v-if="appLeaveMessageReplyList.length">
<div class="reply-title">
<img src="https://cdn.cunwuyun.cn/img/dialogue.svg" alt="">沟通记录
</div>
<div class="reply-list">
<div class="item" v-for="(item, index) in appLeaveMessageReplyList" :key="index">
<div class="item-top">
<div class="user-img-bg" v-if="item.createUnitName">{{ item.first }}</div>
<img :src="item.headPortrait" alt="" class="user-img"
v-if="!item.createUnitName && item.createUserName && !item.openId">
<img :src="avatarUrl" alt="" class="user-img" v-if="item.openId">
<span class="item-title" v-if="item.createUnitName">{{ item.createUnitName }} 回复</span>
<span class="item-title" v-if="!item.createUnitName && item.createUserName && !item.openId">{{
item.createUserName
}} 回复</span>
<span class="item-title" v-if="item.openId">我的 回复</span>
<span class="item-time">{{ item.createTime }}</span>
</div>
<div class="item-content">
<p>{{ item.content }}</p>
<div class="img-list">
<img :src="items.url" alt="" v-for="(items,indexs) in item.images" :key="indexs"
@click="previewdealListImage(indexs, item.images)">
</div>
</div>
</div>
<div class="no-more">------------ 没有更多回复了 ------------</div>
</div>
</div>
</div>
<div class="fixed-bottom confirm-btn" @click="toReply" v-if="detailInfo.status != 2">发表回复</div>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
name: "my",
computed: {
...mapState(['user', 'token'])
},
data() {
return {
id: '',
detailInfo: {},
appLeaveMessageReplyList: [],
avatarUrl: ''
}
},
onLoad(options) {
this.id = options.id
this.avatarUrl = this.user.avatarUrl
},
onShow() {
this.$dict.load('leaveMessageType', 'leaveMessageStatus')
this.getEventDetail()
},
methods: {
getEventDetail() {
this.$instance.post(`/app/appleavemessage/queryDetailById-wx?id=${this.id}`).then(res => {
console.log(res)
if (res.code == 0) {
if (res.data) {
res.data.iamgeList = JSON.parse(res.data.images)
this.detailInfo = res.data;
res.data.appLeaveMessageReplyList.map(item => {
if (item.createUnitName) {
item.first = item.createUnitName.substring(0, 1);
}
if (item.images) {
item.images = JSON.parse(item.images);
}
return item
})
this.appLeaveMessageReplyList = res.data.appLeaveMessageReplyList;
}
}
})
},
previewdealListImage(current, imgList) {
var tempList = []
for (var i in imgList) {
tempList.push(imgList[i].url)
}
uni.previewImage({
current: tempList[current],
urls: tempList
})
},
//回复
toReply() {
this.$linkTo(`./reply?code=${this.detailInfo.msgCode}`)
}
}
}
</script>
<style scoped lang="scss">
@import "../../common/common.scss";
.page {
width: 100%;
background-color: #f3f6f9;
.detail {
padding-bottom: 112px;
.detail-header {
width: 100%;
background: #197DF0;
padding: 24px 32px 16px 32px;
box-sizing: border-box;
color: #FFF;
.info-title {
font-weight: 500;
line-height: 64px;
word-break: break-all;
font-size: 40px;
margin-bottom: 16px;
}
.info-item {
line-height: 40px;
font-size: 28px;
margin-bottom: 16px;
.label {
display: inline-block;
text-align: justify;
text-align-last: justify;
width: 148px;
vertical-align: top;
}
.value {
display: inline-block;
width: calc(100% - 148px);
}
}
}
.detail-content {
background-color: #fff;
padding: 32px 32px 032px;
margin-bottom: 16px;
.info-content {
line-height: 56px;
color: #666;
font-size: 32px;
padding-bottom: 32px;
}
.img-list {
padding-bottom: 16px img {
width: 218px;
height: 218px;
margin: 0 16px 16px 0;
}
img:nth-of-type(3n) {
margin-right: 0;
}
}
}
.reply-content {
background-color: #fff;
padding: 032px;
.reply-title {
width: 100%;
height: 112px;
line-height: 112px;
font-weight: 500;
color: #333;
font-size: 32px img {
width: 48px;
height: 48px;
vertical-align: middle;
margin-right: 8px;
}
}
.reply-list {
.item {
margin-bottom: 32px;
.item-top {
margin-bottom: 16px;
.user-img {
width: 64px;
height: 64px;
border-radius: 50%;
margin-right: 16px;
vertical-align: middle;
}
.user-img-bg {
display: inline-block;
width: 64px;
height: 64px;
line-height: 64px;
text-align: center;
color: #fff;
font-size: 28px;
border-radius: 50%;
margin-right: 16px;
vertical-align: middle;
background-color: #197DF0;
}
.item-title {
display: inline-block;
width: 342px;
font-size: 28px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #197DF0;
line-height: 40px;
}
.item-time {
font-size: 28px;
color: #999;
line-height: 40px;
}
}
.item-content {
width: 606px;
padding: 16px 16px 0;
box-sizing: border-box;
background: #F3F6F9;
margin-left: 72px p {
line-height: 40px;
color: #333;
font-size: 28px;
word-break: break-all;
padding-bottom: 16px;
}
.img-list {
img {
width: 132px;
height: 132px;
margin: 0 16px 16px 0;
}
img:nth-of-type(4n) {
margin-right: 0;
}
}
}
}
.no-more {
padding: 64px 0;
color: #999;
font-size: 24px;
text-align: center;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,229 @@
<template>
<div class="page">
<div class="fixed-top">
<div class="header-tab">
<div class="tab-item" v-for="(item, index) in tabList" :key="index" @click="tabClick(index)">{{ item }}<span
class="active-line" v-if="tabIndex == index"></span></div>
</div>
<div class="header-search">
<div class="search-input-content">
<img src="https://cdn.cunwuyun.cn/img/search-blue.svg" alt="" class="search-icon">
<input type="text" placeholder="请输入标题或者编号" class="search-input" placeholder-style="color:#E2E8F1;"
v-model="inputValue" @confirm="getList" confirm-type="search"/>
</div>
</div>
<div class="header-select">
<div class="select-item" @click="leaveMessageTypeShow = true">
<span>{{ typeName || '提问类型' }}</span>
<img src="https://cdn.cunwuyun.cn/img/down.svg" alt="" class="down-icon">
</div>
<div class="select-item" @click="timeSelectShow = true">
<span>{{ searchTime || '提问时间' }}</span>
<img src="https://cdn.cunwuyun.cn/img/down.svg" alt="" class="down-icon">
</div>
</div>
</div>
<div class="please-list">
<div class="item" v-for="(item, index) in messageList" :key="index" @click="toDetail(item.id)">
<p class="item-title"><span class="item-type"
:class="'color-'+item.type">{{
$dict.getLabel('leaveMessageType', item.type)
}}</span>{{ item.title }}
</p>
<div>
<span>提问人{{ item.leaveName }}</span>
<span>{{ ittem.createTime }}</span>
</div>
<img :src="'https://cdn.cunwuyun.cn/dvcp/question/status'+item.status+'.png'" alt="" class="item-status">
</div>
<AiEmpty v-if="!messageList.length" class="pad-t168"/>
</div>
<u-select v-model="leaveMessageTypeShow" :list="leaveMessageTypeList" @confirm="confirmMessageType"
confirm-color="#07c160"></u-select>
<u-picker v-model="timeSelectShow" mode="time" :params="params" :start-year="startDate" :end-year="endDate"
:default-selector="defaultDate"
confirm-color="#07c160" @confirm="timeSelectConfirm"></u-picker>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
name: "my",
computed: {
...mapState(['user', 'token'])
},
data() {
return {
tabList: ['全部', '待回复', '已回复', '处理完成'],
tabIndex: 0,
status: '',
inputValue: '',
timeSelectShow: false,
params: {
year: true,
month: true,
day: false,
hour: false,
minute: false,
second: false,
},
startYear: '',
endYear: '',
defaultDate: [],
searchTime: '',
leaveMessageTypeShow: false,
leaveMessageTypeList: [],
type: '',
typeName: '',
messageList: []
}
},
onLoad() {
this.$dict.load('leaveMessageType').then((res) => {
this.$nextTick(() => {
this.$dict.getDict('leaveMessageType').map(i => {
var item = {
label: i.dictName,
value: i.dictValue
}
this.leaveMessageTypeList.push(item)
})
})
this.getList()
})
},
methods: {
getList() {
this.messageList = []
var searchParams = {
createTime: this.searchTime ? this.searchTime + "08" + ' ' + '00' + ":" + "00" + ":" + "00" : '',
title: this.inputValue,
type: this.type,
status: this.status,
userType: 0,//小程序用户
openId: this.user.openId
}
this.$instance.post(`/app/appleavemessage/listForWx`, searchParams).then(res => {
if (res.data.records) {
res.data.records.map((item) => {
// var reg = new RegExp('(?<=.).', 'g')
// item.leaveName = item.leaveName.replace(reg, '*')
item.leaveName = item.leaveName.substring(0, 1) + '**'
})
this.messageList = res.data.records
}
})
},
timeSelectConfirm(e) {
this.searchTime = e.year + '-' + e.month
this.getList()
},
confirmMessageType(e) {
this.typeName = e[0].label
this.type = e[0].value
this.getList()
},
getDate(type) {
const date = new Date();
let year = date.getFullYear();
if (type === 'start') {
year = year - 10;
} else if (type === 'end') {
year = year;
}
return `${year}`;
},
toDetail(id) {
this.$linkTo(`./detail?id=${id}`)
},
tabClick(index) {
this.tabIndex = index
if (!this.tabIndex) {
this.status = ''
} else {
this.status = this.tabIndex - 1
}
this.getList()
}
},
}
</script>
<style scoped lang="scss">
@import "../../common/common.scss";
.page {
width: 100%;
background-color: #F3F6F9;
.please-list {
padding: 336px 32px 144px;
.item {
width: 686px;
background: #FFF;
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.02);
border-radius: 8px;
padding: 32px;
box-sizing: border-box;
margin-bottom: 32px;
position: relative;
.item-title {
word-break: break-all;
line-height: 44px;
color: #333;
font-size: 32px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
margin-bottom: 16px;
.item-type {
border-radius: 8px;
padding: 8px 8px 4px;
font-size: 26px;
line-height: 36px;
margin-right: 16px;
}
}
div {
display: flex;
justify-content: space-between;
height: 40px;
line-height: 40px;
color: #999;
font-size: 28px;
}
.item-status {
width: 136px;
height: 136px;
position: absolute;
bottom: 0;
right: 0;
}
}
}
.color-0 {
background: #FFEBEF;
color: #F46;
}
.color-1 {
background: #E8EFFF;
color: #26f;
}
.color-2 {
background: #E8EFFF;
color: #26f;
}
.fixed-top {
z-index: 99;
}
}
</style>

View File

@@ -0,0 +1,161 @@
<template>
<div class="page">
<div class="pad-b112">
<div class="bg-197DF0"></div>
<div class="add-form">
<div class="form-item">
<span class="item-tips">*</span>
<span class="label">留言内容</span>
<div class="item-input title-line">
<u-input type="textarea" height="200" placeholder="请输入留言内容500字以内" placeholder-style="color:#999;"
maxlength="500" v-model="content"/>
</div>
</div>
<div class="form-item">
<span class="item-tips"></span>
<span class="label">图片上传<span class="mini-label">最多9张</span></span>
<div class="upload">
<AiUploader :limit="9" v-model="files"></AiUploader>
</div>
</div>
</div>
</div>
<div class="fixed-bottom confirm-btn" @click="reply">提交</div>
</div>
</template>
<script>
import AiUploader from '@/components/AiUploader/AiUploader'
import {mapState} from 'vuex'
export default {
name: "my",
components: {
AiUploader
},
computed: {
...mapState(['user', 'token'])
},
data() {
return {
content: '',
files: [],
avatarUrl: ''
}
},
onLoad(options) {
this.msgCode = options.code
this.avatarUrl = this.user.avatarUrl
},
methods: {
reply() {
if (!this.content) {
return this.$toast('请输入留言内容')
}
var params = {
"content": this.content,
"images": JSON.stringify(this.files),
"msgCode": this.msgCode,
"userType": 0,
'headPortrait': this.avatarUrl
}
this.$instance.post(`/app/appleavemessagereply/addOrUpdateForWX`, params).then(res => {
if (res.code == 0) {
uni.showModal({
title: '留言回复成功',
confirmText: "查看详情",
confirmColor: "#197DF0",
showCancel: false,
success: function (res) {
if (res.confirm) {
uni.navigateBack()
}
}
});
}
})
},
}
}
</script>
<style scoped lang="scss">
@import "../../common/common.scss";
.page {
width: 100%;
background-color: #F3F6F9;
.pad-b112 {
padding-bottom: 112px;
}
.bg-197DF0 {
width: 100%;
height: 112px;
background: #197DF0;
}
.add-form {
width: 686px;
background: #FFFFFF;
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.02);
border-radius: 8px;
margin: -68px 0 032px;
}
.form-item {
padding: 34px 32px 012px;
line-height: 44px;
.item-tips {
display: inline-block;
width: 12px;
font-size: 32px;
color: #FF4466;
}
.label {
display: inline-block;
min-width: 126px;
color: #333;
font-size: 32px;
margin-left: 8px;
.mini-label {
color: #999;
font-size: 28px;
}
}
.value {
display: inline-block;
width: 520px;
text-align: right;
}
.right-icon {
width: 32px;
height: 32px;
margin-left: 8px;
vertical-align: middle;
}
.item-input {
padding-bottom: 4px;
margin-left: 24px input {
line-height: 42px;
margin-top: 32px;
}
}
.upload {
margin: 32px 0 024px;
padding-bottom: 32px;
}
}
.mar-b8 {
margin-bottom: 16px;
}
}
</style>

View File

@@ -0,0 +1,220 @@
<template>
<div class="wrapper" v-if="pageShow">
<div class="area">
<ai-area-picker ref="area" class="ai-area" :value="areaId" :name.sync="areaName" :areaId="$areaId"
@select="handleSelect">
<div class="ai-area__wrapper">
<span class="label" v-if="areaName">{{ areaName }}</span>
<span v-else>请选择</span>
<image src="/static/img/area-bottom.png"/>
</div>
</ai-area-picker>
</div>
<tempate v-if="list.length">
<header>
<span>辅警列表</span>
<div class="total">
<em>{{ list.length }}</em>名辅警
</div>
</header>
<div class="list-wrap">
<div class="card" v-for="(item,index) in list" :key="index">
<img
:src="item.picture || require('../../static/img/police.png')"
@click="preview(index)"
alt="">
<div class="right">
<span class="user-name">{{ item.name }}</span>
<span class="state">驻村辅警</span>
<span class="phone" @click="call(item)">{{ item.phone }}</span>
<span>{{ item.areaName }}</span>
</div>
</div>
</div>
</tempate>
<AiEmpty v-else></AiEmpty>
</div>
</template>
<script>
export default {
name: 'AppPolice',
appName: "驻村辅警",
data() {
return {
current: 1,
areaId: "",
list: [],
areaName: '',
$areaId: '',
pageShow: false
}
},
onLoad() {
this.$loading()
this.areaId = this.$areaId
this.areaName = this.$areaName
this.$nextTick(() => {
this.getList()
})
},
methods: {
call({phone: phoneNumber}) {
uni.makePhoneCall({phoneNumber})
},
preview(index) {
if (this.list[index]["picture"]?.startsWith("http")) {
uni.previewImage({
current: this.list[index]["picture"],
urls: [this.list[index]["picture"]]
})
}
},
handleSelect(val) {
this.$loading()
this.areaId = val
this.current = 1
this.$nextTick(() => {
this.getList()
})
},
getList() {
this.$instance.post(`/app/appvillageauxiliarypolice/list`, null, {
params: {
isPublic: 1,
areaId: this.areaId,
current: this.current
}
}).then(res => {
if (res?.data) {
this.list = this.current > 1 ? [...this.list, ...res.data.records] : res.data.records;
}
this.pageShow = true
this.$hideLoading()
})
}
},
onReachBottom() {
this.current++;
this.getList();
}
}
</script>
<style lang="scss" scoped>
.wrapper {
padding-top: 124px;
padding-bottom: 20px;
}
.area {
display: flex;
align-items: center;
position: fixed;
left: 0;
top: 0;
z-index: 1;
height: 124px;
width: 100%;
box-sizing: border-box;
background: #4181FF;
padding-left: 32px;
.ai-area__wrapper {
display: flex;
align-items: center;
span {
margin-right: 16px;
color: #FFFFFF;
font-size: 44px;
}
image {
width: 16px;
height: 8px;
}
}
}
header {
display: flex;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
padding: 32px;
& > span {
font-size: 38px;
font-weight: 600;
color: #333333;
}
.total {
margin-left: auto;
font-size: 28px;
font-weight: 400;
color: #666666;
display: flex;
align-items: center;
& > em {
color: #4181FF;
}
}
}
.list-wrap {
box-sizing: border-box;
padding: 0 32px;
.card {
box-sizing: border-box;
padding: 32px;
background: #FFFFFF;
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.02);
border-radius: 16px;
display: flex;
align-items: center;
margin-bottom: 24px;
& > img {
width: 200px;
height: 200px;
border-radius: 8px;
margin-right: 32px;
flex-shrink: 0;
}
.right {
height: 200px;
flex: 1;
display: flex;
flex-direction: column;
font-size: 26px;
font-weight: 400;
color: #666666;
.user-name {
font-size: 32px;
font-weight: 600;
color: #333333;
margin-bottom: 16px;
}
.state {
color: #666666;
}
.phone {
color: #4181FF;
margin: 8px 0;
}
}
}
}
</style>

View File

@@ -0,0 +1,255 @@
<template>
<div class="progressList">
<div class="search">
<div class="search-container">
<i class="iconfont">&#xe715;</i>
<input placeholder="请输入需要搜索的内容" placeholder-style="color:rgba(255,255,255,0.5)" v-model="param" @confirm="reset"
:focus="focus" confirm-type="search">
</div>
</div>
<div class="progressList-list">
<div class="item" v-for="(item, index) in list" :key="index" hover-class="bg-hover"
@click="$linkTo('./progressDetail?id=' + item.id)">
<div class="top">
<h2>{{ item.processDefName }}</h2>
<!-- <AiIcon class="progressList-icon" :icon="iconList[item.approvalStatus]" size="56"></AiIcon> -->
<div class="item-info">
<span>申请类型</span>
<div>{{ item.classificationName }}</div>
</div>
<div class="item-info">
<span>申请日期</span>
<div>{{ item.createTime }}</div>
</div>
<div class="item-info">
<span>完成日期</span>
<div>{{ item.overTime || '-' }}</div>
</div>
</div>
<div class="bottom">
<em :style="{background: mapColor(item.approvalStatus)}"></em>
<span
:style="{color: mapColor(item.approvalStatus)}">{{
$dict.getLabel('approvalStatus', item.approvalStatus)
}}</span>
</div>
</div>
<AiEmpty v-if="!list.length"></AiEmpty>
<!-- <u-loadmore :status="loadingStatus" :margin-top="30" :margin-bottom="30" color="#999" font-size="26"/> -->
</div>
</div>
</template>
<script>
export default {
name: "AppProgress",
appName: "办事进度",
data() {
return {
id: '',
title: '',
subTitle: '',
current: 0,
focus: false,
param: '',
list: [],
loadingStatus: 'loadmore',
iconList: {
'0': 'icon1',
'1': 'icon2',
'2': 'icon3'
}
}
},
onLoad(query) {
if (query.focus === '1') {
this.focus = true
}
this.id = query.id
this.title = query.title
this.subTitle = query.subTitle
this.$dict.load(['approvalStatus']).then(() => {
this.getList()
})
},
methods: {
reset() {
this.current = 0
this.loadingStatus = 'loading'
this.$nextTick(() => {
this.getList()
})
},
mapColor(status) {
return {
'0': '#FF883C',
'1': '#42D784',
'2': '#FF4466'
}[status]
},
getList() {
if (this.loadingStatus === 'nomore') return
this.loadingStatus = 'loading'
this.$instance.post(`/app/approv-alapply-info/xcx-list`, null, {
params: {
current: this.current + 1,
size: 10,
param: this.param
}
}).then(res => {
if (res.code === 0) {
if (!res.data.records.length) {
if (this.current === 0) this.list = []
this.loadingStatus = 'nomore'
return false
}
const data = res.data.records.map(item => {
return item
})
if (this.current === 0) this.list = []
this.list.push(...data);
this.current = this.current + 1
this.loadingStatus = 'loadmore'
if (this.list.length < 10) {
this.loadingStatus = 'nomore'
}
}
})
}
},
onReachBottom() {
this.getList()
}
}
</script>
<style scoped lang="scss">
div, label, i, view {
box-sizing: border-box;
}
.progressList {
padding-bottom: 40px;
}
.search {
position: fixed;
top: 0;
left: 0;
z-index: 11;
width: 100%;
height: 104px;
padding: 20px 32px;
box-sizing: border-box;
background: #4181FF;
.search-container {
display: flex;
align-items: center;
height: 64px;
padding: 032px;
border-radius: 32px;
background: rgba(0, 0, 0, .2);
i {
padding-right: 12px;
font-size: 32px;
color: rgba(255, 255, 255, .5);
}
input {
flex: 1;
font-size: 26px;
color: #ffffff;
}
}
}
.progressList-list {
padding-top: 104px;
.item {
position: relative;
width: 686px;
margin: 24px auto 0;
background: #FFFFFF;
border-radius: 16px;
.top {
box-sizing: border-box;
padding: 32px;
border-bottom: 1px solid #DDDDDD;
.progressList-icon {
position: absolute;
top: 0;
right: 0;
font-size: 56px;
}
.item-info {
display: flex;
align-items: center;
line-height: 42px;
margin-bottom: 8px;
span {
color: #999999;
font-size: 26px;
line-height: 36px;
margin-right: 32px;
}
div {
color: #343D65;
font-size: 30px;
}
}
h2 {
margin-bottom: 24px;
padding-right: 56px;
color: #333333;
font-size: 32px;
text-align: justify;
font-weight: 600;
}
}
.bottom {
height: 104px;
background: #FFFFFF;
display: flex;
align-items: center;
padding-left: 32px;
& > em {
width: 8px;
height: 8px;
border-radius: 50%;
background: #FF883C;
margin-right: 8px;
}
& > span {
font-size: 28px;
font-weight: 400;
color: #FF883C;
}
}
}
}
</style>

View File

@@ -0,0 +1,122 @@
<template>
<div class="annex">
<div class="annex-list">
<div class="annex-item">
<div class="annex-item__left">
<image :src="img" @click="preview"/>
<h2>{{ name }}</h2>
</div>
<i class="iconfont" @click="download">&#xe725;</i>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
img: '',
name: ''
}
},
onLoad(query) {
this.img = query.img
this.name = query.name
},
methods: {
preview() {
uni.previewImage({
urls: [this.img],
current: this.img
})
},
download() {
uni.downloadFile({
url: this.img,
success: res => {
const img = res.tempFilePath
this.$hideLoading()
uni.saveImageToPhotosAlbum({
filePath: img,
success: () => {
this.$toast('保存成功')
},
fail: () => {
uni.getSetting({
success: (res) => {
if (!res.authSetting['scope.writePhotosAlbum']) {
this.$dialog.confirm({
content: '未授权',
confirmText: '去设置'
}).then(() => {
wx.openSetting({
success: res => {
if (!res.authSetting['scope.writePhotosAlbum']) {
this.$toast({
title: '此功能需获取相册权限',
duration: 3000
})
} else {
}
}
})
})
}
}
})
}
})
},
fail: () => {
this.$hideLoading()
this.$toast('保存失败')
}
})
}
}
}
</script>
<style scoped lang="scss">
.annex {
min-height: 100vh;
background: #fff;
}
.annex-list {
padding-top: 40px;
.annex-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 032px i {
font-size: 52px;
color: #197DF0;
}
.annex-item__left {
display: flex;
align-items: center;
image {
position: relative;
top: 4px;
width: 72px;
height: 72px;
margin-right: 18px;
}
h2 {
font-size: 32px;
font-weight: 600;
color: #333;
}
}
}
}
</style>

View File

@@ -0,0 +1,751 @@
<template>
<div class="progressDetail" v-if="pageShow">
<div class="status" v-if="info.approvalStatus === '1'">
<h2>审批通过</h2>
<div class="status-content">
<span>[{{ info.processDefName }}]已签署完成</span>
<i @click="$linkTo('./progressAnnex?img=' + info.pdfPicFile.url + '&name=' + info.processDefName)">点击查看和保存</i>
</div>
</div>
<div class="info">
<h2 :style="{maxWidth: info.approvalStatus !== '1' ? '100%' : '550rpx'}">{{ info.processDefName }}</h2>
<AiIcon class="info-status" v-if="info.approvalStatus === '1'" size="96" icon="iconsp-pass"></AiIcon>
<div class="info-user">
<image v-if="info.createUserAvatar" :src="info.createUserAvatar"/>
<span v-else>{{ nameAvatar(info.createUserName) }}</span>
<div class="inf-user__right flex1">
<h2>{{ info.createUserName }}</h2>
<p>{{ info.createTime }}</p>
</div>
<i :style="{color: mapStatusColor(info.approvalStatus)}"
v-if="info.approvalStatus !== '1'">{{ $dict.getLabel('approvalStatus', info.approvalStatus) }}</i>
</div>
<div class="info-list">
<div class="info-item">
<span>所属类型</span>
<div>{{ info.classificationName || '-' }}</div>
</div>
<div class="info-item">
<span>所属部门</span>
<div>{{ $dict.getLabel('hbDepartment', info.department) || '-' }}</div>
</div>
<div class="info-item">
<span>审批编号</span>
<div>{{ info.serialNumber }}</div>
</div>
<div class="info-item">
<span>附件资料</span>
<div v-if="!!info.annexs && info.annexs.length">
<div class="imgs" v-for="(item, index) in info.annexs" :key="index">
<img :src="item.annexFile.url" mode="aspectFill" @click="preview(info.annexs, item.annexFile.url)">
<span>{{ item.annexName }}</span>
</div>
</div>
<div v-else>暂无附件</div>
</div>
</div>
</div>
<div class="detail">
<div class="detail-tab">
<div @click="currIndex = 0" :class="[currIndex === 0 ? 'active' : '']">申请表单</div>
<div @click="currIndex = 1" :class="[currIndex === 1 ? 'active' : '']">流程信息</div>
</div>
<!--申请表单-->
<div class="detail-form" v-if="currIndex==0">
<div class="detail-form__item" v-for="(item, index) in tableForm" :key="index">
<div class="detail-form__item--title" @click="showMore(index)">
<div class="left">
<span></span>
<h2>{{ item[0].groupName }}</h2>
</div>
<i class="iconfont" :class="[index === formIndex ? 'title-active' : '']">&#xe696;</i>
</div>
<div class="detail-form__item--list" v-show="index === formIndex">
<div class="detail-form__item--info" v-for="(field, i) in item" :key="i">
<h2>{{ field.fieldName }}{{ field.fieldNameSuffix || '' }}</h2>
<span v-if="!field.dictionaryCode">{{ field.fieldValue || '-' }}</span>
<span v-if="field.dictionaryCode && field.fieldDataType !== '5'">{{
$dict.getLabel(field.dictionaryCode, field.fieldValue) || '-'
}}</span>
<span v-if="field.dictionaryCode && field.fieldDataType === '5'">{{
getDictValue(field.dictionaryCode, field.fieldValue)
}}</span>
</div>
</div>
</div>
</div>
<!--流程信息-->
<div class="detail-list" v-if="currIndex==1">
<div class="step-item" v-for="(item, index) in stepList" :key="index">
<div class="line"></div>
<div class="detail-left">
<image class="avatar" v-if="item.stepAvatar && item.userName" :src="item.stepAvatar"/>
<span v-if="!item.stepAvatar && item.userName">{{ item.userName.substr(item.userName.length - 2) }}</span>
<image v-if="index !== 0 && item.candidates && item.candidates.length > 1" class="detail-left__statusicon"
src="/static/img/notice.png"/>
<image class="avatar"
v-if="index !== 0 && item.candidates && item.candidates.length === 1 && item.candidates[0].avatar"
:src="item.candidates[0].avatar"/>
<span v-if="index !== 0 && item.candidates && item.candidates.length === 1 && !item.candidates[0].avatar">{{
item.candidates[0].name.substr(item.candidates[0].name - 2)
}}</span>
<image class="detail-left__icon" src="/static/img/gou.png"
v-if="index === 0 || ['0', '1', '6', '5'].indexOf(item.stepType) > -1"/>
<image class="detail-left__icon" src="/static/img/point.png" v-else-if="item.stepType !== '2'"/>
</div>
<div class="detail-right">
<div class="detail-right__title">
<h2>{{ item.title }}</h2>
<span v-if="item.approvalTime">{{ item.approvalTime }}</span>
</div>
<div class="detail-right__subtitle" v-if="item.stepType === '0'">
<span>{{ item.userName || '-' }}</span>
<i>({{ stepTypeList[item.stepType] }})</i>
</div>
<div class="detail-right__subtitle" v-else-if="item.stepType !== '2'">
<span>{{ item.title2 }}</span>
<i v-if="item.title2Desc" :style="{color: mapColor(item.stepType)}">{{ item.title2Desc }}</i>
</div>
<div class="detail-right__subtitle" v-else-if="item.stepType === '2'">
<span>{{ item.title2 }} </span>
<i style="color: #F14242"> {{ item.title2Desc }}</i>
</div>
<div class="detail-right__subtitle" v-if="item.stepType === '2'">
<span>审批意见</span>
<i style="color: #F14242;">{{ item.opinion || '-' }}</i>
</div>
<div class="detail-right__subtitle detail-right__text" style="display: block"
v-if="item.candidateFieldInfos && item.candidateFieldInfos.length"
v-for="(candidateField, z) in item.candidateFieldInfos" :key="z">
<span>{{ candidateField.fieldName }}</span>
<i style="color: #343D65;display: contents;">{{
candidateField.dictionaryCode ? $dict.getLabel(candidateField.dictionaryCode, candidateField.fieldValue) || '-' : candidateField.fieldValue || '-'
}}</i>
</div>
<div class="detail-right__imgs" v-if="item.pictureFiles && item.pictureFiles.length">
<image :src="img.url" mode="aspectFill" v-for="(img, i) in item.pictureFiles" :key="i"
@click="previewPic(item.pictureFiles, img.url)"/>
</div>
<div class="detail-right__doc" v-if="item.annexFiles && item.annexFiles.length">
<div class="doc-item" v-for="(file, j) in item.annexFiles" :key="j" @click="saveFile(file)">
<h2>{{ file.name }}</h2>
<span>{{ (file.size / 1024).toFixed(2) }}KB</span>
</div>
</div>
<div class="detail-right__userlist" v-if="item.candidates && item.candidates.length">
<div class="detail-right__userinfo" v-for="(user, z) in item.candidates" :key="z">
<image v-if="user.avatar" :src="user.avatar"/>
<span v-else>{{ user.name.substr(user.name.length - 2) }}</span>
<h2>{{ user.name }}</h2>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
title: '',
currIndex: 0,
id: '',
info: {},
formIndex: 0,
tableForm: [],
pageShow: false,
nodeApprovalStatusList: {
'0': '待审批',
'1': '审批通过',
'2': '审批驳回'
},
stepTypeList: {
'0': '发起',
'1': '审批通过',
'2': '审批拒绝',
'3': '抄送',
'4': '转办审批中',
'5': '转办审批同意',
'6': '转办审批拒绝',
'7': '发起人撤回',
'8': '待审批',
'9': '未到达该节点'
},
stepList: []
}
},
onLoad(query) {
this.id = query.id
this.getInfo(query.id)
},
methods: {
showMore(index) {
if (index === this.formIndex) {
this.formIndex = -1
} else {
this.formIndex = index
}
},
mapStatusColor(status) {
return {
'0': '#FF9B2B',
'1': '#3078E1',
'2': '#F14242'
}[status]
},
mapColor(status) {
if (status === '1') {
return '#2EA222'
}
if (status === '2' || status === '6' || status === '7') {
return '#F14242'
}
return '#FF8822'
},
saveFile(file) {
if (['.png', '.jpg', '.jpeg'].indexOf(file.postfix) > -1) {
uni.previewImage({
urls: [file.url],
current: file.url
})
return false
}
uni.downloadFile({
url: file.url,
success: res => {
const filePath = res.tempFilePath
this.$hideLoading()
wx.openDocument({
filePath: filePath,
success: function (res) {
console.log('打开文档成功')
}
})
},
fail: () => {
this.$hideLoading()
this.$toast('保存失败')
}
})
},
previewPic(imgList, img) {
uni.previewImage({
urls: imgList.map(v => v.url),
current: img
})
},
preview(imgList, img) {
uni.previewImage({
urls: imgList.map(v => v.annexFile.url),
current: img
})
},
getDictValue(dictKey, value) {
return value.split(',').map(item => {
return this.$dict.getLabel(dictKey, item)
}).join(',')
},
getInfo(id) {
this.$loading()
this.$instance.post(`/app/approv-alapply-info/info-id-table?id=${id}`).then(res => {
if (res.code === 0) {
const groupFormIds = this.unique(res.data.tableInfo.tableFieldInfos.filter(v => v.fieldType !== '1').map(v => v.groupIndex))
const dictKeys = res.data.tableInfo.tableFieldInfos.filter(v => !!v.dictionaryCode).map(v => v.dictionaryCode)
this.$dict.load([...dictKeys, 'hbDepartment', 'nodeApprovalStatus', 'nodeType']).then(() => {
this.info = res.data
this.$instance.post(`/app/approv-alapply-info/processinfo-id2?id=${id}`).then(res => {
if (res.code === 0) {
let dictKeys = []
res.data.forEach(item => {
if (item.candidateFieldInfos && item.candidateFieldInfos.length) {
item.candidateFieldInfos.forEach(v => {
v.dictionaryCode && dictKeys.push(v.dictionaryCode)
})
}
})
if (dictKeys.length) {
this.$dict.load([...dictKeys]).then(() => {
this.stepList = res.data
})
} else {
this.stepList = res.data
}
}
})
this.pageShow = true
})
this.tableForm = groupFormIds.map(index => {
return res.data.tableInfo.tableFieldInfos.filter(v => v.fieldType !== '1' && v.groupIndex === index)
})
}
})
},
/**
* 数组去重
*/
unique(arr) {
return arr.filter((item, index) => {
return arr.indexOf(item, 0) === index
})
},
nameAvatar(name) {
return name?.split("")?.slice(-2) || "游客"
}
}
}
</script>
<style scoped lang="scss">
div, label, i, view {
box-sizing: border-box;
}
.progressDetail {
padding-bottom: 40px;
}
.ellipsis {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.detail-list {
padding: 40px 32px;
}
.step-item {
display: flex;
position: relative;
padding-bottom: 88px;
&:last-child {
padding-bottom: 0;
.line {
display: none;
}
}
.detail-right__doc {
padding-top: 8px;
.doc-item {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 16px;
padding: 16px;
background: #F7F7F7;
border-radius: 4px;
border: 1px solid #DDDDDD;
&:last-child {
margin-bottom: 16px;
}
span {
color: #999999;
font-size: 24px;
}
h2 {
max-width: 444px;
line-height: 32px;
color: #333333;
font-size: 24px;
word-break: break-all;
}
}
}
.detail-right {
flex: 1;
.detail-right__title {
display: flex;
justify-content: space-between;
margin-bottom: 6px;
span {
color: #999999;
font-size: 28px;
}
& > h2 {
color: #333333;
font-size: 32px;
font-weight: 600;
}
}
.detail-right__userlist {
margin-top: 16px;
font-size: 0;
.detail-right__userinfo {
display: inline-block;
margin-right: 32px;
margin-bottom: 32px;
text-align: center;
image, span {
display: inline-block;
width: 64px;
height: 64px;
line-height: 64px;
border-radius: 50%;
margin-bottom: 8px;
text-align: center;
color: #FFFFFF;
font-size: 26px;
border-radius: 50%;
background: #2266FF;
}
h2 {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
color: #666666;
font-size: 24px;
}
}
}
.detail-right__subtitle {
display: flex;
margin-bottom: 6px span {
margin-right: 10px;
color: #666666;
font-size: 28px;
}
i {
flex: 1;
text-align: justify;
word-break: break-all;
color: #2EA222;
font-size: 28px;
}
}
.detail-right__text {
// color: #343D65;
// font-size: 28px;
// margin: 6px 0;
}
.detail-right__imgs {
font-size: 0;
image {
display: inline-block;
width: 136px;
height: 136px;
margin-right: 8px;
margin-bottom: 8px;
margin-top: 8px;
border-radius: 4px;
}
}
}
.line {
position: absolute;
left: 38px;
top: 80px;
width: 4px;
height: 100%;
background: #EEEEEE;
}
.detail-left {
display: flex;
align-items: center;
justify-content: center;
position: relative;
width: 80px;
height: 80px;
margin-right: 40px;
flex-shrink: 1;
border-radius: 50%;
background: #2266FF;
.detail-left__statusicon {
width: 48px;
height: 48px;
}
.detail-left__icon {
position: absolute;
top: 48px;
right: -4px;
width: 36px;
height: 36px;
}
span, .avatar {
display: block;
width: 80px;
height: 80px;
line-height: 80px;
color: #fff;
font-size: 28px;
text-align: center;
border-radius: 50%;
background: #2266FF;
}
}
}
.status {
width: 100%;
padding: 20px 32 px20px;
font-weight: 600;
background: #EFF4FF;
h2 {
margin-bottom: 10px;
color: #3A7EE2;
font-size: 28px;
}
.status-content {
span {
display: inline;
font-size: 28px;
color: #3A7EE2;
}
i {
display: inline;
font-size: 28px;
color: #3A7EE2;
text-decoration: underline;
}
}
}
.info {
position: relative;
padding: 32px 32px 20px;
background: #fff;
& > h2 {
max-width: 550px;
margin-bottom: 8px;
font-size: 32px;
font-weight: 600;
color: #333333;
}
.info-status {
position: absolute;
right: 0;
top: 0;
font-size: 96px;;
}
.info-user {
display: flex;
align-items: center;
height: 112px;
border-bottom: 1px solid #D8DDE6;
i {
font-size: 28px;
color: #FF8822;
}
span, image {
width: 80px;
height: 80px;
line-height: 80px;
margin-right: 16px;
text-align: center;
color: #FFFFFF;
font-size: 28px;
border-radius: 50%;
background: #2266FF;
}
p {
margin-top: 4px;
font-size: 24px;
color: #999999;
}
h2 {
color: #333333;
font-size: 32px;
}
}
.info-list {
padding-top: 32px;
.info-item {
display: flex;
margin-bottom: 16px;
&:first-child {
div {
color: #1365DD;
}
}
.imgs {
display: inline-block;
position: relative;
margin-right: 8px;
margin-bottom: 8px;
font-size: 0;
image {
width: 170px;
height: 170px;
}
span {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 40px;
line-height: 40px;
text-align: center;
color: #fff;
font-size: 20px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
background: rgba(0, 0, 0, 0.4);
}
}
span {
flex-shrink: 1;
color: #999999;
font-size: 30px;
}
& > div {
flex: 1;
color: #343D65;
font-size: 30px;
}
}
}
}
.detail {
margin-top: 16px;
background: #fff;
.detail-tab {
display: flex;
align-items: center;
height: 96px;
border-bottom: 1px solid #D8DDE6;
div {
flex: 1;
height: 100%;
line-height: 96px;
text-align: center;
color: #999999;
font-size: 34px;
font-weight: 600;
border-bottom: 4px solid transparent;
&.active {
color: #1365DD;
border-bottom: 4px solid #1365DD;
}
}
}
.detail-form {
.detail-form__item {
border-bottom: 1px solid #D8DDE6;
&:last-child {
border: none;
}
}
.detail-form__item--title {
display: flex;
align-items: center;
justify-content: space-between;
height: 96px;
padding: 0 32px;
.left {
display: flex;
align-items: center;
span {
width: 4px;
height: 32px;
margin-right: 12px;
background: #1365DD;
}
h2 {
color: #333333;
font-size: 32px;
}
}
i {
position: relative;
font-size: 32px;
color: #cfcfcf;
transform: rotate(180deg);
transition: all 0.3s ease;
&.title-active {
transform: rotate(-180deg);
}
}
}
.detail-form__item--list {
background: #FAFAFA;
padding: 0 32px;
.detail-form__item--info {
display: flex;
justify-content: space-between;
padding: 10px 0;
span {
text-align: right;
max-width: 500px;
padding-left: 10px;
word-break: break-all;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,339 @@
<template>
<section class="supermarket">
<template v-if="Object.keys(list).length">
<div class="nav-left">
<scroll-view scroll-y style="height: 100%;">
<div class="nav-left-item" v-for="(val, key, index) in list" :key="index"
@click="clickSort(key,index)">
{{ key }}分区
<u-badge size="mini" :count="sortCountList[index]" absolute :offset="[5,5]"></u-badge>
</div>
</scroll-view>
</div>
<div class="nav-right">
<scroll-view scroll-y style="height: 100%;">
<div class="category-item" v-for="(item,index) in categoryList" :key="index">
<img
:src="parseObj(item.photo)"
class="category-img" alt="">
<div class="category-info">
<label class="hidden">{{ item.merchandiseName }}</label>
<span class="score">{{ item.costIntegral }}
<span>积分</span>
</span>
<div class="wrap">
<div class="lxc-count">
<div class="less" @click="less(item,index)">-</div>
<div class="num">{{ item.merchandiseNumber }}</div>
<div class="less" @click="add(item,index)">+</div>
</div>
</div>
</div>
</div>
</scroll-view>
</div>
<div class="footer">
<div class="sum">
<span>{{ totalCount }}件商品</span>
<span>合计{{ totalScore }}
<span>积分</span>
</span>
</div>
<div class="btn" @click="handleSubmit">去结算</div>
</div>
</template>
<AiEmpty v-else></AiEmpty>
</section>
</template>
<script>
import {mapState} from "vuex";
export default {
name: "AppSupermarket",
appName:"信用好超市",
data() {
return {
list: {},
idx: 0,
totalScore: 0,
sortCountList: [],
mark: 0,
}
},
onLoad() {
this.getList()
},
watch: {
list: {
handler(val) {
let sum = 0
Object.keys(val).map(e => {
val[e].map(p => {
if (p.merchandiseNumber != 0) {
sum += (p.merchandiseNumber) * (p.costIntegral)
}
})
})
this.totalScore = sum
},
immediate: true,
deep: true
}
},
computed: {
...mapState(['user']),
totalCount() {
return this.sortCountList.reduce((pre, cur) => (pre + cur), 0)
},
categoryList() {
return this.idx == 0 ? this.list[Object.keys(this.list)[0]] : this.list[this.idx]
},
},
methods: {
handleSubmit() {
if (this.totalCount == 0) {
return uni.showToast({
title: "您还没有选择商品",
icon: 'none'
})
}
let filter = []
Object.keys(this.list).map(e => {
this.list[e].map(p => {
if (p.merchandiseNumber > 0) {
filter.push(p)
}
})
})
uni.navigateTo({
url: "/pages/supermarket/balance?category=" + JSON.stringify(filter)
})
},
active(key) {
const flag = key == this.idx
return {
borderLeft: flag ? '3px solid #1D58FE' : '',
background: flag ? 'linear-gradient(270deg, #FFFFFF 0%, #FFFFFF 77%, #E7EAFA 100%)' : ''
}
},
add(item, index) {
this.list[this.idx][index]["merchandiseNumber"] = this.list[this.idx][index]["merchandiseNumber"] + 1
this.$set(this.sortCountList, this.mark, this.list[this.idx]?.reduce((pre, curr) => {
return (pre + curr.merchandiseNumber)
}, 0))
},
less(item, index) {
if (item.merchandiseNumber > 0) {
this.list[this.idx][index]["merchandiseNumber"] = this.list[this.idx][index]["merchandiseNumber"] - 1
this.$set(this.sortCountList, this.mark, this.list[this.idx]?.reduce((pre, curr) => {
return (pre + curr.merchandiseNumber)
}, 0))
}
},
clickSort(key, index) {
this.mark = index
this.idx = key.toString()
},
parseObj(json) {
return JSON.parse(json || '[]')[0]?.url
},
getList() {
this.$instance.post(`/app/appvillagerintegralmerchandise/listByIntegral`, null, {
params: {
areaId: this.user?.areaId
}
}).then(res => {
if (res && res.data) {
Object.keys(res.data).map(e => {
res.data[e].map(p => {
p.merchandiseNumber = 0
})
})
this.list = res.data
this.idx = Object.keys(res.data)[0]
this.sortCountList = Array(Object.keys(res.data).length).fill(0)
}
})
}
},
}
</script>
<style lang="scss" scoped>
uni-page-body {
background-color: #ffffff;
}
.supermarket {
background-color: #ffffff;
display: flex;
justify-content: space-between;
padding-bottom: 104px;
.nav-left {
width: 168px;
height: 100%;
.nav-left-item {
height: 104px;
background: #FAF9FB;
display: flex;
align-items: center;
justify-content: center;
font-size: 28px;
color: #333333;
border-top: 1px solid #D8E5FF;
border-left: 2px solid transparent;
position: relative;
&:last-child {
border-bottom: 1px solid #D8E5FF;
}
}
}
.nav-right {
width: calc(100% - 168px - 24px);
height: 100%;
.category-item {
height: 264px;
box-sizing: border-box;
padding: 28px 32px 44px 30px;
display: flex;
.category-img {
width: 192px;
height: 192px;
border: 1px solid #F6F6F6;
flex-shrink: 0;
margin-right: 30px;
}
.category-info {
width: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
& > label {
font-size: 30px;
font-weight: 800;
color: #333333;
line-height: 42px;
}
.score {
font-size: 40px;
font-weight: 600;
color: #FA4A51;
line-height: 40px;
& > span {
font-size: 24px;
color: #FA4A51;
margin-left: 8px;
}
}
.wrap {
display: flex;
justify-content: flex-end;
.lxc-count {
display: flex;
align-items: center;
justify-content: center;
.less {
width: 40px;
height: 40px;
font-size: 20px;
display: flex;
align-items: center;
justify-content: center;
font-size: 36px;
font-weight: 500;
color: #333333;
}
.num {
width: 89px;
height: 61px;
display: flex;
align-items: center;
justify-content: center;
background: #F6F6F6;
border-radius: 10px;
font-size: 28px;
font-weight: 400;
color: #333333;
margin: 0 16px;
}
}
}
}
}
}
.footer {
display: flex;
align-items: center;
width: 100%;
background-color: #ffffff;
z-index: 100;
height: 104px;
box-shadow: 0px -2px 8px 0px rgba(214, 214, 214, 0.5);
position: fixed;
left: 0;
bottom: 0;
.sum {
width: calc(100% - 212px);
box-sizing: border-box;
padding: 30px;
display: flex;
justify-content: space-between;
& > span:nth-child(1), span:nth-child(2) {
font-size: 32px;
font-weight: 400;
color: #F94246;
& > span {
font-size: 24px;
margin-left: 12px;
}
}
}
.btn {
width: 212px;
height: 100%;
background-color: #1365DD;
font-size: 36px;
font-weight: 500;
color: #FFFFFF;
display: flex;
align-items: center;
justify-content: center;
}
}
.hidden {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
}
</style>

View File

@@ -0,0 +1,284 @@
<template>
<div class="balance">
<div class="operate">
<div class="target">结算对象</div>
<div class="select" @click="handleSelect">
{{
selected
? `${selected.familyName} 剩余积分:${selected.familyIntegral}`
: '请选择'
}}
<u-icon name="arrow-right" color="#E2E2E2" size="28"></u-icon>
</div>
</div>
<div class="line" :style="{ backgroundImage: 'url(' + uri + ')' }"></div>
<scroll-view scroll-y class="category-wrap">
<div
class="category-item"
v-for="(item, index) in categoryList"
:key="index"
>
<img class="category-img" :src="parseObj(item.photo)" alt=""/>
<div class="category-info">
<label class="hidden">{{ item.merchandiseName }}</label>
<span class="score"
>{{ item.costIntegral }}
<span>积分</span>
</span>
<div class="wrap">×{{ item.merchandiseNumber }}</div>
</div>
</div>
</scroll-view>
<div class="footer">
<div class="sum">
<span>{{ totalCount }}件商品</span>
<span
>合计{{ totalScore }}
<span>积分</span>
</span>
</div>
<div class="btn" @click="hanldeSubmit">确认领取</div>
</div>
</div>
</template>
<script>
export default {
name: 'balance',
data() {
return {
selected: null,
categoryList: [],
totalScore: 0,
totalCount: 0
}
},
onLoad(opt) {
if (opt.category) {
let sum = 0
let count = 0
this.categoryList = JSON.parse(opt.category)
this.categoryList.map(e => {
count += e.merchandiseNumber
if (e.merchandiseNumber != 0) {
sum += e.merchandiseNumber * e.costIntegral
}
})
this.totalScore = sum
this.totalCount = count
}
uni.$on('selected', data => {
if (data) {
this.selected = data
}
})
},
computed: {
uri() {
return this.$cdn + 'other/' + 'line.png'
}
},
methods: {
parseObj(json) {
return JSON.parse(json || '[]')[0]?.url
},
hanldeSubmit() {
if (!this.selected)
return uni.showToast({
title: '请选择结算对象',
icon: 'none'
})
let {memberId, familyId} = this.selected
this.$instance
.post(`/app/appvillagerintegralshoporder/addOrder`, {
shopId: this.categoryList[0].shopId,
memberId,
familyId,
orderIntegral: this.totalScore,
merchandiseList: this.categoryList.map(e => {
return {
...e,
merchandiseId: e.id
}
})
})
.then(res => {
if (res.code == 0) {
uni.navigateTo({
url: '/pages/supermarket/components/resultPage/resultPage'
})
} else {
uni.navigateTo({
url:
'/pages/supermarket/components/resultPage/resultPage?flag=' +
false
})
}
})
.catch(e => {
uni.showToast({
title: e || '网络异常',
icon: 'none'
})
})
},
handleSelect() {
uni.navigateTo({
url: '/pages/supermarket/search'
})
}
}
}
</script>
<style lang="scss" scoped>
.balance {
min-height: 100%;
background-color: #ffffff;
.operate {
height: 120px;
display: flex;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
padding: 0 30px;
.target {
font-size: 32px;
color: #333333;
&:before {
content: '*';
font-size: 32px;
color: #ff4466;
}
}
.select {
font-size: 32px;
color: #666666;
& > i {
font-size: 20px;
}
}
}
.line {
// margin: 0 30px;
padding: 0 15px;
height: 8px;
background-repeat: no-repeat;
background-size: cover;
}
.category-wrap {
padding: 16px 0 110px;
.category-item {
box-sizing: border-box;
padding: 28px 32px 44px 30px;
height: 264px;
display: flex;
.category-img {
width: 192px;
height: 192px;
border: 1px solid #f6f6f6;
flex-shrink: 0;
margin-right: 30px;
}
.category-info {
width: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
& > label {
font-size: 30px;
font-weight: 800;
color: #333333;
line-height: 42px;
}
.score {
font-size: 40px;
font-weight: 600;
color: #fa4a51;
& > span {
font-size: 24px;
color: #fa4a51;
margin-left: 8px;
}
}
.wrap {
display: flex;
justify-content: flex-end;
font-weight: 600;
}
}
}
}
.footer {
display: flex;
align-items: center;
width: 100%;
background-color: #ffffff;
z-index: 100;
height: 104px;
box-shadow: 0px -2px 8px 0px rgba(214, 214, 214, 0.5);
position: fixed;
left: 0;
bottom: 0;
.sum {
width: calc(100% - 212px);
box-sizing: border-box;
padding: 30px;
display: flex;
justify-content: space-between;
& > span:nth-child(1),
span:nth-child(2) {
font-size: 32px;
font-weight: 400;
color: #f94246;
& > span {
font-size: 24px;
margin-left: 12px;
}
}
}
.btn {
width: 212px;
height: 100%;
background-color: #1365dd;
font-size: 36px;
font-weight: 500;
color: #ffffff;
display: flex;
align-items: center;
justify-content: center;
}
}
.hidden {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
}
</style>

View File

@@ -0,0 +1,117 @@
<template>
<div class="search">
<div class="search-wrap">
<u-search :show-action="false" placeholder="请输入手机号或身份证号搜索" v-model.trim="keyword" @search="search"></u-search>
</div>
<div class="result-body">
<div class="res-item" v-if="result" @click="selected">
<span>{{ result.familyName }}</span>
<span>剩余积分:{{ result.familyIntegral }}</span>
</div>
<span class="placeholder" v-else>请通过搜索
<strong>手机号或身份证号</strong>
后选择结算对象
</span>
</div>
<u-modal v-model="show" title="温馨提示" @confirm="confirm" content="该手机号绑定了多个居民,请通过身份证号进行查询"
:confirm-style="{fontWeight:800}"></u-modal>
</div>
</template>
<script>
export default {
name: "search",
data() {
return {
keyword: "",
show: false,
result: null,
}
},
methods: {
selected() {
uni.navigateBack({
delta: 1,
success: () => {
uni.$emit('selected', this.result)
},
fail: (err) => {
console.error(err)
}
})
},
search() {
if (this.keyword == "") {
return uni.showToast({
title: "请输入搜索关键字",
icon: 'none'
})
}
this.$instance.post(`/app/appresident/queryFamilyByPhone`, null, {
params: {
phone: this.keyword
}
}).then(res => {
if (res && res.data) {
this.result = res.data
}
}).catch(e => {
this.result = null
uni.showToast({
title: e,
icon: 'none'
})
})
},
confirm() {
this.show = false
}
}
}
</script>
<style lang="scss" scoped>
.search {
min-height: 100%;
background-color: #ffffff;
.search-wrap {
width: 100%;
box-sizing: border-box;
padding: 24px 32px;
}
.result-body {
.res-item {
height: 112px;
border-bottom: 1px solid #F5F5F5;
box-sizing: border-box;
padding: 0 56px;
display: flex;
align-items: center;
justify-content: space-between;
& > span {
font-size: 32px;
color: #333333;
}
}
.placeholder {
display: flex;
justify-content: center;
margin-top: 144px;
font-size: 28px;
color: #999999;
& > strong {
color: #135AB8;
}
}
}
}
</style>

View File

@@ -0,0 +1,240 @@
<template>
<div class="news">
<div class="header">
<div class="header-search">
<u-icon name="search" class="icon-search" size="40" color="rgba(255,255,255,0.5)"></u-icon>
<input placeholder="请输入标题" v-model="title" @confirm="onConfirm" confirm-type="search"
placeholder-style="color:rgba(255,255,255,0.5);">
</div>
</div>
<div class="topic-list">
<div class="topic-item" v-for="(item, index) in list" :key="index" hover-class="bg-hover"
@click="$linkTo(`./detail?id=${item.id}`)">
<div class="topic-item__left">
<h2>{{ item.title }}</h2>
<p>{{ item.publishTime }}</p>
</div>
<image :src="item.thumbUrl" mode="aspectFill"/>
</div>
</div>
<div class="loading">
<u-loadmore :status="loadingStatus"/>
</div>
</div>
</template>
<script>
export default {
name:"AppTopic",
appName:"热点话题",
data() {
return {
title: '',
isLoading: false,
list: [],
isShowEmpty: false,
isMore: false,
current: 0,
areaId: '',
loadingStatus: 'loadmore'
}
},
onLoad() {
this.areaId = uni.getStorageSync('areaId')
this.getList(uni.getStorageSync('areaId'))
},
methods: {
onConfirm() {
this.loadingStatus = 'loadmore'
this.current = 0
this.$loading()
this.$nextTick(() => {
this.getList(this.areaId)
})
},
getList(areaId) {
if (this.loadingStatus === 'loading' || this.loadingStatus === 'nomore') return
this.loadingStatus = 'loading'
this.$instance.post(`/app/apphotsubject/listForWx?current=${this.current + 1}&size=10&status=1&title=${this.title}`, null, {
withoutToken: 1
}).then(res => {
if (res.code === 0) {
if (this.current === 0) {
this.list = []
}
const data = res.data.records
this.list.push(...data)
this.current = this.current + 1
this.loadingStatus = 'loadmore'
if (!res.data.records.length || res.data.records.length < 10) {
this.loadingStatus = 'nomore'
}
} else {
this.loadingStatus = 'loadmore'
}
}).catch(() => {
this.loadingStatus = 'loadmore'
})
},
toDetail(id) {
this.$linkTo(`./newsDetail?id=${id}&areaId=${this.areaId}`)
}
},
onReachBottom() {
this.getList(this.areaId)
}
}
</script>
<style lang="scss" scoped>
.news {
min-height: 100vh;
background: #F3F6F9;
padding-bottom: 40px;
}
.loading {
margin-top: 40px;
}
.topic-item {
display: flex;
width: 686px;
height: 208px;
margin: 32px auto 0;
padding: 32px;
background: #FFFFFF;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.02);
border-radius: 8px;
overflow: hidden;
.topic-item__left {
flex: 1;
margin-right: 32px h2 {
height: 88px;
line-height: 44px;
margin-bottom: 16px;
color: #333333;
font-size: 32px;
text-align: justify;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
p {
color: #999999;
font-size: 28px;
}
}
image {
flex-shrink: 1;
width: 192px;
height: 144px;
}
}
div {
box-sizing: border-box;
}
.noMore {
line-height: 90px;
text-align: center;
color: #999;
font-size: 26px;
}
.topic-list {
padding-top: 112px;
}
.header {
position: fixed;
top: 0;
left: 0;
z-index: 11;
width: 100%;
height: 112px;
padding: 20px 0 0 0;
background: #4181FF;
.header-search {
display: flex;
align-items: center;
width: 690px;
height: 60px;
margin: 0 auto8px;
padding: 032px;
background: rgba(0, 0, 0, .2);
border-radius: 30px;
.icon-search {
flex-shrink: 1;
width: 32px;
height: 32px;
margin-right: 16px;
}
input {
flex: 1;
height: 100%;
font-size: 28px;
color: #fff;
}
}
.header-tab {
display: flex;
justify-content: center;
height: 80px;
padding-top: 16px;
background: #2D80FB;
span {
margin-right: 50px;
padding-bottom: 24px;
font-size: 28px;
color: #fff;
border-bottom: 4px solid transparent;
&:last-child {
margin-right: 0;
}
&.active {
color: #fff;
border-bottom: 4px solid #fff;
}
}
}
}
.no-more {
margin-top: 20px;
text-align: center;
color: #999;
image {
width: 400px;
height: 240px;
}
p {
text-align: center;
color: #999;
font-size: 28px;
}
}
</style>

View File

@@ -0,0 +1,204 @@
<template>
<div class="topic-detail" v-if="pageShow">
<div class="topic-header">
<h2>{{ info.title }}</h2>
<p>{{ info.publishTime }}</p>
<div class="topic-tags">
<span v-for="(item, index) in info.keyWords" :key="index">{{ item }}</span>
</div>
</div>
<div class="topic-list">
<div class="topic-item" v-for="(item, index) in info.contents" :key="index">
<div class="topic-item__top">
<image src="/static/img/rmht.png"/>
<div class="topic-item__top--right">
<h2>{{ item.question }}</h2>
<p>{{ item.questionSource }}</p>
</div>
</div>
<div class="topic-item__bottom">
<h2 v-if="item.answerSource">
<span style="color:#000;"> {{ item.answerSource }} </span>
回复
</h2>
<h2 v-else>话题回复</h2>
<p>{{ item.answer }}</p>
<div class="topic-item__img">
<image v-for="(img, i) in item.files" :key="i" :src="img.url" mode="aspectFill" hover-class="text-hover"
@click="preview(img.url, item.files)"/>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
info: {},
id: '',
pageShow: false
}
},
onLoad(query) {
this.$loading()
this.id = query.id
this.getInfo()
},
methods: {
getInfo() {
this.$instance.post(`/app/apphotsubject/detailForWx?id=${this.id}`).then(res => {
if (res.code === 0) {
this.info = res.data
if (res.data.keyWords) {
this.info.keyWords = res.data.keyWords.split(',')
}
this.$nextTick(() => {
this.pageShow = true
})
this.$hideLoading()
}
})
},
preview(img, imgs) {
uni.previewImage({
current: img,
urls: imgs.map(v => v.url)
})
}
},
onShareAppMessage() {
return {
title: this.info.title,
path: `/mods/AppTopic/detail?id=${this.id}`
}
}
}
</script>
<style lang="scss" scoped>
.topic-detail {
* {
box-sizing: border-box;
}
.topic-list {
margin-top: 16px;
}
.topic-item__bottom {
margin-top: 22px;
padding: 24px 24px;
background: #FFFFFF;
border-radius: 16px;
border: 1px solid #D8DDE6;
.topic-item__img {
margin-top: 16px;
font-size: 0;
image {
width: 206px;
height: 206px;
margin: 0 10px 10px 0;
border-radius: 8px;
&:nth-of-type(3n) {
margin-right: 0;
}
}
}
p {
color: #333333;
font-size: 32px;
text-align: justify;
}
h2 {
margin-bottom: 16px;
color: #1365DD;
font-size: 26px;
}
}
.topic-item {
margin-bottom: 16px;
padding: 32px;
background: #fff;
.topic-item__top--right {
flex: 1;
h2 {
line-height: 1.3;
margin-bottom: 16px;
font-size: 32px;
color: #333;
text-align: justify;
white-space: pre-line;
}
p {
color: #343D65;
font-size: 28px;
}
}
.topic-item__top {
display: flex;
image {
position: relative;
top: 6px;
width: 32px;
height: 32px;
margin-right: 16px;
}
}
}
.topic-header {
padding: 32px 32px 16px;
background: #FFFFFF;
border-bottom: 1px solid #D8DDE6;
.topic-tags {
font-size: 0;
span {
display: inline-block;
height: 48px;
line-height: 48px;
margin: 0 16px 16px 0;
padding: 016px;
color: #6179A7;
font-size: 28px;
background: #F4F5FA;
border-radius: 24px;
}
}
h2 {
line-height: 1.3;
margin-bottom: 16px;
font-size: 40px;
color: #333333;
text-align: justify;
}
p {
margin-bottom: 16px;
color: #999999;
font-size: 28px;
}
}
}
</style>

View File

@@ -0,0 +1,229 @@
<template>
<div class="page">
<div class="village-info">
<div class="header-content">
<img src="https://cdn.cunwuyun.cn/dvcp/villgroup/group.png" alt="" class="group-img">
<div class="group-name">{{ info.areaName || '' }}</div>
<p>已有{{ info.peopleNum || 0 }}户居民</p>
<img src="https://cdn.cunwuyun.cn/dvcp/villgroup/head.png" alt="" class="banner-img">
<div class="qrcode-content">
<img :src="info.codeUrl" class="qrcode-img">
<div>用微信或政务微信扫码加入</div>
</div>
</div>
<!-- <div class="user-content">
<div class="title">联村政干</div>
<div class="item">
<img src="https://cdn.cunwuyun.cn/dvcp/villgroup/group.png" alt="" class="user-img">
<div class="user-info">
<div class="item-line20 flex-b">
<div>余国明<span class="item-position">组长</span></div>
<div class="item-type">在岗</div>
</div>
<div class="item-line18 flex-b">
<div>上街组建新组后街组</div>
<div>13617896755</div>
</div>
</div>
</div>
</div> -->
</div>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
name: "AppVillageInfo",
appName: "一村一码",
computed: {
...mapState(['user', 'token'])
},
data() {
return {
areaId: '',
info: {}
}
},
onLoad(options) {
if (uni.getStorageSync('areaId')) {
this.areaId = uni.getStorageSync('areaId')
}
this.getDetail()
},
methods: {
getDetail() {
this.$instance.post(`/app/appeveryvillagecode/queryDetailByAreaId?areaId=${this.areaId}`).then(res => {
if (res.code === 0) {
this.info = res.data
}
})
}
},
onShareAppMessage() {
return {
title: '一村一码',
path: `/mods/AppVillageInfo/AppVillageInfo`
}
}
}
</script>
<style scoped lang="scss">
@import "../../common/common.scss";
.page {
width: 100%;
height: auto;
padding-top: 30px;
background-color: #f3f6f9;
.village-info {
padding-bottom: 48px;
.header-content {
padding: 40px 70px 56px;
width: 690px;
background: #FFF;
border-radius: 16px;
margin: 0 0 24px 30px;
box-sizing: border-box;
.group-img {
width: 92px;
height: 96px;
border-radius: 8px;
margin-bottom: 22px;
}
.group-name {
font-size: 36px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333;
line-height: 50px;
margin-bottom: 4px;
}
p {
font-size: 24px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #999;
line-height: 34px;
margin-bottom: 38px;
}
.banner-img {
width: 100%;
height: 110px;
}
.qrcode-content {
width: 100%;
height: 592px;
background: #F6F9FF;
border-radius: 12px;
border: 2px solid #E6EEFF;
padding: 56px 66px;
box-sizing: border-box;
margin-top: -8px;
.qrcode-img {
width: 420px;
height: 420px;
margin-bottom: 24px;
}
div {
font-size: 26px;
font-family: PingFangSC-Regular, PingFang SC;
color: #333;
line-height: 36px;
text-align: center;
}
}
}
.user-content {
padding: 16px 30px 64px;
width: 690px;
background: #FFF;
border-radius: 16px;
box-sizing: border-box;
margin-left: 30px;
.title {
line-height: 80px;
padding-left: 10px;
color: #333;
font-size: 32px;
font-weight: 500;
}
.item {
width: 100%;
padding: 28px 0 30px 0;
border-bottom: 2px solid #D8DDE6;
.user-img {
display: inline-block;
width: 72px;
height: 72px;
border-radius: 50%;
vertical-align: top;
}
.user-name-bg {
display: inline-block;
width: 72px;
height: 72px;
line-height: 72px;
text-align: center;
border-radius: 50%;
background-color: #4E8EEE;
color: #fff;
font-size: 24px;
vertical-align: top;
}
.user-info {
display: inline-block;
width: calc(100% - 72px);
padding-left: 16px;
box-sizing: border-box;
.flex-b {
display: flex;
justify-content: space-between;
}
.item-line20 {
line-height: 40px;
font-size: 28px;
color: #333;
margin-bottom: 8px;
.item-position {
color: #999;
font-size: 24px;
}
.item-type {
padding: 010px;
background: #E8EFFF;
color: #2266FF;
font-size: 24px;
}
}
.item-line18 {
line-height: 36px;
color: #666;
font-size: 26px;
}
}
}
}
}
}
</style>

View File

@@ -0,0 +1,466 @@
<template>
<section class="AppOnlineAnswer">
<div class="page" v-if="list.length">
<img src="./static/img/answer-bg.png" alt="" class="bg-img">
<div class="subject-content" v-if="!showAnwser">
<div class="btn" v-if="showTopBtn" @click="confirm()">{{ topBtnText }}</div>
<div class="bg-fff pad-b48">
<div class="title">
<div class="left">
<span class="tips"></span>{{ list[index].type == 1 ? '单选' : '多选' }}
</div>
<div class="right">
<span class="big-num">{{ index + 1 }}</span>/{{ list.length }}
</div>
</div>
<div class="text">{{ list[index].title }}</div>
<!-- 单选 -->
<div v-if="list[index].type == 1">
<div class="item" v-for="(item, i) in list[index].items" :key="i" @click="itemClick(i)"
:class="{ 'item-click': clickIndex === i, 'item-success': showAnalysis && item.checked == 1, 'item-error': showAnalysis && clickIndex == i && item.checked == 0}">
<img src="./static/img/success-icon.png" alt="" v-if="showAnalysis && item.checked == 1">
<img src="./static/img/error-icon.png" alt=""
v-if="showAnalysis && clickIndex == i && item.checked == 0">
{{ item.sort }} &nbsp;{{ item.content }}
</div>
</div>
<!-- 多选 -->
<div v-if="list[index].type == 2">
<div class="item" v-for="(item, i) in list[index].items" :key="i" @click="itemClick(i)"
:class="{ 'item-click': item.isCheked, 'item-success': showAnalysis && item.checked == 1, 'item-error': showAnalysis && item.isCheked && item.checked == 0}">
<img src="./static/img/success-icon.png" alt="" v-if="showAnalysis && item.checked == 1">
<img src="./static/img/error-icon.png" alt=""
v-if="showAnalysis && clickIndex == i && item.checked == 0">
{{ item.sort }} &nbsp;{{ item.content }}
</div>
</div>
<!-- <div class="item item-click">A. 吴起镇</div>
<div class="item item-success"> <img src="./static/img/success-icon.png" alt="">吴起镇</div>
<div class="item item-error"> <img src="./static/img/error-icon.png" alt="">吴起镇</div>
<div class="item">A. 吴起镇</div> -->
</div>
<div class="bg-fff mar-t32" v-if="showAnalysis">
<div class="title">
<div class="left">
<span class="tips"></span>答案解析
</div>
</div>
<div class="success-title">正确答案{{ list[index].answer }}</div>
<div class="success-text">
<u-parse :html="list[index].analysis"></u-parse>
</div>
</div>
</div>
<div class="subject-content" v-else>
<div class="bg-fff pad-b48">
<img src="./static/img/answer-head.png" alt="" class="head-img">
<div class="head-content">
<p>本次答对题目数</p>
<div>{{ resultInfo.right }}</div>
</div>
<div class="info-content">
<span class="info-item">正确率: {{ resultInfo.rate }}</span>
<span class="info-item">用时: {{ useTime }}</span>
<span class="info-item mar-b132">错题数: {{ resultInfo.wrong }}</span>
</div>
<span class="big-btn mar-r22" @click="back">返回</span>
<span class="big-btn bg-red" @click="again">再来一组</span>
</div>
</div>
</div>
<AiEmpty v-if="list.length == 0"/>
</section>
</template>
<script>
import {mapState} from "vuex";
export default {
name: "AppOnlineAnswer",
appName: "在线答题",
computed: {
...mapState(["user", "token"]),
},
data() {
return {
showAnwser: false,
index: 0,
clickIndex: '',
list: [],
showTopBtn: false,
topBtnText: '',
showAnalysis: false,
createdTime: '',
endTime: '',
useTime: '',
resultInfo: {}
};
},
onLoad() {
this.createdTime = Date.parse(new Date())
this.getList()
},
methods: {
itemClick(i) {
if (this.showAnalysis) return
if (this.list[this.index].type == 1) { //单选
this.clickIndex = i
this.showTopBtn = true
}
if (this.list[this.index].type == 2) { //多选
this.showTopBtn = false
this.list[this.index].items[i].isCheked = !this.list[this.index].items[i].isCheked
this.list[this.index].items.map((item) => {
if (item.isCheked) {
this.showTopBtn = true
}
})
}
this.topBtnText = '确定'
},
confirm() {
if (this.list[this.index].type == 1) { //单选
this.list[this.index].result = this.list[this.index].items[this.clickIndex].sort
}
if (this.list[this.index].type == 2) { //多选
var resultList = []
this.list[this.index].items.map((item) => {
if (item.isCheked) {
resultList.push(item.sort)
}
})
this.list[this.index].result = resultList.join(',')
}
console.log(this.list)
if (this.topBtnText == '下一题') { //next
if (this.index < this.list.length - 1) {
this.index++
this.init()
} else { //答完了
this.showTopBtn = false
this.endTime = Date.parse(new Date());
this.useTime = this.intervalTime(this.endTime - this.createdTime)
this.getResult()
}
}
if (this.topBtnText == '确定') { //确定选项
this.showAnalysis = true
this.topBtnText = '下一题'
}
},
getResult() {
this.$instance.post(`/app/apppartyquestion/checkAnswer`, this.list).then((res) => {
if (res.code == 0) {
this.resultInfo = res.data
this.showAnwser = true
}
});
},
getList() {
this.$instance.post(`/app/apppartyquestion/getQuestions`).then((res) => {
if (res.code == 0) {
res.data.map((item) => {
item.answerList = []
item.items.map((i) => {
if (i.checked == 1) {
item.answerList.push(i.sort)
}
})
item.answer = item.answerList.join(',')
if (item.type == 2) { //多选
item.isCheck = false
}
})
this.list = res.data
}
});
},
intervalTime(time) {
var leave1 = time % (24 * 3600 * 1000); //计算天数后剩余的毫秒数
var hours = Math.floor(leave1 / (3600 * 1000));
hours = hours < 10 ? '0' + hours : hours
var leave2 = leave1 % (3600 * 1000); //计算小时数后剩余的毫秒数
var minutes = Math.floor(leave2 / (60 * 1000));
minutes = minutes < 10 ? '0' + minutes : minutes
var leave3 = leave2 % (60 * 1000); //计算分钟数后剩余的毫秒数
var seconds = Math.round(leave3 / 1000);
seconds = seconds < 10 ? '0' + seconds : seconds
return hours + ":" + minutes + ":" + seconds
},
back() {
uni.navigateBack({delta: 1})
},
again() {
this.init()
this.index = 0
this.list = []
this.getList()
this.createdTime = Date.parse(new Date())
},
init() {
this.showAnwser = false
this.clickIndex = ''
this.showTopBtn = false
this.topBtnText = ''
this.showAnalysis = false
}
},
};
</script>
<style scoped lang="scss">
@import "../../../common/common.css";
.AppOnlineAnswer {
width: 100%;
height: 100%;
}
.page {
width: 100%;
height: 100%;
background-color: #F6F6F6;
.bg-img {
width: 100%;
height: 800px;
}
.subject-content {
width: 100%;
border-radius: 4px;
padding: 24px 36px 48px 36px;
box-sizing: border-box;
position: absolute;
top: 124px;
z-index: 9;
.btn {
padding: 0 30px;
height: 64px;
line-height: 64px;
text-align: center;
background: #D03A28;
border-radius: 4px;
font-size: 28px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #FFF;
position: absolute;
top: -100px;
right: 36px;
z-index: 99;
}
.pad-top {
padding-top: 100px;
}
.pad-b48 {
padding-bottom: 48px;
}
.mar-t32 {
margin-top: 32px;
}
.bg-fff {
width: 100%;
background-color: #fff;
border-radius: 4px;
box-shadow: 0 6px 8px 4px rgba(218, 227, 234, 0.42);
position: relative;
.title {
width: 100%;
height: 100px;
border-bottom: 1px solid #F2F3F5;
padding: 24px 30px;
box-sizing: border-box;
display: flex;
justify-content: space-between;
.left {
font-size: 36px;
font-family: PingFang-SC-Heavy, PingFang-SC;
font-weight: 800;
color: #333;
line-height: 50px;
.tips {
display: inline-block;
width: 8px;
height: 36px;
background: #E02617;
margin-right: 16px;
}
}
.right {
font-size: 34px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #999;
line-height: 48px;
.big-num {
font-size: 72px;
font-family: PingFang-SC-Heavy, PingFang-SC;
font-weight: 800;
color: #333;
}
}
}
.text {
padding: 48px 40px;
font-size: 32px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333;
line-height: 48px;
word-break: break-all;
}
.item {
width: 612px;
background: #FAFBFC;
border-radius: 12px;
border: 1px solid #F2F3F5;
margin-bottom: 28px;
margin-left: 32px;
padding: 26px 48px;
box-sizing: border-box;
font-size: 32px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #687178;
line-height: 44px;
img {
width: 36px;
height: 36px;
vertical-align: middle;
margin-right: 14px;
}
}
.item-click {
background: #F5F5F2;
border: 1px solid #AD9B8D;
color: #B7A38E;
}
.item-success {
background: #E9FAF0;
border: 1px solid #E9FAF0;
color: #40BF6F;
}
.item-error {
background: #FDEBEB;
border: 1px solid #FDEBEB;
color: #D03A28;
}
.success-title {
padding: 32px 0 0 40px;
font-size: 32px;
font-family: PingFang-SC-Heavy, PingFang-SC;
font-weight: 800;
color: #333;
line-height: 44px;
}
.success-text {
padding: 32px 40px 56px;
font-size: 32px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333;
line-height: 48px;
word-break: break-all;
}
.head-img {
width: 100%;
height: 260px;
}
.head-content {
position: absolute;
width: 100%;
height: 260px;
top: 0;
left: 0;
padding: 56px 0 0 72px;
box-sizing: border-box;
p {
font-size: 38px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #FBE5E6;
line-height: 52px;
}
div {
font-size: 100px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #FBE5E6;
line-height: 140px;
}
}
.info-content {
padding: 88px 32px 40px;
.info-item {
display: inline-block;
width: 300px;
font-size: 34px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #666;
line-height: 48px;
margin-bottom: 42px;
}
.mar-b132 {
margin-bottom: 132px;
}
}
.big-btn {
display: inline-block;
width: 296px;
height: 88px;
line-height: 88px;
text-align: center;
border-radius: 4px;
border: 1px solid #E4E5E7;
font-size: 34px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #666;
}
.bg-red {
border: 0;
background: #D03A28;
color: #fff;
}
.mar-r22 {
margin: 0 22px 0 32px;
}
}
}
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,389 @@
<template>
<section class="AppPartyHistory">
<div v-if="isShow" style="height: 100%">
<!-- 头部搜索样式 -->
<div class="fixed-top" style="width:100%;">
<div class="search-box">
<div class="search-input flex-row" @click="changeSearchBox">
<img src="https://cdn.cunwuyun.cn/img/search-red.svg"/>
<span class="color-fff">请输入文章标题</span>
</div>
</div>
<!-- 选择时间和类型 -->
<div class="slect flex-row">
<!-- 类型选择 -->
<div class="uni-list type-slect">
<div class="uni-list-cell">
<div class="uni-list-cell-db">
<picker @change="bindPickerChange" :value="index" :range="array" range-key="dictName">
<div class="uni-input">{{ partyType }}</div>
<img src="https://cdn.cunwuyun.cn/img/down.svg"/>
</picker>
</div>
</div>
</div>
<!-- 时间选择 -->
<div class="uni-list type-slect">
<div class="uni-list-cell">
<div class="uni-list-cell-db">
<picker
mode="date"
:value="date"
:start="startDate"
:end="endDate"
@change="bindDateChange"
fields="month"
>
<div class="uni-input">{{ day }}</div>
<img src="https://cdn.cunwuyun.cn/img/down.svg"/>
</picker>
</div>
</div>
</div>
</div>
</div>
<!-- 党务公开列表 -->
<div class="affairs-list">
<div class="affairs" v-if="affairsList.length > 0">
<!-- 循环 v-for -->
<div v-for="(item, index) in affairsList" :key="index">
<div class="affairs-item" @click="getDetail(item.id)">
<div class="break-word">
<span class="type">{{ $dict.getLabel(`partyHistoryType${style}`, item.type) }}</span>
<span class="affirs-title">{{ item.title }}</span>
</div>
<div class="created-unit flex-row">
<span>{{ item.organizationName || "" }}</span>
<span>{{ item.createDate }}</span>
</div>
</div>
</div>
</div>
</div>
<AiEmpty v-if="affairsList.length == 0"/>
</div>
<div v-if="!isShow" class="search-input">
<div class="input-box flex-row">
<input
type="text"
class="input"
placeholder="请输入文章标题"
focus="false"
v-model="searchValue"
@blur="onBlur"
/>
<img
class="sousuo"
src="https://cdn.cunwuyun.cn/img/search-active.svg"
/>
<img
v-if="searchValue"
@tap="clearInput"
class="clear"
src="https://cdn.cunwuyun.cn/img/empty-Input.svg"
/>
<div class="search-word" @click="search">搜索</div>
</div>
</div>
</section>
</template>
<script>
import {mapState} from "vuex";
export default {
name: "AppPartyHistory",
appName: "党史文章",
data() {
const currentDate = this.getDate({
format: true,
});
return {
inputValue: "请输入文章标题",
isShow: true,
array: [],
index: 0,
partyType: "类型",
partyTypeIndex: "", //类型index 0:党务公开,1:三会一课
date: currentDate,
day: "时间",
createData: "", //创建时间
affairsList: [],
searchValue: "", //搜索框输入值
pageNum: 1,
pageSize: 10,
pages: 2,
style: '',
};
},
computed: {
startDate() {
return this.getDate("start");
},
endDate() {
return this.getDate("end");
},
...mapState(["user"]),
},
onLoad(option) {
this.style = option.style
this.$dict.load("partyHistoryType0", "partyHistoryType1", "partyHistoryType2").then(() => {
this.array = this.$dict.getDict(`partyHistoryType${this.style}`)
this.array.unshift({dictName: "全部类型", dictValue: ""})
this.getPartyList()
})
},
methods: {
bindPickerChange(e) {
this.partyType = this.array[e.detail.value].dictName;
this.partyTypeIndex = this.array[e.detail.value].dictValue;
this.pageNum = 1;
this.pages = 2;
this.pageSize = 10;
this.getPartyList();
},
bindDateChange: function (e) {
this.day = e.target.value;
this.createData =
e.target.value + "-" + "08" + " " + "00" + ":" + "00" + ":" + "00";
this.pageNum = 1;
this.pages = 2;
this.pageSize = 10;
this.getPartyList();
},
getDate(type) {
const date = new Date();
let year = date.getFullYear();
let month = date.getMonth() + 1;
let day = date.getDate();
if (type === "start") {
year = year - 60;
} else if (type === "end") {
year = year + 2;
}
month = month > 9 ? month : "0" + month;
day = day > 9 ? day : "0" + day;
return `${year}-${month}-08 00:00:00 `;
},
changeSearchBox() {
this.isShow = false;
},
onBlur(e) {
this.searchValue = e.target.value;
if (this.searchValue) {
this.inputValue = this.searchValue;
} else {
this.inputValue = "请输入文章标题";
}
},
search() {
this.isShow = true;
this.pageNum = 1;
this.pageSize = 10;
this.pages = 2;
this.getPartyList();
},
clearInput() {
this.searchValue = "";
this.inputValue = "请输入文章标题";
},
getDetail(id) {
uni.navigateTo({
url: `./detail?id=${id}`,
});
},
getPartyList() {
if (this.pageNum > this.pages) return;
this.$instance.post(`/app/apppartyhistory/listWechat`, {
condition: this.searchValue,
style: this.style,
type: this.partyTypeIndex,
createDate: this.createData,
current: this.pageNum,
size: this.pageSize,
// organizationId: this.user.partyOrgId
}).then((res) => {
if (res.code == 0) {
const affairsList = this.pageNum > 1 ? [...this.affairsList, ...res.data.records] : res.data.records;
this.pages = Math.ceil(res.data.total / 10);
this.affairsList = affairsList;
}
});
},
},
onReachBottom() {
this.pageNum = this.pageNum + 1;
this.getPartyList();
},
};
</script>
<style lang="scss" scope>
@import "../../../common/common.css";
.AppPartyHistory {
.search-box {
width: 100%;
height: 112px;
background-color: #D7261E;
padding: 24px 32px;
box-sizing: border-box;
.search-input {
line-height: 64px;
width: 100%;
height: 100%;
background: #ce0010;
// background:rgba(0,0,0,1);
border-radius: 32px;
// opacity: 0.1;
color: #f0cbcd;
font-size: 26px;
img {
width: 40px;
height: 40px;
margin: 8px 8px 8px 24px;
position: relative;
top: 6px;
}
.color-fff {
color: #fff;
}
}
}
.slect {
width: 100%;
height: 96px;
background-color: #fff;
color: #666;
.type-slect {
width: 50%;
border-right: 1px solid #f7f7f7;
margin: 30px 0;
box-sizing: border-box;
text-align: center;
font-size: 26px;
.uni-input {
display: inline-block;
}
img {
width: 32px;
height: 32px;
display: inline-block;
position: relative;
top: 6px;
margin-left: 8px;
}
}
.type-slect:nth-child(2) {
border: none;
}
}
.affairs-list {
width: 100%;
// height:calc(100% - 210px);
// overflow-y: auto;
padding-top: 200px;
.affairs {
background-color: #fff;
margin: 32px;
.affairs-item {
padding: 32px;
box-sizing: border-box;
.type {
padding: 8px;
box-sizing: border-box;
background-color: #e6edf7;
color: #135ab8;
font-size: 26px;
margin-right: 16px;
border-radius: 8px;
}
.affirs-title {
color: #333333;
font-size: 32px;
}
.created-unit {
font-size: 28px;
color: #999;
justify-content: space-between;
margin-top: 16px;
}
}
}
}
.no-affairs {
width: 100%;
height: calc(100% - 210px);
display: flex;
justify-content: center;
align-items: center;
}
.search-input {
// width:100%;
// height:112px;
.input-box {
width: 100%;
height: 112px;
background-color: #fff;
padding: 24px 32px;
box-sizing: border-box;
position: relative;
.sousuo {
position: absolute;
top: 35px;
left: 60px;
width: 40px;
height: 40px;
}
.input {
background-color: #f3f3f3;
width: 598px;
height: 64px;
color: #999999;
font-size: 26px;
margin-left: 8px;
border-radius: 32px;
padding-left: 70px;
padding-right: 60px;
box-sizing: border-box;
}
.clear {
width: 32px;
height: 32px;
position: absolute;
top: 40px;
right: 130px;
z-index: 10;
}
.search-word {
font-size: 28px;
color: #135ab8;
line-height: 60px;
margin-left: 20px;
}
}
}
}
</style>

View File

@@ -0,0 +1,147 @@
<template>
<div>
<scroll-view
scroll-y
class="commentList"
@scrolltolower="page.current++, getComments()"
>
<div class="comments-list" v-if="commentList.length">
<div
class="comments-item flex-row"
v-for="(item, i) in commentList"
:key="i"
>
<div class="user-avatar">
<image v-if="item.avatar" :src="item.avatar"></image>
<image v-else src="https://cdn.cunwuyun.cn/img/personal.png"></image>
</div>
<div class="content flex-column">
<div class="flex-row" style="justify-content: space-between">
<text>{{ item.createUser }}</text>
<text class="commentTime">{{ item.commentTime }}</text>
</div>
<div>{{ item.content }}</div>
</div>
</div>
</div>
<AiEmpty v-else/>
<view class="tips" v-if="commentList.length"> 已加载全部评论</view>
</scroll-view>
</div>
</template>
<script>
export default {
name: "commentList",
props: {
detail: Object,
},
data() {
return {
commentList: [],
page: {
current: 1,
size: 10000,
},
};
},
methods: {
getComments() {
this.$instance.post(`/app/apppartyhistorycomment/list?partyHistoryId=${this.detail.id}&size=10000`).then((res) => {
if (res && res.data) {
this.commentList = res.data.records;
this.$emit("comments", res.data.total);
}
});
},
},
mounted() {
this.$nextTick(() => this.getComments());
},
};
</script>
<style lang="scss" scoped>
.commentList {
width: 100%;
margin-bottom: 135px;
overflow-y: auto;
.comments-list {
width: 100%;
overflow-y: auto;
box-sizing: border-box;
.user-avatar {
display: inline-block;
width: 80px;
margin: 46px 20px 0 0;
image {
width: 80px;
height: 80px;
border-radius: 50%;
}
.user-bg {
display: inline-block;
width: 80px;
height: 80px;
border-radius: 50%;
line-height: 80px;
text-align: center;
background-color: #26f;
color: #fff;
font-size: 28px;
}
}
.comments-item {
border-bottom: 1px solid #f7f7f7;
padding: 0 32px;
color: #333;
font-size: 28px;
background-color: #fff;
& + .comments-item {
border-top: 4px solid #eee;
}
.content {
display: inline-block;
width: calc(100% - 120px);
background-color: #fff;
padding: 46px 0 32px 0;
box-sizing: border-box;
.name {
margin-bottom: 10px;
}
}
.commentTime {
color: #999;
font-size: 24px;
}
}
}
.tips {
line-height: 90px;
width: 100%;
color: #999;
font-size: 24px;
text-align: center;
background-color: #f3f6f9;
}
.no-comment-list {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
font-size: 30px;
}
}
</style>

View File

@@ -0,0 +1,280 @@
<template>
<div class="page">
<div>
<div v-if="!showCommentList" class="detail">
<!-- 文章标题 -->
<div class="created-unit">
<div class="artical-title break-word">{{ affairs.title }}</div>
<div class="artical-unit">
<span> 发布党组织 {{ affairs.organizationName || "-" }}</span>
</div>
<div class="artical-unit">
<text>发布时间{{ affairs.createDate }}</text>
<text/>
</div>
</div>
<!-- 文章内容 -->
<div class="artical-content break-word">
<u-parse :html="affairs.content" class="content" v-if="affairs.content"></u-parse>
</div>
<!-- 语音播报-->
<AiTransSpeech :src="affairs.speech" v-if="affairs.speech"/>
</div>
<commentList v-else :detail="affairs"></commentList>
<AiComment
:comment-count="commentCount"
@submitComment="submitComment"
@showCommentList="showCommentList = true"
/>
</div>
</div>
</template>
<script>
import {mapState} from "vuex";
import commentList from './commentList'
export default {
name: "policyDetail",
components: {commentList},
computed: {
...mapState(["user"]),
},
data() {
return {
affairs: {},
showCommentList: false,
commentCount: 0,
};
},
onLoad(options) {
this.$dict.load("policyPromotionType");
this.id = options.id;
this.getPartyAffairsDetail(this.id);
this.getCount();
},
methods: {
getCount() {
this.$instance.post(`/app/apppartyhistorycomment/list?partyHistoryId=${this.id}`).then((res) => {
if (res && res.data) {
this.commentCount = res.data.total;
}
});
},
getPartyAffairsDetail(id) {
this.$instance.post(`/app/apppartyhistory/queryDetailByIdWeChat?id=${id}`).then((res) => {
if (res && res.data) {
res.data.createDate = res.data.createDate.substring(0, 10);
const regex = new RegExp("<img", "gi");
res.data.content = res.data.content
.replace(
regex,
`<img style="max-width:100%!important;" calss="img"`
)
.replace(/<p([\s\w"=\/\.:;]+)((?:(class="[^"]+")))/gi, "<p")
.replace(/<p>/gi, '<p class="p_class">')
.replace(/style=""/g, 'style="max-width:100%!important;"');
res.data.content = res.data.content.replace(
/<img[^>]*>/gi,
function (match) {
return match.replace(
/style\s*?=\s*?(["])[\s\S]*?\1/gi,
'style="max-width:100%;"'
); // 替换style
}
);
if (res.data.files && res.data.files.length) {
res.data.files.map(item => {
var size = item.size / 1024;
item.fileSize = size.toFixed(0);
return item
})
}
this.affairs = {...res.data};
}
});
},
back() {
if (getCurrentPages().length === 1) {
uni.switchTab({
url: "/pages/home/home",
});
return false;
}
this.showCommentList
? (this.showCommentList = false)
: uni.navigateBack();
},
submitComment(content) {
this.$instance
.post("/app/apppartyhistorycomment/addOrUpdate", {
partyHistoryId: this.affairs.id,
content: content,
name: this.user.nickName,
avatar: this.user.avatarUrl,
organizationId: this.affairs.organizationId
})
.then((res) => {
if (res && res.code == 0) {
uni.showToast({icon: "success", title: "评论成功"});
this.showCommentList = true
this.getCount()
} else {
uni.showToast({icon: "none", title: res.msg});
}
})
.catch((err) => {
uni.showToast({icon: "none", title: err});
});
},
},
};
</script>
<style lang="scss" scoped>
@import "../../../common/common.css";
.page {
.navHeadBar {
display: flex;
justify-content: space-between;
align-items: center;
background: #135ab8;
color: #fff;
font-size: 13px;
height: 40px;
}
.detail {
width: 100%;
overflow-y: auto;
.created-unit {
width: 100%;
padding: 32px;
box-sizing: border-box;
background-color: #D40A05;
color: #fff;
.artical-title {
font-size: 40px;
}
.artical-unit {
font-size: 28px;
margin-top: 16px;
opacity: 0.8;
}
}
.artical-content {
color: #666666;
font-size: 32px;
padding: 32px 32px 128px 32px;
box-sizing: border-box;
background-color: #fff;
.p_class {
margin-top: 40px;
font-size: 32px;
color: #333;
text-indent: 0;
width: 100%;
}
.img {
width: 100% !important;
}
}
.attachment {
width: 100%;
padding: 32px 32px 96px 32px;
box-sizing: border-box;
background-color: #ffffff;
margin-top: 16px;
.attachment-title {
font-size: 32px;
color: #333333;
font-weight: 500;
image {
width: 48px;
height: 48px;
vertical-align: middle;
}
}
}
}
}
.p_class {
margin-top: 40px;
font-size: 32px;
color: #333;
text-indent: 0;
width: 100%;
}
.img {
max-width: 100% !important;
}
.attachment {
width: 100%;
padding: 32px;
box-sizing: border-box;
background-color: #FFFFFF;
margin-top: 16px;
.attachment-title {
font-size: 32px;
color: #333333;
font-weight: 500;
image {
width: 48px;
height: 48px;
vertical-align: middle;
}
}
.attachment-item {
border: 1px solid rgba(204, 204, 204, 1);
padding: 16px;
box-sizing: border-box;
margin-top: 34px;
display: flex;
flex-direction: row;
justify-content: space-between;
border-radius: 8px;
.file-name {
justify-content: flex-start;
align-items: center;
image {
width: 96px;
height: 96px;
vertical-align: middle;
}
.title {
color: #333333;
font-size: 32px;
word-break: break-all;
flex: 1;
}
}
.size {
color: #999;
font-size: 28px;
display: flex;
justify-content: cemter;
align-items: center;
}
}
}
</style>

View File

@@ -0,0 +1,335 @@
<template>
<section class="AppPartyHistoryEducation">
<div class="page">
<div class="title">
<div class="left">
<span class="tips"></span>党史上的今天
</div>
<div class="right" @click="handleGoto('./todayList')">
查看全部
<img src="https://cdn.cunwuyun.cn/img/down.svg" class="right-icon">
</div>
</div>
<div class="header" v-for="(item, index) in todayList" :key="index"
@click="handleGoto(`./todayDetail?id=${item.id}`)">
<img :src="item.thumbUrl[0].url" alt="" v-if="item.thumbUrl && item.thumbUrl.length">
<p class="text">{{ item.title }}</p>
<p class="time">{{ item.organizationName }} {{ item.publishDate || '' }}</p>
</div>
<AiEmpty v-if="todayList.length == 0"/>
<div class="line-bg"></div>
<div class="title">
<div class="left">
<span class="tips"></span>党史课堂
</div>
<div class="right" @click="handleGoto('./classroomList')">
查看全部
<img src="https://cdn.cunwuyun.cn/img/down.svg" class="right-icon">
</div>
</div>
<div class="tab-content">
<div class="tab-item" v-for="(item, index) in classList" :key="index"
@click="handleGoto(`./videoDetail?id=${item.id}`)">
<img :src="item.thumbUrl[0].url" alt="" v-if="item.thumbUrl && item.thumbUrl.length">
<p>{{ item.title }}</p>
</div>
</div>
<AiEmpty v-if="classList.length == 0"/>
<div class="line-bg"></div>
<div class="title">
<div class="left">
<span class="tips"></span>党史知识
</div>
<div class="right" @click="handleGoto('./knowledgeList?type=knowledge')">
查看全部
<img src="https://cdn.cunwuyun.cn/img/down.svg" class="right-icon">
</div>
</div>
<div class="new-list">
<div class="list-content">
<div class="bg-fff" v-for="(item, index) in knowledgeList" :key="index"
@click="handleGoto(`./todayDetail?type=know&id=${item.id}`)">
<div class="item">
<div class="info">
<p>{{ item.title }}</p>
<span>{{ item.organizationName }} {{ item.createDate }}</span>
</div>
<img :src="item.thumbUrl[0].url" alt="" v-if="item.thumbUrl && item.thumbUrl.length"/>
</div>
</div>
<AiEmpty v-if="knowledgeList.length == 0"/>
</div>
</div>
</div>
</section>
</template>
<script>
import {mapState} from "vuex";
export default {
name: "AppPartyHistoryEducation",
appName: "党史教育",
computed: {
...mapState(["user", "token"]),
},
data() {
return {
todayList: [],
classList: [],
knowledgeList: []
};
},
onLoad() {
this.getTodayList()
this.getClassList()
this.getKnowledgeList()
},
methods: {
getTodayList() {
this.$instance.post(`/app/apppartyeducation/list?style=2&size=1&status=1`).then((res) => {
if (res.code == 0) {
if (res.data && res.data.records) {
res.data.records.map((item) => {
if (item.thumbUrl) {
item.thumbUrl = JSON.parse(item.thumbUrl)
}
if (item.publishDate) {
item.publishDate = item.publishDate.substring(0, 10)
}
})
this.todayList = res.data.records
}
}
});
},
getClassList() {
this.$instance.post(`/app/apppartyclassroom/list?size=3&status=1`).then((res) => {
if (res.code == 0) {
if (res.data && res.data.records) {
res.data.records.map((item) => {
item.thumbUrl = JSON.parse(item.thumbUrl)
})
this.classList = res.data.records
}
}
});
},
getKnowledgeList() {
this.$instance.post(`/app/apppartyeducation/list?style=0&size=4&status=1`).then((res) => {
if (res.code == 0) {
if (res.data && res.data.records) {
res.data.records.map((item) => {
if (item.thumbUrl) {
item.thumbUrl = JSON.parse(item.thumbUrl)
}
if (item.createDate) {
item.createDate = item.createDate.substring(0, 10)
}
})
this.knowledgeList = res.data.records
}
}
});
},
handleGoto(url) {
uni.navigateTo({url});
},
toNewDetail(id) {
this.handleGoto(`/pages/party/partyHistory/detail?id=${id}`);
},
},
};
</script>
<style scoped lang="scss">
@import "../../../common/common.css";
.AppPartyHistoryEducation {
width: 100%;
height: 100%;
}
.page {
width: 100%;
overflow-x: hidden;
background-color: #fff;
.title {
padding: 28px 16px 28px 28px;
background-color: #fff;
display: flex;
justify-content: space-between;
.tips {
display: inline-block;
width: 8px;
height: 32px;
background: #E02617;
vertical-align: middle;
margin-right: 18px;
}
.right-icon {
width: 32px;
height: 32px;
float: right;
vertical-align: middle;
transform: rotate(270deg);
padding: 0 8px 0 0;
}
.left {
font-size: 34px;
font-family: PingFang-SC-Heavy, PingFang-SC;
font-weight: 800;
color: #333;
line-height: 48px;
}
.right {
font-size: 28px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #666;
line-height: 40px;
}
}
.header {
padding: 0 34px 40px 34px;
img {
width: 684px;
height: 252px;
margin-bottom: 32px;
}
.text {
font-size: 32px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333;
line-height: 48px;
word-break: break-all;
margin-bottom: 16px;
height: 96px;
text-overflow: -o-ellipsis-lastline;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
-webkit-box-orient: vertical;
}
.time {
font-size: 24px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #999;
line-height: 30px;
}
}
.line-bg {
width: 100%;
height: 12px;
background: #F2F2F2;
}
.tab-content {
padding: 0 0 40px 30px;
overflow-x: hidden;
height: 236px;
width: 800px;
.tab-item {
float: left;
width: 236px;
height: 236px;
background: #FFF;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.12);
border-radius: 8px;
margin-right: 16px;
img {
width: 236px;
height: 160px;
}
p {
padding: 12px 8px 0;
font-size: 26px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333;
line-height: 36px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
.new-list {
background-color: #fff;
.list-content {
.bg-fff {
padding: 0 30px;
border-top: 1px solid #ddd;
.item {
padding: 24px 0 32px 0;
border-bottom: 2px solid #eee;
display: flex;
justify-content: space-between;
.info {
// width: 410px;
p {
// width: 410px;
font-size: 30px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333;
line-height: 46px;
text-overflow: -o-ellipsis-lastline;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
-webkit-box-orient: vertical;
margin-bottom: 52px;
}
span {
font-size: 24px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #999999;
line-height: 30px;
}
}
img {
width: 224px;
height: 168px;
margin-left: 56px;
}
}
}
.view-more {
background-color: #fff;
font-size: 28px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #c50000;
line-height: 40px;
padding: 30px 0 40px 30px;
}
}
}
}
</style>

View File

@@ -0,0 +1,114 @@
<template>
<section class="home">
<div class="page">
<div class="item" v-for="(item, index) in classList" :key="index" @click.stop="toDetail(item.id)">
<img :src="item.thumbUrl[0].url" alt="" class="banner-img">
<img src="https://cdn.cunwuyun.cn/dvcp/pay-btn.png" alt="" class="play-img">
<p>{{ item.title }}</p>
<div>{{ item.organizationName }} {{ item.createDate }}</div>
</div>
<AiEmpty v-if="classList.length == 0"/>
</div>
</section>
</template>
<script>
import {mapState} from "vuex";
export default {
name: "home",
computed: {
...mapState(["user", "token"]),
},
data() {
return {
current: 1,
pages: 2,
classList: []
};
},
onLoad() {
this.getClassList()
},
methods: {
getClassList() {
if (this.current > this.pages) return;
this.$instance.post(`/app/apppartyclassroom/list?size=10&status=1&current=${this.current}`).then((res) => {
if (res.code == 0) {
if (res.data && res.data.records) {
res.data.records.map((item) => {
item.thumbUrl = JSON.parse(item.thumbUrl)
item.createDate = item.createDate.substring(0, 10)
})
const classList = this.current > 1 ? [...this.classList, ...res.data.records] : res.data.records
this.pages = Math.ceil(res.data.total / 10)
this.classList = classList
this.classList = res.data.records
}
}
});
},
toDetail(id) {
uni.navigateTo({url: `./videoDetail?id=${id}`})
}
},
onReachBottom() {
this.current = this.current + 1
this.getClassList()
},
};
</script>
<style scoped lang="scss">
@import "../../../common/common.css";
.home {
width: 100%;
height: 100%;
}
.page {
width: 100%;
overflow-x: hidden;
background-color: #fff;
.item {
position: relative;
video {
width: 100%;
height: 416px;
// background: rgba(0, 0, 0, 0.3);
}
.banner-img {
width: 100%;
height: 416px;
}
.play-img {
width: 80px;
height: 80px;
position: absolute;
top: 148px;
left: 334px;
}
p {
padding: 20px 32px;
width: 686px;
font-size: 34px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333;
line-height: 48px;
}
div {
padding: 0 0 34px 32px;
font-size: 22px;
font-family: PingFangSC-Regular, PingFang SC;
color: #999;
line-height: 22px;
}
}
}
</style>

View File

@@ -0,0 +1,111 @@
<template>
<section class="home">
<div class="page">
<div class="header">
<p class="title">{{ info.title }}</p>
<div class="info mar-b16"><span class="label">发布单位</span><span class="value">{{ info.organizationName }}</span>
</div>
<div class="info">发布时间{{ info.publishDate || info.createDate }}</div>
</div>
<div class="content">
<u-parse :html="info.content"></u-parse>
</div>
<AiTransSpeech :src="info.speech" v-if="info.speech"/>
</div>
</section>
</template>
<script>
import {mapState} from "vuex";
export default {
name: "home",
computed: {
...mapState(["user", "token"]),
},
data() {
return {
id: '',
info: {},
content: ''
};
},
onLoad(options) {
this.id = options.id
this.getDetail()
},
methods: {
getDetail() {
this.$instance.post(`/app/apppartyhistory/queryDetailByIdWeChat?id=${this.id}`).then((res) => {
if (res.code == 0) {
if (res.data.publishDate) {
res.data.publishDate = res.data.publishDate.substring(0, 10)
}
if (res.data.createDate) {
res.data.createDate = res.data.createDate.substring(0, 10)
}
this.info = res.data
}
});
},
},
};
</script>
<style scoped lang="scss">
@import "../../../common/common.css";
.home {
width: 100%;
height: 100%;
}
.page {
width: 100%;
overflow-x: hidden;
background-color: #fff;
.header {
width: 100%;
padding: 24px 32px 32px;
box-sizing: border-box;
background: #D03A28;
.title {
width: 100%;
font-size: 40px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #FFF;
line-height: 64px;
letter-spacing: 1px;
word-break: break-all;
margin-bottom: 16px;
}
.info {
font-size: 28px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #FFF;
line-height: 40px;
.label {
width: 140px;
}
.value {
width: calc(100% - 140px);
word-break: break-all;
}
}
.mar-b16 {
margin-bottom: 16px;
}
}
.content {
padding: 32px;
}
}
</style>

View File

@@ -0,0 +1,320 @@
<template>
<div class="page">
<div style="height: 100%">
<div class="fixed-top">
<!-- 选择时间和类型 -->
<div class="slect flex-row">
<!-- 类型选择 -->
<div class="uni-list type-slect">
<div class="uni-list-cell">
<div class="uni-list-cell-db">
<picker
@change="bindPickerChange"
:range="array"
range-key="dictName"
>
<div class="uni-input">{{ styleText }}</div>
<image src="https://cdn.cunwuyun.cn/img/down.svg"></image>
</picker>
</div>
</div>
</div>
<!-- 时间选择 -->
<div class="uni-list type-slect">
<div class="uni-list-cell">
<div class="uni-list-cell-db">
<picker
mode="date"
:value="date"
:start="startDate"
:end="endDate"
@change="bindDateChange"
fields="month"
>
<div class="uni-input">{{ day }}</div>
<image src="https://cdn.cunwuyun.cn/img/down.svg"></image>
</picker>
</div>
</div>
</div>
</div>
</div>
<div class="session-list">
<div class="session-item" v-for="(item, index) in meetList" :key="index" @click="toDetail(item.id)">
<div class="info">
<p v-if="fromType != 'style'"><span
:class="item.style == 0 ? 'status0' : 'status1'">{{
item.style == 0 ? '党史知识' : '党史图书馆'
}}</span>{{ item.title }}
</p>
<p v-else><span class="status0">{{
$dict.getLabel(`partyHistoryType${optionStyle}`, item.type)
}}</span>{{ item.title }}</p>
<span class="time">{{ item.organizationName }} {{ item.createDate }}</span>
</div>
<div class="img" v-if="item.thumbUrl && item.thumbUrl.length">
<img :src="item.thumbUrl[0].url" alt="">
</div>
</div>
</div>
<AiEmpty v-if="meetList.length == 0"/>
</div>
</div>
</template>
<script>
export default {
data() {
const currentDate = this.getDate({
format: true,
});
return {
array: [],
partyStudyType: "",
date: currentDate,
day: "时间",
createDate: "", //创建时间
meetList: [],
pageNum: 1,
pageSize: 10,
pages: 2,
fromType: '', //style 0、党建要闻 1、政策解读 knowledge 党史知识 policy 党史图书馆
style: '4',
styleText: '类型',
optionStyle: ''
};
},
computed: {
startDate() {
return this.getDate("start");
},
endDate() {
return this.getDate("end");
},
},
onLoad(options) {
console.log(options)
if (options.type == 'knowledge') {
this.array = [{dictName: "全部类型", dictValue: "4"}, {dictName: "党史知识 ", dictValue: 0}, {
dictName: "党史图书馆",
dictValue: 1
}]
}
if (options.type == 'style') {
this.style = ''
this.optionStyle = options.style
this.$dict.load("partyHistoryType0", "partyHistoryType1").then(() => {
this.array = this.$dict.getDict(`partyHistoryType${options.style}`)
this.array.unshift({dictName: "全部类型", dictValue: ""})
})
}
this.fromType = options.type
this.getList();
},
methods: {
bindPickerChange(e) {
console.log(e)
this.style = this.array[e.detail.value].dictValue
if (this.style === '') {
this.styleText = '类型'
} else {
this.styleText = this.array[e.detail.value].dictName
}
this.pageNum = 1;
this.pages = 2;
this.pageSize = 10;
this.getList();
},
bindDateChange(e) {
this.day = e.target.value;
this.createDate = e.target.value;
this.pageNum = 1;
this.pages = 2;
this.pageSize = 10;
this.getList();
},
getDate(type) {
const date = new Date();
let year = date.getFullYear();
let month = date.getMonth() + 1;
let day = date.getDate();
if (type === "start") {
year = year - 60;
} else if (type === "end") {
year = year + 2;
}
month = month > 9 ? month : "0" + month;
day = day > 9 ? day : "0" + day;
return `${year}-${month}-08 00:00:00 `;
},
search() {
this.pageNum = 1;
this.pageSize = 10;
this.pages = 2;
this.getList();
},
getList() {
if (this.pageNum > this.pages) return;
var createDate = ''
if (this.createDate) {
createDate = this.createDate + '-01'
}
this.$instance.post(`/app/apppartyeducation/list?size=10&current=${this.pageNum}&createDateParam=${createDate}&style=${this.style}&status=1`).then((res) => {
if (res.code == 0) {
res.data.records.map((item) => {
if (item.thumbUrl) {
item.thumbUrl = JSON.parse(item.thumbUrl)
}
if (item.createDate) {
item.createDate = item.createDate.substring(0, 10)
}
})
const meetList = this.pageNum > 1 ? [...this.meetList, ...res.data.records] : res.data.records
this.pages = Math.ceil(res.data.total / 10)
this.meetList = meetList
}
});
},
toDetail(id) {
uni.navigateTo({
url: "./todayDetail?type=know&id=" + id,
});
},
},
onReachBottom() {
this.pageNum = this.pageNum + 1;
this.getList();
},
};
</script>
<style lang="scss" scope>
@import "../../../common/common.css";
.page {
.search-box {
width: 100%;
height: 112px;
background-color: #D7261E;
padding: 24px 32px;
box-sizing: border-box;
}
.slect {
width: 100%;
height: 96px;
background-color: #fff;
color: #666;
.type-slect {
width: 50%;
border-right: 1px solid #f7f7f7;
margin: 30px 0;
box-sizing: border-box;
text-align: center;
font-size: 26px;
.uni-input {
display: inline-block;
}
image {
width: 32px;
height: 32px;
display: inline-block;
position: relative;
top: 6px;
margin-left: 8 spx;
}
}
.type-slect:nth-child(2) {
border: none;
}
}
.session-list {
padding-top: 112px;
.session-item {
width: 686px;
padding: 32px;
box-sizing: border-box;
margin: 0 auto 32px auto;
background-color: #fff;
position: relative;
overflow: hidden;
display: flex;
justify-content: space-between;
border-radius: 8px;
.info {
p {
height: 88px;
font-size: 32px;
font-family: PingFangSC-Regular, PingFang SC;
color: #333;
line-height: 44px;
text-overflow: -o-ellipsis-lastline;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
-webkit-box-orient: vertical;
margin-bottom: 24px;
span {
display: inline-block;
padding: 0 8px;
font-size: 26px;
font-family: PingFangSC-Regular, PingFang SC;
line-height: 44px;
margin-right: 16px;
border-radius: 8px;
}
.status0 {
color: #2266FF;
background-color: #E8EFFF;
}
.status1 {
color: #FF8822;
background-color: #FFF3E9;
}
}
.time {
font-size: 28px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #999;
line-height: 22px;
}
}
.img {
padding-left: 24px;
img {
width: 192px;
height: 144px;
}
}
}
}
.no-affairs {
width: 100%;
height: calc(100% - 210px);
display: flex;
justify-content: center;
align-items: center;
}
}
</style>

View File

@@ -0,0 +1,330 @@
<template>
<div class="page">
<div style="height: 100%">
<div class="fixed-top">
<!-- 选择时间和类型 -->
<div class="slect flex-row">
<!-- 类型选择 -->
<div class="uni-list type-slect">
<div class="uni-list-cell">
<div class="uni-list-cell-db">
<picker
@change="bindPickerChange"
:range="array"
range-key="dictName"
>
<div class="uni-input">{{ styleText }}</div>
<image src="https://cdn.cunwuyun.cn/img/down.svg"></image>
</picker>
</div>
</div>
</div>
<!-- 时间选择 -->
<div class="uni-list type-slect">
<div class="uni-list-cell">
<div class="uni-list-cell-db">
<picker
mode="date"
:value="date"
:start="startDate"
:end="endDate"
@change="bindDateChange"
fields="month"
>
<div class="uni-input">{{ day }}</div>
<image src="https://cdn.cunwuyun.cn/img/down.svg"></image>
</picker>
</div>
</div>
</div>
</div>
</div>
<div class="session-list">
<div class="session-item" v-for="(item, index) in meetList" :key="index" @click="toDetail(item.id)">
<div class="info">
<p v-if="fromType != 'style'"><span
:class="item.style == 0 ? 'status0' : 'status1'">{{
item.style == 0 ? '党史知识' : '党史图书馆'
}}</span>{{ item.title }}
</p>
<p v-else><span class="status0">{{
$dict.getLabel(`partyHistoryType${optionStyle}`, item.type)
}}</span>{{ item.title }}</p>
<span class="time">{{ item.organizationName }} {{ item.createDate }}</span>
</div>
<div class="img" v-if="item.thumbUrl && item.thumbUrl.length">
<img :src="item.thumbUrl[0].url" alt="">
</div>
</div>
</div>
<AiEmpty v-if="meetList.length == 0"/>
</div>
</div>
</template>
<script>
export default {
data() {
const currentDate = this.getDate({
format: true,
});
return {
array: [],
partyStudyType: "",
date: currentDate,
day: "时间",
createDate: "", //创建时间
meetList: [],
pageNum: 1,
pageSize: 10,
pages: 2,
fromType: '', //style 0、党建要闻 1、政策解读 knowledge 党史知识 policy 党史图书馆
style: '',
styleText: '类型',
optionStyle: ''
};
},
computed: {
startDate() {
return this.getDate("start");
},
endDate() {
return this.getDate("end");
},
},
onLoad(options) {
console.log(options)
if (options.type == 'knowledge') {
this.array = [{dictName: "全部类型", dictValue: "0|1"}, {dictName: "党史知识 ", dictValue: 0}, {
dictName: "党史图书馆",
dictValue: 1
}]
}
if (options.type == 'style') {
this.style = ''
this.optionStyle = options.style
this.$dict.load("partyHistoryType0", "partyHistoryType1").then(() => {
this.array = this.$dict.getDict(`partyHistoryType${options.style}`)
this.array.unshift({dictName: "全部类型", dictValue: ""})
})
}
this.fromType = options.type
this.getList();
},
methods: {
bindPickerChange(e) {
console.log(e)
this.style = this.array[e.detail.value].dictValue
if (this.style === '') {
this.styleText = '类型'
} else {
this.styleText = this.array[e.detail.value].dictName
}
this.pageNum = 1;
this.pages = 2;
this.pageSize = 10;
this.getList();
},
bindDateChange(e) {
this.day = e.target.value;
this.createDate = e.target.value;
this.pageNum = 1;
this.pages = 2;
this.pageSize = 10;
this.getList();
},
getDate(type) {
const date = new Date();
let year = date.getFullYear();
let month = date.getMonth() + 1;
let day = date.getDate();
if (type === "start") {
year = year - 60;
} else if (type === "end") {
year = year + 2;
}
month = month > 9 ? month : "0" + month;
day = day > 9 ? day : "0" + day;
return `${year}-${month}-08 00:00:00 `;
},
search() {
this.pageNum = 1;
this.pageSize = 10;
this.pages = 2;
this.getList();
},
getList() {
if (this.pageNum > this.pages) return;
var createDate = ''
if (this.createDate) {
createDate = this.createDate + '-01 00:00:00'
}
this.$instance.post(`/app/apppartyhistory/listWechat`, {
style: this.fromType == 'style' ? this.optionStyle : this.style,
type: this.style,
createDate: createDate,
current: this.pageNum,
size: this.pageSize,
status: 1
}).then((res) => {
if (res.code == 0) {
res.data.records.map((item) => {
if (item.thumbUrl) {
item.thumbUrl = JSON.parse(item.thumbUrl)
}
if (item.createDate) {
item.createDate = item.createDate.substring(0, 10)
}
})
const meetList = this.pageNum > 1 ? [...this.meetList, ...res.data.records] : res.data.records
this.pages = Math.ceil(res.data.total / 10)
this.meetList = meetList
// this.meetList.map((item) => {
// item.thumbUrl = JSON.parse(item.thumbUrl)
// })
}
});
},
toDetail(id) {
uni.navigateTo({
url: "./detail?id=" + id,
});
},
},
onReachBottom() {
this.pageNum = this.pageNum + 1;
this.getList();
},
};
</script>
<style lang="scss" scope>
@import "../../../common/common.css";
.page {
.search-box {
width: 100%;
height: 112px;
background-color: #D7261E;
padding: 24px 32px;
box-sizing: border-box;
}
.slect {
width: 100%;
height: 96px;
background-color: #fff;
color: #666;
.type-slect {
width: 50%;
border-right: 1px solid #f7f7f7;
margin: 30px 0;
box-sizing: border-box;
text-align: center;
font-size: 26px;
.uni-input {
display: inline-block;
}
image {
width: 32px;
height: 32px;
display: inline-block;
position: relative;
top: 6px;
margin-left: 8 spx;
}
}
.type-slect:nth-child(2) {
border: none;
}
}
.session-list {
padding-top: 112px;
.session-item {
width: 686px;
padding: 32px;
box-sizing: border-box;
margin: 0 auto 32px auto;
background-color: #fff;
position: relative;
overflow: hidden;
display: flex;
justify-content: space-between;
border-radius: 8px;
.info {
p {
height: 88px;
font-size: 32px;
font-family: PingFangSC-Regular, PingFang SC;
color: #333;
line-height: 44px;
text-overflow: -o-ellipsis-lastline;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
-webkit-box-orient: vertical;
margin-bottom: 24px;
span {
display: inline-block;
padding: 0 8px;
font-size: 26px;
font-family: PingFangSC-Regular, PingFang SC;
line-height: 44px;
margin-right: 16px;
border-radius: 8px;
}
.status0 {
color: #2266FF;
background-color: #E8EFFF;
}
.status1 {
color: #FF8822;
background-color: #FFF3E9;
}
}
.time {
font-size: 28px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #999;
line-height: 22px;
}
}
.img {
padding-left: 24px;
img {
width: 192px;
height: 144px;
}
}
}
}
.no-affairs {
width: 100%;
height: calc(100% - 210px);
display: flex;
justify-content: center;
align-items: center;
}
}
</style>

View File

@@ -0,0 +1,84 @@
<template>
<section class="home">
<div class="page">
<p class="title">点击进入月份</p>
<div class="tab-content">
<span v-for="(item, index) in tabList" :key="index" class="tab-item" :class="tabIndex == index ? 'active' : ''"
@click="back(index)">{{ item }}</span>
</div>
</div>
</section>
</template>
<script>
import {mapState} from "vuex";
export default {
name: "home",
computed: {
...mapState(["user", "token"]),
},
data() {
return {
tabList: ['全部', '一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
tabIndex: 0,
};
},
onLoad(options) {
this.tabIndex = options.index
},
methods: {
back(index) {
this.tabIndex = index
uni.setStorageSync('partyTabIndex', this.tabIndex)
uni.navigateBack({delta: 1})
}
},
};
</script>
<style scoped lang="scss">
@import "../../../common/common.css";
.home {
width: 100%;
height: 100%;
}
.page {
width: 100%;
overflow-x: hidden;
background-color: #fff;
.title {
padding: 32px 0 40px 30px;
font-size: 26px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #B9B9B9;
line-height: 36px;
}
.tab-content {
padding-left: 30px;
.tab-item {
display: inline-block;
width: 144px;
height: 48px;
text-align: center;
line-height: 48px;
border-radius: 24px;
box-sizing: border-box;
border: 1px solid #CBCBCB;
font-size: 26px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #333;
margin: 0 38px 32px 0;
}
.active {
color: #DA2D1A;
}
}
}
</style>

View File

@@ -0,0 +1,115 @@
<template>
<section class="home">
<div class="page">
<div class="header">
<p class="title">{{ info.title }}</p>
<div class="info mar-b16"><span class="label">发布单位</span><span class="value">{{ info.organizationName }}</span>
</div>
<div class="info" v-if="type == 'know'">发布时间{{ info.createDate || '-' }}</div>
<div class="info" v-else>发布时间{{ info.publishDate || '-' }}</div>
</div>
<div class="content">
<u-parse :html="info.content"></u-parse>
</div>
<AiTransSpeech :src="info.speech" v-if="info.speech"/>
</div>
</section>
</template>
<script>
import {mapState} from "vuex";
export default {
name: "home",
computed: {
...mapState(["user", "token"]),
},
data() {
return {
id: '',
info: {},
content: '',
type: '', //know 党史知识
};
},
onLoad(options) {
console.log(options)
this.id = options.id
this.type = options.type
this.getDetail()
},
methods: {
getDetail() {
this.$instance.post(`/app/apppartyeducation/queryDetailById?id=${this.id}`).then((res) => {
if (res.code == 0) {
if (res.data.createDate) {
res.data.createDate = res.data.createDate.substring(0, 10)
}
if (res.data.publishDate) {
res.data.publishDate = res.data.publishDate.substring(0, 10)
}
this.info = res.data
}
});
},
},
};
</script>
<style scoped lang="scss">
@import "../../../common/common.css";
.home {
width: 100%;
height: 100%;
}
.page {
width: 100%;
overflow-x: hidden;
background-color: #fff;
.header {
width: 100%;
padding: 24px 32px 32px;
box-sizing: border-box;
background: #D03A28;
.title {
width: 100%;
font-size: 40px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #FFF;
line-height: 64px;
letter-spacing: 1px;
word-break: break-all;
margin-bottom: 16px;
}
.info {
font-size: 28px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #FFF;
line-height: 40px;
display: flex;
.label {
width: 140px;
}
.value {
width: calc(100% - 140px);
word-break: break-all;
}
}
.mar-b16 {
margin-bottom: 16px;
}
}
.content {
padding: 32px;
}
}
</style>

View File

@@ -0,0 +1,175 @@
<template>
<section class="home">
<div class="page">
<div class="tab-content">
<span v-for="(item, index) in tabList" :key="index" class="tab-item" :class="tabIndex == index ? 'active' : ''"
@click="timeSelect(index)">{{ item }}</span>
<img src="https://cdn.cunwuyun.cn/img/party_detail.png" alt=""
@click="handleGoto(`./select?index=${tabIndex}`)">
</div>
<div class="item" v-for="(item, index) in todayList" :key="index"
@click="handleGoto(`./todayDetail?id=${item.id}`)">
<div class="header">
<img :src="item.thumbUrl[0].url" alt="" v-if="item.thumbUrl && item.thumbUrl.length"/>
<p class="text">{{ item.title }}</p>
<p class="time">{{ item.organizationName }} {{ item.publishDate || '' }}</p>
</div>
<div class="line-bg"></div>
</div>
<AiEmpty v-if="todayList.length == 0"/>
</div>
</section>
</template>
<script>
import {mapState} from "vuex";
export default {
name: "home",
computed: {
...mapState(["user", "token"]),
},
data() {
return {
tabList: ['全部', '一月', '二月', '三月', '四月', '五月'],
tabIndex: 0,
todayList: [],
current: 1,
pages: 2
};
},
onLoad() {
this.getTodayList();
},
onShow() {
if (uni.getStorageSync('partyTabIndex')) {
this.tabIndex = uni.getStorageSync('partyTabIndex')
uni.setStorageSync('partyTabIndex', '')
this.timeSelect(this.tabIndex);
}
},
methods: {
getTodayList() {
if (this.current > this.pages) return;
var publishDate = ''
if (this.tabIndex > 0) {
var myDate = new Date();
var tYear = myDate.getFullYear();
var month = this.tabIndex < 10 ? '0' + this.tabIndex : this.tabIndex
publishDate = tYear + '-' + month + '-01'
}
this.$instance.post(`/app/apppartyeducation/list?style=2&current=${this.current}&size=10&publishDate=${publishDate}&status=1`).then((res) => {
if (res.code == 0) {
if (res.data.records && res.data.records.length) {
res.data.records.map((item) => {
console.log(item.thumbUrl)
if (item.thumbUrl) {
item.thumbUrl = JSON.parse(item.thumbUrl)
}
if (item.publishDate) {
item.publishDate = item.publishDate.substring(0, 10)
}
})
const todayList = this.current > 1 ? [...this.todayList, ...res.data.records] : res.data.records
this.pages = Math.ceil(res.data.total / 10)
this.todayList = todayList
}
}
});
},
handleGoto(url) {
uni.navigateTo({url})
},
timeSelect(index) {
this.tabIndex = index
this.current = 1
this.pages = 2
this.todayList = []
this.getTodayList()
}
},
onReachBottom() {
this.current = this.current + 1
this.getTodayList()
},
};
</script>
<style scoped lang="scss">
@import "../../../common/common.css";
.home {
width: 100%;
height: 100%;
}
.page {
width: 100%;
overflow-x: hidden;
background-color: #fff;
.tab-content {
width: 100%;
height: 84px;
padding: 0 30px;
box-sizing: border-box;
background: #FCF0ED;
.tab-item {
display: inline-block;
width: 60px;
line-height: 80px;
height: 80px;
margin-right: 48px;
font-size: 30px;
font-family: PingFangSC-Regular, PingFang SC;
color: #70737B;
}
.active {
font-family: PingFangSC-Semibold, PingFang SC;
font-weight: 600;
color: #DA2D1A;
border-bottom: 4px solid #DE2C19;
}
img {
width: 32px;
vertical-align: middle;
}
}
.header {
padding: 0 34px;
img {
width: 684px;
height: 252px;
margin: 32px 0;
}
.text {
font-size: 32px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333;
line-height: 48px;
word-break: break-all;
margin-bottom: 16px;
}
.time {
font-size: 24px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #999;
line-height: 30px;
padding-bottom: 40px;
}
}
.line-bg {
width: 100%;
height: 12px;
background: #f2f2f2;
}
}
</style>

View File

@@ -0,0 +1,199 @@
<template>
<section class="home" v-if="pageShow">
<div class="page" v-if="videoList.length">
<video :src="videoList[activeIndex].videoUrl" :id="`video${activeIndex+1}`"></video>
<p class="video-name">{{ videoList[activeIndex].title }}</p>
<div class="time">{{ info.organizationName }} {{ info.createDate }}</div>
<div class="title">
<span>选集</span>
<p @click="show=true" v-if="videoList.length > 7">查看全部&nbsp;&nbsp;></p>
</div>
<div class="select page-select">
<div class="item" :class="index == activeIndex ? 'active' : ''" v-for="(item, index) in videoList" :key="index"
@click="activeIndex=index">{{ item.num }}
</div>
</div>
<div class="title">
<span>内容简介</span>
</div>
<div class="detail-content">
<u-parse :html="info.content"></u-parse>
</div>
<u-popup v-model="show" mode="bottom">
<div class="title">
<span>选集</span>
</div>
<div class="select pop-select">
<div class="item" :class="index == activeIndex ? 'active' : ''" v-for="(item, index) in videoList"
:key="index" @click="activeIndex=index;show=false">{{ item.num }}
</div>
</div>
</u-popup>
</div>
<AiEmpty v-else/>
</section>
</template>
<script>
import {mapState} from "vuex";
export default {
name: "home",
computed: {
...mapState(["user", "token"]),
},
data() {
return {
show: false,
id: '',
info: {},
videoList: [],
activeIndex: 0,
pageShow: false
};
},
onLoad(options) {
this.id = options.id
this.getClassDetail()
this.getVideoList()
},
methods: {
change(index) {
this.current = index;
},
getClassDetail() {
this.$instance.post(`/app/apppartyclassroom/queryDetailById?id=${this.id}`).then((res) => {
if (res.code == 0) {
if (res.data) {
res.data.createDate = res.data.createDate.substring(0, 10)
this.info = res.data
}
}
});
},
getVideoList() {
this.$instance.post(`/app/apppartyclassroomepisode/list?classroomId=${this.id}&size=10000`).then((res) => {
if (res.code == 0) {
console.log(res)
if (res.data && res.data.records) {
this.videoList = res.data.records
this.pageShow = true
}
}
});
},
},
};
</script>
<style scoped lang="scss">
@import "../../../common/common.css";
.home {
width: 100%;
height: 100%;
}
.page {
width: 100%;
height: 100%;
overflow-x: hidden;
background-color: #fff;
video {
width: 100%;
height: 416px;
}
.video-name {
padding: 24px 32px 20px;
width: 686px;
font-size: 34px;
font-family: PingFang-SC-Heavy, PingFang-SC;
font-weight: 800;
color: #333;
line-height: 48px;
}
.time {
font-size: 24px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #999;
line-height: 30px;
margin-bottom: 32px;
padding-left: 32px;
}
.title {
width: 100%;
height: 80px;
line-height: 80px;
padding: 0 32px 16px 32px;
display: flex;
justify-content: space-between;
box-sizing: border-box;
span {
display: inline-block;
font-size: 34px;
font-family: PingFang-SC-Heavy, PingFang-SC;
font-weight: 800;
color: #333;
line-height: 80px;
}
p {
font-size: 26px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #999;
line-height: 80px;
}
}
.select {
padding: 0 0 24px 32px;
width: 800px;
overflow-x: hidden;
.item {
width: 96px;
height: 96px;
line-height: 96px;
text-align: center;
background: #F0F4FB;
border-radius: 8px;
float: left;
font-size: 32px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333;
margin-right: 11px;
}
.active {
color: #DA2D1A;
}
}
.page-select {
height: 96px;
padding-bottom: 0;
overflow-y: hidden;
}
.detail-content {
padding: 0 32px;
font-size: 32px;
font-family: PingFangSC-Regular, PingFang SC;
color: #333;
line-height: 48px;
word-break: break-all;
}
.pop-select {
.item {
margin: 0 22px 22px 0;
}
}
}
</style>

View File

@@ -0,0 +1,304 @@
<template>
<div class="AppPartyOrganization">
<div class="header"></div>
<div class="content">
<div class="party-org">
<div class="title">所在组织</div>
<p class="org-select" @click="selectShow = true">{{ detail.name || '请选择' }}<img
src="https://cdn.cunwuyun.cn/img/down.svg"/></p>
</div>
<div class="org-info">
<div class="title">组织信息</div>
<div class="flex-row">
<span class="color-666">组织类型</span>
<span class="color-333">{{ $dict.getLabel("orgType", detail.orgType) }}</span>
</div>
<div class="flex-row">
<span class="color-666">组织级别</span>
<span class="color-333">{{ $dict.getLabel("orgPartyType", detail.partyType) }}</span>
</div>
<div class="flex-row">
<span class="color-666">党员人数</span>
<span class="color-333">{{ count }}</span>
</div>
</div>
<div class="org-info">
<div class="flex-row">
<span class="title">报到状态</span>
<span :class="userInfo.reportOrgId ? 'status1' : 'status0'">{{ userInfo.reportOrgId ? '已报到' : '未报到' }}</span>
</div>
</div>
</div>
<u-select v-model="selectShow" :list="treeData" @confirm="confirm"></u-select>
<u-popup v-model="dialog" mode="center" border-radius="8">
<div class="estateNotice">
<b>您已加入过党组织,是否变更</b>
<u-gap height="40"/>
<div class="curEstate">
<div class="flexRow">
<b>当前党组织</b>
<span>{{ detail.name }}</span>
</div>
<div class="flexRow">
<b>当前报到状态</b>
<span
:class="userInfo.reportOrgId ? 'status1' : 'status0'">{{ userInfo.reportOrgId ? '已报到' : '未报到' }}</span>
</div>
<div class="flexRow">
<b>变更党组织</b>
<span>{{ changeOrgInfo.label }}</span>
</div>
</div>
<u-gap height="34"/>
<div class="alert">变更党组织后需尽快前往新党组织报到</div>
<u-gap height="62"/>
<div class="flexRow footer">
<div class="fill"/>
<span @click="dialog=false">取消</span>
<span @click="dialog=false,bindEstate()">确认</span>
</div>
</div>
</u-popup>
</div>
</template>
<script>
export default {
name: "AppPartyOrganization",
appName: "党组织",
data() {
return {
dialog: false,
detail: {},
treeData: [],
selectShow: false,
reportOrgName: '', //报到党组织名称
reportOrgId: '',
changeOrgInfo: {},
userInfo: {},
count: 0
}
},
onLoad() {
this.$dict.load("orgType", "orgPartyType").then(() => {
this.getUserInfo()
})
},
methods: {
getUserInfo() {
this.$instance.post("/app/appparty/chanhudetail").then(res => {
if (res?.data) {
if (res.data.reportOrgId) {
this.reportOrgName = res.data.reportOrgName
this.reportOrgId = res.data.reportOrgId
} else {
this.reportOrgName = res.data.partyOrgName
this.reportOrgId = res.data.partyOrgId
}
this.userInfo = res.data
this.getDetail()
this.getTree()
}
})
},
getTree() {
this.$instance.post(`/admin/partyOrganization/queryAllChildren?id=${this.userInfo.topOrgId}`).then(res => {
if (res?.data) {
res.data.map((item) => {
item.label = item.name
item.value = item.id
})
this.treeData = res.data
}
})
},
getDetail() {
this.$instance.post(`/admin/partyOrganization/detail?id=${this.userInfo.reportOrgId}`).then(res => {
if (res?.data) {
this.detail = res.data
this.count = res.data.memberCount.one || 0
}
})
},
confirm(e) {
this.treeData.map((item) => {
if (item.id == e[0].value) {
this.changeOrgInfo = item
}
})
this.dialog = true
},
bindEstate() {
this.$instance.post("/app/apppartyreportorgchange/changeReportOrg", {
orgId: this.changeOrgInfo.id,
orgName: this.changeOrgInfo.name,
partyId: this.userInfo.id,
}).then(res => {
if (res?.code == 0) {
this.$toast('党组织变更成功')
this.getUserInfo()
this.$store.commit("getUserInfo")
}
})
},
}
}
</script>
<style lang="scss" scoped>
.AppPartyOrganization {
height: 100%;
padding-bottom: 112px;
box-sizing: border-box;
position: relative;
.header {
height: 160px;
background: #D7261E;
}
.content {
width: 686px;
position: absolute;
top: 50px;
left: 32px;
.party-org {
padding: 32px;
margin-bottom: 16px;
background: #FFFFFF;
.title {
font-size: 34px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 700;
color: #333;
line-height: 60px;
}
.org-select {
font-size: 30px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #666;
line-height: 42px;
img {
width: 32px;
height: 32px;
vertical-align: middle;
transform: rotate(270deg);
}
}
}
.org-info {
padding: 0 32px;
background: #FFFFFF;
margin-bottom: 16px;
div {
line-height: 100px;
font-size: 30px;
border-bottom: 2px solid #eee;
box-sizing: content-box;
}
div:nth-last-of-type(1) {
border-bottom: 0;
}
.title {
font-size: 32px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 700;
color: #333;
}
.flex-row {
display: flex;
justify-content: space-between;
.color-666 {
color: #666;
}
.color-333 {
color: #333;
}
}
.status0 {
color: #FF8822;
}
.status1 {
color: #2EA222;
}
}
}
::v-deep .estateNotice {
width: 560px;
background: #FFFFFF;
padding: 48px;
box-sizing: border-box;
.status0 {
color: #FF8822;
}
.status1 {
color: #2EA222;
}
.curEstate {
color: #666;
font-size: 28px;
b {
color: #333
}
}
.alert {
font-size: 28px;
font-weight: 400;
color: #F14242;
}
.footer {
span {
width: 128px;
height: 40px;
line-height: 40px;
text-align: center;
color: #1365DD;
font-size: 28px;
transform: translateX(32px);
& + span {
margin-left: 16px;
}
}
}
}
.bottomBtn {
position: fixed;
width: 100%;
bottom: 0;
text-align: center;
height: 112px;
line-height: 112px;
background: #D7261E;
font-size: 32px;
font-weight: 500;
color: #FFFFFF;
}
}
</style>

View File

@@ -0,0 +1,485 @@
<template>
<div class="page">
<div v-if="isShow" style="height: 100%">
<div class="fixed-top">
<!-- 头部搜索样式 -->
<div class="search-box">
<div class="search-input flex-row" @click="changeSearchBox">
<image src="https://cdn.cunwuyun.cn/img/search-red.svg"></image>
<span>{{ inputValue }}</span>
</div>
</div>
<!-- 选择时间和类型 -->
<div class="slect flex-row">
<!-- 类型选择 -->
<div class="uni-list type-select">
<div class="uni-list-cell">
<div class="uni-list-cell-db">
<picker
@change="bindPickerChange"
:range="array"
range-key="dictName"
>
<div class="uni-input" v-if="partyStudyType === ''">
学习类别
</div>
<div class="uni-input" v-else>
{{ array[partyStudyType + 1].dictName }}
</div>
<image src="https://cdn.cunwuyun.cn/img/down.svg"></image>
</picker>
</div>
</div>
</div>
<!-- 时间选择 -->
<div class="uni-list type-select">
<div class="uni-list-cell">
<div class="uni-list-cell-db">
<picker
mode="date"
:value="date"
:start="startDate"
:end="endDate"
@change="bindDateChange"
fields="month"
>
<div class="uni-input">{{ day }}</div>
<image src="https://cdn.cunwuyun.cn/img/down.svg"></image>
</picker>
</div>
</div>
</div>
</div>
</div>
<div class="session-list">
<div
class="session-item"
v-for="(item, index) in meetList"
:key="index"
>
<div class="item-top" @click="toDetail(item.id)">
<div class="item-title mar-b12">{{ item.title }}</div>
<div class="item-info">
<span class="info-label">学习类别</span>
<span class="info-value">{{
$dict.getLabel("partyStudyType", item.type)
}}</span>
</div>
<div class="item-info">
<span class="info-label">发布时间</span>
<span class="info-value">{{ item.publishTime }}</span>
</div>
<div class="item-info mar-b12">
<span class="info-label">发布人员</span>
<span class="info-value">{{ item.publishUserName }}</span>
</div>
</div>
<div class="item-status" :class="'item-status' + item.studyStatus">
{{ $dict.getLabel("partyStudyStatus", item.studyStatus) }}
</div>
</div>
</div>
<AiEmpty v-if="meetList.length == 0"/>
</div>
<div v-if="!isShow" class="search-input">
<div class="input-box flex-row">
<input
type="span"
class="input"
placeholder="请输入学习标题"
focus="false"
v-model="searchValue"
@blur="onBlur"
/>
<image
class="sousuo"
src="https://cdn.cunwuyun.cn/img/search-active.svg"
></image>
<image
v-if="searchValue"
@tap="clearInput"
class="clear"
src="https://cdn.cunwuyun.cn/img/empty-Input.svg"
></image>
<div class="search-word" @click="search">搜索</div>
</div>
</div>
</div>
</template>
<script>
export default {
appName: "党员学习",
data() {
const currentDate = this.getDate({
format: true,
});
return {
inputValue: "请输入学习标题",
isShow: true,
array: [],
meetType: "",
partyStudyType: "",
index: 0,
date: currentDate,
day: "时间",
createDate: "", //创建时间
meetList: [],
searchValue: "", //搜索框输入值
pageNum: 1,
pageSize: 10,
pages: 2,
userId: "",
partyId: "",
};
},
computed: {
startDate() {
return this.getDate("start");
},
endDate() {
return this.getDate("end");
},
},
onLoad(options) {
this.partyId = options.partyId;
this.$dict.load("partyStudyStatus", "partyStudyType").then((res) => {
this.array = this.$dict.getDict("partyStudyType");
this.array.unshift({dictName: "全部类型", dictValue: ""})
this.getList();
});
},
onShow() {
this.$dict.load("partyStudyStatus", "partyStudyType");
this.getList();
},
methods: {
bindPickerChange(e) {
if (e.detail.value - 1 >= 0) {
this.partyStudyType = e.detail.value - 1;
} else {
this.partyStudyType = "";
}
this.pageNum = 1;
this.pages = 2;
this.pageSize = 10;
this.getList();
},
bindDateChange: function (e) {
this.day = e.target.value;
this.createDate = e.target.value;
this.pageNum = 1;
this.pages = 2;
this.pageSize = 10;
this.getList();
},
getDate(type) {
const date = new Date();
let year = date.getFullYear();
let month = date.getMonth() + 1;
let day = date.getDate();
if (type === "start") {
year = year - 60;
} else if (type === "end") {
year = year + 2;
}
month = month > 9 ? month : "0" + month;
day = day > 9 ? day : "0" + day;
return `${year}-${month}-08 00:00:00 `;
},
changeSearchBox() {
this.isShow = false;
},
onBlur(e) {
this.searchValue = e.target.value;
if (this.searchValue) {
this.inputValue = this.searchValue;
} else {
this.inputValue = "请输入学习标题";
}
},
search() {
this.isShow = true;
this.pageNum = 1;
this.pageSize = 10;
this.pages = 2;
this.getList();
},
clearInput() {
this.searchValue = "";
this.inputValue = "请输入学习标题";
},
getList() {
if (this.pageNum > this.pages) return;
this.$instance.post(`/app/apppartystudy/listWechat`, {
title: this.searchValue,
type: this.partyStudyType,
searchMonth: this.createDate,
current: this.pageNum,
size: this.pageSize,
}).then((res) => {
if (res.code == 0) {
const meetList = this.pageNum > 1 ? [...this.meetList, ...res.data.records] : res.data.records;
this.pages = Math.ceil(res.data.total / 10);
this.meetList = meetList;
}
});
},
toDetail(id) {
uni.navigateTo({
url: "./partyStudyDetail?id=" + id,
});
},
},
onReachBottom() {
this.pageNum = this.pageNum + 1;
this.getList();
},
};
</script>
<style lang="scss" scope>
@import "../../../common/common.css";
.page {
.search-box {
width: 100%;
height: 112px;
background-color: #D7261E;
padding: 24px 32px;
box-sizing: border-box;
.search-input {
line-height: 64px;
width: 100%;
height: 100%;
background: #ce0010;
border-radius: 32px;
color: #f0cbcd;
font-size: 26px;
image {
width: 34px;
height: 34px;
margin: 8px 8px 8px 24px;
position: relative;
top: 6px;
}
span {
display: inline-block;
overflow: hidden;
white-space: nowrap;
span-overflow: ellipsis;
width: 600px;
}
}
}
.slect {
width: 100%;
height: 96px;
background-color: #fff;
color: #666;
.type-select {
width: 50%;
border-right: 1px solid #f7f7f7;
margin: 30px 0;
box-sizing: border-box;
text-align: center;
font-size: 26px;
.uni-input {
display: inline-block;
}
image {
width: 32px;
height: 32px;
display: inline-block;
position: relative;
top: 6px;
margin-left: 8px;
}
}
.type-select:nth-child(2) {
border: none;
}
}
.search-input {
.input-box {
width: 100%;
height: 112px;
background-color: #fff;
padding: 24px 32px;
box-sizing: border-box;
position: relative;
.sousuo {
position: absolute;
top: 35px;
left: 60px;
width: 34px;
height: 34px;
}
.input {
background-color: #f3f3f3;
width: 598px;
height: 64px;
color: #999999;
font-size: 26px;
margin-left: 8px;
border-radius: 32px;
padding-left: 70px;
padding-right: 60px;
box-sizing: border-box;
}
.clear {
width: 32px;
height: 32px;
position: absolute;
top: 40px;
right: 130px;
z-index: 10;
}
.search-word {
font-size: 28px;
color: #135ab8;
line-height: 60px;
margin-left: 20px;
}
}
}
.session-list {
padding-top: 224px;
.session-item {
width: 686px;
margin: 0 auto 32px auto;
background-color: #fff;
position: relative;
overflow: hidden;
.item-top {
padding: 32px 32px 0 32px;
}
.item-title {
font-size: 32px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333;
line-height: 44px;
word-break: break-all;
width: 600px;
}
.item-info {
line-height: 42px;
font-size: 28px;
margin-bottom: 8px;
.info-label {
color: #999;
}
}
.item-bottom {
border-top: 2px solid #eee;
text-align: right;
padding-right: 64px;
box-sizing: border-box;
line-height: 96px;
.item-btn {
display: inline-block;
width: 152px;
height: 52px;
line-height: 52px;
border-radius: 28px;
text-align: center;
font-size: 28px;
margin-left: 32px;
border: 2px solid #e1e1e1;
}
}
.info-value {
color: #343d65;
background-color: #fff !important;
}
.item-status {
position: absolute;
top: 14px;
right: -30px;
width: 140px;
text-align: center;
line-height: 44px;
font-size: 24px;
transform: rotate(45deg);
}
.item-status1 {
color: #5a98f2;
background-color: #f1f6ff;
}
.item-status0 {
color: #ff9b2b;
background-color: #fff3e8;
}
.color-1365DD {
color: #1365dd;
}
.color-FF4466 {
color: #ff4466;
}
.color-333333 {
color: #333;
}
.color-606060 {
color: #606060;
}
.border-1365DD {
border-color: #1365dd !important;
color: #1365dd !important;
}
.border-E1E1E1 {
border-color: #e1e1e1 !important;
color: #606060;
}
.border-E1E1E1 {
border-color: #e1e1e1 !important;
}
.mar-b12 {
margin-bottom: 26px !important;
}
}
}
.no-affairs {
width: 100%;
height: calc(100% - 210px);
display: flex;
justify-content: center;
align-items: center;
}
}
</style>

View File

@@ -0,0 +1,220 @@
<template>
<div class="page">
<header></header>
<div class="form">
<div class="main">
<div class="textarea">
<div class="color-333 fs32">
<span class="color-red">*</span>学习心得
</div>
<textarea
type="textarea"
placeholder="请输入学习心得200字以内"
v-model="content"
adjust-position="false"
maxlength="200"
class="fs32"
></textarea>
</div>
</div>
</div>
<p class="tips-span">说明 : 提交学习心得意味着完成本次内容的学习</p>
<div class="report" @click="changeStatus()">提交</div>
</div>
</template>
<script>
export default {
name: "fillLog",
data() {
return {
id: "",
content: "",
};
},
onLoad(options) {
this.id = options.id;
this.getDetailInfo();
},
methods: {
getDetailInfo() {
this.$instance
.post(`/app/apppartystudylog/queryStudyLog?id=${this.id}`, null, {})
.then((res) => {
if (res.data) {
if (res.data.content != null) {
this.content = res.data.content;
} else {
this.content = "";
}
}
});
},
changeStatus() {
if (!this.content) {
this.$toast("请输入学习心得");
return;
}
let params = {
studyId: this.id,
content: this.content,
};
this.$instance
.post(`/app/apppartystudylog/addStudyLog`, params)
.then((res) => {
if (res.code == 0) {
this.$toast("学习心得提交完成");
setTimeout(function () {
uni.navigateBack({
delta: 2,
});
}, 1000);
}
});
},
},
};
</script>
<style lang="scss" scoped>
@import "../../../common/common.css";
.page {
width: 100%;
height: 100%;
.tips-span {
width: 626px;
font-size: 28px;
font-family: PingFangSC-Regular, PingFang SC;
color: rgba(153, 153, 153, 1);
line-height: 40px;
margin-top: 20px;
padding-left: 32px;
}
textarea {
width: 100%;
height: 688px;
margin-top: 16px;
}
header {
width: 100%;
height: 112px;
background-color: #D7261E;
}
.form {
width: 100%;
padding: 32px;
box-sizing: border-box;
margin-top: -100px;
.main {
background-color: #fff;
border-radius: 8px;
padding: 16px;
box-sizing: border-box;
}
.basic-item {
font-size: 32px;
justify-content: space-between;
width: 100%;
height: 112px;
padding: 32px 32px 32px 12px;
box-sizing: border-box;
background-color: #fff;
border-bottom: 1px solid #eee;
input {
text-align: right;
}
.wid-110 {
width: 214px;
}
.skill-span {
max-width: 432px;
text-align: right;
display: inline-block;
overflow: hidden;
span-overflow: ellipsis;
white-space: nowrap;
font-size: 30px;
}
.picker {
justify-content: flex-end;
align-items: center;
color: #999999;
font-size: 32px;
background-color: #ffffff;
}
.picker > .AiArea {
background-color: #fff !important;
}
.image {
width: 32px;
height: 32px;
vertical-align: middle;
}
.wei-span {
width: 40%;
}
.msg-value {
width: 60%;
}
.msg-btn {
width: 160px;
text-align: right;
background-color: #fff !important;
}
button {
font-size: 28px;
background-color: #fff;
line-height: 48px;
padding: 0;
}
button::after {
border: 0;
}
.button-hover {
background-color: #fff;
}
button[disabled] {
background-color: #fff !important;
font-size: 28px;
border-radius: 0;
}
}
}
.report {
position: fixed;
left: 0;
bottom: 0;
height: 112px;
line-height: 112px;
font-size: 32px;
text-align: center;
background: rgba(230, 0, 18, 1);
color: #fff;
}
.fs32 {
font-size: 32px;
}
}
</style>

View File

@@ -0,0 +1,351 @@
<template>
<div class="page">
<div class="detail-content">
<div class="detail-info">
<div class="info-title">{{ data.title }}</div>
<div class="item-info">
<span class="info-label">学习类别</span>
<span class="info-value">{{ $dict.getLabel('partyStudyType', data.type) }}</span>
</div>
<div class="item-info">
<span class="info-label">发布人员</span>
<span class="info-value">{{ data.publishUserName }}</span>
</div>
<div class="item-info">
<span class="info-label">发布时间</span>
<span class="info-value">{{ data.publishTime }}</span>
</div>
<div class="item-info">
<span class="info-label">学习时间</span>
<span class="info-value">{{ data.studyBeginDate }}{{ data.studyEndDate }}</span>
</div>
<div class="item-info">
<span class="info-label">学习状态</span>
<span class="info-value">{{ $dict.getLabel('partyStudyStatus', data.studyStatus) }}</span>
</div>
<div class="item-info" v-if="data.studyStatus == 1">
<span class="info-label">完成时间</span>
<span class="info-value">{{ data.finishDate || '-' }}</span>
</div>
</div>
<!-- <div class="page-title">学习内容</div> -->
<u-parse :html="data.content" class="content" v-if="data.content"></u-parse>
<AiTransSpeech :src="data.speech"/>
</div>
<div class="btn-box" @click="toContent()">
<span class="active">学习心得</span>
</div>
</div>
</template>
<script>
export default {
data() {
return {
id: '',
data: {},
};
},
onLoad(options) {
this.$dict.load('partyStudyStatus', 'partyStudyType')
this.id = options.id
this.getDetailInfo()
},
onShow() {
this.getDetailInfo()
},
methods: {
toContent() {
uni.navigateTo({url: `./AppPartyStudy?id=${this.id}`})
},
getDetailInfo() {
this.$instance.post(`/app/apppartystudy/queryDetailByIdWeChat?id=${this.id}`, null, {}).then(res => {
if (res.data) {
if (res.data.files && res.data.files.length) {
res.data.files.map(item => {
var size = item.size / 1024;
item.fileSize = size.toFixed(0);
return item
})
}
this.data = res.data
}
})
},
},
};
</script>
<style lang="scss" scope>
@import "../../../common/common.css";
.page {
background-color: #fff;
.detail-content {
padding-bottom: 140px;
}
.content {
padding: 20px;
background-color: #fff;
}
.detail-info {
padding: 16px 32px 8px 32px;
border-bottom: 2px solid #D8DDE6;
background-color: #D7261E;
padding-bottom: 80px;
position: relative;
.info-title {
line-height: 64px;
font-size: 40px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #fff;
word-break: break-all;
margin-bottom: 16px;
}
.item-info {
line-height: 48px;
font-size: 30px;
margin-bottom: 8px;
.info-label {
display: inline-block;
color: #fff;
vertical-align: top;
}
.info-value {
display: inline-block;
width: 510px;
word-break: break-all;
color: #FFE8E8;
}
.item-status0 {
color: #FF9B2B;
}
.item-status1 {
color: #2EA222;
}
.item-status2 {
color: #343D65;
}
.item-status3 {
color: #5A98F2;
}
.item-status4 {
color: #f46;
}
}
.retract-btn {
line-height: 80px;
text-align: center;
font-size: 28px;
color: #fff;
position: absolute;
bottom: 0;
width: 690px;
.down-icon {
width: 32px;
height: 32px;
margin-left: 4px;
vertical-align: middle;
transition: all .3s ease-in-out;
}
.icon-active {
transform: rotate(180deg);
}
}
}
.page-title {
line-height: 96px;
color: #333;
font-size: 32px;
padding-left: 32px;
background-color: #fff;
span {
font-size: 28px;
}
}
.info-content {
padding: 16px 32px;
background-color: #fff;
line-height: 48px;
color: #333;
font-size: 32px;
box-sizing: border-box;
}
.user-list {
background-color: #fff;
.user-item {
height: 112px;
padding-top: 16px;
box-sizing: border-box;
.user-bg {
display: inline-block;
width: 80px;
height: 80px;
background-color: #4E8EEE;
color: #fff;
text-align: center;
line-height: 80px;
margin: 0 16px 0 32px;
font-size: 28px;
border-radius: 50%;
vertical-align: top;
}
.user-info {
display: inline-block;
width: 622px;
height: 96px;
border-bottom: 2px solid #D8DDE6;
box-sizing: border-box;
.user-name {
line-height: 44px;
color: #333;
font-size: 32px;
}
.user-unit {
line-height: 34px;
color: #999;
font-size: 24px;
}
}
}
.user-item:nth-last-of-type(1) {
.user-info {
border-bottom: 0;
}
}
}
.mar-b8 {
margin-bottom: 16px;
}
.color-1365DD {
color: #1365DD;
}
.color-999999 {
color: #999999;
}
.pad-l7 {
padding-left: 14px;
}
.attachment {
width: 100%;
padding: 32px;
box-sizing: border-box;
background-color: #FFFFFF;
margin-top: 16px;
.attachment-title {
font-size: 32px;
color: #333333;
font-weight: 500;
image {
width: 48px;
height: 48px;
vertical-align: middle;
}
}
.attachment-item {
border: 1px solid rgba(204, 204, 204, 1);
padding: 16px;
box-sizing: border-box;
margin-top: 34px;
display: flex;
flex-direction: row;
justify-content: space-between;
border-radius: 8px;
.file-name {
justify-content: flex-start;
align-items: center;
image {
width: 96px;
height: 96px;
vertical-align: middle;
}
.title {
color: #333333;
font-size: 32px;
word-break: break-all;
flex: 1;
}
}
.size {
color: #999;
font-size: 28px;
display: flex;
justify-content: cemter;
align-items: center;
}
}
}
.btn-box {
position: fixed;
display: flex;
bottom: 0;
height: 112px;
line-height: 112px;
width: 100%;
color: #333;
background-color: #fff;
font-size: 36px;
span {
flex: 1;
text-align: center;
}
.active {
background-color: #D7261E;
color: #fff;
}
}
}
.partyStudyContent {
width: 100%;
height: calc(100% - 184px);
padding: 32px;
box-sizing: border-box;
color: #666;
font-size: 32px;
background-color: #fff;
word-break: break-all;
}
</style>

View File

@@ -0,0 +1,576 @@
<template>
<div class="page">
<div v-if="isShow" style="height:100%;">
<div class="fixed-top" style="width:100%;">
<!-- 头部搜索样式 -->
<div class="search-box">
<div class="search-input flex-row" @click="changeSearchBox">
<image src="https://cdn.cunwuyun.cn/img/search-red.svg"></image>
<span>{{ inputValue }}</span>
</div>
</div>
<!-- 选择时间和类型 -->
<div class='slect flex-row'>
<!-- 类型选择 -->
<div class="uni-list type-slect">
<div class="uni-list-cell">
<div class="uni-list-cell-db">
<picker @change="bindPickerChange" :range="array" range-key="dictName">
<div class="uni-input">{{ meetTypespan }}</div>
<image src="https://cdn.cunwuyun.cn/img/down.svg"></image>
</picker>
</div>
</div>
</div>
<!-- 时间选择 -->
<div class="uni-list type-slect">
<div class="uni-list-cell">
<div class="uni-list-cell-db">
<picker mode="date" :value="date" :start="startDate" :end="endDate" @change="bindDateChange"
fields='month'>
<div class="uni-input">{{ day }}</div>
<image src="https://cdn.cunwuyun.cn/img/down.svg"></image>
</picker>
</div>
</div>
</div>
</div>
</div>
<div class="session-list">
<div class="session-item" v-for="(item, index) in meetList" :key="index">
<div class="item-top" @click="toSessionDetail(item.meetingId, item.status)">
<div class="item-title mar-b12">{{ item.meetingAgenda }}</div>
<div class="item-info">
<span class="info-label">会议状态</span>
<span :class="'item-status'+item.postStatus" class="info-value">
{{ $dict.getLabel('postStatus', item.postStatus) }}
</span>
</div>
<div class="item-info">
<span class="info-label">开始时间</span>
<span class="info-value">{{ item.startTime || '-' }}</span>
</div>
<div class="item-info">
<span class="info-label">会议地点</span>
<span class="info-value">{{ item.meetingAddress || '-' }}</span>
</div>
<div class="item-info">
<span class="info-label">主持人员</span>
<span class="info-value">{{ item.hostName || '-' }}</span>
</div>
<div class="item-info mar-b12">
<span class="info-label">会议类型</span>
<span class="info-value">{{ item.meetingClassification || '-' }}</span>
</div>
</div>
<div class="item-bottom">
<span class="item-btn border-E1E1E1" v-if="item.status == 3">已请假</span>
<span class="item-btn border-1365DD" v-if="item.status == 0 && item.isSignEnd"
@click="signMeeting(item.meetingId)">签到</span>
<span class="item-btn border-E1E1E1" v-if="item.status == 1">已签到</span>
<!-- <span class="item-btn border-E1E1E1" v-if="item.status == 4">不签到</span> -->
</div>
<div class="item-status" :class="'item-status'+item.postStatus">
{{ $dict.getLabel('postStatus', item.postStatus) }}
</div>
</div>
</div>
<AiEmpty v-if="meetList.length == 0"/>
</div>
<div v-if="!isShow" class="search-input">
<div class="input-box flex-row">
<input class="input" placeholder="请输入会议标题" focus="false" v-model="searchValue" @blur="onBlur"/>
<image class="sousuo" src="https://cdn.cunwuyun.cn/img/search-active.svg"></image>
<image v-if="searchValue" @tap="clearInput" class="clear"
src="https://cdn.cunwuyun.cn/img/empty-Input.svg"></image>
<div class="search-word" @click="search">搜索</div>
</div>
</div>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
appName: "三会一课",
data() {
const currentDate = this.getDate({
format: true
})
return {
inputValue: "请输入会议标题",
isShow: true,
array: [],
meetType: "",
meetTypespan: "会议类型",
index: 0,
date: currentDate,
day: "会议时间",
createDate: "",//创建时间
meetList: [],
searchValue: "",//搜索框输入值
pageNum: 1,
pageSize: 10,
pages: 2,
userId: '',
partyId: '',
meetTypeIndex: '',
};
},
computed: {
startDate() {
return this.getDate('start');
},
endDate() {
return this.getDate('end');
},
...mapState(['user']),
},
onLoad() {
this.partyId = this.user.id
this.$dict.load('postStatus', 'meetingClassification').then(() => {
this.array = this.$dict.getDict('meetingClassification')
this.getList()
})
uni.$on('updateList', () => {
this.pageNum = 1;
this.pages = 2;
this.getList()
})
},
methods: {
signMeeting(id) {
this.$instance.post(`/app/appthreemeetinguser/signByMeetingIdAndUserIdForWX?meetingId=${id}&userId=${this.user.partyId}`, null, {}).then(res => {
if (res.code == 0) {
this.$toast('签到成功')
this.pageNum = 1;
this.pages = 2;
this.getList()
}
}).catch(err => {
uni.showToast({
icon: 'none',
title: err,
duration: 2000
});
})
},
btnClick(span) {
uni.showToast({
icon: 'none',
title: span,
duration: 2000
});
},
bindPickerChange(e) {
this.array.map((item, index) => {
if (e.detail.value == item.dictValue) {
this.meetTypespan = this.array[index].dictName
}
})
this.meetTypeIndex = e.detail.value
this.pageNum = 1;
this.pages = 2;
this.pageSize = 10;
this.getList()
},
bindDateChange: function (e) {
this.day = e.target.value;
this.createDate = e.target.value + '-' + "01"
this.pageNum = 1;
this.pages = 2;
this.pageSize = 10;
this.getList()
},
getDate(type) {
const date = new Date();
let year = date.getFullYear();
let month = date.getMonth() + 1;
let day = date.getDate();
if (type === 'start') {
year = year - 60;
} else if (type === 'end') {
year = year + 2;
}
month = month > 9 ? month : '0' + month;
day = day > 9 ? day : '0' + day;
return `${year}-${month}-08 00:00:00 `;
},
changeSearchBox() {
this.isShow = false;
},
onBlur(e) {
this.searchValue = e.target.value;
if (this.searchValue) {
this.inputValue = this.searchValue;
} else {
this.inputValue = "请输入会议标题";
}
},
search() {
this.isShow = true;
this.pageNum = 1;
this.pageSize = 10;
this.pages = 2;
this.getList()
},
clearInput() {
this.searchValue = ''
this.inputValue = "请输入会议标题";
},
getList() {
if (this.pageNum > this.pages) return
// var searchYMD = ''
// if(this.createDate) {
// searchYMD = this.createDate + '-01'
// }
this.$instance.post(`/app/appthreemeetinguser/listForWX?meetingUserId=${this.user.partyId}&meetingAgenda=${this.searchValue}&meetingClassification=${this.meetTypeIndex}&searchYMD=${this.createDate}&current=${this.pageNum}&size=${this.pageSize}`
).then(res => {
if (res.code == 0) {
const meetList = this.pageNum > 1 ? [...this.meetList, ...res.data.records] : res.data.records
meetList.map(item => {
if (item.meetingAfter) {
var dEnd = new Date(item.startTime.replaceAll('-', '/'));
item.isSignEnd = new Date(dEnd.getTime() + (Number(item.meetingAfter)) * 60000).getTime() > new Date().getTime()
}
if (item.meetingClassification.length == 1) {
item.meetingClassification = this.$dict.getLabel('meetingClassification', item.meetingClassification)
} else {
var typeList = item.meetingClassification.split(',')
typeList.map((items, index) => {
if (index == 0) {
item.meetingClassification = this.$dict.getLabel('meetingClassification', items)
} else {
item.meetingClassification = item.meetingClassification + ',' + this.$dict.getLabel('meetingClassification', items)
}
return item.meetingClassification
})
return item.meetingClassification
}
return item
})
this.pages = Math.ceil(res.data.total / 10)
this.meetList = meetList
}
})
},
toSessionDetail(id, signStatus) {
uni.navigateTo({
url: `./threeSessionsDetail?id=${id}&signStatus=${signStatus}&token=${uni.getStorageSync("token")}`
})
},
leave() {
uni.showModal({
title: '如需请假,请联系签到负责人',
confirmspan: "确认",
confirmColor: "#135AB8",
success: function (res) {
if (res.confirm) {
} else if (res.cancel) {
}
}
});
},
changeStatus(id, signStatus, joinStatus, signMethod, absence, meetingUserId, meetingId, successspan) {
let signTime = new Date().getFullYear() + '-' + this.isDate(new Date().getMonth() + 1) + '-' + this.isDate(new Date().getDate()) + ' ' + this.isDate(new Date().getHours()) + ':' + this.isDate(new Date().getMinutes()) + ':' + this.isDate(new Date().getSeconds())
var params = {
id,
signStatus,
joinStatus,
signMethod,
absence,
signUserId: this.user.id,
signUserName: this.user.realName,
signTime,
meetingUserId,
meetingId
}
this.$instance.post(`/app/appthreemeetinguser/addOrUpdate`, null, {
data: params
}).then(res => {
if (res?.code == 0) {
uni.showToast({
title: successspan + '成功!',
duration: 2000
});
this.pageNum = 1;
this.pages = 2;
this.getList()
}
})
},
isDate(num) {
if (num < 10) {
num = '0' + num
}
return num
},
},
onReachBottom() {
this.pageNum = this.pageNum + 1
this.getList()
}
};
</script>
<style lang="scss" scope>
.page {
.fixed-top {
z-index: 9999;
}
.search-box {
width: 100%;
height: 112px;
background-color: #D7261E;
padding: 24px 32px;
box-sizing: border-box;
.search-input {
display: flex;
align-items: center;
line-height: 64px;
width: 100%;
height: 100%;
background: #CE0010;
border-radius: 32px;
color: #F0CBCD;
font-size: 26px;
image {
width: 34px;
height: 34px;
margin: 8px 8px 8px 24px;
}
}
}
.slect {
width: 100%;
height: 96px;
background-color: #fff;
color: #666;
.type-slect {
width: 50%;
border-right: 1px solid #F7F7F7;
margin: 30px 0;
box-sizing: border-box;
text-align: center;
font-size: 26px;
.uni-input {
display: inline-block;
}
image {
width: 32px;
height: 32px;
display: inline-block;
position: relative;
top: 6px;
margin-left: 8px;
}
}
.type-slect:nth-child(2) {
border: none;
}
}
.search-input {
.input-box {
width: 100%;
height: 112px;
background-color: #fff;
padding: 24px 32px;
box-sizing: border-box;
position: relative;
.sousuo {
position: absolute;
top: 50%;
left: 60px;
width: 34px;
height: 34px;
transform: translateY(-50%);
}
.input {
background-color: #F3F3F3;
width: 598px;
height: 64px;
color: #999999;
font-size: 26px;
margin-left: 8px;
border-radius: 32px;
padding-left: 70px;
padding-right: 60px;
box-sizing: border-box;
}
.clear {
width: 32px;
height: 32px;
position: absolute;
top: 40px;
right: 130px;
z-index: 10;
}
.search-word {
font-size: 28px;
color: #135AB8;
line-height: 60px;
margin-left: 20px;
}
}
}
.session-list {
padding-top: 224px;
.session-item {
width: 686px;
margin: 0 auto 32px auto;
background-color: #fff;
// height:462px; position: relative;
overflow: hidden;
.item-top {
padding: 32px 32px 0 32px;
}
.item-title {
font-size: 32px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333;
line-height: 44px;
word-break: break-all;
}
.item-info {
line-height: 42px;
font-size: 28px;
margin-bottom: 8px;
.info-label {
display: inline-block;
color: #999;
width: 200px;
}
.info-value {
display: inline-block;
width: calc(100% - 200px);
vertical-align: top;
word-break: break-all;
}
}
.item-bottom {
border-top: 2px solid #EEE;
text-align: right;
padding-right: 64px;
box-sizing: border-box;
line-height: 96px;
.item-btn {
display: inline-block;
width: 152px;
height: 52px;
line-height: 52px;
border-radius: 28px;
text-align: center;
font-size: 28px;
margin-left: 32px;
border: 2px solid #E1E1E1;
}
}
.info-value {
color: #343D65;
background-color: #fff !important;
}
.item-status {
position: absolute;
top: 14px;
right: -36px;
width: 140px;
text-align: center;
line-height: 44px;
font-size: 24px;
transform: rotate(45deg);
}
.item-status1 {
color: #FF9B2B;
background-color: #FFF3E8;
}
.item-status0 {
color: #2EA222;
background-color: #EAF5E8;
}
.item-status3 {
color: #999;
background-color: #F2F2F2;
}
.item-status2 {
color: #5A98F2;
background-color: #F1F6FF;
}
.color-1365DD {
color: #1365DD;
}
.color-FF4466 {
color: #FF4466;
}
.color-333333 {
color: #333;
}
.color-606060 {
color: #606060;
}
.border-1365DD {
border-color: #1365DD !important;
color: #1365DD !important;
}
.border-E1E1E1 {
border-color: #E1E1E1 !important;
color: #606060;
}
.border-E1E1E1 {
border-color: #E1E1E1 !important;
}
.mar-b12 {
margin-bottom: 26px !important;
}
}
}
.no-affairs {
width: 100%;
height: calc(100% - 210px);
display: flex;
justify-content: center;
align-items: center;
}
}
</style>

View File

@@ -0,0 +1,209 @@
<template>
<div class="page">
<!-- <span class="close-img" @click="closePage()">×</span> -->
<image src="https://cdn.cunwuyun.cn/img/qrcode-sign-img.png" class="banner-img"></image>
<div class="btn" @click="btnClick()">{{ btnspan }}</div>
<div class="mask" v-if="showFail">
<div class="mask-content">
<image src="https://cdn.cunwuyun.cn/img/qrcode-sign-fail.png" class="fail-img"></image>
<div class="mask-span">签到失败请重新签到</div>
<div class="mask-btn" @click="btnClick()">确认签到</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
showFail: false,
meetingId: '',
btnspan: '',
scene: '',
userId: '',
isSign: true
};
},
onShow() {
if (uni.getStorageSync('token')) {
this.meetingId = this.$mp.query.scene
// this.meetingId = 'c29aacb54f074c14ab93532e384a6daa'
this.getUserInfo()
} else {
uni.showModal({
title: '提示',
content: '您还未登录,请先登录!',
confirmspan: "去登录",
showCancel: false,
success(res) {
if (res.confirm) {
wx.switchTab({
url: '../mine/mine',
})
}
}
})
}
},
methods: {
getUserInfo() {
this.$store.commit("getUserInfo", v => {
if (v) {
this.userId = res.data.id
this.getDetailInfo()
}
})
},
getDetailInfo() {
this.$instance.post(`/app/appthreemeetinguser/queryWeathersignByMeetingIdAndUserIdForWX?meetingId=${this.meetingId}&userId=${this.userId}`, null, {}).then(res => {
if (res.data) {
this.isSign = true
// if(res.data.status == 1) { //已签到
// this.btnspan = '已签到'
// }
if (res.data.status == 0) { //未签
this.btnspan = '确认签到'
} else {
this.btnspan = '已签到'
}
} else {
this.btnspan = '确认签到'
this.isSign = false //不是参会人员
}
}).catch(err => {
uni.showToast({
icon: 'none',
title: err,
duration: 2000
});
})
},
btnClick() {
// if(!this.isSign) {
// uni.showToast({
// icon: 'none',
// title: '您不是参会人员',
// duration: 2000
// });
// return
// }
if (this.btnspan == '已签到') {
uni.showToast({
icon: 'none',
title: '已签到',
duration: 2000
});
return
}
this.$instance.post(`/app/appthreemeetinguser/signByMeetingIdAndUserIdForWX?meetingId=${this.meetingId}&userId=${this.userId}`, null, {}).then(res => {
if (res.code == 0) {
this.btnspan = '已签到'
uni.showToast({
title: '签到成功',
duration: 2000
});
} else {
this.showFail = true
}
}).catch(err => {
uni.showToast({
icon: 'none',
title: err,
duration: 2000
});
})
},
closePage() {
uni.reLaunch({
url: "../home/portal"
})
}
},
};
</script>
<style lang="scss" scope>
@import "../../../common/common.css";
.page {
background-color: #FFFFFF;
position: relative;
.close-img {
position: absolute;
font-size: 50px;
left: 32px;
}
.banner-img {
width: 514px;
height: 340px;
margin: 48px 0 118px 96px;
}
.btn {
width: 622px;
line-height: 96px;
text-align: center;
background: rgba(19, 90, 184, 1);
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.02);
border-radius: 8px;
margin: 0 auto;
color: #fff;
font-size: 32px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
}
.mask {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, .3);
.mask-content {
width: 686px;
height: 640px;
background: #fff;
border-radius: 8px;
border: 2px solid rgba(151, 151, 151, 1);
margin: 260px auto 0;
.fail-img {
width: 160px;
height: 160px;
margin: 112px 0 32px 264px;
}
.mask-span {
width: 100%;
line-height: 50px;
font-size: 36px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 700;
color: rgba(51, 51, 51, 1);
text-align: center;
margin-bottom: 134px;
}
.mask-btn {
width: 560px;
line-height: 96px;
text-align: center;
background: rgba(19, 90, 184, 1);
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.02);
border-radius: 8px;
margin: 0 auto;
color: #fff;
font-size: 32px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
}
}
}
}
</style>

View File

@@ -0,0 +1,460 @@
<template>
<div class="page">
<header></header>
<div class="form">
<div class="main">
<div class="textarea">
<div class="color-666"><span class="color-red">*</span>会议内容</div>
<textarea
type="textarea"
placeholder="请输入会议内容3000字以内"
v-model="baseInfo.content"
adjust-position="false"
maxlength="3000"
></textarea>
</div>
<div class="uni-uploader">
<div class="title-box title-box-margin">
<span class="title color-666">图片资料最多9张</span>
</div>
<div class="uni-uploader-body">
<div class="uni-uploader__files">
<block v-for="(image, index) in imageList" :key="index">
<div class="uni-uploader__file">
<image
class="uni-uploader__img"
:src="image.accessUrl"
:data-index="index"
@tap="previewImage"
></image>
<AiUniIcon
type="clear"
class="icon"
color="#8f8f94"
size="26"
@click="deleteImage(index)"
></AiUniIcon>
</div>
</block>
<div
class="pre-div"
@tap="chooseImageType"
v-if="imageList.length < 9"
>
<span class="pre-label">+</span>
<span class="add-image">添加照片</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="report" @click="report()">提交</div>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
name: "fillLog",
data() {
return {
reportId: "",
baseInfo: {
content: "",
fileIds: [],
reportId: "",
id: "",
images: [],
meetingId: "",
createUserName: "",
},
imageList: [],
sourceTypeIndex: 2,
sourceType: [
// 图片来源类型
["camera"],
["album"],
],
};
},
computed: {
...mapState(['user']),
},
onLoad(options) {
this.baseInfo.meetingId = options.id;
this.getDetailInfo();
},
methods: {
getDetailInfo() {
this.$instance.post(`/app/appthreemeetinginfoexpand/queryDetailById?id=${this.baseInfo.meetingId}`).then((res) => {
if (res.data) {
if (res.data.images != null) {
this.imageList = JSON.parse(res.data.images);
}
this.baseInfo = {...res.data};
}
})
.catch((err) => {
});
},
// 选择照片类型
chooseImageType() {
let that = this;
uni.showActionSheet({
itemList: ["拍照", "从相册选择"],
success: function (res) {
// console.log(res.tapIndex)
that.sourceTypeIndex = res.tapIndex;
// console.log(that.sourceTypeIndex)
that.chooseImage();
},
});
},
showModel(title) {
uni.showModal({
title: "温馨提示",
content: title,
showCancel: false,
confirmColor: "#135AB8",
success(res) {
if (res.confirm) {
}
},
});
},
chooseImage: async function () {
let that = this;
if (that.imageList.length === 9) {
let isContinue = await that.isFullImg();
// console.log("是否继续?", isContinue);
if (!isContinue) {
return;
}
}
uni.chooseImage({
// 从相册选择或相机拍摄
sourceType: that.sourceType[that.sourceTypeIndex],
// 最多可以选择的图片数量
count: 9,
success: (res) => {
// 图片的本地文件路径列表
that.tempFilePaths = res.tempFilePaths;
// console.log(res.tempFilePaths)
for (let i = 0; i < that.tempFilePaths.length; i++) {
let str = "";
let token = uni.getStorageSync("token");
// console.log('token',token)
let params = {
token: token,
};
// url String 是 开发者服务器 url
// files Aarry 否 需要上传的文件列表。使用 files 时filePath 和 name 不生效。 5+App
// filePath String 是 要上传文件资源的路径。
// name String 是 文件对应的 key , 开发者在服务器端通过这个 key 可以获取到文件二进制内容
// header Object 否 HTTP 请求 Header, header 中不能设置 Referer
// formData Object 否 HTTP 请求中其他额外的 form data
// success Function 否 接口调用成功的回调函数
// fail Function 否 接口调用失败的回调函数
// complete Function 否 接口调用结束的回调函数(调用成功、失败都会执行)
uni.uploadFile({
url: this.$instance.baseURL + "/admin/file/add",
filePath: that.tempFilePaths[i],
name: "file",
// formData:params,
header: {
"Content-Type": "multipart/form-data",
access_token: token,
Authorization: token,
},
success(res) {
// console.log('uploader',res)
str = JSON.stringify(JSON.parse(res.data).data[0]).replace(
/\"/g,
""
);
var temp = {
fileId: str.split(";")[1],
accessUrl: str.split(";")[0],
};
that.imageList = that.imageList.concat(temp);
if (that.imageList.length > 9) {
that.imageList = that.imageList.slice(0, 9);
uni.showToast({
title: "图片最多只能上传9张",
icon: "none",
});
}
that.imgUrl = JSON.stringify(that.imageList);
// console.log('imageList-upload',that.imageList)
},
fail(res) {
console.log("error", res);
},
});
}
},
});
},
// 预览图片(大图预览)
previewImage: function (e) {
let that = this;
// console.log('预览',e)
var current = e.target.dataset.index;
// console.log(current)
var tempList = [];
for (var i in that.imageList) {
tempList.push(that.imageList[i].accessUrl);
}
uni.previewImage({
// 当前图片的索引、链接
current: tempList[current],
urls: tempList,
longPressActions: {
itemList: ["发送给朋友", "保存图片", "收藏"],
success: function (data) {
// console.log('选中了第' + (data.tapIndex + 1) + '个按钮,第' + (data.index + 1) + '张图片');
},
fail: function (err) {
// console.log(err.errMsg);
},
},
});
},
// 删除照片
deleteImage(index) {
this.imageList.splice(index, 1);
},
report() {
if (!this.baseInfo.content) {
uni.showToast({title: "会议内容不能为空", icon: "none"});
return false;
}
this.baseInfo.fileIds = [];
this.imageList.forEach((e) => {
this.baseInfo.fileIds.push(e.fileId);
});
this.baseInfo.images = JSON.stringify(this.imageList);
this.baseInfo.createUserName = this.user.realName;
this.$instance
.post(`/app/appthreemeetinginfoexpand/addOrUpdate`, this.baseInfo, null)
.then((res) => {
if (res.code == 0) {
uni.showToast({
title: "会议纪要提交成功",
icon: "none",
duration: 2000,
});
setTimeout(() => {
uni.navigateBack({
delta: 2,
});
}, 2000);
}
})
.catch((err) => {
uni.showToast({
title: err,
icon: "none",
duration: 1000,
});
});
},
},
};
</script>
<style lang="scss" scoped>
@import "../../../common/common.css";
.page {
width: 100%;
height: 100%;
font-size: 32px;
header {
width: 100%;
height: 112px;
background-color: #D7261E;
}
.form {
width: 100%;
padding: 32px;
box-sizing: border-box;
margin-top: -100px;
.main {
background-color: #fff;
border-radius: 8px;
padding: 16px;
box-sizing: border-box;
}
.basic-item {
font-size: 32px;
justify-content: space-between;
width: 100%;
height: 112px;
padding: 32px 32px 32px 12px;
box-sizing: border-box;
background-color: #fff;
border-bottom: 1px solid #eee;
input {
text-align: right;
}
.wid-110 {
width: 214px;
}
.skill-span {
max-width: 432px;
text-align: right;
display: inline-block;
overflow: hidden;
span-overflow: ellipsis;
white-space: nowrap;
font-size: 30px;
}
.picker {
justify-content: flex-end;
align-items: center;
color: #999999;
font-size: 32px;
background-color: #ffffff;
}
.picker > .AiArea {
background-color: #fff !important;
}
.image {
width: 32px;
height: 32px;
vertical-align: middle;
}
.wei-span {
width: 40%;
}
.msg-value {
width: 60%;
}
.msg-btn {
width: 160px;
text-align: right;
background-color: #fff !important;
}
button {
font-size: 28px;
background-color: #fff;
line-height: 48px;
padding: 0;
}
button::after {
border: 0;
}
.button-hover {
background-color: #fff;
}
button[disabled] {
background-color: #fff !important;
font-size: 28px;
border-radius: 0;
}
}
/* 上传照片 */
.uni-uploader {
flex: 1;
flex-direction: column;
}
.uni-uploader-head {
display: flex;
flex-direction: row;
justify-content: space-between;
}
.uni-uploader-info {
color: #b2b2b2;
}
.uni-uploader-body {
margin-top: 16px;
}
.uni-uploader__files {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.uni-uploader__file {
margin-right: 10px;
margin-bottom: 20px;
width: 160px;
height: 160px;
position: relative;
}
.uni-uploader__img {
display: block;
width: 160px;
height: 160px;
}
.pre-label {
font-size: 80px;
color: #dddddd;
}
.add-image {
color: #dddddd;
font-size: 24px;
}
.pre-div {
width: 160px;
height: 160px;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
border-radius: 8px;
border: 2px solid #dddddd;
}
.icon {
position: absolute;
top: -15px;
right: -10px;
}
}
.report {
position: fixed;
left: 0;
bottom: 0;
height: 112px;
line-height: 112px;
font-size: 32px;
text-align: center;
background: rgba(230, 0, 18, 1);
color: #fff;
}
}
</style>

View File

@@ -0,0 +1,528 @@
<template>
<div class="page">
<div class="detail-info">
<div class="info-title">{{ data.meetingAgenda }}</div>
<div class="item-info">
<span class="info-label">会议状态</span>
<span class="info-value">{{ $dict.getLabel('postStatus', data.postStatus) }}</span>
</div>
<div class="item-info">
<span class="info-label">举办方式</span>
<span class="info-value">{{ data.isOnline == 1 ? '线上会议' : '线下会议' }}</span>
</div>
<div class="item-info">
<span class="info-label">会议分类</span>
<span class="info-value" v-if="data.meetingClassification && data.meetingClassification.length">
<span v-for="(item, index) in data.meetingClassification" :key="index">
{{ $dict.getLabel('meetingClassification', item) }}
<span v-if="index < data.meetingClassification.length - 1">,</span>
</span>
</span>
<span class="info-value" v-else>-</span>
</div>
<div class="item-info" v-if="showAll">
<span class="info-label">会议时间</span>
<span class="info-value">{{ data.startTime || '-' }}</span>
</div>
<div class="item-info" v-if="showAll">
<span class="info-label">签到时间</span>
<div class="info-value">
<i v-if="data.signMethod == 1 && signStart">{{ signStart }}</i>
<i class="sign-end" v-if="data.signMethod == 1 && signEnd"> {{ signEnd }}</i>
<i v-if="data.signMethod != 1">-</i>
</div>
</div>
<div class="item-info" v-if="showAll">
<span class="info-label">会议地点</span>
<span class="info-value">{{ data.meetingAddress || '-' }}</span>
</div>
<!-- <div class="item-info" v-if="showAll">
<span class="info-label">会议主题</span>
<span class="info-value" v-if="data.topicClassification && data.topicClassification.length">
<span v-for="(item, index) in data.topicClassification" :key="index">
{{ $dict.getLabel('topicClassification', item) }}
<span v-if="index < data.topicClassification.length - 1">,</span>
</span>
</span>
<span class="info-value" v-else>-</span>
</div> -->
<div class="item-info" v-if="showAll">
<span class="info-label">主持人员</span>
<span class="info-value">{{ data.hostName || '-' }}</span>
</div>
<div class="item-info" v-if="showAll">
<span class="info-label">发布人员</span>
<span class="info-value">{{ data.createUserName || '-' }}</span>
</div>
<div class="item-info" v-if="showAll">
<span class="info-label">签到人员</span>
<span class="info-value" v-if="data.chargeOfSignInList && data.chargeOfSignInList.length">
<span v-for="(item, index) in data.chargeOfSignInList" :key="index">
{{ item.userName }}
<span v-if="index < data.chargeOfSignInList.length - 1">,</span>
</span>
</span>
<span class="info-value" v-else>-</span>
</div>
<div class="item-info" v-if="showAll">
<span class="info-label">记录人员</span>
<span class="info-value">{{ data.recorderName || '-' }}</span>
</div>
<div class="retract-btn" @click="divAll()">
<span>{{ btnspan }}</span>
<image src="https://cdn.cunwuyun.cn/img/down-icon-fff.png"
:class="btnspan == '收起' ? 'down-icon icon-active' : 'down-icon'"></image>
</div>
</div>
<div class="page-title">会议内容</div>
<div class="info-content mar-b8" v-html="data.meetingDescription"></div>
<div class="page-title mar-b8" @click="toSessionUser">参会情况
<span class="pad-l7" v-for="(item, index) in titleList" :key="index">
<span class="color-999999">{{ item.label }}</span>
<span class="color-1365DD">({{ item.value }})</span>
</span>
<img src="https://cdn.cunwuyun.cn/img/down.svg" class="right-icon">
</div>
<div class="user-list">
<div class="user-item" v-for="(item, index) in data.appThreeMeetingUserList" :key="index"
v-if="item.meetingUserRole == 0 || item.meetingUserRole == 3">
<div class="user-bg">{{ formatName(item.meetingUserName) }}</div>
<div class="user-info">
<div class="user-name">{{ item.meetingUserName }}</div>
</div>
</div>
</div>
<div class="btn-bottom" v-if="signStatus < 1 || data.isOnline == 1">
<div class="btn" @click="signMeeting" v-if="data.isOnline != 1 && isSignEnd">签到</div>
<div class="btn" @click="isWeiXin" v-if="data.isOnline == 1">进入直播间</div>
</div>
<div class="mask" v-if="showMask" @click="showMask=false">
<img src="https://cdn.cunwuyun.cn/guangdong/h5/mask-text.png" alt="" class="text-img">
</div>
<img src="https://cdn.cunwuyun.cn/guangdong/h5/vote-img.png" alt="" class="vote-img" v-if="data.isVote == 1"
@click="toVote">
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
data() {
return {
titleList: [
{label: '参与', value: '0'},
{label: '已到', value: '0'},
{label: '未到', value: '0'},
// {label: '请假', value: '0'}
],
id: '',
data: {},
btnspan: '展开',
showAll: false,
partyId: '',
signStart: '',
signEnd: '',
signStatus: '', //0表示显示签到
showMask: false,
isSignEnd: false
};
},
computed: {
...mapState(['user']),
},
onLoad(options) {
if (!uni.getStorageSync("token")) {
uni.setStorageSync("token", options.token)
}
this.$dict.load('postStatus', 'meetingClassification', 'topicClassification').then(() => {
this.id = options.id
this.signStatus = options.signStatus
this.getDetailInfo()
})
},
methods: {
isWeiXin() {
uni.navigateTo({url: `./ylinkMeetingRoom?meetingNum=${this.data.onlineNum}&pwd=${this.data.onlinePwd}`})
},
copy() {
var token = uni.getStorageSync('token')
uni.setClipboardData({data: `https://gdpartyh5.cunwuyun.cn/pages/party/threeSessions/threeSessionsDetail?id=${this.id}&signStatus=${this.signStatus}&token=${token}`});
},
signMeeting() {
this.$instance.post(`/app/appthreemeetinguser/signByMeetingIdAndUserIdForWX?meetingId=${this.data.id}&userId=${this.user.partyId}`, null, {}).then(res => {
if (res.code == 0) {
this.$toast('签到成功')
this.getDetailInfo()
this.signStatus = 1
uni.$emit('updateList')
}
}).catch(err => {
uni.showToast({
icon: 'none',
title: err,
duration: 2000
});
})
},
toContent() {
uni.navigateTo({
url: './threeSessionsContent?id=' + this.id
})
},
toSessionUser() {
uni.navigateTo({
url: './threeSessionsUser?id=' + this.id
})
},
getDetailInfo() {
this.$loading()
this.$instance.post(`/app/appthreemeetinginfo/queryDetailById?id=${this.id}`, null, {}).then(res => {
if (res.data) {
var data = res.data
if (data.startTime && data.meetingBefore) {
var dStart = new Date(data.startTime.replaceAll('-', '/'));
var timeStart = dStart.getTime();
var minStart = (Number(data.meetingBefore)) * 60000
var totalStart = timeStart - minStart;
this.signStart = this.countTime(totalStart);
}
if (data.startTime && data.meetingAfter) {
var dEnd = new Date(data.startTime.replaceAll('-', '/'));
var timeEnd = dEnd.getTime();
var minEnd = (Number(data.meetingAfter)) * 60000
var totalEnd = timeEnd + minEnd;
this.signEnd = this.countTime(totalEnd);
this.isSignEnd = new Date(dEnd.getTime() + minEnd).getTime() > new Date().getTime()
}
data.meetingClassification = data.meetingClassification.split(',')
this.titleList[0].value = data.participantList.length || '0'
if (data.isArriveLIst) {
this.titleList[1].value = data.isArriveLIst.length
}
if (data.isArriveLIst) {
this.titleList[2].value = data.notArriveLIst.length
}
// if (data.isArriveLIst) {
// this.titleList[3].value = data.leaveLIst.length
// }
this.data = data
// var methodsObj = data.reminderMethod
// this.objInit(methodsObj, 'reminderMethod')
// var meetingClassificationObj = data.meetingClassification
// this.objInit(meetingClassificationObj, 'meetingClassification')
// var topicClassificationObj = data.topicClassification
// this.objInit(topicClassificationObj, 'topicClassification')
this.$hideLoading()
}
})
},
objInit(obj, name) {
this.data[name] = []
for (let i in obj) {
if (obj[i] !== '') {
this.data[name].push(obj[i])
}
}
},
//会议签到时间计算
countTime(total) {
var now = new Date(total)
var y = now.getFullYear();
var m = now.getMonth() + 1;
m = m < 10 ? ('0' + m) : m;
var da = now.getDate();
da = da < 10 ? ('0' + da) : da;
var h = now.getHours();
h = h < 10 ? ('0' + h) : h;
var minute = now.getMinutes();
minute = minute < 10 ? ('0' + minute) : minute;
var seconds = now.getSeconds();
seconds = seconds < 10 ? ('0' + seconds) : seconds;
var resDate = y + '-' + m + '-' + da + ' ' + h + ':' + minute + ":" + seconds;
resDate = resDate.substring(0, 16)
return resDate;
},
formatName(name) {
if (name == undefined) {
return
}
return name.substr(name.length - 2, name.length > 2 ? (name.length - 1) : name.length)
},
divAll() {
if (this.btnspan == '展开') {
this.btnspan = '收起'
this.showAll = true
} else {
this.btnspan = '展开'
this.showAll = false
}
},
toVote() {
var myVote = ''
if (this.data.myVote) {
myVote = this.data.myVote
}
uni.navigateTo({
url: `./vote?id=${this.id}`
})
}
},
};
</script>
<style lang="scss" scope>
@import "../../../common/common.css";
.page {
width: 100%;
overflow-x: hidden;
background-color: #F4F6F8;
.mask {
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, .8);
position: fixed;
top: 0;
left: 0;
z-index: 999;
.cancel-img {
width: 219px;
height: 94px;
margin: 580px 0 166px 266px;
}
.text-img {
position: absolute;
top: 0;
right: 0;
width: 90%;
}
.btn {
width: 50%;
line-height: 112px;
background: #D7261E;
color: #fff;
font-size: 32px;
text-align: center;
position: absolute;
bottom: 0;
right: 0;
}
}
.right-icon {
width: 32px;
height: 32px;
float: right;
vertical-align: middle;
transform: rotate(270deg);
padding: 0 72px 0 0;
}
.vote-img {
width: 140px;
height: 140px;
position: fixed;
bottom: 344px;
right: 48px;
}
.sign-end {
padding-left: 150px;
}
.btn-bottom {
position: fixed;
bottom: 0;
left: 0;
z-index: 9;
width: 100%;
display: flex;
.btn {
flex: 1;
line-height: 112px;
background: #D7261E;
color: #fff;
font-size: 32px;
text-align: center;
}
.sign {
background-color: #fff;
color: #666;
}
}
.detail-info {
padding: 16px 0 8px 32px;
border-bottom: 2px solid #D8DDE6;
background-color: #D7261E;
padding-bottom: 80px;
position: relative;
.info-title {
line-height: 64px;
font-size: 40px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #fff;
word-break: break-all;
margin-bottom: 16px;
}
.item-info {
display: flex;
line-height: 48px;
font-size: 28px;
margin-bottom: 8px;
.info-label {
color: #fff;
}
div {
display: flex;
align-items: center;
}
.info-value {
flex: 1;
color: #FFE8E8;
}
.item-status0 {
color: #FF9B2B;
}
.item-status1 {
color: #2EA222;
}
.item-status2 {
color: #343D65;
}
.item-status3 {
color: #5A98F2;
}
.item-status4 {
color: #f46;
}
}
.retract-btn {
line-height: 80px;
text-align: center;
font-size: 28px;
color: #fff;
position: absolute;
bottom: 0;
width: 690px;
.down-icon {
width: 32px;
height: 32px;
margin-left: 4px;
vertical-align: middle;
transition: all .3s ease-in-out;
}
.icon-active {
transform: rotate(180deg);
}
}
}
.page-title {
line-height: 96px;
color: #333;
font-size: 32px;
padding-left: 32px;
background-color: #fff;
span {
font-size: 28px;
}
}
.info-content {
padding: 16px 32px;
background-color: #fff;
line-height: 48px;
color: #333;
font-size: 32px;
box-sizing: border-box;
}
.user-list {
padding-bottom: 140px;
.user-item {
background-color: #fff;
height: 112px;
padding-top: 16px;
box-sizing: border-box;
.user-bg {
display: inline-block;
width: 80px;
height: 80px;
background-color: #4E8EEE;
color: #fff;
text-align: center;
line-height: 80px;
margin: 0 16px 0 32px;
font-size: 28px;
border-radius: 50%;
vertical-align: top;
}
.user-info {
display: inline-block;
width: 622px;
height: 96px;
border-bottom: 2px solid #D8DDE6;
box-sizing: border-box;
.user-name {
line-height: 44px;
color: #333;
font-size: 32px;
margin-top: 16px;
}
}
}
.user-item:nth-last-of-type(1) {
.user-info {
border-bottom: 0;
}
}
}
.mar-b8 {
margin-bottom: 16px;
}
.color-1365DD {
color: #1365DD;
}
.color-999999 {
color: #999999;
}
.pad-l7 {
padding-left: 14px;
}
}
</style>

View File

@@ -0,0 +1,201 @@
<template>
<div class="page">
<div class="tab-list">
<div
class="tab-item"
v-for="(item, index) in tabList"
:key="index"
:class="tabIndex == index ? 'tab-active' : ''"
@click="tabClick(index)"
>
{{ item.label }}({{ item.value }})
<span class="line"></span>
</div>
</div>
<div
class="user-list"
v-for="(item, index) in list"
:key="index"
v-if="tabIndex != 0"
>
<div class="user-item">
<div class="user-bg">{{ formatName(item.meetingUserName) }}</div>
<div class="user-info">
<div class="user-name">{{ item.meetingUserName }}</div>
</div>
</div>
</div>
<div
class="user-list"
v-for="(item, index) in list"
:key="index"
v-if="tabIndex == 0"
>
<div
class="user-item"
v-if="item.meetingUserRole == 0 || item.meetingUserRole == 3"
>
<div class="user-bg">{{ formatName(item.meetingUserName) }}</div>
<div class="user-info">
<div class="user-name">{{ item.meetingUserName }}</div>
</div>
</div>
</div>
<AiEmpty v-if="list.length == 0 || list == null"/>
</div>
</template>
<script>
export default {
data() {
return {
tabList: [
{label: "参与", value: "0"},
{label: "已到", value: "0"},
{label: "未到", value: "0"},
// { label: "请假", value: "0" },
],
tabIndex: 0,
id: "",
data: {},
list: [],
};
},
onLoad(options) {
this.id = options.id;
this.getDetailInfo();
},
methods: {
tabClick(index) {
this.tabIndex = index;
if (index == 0) {
this.list = this.data.appThreeMeetingUserList;
}
if (index == 1) {
this.list = this.data.isArriveLIst;
}
if (index == 2) {
this.list = this.data.notArriveLIst;
}
if (index == 3) {
this.list = this.data.leaveLIst;
}
},
getDetailInfo() {
this.$instance
.post(
`/app/appthreemeetinginfo/queryDetailById?id=${this.id}`,
null,
{}
)
.then((res) => {
if (res.data) {
var data = res.data;
if (data.appThreeMeetingUserList) {
this.tabList[0].value = data.participantList.length;
}
if (data.isArriveLIst) {
this.tabList[1].value = data.isArriveLIst.length;
}
if (data.isArriveLIst) {
this.tabList[2].value = data.notArriveLIst.length;
}
// if (data.isArriveLIst) {
// this.tabList[3].value = data.leaveLIst.length;
// }
this.data = data;
this.list = this.data.appThreeMeetingUserList;
}
});
},
formatName(name) {
if (name == undefined) {
return;
}
return name.substr(
name.length - 2,
name.length > 2 ? name.length - 1 : name.length
);
},
},
};
</script>
<style lang="scss" scope>
@import "../../../common/common.css";
.page {
background-color: #f4f6f8;
.tab-list {
display: flex;
background-color: #D7261E;
line-height: 96px;
.tab-item {
flex: 1;
text-align: center;
color: #fff;
font-size: 28px;
position: relative;
}
.tab-active {
.line {
position: absolute;
bottom: 14px;
left: 50%;
margin-left: -20px;
display: inline-block;
width: 40px;
height: 4px;
border-radius: 4px;
background: #fff;
}
}
}
.user-list {
background-color: #fff;
.user-item {
height: 112px;
padding-top: 16px;
box-sizing: border-box;
.user-bg {
display: inline-block;
width: 80px;
height: 80px;
background-color: #4e8eee;
color: #fff;
text-align: center;
line-height: 80px;
margin: 0 16px 032px;
font-size: 28px;
border-radius: 50%;
vertical-align: top;
}
.user-info {
display: inline-block;
width: 622px;
height: 96px;
border-bottom: 2px solid #d8dde6;
box-sizing: border-box;
.user-name {
line-height: 44px;
color: #333;
font-size: 32px;
margin-top: 16px;
}
}
}
.user-item:nth-last-of-type(1) {
.user-info {
border-bottom: 0;
}
}
}
}
</style>

View File

@@ -0,0 +1,155 @@
<template>
<div class="page">
<img src="https://cdn.cunwuyun.cn/guangdong/h5/bg@2x.png" alt="" class="bg-img">
<div class="title">会议投票</div>
<div class="content">
<img src="https://cdn.cunwuyun.cn/guangdong/h5/dh@2x.png" alt="">
<div>投票主题</div>
<p v-html="info.voteTopic"></p>
</div>
<div class="footer">
<div class="bg-gray" v-if="info.myVote">已投票</div>
<div class="bg-pink" @click="voteSubmit(0)" v-if="!info.myVote">不同意</div>
<div class="bg-red" @click="voteSubmit(1)" v-if="!info.myVote">同意观点</div>
</div>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
computed: {
...mapState(['user']),
},
data() {
return {
id: '',
info: {},
};
},
onLoad(options) {
this.id = options.id
this.getDetailInfo()
},
methods: {
voteSubmit(myVote) {
this.$instance.post(`/app/appthreemeetinguser/voteMeetting?meetingId=${this.id}&myVote=${myVote}&userId=${this.user.partyId}`).then((res) => {
if (res.code == 0) {
this.$toast('投票成功')
this.getDetailInfo()
}
}).catch((err) => {
this.$toast(err)
})
},
getDetailInfo() {
this.$instance.post(`/app/appthreemeetinginfo/queryDetailById?id=${this.id}&partyId=${this.user.partyId}`, null, {}).then(res => {
if (res.data) {
this.info = res.data
}
})
},
},
};
</script>
<style lang="scss" scope>
@import "../../../common/common.css";
.page {
background-color: #F3F6F9;
position: relative;
width: 100%;
overflow-x: hidden;
.bg-img {
width: 100%;
height: 340px;
}
.title {
width: 100%;
height: 60px;
font-size: 44px;
font-family: PingFangSC-Semibold, PingFang SC;
font-weight: 600;
color: #FFF;
line-height: 60px;
position: absolute;
top: 50px;
left: 290px;
}
.content {
position: absolute;
top: 210px;
left: 20px;
width: 710px;
background: #FFF;
border-radius: 24px;
padding: 100px 32px 172px;
box-sizing: border-box;
img {
position: absolute;
top: -60px;
left: 310px;
width: 120px;
height: 120px;
}
div {
font-size: 32px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333;
line-height: 44px;
margin-bottom: 36px;
}
p {
font-size: 28px;
color: #333;
line-height: 40px;
}
}
.footer {
display: flex;
width: 100%;
position: fixed;
bottom: 0;
left: 0;
div {
flex: 1;
text-align: center;
height: 112px;
line-height: 112px;
}
.bg-gray {
font-size: 36px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #999;
background: #EAE9E9;
}
.bg-pink {
font-size: 32px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #D73D3D;
background: #FFE4DD;
}
.bg-red {
font-size: 32px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #fff;
background: #FE5A49;
}
}
}
</style>