feat: add cron msg

This commit is contained in:
engigu
2024-04-11 17:20:36 +08:00
parent 17a99a67e6
commit a78ff937c0
18 changed files with 1144 additions and 5 deletions
+5
View File
@@ -27,6 +27,11 @@ const router = createRouter({
name: 'sendtasks',
component: () => import('../views/tabsTools/sendTasks/sendTasks.vue')
},
{
path: '/sendmessages',
name: 'sendmessages',
component: () => import('../views/tabsTools/sendMessage/sensMessage.vue')
},
{
path: '/sendlogs',
name: 'sendlogs',
+4 -3
View File
@@ -35,9 +35,10 @@ export default {
const menuData = reactive([
{ id: '0', title: '数据统计', path: '/statistic' },
{ id: '1', title: '发信日志', path: '/sendlogs' },
{ id: '2', title: '发信任务', path: '/sendtasks' },
{ id: '3', title: '发信渠道', path: '/sendways' },
{ id: '4', title: '设置', path: '/settings' },
{ id: '2', title: '定时发信', path: '/sendmessages' },
{ id: '3', title: '发信任务', path: '/sendtasks' },
{ id: '4', title: '发信渠道', path: '/sendways' },
{ id: '5', title: '设置', path: '/settings' },
]);
const checkIsLogin = () => {
@@ -0,0 +1,204 @@
<template>
<div class="main-center-body">
<div class="container">
<div class="search-input-sendways">
<el-input v-model="search" size="small" placeholder="搜索" @change="filterFunc()" />
</div>
<div class="search-box">
<el-button size="small" type="primary" @click="clickAdd">新增定时消息</el-button>
</div>
<hr />
<div ref="refContainer">
<el-table :data="tableData" stripe empty-text="定时发信为空" :row-style="rowStyle()">
<el-table-column label="消息ID" prop="id" />
<el-table-column label="关联ID" prop="task_id" />
<el-table-column label="消息名" prop="name" />
<el-table-column label="Cron" prop="cron" />
<el-table-column label="消息内容" prop="content" />
<el-table-column label="创建时间" prop="created_on" />
<el-table-column fixed="right" label="操作" width="190px">
<template #default="scope">
<div>
<!-- <el-button link size="small" type="primary" @click="handleViewAPI(scope.$index, scope.row)">接口</el-button> -->
<el-button link size="small" type="primary"
@click="handleViewLogs(scope.$index, scope.row)">日志</el-button>
<el-button link size="small" type="primary" @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
<tableDeleteButton @customHandleDelete="handleDelete(scope.$index, scope.row)" />
<el-switch v-model.bool="scope.row.enable" inline-prompt active-text="开启" inactive-text="关闭"
@click="updateEnableStatus(scope.row)" />
</div>
</template>
</el-table-column>
</el-table>
</div>
<div class="pagination-block">
<el-pagination layout="prev, pager, next" :total="total" :page-size="pageSize"
@current-change="handPageChange" />
<el-text class="total-tip" size="small">每页{{ pageSize }}{{ total }}</el-text>
</div>
</div>
</div>
<addCronMsgPopUpComponent :componentName="addCronMsgPopUpComponentName" />
<editCronMsgPopUpComponent :componentName="editCronMsgPopUpComponentName" />
</template>
<script>
import { computed, ref, reactive, toRefs, onMounted } from 'vue'
import { usePageState } from '@/store/page_sate';
import { request } from '@/api/api'
import addCronMsgPopUpComponent from './view/addCronMsgPopUp.vue'
import editCronMsgPopUpComponent from './view/editCronMsgPopUp.vue'
import tableDeleteButton from '@/views/common/tableDeleteButton.vue'
import { useRouter } from 'vue-router';
import { CONSTANT } from '@/constant'
import { ElMessage } from 'element-plus'
export default {
components: {
addCronMsgPopUpComponent,
editCronMsgPopUpComponent,
tableDeleteButton,
},
setup() {
const pageState = usePageState();
const router = useRouter();
const state = reactive({
addCronMsgPopUpComponentName: 'addCronMsgPopUpComponentName',
editCronMsgPopUpComponentName: 'editCronMsgPopUpComponentName',
search: '',
optionValue: '',
dialogFormVisible: false,
tableData: [],
total: CONSTANT.TOTAL,
pageSize: pageState.siteConfigData.pagesize,
currPage: CONSTANT.PAGE,
});
const handleEdit = (index, row) => {
let name = state.editCronMsgPopUpComponentName;
pageState.ShowDialogData[name] = {};
pageState.ShowDialogData[name].isShow = true;
pageState.ShowDialogData[name].rowData = row;
}
const handleDelete = async (index, row) => {
const rsp = await request.post('/sendmessages/delete', { id: row.id });
if (rsp.status == 200) {
state.tableData.splice(index, 1);
}
}
const handPageChange = async (pageNum) => {
state.currPage = pageNum;
await queryListData(pageNum, state.pageSize);
}
const rowStyle = () => {
return {
'font-size': '13px',
}
}
const handleViewLogs = (index, row) => {
router.push('/sendlogs?taskid=' + row.task_id, { replace: true });
}
const filterFunc = async () => {
await queryListData(state.currPage, state.pageSize, state.search, state.optionValue);
}
const clickAdd = () => {
pageState.ShowDialogData[state.addCronMsgPopUpComponentName] = {};
pageState.ShowDialogData[state.addCronMsgPopUpComponentName].isShow = true;
}
const queryListData = async (page, size, name = '') => {
let params = { page: page, size: size, name: name };
const rsp = await request.get('/sendmessages/list', { params: params });
state.tableData = await rsp.data.data.lists;
dealInsEnableStatus(state.tableData)
state.total = await rsp.data.data.total;
}
const dealInsEnableStatus = (data) => {
data.forEach(ins => {
ins.enable = ins.enable == 1;
});
}
// 开启暂停定时任务
const updateEnableStatus = async (data) => {
data.enable = !Boolean(data.enable) ? 0 : 1
const rsp = await request.post('/sendmessages/edit', data);
if (await rsp.data.code == 200) {
ElMessage({ message: await rsp.data.msg, type: 'success' });
data.enable = Boolean(data.enable)
}
}
onMounted(async () => {
await queryListData(1, state.pageSize);
});
return {
...toRefs(state), handleEdit, handleDelete, handleViewLogs,
clickAdd, rowStyle, handPageChange, filterFunc, updateEnableStatus
};
}
}
</script>
<style scoped>
hr {
color: #FAFCFF;
background-color: #FAFCFF;
border-color: #FAFCFF;
}
.container {
background-color: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1);
max-width: 1000px;
width: 100%;
/* margin-top: -10vh; */
}
.pagination-block {
margin-top: 15px;
display: flex;
justify-content: flex-end;
}
.total-tip {
display: inline-block;
}
.search-box {
float: right;
}
:global(.select .el-input__inner) {
width: 80px;
}
.search-input-sendways {
/* margin-left: 40px; */
width: 150px;
display: inline-flex;
}
.op-col {
text-align: left;
}
</style>
@@ -0,0 +1,211 @@
<template>
<el-dialog v-model="isShow" width="400px" :close-on-press-escape="false" :before-close="() => { }"
:show-close="false">
<template #header="">
<el-text class="mx-1">添加定时消息发送</el-text>
<el-tooltip placement="top">
<template #content>
可以定制一些定时消息通知完成一些简单的提醒事件
<br />
** 需要基于已经创建的发信任务进行绑定
</template>
<el-icon>
<QuestionFilled />
</el-icon>
</el-tooltip>
</template>
<div class="add-top">
<el-input v-model="currTaskInput.name" placeholder="请输入消息名称" size="small" class="nameInput"></el-input>
</div>
<div class="ins-area">
<div class="ins-add">
<el-autocomplete v-model="currSearchInputText" size="small" :fetch-suggestions="querySearchWayAsync"
placeholder="请输入消息名进行搜索" @select="handleSearchSelect" :clearable="true" value-key="name" />
<div class="store-area" v-if="isShowAddBox">
<div class="display-label">
<el-text class="mx-1" size="small">消息ID{{ currTaskTmp.id }}</el-text><br />
<el-text class="mx-1" size="small">消息名{{ currTaskTmp.name }}</el-text><br />
<el-text class="mx-1" size="small">消息创建时间{{ currTaskTmp.created_on }}</el-text><br />
</div>
<el-input v-model="currTaskInput.title" placeholder="请输入消息标题" size="small" class="msg-input"></el-input>
<el-input type="textarea" :rows="5" v-model="currTaskInput.content" placeholder="请输入消息内容" size="small"
class="msg-input"></el-input>
<el-input v-model="currTaskInput.cron" placeholder="请输入定时cron表达式" size="small" class="msg-input"></el-input>
<el-input v-model="currTaskInput.url" placeholder="请输入消息详情url(可选)" size="small" class="msg-input"></el-input>
</div>
</div>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="handleCancer()" size="small">取消</el-button>
<!-- <el-button type="primary" size="small" @click="cliclSendNow()">
立即发送
</el-button> -->
<el-button type="primary" size="small" @click="handleSubmit()">
确定添加
</el-button>
</span>
</template>
</el-dialog>
</template>
<script>
import { defineComponent, onMounted, watch, reactive, toRefs } from 'vue';
import { _ } from 'lodash';
import { QuestionFilled } from '@element-plus/icons-vue'
import { usePageState } from '@/store/page_sate.js';
import { request } from '@/api/api'
import { CONSTANT } from '@/constant'
import { CommonUtils } from "@/util/commonUtils.js";
import { generateBizUniqueID } from "@/util/uuid.js";
import { ElMessage } from 'element-plus'
export default defineComponent({
components: {
QuestionFilled,
},
props: {
componentName: String
},
setup(props) {
const pageState = usePageState();
const state = reactive({
insTableData: [],
currSearchWaysData: [],
currSearchInputText: '',
isShow: false,
isShowAddBox: false,
searchway_id: '',
currTaskTmp: {},
currInsInput: {},
currInsInputContentType: 'text',
currTaskInput: {
name: '',
title: '',
content: '',
cron: '',
url: '',
id: generateBizUniqueID('C'),
},
sysKeptTaskIds: [CONSTANT.LOG_TASK_ID],
});
watch(pageState.ShowDialogData, (newValue, oldValue) => {
if (newValue[props.componentName]) {
state.isShow = pageState.ShowDialogData[props.componentName].isShow;
resetPageInitData();
}
});
const handleCancer = () => {
if (pageState.ShowDialogData[props.componentName]) {
pageState.ShowDialogData[props.componentName].isShow = false;
}
}
// 页面每次弹出,重置数据
const resetPageInitData = () => {
state.insTableData = [];
state.currInsInputContentType = 'text';
state.currInsInput = {};
state.currTaskTmp = {};
state.searchway_id = '';
state.isShowAddBox = false;
state.currTaskInput = {
name: '',
id: generateBizUniqueID('C'),
}
}
const cliclSendNow = () => {
console.log('cliclSendNow');
}
// 匹配出当前搜索的消息数据
const matchSearchData = (way_name) => {
let result = {};
state.currSearchWaysData.forEach(element => {
if (element.name == way_name) {
result = element;
}
});
return result;
}
const handleSearchSelect = async () => {
let currTask = matchSearchData(state.currSearchInputText)
state.isShowAddBox = Boolean(currTask);
if (currTask) {
state.currTaskTmp = currTask;
}
}
const querySearchWayAsync = async (query, cb) => {
let params = { name: query };
const rsp = await request.get('/sendtasks/list', { params: params });
let tableData = await rsp.data.data.lists;
tableData = filtersysKeptTask(tableData);
cb(tableData);
state.currSearchWaysData = tableData;
}
const filtersysKeptTask = (data) => {
let result = data.filter(item => !state.sysKeptTaskIds.includes(item.id));
return result;
}
const getFinalData = () => {
state.currTaskInput.task_id = state.currTaskTmp.id;
return state.currTaskInput
}
const handleSubmit = async () => {
let postData = getFinalData();
const rsp = await request.post('/sendmessages/addone', postData);
if (await rsp.data.code == 200) {
ElMessage({ message: await rsp.data.msg, type: 'success' });
handleCancer();
window.location.reload();
}
}
return {
...toRefs(state), handleCancer, handleSubmit, querySearchWayAsync,
handleSearchSelect, CONSTANT, CommonUtils,
cliclSendNow
};
},
});
</script>
<style scoped>
:deep(.el-autocomplete) {
width: 100%;
}
.msg-input {
/* width: 200px; */
margin: 5px 10px 5px 0;
}
.add-top {
margin-bottom: 20px;
margin-top: -20px;
}
.display-label {
margin-top: 10px;
margin-bottom: 10px;
}
</style>
@@ -0,0 +1,229 @@
<template>
<el-dialog v-model="isShow" width="400px" :close-on-press-escape="false" :before-close="() => { }"
:show-close="false">
<template #header="">
<el-text class="mx-1">编辑发信任务</el-text>
</template>
<div class="add-top">
<el-input v-model="currTaskInput.name" placeholder="请输入消息名称" size="small" class="nameInput"></el-input>
</div>
<div class="ins-area">
<div class="ins-add">
<el-autocomplete v-model="currSearchInputText" size="small" :fetch-suggestions="querySearchWayAsync"
placeholder="请输入任务名进行搜索" @select="handleSearchSelect" :clearable="true" value-key="name" />
<div class="store-area" v-if="isShowAddBox">
<div class="display-label">
<el-text class="mx-1" size="small">消息ID{{ currTaskTmp.id }}</el-text><br />
<el-text class="mx-1" size="small">消息名{{ currTaskTmp.name }}</el-text><br />
<el-text class="mx-1" size="small">消息创建时间{{ currTaskTmp.created_on }}</el-text><br />
</div>
<el-input v-model="currTaskInput.title" placeholder="请输入消息标题" size="small" class="msg-input"></el-input>
<el-input type="textarea" :rows="5" v-model="currTaskInput.content" placeholder="请输入消息内容" size="small"
class="msg-input"></el-input>
<el-input v-model="currTaskInput.cron" placeholder="请输入定时cron表达式" size="small" class="msg-input"></el-input>
<el-input v-model="currTaskInput.url" placeholder="请输入消息详情url(可选)" size="small" class="msg-input"></el-input>
</div>
</div>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="handleCancer()" size="small">取消</el-button>
<el-button type="primary" size="small" @click="handleEditCronMsg()">
确定修改
</el-button>
</span>
</template>
</el-dialog>
</template>
<script>
import { defineComponent, onMounted, watch, reactive, toRefs } from 'vue';
import { _ } from 'lodash';
import { QuestionFilled } from '@element-plus/icons-vue'
import { usePageState } from '@/store/page_sate.js';
import { request } from '@/api/api'
import tableDeleteButton from '@/views/common/tableDeleteButton.vue'
import { ElMessage } from 'element-plus'
import { CONSTANT } from '@/constant'
import { CommonUtils } from "@/util/commonUtils.js";
import { generateBizUniqueID } from "@/util/uuid.js";
export default defineComponent({
components: {
QuestionFilled,
tableDeleteButton,
},
props: {
componentName: String
},
setup(props) {
const pageState = usePageState();
const state = reactive({
insTableData: [],
currSearchWaysData: [],
currSearchInputText: '',
isShow: false,
isShowAddBox: false,
searchWayID: '',
currInsInputContentType: '',
currTaskTmp: {},
currInsInput: {},
currTaskInput: {
name: '',
title: '',
content: '',
cron: '',
url: '',
},
sysKeptTaskIds: [CONSTANT.LOG_TASK_ID],
});
watch(pageState.ShowDialogData, (newValue, oldValue) => {
if (newValue[props.componentName]) {
let data = pageState.ShowDialogData[props.componentName];
state.isShow = data.isShow;
resetPageInitData();
state.currTaskInput.taskId = data.rowData.id;
if (data && state.isShow) {
state.currTaskInput = data.rowData;
InitOpenSeletValue(state.currTaskInput)
}
}
});
const InitOpenSeletValue = async (data) => {
// 填充编辑框数据
let task_id = data.task_id;
const rsp = await request.get('/sendtasks/get', { params: { id: task_id } });
let rsp_data = await rsp.data;
state.isShowAddBox = true;
state.currSearchInputText = rsp_data.data.name;
state.currTaskTmp = {
id: rsp_data.data.id,
name: rsp_data.data.name,
created_on: rsp_data.data.created_on,
};
}
const handleCancer = () => {
if (pageState.ShowDialogData[props.componentName]) {
pageState.ShowDialogData[props.componentName].isShow = false;
}
}
// 页面每次弹出,重置数据
const resetPageInitData = () => {
state.insTableData = [];
state.currInsInput = {};
state.currTaskTmp = {};
state.currInsInput = {};
state.searchWayID = '';
state.currInsInputContentType = '';
state.isShowAddBox = false;
state.currTaskInput = {
taskName: '',
// taskId: uuidv4(),
}
}
// 匹配出当前搜索的任务数据
const matchSearchData = (way_name) => {
let result = {};
state.currSearchWaysData.forEach(element => {
if (element.name == way_name) {
result = element;
}
});
return result;
}
const handleSearchSelect = async () => {
let currTask = matchSearchData(state.currSearchInputText)
state.isShowAddBox = Boolean(currTask);
if (currTask) {
state.currTaskTmp = currTask;
}
}
const querySearchWayAsync = async (query, cb) => {
let params = { name: query };
const rsp = await request.get('/sendtasks/list', { params: params });
let tableData = await rsp.data.data.lists;
tableData = filtersysKeptTask(tableData);
cb(tableData);
state.currSearchWaysData = tableData;
}
const filtersysKeptTask = (data) => {
let result = data.filter(item => !state.sysKeptTaskIds.includes(item.id));
return result;
}
const getFinalData = () => {
let postData = {
name: state.currTaskInput.name,
title: state.currTaskInput.title,
content: state.currTaskInput.content,
cron: state.currTaskInput.cron,
url: state.currTaskInput.url,
id: state.currTaskInput.id,
enable: state.currTaskInput.enable ? 1 : 0,
task_id: state.currTaskTmp.id,
};
return postData
}
const handleEditCronMsg = async () => {
let postData = getFinalData();
console.log('postdata', postData);
const rsp = await request.post('/sendmessages/edit', postData);
if (await rsp.data.code == 200) {
ElMessage({ message: await rsp.data.msg, type: 'success' });
setTimeout(() => {
handleCancer();
window.location.reload();
}, 1000)
}
}
return {
...toRefs(state), handleCancer, CONSTANT, CommonUtils,
handleSearchSelect, querySearchWayAsync, handleEditCronMsg
};
},
});
</script>
<style scoped>
:deep(.el-autocomplete) {
width: 100%;
}
.msg-input {
/* width: 200px; */
margin: 5px 10px 5px 0;
}
.add-top {
margin-bottom: 20px;
margin-top: -20px;
}
.display-label {
margin-top: 10px;
margin-bottom: 10px;
}
</style>