feat: add hosted message
This commit is contained in:
+16
-1
@@ -69,7 +69,7 @@ const CONSTANT = {
|
||||
},
|
||||
{
|
||||
type: 'Custom',
|
||||
label: '自定义',
|
||||
label: '自定义推送',
|
||||
inputs: [
|
||||
{ subLabel: 'webhook地址', value: '', col: 'webhook', desc: "自定义webhook地址" },
|
||||
{ subLabel: '请求体', value: '', col: 'body', desc: "请求体, text内容请使用 TEXT 进行占位\n例如:{\"message\": \"TEXT\", \"foo\": \"bar\"}", isTextArea: true },
|
||||
@@ -103,6 +103,21 @@ const CONSTANT = {
|
||||
{ value: '', col: 'to_account', desc: "要发送的OpenId(登录微信公众号后台查看)" },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'MessageNest',
|
||||
label: '自托管消息',
|
||||
inputs: [
|
||||
{ subLabel: '渠道名', value: '', col: 'name', desc: "想要设置的渠道名字" },
|
||||
],
|
||||
tips: {
|
||||
text: "自托管消息说明", desc: "站点本身会作为消息接收站点,接收、展示推送过来的消息。"
|
||||
},
|
||||
taskInsRadios: [
|
||||
{ subLabel: 'text', content: 'text' },
|
||||
],
|
||||
taskInsInputs: [
|
||||
],
|
||||
},
|
||||
],
|
||||
API_VIEW_DATA: [
|
||||
{ label: "curl", class: "language-shell line-numbers", code: "", func: ApiStrGenerate.getCurlString },
|
||||
|
||||
@@ -41,6 +41,11 @@ const router = createRouter({
|
||||
path: '/settings',
|
||||
name: 'settings',
|
||||
component: () => import('../views/tabsTools/settings/settings.vue')
|
||||
},
|
||||
{
|
||||
path: '/hostedMessage',
|
||||
name: 'hostedmessage',
|
||||
component: () => import('../views/tabsTools/hostedMessage/hostedMessage.vue')
|
||||
},
|
||||
{
|
||||
path: '/:catchAll(.*)',
|
||||
|
||||
@@ -35,10 +35,11 @@ export default {
|
||||
const menuData = reactive([
|
||||
{ id: '0', title: '数据统计', path: '/statistic' },
|
||||
{ id: '1', title: '发信日志', path: '/sendlogs' },
|
||||
{ id: '2', title: '定时发信', path: '/cronmessages' },
|
||||
{ id: '3', title: '发信任务', path: '/sendtasks' },
|
||||
{ id: '4', title: '发信渠道', path: '/sendways' },
|
||||
{ id: '5', title: '设置', path: '/settings' },
|
||||
{ id: '2', title: '托管消息', path: '/hostedmessage' },
|
||||
{ id: '3', title: '定时发信', path: '/cronmessages' },
|
||||
{ id: '4', title: '发信任务', path: '/sendtasks' },
|
||||
{ id: '5', title: '发信渠道', path: '/sendways' },
|
||||
{ id: '6', title: '设置', path: '/settings' },
|
||||
]);
|
||||
|
||||
const checkIsLogin = () => {
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
<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-text class="refresh-time" v-if="refreshText" size="small">{{ refreshText }}</el-text>
|
||||
<el-input-number class="refresh-box" v-model="refreshSec" size="small" :step="2" :min="5"
|
||||
controls-position="right" />
|
||||
<el-switch v-model="refreshSwitch" class="ml-2" width="80" inline-prompt active-text="自动刷新" inactive-text="自动刷新"
|
||||
@click="clickFreshSwitch" />
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
<div ref="refContainer">
|
||||
<el-table :data="tableData" stripe empty-text="托管消息为空" :row-style="rowStyle()">
|
||||
<el-table-column label="ID" prop="id" width="85px" />
|
||||
<el-table-column label="消息标题" prop="title" show-overflow-tooltip width="150px" />
|
||||
<el-table-column label="托管消息" prop="content">
|
||||
<template #default="scope">
|
||||
<el-tooltip enterable placement="top">
|
||||
<template #content>
|
||||
<div v-html="formatLogDisplayHtml(scope)"></div>
|
||||
</template>
|
||||
<span class="log-overflow">{{ scope.row.content }}</span>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="发送时间" prop="created_on" width="160px" />
|
||||
<el-table-column label="详情" prop="status" width="120px" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button link size="small" style="margin-right: 10px;" type="primary"
|
||||
@click="drawer = true; logText = formatLogDisplayHtml(scope)">查看消息</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<el-drawer v-model="drawer" :with-header="false">
|
||||
<el-text v-html="logText" size="small"></el-text>
|
||||
</el-drawer>
|
||||
|
||||
<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>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { reactive, toRefs, onMounted, watch, ref } from 'vue'
|
||||
import { request } from '../../../api/api'
|
||||
import { copyToClipboard } from '../../../util/clipboard.js';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { CONSTANT } from '@/constant'
|
||||
import { usePageState } from '@/store/page_sate.js';
|
||||
import { CommonUtils } from "@/util/commonUtils.js";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
},
|
||||
setup() {
|
||||
const pageState = usePageState();
|
||||
const router = useRoute();
|
||||
const state = reactive({
|
||||
search: '',
|
||||
refreshText: '',
|
||||
refreshSwitch: false,
|
||||
refreshSec: 20,
|
||||
refreshIntervalFuncList: [],
|
||||
optionValue: '',
|
||||
logText: '',
|
||||
drawer: false,
|
||||
tableData: [],
|
||||
total: CONSTANT.TOTAL,
|
||||
pageSize: pageState.siteConfigData.pagesize,
|
||||
currPage: CONSTANT.PAGE,
|
||||
});
|
||||
|
||||
const TransHtml = (raw) => {
|
||||
if (raw) {
|
||||
return raw.replace(/\n/g, '<br />')
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
const formatLogDisplayHtml = (scope) => {
|
||||
let content = TransHtml(scope.row.content);
|
||||
return content;
|
||||
}
|
||||
|
||||
const handPageChange = async (pageNum) => {
|
||||
state.currPage = pageNum;
|
||||
await queryListData(pageNum, state.pageSize);
|
||||
|
||||
}
|
||||
|
||||
const rowStyle = () => {
|
||||
return {
|
||||
'font-size': '13px',
|
||||
}
|
||||
}
|
||||
|
||||
const clickFreshSwitch = () => {
|
||||
if (state.refreshSwitch) {
|
||||
let flag = setInterval(async function () {
|
||||
await filterFunc();
|
||||
state.refreshText = `自动刷新于:${CommonUtils.getCurrentTimeStr()}`;
|
||||
}, state.refreshSec * 1000);
|
||||
state.refreshIntervalFuncList.push(flag);
|
||||
} else {
|
||||
state.refreshIntervalFuncList.forEach(intervalId => {
|
||||
clearInterval(intervalId);
|
||||
});
|
||||
state.refreshIntervalFuncList = [];
|
||||
state.refreshText = '';
|
||||
}
|
||||
}
|
||||
|
||||
const filterFunc = async () => {
|
||||
await queryListData(state.currPage, state.pageSize, state.search, state.optionValue);
|
||||
|
||||
}
|
||||
|
||||
const queryListData = async (page, size, name = '', query = '') => {
|
||||
let params = { page: page, size: size, text: name, query: query };
|
||||
const rsp = await request.get('/hostedmessages/list', { params: params });
|
||||
state.tableData = await rsp.data.data.lists;
|
||||
state.total = await rsp.data.data.total;
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
state.search = router.query.name;
|
||||
await queryListData(1, state.pageSize, router.query.name, router.query.taskid, router.query.query);
|
||||
});
|
||||
|
||||
return {
|
||||
...toRefs(state), TransHtml, clickFreshSwitch,
|
||||
rowStyle, handPageChange, filterFunc, copyToClipboard, formatLogDisplayHtml
|
||||
};
|
||||
}
|
||||
}
|
||||
</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; */
|
||||
}
|
||||
|
||||
.search-box {
|
||||
float: right;
|
||||
margin-top: -2px;
|
||||
}
|
||||
|
||||
.refresh-box {
|
||||
width: 80px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.refresh-time {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.pagination-block {
|
||||
margin-top: 15px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
}
|
||||
|
||||
.total-tip {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.search-input-sendways {
|
||||
width: 200px;
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
|
||||
.log-overflow {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 1;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
</style>
|
||||
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<div class="main-center-body">
|
||||
<div class="container">
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="6">
|
||||
<el-row :gutter="18">
|
||||
<el-col :span="4">
|
||||
<div class="statistic-card">
|
||||
<el-statistic :value="data.message_total_num">
|
||||
<template #title>
|
||||
@@ -13,7 +13,18 @@
|
||||
</el-statistic>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-col :span="5">
|
||||
<div class="statistic-card">
|
||||
<el-statistic :value="data.hosted_message_total_num">
|
||||
<template #title>
|
||||
<div style="display: inline-flex; align-items: center">
|
||||
托管消息数
|
||||
</div>
|
||||
</template>
|
||||
</el-statistic>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="5">
|
||||
<div class="statistic-card">
|
||||
<el-statistic :value="data.today_total_num">
|
||||
<template #title>
|
||||
@@ -24,7 +35,7 @@
|
||||
</el-statistic>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-col :span="5">
|
||||
<div class="statistic-card">
|
||||
<el-statistic :value="data.today_succ_num">
|
||||
<template #title>
|
||||
@@ -35,7 +46,7 @@
|
||||
</el-statistic>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-col :span="5">
|
||||
<div class="statistic-card">
|
||||
<el-statistic :value="data.today_failed_num" :value-style="formatFailedNumStyle()">
|
||||
<template #title>
|
||||
|
||||
Reference in New Issue
Block a user