Compare commits

..

No commits in common. "d988e385b701e766ede00fd0c69e619ccf326039" and "0f0c18bd35d07e32b0c57fb0c54887f901e2b246" have entirely different histories.

7 changed files with 175 additions and 141 deletions

1
.gitignore vendored
View File

@ -4,4 +4,3 @@
/package-lock.json /package-lock.json
/src/components/statistics.vue /src/components/statistics.vue
/src/components/SwarmStatus.vue /src/components/SwarmStatus.vue
/src/views/layout/components/main/admin/message.vue

View File

@ -401,6 +401,17 @@ const routes = [
tapName: 'admin', tapName: 'admin',
hidden: true hidden: true
} }
},
{
path: '/admin/message',
component: () => import('@/views/layout/components/main/admin/message'),
meta: {
title: '公告发布',
icon: 'el-icon-microphone',
roles: ['admin', 'editor'],
tapName: 'admin',
hidden: true
}
} }
] ]
}, },
@ -410,7 +421,7 @@ const routes = [
redirect: '/message/index', redirect: '/message/index',
meta: { meta: {
title: '公告管理', title: '公告管理',
icon: 'el-icon-microphone', icon: 'iconfont icon-guanliyuan',
roles: ['admin', 'editor'], roles: ['admin', 'editor'],
tapName: 'admin' tapName: 'admin'
}, },
@ -420,7 +431,7 @@ const routes = [
component: () => import('@/views/layout/components/main/message/index'), component: () => import('@/views/layout/components/main/message/index'),
meta: { meta: {
title: '公告列表', title: '公告列表',
icon: 'el-icon-chat-line-square', icon: 'iconfont icon-yonghuguanli',
roles: ['admin', 'editor'], roles: ['admin', 'editor'],
tapName: 'admin' tapName: 'admin'
} }
@ -430,7 +441,7 @@ const routes = [
component: () => import('@/views/layout/components/main/message/pub'), component: () => import('@/views/layout/components/main/message/pub'),
meta: { meta: {
title: '发布公告', title: '发布公告',
icon: 'el-icon-microphone', icon: 'iconfont icon-yonghuguanli',
roles: ['admin', 'editor'], roles: ['admin', 'editor'],
tapName: 'admin' tapName: 'admin'
} }

View File

@ -146,21 +146,19 @@ export async function addLog (log) {
/** /**
* @description: 向管理员用户发布公告 * @description: 向管理员用户发布公告
* @param {*} shop_id 商铺 ID
* @param {*} tit 公告标题 * @param {*} tit 公告标题
* @param {*} message 公告内容 * @param {*} message 公告内容
* @param {*} idArr 接收公告的管理员ID数组 * @param {*} idArr 接收公告的管理员ID数组
* @param {*} endTime 公告截止时间时间戳秒级 * @param {*} endTime 公告截至时间时间戳
*/ */
export async function pubMessage (shopId, tit, message, idArr, endTime) { export async function pubMessage (tit, message, idArr, endTime) {
const params = new URLSearchParams() const params = new URLSearchParams()
params.append('shop_id', shopId)
params.append('tit', tit) params.append('tit', tit)
params.append('message', message) params.append('message', message)
params.append('idArr', idArr.join(',')) // 后端只收字符串 params.append('idArr', idArr.join(',')) // 后端只收字符串
params.append('endTime', endTime) params.append('endTime', endTime)
const res = await api.post('pubMessage', params, 'Admin') // 第三个参数为模块名 const res = await api.post('pubMessage', params, 'Admin') // 模块名根据你实际配置来
return res return res
} }
@ -173,19 +171,6 @@ export async function getAllMessageList () {
return res return res
} }
/**
* @description 删除指定公告
* @param {Array} delIdArr 要删除的公告 ID 数组
* @returns {Promise}
*/
export async function delMessage (delIdArr) {
const params = new URLSearchParams()
params.append('delIdArr', delIdArr.join(',')) // 后端通过 $_POST['delIdArr'] 接收
const res = await api.post('deleteMessage', params, 'Admin')
return res
}
/** /**
* @abstract 获取指定飞机组的飞行数据按时间范围 * @abstract 获取指定飞机组的飞行数据按时间范围
* @param {Array} idArr 飞机ID数组 * @param {Array} idArr 飞机ID数组

View File

@ -6,6 +6,7 @@
<el-button type="danger" icon="el-icon-delete" @click="deleteAdmin(countSelIdArr($refs.myTable.selection))">删除 <el-button type="danger" icon="el-icon-delete" @click="deleteAdmin(countSelIdArr($refs.myTable.selection))">删除
</el-button> </el-button>
<el-button type="warning" icon="el-icon-edit" @click="toEditPage()">编辑</el-button> <el-button type="warning" icon="el-icon-edit" @click="toEditPage()">编辑</el-button>
<el-button type="success" icon="el-icon-microphone" @click="toMessagePage(countSelIdArr($refs.myTable.selection))">发布公告</el-button>
</el-button-group> </el-button-group>
<!-- 用户select选项 --> <!-- 用户select选项 -->
<el-button-group class="m-b-20"> <el-button-group class="m-b-20">
@ -13,7 +14,7 @@
</el-button-group> </el-button-group>
<!-- 管理员列表 --> <!-- 管理员列表 -->
<el-table class="w-100" ref="myTable" <el-table class="w-100" ref="myTable"
:data="adminListArr.slice((currentPage - 1) * pageSize, currentPage * pageSize)" border tooltip-effect="dark"> :data="adminListArr.slice((currentPage - 1) * pageSize, currentPage * pageSize)" border tooltip-effect="dark" @selection-change="handleSelectionChange">
<el-table-column align="center" type="selection" width="40"> <el-table-column align="center" type="selection" width="40">
</el-table-column> </el-table-column>
<el-table-column align="center" prop="id" label="id" width="50"> <el-table-column align="center" prop="id" label="id" width="50">
@ -38,6 +39,7 @@
<el-button type="warning" icon="el-icon-edit" <el-button type="warning" icon="el-icon-edit"
@click="$router.replace(`/admin/edit/${scope.row.id}`)">编辑</el-button> @click="$router.replace(`/admin/edit/${scope.row.id}`)">编辑</el-button>
<el-button type="danger" icon="el-icon-delete" @click="deleteAdmin([scope.row.id])">删除</el-button> <el-button type="danger" icon="el-icon-delete" @click="deleteAdmin([scope.row.id])">删除</el-button>
<el-button type="success" icon="el-icon-microphone" @click="toMessagePage([scope.row.id])">发布公告</el-button>
</el-button-group> </el-button-group>
</template> </template>
</el-table-column> </el-table-column>
@ -101,6 +103,17 @@ export default {
this.$message.error('只能选择一条记录') this.$message.error('只能选择一条记录')
} }
}, },
/**
* @description: 跳转到发布公告页面
*/
toMessagePage (selIdArr) {
if (selIdArr.length === 0) {
this.$message.error('请选择至少一个用户')
} else {
this.$store.commit('app/setToMessageIdArr', selIdArr)//
this.$router.push('/admin/message/')
}
},
/** /**
* @description: 删除用户 * @description: 删除用户
*/ */

View File

@ -0,0 +1,107 @@
<template>
<div class="app-container">
<el-row class="m-t-0">
<el-col :span="24">
<el-container>
<el-header height="42px" class="l-h-42 p-l-10 p-r-10 border border-b-n">
<div class="l">
<i class="iconfont el-icon-link f-s-20"></i>
<font class="m-l-10 f-s-18 fb">发布公告</font>
</div>
</el-header>
<el-main class="border p-20">
<el-form label-width="120px">
<el-form-item label="公告标题">
<el-input v-model="form.tit" placeholder="请输入公告标题" maxlength="50" show-word-limit />
</el-form-item>
<el-form-item label="公告信息">
<el-input v-model="form.message" type="textarea" placeholder="请输入公告内容" :rows="5" maxlength="80"
show-word-limit />
</el-form-item>
<el-form-item label="显示截止日期">
<el-date-picker v-model="form.date" type="date" placeholder="选择日期" format="yyyy 年 MM 月 dd 日"
value-format="timestamp" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-edit" :loading="loading" @click="pubMessage()">
发布公告
</el-button>
</el-form-item>
</el-form>
</el-main>
</el-container>
</el-col>
</el-row>
</div>
</template>
<script>
import { pubMessage } from '@/utils/api/table'
export default {
name: 'message',
data () {
return {
form: {
date: '',
message: '',
tit: ''
},
loading: false
}
},
computed: {
// Vuex ID
idArr () {
return this.$store.state.app.toMessageIdArr
}
},
created () {
},
methods: {
async pubMessage () {
// idArr
if (!this.idArr || this.idArr.length === 0) {
this.$message.warning('接收用户为空,请重新操作')
this.$router.push('/admin/index')
return
}
if (!this.form.tit) {
this.$message.error('请输入公告标题')
return
}
if (!this.form.message) {
this.$message.error('请输入公告内容')
return
}
if (!this.form.date) {
this.$message.error('请选择截止日期')
return
}
const endTime = Math.floor(new Date(this.form.date).setHours(23, 59, 59, 999) / 1000)//
const res = await pubMessage(this.form.tit, this.form.message, this.idArr, endTime)
if (res.data.status === 1) {
this.$message.success(res.data.msg)
this.form.message = ''
this.form.date = ''
this.form.tit = ''
//
this.$router.push('/admin/index')
} else {
this.$message.error(res.data.msg || '公告发布失败')
}
}
}
}
</script>
<style lang="scss" scoped>
.rspan {
float: right;
color: #8492a6;
font-size: 13px;
}
</style>

View File

@ -2,8 +2,9 @@
<div class="app-container"> <div class="app-container">
<!-- 组合按钮 --> <!-- 组合按钮 -->
<el-button-group class="m-b-20 m-r-20"> <el-button-group class="m-b-20 m-r-20">
<el-button type="danger" icon="el-icon-delete" @click="deleteMessage(countSelIdArr($refs.myTable.selection))">删除 <el-button type="danger" icon="el-icon-delete" @click="deleteAdmin(countSelIdArr($refs.myTable.selection))">删除
</el-button> </el-button>
<el-button type="warning" icon="el-icon-edit" @click="toEditPage()">编辑</el-button>
</el-button-group> </el-button-group>
<!-- 用户select选项 --> <!-- 用户select选项 -->
<el-button-group class="m-b-20"> <el-button-group class="m-b-20">
@ -44,11 +45,11 @@
<!-- 操作 --> <!-- 操作 -->
<el-table-column label="操作" width="220" fixed="right"> <el-table-column label="操作" width="220" fixed="right">
<template slot-scope="scope"> <el-button-group>
<el-button-group> <el-button type="warning" icon="el-icon-edit"
<el-button type="danger" icon="el-icon-delete" @click="deleteMessage([scope.row.id])">删除</el-button> @click="$router.replace(`/admin/edit/${scope.row.id}`)">编辑</el-button>
</el-button-group> <el-button type="danger" icon="el-icon-delete" @click="deleteAdmin([scope.row.id])">删除</el-button>
</template> </el-button-group>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -63,7 +64,7 @@
<script> <script>
import { parseTime, countSelIdArr } from '@/utils' import { parseTime, countSelIdArr } from '@/utils'
import SelectionShopId from '@/components/SelectionShopId' import SelectionShopId from '@/components/SelectionShopId'
import { getAllMessageList, delMessage } from '@/utils/api/table' import { getAllMessageList } from '@/utils/api/table'
export default { export default {
name: 'Admin', name: 'Admin',
@ -94,7 +95,6 @@ export default {
this.getAllMessageList() this.getAllMessageList()
}, },
methods: { methods: {
countSelIdArr,
parseTime, parseTime,
// //
async getAllMessageList () { async getAllMessageList () {
@ -104,31 +104,10 @@ export default {
} else { } else {
this.$message.error(res.msg) this.$message.error(res.msg)
} }
},
//
deleteMessage (idArr) {
if (!idArr || idArr.length === 0) {
this.$message.error('未勾选记录')
} else {
this.$confirm('请谨慎操作,确认删除这些公告?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
delMessage(idArr).then(res => {
if (res.data.status === 1) {
this.$message.success(res.data.msg)
this.getAllMessageList() //
} else {
this.$message.error(res.data.msg)
}
})
}).catch(() => {
this.$message.info('取消操作')
})
}
} }
},
filters: {
countSelIdArr
} }
} }

