Browse Source

Merge remote-tracking branch 'origin/dev' into dev

dev-V1.10.2-temp
zhuibobo 4 months ago
parent
commit
a5e36a1b01
  1. 74
      zdxt-web-client/zdxt-admin-plus-ui/src/views/nos/legalTech.vue
  2. 11
      zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/carouselBanner/add.vue
  3. 2
      zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/carouselBanner/detail.vue
  4. 10
      zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/carouselBanner/draft.vue
  5. 11
      zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/carouselBanner/edit.vue
  6. 11
      zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/carouselBanner/index.vue
  7. 12
      zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/educationServices/add.vue
  8. 2
      zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/educationServices/detail.vue
  9. 12
      zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/educationServices/draft.vue
  10. 10
      zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/educationServices/edit.vue
  11. 6
      zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/educationServices/index.vue
  12. 12
      zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/educationServices/repost.vue
  13. 12
      zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/noticeInfo/add.vue
  14. 10
      zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/noticeInfo/draft.vue
  15. 14
      zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/noticeInfo/edit.vue
  16. 8
      zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/noticeInfo/index.vue
  17. 11
      zdxt-web-client/zdxt-efcode-enforcement-app/src/components/FooterBar.vue
  18. 64
      zdxt-web-client/zdxt-efcode-enforcement-app/src/components/enforcement/register/EnforcementInfoSection.vue
  19. 17
      zdxt-web-client/zdxt-efcode-enforcement-app/src/store/messageState.js
  20. 45
      zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/enforce/enforcementNoticeList.vue
  21. 88
      zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/law/lawServiceDetail.vue
  22. 27
      zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/law/lawServiceList.vue
  23. 45
      zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/message/enforcementEvaluateList.vue
  24. 97
      zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/message/messageCenter.vue

74
zdxt-web-client/zdxt-admin-plus-ui/src/views/nos/legalTech.vue

