Files
jjx-wap/components/user/notice.vue
T
2026-10-08 18:34:09 +08:00

526 lines
20 KiB
Vue

<template> <!-- 消息 -->
<view>
<view class="layout-notice">
<template v-if="!isNotice">
<view class="notice-head flex justify-between align-center">
<view class="text">
有
<text class="red">{{ unreadNum }}</text>
条系统通知消息未读
</view>
<view class="read flex justify-center align-center" @click="allRead">
<u-icon name="eye" color="#666666" size="20"></u-icon>
<text>全部标为已读</text>
</view>
<view class="push flex justify-center align-center" @click="isNotice = true">
<u-icon name="setting" color="#666666" size="20"></u-icon>
<text>消息推送设置</text>
</view>
</view>
<view class="notice-body">
<!-- 未读消息使用unread -->
<view class="item" :class="{'unread': !item.hasRead}" v-for="(item, index) in noticeList"
:key="index">
<view class="info flex justify-between align-center">
<view class="title text-single" @click="toDetail(item, index)">{{ item.title }}</view>
<view class="date flex-1 m-left-20" @click="toDetail(item, index)">{{
item._add_time_str
}}
</view>
<view class="flex justify-center align-center" v-if="!item.hasRead" @click="setRead(index)">
<u-icon name="eye" color="#A92924" size="18"></u-icon>
<text class="read">标为已读</text>
</view>
<view class="flex justify-center align-center" @click="del(index)">
<u-icon name="trash" color="#A92924" size="18"></u-icon>
<text class="delete">删除</text>
</view>
</view>
<view class="detail m-top-10" @click="toDetail(item, index)">
{{ item.content }}
</view>
</view>
</view>
</template>
<template v-else>
<view class="account-title m-top-20">消息推送设置</view>
<u--text color="#626262" margin="20rpx 0 40rpx"
text="注!我们将针对您的选择,为您精准推送询价信息"></u--text>
<u-line color="#bbb"></u-line>
<!-- 开关遍历容器 -->
<view class="switch-list m-top-20">
<view class="switch-box flex justify-between align-center" v-for="(item,index) in settingList"
:key="index">
<view class="text">
<text class="red">*</text>
{{ item.title }}
</view>
<u-switch v-model="item.status" activeColor="#be2a28" size="20"
@change="handSwitchChange($event,index)"></u-switch>
</view>
</view>
<view class="m-top-30">
<u-line color="#bbb"></u-line>
</view>
<view class="account-title m-top-20">选择产品</view>
<!-- 产品遍历容器 -->
<view class="goods-list">
<view class="goods-box flex" v-for="(item, index) in productList" :key="index">
<view class="lb">{{ item.name }}</view>
<view class="flex-1">
<view class="flex justify-start flex-wrap">
<view class="m-right-20 m-top-20" v-for="(productItem, productIndex) in item.children"
:key="productIndex">
<u-tag size="mini"
:text="productItem.name"
:plain="!productList[index].idList.includes(productItem.name)"
type="error"
:name="productItem.name"
@click="handCheckboxClick"
></u-tag>
</view>
</view>
</view>
</view>
</view>
<!-- 已选 -->
<div class="form">
<view class="account-title m-top-20">请选择服务地区</view>
<view class="flex flex-col justify-start items-start">
<view class="w-100p">
<el-select size="small" v-model="addressIndex[0]" placeholder="请选择省" class="w-100p">
<el-option v-for="(item, index) in provinceData" :key="index"
:label="item.name"
:value="index">
</el-option>
</el-select>
</view>
<view class="my-10 w-100p">
<el-select size="small" v-model="addressIndex[1]" placeholder="请选择市" class="w-100p"
:disabled="!addressIndex[0]">
<template v-if="addressIndex[0] !== null">
<el-option v-for="(item, index) in cityData[addressIndex[0]]"
:key="index"
:label="item.name"
:value="index">
</el-option>
</template>
</el-select>
</view>
<view class="my-10 w-100p">
<el-select size="small" v-model="addressIndex[2]" placeholder="请选择区" class="w-100p"
:disabled="!addressIndex[1]">
<template v-if="addressIndex[0] !== null && addressIndex[1] !== null">
<el-option
v-for="(item, index) in areaData[addressIndex[0]][addressIndex[1]]"
:key="index"
:label="item.name"
:value="index">
</el-option>
</template>
</el-select>
</view>
</view>
<u-button type="primary" size="mini" @click="addAddress">添加</u-button>
</div>
<div class="flex justify-start items-start flex-wrap mt-20 text-25">
<div class="flex justify-start items-center pointer" @click="deleteAddress(item)"
v-for="(item, index) in addressList"
:key="index" style="margin: 10px 10px 0 0">
<image src="/static/img/check.png" style="width: 12px; height: 12px; margin-right: 5px"/>
<span style="line-height: 18px">{{ item.province.name }}-{{
item.city ? item.city.name : '不限'
}}-{{ item.area ? item.area.name : '不限' }}</span>
</div>
</div>
<el-divider></el-divider>
<div class="form">
<view class="account-title m-top-20">请选择单笔交易额</view>
<div class="flex justify-start items-center">
<el-input size="small" v-model="tradeAmount[0]" placeholder="请输入金额" style="width: 200px">
<template #suffix>元</template>
</el-input>
<span class="mx-20">~</span>
<el-input size="small" v-model="tradeAmount[1]" placeholder="请输入金额" style="width: 200px">
<template #suffix>元</template>
</el-input>
</div>
</div>
<el-divider></el-divider>
<div class="form text-25">
<view class="account-title m-top-20">请选择交易方式</view>
<div class="flex justify-start items-center pointer" @click="changeItemCheck('tradeSelf')"
style="margin: 10px 10px 0 0">
<image :src="tradeSelf ? '/static/img/check.png' : '/static/img/uncheck.png'"
style="width: 12px; height: 12px; margin-right: 5px"/>
<span style="line-height: 18px">自主交易</span>
</div>
<div class="flex justify-start items-center pointer"
@click="changeItemCheck('tradePlatform')"
style="margin: 10px 10px 0 0">
<image :src="tradePlatform ? '/static/img/check.png' : '/static/img/uncheck.png'"
style="width: 12px; height: 12px; margin-right: 5px"/>
<span style="line-height: 18px">金久信公证</span>
</div>
</div>
<el-divider></el-divider>
<div class="form">
<view class="account-title m-top-20">请设置免打扰时间段</view>
<div class="flex justify-start items-center">
<el-time-picker v-model="doNotDisturbRange" range-separator="~" is-range style="width: 200px"/>
</div>
</div>
<view class="flex justify-between items-center">
<view class="mx-15 flex-1">
<u-button class="public-btn" text="保存设置" @click="handSubmit"></u-button>
</view>
<view class="mx-15 flex-1">
<u-button class="public-btn-plain" text="取消" @click="isNotice = false"></u-button>
</view>
</view>
</template>
</view>
</view>
</template>
<script>
import provinces from "@/util/address/provinces.json";
import citys from "@/util/address/citys.json";
import areas from "@/util/address/areas.json";
export default {
data() {
return {
provinceData: provinces,
cityData: citys,
areaData: areas,
isNotice: false,
settingList: {
article: {
title: '现货推送服务',
status: false
},
process: {
title: '找加工信息推送服务',
status: false
},
old: {
title: '旧货交易信息推送服务',
status: false
},
enquiry: {
title: '询价单和选项推送服务',
status: false
},
},
value: false,
unreadNum: 0,
noticeList: [],
productList: [],
addressRegion: {},
tradeSelf: false,
tradePlatform: false,
doNotDisturbRange: [new Date(2024, 1, 1, 0, 0), new Date(2024, 1, 1, 0, 0)],
tradeAmount: [],
addressIndex: [null, null, null],
addressList: []
};
},
methods: {
handCheckboxClick(name) {
this.checkboxs[name].checked = !this.checkboxs[name].checked
},
handSwitchChange(val, index) {
this.settingList[index].status = val
},
async getList(pageIndex = 1) {
const {rows, total} = await vk.callFunction({
url: 'client/message/kh/getList',
data: {
pageIndex,
pageSize: 500,
}
})
this.total = total
this.noticeList = rows
},
async getUnreadNum() {
const {data} = await vk.callFunction({
url: 'client/message/kh/getUnreadCount',
});
this.unreadNum = data
},
async setRead(index) {
this.noticeList[index].hasRead = true
await vk.callFunction({
url: 'client/message/kh/setRead',
data: {
id: this.noticeList[index]._id
}
})
},
del(index) {
uni.showModal({
title: '提示',
content: '确定清空内容吗?',
success: async res => {
if (res.confirm) {
await vk.callFunction({
url: 'client/message/kh/delete',
data: {
id: this.noticeList[index]._id
}
})
this.$message.success('删除成功')
await this.getList()
}
}
})
},
toDetail(item, index) {
if (!item.hasRead) this.setRead(index)
let url = null
if (item.type === 'old') url = `/pages/junk/detail?id=${item.pk}`
else if (item.type === 'enquiry') url = `/pages/price/detail?id=${item.pk}`
else if (item.type === 'process') url = `/pages/work/detail?id=${item.pk}`
else if (item.type === 'contract') url = `/pages/public/contract?tab=1`
else if (item.type === 'self-support') url = `/pages/self/makeQuote?id=${item.pk}`
else if (item.type === 'self-product') url = `/pages/user/seller`
else if (item.type === 'spot') url = `/pages/goods/detail?id=${item.pk}`
else if (item.type === 'self-support-quote') {
this.getQuoteDetail(item.pk)
}
if (url) vk.navigateTo({url})
},
async allRead() {
await vk.callFunction({
url: 'client/message/kh/setAllRead'
})
await this.getList(1)
await this.getUnreadNum()
},
async getQuoteDetail(_id) {
await vk.callFunction({
url: 'client/selfSupport/kh/getQuoteDetail',
data: {
_id
},
success: ({rows}) => {
this.sheet = rows
this.dialogVisible = true
}
});
},
toContract() {
this.dialogVisible = false
vk.navigateTo({url: '/pages/public/contract?tab=1'})
},
async getConfig() {
const res = await vk.callFunction({
url: 'client/message/config/kh/getConfig'
})
for (let key in this.settingList) this.settingList[key].status = res[key]
this.productList.forEach((item, index) => {
item.children.forEach(productItem => {
if (res.productList.includes(productItem.name)) {
this.productList[index].idList.push(productItem.name)
}
})
})
this.tradeSelf = res.tradeSelf ?? false
this.tradePlatform = res.tradePlatform ?? false
if (res.addressList) this.addressList = res.addressList
else {
this.addressList = []
}
this.doNotDisturbRange = res.doNotDisturbRange ?? []
this.tradeAmount = res.tradeAmount ?? []
},
async getCate() {
const {rows} = await vk.callFunction({
url: 'client/spot/category/pub/getTree',
title: '请求中...',
});
this.productList = rows.map(item => {
item.idList = []
return item
})
},
async handSubmit() {
let productList = []
this.productList.forEach(item => {
productList = [...productList, ...item.idList]
})
await vk.callFunction({
url: 'client/message/config/kh/update',
data: {
article: this.settingList.article.status,
process: this.settingList.process.status,
old: this.settingList.old.status,
enquiry: this.settingList.enquiry.status,
productList,
addressList: this.addressList,
tradeSelf: this.tradeSelf,
tradePlatform: this.tradePlatform,
doNotDisturbRange: this.doNotDisturbRange,
tradeAmount: this.tradeAmount,
}
})
this.$message.success('保存成功')
this.isNotice = false
},
addAddress() {
if (!this.addressIndex[0]) return
this.addressList.push({
province: this.provinceData[this.addressIndex[0]],
city: this.addressIndex[1] ? this.cityData[this.addressIndex[0]][this.addressIndex[1]] : null,
area: this.addressIndex[2] ? this.areaData[this.addressIndex[0]][this.addressIndex[1]][this.addressIndex[2]] : null
})
this.addressIndex = [null, null, null]
},
deleteAddress(index) {
this.addressList.splice(index, 1)
},
changeItemCheck(field) {
this[field] = !this[field]
}
},
async mounted() {
await this.getList()
await this.getUnreadNum()
await this.getCate()
await this.getConfig()
}
}
</script>
<style lang="scss">
.layout-notice {
padding: 10rpx 30rpx;
}
.notice-head {
height: 80rpx;
font-size: 24rpx;
line-height: 32rpx;
color: #333333;
border-bottom: 1px solid #f2f2f2;
}
.notice-body {
.item {
position: relative;
padding: 20rpx 0 40rpx 20rpx;
border-bottom: 1px solid #f2f2f2;
.detail {
font-size: 24rpx;
line-height: 32rpx;
color: #999999;
}
}
.unread::before {
position: absolute;
left: 0;
top: 30rpx;
z-index: 9;
content: '';
width: 12rpx;
height: 12rpx;
border-radius: 50%;
background: #A92924;
}
.title {
max-width: 280rpx;
font-size: 26rpx;
line-height: 32rpx;
color: #333333;
}
.date {
font-size: 22rpx;
line-height: 32rpx;
color: #999999;
}
.read, .delete {
font-size: 24rpx;
line-height: 32rpx;
color: #A92924;
}
}
.account-title {
position: relative;
padding-left: 20rpx;
font-size: 28rpx;
font-weight: 600;
line-height: 48rpx;
color: #A92924;
&:before {
position: absolute;
left: 0;
top: 50%;
z-index: 9;
margin-top: -14rpx;
content: '';
width: 6rpx;
height: 28rpx;
background: #A92924;
}
}
.public-btn {
width: 100%;
margin-top: 60rpx;
color: #ffffff;
background: #A92924;
}
.public-btn-plain {
width: 100%;
margin-top: 60rpx;
color: #A92924;
border: 1px solid #A92924;
}
.lb {
width: 160rpx;
height: auto;
padding-top: 20rpx;
font-size: 24rpx;
line-height: 48rpx;
color: #333333;
}
.goods-box {
padding-bottom: 20rpx;
border-bottom: 1px dashed #f2f2f2;
}
.switch-box {
padding: 16rpx 0;
font-size: 26rpx;
color: #333333;
}
/deep/ .i-icon {
display: flex;
align-items: center;
justify-content: center;
}
/deep/ .el-input__suffix {
display: flex;
align-items: center;
justify-content: center;
}
</style>