Compare commits

...

1 Commits

Author SHA1 Message Date
wxc 1ef3b6b2cf 251014 2 months ago
  1. 2
      .env.prod
  2. BIN
      admin.zip
  3. 2
      index.html
  4. 19
      src/api/blackuser.js
  5. 12
      src/api/mail.js
  6. 22
      src/layout/Index.vue
  7. 12
      src/router/index.js
  8. 7
      src/util/request.js
  9. 189
      src/views/Blacklist.vue
  10. 40
      src/views/Home.vue
  11. 325
      src/views/Mail12345.vue
  12. 268
      src/views/MailEtl.vue
  13. 323
      src/views/MailPush.vue
  14. 2
      src/views/ManageMail.vue
  15. 4
      vite.config.js

2
.env.prod

@ -1,3 +1,3 @@
VITE_BASE=/admin
VITE_BASE=./
VITE_API_URL=/admin-api

BIN
admin.zip

Binary file not shown.

2
index.html

@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/police-icon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>长信箱 即接即办</title>
<title>长信箱 即接即办</title>
</head>
<body>
<div id="app"></div>

19
src/api/blackuser.js

@ -0,0 +1,19 @@
import { get, post, del} from "@/util/request"
export function listBlackuser(query) {
return get({
url: '/blackuser', query
})
}
export function addBlackuser(body) {
return post({
url: '/blackuser', body
})
}
export function delBlackuser(id) {
return del({
url: '/blackuser/' + id
})
}

12
src/api/mail.js

@ -5,3 +5,15 @@ export function listMail(query) {
url: '/mail/list', query
})
}
export function listMailPush(query) {
return get({
url: '/mail/push', query
})
}
export function pushMail(id) {
return post({
url: '/mail/push?mailId=' + id
})
}

22
src/layout/Index.vue

@ -2,7 +2,7 @@
<header class="flex v-center between header">
<div style="display: inline-flex;align-items: center;justify-content: center;height: 100%;">
<el-image src="/admin/police-icon.png" style="width: 40px;height: 40px;margin-right: 10px;"></el-image>
<div class="title"><a href="">长信箱 即接即办管理端</a></div>
<div class="title"><a href="">长信箱 即接即办管理端</a></div>
</div>
<div>
<el-button type="primary" @click="logout" style="--el-button-bg-color: #283AAC;--el-button-border-color: #586EFF;">
@ -16,18 +16,12 @@
<div class="flex">
<aside>
<nav>
<a class="flex v-center center wrap pointer" @click="go('/')" :active="activeUrl === '/'">
<el-icon><Message /></el-icon>
<span>12345投诉</span>
</a>
<a class="flex v-center center wrap pointer" @click="go('/mail')" :active="activeUrl === '/mail'">
<a class="flex v-center center wrap pointer" @click="go('/')" :active="activeUrl === '/mail'">
<el-icon><Message /></el-icon>
<span>信件查询</span>
</a>
<a class="flex v-center center wrap pointer" @click="go('/holiday')" :active="activeUrl === '/holiday'">
<el-icon><Calendar /></el-icon>
<span>节假日管理</span>
</a>
<a class="flex v-center center wrap pointer" @click="go('/admin')" :active="activeUrl === '/admin'">
<el-icon>
<User />
@ -40,10 +34,14 @@
</el-icon>
<span>用户管理</span>
</a>
<a class="flex v-center center wrap pointer" @click="router.push('/mail_etl')">
<a class="flex v-center center wrap pointer" @click="router.push('/mailPush')">
<el-icon><ChatDotSquare /></el-icon>
<span>信件推送查询</span>
</a>
<a class="flex v-center center wrap pointer" @click="router.push('/blacklist')">
<el-icon><Lock /></el-icon>
<span>黑名单管理</span>
</a>
</nav>
</aside>
<main><router-view /></main>
@ -51,7 +49,7 @@
</template>
<script setup>
import { HomeFilled, Platform, Menu, User,Message,Calendar,ChatDotSquare, Download } from '@element-plus/icons-vue'
import { HomeFilled, Platform, Menu, User,Message,Calendar,ChatDotSquare, Download, Lock } from '@element-plus/icons-vue'
import { useRouter } from "vue-router";
import { useTokenStore } from '../stores/useTokenStore';
import { request } from '../util/axios_config';

12
src/router/index.js