View File

@ -11,38 +11,19 @@
</el-header> </el-header>
<el-main class="border p-20"> <el-main class="border p-20">
<el-form label-width="120px"> <el-form label-width="120px">
<el-form-item label="所属商铺">
<SelectionShopId v-model="form.shop_id" :allSel="true" />
</el-form-item>
<el-form-item label="公告接收者">
<el-checkbox v-model="allSelected" @change="handleCheckAll" style="margin-bottom: 10px;">
全选
</el-checkbox>
<el-checkbox-group v-model="form.idArr" @change="updateAllSelected">
<el-checkbox
v-for="admin in filteredAdminList"
:key="admin.id"
:label="admin.id">
{{ admin.name }}
</el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item label="公告标题"> <el-form-item label="公告标题">
<el-input v-model="form.tit" placeholder="请输入公告标题" maxlength="50" show-word-limit /> <el-input v-model="form.tit" placeholder="请输入公告标题" maxlength="50" show-word-limit />
</el-form-item> </el-form-item>
<el-form-item label="公告信息"> <el-form-item label="公告信息">
<el-input v-model="form.message" type="textarea" placeholder="请输入公告内容" :rows="5" maxlength="80" show-word-limit /> <el-input v-model="form.message" type="textarea" placeholder="请输入公告内容" :rows="5" maxlength="80"
show-word-limit />
</el-form-item> </el-form-item>
<el-form-item label="显示截止日期"> <el-form-item label="显示截止日期">
<el-date-picker v-model="form.date" type="date" placeholder="选择日期" format="yyyy 年 MM 月 dd 日" value-format="timestamp" /> <el-date-picker v-model="form.date" type="date" placeholder="选择日期" format="yyyy 年 MM 月 dd 日"
value-format="timestamp" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" icon="el-icon-edit" :loading="loading" @click="submitMessage"> <el-button type="primary" icon="el-icon-edit" :loading="loading" @click="pubMessage()">
发布公告 发布公告
</el-button> </el-button>
</el-form-item> </el-form-item>
@ -56,56 +37,33 @@
<script> <script>
import { pubMessage } from '@/utils/api/table' import { pubMessage } from '@/utils/api/table'
import SelectionShopId from '@/components/SelectionShopId'
export default { export default {
name: 'message', name: 'message',
data () { data () {
return { return {
form: { form: {
shop_id: '',
date: '', date: '',
message: '', message: '',
tit: '', tit: ''
idArr: []
}, },
loading: false, loading: false
allSelected: false
} }
}, },
components: {
SelectionShopId
},
computed: { computed: {
adminList () { // Vuex ID
return this.$store.state.adminList || [] idArr () {
}, return this.$store.state.app.toMessageIdArr
filteredAdminList () {
if (!this.form.shop_id) return this.adminList
return this.adminList.filter(admin => admin.shop_id === this.form.shop_id)
} }
}, },
watch: { created () {
'form.shop_id' () {
this.form.idArr = []
this.allSelected = false
}
}, },
methods: { methods: {
handleCheckAll (checked) { async pubMessage () {
this.form.idArr = checked ? this.filteredAdminList.map(admin => admin.id) : [] // idArr
}, if (!this.idArr || this.idArr.length === 0) {
updateAllSelected () {
const filteredIds = this.filteredAdminList.map(admin => admin.id)
this.allSelected = this.form.idArr.length === filteredIds.length && filteredIds.length > 0
},
async submitMessage () {
if (!this.form.shop_id) {
this.$message.warning('请选择所属商铺')
return
}
if (!this.form.idArr || this.form.idArr.length === 0) {
this.$message.warning('接收用户为空,请重新操作') this.$message.warning('接收用户为空,请重新操作')
this.$router.push('/admin/index')
return return
} }
if (!this.form.tit) { if (!this.form.tit) {
@ -121,37 +79,19 @@ export default {
return return
} }
const endTime = Math.floor(new Date(this.form.date).setHours(23, 59, 59, 999) / 1000) const endTime = Math.floor(new Date(this.form.date).setHours(23, 59, 59, 999) / 1000)//
this.loading = true const res = await pubMessage(this.form.tit, this.form.message, this.idArr, endTime)
try {
const res = await pubMessage(
this.form.shop_id,
this.form.tit,
this.form.message,
this.form.idArr,
endTime
)
if (res?.data?.status === 1) { if (res.data.status === 1) {
this.$message.success(res.data.msg) this.$message.success(res.data.msg)
this.form = { this.form.message = ''
shop_id: '', this.form.date = ''
date: '', this.form.tit = ''
message: '', //
tit: '', this.$router.push('/admin/index')
idArr: [] } else {
} this.$message.error(res.data.msg || '公告发布失败')
this.allSelected = false
this.$router.push('/message/index')
} else {
this.$message.error(res?.data?.msg || '公告发布失败')
}
} catch (err) {
console.error('发布公告失败:', err)
this.$message.error('网络错误')
} finally {
this.loading = false
} }
} }
} }