This commit is contained in:
zhang zhuo 2025-12-19 11:31:36 +08:00
parent 6858345888
commit 4f463dcbb3
5 changed files with 137 additions and 80 deletions

View File

@ -266,5 +266,8 @@ export default {
remove: async function (data = {}) { remove: async function (data = {}) {
return await http.delete("message/remove", data); return await http.delete("message/remove", data);
}, },
clear: async function (data = {}) {
return await http.delete("message/clear", data);
},
}, },
} }

View File

@ -39,5 +39,16 @@ export default {
export: async function (data = {}) { export: async function (data = {}) {
return await http.get("file/export", data); return await http.get("file/export", data);
}, },
} },
attachment: {
list: async function (data = {}) {
return await http.get("attachment/list", data);
},
del: async function (data = {}) {
return await http.delete("attachment/del", data);
},
clear: async function (data = {}) {
return await http.delete("attachment/clear", data);
},
},
} }

View File

@ -1,41 +1,44 @@
<template> <template>
<el-container v-loading="loading"> <el-container v-loading="loading">
<el-main> <el-scrollbar :view-style="{ 'overflow-x': 'hidden' }" @endReached="handleScroll">
<el-empty v-if="tasks.length==0" :image-size="120"> <el-main>
<template #description> <el-empty v-if="attachList.length===0" :image-size="120">
<h2>没有正在执行的任务</h2> <template #description>
</template> <h2>没有正在执行的任务</h2>
</el-empty> </template>
<el-card v-for="task in tasks" :key="task.id" shadow="hover" class="user-bar-tasks-item"> </el-empty>
<div class="user-bar-tasks-item-body"> <el-card v-for="(attach, index) in attachList" :key="attach.attachment_id" shadow="hover"
<div class="taskIcon"> class="user-bar-attach-item">
<el-icon :size="20"> <div class="user-bar-attach-item-body">
<el-icon-paperclip/> <div class="attachIcon">
</el-icon> <el-icon :size="20">
</div> <el-icon-paperclip/>
<div class="taskMain"> </el-icon>
<div class="title">
<h2>{{ task.taskName }}</h2>
<p><span v-time.tip="task.createDate"></span> 创建</p>
</div> </div>
<div class="bottom"> <div class="attachMain">
<div class="state"> <div class="title">
<el-tag type="info" v-if="task.state=='0'">待处理</el-tag> <h2>{{ attach.name }}</h2>
<el-tag type="info" v-if="task.state=='1'">处理中</el-tag> <p><span v-time.tip="attach.create_time"></span> 创建</p>
<el-tag type="primary" v-if="task.state=='2'">完成</el-tag> <p v-if="attach.status===2"><span>{{ attach.fail_reason }}</span></p>
<el-tag type="danger" v-if="task.state=='3'">失败</el-tag>
</div> </div>
<div class="handler"> <div class="bottom">
<el-button v-if="task.state=='2'" type="danger" circle icon="el-icon-delete" <div class="state">
@click="remove(task)"></el-button> <el-tag type="info" v-if="attach.status===0">待处理</el-tag>
<el-button v-if="task.state=='2'" type="primary" circle icon="el-icon-download" <el-tag type="success" v-if="attach.status===1">完成</el-tag>
@click="download(task)"></el-button> <el-tag type="warning" v-if="attach.status===2">失败</el-tag>
</div>
<div class="handler">
<el-button type="danger" circle icon="el-icon-delete"
@click="remove(attach, index)"></el-button>
<el-button v-if="attach.status===1" type="primary" circle icon="el-icon-download"
@click="download(attach)"></el-button>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </el-card>
</el-card> </el-main>
</el-main> </el-scrollbar>
<el-footer style="padding:10px;text-align: right;"> <el-footer style="padding:10px;text-align: right;">
<el-button circle icon="el-icon-delete" @click="removeAll"></el-button> <el-button circle icon="el-icon-delete" @click="removeAll"></el-button>
<el-button circle icon="el-icon-refresh" @click="refresh"></el-button> <el-button circle icon="el-icon-refresh" @click="refresh"></el-button>
@ -44,42 +47,38 @@
</template> </template>
<script setup> <script setup>
import {ref, onMounted} from "vue"; import {ref, onMounted, getCurrentInstance} from "vue"
import api from "@/api"; import api from "@/api"
import {ElMessageBox} from 'element-plus' import {ElMessageBox} from 'element-plus'
import tools from "@/utils/tools"
const {proxy} = getCurrentInstance()
let loading = ref(false) let loading = ref(false)
let tasks = ref([]) let attachList = ref([])
let page = ref(1)
let limit = ref(5)
let finish = ref(false)
onMounted(() => { onMounted(() => {
getData() loadData()
}) })
async function getData() { async function loadData() {
// loading.value = true loading.value = true
// const res = await api.system.tasks.list(); const res = await api.tools.attachment.list({page: page.value, limit: limit.value});
// tasks.value= res.data loading.value = false
// loading.value = false attachList.value = attachList.value.concat(res.data)
if (res.data.length < limit.value) {
tasks.value.push({ finish.value = true
"id": "100", }
"taskName": "年度报表生成",
"result": "",
"state": "0",
"createDate": "2022-06-13 17:04:55"
})
tasks.value.push({
"id": "101",
"taskName": "系统日志导出",
"result": "http://www.baidu.com",
"state": "2",
"createDate": "2022-06-12 09:31:08"
})
} }
function refresh() { function refresh() {
getData() page.value = 1
attachList.value = []
finish.value = false
loadData()
} }
function removeAll() { function removeAll() {
@ -88,41 +87,59 @@ function removeAll() {
cancelButtonText: '取消', cancelButtonText: '取消',
inputPattern: /^清空所有$/, inputPattern: /^清空所有$/,
inputErrorMessage: '输入错误', inputErrorMessage: '输入错误',
}).then(() => { }).then(async () => {
tasks.value = [] loading.value = true
}).catch(() => {}) const [res, err] = await tools.go(api.tools.attachment.clear());
loading.value = false
if (!err) {
proxy.$message.error(res.msg)
return
}
proxy.$message.success(res.msg)
attachList.value = []
}).catch(() => {
})
} }
function download(row) { function download(row) {
let a = document.createElement("a") let a = document.createElement("a")
a.style = "display: none" a.style = "display: none"
a.target = "_blank" a.href = row.path
a.href = row.attach
document.body.appendChild(a) document.body.appendChild(a)
a.click() a.click()
document.body.removeChild(a) document.body.removeChild(a)
} }
function remove(row) { async function handleScroll(event) {
if (loading.value || finish.value || event !== "bottom") return
page.value++
await loadData()
}
async function remove(row, index) {
loading.value = true
const res = await api.tools.attachment.del({ids: [row.attachment_id]});
loading.value = false
proxy.$message.success(res.msg)
attachList.value.splice(index, 1)
} }
</script> </script>
<style scoped> <style scoped>
.user-bar-tasks-item { .user-bar-attach-item {
margin-bottom: 10px; margin-bottom: 10px;
} }
.user-bar-tasks-item:hover { .user-bar-attach-item:hover {
border-color: var(--el-color-primary); border-color: var(--el-color-primary);
} }
.user-bar-tasks-item-body { .user-bar-attach-item-body {
display: flex; display: flex;
} }
.user-bar-tasks-item-body .taskIcon { .user-bar-attach-item-body .attachIcon {
width: 45px; width: 45px;
height: 45px; height: 45px;
background: var(--el-color-primary-light-9); background: var(--el-color-primary-light-9);
@ -134,21 +151,21 @@ function remove(row) {
border-radius: 20px; border-radius: 20px;
} }
.user-bar-tasks-item-body .taskMain { .user-bar-attach-item-body .attachMain {
flex: 1; flex: 1;
} }
.user-bar-tasks-item-body .title h2 { .user-bar-attach-item-body .title h2 {
font-size: 15px; font-size: 15px;
} }
.user-bar-tasks-item-body .title p { .user-bar-attach-item-body .title p {
font-size: 12px; font-size: 12px;
color: #999; color: #999;
margin-top: 5px; margin-top: 5px;
} }
.user-bar-tasks-item-body .bottom { .user-bar-attach-item-body .bottom {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;

View File

@ -11,8 +11,7 @@
</el-icon> </el-icon>
</div> </div>
<div v-else> <div v-else>
<el-scrollbar ref="scrollbar" height="230px" :view-style="{ 'overflow-x': 'hidden' }" <el-scrollbar height="230px" :view-style="{ 'overflow-x': 'hidden' }" @endReached="handleScroll">
@endReached="handleScroll">
<el-link v-for="item in msgList" :key="item" underline="never" <el-link v-for="item in msgList" :key="item" underline="never"
:title="item.create_time + ' ' + item.title" :title="item.create_time + ' ' + item.title"
style="display: block; width: 100%;" @click="detail(item)"> style="display: block; width: 100%;" @click="detail(item)">
@ -29,7 +28,11 @@
</div> </div>
<el-divider/> <el-divider/>
<div class="msg-more"> <div class="msg-more">
<el-button link type="primary" icon="el-icon-select" @click="read" :loading="loading">全部已读</el-button> <el-button v-if="!isRead" link type="primary" icon="el-icon-select" @click="readAll" :loading="loading">
全部已读
</el-button>
<el-button v-else link type="danger" icon="el-icon-delete" @click="clearAll" :loading="loading">全部删除
</el-button>
</div> </div>
</template> </template>
@ -37,9 +40,10 @@
import {getCurrentInstance, onMounted, ref} from "vue"; import {getCurrentInstance, onMounted, ref} from "vue";
import api from "@/api" import api from "@/api"
import {useRouter} from "vue-router" import {useRouter} from "vue-router"
import {ElMessageBox} from "element-plus";
import tools from "@/utils/tools.js";
const {proxy} = getCurrentInstance() const {proxy} = getCurrentInstance()
const scrollbar = ref(null)
const router = useRouter() const router = useRouter()
const emit = defineEmits(['closed']) const emit = defineEmits(['closed'])
@ -49,6 +53,7 @@ let page = ref(1)
const limit = ref(10) const limit = ref(10)
const loading = ref(false) const loading = ref(false)
const finish = ref(false) const finish = ref(false)
const isRead = ref(false)
onMounted(() => { onMounted(() => {
loadData() loadData()
@ -56,10 +61,10 @@ onMounted(() => {
async function loadData() { async function loadData() {
loading.value = true loading.value = true
let res = await api.system.message.mine({type: msgTab.value, page: page.value}) let res = await api.system.message.mine({page: page.value, limit: limit.value, type: msgTab.value})
loading.value = false loading.value = false
msgList.value = msgList.value.concat(res.data) msgList.value = msgList.value.concat(res.data)
if (res.data.length > limit.value) { if (res.data.length < limit.value) {
finish.value = true finish.value = true
} }
} }
@ -71,7 +76,7 @@ async function switchTab() {
await loadData() await loadData()
} }
async function read() { async function readAll() {
let res = await api.system.message.read({type: msgTab.value}) let res = await api.system.message.read({type: msgTab.value})
proxy.$message.success(res.msg) proxy.$message.success(res.msg)
msgList.value.forEach((item) => { msgList.value.forEach((item) => {
@ -79,6 +84,27 @@ async function read() {
item.read_flag = 1 item.read_flag = 1
} }
}) })
isRead.value = true
}
async function clearAll() {
ElMessageBox.prompt('请输入“清空所有”以确认操作', '警告', {
confirmButtonText: '确认',
cancelButtonText: '取消',
inputPattern: /^清空所有$/,
inputErrorMessage: '输入错误',
}).then(async () => {
loading.value = true
const [res, err] = await tools.go(api.system.message.clear({type: msgTab.value}));
loading.value = false
if (!err) {
proxy.$message.error(res.msg)
return
}
proxy.$message.success(res.msg)
msgList.value = []
}).catch(() => {
})
} }
async function handleScroll(event) { async function handleScroll(event) {

View File

@ -4,7 +4,7 @@
<el-button v-auth="'post:add'" type="primary" icon="el-icon-plus" @click="add"></el-button> <el-button v-auth="'post:add'" type="primary" icon="el-icon-plus" @click="add"></el-button>
<el-button v-auth="'post:del'" type="danger" plain icon="el-icon-delete" :disabled="selection.length===0" <el-button v-auth="'post:del'" type="danger" plain icon="el-icon-delete" :disabled="selection.length===0"
@click="batch_del"></el-button> @click="batch_del"></el-button>
<pi-export v-auth="'post:export'" module="post_export" :params="search"></pi-export> <pi-export v-auth="'post:export'" module="post_export" :params="search" name="岗位列表导出"></pi-export>
<pi-import v-auth="'post:import'" :api-obj="api.system.post.import"></pi-import> <pi-import v-auth="'post:import'" :api-obj="api.system.post.import"></pi-import>
</template> </template>
<template #search> <template #search>