@ -15,10 +15,6 @@ const constantRoutes = [
children: [
{
path: '/',
component: () => import('@/views/Mail12345.vue'),
},
{
path: '/mail',
component: () => import('@/views/ManageMail.vue')
},
{
@ -34,8 +30,12 @@ const constantRoutes = [
component: () => import('@/components/HolidayList.vue')
},
{
path: '/mail_etl',
component: () => import('@/views/MailEtl.vue')
path: '/mailPush',
component: () => import('@/views/MailPush.vue')
},
{
path: '/blacklist',
component: () => import('@/views/Blacklist.vue')
}
]
},

7
src/util/request.js

@ -5,7 +5,7 @@ import {
} from 'element-plus'
import { getToken } from './token'
const BASE_PATH = '/admin-api'
const BASE_PATH = './admin-api'
export function get(options) {
options.method = 'GET';
return ajax(options.url, options)
@ -71,7 +71,7 @@ function ajax(url, options) {
let message = res.msg;
if (res.code === 401) {
if (url === '/admin/self') {
feedback.msgError('登录状态已过期')
ElMessage.error('登录状态已过期')
reject(res)
return
}
@ -80,7 +80,8 @@ function ajax(url, options) {
ElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '温馨提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
isRelogin = false;
// 调整登录
location.href = process.env.VITE_BASE + "#/login";
console.log(location)
location.href = location.href.replace(location.hash, '#login');
}).catch(() => {
isRelogin = false;
});

189
src/views/Blacklist.vue

@ -0,0 +1,189 @@
<template>
<div class="container">
<header class="mb-24">
<el-form :label-width="120">
<el-row>
<el-col :span="6">
<el-form-item label="姓名">
<el-input
placeholder="请输入"
v-model="query.contactName"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="身份证">
<el-input
placeholder="请输入"
v-model="query.contactIdCard"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div class="flex between">
<el-button type="primary" @click="handleAdd">新增</el-button>
<div>
<el-button type="primary" @click="getList">查询</el-button>
<el-button @click="reset">重置</el-button>
</div>
</div>
</header>
<div>
<el-table :data="list">
<el-table-column
prop="name"
label="姓名"
width="120"
/>
<el-table-column
prop="idCard"
label="身份证"
width="180"
/>
<el-table-column
prop="cause"
label="拉黑原因"
/>
<el-table-column
label="操作"
width="150"
>
<template #default="{ row }">
<el-button
type="danger"
link
@click="handleDel(row)"
size="small"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
<div class="flex mt-4 end">
<el-pagination
@size-change="getList"
@current-change="getList"
:current-page="query.current"
:page-sizes="[10, 20, 50]"
:page-size="query.size"
v-model:current-page="query.current"
:total="totalSize.total"
layout="total, sizes, prev, pager, next"
>
</el-pagination>
</div>
</div>
</div>
<el-dialog title="新增黑名单" v-model="show" width="600">
<el-form :model="form" label-width="120px">
<el-form-item label="姓名">
<el-input v-model="form.name" />
</el-form-item>
<el-form-item label="身份证">
<el-input v-model="form.idCard" />
</el-form-item>
<el-form-item label="拉黑原因">
<el-input v-model="form.cause" type="textarea" />
</el-form-item>
</el-form>
<div class="footer flex end">
<el-button type="primary" @click="submit">确定</el-button>
<el-button @click="show = false">取消</el-button>
</div>
</el-dialog>
</template>
<script setup>
import {
ElMessage,
ElMessageBox
} from 'element-plus'
import { listBlackuser, addBlackuser, delBlackuser } from "@/api/blackuser";
const query = ref({
current: 1,
size: 10,
});
const totalSize = ref({
total: 0,
});
const list = ref([]);
function getList() {
listBlackuser(query.value).then((data) => {
list.value = data.records;
totalSize.value.total = data.total;
});
}
function reset() {
query.value = {
current: 1,
size: 10,
};
getList();
}
getList();
const show = ref(false);
const form = ref({
})
function handleAdd() {
show.value = true;
}
function submit() {
addBlackuser(form.value).then(() => {
getList();
show.value = false;
form.value = {}
})
}
function handleDel(row) {
ElMessageBox.confirm('确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
delBlackuser(row.idCard).then(() => {
ElMessage.success('删除成功');
getList();
})
})
}
</script>
<style lang="scss" scoped>
.row {
display: flex;
padding: 10px 0;
.col {
width: 50%;
display: flex;
gap: 10px;
label {
width: 160px;
text-align: right;
color: #666;
+ * {
width: calc(100% - 170px);
}
}
span {
color: #333;
}
.content {
background: #EFF0F5;
padding: 8px 20px;
white-space: pre-wrap;
}
}
}
footer {
min-height: 20px;
}
</style>

40
src/views/Home.vue

@ -1,43 +1,5 @@
<template>
<div class="container">
<h1>首页</h1>
<h2>按钮</h2>
<el-row class="mb-4">
<el-button>Default</el-button>
<el-button type="primary">Primary</el-button>
<el-button type="success">Success</el-button>
<el-button type="info">Info</el-button>
<el-button type="warning">Warning</el-button>
<el-button type="danger">Danger</el-button>
</el-row>
<el-row class="mb-4">
<el-button plain>Plain</el-button>
<el-button type="primary" plain>Primary</el-button>
<el-button type="success" plain>Success</el-button>
<el-button type="info" plain>Info</el-button>
<el-button type="warning" plain>Warning</el-button>
<el-button type="danger" plain>Danger</el-button>
</el-row>
<el-row class="mb-4">
<el-button round>Round</el-button>
<el-button type="primary" round>Primary</el-button>
<el-button type="success" round>Success</el-button>
<el-button type="info" round>Info</el-button>
<el-button type="warning" round>Warning</el-button>
<el-button type="danger" round>Danger</el-button>
</el-row>
<el-row>
<el-button :icon="Search" circle />
<el-button type="primary" :icon="Edit" circle />
<el-button type="success" :icon="Check" circle />
<el-button type="info" :icon="Message" circle />
<el-button type="warning" :icon="Star" circle />
<el-button type="danger" :icon="Delete" circle />
</el-row>
</div>
</template>
<script setup>
import { useRouter } from "vue-router";

325
src/views/Mail12345.vue

@ -1,325 +0,0 @@
<template>
<div class="container">
<header class="mb-24">
<el-form :label-width="120">
<el-row>
<el-col :span="6">
<el-form-item label="编号">
<el-input placeholder="请输入" v-model="query.id" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="来源">
<el-input
placeholder="请输入"
v-model="query.source"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="来电时间">
<el-date-picker
type="datetimerange"
start-placeholder="开始时间"
end-placeholder="结束时间"
value-format="YYYY-MM-DD HH:mm:ss"
time-format="A hh:mm:ss"
v-model="query.phoneTime"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="市民姓名">
<el-input
placeholder="请输入"
v-model="query.contactName"
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="6">
<el-form-item label="来电电话">
<el-input
placeholder="请输入"
v-model="query.contactPhone"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="证件号码">
<el-input
placeholder="请输入"
v-model="query.contactIdCard"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="话务类型">
<el-input
placeholder="请输入"
v-model="query.contactType"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="案件类型">
<el-input
placeholder="请输入"
v-model="query.caseType"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div class="flex between">
<div>
<el-button type="primary" @click="addMailShow = true"
>新增12345投诉</el-button
>
<el-button type="primary" @click="importShow = true"
>信件导入</el-button
>
</div>
<div>
<el-button type="primary" @click="getList">查询</el-button>
<el-button @click="reset">重置</el-button>
</div>
</div>
</header>
<div>
<el-table :data="list">
<el-table-column prop="id" label="编号" width="220" />
<el-table-column prop="contactName" label="市民姓名" width="120" />
<el-table-column prop="contactPhone" label="来电电话" width="120" />
<el-table-column prop="contactIdCard" label="证件号码" width="180" />
<el-table-column
prop="content"
label="来话内容"
show-overflow-tooltip
/>
<el-table-column prop="contactType" label="话务类型" width="120" />
<el-table-column prop="source" label="来源" width="150" />
<el-table-column prop="caseType" label="案件类型" width="120" />
<el-table-column label="操作" width="120">
<template #default="{ row }">
<el-button
type="primary"
link
@click="handleMail(row)"
size="small"
>详情</el-button
>
</template>
</el-table-column>
</el-table>
<div class="flex mt-4 end">
<el-pagination
@size-change="getList"
@current-change="getList"
:current-page="query.current"
:page-sizes="[10, 20, 50]"
:page-size="query.size"
v-model:current-page="query.current"
:total="totalSize.total"
layout="total, sizes, prev, pager, next"
>
</el-pagination>
</div>
</div>
</div>
<AddMail
v-model="addMailShow"
@close="addMailShow = false"
@success="getList"
/>
<el-dialog width="1000px" title="12345投诉导入" v-model="importShow">
<header class="mb-20 flex gap">
<el-upload
:action="`${VITE_API_URL}/mail12345/analyzeExcel`"
:headers="{ Authorization: getToken() }"
accept="application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
:on-success="onAnalyzeExcelSuccess"
:show-file-list="false"
>
<template #trigger>
<el-button type="primary" plain>选择文件</el-button>
</template>
</el-upload>
<el-button type="primary" @click="downloadTemplate" plain
>下载模版</el-button
>
</header>
<el-table :data="importList" ref="importTable">
<el-table-column type="selection" width="55" />
<el-table-column prop="contactName" label="市民姓名" width="100" />
<el-table-column prop="contactPhone" label="来电电话" width="120" />
<el-table-column
prop="contactIdCard"
label="证件号码"
width="180"
/>
<el-table-column
prop="content"
label="来话内容"
show-overflow-tooltip
/>
<el-table-column prop="phoneTime" label="来电时间" />
<el-table-column label="数据是否正确" align="center">
<template #default="{ row }">
<span v-if="row.flag">正确</span>
<el-tooltip
class="box-item"
effect="dark"
:content="row.errMsg"
placement="top"
:raw-content="true"
v-else
>
<span class="text-danger">错误</span>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<footer class="flex end mt-20">
<el-button
type="primary"
@click="handleImport"
size="large"
:disabled="disabled"
>确认导入</el-button
>
</footer>
</el-dialog>
<el-dialog title="信件详情" v-model="showDetail">
<el-scrollbar max-height="600px" class="dialog-content">
<div class="row">
<div class="col-12 form-item">
<label>姓名</label>
<div>{{ activeRow.contactName }}</div>
</div>
</div>
<div class="row">
<div class="col-12 form-item">
<label>手机号</label>
<div>{{ activeRow.contactPhone }}</div>
</div>
<div class="col-12 form-item">
<label>身份证号码</label>
<div>{{ activeRow.contactIdCard }}</div>
</div>
</div>
<div class="form-item">
<label>内容</label>
<div class="content text-wrap">{{ activeRow.content }}</div>
</div>
</el-scrollbar>
<footer class="flex end mt-20">
<el-button @click="showDetail = false">关闭窗口</el-button>
</footer>
</el-dialog>
</template>
<script setup>
import AddMail from "@/components/AddMail.vue";
import { mail12345List, mail12345Import } from "@/api/mail12345";
import { getToken } from "@/util/token";
import { ElMessage } from "element-plus";
const { VITE_API_URL } = process.env;
const query = ref({
current: 1,
size: 10,
});
const totalSize = ref({
total: 0,
});
const list = ref([]);
const addMailShow = ref(false);
const importShow = ref(false);
function getList() {
if (query.value.phoneTime && query.value.phoneTime.length === 2) {
query.value.phoneTimeBegin = query.value.phoneTime[0];
query.value.phoneTimeEnd = query.value.phoneTime[1];
} else {
query.value.phoneTimeBegin = "";
query.value.phoneTimeEnd = "";
}
mail12345List(query.value).then((data) => {
list.value = data.records;
totalSize.value.total = data.total;
});
}
function reset() {
query.value = {
current: 1,
size: 10,
};
getList();
}
getList();
const importList = ref([]);
const importTable = ref();
function onAnalyzeExcelSuccess(response) {
console.log(response);
importList.value = response.data;
}
function downloadTemplate() {
location.href = `${VITE_API_URL}/file/download/template/12345投诉模版.xlsx`;
}
const disabled = ref(false);
function handleImport() {
const rows = importTable.value.getSelectionRows();
console.log(rows);
if (!rows.length) {
ElMessage.warning("请选择至少一条数据");
return;
}
disabled.value = true;
mail12345Import(rows).then(() => {
disabled.value = false;
ElMessage.success("导入成功");
getList();
importList.value = [];
importShow.value = false;
});
}
const showDetail = ref(false);
const activeRow = ref({})
function handleMail(row) {
showDetail.value = true;
activeRow.value = row
}
</script>
<style lang="scss" scoped>
.form-item {
display: flex;
line-height: 22px;
margin: 10px 0;
gap: 20px;
label {
width: 137px;
text-align: right;
}
div {
color: #333;
max-width: calc(100% - 137px);
}
.content {
background: #EFF0F5;
padding: 0 20px;
}
}
</style>

268
src/views/MailEtl.vue

@ -1,268 +0,0 @@
<template>
<div class="container">
<el-form :model="form" label-width="150px">
<el-row>
<el-col :span="6">
<el-form-item label="数据库名">
<el-select
v-model="MailTab"
placeholder="Select"
size="small"
style="width: 240px"
>
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="编号">
<el-input
v-model="form.id"
placeholder="请输入编号"
max-length="200px"
></el-input>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="信件编号">
<el-input
v-model="form.mailId"
placeholder="请输入信件编号"
></el-input>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="是否成功">
<el-input
v-model="form.success"
placeholder=""
></el-input>
</el-form-item>
</el-col>
</el-row>
<div class="flex end mb-24">
<el-button type="primary" @click="search" class="under-btn"
>搜索</el-button
>
<el-button type="default" @click="reset" class="under-btn"
>重置</el-button
>
</div>
</el-form>
<div class="table-box" ref="tableBoxHeight" v-loading="loading">
<el-table
:data="tableData"
border
:height="tableHeight"
table-layout="fixed"
:header-cell-style="{
'background-color': '#EBEEFC',
color: '#1D2C86',
}"
>
<el-table-column
prop="id"
label="编号"
width="80"
align="center"
>
</el-table-column>
<el-table-column
prop="mailId"
label="信件编号"
width="230"
show-overflow-tooltip
>
</el-table-column>
<el-table-column
prop="createTime"
label="创建日期"
width="120px"
/>
<el-table-column label="是否成功" width="90px" align="center">
<template #default="{ row }">
<el-tag type="success" v-if="row.success">成功</el-tag>
<el-tag type="danger" v-else>失败</el-tag>
</template>
</el-table-column>
<el-table-column
prop="errMsg"
label="错误信息"
show-overflow-tooltip
/>
<el-table-column width="120" label="操作">
<template #default="{ row }">
<el-popconfirm
title="确认删除?"
@confirm="handleDel(row.id)"
v-if="!row.success"
>
<template #reference>
<el-button
type="danger"
link
size="small"
>删除</el-button
>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
</div>
<div class="flex end mt-10">
<el-pagination
background
@size-change="handleSizeChange"
@current-change="handlePageChange"
:current-page="pageData.currentPage"
:page-sizes="[10, 20, 40, 50]"
:page-size="pageData.pageSize"
layout="total,sizes, prev, pager, next, jumper"
:total="pageData.totalSize"
>
</el-pagination>
</div>
</div>
</template>
<script setup>
import { request } from "@/util/axios_config";
import { getToken } from "@/util/token";
import { delMailEtl } from "@/api/mailEtl";
const MailTab = ref("mail_etl");
const { VITE_API_URL } = process.env;
const options = [
{
value: "mail_etl",
label: "mail_etl",
},
{
value: "mail_evaluate_etl",
label: "mail_evaluate_etl",
},
];
const loading = ref(true);
const form = ref({
id: "",
mailId: "",
success: "",
});
// tableDataaxios
const tableData = ref([]);
const pageData = ref({
currentPage: 1,
pageSize: 12,
totalSize: 0,
});
const tableBoxHeight = ref(null);
const tableHeight = ref("100%");
const flexColumnWidth = (label, prop) => {
const width = Math.max(label.length * 12, 120);
return `${width}px`;
};
const handleResponse = (response) => {
tableData.value = [];
if (MailTab.value == "mail_etl") {
console.log("aaaa");
tableData.value = response.data.mails;
} else {
console.log("bbbb");
tableData.value = response.data.evaMails;
}
tableData.value.forEach((item) => {
item.createTime = item.createTime.split("T")[0];
});
pageData.value.totalSize = response.data.pageSet.totalSize;
loading.value = false;
};
const makeRequest = (requestData, callback) => {
const data = JSON.stringify(requestData);
const url = VITE_API_URL + "/mailetl/list-submit";
request({
url: url,
method: "POST",
data: data,
headers: {
"Content-Type": "application/json",
authorization: getToken(),
},
})
.then(callback)
.catch(function (error) {
console.log(error);
});
};
const updateData = (requestData) => {
makeRequest(requestData, function (response) {
handleResponse(response);
});
};
onMounted(() => {
const requestData = {
formData: form.value,
selectData: MailTab.value,
pageData: pageData.value,
};
updateData(requestData);
});
const handleSizeChange = (size) => {
const requestData = {
formData: form.value,
selectData: MailTab.value,
pageData: pageData.value,
};
pageData.value.pageSize = size;
updateData(requestData);
};
const handlePageChange = (currentPage) => {
const requestData = {
formData: form.value,
selectData: MailTab.value,
pageData: pageData.value,
};
pageData.value.currentPage = currentPage;
updateData(requestData);
};
const search = () => {
const requestData = {
formData: form.value,
selectData: MailTab.value,
pageData: pageData.value,
};
updateData(requestData);
};
const reset = () => {
form.value = {
id: "",
mailId: "",
success: "",
};
}
async function handleDel(id) {
await delMailEtl(id)
search()
}
</script>

323
src/views/MailPush.vue

@ -0,0 +1,323 @@
<template>
<div class="container">
<header class="mb-24">
<el-form :label-width="120">
<el-row>
<el-col :span="6">
<el-form-item label="来信时间">
<el-date-picker
type="datetimerange"
start-placeholder="开始时间"
end-placeholder="结束时间"
value-format="YYYY-MM-DD HH:mm:ss"
time-format="A hh:mm:ss"
v-model="query.createTime"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="来信人姓名">
<el-input
placeholder="请输入"
v-model="query.contactName"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="来信人电话">
<el-input
placeholder="请输入"
v-model="query.contactPhone"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="来信人证件号码">
<el-input
placeholder="请输入"
v-model="query.contactIdCard"
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="6">
<el-form-item label="信件内容">
<el-input
placeholder="请输入"
v-model="query.content"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="评价结果">
<el-select v-model="query.satisfactionSms">
<el-option value="satisfied" label="非常满意" />
<el-option
value="basically_satisfied"
label="基本满意"
/>
<el-option
value="not_satisfied"
label="不满意"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div class="flex end">
<div>
<el-button type="primary" @click="getList">查询</el-button>
<el-button @click="reset">重置</el-button>
</div>
</div>
</header>
<div>
<el-table :data="list">
<el-table-column prop="id" label="编号" width="220" />
<el-table-column
prop="createTime"
label="来信时间"
width="180"
/>
<el-table-column
prop="contactName"
label="来信人姓名"
width="120"
/>
<el-table-column
prop="contactPhone"
label="来信人电话"
width="120"
/>
<el-table-column
prop="contactIdCard"
label="来信人证件号码"
width="180"
/>
<el-table-column
prop="content"
label="信件内容"
show-overflow-tooltip
/>
<el-table-column
prop="caseNumber"
label="案件编号"
width="120"
/>
<el-table-column
prop="involvedDeptName"
label="被投诉/涉及单位"
width="150"
/>
<el-table-column
label="评价结果"
width="150"
>
<template #default="{ row }">
<span>{{ getSatisfactionLabel(row.satisfactionSms) }}</span>
</template>
</el-table-column>
<el-table-column
label="操作"
width="150"
>
<template #default="{ row }">
<el-button
type="primary"
link
@click="handleMail(row)"
size="small"
>详情</el-button
>
<el-button
type="primary"
link
@click="handlePushMail(row)"
size="small"
>推送信件</el-button
>
</template>
</el-table-column>
</el-table>
<div class="flex mt-4 end">
<el-pagination
@size-change="getList"
@current-change="getList"
:current-page="query.current"
:page-sizes="[10, 20, 50]"
:page-size="query.size"
v-model:current-page="query.current"
:total="totalSize.total"
layout="total, sizes, prev, pager, next"
>
</el-pagination>
</div>
</div>
</div>
<el-dialog title="信件详情" v-model="show">
<div class="row">
<div class="col">
<label>信件编号</label>
<span>{{ activeRow.id }}</span>
</div>
<div class="col">
<label>来信时间</label>
<span>{{ activeRow.createTime }}</span>
</div>
</div>
<div class="row">
<div class="col">
<label>来信人姓名</label>
<span>{{ activeRow.contactName }}</span>
</div>
<div class="col">
<label>来信人电话</label>
<span>{{ activeRow.contactPhone }}</span>
</div>
</div>
<div class="row">
<div class="col">
<label>证件号码</label>
<span>{{ activeRow.contactIdCard }}</span>
</div>
</div>
<div class="row">
<div class="col" style="width: 100%">
<label>信件内容</label>
<div class="content">{{ activeRow.content }}</div>
</div>
</div>
<div class="row">
<div class="col">
<label>案件编号</label>
<span>{{ activeRow.caseNumber }}</span>
</div>
<div class="col">
<label>被投诉/举报单位</label>
<span>{{ activeRow.involvedDeptName }}</span>
</div>
</div>
<div class="row" v-if="activeRow.attachments">
<div class="col" style="width: 100%">
<label>附件</label>
<div class="flex gap wrap attachments" v-if="JSON.parse(activeRow.attachments).length">
<img v-for="(item, index) in JSON.parse(activeRow.attachments)" :key="index" :src="`./admin-api/file/stream/${item.filepath}`" alt="" @click="open(`./admin-api/file/stream/${item.filepath}`)">
</div>
<el-empty description="无附件" v-else />
</div>
</div>
<footer></footer>
</el-dialog>
</template>
<script setup>
import {
ElMessage,
ElMessageBox
} from 'element-plus'
import { listMailPush, pushMail } from "@/api/mail";
const query = ref({
current: 1,
size: 10,
});
const totalSize = ref({
total: 0,
});
const list = ref([]);
function getList() {
listMailPush(query.value).then((data) => {
list.value = data.records;
totalSize.value.total = data.total;
});
}
function reset() {
query.value = {
current: 1,
size: 10,
};
getList();
}
getList();
function getSatisfactionLabel(satisfaction) {
if (satisfaction === "satisfied") {
return "非常满意";
} else if (satisfaction === "not_satisfied") {
return "不满意";
} else if (satisfaction === "basically_satisfied") {
return "基本满意";
} else {
return "暂无评价";
}
}
const show = ref(false)
const activeRow = ref({})
function handleMail(row) {
activeRow.value = row
show.value = true
}
function open(url) {
window.open(url)
}
function handlePushMail(row) {
ElMessageBox.confirm('确定要推送信件?', '温馨提示').then(() => {
pushMail(row.id).then(() => {
getList()
});
}).catch(() => {
});
}
</script>
<style lang="scss" scoped>
.row {
display: flex;
padding: 10px 0;
.col {
width: 50%;
display: flex;
gap: 10px;
label {
width: 160px;
text-align: right;
color: #666;
+ * {
width: calc(100% - 170px);
}
}
span {
color: #333;
}
.content {
background: #EFF0F5;
padding: 8px 20px;
white-space: pre-wrap;
}
}
}
.attachments {
img {
max-width: 160px;
max-height: 300px;
border: 1px solid transparent;
&:hover {
cursor: pointer;
border-color: red;
}
}
}
footer {
min-height: 20px;
}
</style>

2
src/views/ManageMail.vue

@ -198,7 +198,7 @@
<div class="col" style="width: 100%">
<label>附件</label>
<div class="flex gap wrap attachments" v-if="JSON.parse(activeRow.attachments).length">
<img v-for="(item, index) in JSON.parse(activeRow.attachments)" :key="index" :src="`https://jzxx.hncsga.cn/api/file/stream/${item.filepath}`" alt="" @click="open(`https://jzxx.hncsga.cn/api/file/stream/${item.filepath}`)">
<img v-for="(item, index) in JSON.parse(activeRow.attachments)" :key="index" :src="`./admin-api/file/stream/${item.filepath}`" alt="" @click="open(`./admin-api/file/stream/${item.filepath}`)">
</div>
<el-empty description="无附件" v-else />
</div>

4
vite.config.js

@ -11,12 +11,12 @@ import svgLoader from 'vite-svg-loader'
export default ({ mode }) => {
const env = loadEnv(mode, process.cwd());
return defineConfig({
base: env.VITE_BASE,
base: './',
define: {
'process.env': env
},
plugins: [
vue(),
vue(),
svgLoader(),
AutoImport({
imports: [

Loading…
Cancel
Save