@ -4,20 +4,14 @@
<div class="search-panel">
<el-form :model="searchForm" inline>
<el-form-item label="时间筛选:">
<el-date-picker
v-model="searchForm.timeRange"
type="datetimerange"
range-separator="至"
start-placeholder="开始时间"
end-placeholder="截止时间"
class="date-picker"
format="YYYY-MM-DD HH:mm"
value-format="YYYY-MM-DD HH:mm:ss"
/>
<el-date-picker v-model="searchForm.timeRange" type="datetimerange" range-separator="至"
start-placeholder="开始时间" end-placeholder="截止时间" class="date-picker" format="YYYY-MM-DD HH:mm"
value-format="YYYY-MM-DD HH:mm:ss" />
</el-form-item>
<el-form-item label="执法单位:">
<el-input v-model="searchForm.lawEnforcementAgency" placeholder="请输入关键字" class="search-input" clearable @keyup.enter="handleSearch" />
<el-input v-model="searchForm.lawEnforcementAgency" placeholder="请输入关键字" class="search-input" clearable
@keyup.enter="handleSearch" />
</el-form-item>
<el-form-item>
@ -28,19 +22,27 @@
<el-button @click="handleReset">重置</el-button>
</el-form-item>
</el-form>
<el-button type="primary" @click="handleAdd">新增</el-button>
</div>
<div class="action-bar">
<div class="action-left">
<el-button type="primary" @click="handleAdd">新增</el-button>
</div>
</div>
<!-- 数据表格 -->
<div class="table-container">
<el-table v-loading="loading" :data="tableData" border :header-cell-style="{ backgroundColor: '#f5f7fa', fontWeight: 'bold' }">
<el-table v-loading="loading" :data="tableData" border
:header-cell-style="{ backgroundColor: '#f5f7fa', fontWeight: 'bold' }">
<el-table-column prop="lawEnforcementAgency" label="执法单位" min-width="160" show-overflow-tooltip />
<el-table-column label="法制材料" min-width="200">
<template #default="{ row }">
<div v-if="row.legalMaterials" class="file-cell">
<el-icon class="file-icon"><Paperclip /></el-icon>
<span class="file-name" :title="extractFileName(row.legalMaterials)">{{ extractFileName(row.legalMaterials) }}</span>
<el-icon class="file-icon">
<Paperclip />
</el-icon>
<span class="file-name" :title="extractFileName(row.legalMaterials)">{{
extractFileName(row.legalMaterials) }}</span>
<el-button size="small" @click="downloadFile(row.legalMaterials)">下载</el-button>
</div>
<span v-else>--</span>
@ -50,8 +52,11 @@
<el-table-column label="技术材料" min-width="200">
<template #default="{ row }">
<div v-if="row.technicalMaterials" class="file-cell">
<el-icon class="file-icon"><Paperclip /></el-icon>
<span class="file-name" :title="extractFileName(row.technicalMaterials)">{{ extractFileName(row.technicalMaterials) }}</span>
<el-icon class="file-icon">
<Paperclip />
</el-icon>
<span class="file-name" :title="extractFileName(row.technicalMaterials)">{{
extractFileName(row.technicalMaterials) }}</span>
<el-button size="small" @click="downloadFile(row.technicalMaterials)">下载</el-button>
</div>
<span v-else>--</span>
@ -75,15 +80,9 @@
<!-- 分页 -->
<div class="pagination-container">
<span class="total-text">共 {{ total }} 项数据</span>
<el-pagination
v-model:current-page="currentPage"
v-model:page-size="pageSize"
:total="total"
:page-sizes="[10, 20, 50, 100]"
layout="prev, pager, next, jumper, ->, total, sizes"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
<el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize" :total="total"
:page-sizes="[10, 20, 50, 100]" layout="prev, pager, next, jumper, ->, total, sizes"
@size-change="handleSizeChange" @current-change="handleCurrentChange" />
</div>
</div>
</template>
@ -119,6 +118,9 @@ const formatDateTime = (time?: string) => {
const BASE_API = import.meta.env.VITE_APP_BASE_API || '';
const FILE_SERVER_PREFIX = import.meta.env.VITE_APP_FILE_SERVER_PREFIX || '';
onMounted(() => {
getList();
});
const isOssId = (val: string) => /^[0-9]+$/.test(val.trim());
const toRelativeFilePath = (val: string) => {
@ -247,9 +249,6 @@ const handleCurrentChange = (val: number) => {
getList();
};
onMounted(() => {
getList();
});
</script>
<style scoped>
@ -284,6 +283,21 @@ onMounted(() => {
.date-picker {
width: 360px;
}
.action-bar {
display: flex;
justify-content: space-between;
align-items: center;
background: #fff;
padding: 12px 20px;
border-radius: 8px;
margin-bottom: 16px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
.action-left {
display: flex;
gap: 8px;
}
.table-container {
background: #fff;

11
zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/carouselBanner/add.vue

@ -70,10 +70,12 @@ import { getCurrentInstance, onMounted, reactive, ref } from 'vue';
import type { ComponentInternalInstance } from 'vue';
import type { FormRules, UploadRequestOptions } from 'element-plus';
import { ElForm, ElMessage } from 'element-plus';
import { useRoute } from 'vue-router';
import { addCarouselBanner } from '@/api/supervision/carouselBanner';
import { getDicts } from '@/api/system/dict/data';
import request from '@/utils/request';
const route = useRoute();
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const formRef = ref<InstanceType<typeof ElForm>>();
const submitting = ref(false);
@ -158,7 +160,7 @@ const removeImage = () => {
};
const handleCancel = () => {
proxy?.$tab.closePage();
proxy?.$tab.closeOpenPage({ path: '/general-manage/supervision-carouselBanner' });
};
const submitForm = async (status: number, successMessage: string) => {
@ -181,7 +183,10 @@ const submitForm = async (status: number, successMessage: string) => {
});
if (res.code === 200) {
ElMessage.success(successMessage);
proxy?.$tab.closePage();
const targetPath = route.query.from === 'draft'
? '/supervision/carouselBanner/draft'
: '/general-manage/supervision-carouselBanner';
proxy?.$tab.closeOpenPage({ path: targetPath });
} else {
ElMessage.error(res.msg || '操作失败');
}
@ -320,7 +325,7 @@ onMounted(() => {
.preview-image img {
width: 100%;
height: 100%;
object-fit: cover;
/* object-fit: cover; */
}
.remove-btn {

2
zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/carouselBanner/detail.vue

@ -106,7 +106,7 @@ const loadDetail = async () => {
};
const handleBack = () => {
proxy?.$tab.closePage();
proxy?.$tab.closeOpenPage({ path: '/general-manage/supervision-carouselBanner' });
};
const handleEdit = () => {

10
zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/carouselBanner/draft.vue

@ -74,8 +74,8 @@
</el-table-column>
<el-table-column label="操作" width="160" fixed="right">
<template #default="scope">
<el-button size="small" type="text" @click="handleEdit(scope.row)">编辑</el-button>
<el-button size="small" type="text" class="delete-btn" @click="handleDelete(scope.row)">删除</el-button>
<el-button size="small" text type="primary" @click="handleEdit(scope.row)">编辑</el-button>
<el-button size="small" text type="primary" class="delete-btn" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
@ -170,11 +170,11 @@ const handleReset = () => {
};
const handleAdd = () => {
router.push('/supervision/carouselBanner/add');
router.push('/supervision/carouselBanner/add?from=draft');
};
const handleBack = () => {
proxy?.$tab.closePage();
proxy?.$tab.closeOpenPage({ path: '/general-manage/supervision-carouselBanner'});
};
const handleBatchDelete = () => {
@ -204,7 +204,7 @@ const handleSelectionChange = (selection: CarouselBannerVo[]) => {
};
const handleEdit = (row: CarouselBannerVo) => {
router.push(`/supervision/carouselBanner/edit/${row.id}`);
router.push(`/supervision/carouselBanner/edit/${row.id}?from=draft`);
};
const handleDelete = async (row: CarouselBannerVo) => {

11
zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/carouselBanner/edit.vue

@ -164,7 +164,10 @@ const removeImage = () => {
};
const handleCancel = () => {
proxy?.$tab.closePage();
const targetPath = route.query.from === 'draft'
? '/supervision/carouselBanner/draft'
: '/general-manage/supervision-carouselBanner';
proxy?.$tab.closeOpenPage({ path: targetPath });
};
const submitForm = async (status: number, successMessage: string) => {
@ -182,9 +185,9 @@ const submitForm = async (status: number, successMessage: string) => {
displayDays: form.displayDays,
linkUrl: form.linkUrl,
imageUrl: form.imageUrl,
status,
// status,
type: form.type,
isDelete: 0
// isDelete: status === 2 ? 0 : 1
});
if (res.code === 200) {
ElMessage.success(successMessage);
@ -363,7 +366,7 @@ onMounted(async () => {
.preview-image img {
width: 100%;
height: 100%;
object-fit: cover;
/* object-fit: cover; */
}
.remove-btn {

11
zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/carouselBanner/index.vue

@ -94,17 +94,18 @@
</el-table-column>
<el-table-column label="操作" width="260" fixed="right">
<template #default="scope">
<el-button size="small" type="text" @click="handleView(scope.row)">查看</el-button>
<el-button size="small" type="text" @click="handleEdit(scope.row)">编辑</el-button>
<el-button size="small" text type="primary" @click="handleView(scope.row)">查看</el-button>
<el-button size="small" text type="primary" @click="handleEdit(scope.row)">编辑</el-button>
<el-button
size="small"
type="text"
text
type="primary"
:class="scope.row.status === 2 ? 'offline-btn' : 'online-btn'"
@click="handleStatusChange(scope.row)"
>
{{ scope.row.status === 2 ? '下架' : '上架' }}
</el-button>
<el-button size="small" type="text" class="delete-btn" @click="handleDelete(scope.row)">删除</el-button>
<el-button size="small" text type="primary" class="delete-btn" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
@ -278,7 +279,7 @@ const handleStatusChange = (row: CarouselBannerVo) => {
imageUrl: row.imageUrl,
status: newStatus,
type: row.type ?? 1,
isDelete: 0
// isDelete: newStatus === 2 ? 0 : 1
});
if (res.code === 200) {
ElMessage.success(`${actionText}成功`);

12
zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/educationServices/add.vue

@ -100,6 +100,7 @@ import type { UploadFile, UploadRequestOptions, UploadUserFile } from 'element-p
import { ElMessage, ElForm, FormRules } from 'element-plus';
import { QuillEditor } from '@vueup/vue-quill';
import '@vueup/vue-quill/dist/vue-quill.snow.css';
import { useRoute } from 'vue-router';
import {
addEducationServices,
listPublishDeptOptions,
@ -118,6 +119,7 @@ interface AttachmentItem {
uploadPersonName: string;
}
const route = useRoute();
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const userStore = useUserStore();
const formRef = ref<InstanceType<typeof ElForm>>();
@ -199,7 +201,10 @@ const submitForm = async (status: number, successMessage: string) => {
const res: any = await addEducationServices(buildPayload(status));
if (res.code === 200) {
ElMessage.success(successMessage);
proxy?.$tab.closePage();
const targetPath = route.query.from === 'draft'
? '/supervision/educationServices/draft'
: '/general-manage/enforcementcode-educationServices';
proxy?.$tab.closeOpenPage({ path: targetPath });
} else {
ElMessage.error(res.msg || '操作失败');
}
@ -236,7 +241,10 @@ const handlePreview = () => {
};
const handleCancel = () => {
proxy?.$tab.closePage();
const targetPath = route.query.from === 'draft'
? '/supervision/educationServices/draft'
: '/general-manage/enforcementcode-educationServices';
proxy?.$tab.closeOpenPage({ path: targetPath });
};
const handleSaveDraft = () => {

2
zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/educationServices/detail.vue

@ -123,7 +123,7 @@ const loadDetail = async () => {
};
const handleBack = () => {
proxy?.$tab.closePage();
proxy?.$tab.closeOpenPage({ path: '/general-manage/enforcementcode-educationServices' });
};
onMounted(() => {

12
zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/educationServices/draft.vue

@ -103,8 +103,8 @@
<el-table-column label="操作" width="160" fixed="right">
<template #default="scope">
<el-button size="small" type="text" @click="handleEdit(scope.row)">编辑</el-button>
<el-button size="small" type="text" class="delete-btn" @click="handleDelete(scope.row)">删除</el-button>
<el-button size="small" text type="primary" @click="handleEdit(scope.row)">编辑</el-button>
<el-button size="small" text type="primary" class="delete-btn" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
@ -243,15 +243,15 @@ const loadDictOptions = async () => {
};
const handleAdd = () => {
router.push('/supervision/educationServices/add');
router.push('/supervision/educationServices/add?from=draft');
};
const handleRepost = () => {
router.push('/supervision/educationServices/repost');
router.push('/supervision/educationServices/repost?from=draft');
};
const handleBack = () => {
proxy?.$tab.closePage();
proxy?.$tab.closeOpenPage({ path: '/general-manage/enforcementcode-educationServices' });
};
const handleBatchDelete = () => {
@ -281,7 +281,7 @@ const handleSelectionChange = (selection: any[]) => {
};
const handleEdit = (row: any) => {
router.push(`/supervision/educationServices/edit/${row.id}`);
router.push(`/supervision/educationServices/edit/${row.id}?from=draft`);
};
const handleDelete = async (row: any) => {

10
zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/educationServices/edit.vue

@ -227,7 +227,10 @@ const submitForm = async (status: number, successMessage: string) => {
const res: any = await editEducationServices(buildPayload(status));
if (res.code === 200) {
ElMessage.success(successMessage);
proxy?.$tab.closePage();
const targetPath = route.query.from === 'draft'
? '/supervision/educationServices/draft'
: '/general-manage/enforcementcode-educationServices';
proxy?.$tab.closeOpenPage({ path: targetPath });
} else {
ElMessage.error(res.msg || '操作失败');
}
@ -272,7 +275,10 @@ const handlePreview = () => {
};
const handleCancel = () => {
proxy?.$tab.closePage();
const targetPath = route.query.from === 'draft'
? '/supervision/educationServices/draft'
: '/general-manage/enforcementcode-educationServices';
proxy?.$tab.closeOpenPage({ path: targetPath });
};
const handleSaveDraft = () => {

6
zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/educationServices/index.vue

@ -92,9 +92,9 @@
<el-table-column label="操作" width="240" fixed="right">
<template #default="scope">
<el-button size="small" type="text" @click="handleEdit(scope.row)">编辑</el-button>
<el-button size="small" type="text" @click="handleView(scope.row)">查看</el-button>
<el-button size="small" type="text" class="delete-btn" @click="handleDelete(scope.row)">删除</el-button>
<el-button size="small" text type="primary" @click="handleEdit(scope.row)">编辑</el-button>
<el-button size="small" text type="primary" @click="handleView(scope.row)">查看</el-button>
<el-button size="small" text type="primary" class="delete-btn" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>

12
zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/educationServices/repost.vue

@ -52,6 +52,7 @@
import { getCurrentInstance, onMounted, reactive, ref } from 'vue';
import type { ComponentInternalInstance } from 'vue';
import { ElMessage, ElForm, FormRules } from 'element-plus';
import { useRoute } from 'vue-router';
import {
addEducationServices,
listPublishDeptOptions,
@ -59,6 +60,7 @@ import {
} from '@/api/supervision/educationServices';
import { getDicts } from '@/api/system/dict/data';
const route = useRoute();
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const formRef = ref<InstanceType<typeof ElForm>>();
const contentTypeOptions = ref<{ label: string; value: number }[]>([]);
@ -96,7 +98,10 @@ const submitForm = async (status: number, successMessage: string) => {
const res: any = await addEducationServices(buildPayload(status));
if (res.code === 200) {
ElMessage.success(successMessage);
proxy?.$tab.closePage();
const targetPath = route.query.from === 'draft'
? '/supervision/educationServices/draft'
: '/general-manage/enforcementcode-educationServices';
proxy?.$tab.closeOpenPage({ path: targetPath });
} else {
ElMessage.error(res.msg || '操作失败');
}
@ -115,7 +120,10 @@ const handlePreview = () => {
};
const handleCancel = () => {
proxy?.$tab.closePage();
const targetPath = route.query.from === 'draft'
? '/supervision/educationServices/draft'
: '/general-manage/enforcementcode-educationServices';
proxy?.$tab.closeOpenPage({ path: targetPath });
};
const handleSaveDraft = () => {

12
zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/noticeInfo/add.vue

@ -49,8 +49,10 @@ import { getCurrentInstance, reactive, ref } from 'vue';
import type { ComponentInternalInstance } from 'vue';
import type { FormRules } from 'element-plus';
import { ElForm, ElMessage } from 'element-plus';
import { useRoute } from 'vue-router';
import { addNoticeInfo } from '@/api/supervision/noticeInfo';
const route = useRoute();
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const formRef = ref<InstanceType<typeof ElForm>>();
const submitting = ref(false);
@ -92,7 +94,10 @@ const submitForm = async (status: number, successMessage: string) => {
});
if (res.code === 200) {
ElMessage.success(successMessage);
proxy?.$tab.closePage();
const targetPath = route.query.from === 'draft'
? '/supervision/noticeInfo/draft'
: '/general-manage/supervision-noticeInfo';
proxy?.$tab.closeOpenPage({ path: targetPath });
} else {
ElMessage.error(res.msg || '操作失败');
}
@ -105,7 +110,10 @@ const submitForm = async (status: number, successMessage: string) => {
};
const handleCancel = () => {
proxy?.$tab.closePage();
const targetPath = route.query.from === 'draft'
? '/supervision/noticeInfo/draft'
: '/general-manage/supervision-noticeInfo';
proxy?.$tab.closeOpenPage({ path: targetPath });
};
const handleSaveDraft = () => {

10
zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/noticeInfo/draft.vue

@ -69,8 +69,8 @@
<el-table-column prop="targetPlatformLabel" label="内容发布到" width="140" show-overflow-tooltip />
<el-table-column label="操作" width="160" fixed="right">
<template #default="scope">
<el-button size="small" type="text" @click="handleEdit(scope.row)">编辑</el-button>
<el-button size="small" type="text" class="delete-btn" @click="handleDelete(scope.row)">删除</el-button>
<el-button size="small" text type="primary" @click="handleEdit(scope.row)">编辑</el-button>
<el-button size="small" text type="primary" class="delete-btn" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
@ -165,11 +165,11 @@ const handleReset = () => {
};
const handleAdd = () => {
router.push('/supervision/noticeInfo/add');
router.push('/supervision/noticeInfo/add?from=draft');
};
const handleBack = () => {
proxy?.$tab.closePage();
proxy?.$tab.closeOpenPage({ path: '/general-manage/supervision-noticeInfo' });
};
const handleBatchDelete = () => {
@ -199,7 +199,7 @@ const handleSelectionChange = (selection: NoticeInfoVo[]) => {
};
const handleEdit = (row: NoticeInfoVo) => {
router.push(`/supervision/noticeInfo/edit/${row.id}`);
router.push(`/supervision/noticeInfo/edit/${row.id}?from=draft`);
};
const handleDelete = async (row: NoticeInfoVo) => {

14
zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/noticeInfo/edit.vue

@ -95,12 +95,15 @@ const submitForm = async (status: number, successMessage: string) => {
targetPlatform: form.targetPlatform,
displayDays: form.displayDays,
publishTime: form.publishTime,
status,
isDelete: 0
// status,
// isDelete: status === 2 ? 0 : 1
});
if (res.code === 200) {
ElMessage.success(successMessage);
proxy?.$tab.closePage();
const targetPath = route.query.from === 'draft'
? '/supervision/noticeInfo/draft'
: '/general-manage/supervision-noticeInfo';
proxy?.$tab.closeOpenPage({ path: targetPath });
} else {
ElMessage.error(res.msg || '操作失败');
}
@ -113,7 +116,10 @@ const submitForm = async (status: number, successMessage: string) => {
};
const handleCancel = () => {
proxy?.$tab.closePage();
const targetPath = route.query.from === 'draft'
? '/supervision/noticeInfo/draft'
: '/general-manage/supervision-noticeInfo';
proxy?.$tab.closeOpenPage({ path: targetPath });
};
const handleSaveDraft = () => {

8
zdxt-web-client/zdxt-admin-plus-ui/src/views/supervision/noticeInfo/index.vue

@ -87,14 +87,14 @@
<template #default="scope">
<el-button
size="small"
type="text"
text type="primary"
:class="scope.row.status === 2 ? 'offline-btn' : 'online-btn'"
@click="handleStatusChange(scope.row)"
>
{{ scope.row.status === 2 ? '下架' : '上架' }}
</el-button>
<el-button size="small" type="text" @click="handleEdit(scope.row)">编辑</el-button>
<el-button size="small" type="text" class="delete-btn" @click="handleDelete(scope.row)">删除</el-button>
<el-button size="small" text type="primary" @click="handleEdit(scope.row)">编辑</el-button>
<el-button size="small" text type="primary" class="delete-btn" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
@ -265,7 +265,7 @@ const handleStatusChange = (row: NoticeInfoVo) => {
displayDays: row.displayDays,
publishTime: row.publishTime,
status: newStatus,
isDelete: 0
// isDelete: newStatus === 2 ? 0 : 1
});
if (res.code === 200) {
ElMessage.success(`${actionText}成功`);

11
zdxt-web-client/zdxt-efcode-enforcement-app/src/components/FooterBar.vue

@ -20,6 +20,7 @@ import { onMounted } from 'vue';
import { getMessageUnreadCount } from '@/api/enforcement/index';
import nosIcon from '@/assets/images/nos/off_site_bottom_icon.png';
import tabBarBg from '@/assets/images/nos/tab_bar_bg.png';
import { messageUnread, setMessageStats } from '@/store/messageState';
const props = defineProps({
active: {
@ -30,8 +31,6 @@ const props = defineProps({
const router = useRouter();
const messageUnread = ref(0);
const tabs = [
{
key: 'home', label: '首页', route: '/enforcement/enforcementHome',
@ -64,16 +63,16 @@ const onTabClick = (item) => {
if (item.key === props.active) return;
if (router.currentRoute.value.path !== item.route) {
router.replace(item.route);
}
fetchMessageUnreadCount();
}
// console.log('获取消息未读数量2222');
// fetchMessageUnreadCount();
};
// ========== 获取消息未读数量 ==========
const fetchMessageUnreadCount = () => {
getMessageUnreadCount({}, (res) => {
if (res && res.code === 200 && res.data) {
const totalCount = Number(res.data.totalCount) || 0;
messageUnread.value = totalCount;
setMessageStats(res.data);
}
}, () => {
// 接口调用失败不处理

64
zdxt-web-client/zdxt-efcode-enforcement-app/src/components/enforcement/register/EnforcementInfoSection.vue

@ -93,18 +93,19 @@
<div v-if="!formData.isNewJoint" class="union-list-container">
<van-loading v-if="unionLoading" size="20" />
<div v-else-if="unionList.length === 0" class="empty-tip">暂无联合执法数据</div>
<div v-else class="union-list">
<div
<van-radio-group v-else v-model="formData.uniteCheck" direction="vertical" class="union-list" @change="onUnionChange">
<van-radio
v-for="item in unionList"
:key="item.id"
:name="String(item.id)"
class="union-item"
:class="{ active: formData.uniteCheck === item.id }"
@click="selectUnion(item)"
>
<div class="union-item-title">{{ item.bureauDeptName || '联合执法' }}</div>
<div class="union-item-desc">{{ item.deptTexts || item.lawText || '' }}</div>
</div>
</div>
<div class="union-item-content">
<div class="union-item-title">{{ item.bureauDeptName || '联合执法' }}</div>
<div class="union-item-desc">{{ item.deptTexts || item.lawText || '' }}</div>
</div>
</van-radio>
</van-radio-group>
</div>
</div>
<!-- 隐藏字段用于验证联合执法 -->
@ -198,7 +199,7 @@ const unionList = ref([]);
const unionLoading = ref(false);
onMounted(() => {
const range = getEnforcementTimeDateRange(10);
const range = getEnforcementTimeDateRange(7);
minDate.value = range.minDate;
maxDate.value = range.maxDate;
defaultPickerValue = range.currentDate;
@ -224,6 +225,7 @@ const fetchUnionList = () => {
unionLoading.value = false;
if (res && res.data) {
unionList.value = res.data;
console.log('联合执法列表:', unionList.value);
}
}, (err) => {
unionLoading.value = false;
@ -232,8 +234,20 @@ const fetchUnionList = () => {
};
const selectUnion = (item) => {
props.formData.unionNo = item.unionNo || '';
props.formData.uniteCheck = item.id || '';
if (props.formData.uniteCheck === item.id) {
props.formData.unionNo = '';
props.formData.uniteCheck = '';
} else {
props.formData.unionNo = item.unionNo || '';
props.formData.uniteCheck = item.id || '';
}
};
const onUnionChange = (id) => {
const item = unionList.value.find(item => String(item.id) === id);
if (item) {
props.formData.unionNo = item.unionNo || '';
}
};
const openTimePicker = () => {
@ -462,6 +476,7 @@ const onAfterReadImage = (file) => {
display: flex;
flex-direction: column;
gap: 0.16rem;
padding: 0;
}
.union-item {
@ -472,24 +487,23 @@ const onAfterReadImage = (file) => {
transition: all 0.2s;
&:active {
transform: scale(0.98);
background: #f5f5f5;
}
&.active {
border-color: #1367fe;
background: rgba(19, 103, 254, 0.05);
}
.union-item-content {
flex: 1;
.union-item-title {
font-size: 14px;
color: #333;
font-weight: 500;
}
.union-item-title {
font-size: 14px;
color: #333;
font-weight: 500;
}
.union-item-desc {
font-size: 12px;
color: #999;
margin-top: 0.08rem;
.union-item-desc {
font-size: 12px;
color: #999;
margin-top: 0.08rem;
}
}
}
}

17
zdxt-web-client/zdxt-efcode-enforcement-app/src/store/messageState.js

@ -6,6 +6,12 @@ import { ref, computed } from 'vue';
* - 消息中心页面负责写入;其他页面仅读取用于 footer-bar 角标展示
*/
export const messageUnread = ref(0);
export const pffwCount = ref(0); // 普法服务未读数量
export const zfpjcount = ref(0); // 执法评价未读数量
export const zfygCount = ref(0); // 执法预告未读数量
export const jhtzcount = ref(0); // 计划通知未读数量
export const zfywCount = ref(0); // 执法任务未读数量
export const zfyyCount = ref(0); // 执法预约未读数量
/** 格式化为角标展示值(0 显示空) */
export const messageUnreadBadge = computed(() => (messageUnread.value > 0 ? messageUnread.value : ''));
@ -15,6 +21,17 @@ export const setMessageUnread = (count) => {
messageUnread.value = Number(count) || 0;
};
/** 设置所有消息数量 */
export const setMessageStats = (data) => {
pffwCount.value = Number(data.pffwCount) || 0;
zfpjcount.value = Number(data.zfpjcount) || 0;
zfygCount.value = Number(data.zfygCount) || 0;
jhtzcount.value = Number(data.jhtzcount) || 0;
zfywCount.value = Number(data.zfywCount) || 0;
zfyyCount.value = Number(data.zfyyCount) || 0;
messageUnread.value = Number(data.totalCount) || 0;
};
// 占位 default 导出:src/store 目录会被 globalStore.js 通过 import.meta.glob
// 以 { import: 'default' } 的方式扫描,缺少 default 会触发
// "does not provide an export named 'default'" 错误。

45
zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/enforce/enforcementNoticeList.vue

@ -13,6 +13,14 @@
</template> -->
</van-nav-bar>
<!-- 搜索栏 -->
<van-search v-model="searchText" show-action placeholder="请输入关键字查询" clearable clear-trigger="always"
@clear="onClear" @search="onSearch">
<template #action>
<div @click="onSearch">搜索</div>
</template>
</van-search>
<!-- 列表区域 -->
<div class="list-container">
<van-pull-refresh v-model="refreshing" @refresh="onRefresh">
@ -68,6 +76,7 @@ const finished = ref(false);
const refreshing = ref(false);
const pageNum = ref(1);
const pageSize = ref(10);
const searchText = ref('');
// ========== 加载数据 ==========
const fetchList = () => {
@ -75,6 +84,9 @@ const fetchList = () => {
pageNum: pageNum.value,
pageSize: pageSize.value,
};
if (searchText.value) {
params.searchValue = searchText.value;
}
getLawNoticeList(params, (res) => {
if (res.code === 200) {
const rows = res.rows || res.data?.rows || res.data?.list || res.data || [];
@ -127,6 +139,21 @@ const onClickLeft = () => {
router.back();
};
// ========== 搜索 ==========
const onSearch = () => {
pageNum.value = 1;
list.value = [];
finished.value = false;
loading.value = true;
fetchList();
};
// ========== 清空搜索 ==========
const onClear = () => {
searchText.value = '';
onSearch();
};
// ========== 筛选点击 ==========
const onFilterClick = () => {
showToast('筛选功能开发中');
@ -256,4 +283,22 @@ const onFeedback = (item) => {
}
}
}
/* ===== Vant 搜索框样式覆盖 ===== */
:deep(.van-search__content) {
height: 0.9rem;
border: 1px solid #ececec;
border-radius: 0.15rem 0 0 0.15rem;
}
:deep(.van-search__action) {
margin: 0 3% 0 0;
width: 10%;
height: 0.9rem;
background: #1367fe;
border: 0.01rem solid #1367fe;
border-radius: 0 0.15rem 0.15rem 0;
color: #fff;
text-align: center;
line-height: 0.9rem;
}
</style>

88
zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/law/lawServiceDetail.vue

@ -24,8 +24,8 @@
<span class="detail-time">{{ detail.time }}</span>
</div>
<!-- 文本内容 (contentType == 1) -->
<template v-if="detail.contentType !== 2">
<!-- 文本内容 (sourceType == 1) -->
<template v-if="detail.sourceType== 1">
<!-- 正文 -->
<div class="detail-body" v-html="detail.content"></div>
@ -41,15 +41,21 @@
</div>
</template>
<!-- 链接内容 (contentType == 2) -->
<!-- 链接内容 (sourceType == 2) -->
<template v-else>
<div class="detail-iframe-wrap">
<iframe
:src="detail.content"
:src="detail.forwardUrl"
class="detail-iframe"
frameborder="0"
sandbox="allow-scripts allow-same-origin allow-forms"
@load="onIframeLoad"
@error="onIframeError"
></iframe>
<div class="copy-link-btn" @click="copyLink">
<van-icon name="link-o" size="16" />
<span>复制链接</span>
</div>
</div>
</template>
</div>
@ -62,7 +68,8 @@ import { useRouter, useRoute } from 'vue-router';
import { showToast, showImagePreview } from 'vant';
import 'vant/es/toast/style';
import 'vant/es/image-preview/style';
import { getEducationServicesDetail } from '@/api/enforcement';
import { getEducationServicesDetail, getMessageUnreadCount } from '@/api/enforcement';
import { setMessageStats } from '@/store/messageState';
const router = useRouter();
const route = useRoute();
@ -76,6 +83,7 @@ const detail = ref({
contentType: 1, // 1: 文本详情, 2: 超链接
content: [],
images: [],
forwardUrl: '',
});
const loading = ref(false);
@ -101,9 +109,12 @@ const fetchDetail = () => {
source: res.data.source || '',
time: res.data.time || '',
contentType: res.data.contentType || 1, // 1: 文本详情, 2: 超链接
sourceType: res.data.sourceType || 1,
content: res.data.content || '',
images: res.data.images || [],
forwardUrl: res.data.forwardUrl || res.data.content || '',
};
fetchMessageUnreadCount();
} else {
showToast(res.message || '获取详情失败');
}
@ -135,6 +146,48 @@ const onSearchClick = () => {
showToast('搜索功能开发中');
};
// ========== 获取消息未读数量 ==========
const fetchMessageUnreadCount = () => {
getMessageUnreadCount({}, (res) => {
if (res && res.code === 200 && res.data) {
setMessageStats(res.data);
}
}, () => {
// 接口调用失败不处理
});
};
// ========== iframe加载成功 ==========
const onIframeLoad = () => {
console.log('iframe加载成功');
};
// ========== iframe加载失败 ==========
const onIframeError = () => {
showToast('页面加载失败,可复制链接到浏览器打开');
};
// ========== 复制链接 ==========
const copyLink = async () => {
const url = detail.value.forwardUrl || '';
if (!url) {
showToast('暂无链接');
return;
}
try {
await navigator.clipboard.writeText(url);
showToast('复制成功');
} catch (err) {
const textarea = document.createElement('textarea');
textarea.value = url;
document.body.appendChild(textarea);
textarea.select();
document.execCommand('copy');
document.body.removeChild(textarea);
showToast('复制成功');
}
};
// ========== 预览图片 ==========
const previewImage = (index) => {
showImagePreview({
@ -274,6 +327,7 @@ const previewImage = (index) => {
border-radius: 0.15rem;
overflow: hidden;
background: #f5f5f5;
position: relative;
}
.detail-iframe {
@ -281,4 +335,28 @@ const previewImage = (index) => {
height: 500px;
background: #fff;
}
.copy-link-btn {
position: absolute;
bottom: 0.3rem;
right: 0.3rem;
display: flex;
align-items: center;
gap: 0.1rem;
padding: 0.15rem 0.3rem;
background: rgba(0, 0, 0, 0.6);
color: #fff;
font-size: 0.28rem;
border-radius: 0.2rem;
cursor: pointer;
z-index: 10;
:deep(.van-icon) {
color: #fff;
}
&:active {
background: rgba(0, 0, 0, 0.8);
}
}
</style>

27
zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/law/lawServiceList.vue

@ -13,6 +13,14 @@
</template> -->
</van-nav-bar>
<!-- 搜索栏 -->
<van-search v-model="searchText" show-action placeholder="请输入关键字查询" clearable clear-trigger="always"
@clear="onClear" @search="onSearch">
<template #action>
<div @click="onSearch">搜索</div>
</template>
</van-search>
<!-- 列表区域 -->
<div class="list-container">
<van-pull-refresh v-model="refreshing" @refresh="onRefresh">
@ -77,6 +85,7 @@ const refreshing = ref(false);
const pageNum = ref(1);
const pageSize = ref(10);
const isFetching = ref(false); // 防重复请求标志位
const searchText = ref('');
// ========== 格式化时间 ==========
const formatTime = (val) => {
@ -109,6 +118,9 @@ const fetchList = () => {
pageNum: pageNum.value,
pageSize: pageSize.value,
};
if (searchText.value) {
params.searchValue = searchText.value;
}
getEducationServicesList(params, (res) => {
if (res.code === 200) {
const rows = res.rows || res.data?.rows || [];
@ -163,6 +175,21 @@ const onClickLeft = () => {
router.back();
};
// ========== 搜索 ==========
const onSearch = () => {
pageNum.value = 1;
list.value = [];
finished.value = false;
loading.value = true;
fetchList();
};
// ========== 清空搜索 ==========
const onClear = () => {
searchText.value = '';
onSearch();
};
// ========== 筛选点击 ==========
const onFilterClick = () => {
showToast('筛选功能开发中');

45
zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/message/enforcementEvaluateList.vue

@ -4,6 +4,14 @@
<van-nav-bar title="执法评价" left-text="返回" left-arrow @click-left="onClickLeft">
</van-nav-bar>
<!-- 搜索栏 -->
<van-search v-model="searchText" show-action placeholder="请输入关键字查询" clearable clear-trigger="always"
@clear="onClear" @search="onSearch">
<template #action>
<div @click="onSearch">搜索</div>
</template>
</van-search>
<!-- 列表区域 -->
<div class="list-container">
<van-pull-refresh v-model="refreshing" @refresh="onRefresh">
@ -71,6 +79,7 @@ const finished = ref(false);
const refreshing = ref(false);
const pageNum = ref(1);
const pageSize = ref(10);
const searchText = ref('');
// ========== 获取状态文本 ==========
const getStatusText = (status) => {
@ -99,6 +108,9 @@ const fetchList = () => {
pageSize: pageSize.value,
hasEvaluate: 1,
};
if (searchText.value) {
params.searchValue = searchText.value;
}
queryEvaluateList(params, (res) => {
if (res.code === 200) {
const rows = res.rows || res.data?.rows || res.data?.list || res.data || [];
@ -146,6 +158,21 @@ const onRefresh = () => {
fetchList();
};
// ========== 搜索 ==========
const onSearch = () => {
pageNum.value = 1;
list.value = [];
finished.value = false;
loading.value = true;
fetchList();
};
// ========== 清空搜索 ==========
const onClear = () => {
searchText.value = '';
onSearch();
};
// ========== 跳转详情页面 ==========
const toDetail = (item) => {
router.push({
@ -287,4 +314,22 @@ onMounted(() => {
:deep(.van-empty) {
padding: 60px 0;
}
/* ===== Vant 搜索框样式覆盖 ===== */
:deep(.van-search__content) {
height: 0.9rem;
border: 1px solid #ececec;
border-radius: 0.15rem 0 0 0.15rem;
}
:deep(.van-search__action) {
margin: 0 3% 0 0;
width: 10%;
height: 0.9rem;
background: #1367fe;
border: 0.01rem solid #1367fe;
border-radius: 0 0.15rem 0.15rem 0;
color: #fff;
text-align: center;
line-height: 0.9rem;
}
</style>

97
zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/message/messageCenter.vue

@ -71,12 +71,13 @@
</template>
<script setup name="messageCenter">
import { ref, computed, onMounted } from 'vue';
import { ref, computed, onMounted, watch } from 'vue';
import { useRouter, useRoute } from 'vue-router';
import { showToast } from 'vant';
import 'vant/es/toast/style';
import FooterBar from '@/components/FooterBar.vue';
import { getMessageUnreadCount } from '@/api/enforcement/index';
import { pffwCount, zfpjcount, zfygCount, jhtzcount, zfywCount, zfyyCount, setMessageStats } from '@/store/messageState';
const router = useRouter();
const route = useRoute();
@ -100,31 +101,11 @@ const todoRefreshing = ref(false);
const todoPageNum = ref(1);
const todoPageSize = ref(10);
// ========== 消息统计数据 ==========
const messageStats = ref({
pffwCount: 0, // 普法服务未读数量
zfpjcount: 0, // 执法评价未读数量
zfygCount: 0, // 执法预告未读数量
totalCount: 0, // 未读总数
});
// 未读总数(tabbar 角标)
const totalUnread = computed(() => {
const messageUnread = messageList.value.reduce((sum, item) => sum + (item.unreadCount || 0), 0);
const todoUnread = todoList.value.reduce((sum, item) => sum + (item.unreadCount || 0), 0);
return messageUnread + todoUnread;
});
// ========== 获取消息未读数量 ==========
const fetchMessageStats = () => {
getMessageUnreadCount({}, (res) => {
if (res && res.code === 200 && res.data) {
messageStats.value = {
pffwCount: Number(res.data.pffwCount) || 0, // 普法服务未读数量
zfpjcount: Number(res.data.zfpjcount) || 0, // 执法评价未读数量
zfygCount: Number(res.data.zfygCount) || 0, // 执法预告未读数量
totalCount: Number(res.data.totalCount) || 0, // 总未读数量
};
setMessageStats(res.data);
initMessageList();
initTodoList();
}
@ -143,7 +124,7 @@ const initMessageList = () => {
time: '',
icon: 'law',
iconBg: 'icon-blue',
unreadCount: messageStats.value.pffwCount,
unreadCount: pffwCount.value,
},{
id: 3,
title: '执法评价',
@ -151,7 +132,7 @@ const initMessageList = () => {
time: '',
icon: 'law',
iconBg: 'icon-blue',
unreadCount: messageStats.value.zfpjcount,
unreadCount: zfpjcount.value,
},{
id: 4,
title: '非现场执法评价',
@ -159,7 +140,7 @@ const initMessageList = () => {
time: '',
icon: 'law',
iconBg: 'icon-blue',
unreadCount: messageStats.value.zfpjcount,
unreadCount: zfpjcount.value,
},{
id: 2,
title: '计划通知',
@ -167,7 +148,7 @@ const initMessageList = () => {
time: '',
icon: 'law',
iconBg: 'icon-blue',
unreadCount: messageStats.value.jhtzcount,
unreadCount: jhtzcount.value,
},
];
};
@ -182,7 +163,7 @@ const initTodoList = () => {
time: '',
icon: 'check',
iconBg: 'icon-red',
unreadCount: messageStats.value.zfygCount,
unreadCount: zfygCount.value,
},
{
id: 102,
@ -191,7 +172,7 @@ const initTodoList = () => {
time: '',
icon: 'check',
iconBg: 'icon-red',
unreadCount: messageStats.value.zfygCount,
unreadCount: zfywCount.value,
},
{
id: 103,
@ -200,7 +181,7 @@ const initTodoList = () => {
time: '',
icon: 'check',
iconBg: 'icon-red',
unreadCount: messageStats.value.zfygCount,
unreadCount: zfyyCount.value,
},
];
};
@ -217,7 +198,34 @@ const fetchMessageList = () => {
time: '2026-04-15 10:07',
icon: 'law',
iconBg: 'icon-blue',
unreadCount: messageStats.value.pffwCount,
unreadCount: pffwCount.value,
},
{
id: 3,
title: '执法评价',
desc: zfpjcount.value > 0 ? `您有${zfpjcount.value}条执法评价,请及时查看` : '暂无执法评价',
time: '2026-04-15 10:07',
icon: 'law',
iconBg: 'icon-blue',
unreadCount: zfpjcount.value,
},
{
id: 4,
title: '非现场执法评价',
desc: zfpjcount.value > 0 ? `您有${zfpjcount.value}条非现场执法评价,请及时查看` : '暂无非现场执法评价',
time: '2026-04-15 10:07',
icon: 'law',
iconBg: 'icon-blue',
unreadCount: zfpjcount.value,
},
{
id: 2,
title: '计划通知',
desc: jhtzcount.value > 0 ? `您有${jhtzcount.value}条计划通知,请及时查看` : '暂无计划通知',
time: '2026-04-15 10:07',
icon: 'law',
iconBg: 'icon-blue',
unreadCount: jhtzcount.value,
},
];
messageRefreshing.value = false;
@ -235,11 +243,29 @@ const fetchTodoList = () => {
{
id: 101,
title: '执法预告',
desc: messageStats.value.zfygCount > 0 ? `您有${messageStats.value.zfygCount}条执法预告,请及时查看` : '暂无执法预告',
desc: zfygCount.value > 0 ? `您有${zfygCount.value}条执法预告,请及时查看` : '暂无执法预告',
time: '2026-04-15 09:30',
icon: 'check',
iconBg: 'icon-red',
unreadCount: messageStats.value.zfygCount,
unreadCount: zfygCount.value,
},
{
id: 102,
title: '执法任务',
desc: zfywCount.value > 0 ? `您有${zfywCount.value}条执法任务,请及时查看` : '暂无执法任务',
time: '2026-04-15 09:30',
icon: 'check',
iconBg: 'icon-red',
unreadCount: zfywCount.value,
},
{
id: 103,
title: '执法预约',
desc: zfyyCount.value > 0 ? `您有${zfyyCount.value}条执法预约,请及时查看` : '暂无执法预约',
time: '2026-04-15 09:30',
icon: 'check',
iconBg: 'icon-red',
unreadCount: zfyyCount.value,
},
];
todoRefreshing.value = false;
@ -335,6 +361,11 @@ const onTodoClick = (item) => {
}
};
watch([pffwCount, zfpjcount, zfygCount, jhtzcount, zfywCount, zfyyCount], () => {
initMessageList();
initTodoList();
});
onMounted(() => {
const returnTab = sessionStorage.getItem('messageReturnTab');
if (returnTab === '1') {
@ -351,8 +382,6 @@ onMounted(() => {
activeTab.value = 0;
}
}
initMessageList();
initTodoList();
fetchMessageStats();
});
</script>

Loading…
Cancel
Save