This commit is contained in:
liuye
2022-07-27 10:54:10 +08:00
15 changed files with 182 additions and 359 deletions

View File

@@ -1,8 +1,8 @@
<template>
<div class="AppAnnounce">
<keep-alive :include="['List']">
<!-- <keep-alive :include="['List']"> -->
<component ref="component" :is="component" @change="onChange" :params="params" :instance="instance" :dict="dict"></component>
</keep-alive>
<!-- </keep-alive> -->
</div>
</template>
@@ -35,7 +35,13 @@
},
mounted () {
console.log(this.$route)
if (this.$route.params.id) {
this.component = 'Detail'
this.params = {
id: this.$route.params.id
}
}
},
methods: {

View File

@@ -23,24 +23,26 @@
<el-form-item label="选择群主" v-if="form.sendScope !== '0'" prop="wxGroupsName" style="width: 100%;" :rules="[{ required: true, message: '请选择选择群主', trigger: 'change' }]">
<div class="AppAnnounceDetail-select">
<el-input size="small" class="AppAnnounceDetail-select__input" placeholder="请选择..." disabled v-model="form.wxGroupsName"></el-input>
<div class="select-left" v-if="form.filterCriteria.length">
<span v-for="(item, index) in form.filterCriteria" :key="index">
<ai-open-data type="departmentName" :openid="item"></ai-open-data>
<div class="select-left" v-if="form.wxGroups.length">
<span v-for="(item, index) in form.wxGroups" :key="index">
<ai-open-data type="userName" :openid="item.groupOwnerId"></ai-open-data>
</span>
</div>
<i v-if="!form.filterCriteria.length">请选择</i>
<i v-if="!form.wxGroups.length">请选择</i>
<ai-picker
:instance="instance"
multiple
:ops="{label: form.sendScope === '2' ? 'girdName' : 'name'}"
:action="form.sendScope === '1' ? '/app/wxcp/wxdepartment/departList' : '/app/appgirdinfo/girdList'"
v-model="form.filterCriteria"
@pick="onPick"
@change="onSelcetChange">
<div class="select-right">选择</div>
</ai-picker>
</div>
<div class="tips">
<p>消息预计送达居民群数</p>
<span>{{ form.filterCriteria.length }}</span>
<span>{{ groupLen }}</span>
<el-tooltip
placement="top"
content="任务开始后3天内15分钟更新1次3天后访问页面时触发更新1时间最多刷新1次">
@@ -157,57 +159,7 @@
</ai-card>
</el-form>
<div class="right">
<img class="phone" src="https://cdn.cunwuyun.cn/dvcp/announce/phone.png" />
<img class="phone-wrapper" src="https://cdn.cunwuyun.cn/dvcp/announce/phone-wrapper.png" />
<div class="right-content">
<div class="msg-list">
<div class="msg-item" v-if="form.content">
<div class="msg-item__left">
<img v-if="user.info.avatar" :src="user.info.avatar" />
</div>
<div class="msg-item__right">
<div class="msg-wrapper msg-text">
<p>{{ form.content }}</p>
</div>
</div>
</div>
<div class="msg-item" v-for="item in fileList" :key="item.id">
<div class="msg-item__left">
<img v-if="user.info.avatar" :src="user.info.avatar" />
</div>
<div class="msg-item__right" :class="[['1', '2'].indexOf(item.msgType) !== -1 ? 'left-border' : '']">
<div class="msg-wrapper msg-img" v-if="item.msgType === '1'">
<img :src="item.imgPicUrl" />
</div>
<div class="msg-wrapper msg-video" v-if="item.msgType === '2'">
<video controls :src="item.url"></video>
</div>
<div class="msg-wrapper msg-file" v-if="item.msgType === '3'">
<div class="msg-left">
<h2>{{ item.name }}</h2>
<p>{{ item.fileSizeStr }}</p>
</div>
<img src="https://cdn.cunwuyun.cn/dvcp/announce/folder.png" />
</div>
<div class="msg-wrapper msg-link" v-if="item.msgType === '4'">
<h2>{{ item.linkTitle }}</h2>
<div class="msg-right">
<p>{{ item.linkDesc }}</p>
<img :src="item.linkPicUrl" />
</div>
</div>
<div class="msg-wrapper msg-miniapp" v-if="item.msgType === '5'">
<h2>{{ item.mpTitle }}</h2>
<img :src="item.url" />
<div class="msg-bottom">
<i>小程序</i>
<img src="https://cdn.cunwuyun.cn/dvcp/announce/miniapp.png">
</div>
</div>
</div>
</div>
</div>
</div>
<Phone :avatar="user.info.avatar" @close="isShowPhone = false" :isShowClose="false" :content="form.content" :fileList="fileList"></Phone>
</div>
<ai-dialog
:visible.sync="isShowAddLink"
@@ -311,6 +263,7 @@
</template>
<script>
import Phone from './Phone'
import { mapActions, mapState } from 'vuex'
export default {
name: 'Add',
@@ -321,6 +274,10 @@
params: Object
},
components: {
Phone
},
data () {
return {
info: {},
@@ -360,23 +317,23 @@
taskTitle: '',
examinesName: ''
},
girdNames: '',
id: '',
tagsList: []
}
},
watch: {
fileList (v) {
if (v.length) {
setTimeout(() => {
document.querySelector('.right-content').scrollTo(0, 999999)
}, 800)
}
}
},
computed: {
...mapState(['user'])
...mapState(['user']),
groupLen () {
let i = 0
this.form.wxGroups.forEach(v => {
i = i + v.groupIds.split(',').length
})
return i
}
},
created () {
@@ -401,6 +358,10 @@
filterCriteria: res.data.filterCriteria.split(',')
}
if (res.data.girdNames) {
this.girdNames = res.data.girdNames.split(',')
}
this.dateForm.choiceTime = res.data.choiceTime
if (res.data.examines && res.data.examines.length) {
@@ -439,6 +400,10 @@
},
onScopeChange (e) {
this.form.filterCriteria = []
this.form.wxGroups = []
this.girdNames = ''
if (e === '0') {
this.getWxGroups()
} else {
@@ -446,6 +411,12 @@
}
},
onPick (e) {
if (this.form.sendScope === '2' && e.length) {
this.girdNames = e.map(v => v.girdName)
}
},
onSelcetChange (e) {
if (e.length) {
this.form.wxGroupsName = '1'
@@ -590,6 +561,10 @@
confirm (sendType) {
this.$refs.form.validate((valid) => {
if (valid) {
if (!this.form.wxGroups.length) {
return this.$message.error('居民群数量不能为0')
}
if (sendType === 1 && !this.dateForm.choiceTime) {
this.isShowDate = true
return false
@@ -777,223 +752,6 @@
.right {
position: sticky;
top: 0;
width: 338px;
height: 675px;
padding: 80px 15px 100px 32px;
.phone {
position: absolute;
left: 13px;
top: 4px;
z-index: 1;
width: 314px;
height: 647px;
}
.phone-wrapper {
position: absolute;
left: 0;
top: 0;
z-index: 2;
width: 338px;
height: 675px;
}
.right-content {
position: relative;
z-index: 11;
height: 100%;
overflow-y: auto;
.msg-item {
display: flex;
margin-bottom: 20px;
.msg-item__left {
width: 42px;
height: 42px;
margin-right: 16px;
background: #2891FF;
border-radius: 4px;
flex-shrink: 1;
overflow: hidden;
img {
width: 100%;
height: 100%;
}
}
.msg-item__right {
position: relative;
flex: 1;
&::after {
position: absolute;
top: 16px;
left: 0;
z-index: 1;
width: 0;
height: 0;
border-right: 6px solid #fff;
border-left: 6px solid transparent;
border-bottom: 6px solid transparent;
border-top: 6px solid transparent;
content: " ";
transform: translate(-100%, 0%);
}
&.left-border::after {
display: none;
}
.msg-img img {
max-width: 206px;
max-height: 200px;
}
.msg-video video {
max-width: 206px;
max-height: 200px;
}
.msg-text {
max-width: 206px;
width: max-content;
line-height: 1.3;
padding: 12px;
background: #FFFFFF;
border-radius: 5px;
word-break: break-all;
font-size: 14px;
color: #222222;
}
.msg-miniapp {
width: 206px;
padding: 0 12px;
text-align: justify;
font-size: 0;
background: #FFFFFF;
border-radius: 5px;
font-size: 14px;
color: #222222;
h2 {
line-height: 1.2;
padding: 8px 0;
border-bottom: 1px solid #eee;
color: #222222;
font-size: 14px;
}
img {
width: 100%;
height: 120px;
margin-bottom: 8px;
}
.msg-bottom {
display: flex;
align-items: center;
line-height: 1;
padding: 4px 0;
border-top: 1px solid #eee;
i {
margin-right: 4px;
font-size: 12px;
font-style: normal;
color: #999;
}
img {
width: 16px;
height: 16px;
border-radius: 50%;
}
}
}
.msg-file {
display: flex;
align-items: center;
width: 206px;
padding: 12px;
background: #FFFFFF;
border-radius: 5px;
.msg-left {
flex: 1;
margin-right: 18px;
h2 {
display: -webkit-box;
flex: 1;
line-height: 16px;
margin-bottom: 4px;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
text-overflow: ellipsis;
overflow: hidden;
color: #222222;
font-size: 14px;
}
p {
color: #888888;
font-size: 12px;
}
}
img {
width: 44px;
height: 44px;
border-radius: 2px;
}
}
.msg-link {
width: 206px;
height: 102px;
padding: 12px;
background: #FFFFFF;
border-radius: 5px;
h2 {
margin-bottom: 4px;
color: #222222;
font-size: 14px;
font-weight: normal;
}
.msg-right {
display: flex;
align-items: center;
p {
display: -webkit-box;
flex: 1;
line-height: 16px;
margin-right: 10px;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
text-overflow: ellipsis;
overflow: hidden;
color: #888;
font-size: 12px;
}
img {
width: 50px;
height: 50px;
border-radius: 4px;
}
}
}
}
}
}
}
.AppAnnounceDetail-select {

View File

@@ -7,7 +7,7 @@
<template slot="content">
<ai-card title="基础信息">
<template #right>
<div class="right-tips">
<div class="right-tips" v-if="info.status === '4'">
<el-tooltip
placement="top"
content="任务开始后3天内15分钟更新1次3天后访问页面时触发更新1时间最多刷新1次">
@@ -26,15 +26,15 @@
<div class="user">
<img src="https://cdn.cunwuyun.cn/dvcp/announce/user.png" />
<span><ai-open-data type="userName" :openid="info.createUserId"></ai-open-data></span>
<span v-if="info.createUserSecondDept"><ai-open-data type="departmentName" :openid="info.createUserSecondDept"></ai-open-data>,</span>
<span><ai-open-data type="departmentName" :openid="info.createUserDept"></ai-open-data></span>
</div>
</ai-info-item>
<ai-info-item label="审批人">
<div class="user-wrapper">
<div class="user" v-for="(item, index) in info.examines" :key="index">
<img src="https://cdn.cunwuyun.cn/dvcp/announce/user.png" />
<span>
<ai-open-data type="userName" :openid="item.examineUserId"></ai-open-data>
</span>
<span><ai-open-data type="userName" :openid="item.examineUserId"></ai-open-data></span>
</div>
</div>
</ai-info-item>
@@ -51,14 +51,17 @@
<ai-info-item label="消息内容" isLine>
<div class="msg">
<p>{{ content }}</p>
<div class="msg-bottom" v-if="fileList.length">
<div class="left">
<div class="msg-bottom">
<div class="left" v-if="fileList.length">
<img :src="mapIcon(fileList[0].msgType)" />
<span>{{ mapType(fileList[0].msgType) }}{{ fileList[0].mpTitle || fileList[0].name || fileList[0].linkTitle }} </span>
<i>{{ fileList.length }}</i>
<span>个附件</span>
</div>
<div class="right">预览消息</div>
<div class="left" v-else>
<span>暂无附件</span>
</div>
<div class="right" @click="isShowPhone = true">预览消息</div>
</div>
</div>
</ai-info-item>
@@ -201,7 +204,7 @@
:current.sync="search2.current"
:size.sync="search2.size"
@getList="getGroupInfo">
<el-table-column slot="user" label="群" align="center">
<el-table-column slot="user" label="群" align="center">
<template slot-scope="{ row }">
<div class="userinfo">
<span>
@@ -230,20 +233,11 @@
tableSize="small"
:isShowPagination="false"
@getList="() => {}">
<el-table-column slot="user" label="群名称" align="center">
<template slot-scope="{ row }">
<div class="userinfo">
<span v-for="(item, index) in row.groupIds" :key="index">
<ai-open-data type="departmentName" :openid="item"></ai-open-data>
</span>
</div>
</template>
</el-table-column>
</ai-table>
</ai-dialog>
<div class="detail-phone">
<div class="detail-phone" v-if="isShowPhone">
<div class="mask"></div>
<Phone :avatar="user.info.avatar" :content="content" :fileList="fileList"></Phone>
<Phone :avatar="user.info.avatar" @close="isShowPhone = false" :isShowClose="true" :content="content" :fileList="fileList"></Phone>
</div>
</template>
</ai-detail>
@@ -269,6 +263,7 @@
return {
total1: 0,
isShowGroups: false,
isShowPhone: false,
total2: 0,
user1: [],
user2: [],
@@ -297,7 +292,7 @@
currIndex: 0,
colConfigs3: [
{ prop: 'groupOwnerId', label: '群主', openType: 'userName' },
{ slot: 'user' }
{ prop: 'groupNames', label: '群名称' }
],
colConfigs1: [
{ slot: 'user', label: '成员', openType: 'userName' },
@@ -369,7 +364,12 @@
}
}).then(res => {
if (res.code === 0) {
this.tableData2 = res.data.executedList.records
this.tableData2 = res.data.executedList.records.map(v => {
return {
...v,
groupName: v.groupName || '未命名群聊'
}
})
this.total2 = res.data.executedList.total
this.groupInfo = res.data
}

View File

@@ -35,7 +35,7 @@
</el-date-picker>
<div class="userSelcet" placeholder="请选择创建人">
<span v-if="search.createUserId"><ai-open-data type="userName" :openid="search.createUserId"></ai-open-data></span>
<span v-else>请选择</span>
<span v-else>创建人</span>
<ai-user-get isStrictly :instance="instance" @change="onUserChange" :isMultiple="false" v-model="user">
<div class="select-btn">选择</div>
</ai-user-get>
@@ -77,9 +77,11 @@
<el-table-column slot="options" width="140px" fixed="right" label="操作" align="center">
<template slot-scope="{ row }">
<div class="table-options">
<el-button type="text" @click="toAdd(row.id)">编辑</el-button>
<el-button type="text" @click="remindExamine(row.id)" v-if="['0'].includes(row.status)">催办</el-button>
<el-button type="text" @click="cancel(row.id)" v-if="['0'].includes(row.status)">撤回</el-button>
<el-button type="text" @click="toDetail(row.id)">详情</el-button>
<el-button type="text" @click="remove(row.id)">删除</el-button>
<el-button type="text" @click="toAdd(row.id)" v-if="['1', '3'].includes(row.status)">编辑</el-button>
<!-- <el-button type="text" @click="remove(row.id)">删除</el-button> -->
</div>
</template>
</el-table-column>
@@ -116,8 +118,19 @@
{ prop: 'taskTitle', label: '任务名称' },
{ prop: 'sendType', label: '群发类型', formart: v => v === '0' ? '立即发送' : '定时发送', align: 'center' },
{ slot: 'user', label: '创建人', openType: 'userName', align: 'center' },
{ prop: 'createTime', label: '群发时间', align: 'center' },
{ prop: 'status', label: '状态', formart: v => this.dict.getLabel('mstStatus', v), align: 'center' },
{ prop: 'choiceTime', label: '群发时间', align: 'center' },
{
prop: 'status',
align: 'center',
label: '状态',
render: (h, {row}) => {
return h('span', {
style: {
color: this.dict.getColor('mstStatus', row.status)
}
}, this.dict.getLabel('mstStatus', row.status))
}
},
{ prop: 'completionRate', label: '任务完成率', align: 'center' }
]
}
@@ -164,6 +177,28 @@
})
},
remindExamine (id) {
this.$confirm('确定催办该数据?').then(() => {
this.instance.post(`/app/appmasssendingtask/remindExamine?id=${id}`).then(res => {
if (res.code == 0) {
this.$message.success('催办成功!')
this.getList()
}
})
})
},
cancel (id) {
this.$confirm('确定撤回该数据?').then(() => {
this.instance.post(`/app/appmasssendingtask/cancel?id=${id}`).then(res => {
if (res.code == 0) {
this.$message.success('撤回成功!')
this.getList()
}
})
})
},
remove(id) {
this.$confirm('确定删除该数据?').then(() => {
this.instance.post(`/app/appmasssendingtask/delete?ids=${id}`).then(res => {

View File

@@ -1,12 +1,13 @@
<template>
<div class="phone-container">
<img class="close" @click="$emit('close')" v-if="isShowClose" src="https://cdn.cunwuyun.cn/dvcp/announce/close.png" />
<img class="phone" src="https://cdn.cunwuyun.cn/dvcp/announce/phone.png" />
<img class="phone-wrapper" src="https://cdn.cunwuyun.cn/dvcp/announce/phone-wrapper.png" />
<div class="right-content">
<div class="msg-list">
<div class="msg-item" v-if="content">
<div class="msg-item__left">
<img v-if="avatar" :src="avatar" />
<img src="https://cdn.cunwuyun.cn/dvcp/announce/avatar.png" />
</div>
<div class="msg-item__right">
<div class="msg-wrapper msg-text">
@@ -16,7 +17,7 @@
</div>
<div class="msg-item" v-for="item in fileList" :key="item.id">
<div class="msg-item__left">
<img v-if="avatar" :src="avatar" />
<img src="https://cdn.cunwuyun.cn/dvcp/announce/avatar.png" />
</div>
<div class="msg-item__right" :class="[['1', '2'].indexOf(item.msgType) !== -1 ? 'left-border' : '']">
<div class="msg-wrapper msg-img" v-if="item.msgType === '1'">
@@ -56,7 +57,17 @@
<script>
export default {
props: ['fileList', 'avatar', 'content']
props: ['fileList', 'avatar', 'content', 'isShowClose'],
watch: {
fileList (v) {
if (v.length) {
setTimeout(() => {
document.querySelector('.right-content').scrollTo(0, 999999)
}, 800)
}
}
},
}
</script>
@@ -75,6 +86,22 @@
height: 647px;
}
.close {
position: absolute;
top: 0;
right: 0;
z-index: 111;
width: 60px;
height: 60px;
cursor: pointer;
transition: all ease 0.5s;
transform: translate(100%, -50%);
&:hover {
opacity: 0.7;
}
}
.phone-wrapper {
position: absolute;
left: 0;
@@ -98,7 +125,6 @@
width: 42px;
height: 42px;
margin-right: 16px;
background: #2891FF;
border-radius: 4px;
flex-shrink: 1;
overflow: hidden;
@@ -172,7 +198,7 @@
font-size: 14px;
}
img {
& > img {
width: 100%;
height: 120px;
margin-bottom: 8px;

View File

@@ -46,7 +46,7 @@
</div>
<div class="flex-between">
<div class="item-info">群发类型<span>{{$dict.getLabel('mstSendType', item.sendType) || ''}}</span></div>
<span class="item-btn">详情{{item.sendType}}</span>
<span class="item-btn" @click="$router.push({name: '357e228ba8e64008ace90d095a7a0dd7', params: { id: item.id }})">详情{{item.sendType}}</span>
</div>
</el-card>
</el-timeline-item>
@@ -213,7 +213,7 @@
this.getCalendarList(year, month)
this.getEffect()
this.getDepart()
this.dict.load('mstSendType')
this.dict.load('mstSendType')
},
methods: {
...mapActions(['initOpenData', 'transCanvas']),
@@ -561,7 +561,7 @@
width: 70px;
}
.name{
width: calc(100% - 70px);
width: calc(100% - 70px);
}
}
.item-btn{

View File

@@ -255,11 +255,9 @@ export default {
params: {id}
}).then(res => {
if (res?.data) {
this.info = {
...res.data,
content: this.formatContent(res.data.content || ""),
files: res.data.files || []
};
let {files = [], content} = res.data
content = content.replace(/(\r\n)|(\n)/g, "<br>")
this.info = {...res.data, content, files};
this.searchMeetinguser()
}
});