添加后端接口修改前端及小程序
This commit is contained in:
@@ -1,7 +1,11 @@
|
||||
<template>
|
||||
<a-layout style="min-height: 100vh">
|
||||
<!-- 侧边栏 -->
|
||||
<a-layout-sider v-model:collapsed="collapsed" collapsible>
|
||||
<a-layout style="min-height: 100vh; display: flex;">
|
||||
<!-- 侧边栏 - 固定 -->
|
||||
<a-layout-sider
|
||||
v-model:collapsed="collapsed"
|
||||
collapsible
|
||||
:style="{ position: 'fixed', left: 0, top: 0, bottom: 0, height: '100vh', overflow: 'auto', zIndex: 10 }"
|
||||
>
|
||||
<div class="logo">
|
||||
<h2 v-if="!collapsed">政府管理系统</h2>
|
||||
<h2 v-else>政府</h2>
|
||||
@@ -9,17 +13,22 @@
|
||||
<Sidebar />
|
||||
</a-layout-sider>
|
||||
|
||||
<!-- 主内容区 -->
|
||||
<a-layout>
|
||||
<!-- 主内容区 - 可滚动 -->
|
||||
<a-layout
|
||||
:style="{ marginLeft: collapsed ? '80px' : '200px', width: 'calc(100% - ' + (collapsed ? '80px' : '200px') + ')' }"
|
||||
class="main-content-wrapper"
|
||||
>
|
||||
<!-- 头部 -->
|
||||
<a-layout-header style="background: #fff; padding: 0 16px; display: flex; justify-content: space-between; align-items: center">
|
||||
<a-layout-header
|
||||
style="background: #fff; padding: 0 16px; display: flex; justify-content: space-between; align-items: center; position: sticky; top: 0; zIndex: 5; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1)"
|
||||
>
|
||||
<div>
|
||||
<menu-unfold-outlined
|
||||
<MenuUnfoldOutlined
|
||||
v-if="collapsed"
|
||||
class="trigger"
|
||||
@click="() => (collapsed = !collapsed)"
|
||||
/>
|
||||
<menu-fold-outlined
|
||||
<MenuFoldOutlined
|
||||
v-else
|
||||
class="trigger"
|
||||
@click="() => (collapsed = !collapsed)"
|
||||
@@ -48,15 +57,15 @@
|
||||
</div>
|
||||
</a-layout-header>
|
||||
|
||||
<!-- 内容区 -->
|
||||
<a-layout-content style="margin: 16px">
|
||||
<!-- 内容区 - 可滚动 -->
|
||||
<a-layout-content style="margin: 16px; padding-bottom: 24px; overflow-y: auto; max-height: calc(100vh - 136px)">
|
||||
<div :style="{ padding: '24px', background: '#fff', minHeight: '360px' }">
|
||||
<router-view />
|
||||
</div>
|
||||
</a-layout-content>
|
||||
|
||||
<!-- 底部 -->
|
||||
<a-layout-footer style="text-align: center">
|
||||
<a-layout-footer style="text-align: center; position: sticky; bottom: 0; background: #fff">
|
||||
政府端后台管理系统 ©2024
|
||||
</a-layout-footer>
|
||||
</a-layout>
|
||||
@@ -118,4 +127,31 @@ const handleLogout = () => {
|
||||
gap: 8px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.main-content-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
/* 隐藏滚动条但保持滚动功能 */
|
||||
.ant-layout-content::-webkit-scrollbar {
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.ant-layout-content::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.ant-layout-content::-webkit-scrollbar-thumb {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/* 兼容Firefox */
|
||||
.ant-layout-content {
|
||||
scrollbar-width: none;
|
||||
-ms-overflow-style: none;
|
||||
}
|
||||
</style>
|
||||
@@ -41,7 +41,7 @@
|
||||
</a-menu-item>
|
||||
|
||||
<!-- 智慧仓库 -->
|
||||
<a-sub-menu key="smart-warehouse">
|
||||
<a-sub-menu key="/smart-warehouse">
|
||||
<template #icon><HddOutlined /></template>
|
||||
<template #title>
|
||||
<span>智慧仓库</span>
|
||||
@@ -58,7 +58,7 @@
|
||||
</a-sub-menu>
|
||||
|
||||
<!-- 屠宰无害化 -->
|
||||
<a-sub-menu key="slaughter">
|
||||
<a-sub-menu key="/slaughter">
|
||||
<template #icon><SafetyOutlined /></template>
|
||||
<template #title>
|
||||
<span>屠宰无害化</span>
|
||||
@@ -72,43 +72,43 @@
|
||||
</a-sub-menu>
|
||||
|
||||
<!-- 无纸化防疫 -->
|
||||
<a-sub-menu key="paperless-epidemic">
|
||||
<a-sub-menu key="/paperless/epidemic">
|
||||
<template #icon><FileTextOutlined /></template>
|
||||
<template #title>
|
||||
<span>无纸化防疫</span>
|
||||
</template>
|
||||
<!-- <a-menu-item key="paperless/epidemic"><span>防疫首页</span></a-menu-item> -->
|
||||
<a-menu-item key="paperless/epidemic/epidemic-agency"><span>防疫机构管理</span></a-menu-item>
|
||||
<a-menu-item key="paperless/epidemic/epidemic-record"><span>防疫记录</span></a-menu-item>
|
||||
<a-menu-item key="paperless/epidemic/vaccine-management"><span>疫苗管理</span></a-menu-item>
|
||||
<a-menu-item key="paperless/epidemic/epidemic-activity"><span>防疫活动管理</span></a-menu-item>
|
||||
<a-menu-item key="/paperless/epidemic/epidemic-agency"><span>防疫机构管理</span></a-menu-item>
|
||||
<a-menu-item key="/paperless/epidemic/epidemic-record"><span>防疫记录</span></a-menu-item>
|
||||
<a-menu-item key="/paperless/epidemic/vaccine-management"><span>疫苗管理</span></a-menu-item>
|
||||
<a-menu-item key="/paperless/epidemic/epidemic-activity"><span>防疫活动管理</span></a-menu-item>
|
||||
</a-sub-menu>
|
||||
|
||||
<!-- 无纸化检疫 -->
|
||||
<a-sub-menu key="paperless-quarantine">
|
||||
<a-sub-menu key="/paperless/quarantine">
|
||||
<template #icon><SafetyOutlined /></template>
|
||||
<template #title>
|
||||
<span>无纸化检疫</span>
|
||||
</template>
|
||||
<a-menu-item key="paperless/quarantine/declaration"><span>检疫审批</span></a-menu-item>
|
||||
<a-menu-item key="paperless/quarantine/record-query"><span>检疫证查询</span></a-menu-item>
|
||||
<a-menu-item key="paperless/quarantine/config"><span>检疫站清单</span></a-menu-item>
|
||||
<a-menu-item key="/paperless/quarantine/declaration"><span>检疫审批</span></a-menu-item>
|
||||
<a-menu-item key="/paperless/quarantine/record-query"><span>检疫证查询</span></a-menu-item>
|
||||
<a-menu-item key="/paperless/quarantine/config"><span>检疫站清单</span></a-menu-item>
|
||||
</a-sub-menu>
|
||||
|
||||
<!-- 生资认证 -->
|
||||
<a-menu-item key="examine/index">
|
||||
<a-menu-item key="/examine/index">
|
||||
<template #icon><CheckCircleOutlined /></template>
|
||||
<span>生资认证</span>
|
||||
</a-menu-item>
|
||||
|
||||
<!-- 养牛学院 -->
|
||||
<a-menu-item key="academy">
|
||||
<a-menu-item key="/academy">
|
||||
<template #icon><BookOutlined /></template>
|
||||
<span>养牛学院</span>
|
||||
</a-menu-item>
|
||||
|
||||
<!-- 设备预警 -->
|
||||
<a-menu-item key="device-alert">
|
||||
<a-menu-item key="/device-alert">
|
||||
<template #icon><ExclamationCircleOutlined /></template>
|
||||
<span>设备预警</span>
|
||||
</a-menu-item>
|
||||
@@ -132,9 +132,7 @@ const openKeys = ref([])
|
||||
// 处理菜单选择
|
||||
const handleMenuSelect = ({ key }) => {
|
||||
if (key) {
|
||||
// 确保使用绝对路径进行路由跳转
|
||||
const absolutePath = key.startsWith('/') ? key : `/${key}`
|
||||
router.replace(absolutePath)
|
||||
router.replace(key)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,10 +34,10 @@ const routes = [
|
||||
name: 'Login',
|
||||
component: Login
|
||||
},
|
||||
{
|
||||
{
|
||||
path: '/',
|
||||
component: Layout,
|
||||
redirect: '/dashboard',
|
||||
redirect: '/index/data_center',
|
||||
children: [
|
||||
{
|
||||
path: 'dashboard',
|
||||
@@ -130,7 +130,7 @@ const routes = [
|
||||
{
|
||||
path: 'paperless/epidemic/epidemic-agency',
|
||||
name: 'EpidemicAgencyManagement',
|
||||
component: () => import('@/views/paperless/epidemic/epidemic-agency/EpidemicAgencyManagement.vue'),
|
||||
component: () => import('@/views/paperless/epidemic/epidemic-agency/EpidemicAgency.vue'),
|
||||
meta: { title: '防疫机构管理' }
|
||||
},
|
||||
{
|
||||
|
||||
18
government-admin/src/router/testRoutes.js
Normal file
18
government-admin/src/router/testRoutes.js
Normal file
@@ -0,0 +1,18 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory('/test/'),
|
||||
routes: [
|
||||
{
|
||||
path: '/',
|
||||
redirect: '/test'
|
||||
},
|
||||
{
|
||||
path: '/test',
|
||||
name: 'TestPage',
|
||||
component: { template: '<div>测试页面</div>' }
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
export default router
|
||||
@@ -3,6 +3,7 @@ import { computed, ref } from 'vue'
|
||||
import { defineStore } from 'pinia'
|
||||
import { message } from 'ant-design-vue'
|
||||
import router from '@/router'
|
||||
import api from '@/utils/api'
|
||||
|
||||
// 认证状态管理
|
||||
// 管理用户的登录、登出和认证信息
|
||||
@@ -37,36 +38,37 @@ export const useAuthStore = defineStore('auth', () => {
|
||||
// 登录方法
|
||||
const login = async (credentials) => {
|
||||
try {
|
||||
// 在实际应用中,这里应该调用后端API进行登录验证
|
||||
// 现在使用模拟数据模拟登录成功
|
||||
// 调用后端登录接口
|
||||
const response = await api.auth.login(credentials)
|
||||
|
||||
// 模拟API调用延迟
|
||||
await new Promise(resolve => setTimeout(resolve, 500))
|
||||
|
||||
// 模拟登录成功数据
|
||||
const mockToken = 'mock-jwt-token-' + Date.now()
|
||||
const mockUserInfo = {
|
||||
id: '1',
|
||||
username: credentials.username,
|
||||
name: '管理员',
|
||||
avatar: '',
|
||||
role: 'admin',
|
||||
department: '信息管理处'
|
||||
if (response.code === 200) {
|
||||
// 保存token
|
||||
const token = response.data.token
|
||||
setToken(token)
|
||||
|
||||
// 获取用户信息
|
||||
const userInfoResponse = await api.auth.getUserInfo()
|
||||
if (userInfoResponse.code === 200) {
|
||||
const userInfoData = userInfoResponse.data
|
||||
setUserInfo(userInfoData)
|
||||
setPermissions(userInfoData.permissions || [])
|
||||
|
||||
// 如果勾选了记住我,保存更长时间
|
||||
if (credentials.remember) {
|
||||
// 在实际应用中,这里可以设置更长的过期时间
|
||||
// 这里简化处理
|
||||
}
|
||||
|
||||
message.success('登录成功')
|
||||
return true
|
||||
} else {
|
||||
message.error(userInfoResponse.message || '获取用户信息失败')
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
message.error(response.message || '登录失败')
|
||||
return false
|
||||
}
|
||||
const mockPermissions = ['view', 'add', 'edit', 'delete', 'export']
|
||||
|
||||
// 保存登录信息
|
||||
setToken(mockToken)
|
||||
setUserInfo(mockUserInfo)
|
||||
setPermissions(mockPermissions)
|
||||
|
||||
// 如果勾选了记住我,保存更长时间
|
||||
if (credentials.remember) {
|
||||
// 在实际应用中,这里可以设置更长的过期时间
|
||||
// 这里简化处理
|
||||
}
|
||||
|
||||
return true
|
||||
} catch (error) {
|
||||
console.error('登录失败:', error)
|
||||
message.error(error.message || '登录失败,请重试')
|
||||
@@ -75,14 +77,25 @@ export const useAuthStore = defineStore('auth', () => {
|
||||
}
|
||||
|
||||
// 退出登录
|
||||
const logout = () => {
|
||||
token.value = null
|
||||
userInfo.value = {}
|
||||
permissions.value = []
|
||||
localStorage.removeItem('token')
|
||||
localStorage.removeItem('userInfo')
|
||||
localStorage.removeItem('permissions')
|
||||
router.push('/login')
|
||||
const logout = async () => {
|
||||
try {
|
||||
// 调用后端退出登录接口
|
||||
await api.auth.logout()
|
||||
} catch (error) {
|
||||
console.error('退出登录API调用失败:', error)
|
||||
// 即使API调用失败,仍然清除本地数据并跳转到登录页
|
||||
} finally {
|
||||
// 清除本地存储的用户信息
|
||||
token.value = null
|
||||
userInfo.value = {}
|
||||
permissions.value = []
|
||||
localStorage.removeItem('token')
|
||||
localStorage.removeItem('userInfo')
|
||||
localStorage.removeItem('permissions')
|
||||
|
||||
// 跳转到登录页面
|
||||
router.push('/login')
|
||||
}
|
||||
}
|
||||
|
||||
// 检查用户是否有特定权限
|
||||
|
||||
45
government-admin/src/test-main.js
Normal file
45
government-admin/src/test-main.js
Normal file
@@ -0,0 +1,45 @@
|
||||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
import testRouter from './router/testRoutes.js'
|
||||
import { createPinia } from 'pinia'
|
||||
import Antd from 'ant-design-vue'
|
||||
import { ConfigProvider } from 'ant-design-vue'
|
||||
import 'ant-design-vue/dist/reset.css'
|
||||
import dayjs from 'dayjs'
|
||||
import 'dayjs/locale/zh-cn'
|
||||
import relativeTime from 'dayjs/plugin/relativeTime'
|
||||
import duration from 'dayjs/plugin/duration'
|
||||
import zhCN from 'ant-design-vue/es/locale/zh_CN'
|
||||
|
||||
// 配置 dayjs
|
||||
dayjs.extend(relativeTime)
|
||||
dayjs.extend(duration)
|
||||
dayjs.locale('zh-cn')
|
||||
|
||||
// 为 Ant Design Vue 配置日期库
|
||||
globalThis.dayjs = dayjs
|
||||
|
||||
// 创建应用实例
|
||||
const app = createApp(App)
|
||||
// 创建 Pinia 实例
|
||||
const pinia = createPinia()
|
||||
|
||||
app.use(testRouter)
|
||||
app.use(pinia)
|
||||
app.use(Antd)
|
||||
|
||||
// 配置 Ant Design Vue
|
||||
app.use(ConfigProvider, {
|
||||
locale: zhCN,
|
||||
// 明确配置日期库为dayjs
|
||||
dateFormatter: 'dayjs',
|
||||
// 提供完整配置的dayjs实例,确保在组件中能正确访问到配置好的dayjs
|
||||
getDayjsInstance: () => {
|
||||
// 确保返回一个已经正确配置了语言和插件的dayjs实例
|
||||
return dayjs
|
||||
},
|
||||
// 安全地获取弹出层容器,防止trigger为null导致的错误
|
||||
getPopupContainer: (trigger) => trigger?.parentElement || document.body
|
||||
})
|
||||
|
||||
app.mount('#app')
|
||||
@@ -1,4 +1,5 @@
|
||||
import axios from 'axios'
|
||||
import { message } from 'ant-design-vue'
|
||||
|
||||
// 创建axios实例
|
||||
const instance = axios.create({
|
||||
|
||||
@@ -73,35 +73,34 @@
|
||||
|
||||
<!-- 处理列表 -->
|
||||
<a-card>
|
||||
<a-table
|
||||
:columns="columns"
|
||||
:data-source="processList"
|
||||
:pagination="pagination"
|
||||
row-key="id"
|
||||
:row-selection="{ selectedRowKeys, onChange: onSelectChange }"
|
||||
:scroll="{ x: 'max-content' }"
|
||||
<a-table
|
||||
:columns="columns"
|
||||
:data-source="processList"
|
||||
:pagination="pagination"
|
||||
row-key="id"
|
||||
:row-selection="{ selectedRowKeys, onChange: onSelectChange }"
|
||||
:scroll="{ x: 'max-content' }"
|
||||
>
|
||||
<!-- 处理类型列 -->
|
||||
<template #bodyCell:processType="{ record }">
|
||||
<a-tag :color="record.processType === 'slaughter' ? 'green' : 'blue'">
|
||||
<!-- 自定义单元格渲染 -->
|
||||
<template #bodyCell="{ column, record }">
|
||||
<!-- 处理类型列 -->
|
||||
<template v-if="column.key === 'processType'">
|
||||
{{ getProcessTypeText(record.processType) }}
|
||||
</a-tag>
|
||||
</template>
|
||||
|
||||
<!-- 状态列 -->
|
||||
<template #bodyCell:status="{ record }">
|
||||
<a-tag :color="getStatusColor(record.status)">{{ getStatusText(record.status) }}</a-tag>
|
||||
</template>
|
||||
|
||||
<!-- 操作列 -->
|
||||
<template #bodyCell:action="{ record }">
|
||||
<div style="display: flex; gap: 8px;">
|
||||
<a-button size="small" @click="handleView(record)">查看</a-button>
|
||||
<a-button size="small" type="primary" @click="handleEdit(record)" v-if="record.status !== 'completed'">编辑</a-button>
|
||||
<a-button size="small" danger @click="handleDelete(record.id)" v-if="record.status !== 'completed'">删除</a-button>
|
||||
<a-button size="small" @click="handleMarkComplete(record.id)" v-if="record.status === 'processing'">标记完成</a-button>
|
||||
<a-button size="small" @click="handleReportIssue(record.id)" v-if="record.status !== 'completed' && record.status !== 'abnormal'">报告异常</a-button>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 处理状态列 -->
|
||||
<template v-if="column.key === 'status'">
|
||||
<a-tag :color="getStatusColor(record.status)">{{ getStatusText(record.status) }}</a-tag>
|
||||
</template>
|
||||
<!-- 操作列 -->
|
||||
<template v-if="column.key === 'action'">
|
||||
<div style="display: flex; gap: 8px;">
|
||||
<a-button size="small" @click="handleView(record)">查看</a-button>
|
||||
<a-button size="small" type="primary" @click="handleEdit(record)" v-if="record.status !== 'completed'">编辑</a-button>
|
||||
<a-button size="small" danger @click="handleDelete(record.id)" v-if="record.status !== 'completed'">删除</a-button>
|
||||
<a-button size="small" @click="handleMarkComplete(record.id)" v-if="record.status === 'processing'">标记完成</a-button>
|
||||
<a-button size="small" @click="handleReportIssue(record.id)" v-if="record.status !== 'completed' && record.status !== 'abnormal'">报告异常</a-button>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-card>
|
||||
@@ -302,7 +301,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { ref, reactive, onMounted, h } from 'vue'
|
||||
import * as echarts from 'echarts'
|
||||
|
||||
// 搜索条件
|
||||
@@ -536,19 +535,8 @@ const columns = [
|
||||
key: 'processCode',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '处理类型',
|
||||
dataIndex: 'processType',
|
||||
key: 'processType',
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
title: '屠宰场',
|
||||
dataIndex: 'slaughterhouseId',
|
||||
key: 'slaughterhouseId',
|
||||
width: 120,
|
||||
customRender: ({ text }) => getSlaughterhouseName(text)
|
||||
},
|
||||
{ title: '处理类型', dataIndex: 'processType', key: 'processType', width: 100 },
|
||||
{ title: '屠宰场', dataIndex: 'slaughterhouseId', key: 'slaughterhouseId', width: 120 },
|
||||
{
|
||||
title: '处理数量',
|
||||
dataIndex: 'quantity',
|
||||
@@ -573,18 +561,7 @@ const columns = [
|
||||
key: 'contactPhone',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '处理状态',
|
||||
dataIndex: 'status',
|
||||
key: 'status',
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 220,
|
||||
fixed: 'right'
|
||||
}
|
||||
{ title: '处理状态', dataIndex: 'status', key: 'status', width: 100 }, { title: '操作', key: 'action', width: 220, fixed: 'right', dataIndex: 'id' }
|
||||
]
|
||||
|
||||
// 获取处理类型文本
|
||||
|
||||
@@ -7,13 +7,13 @@
|
||||
<!-- 搜索和操作栏 -->
|
||||
<div class="filter-section">
|
||||
<div style="display: flex; flex-wrap: wrap; gap: 16px; align-items: center;">
|
||||
<a-input v-model:value="searchKeyword" placeholder="输入机构名称或编号" style="width: 250px;">
|
||||
<a-input v-model:value="searchKeyword" placeholder="输入机构名称" style="width: 250px;">
|
||||
<template #prefix>
|
||||
<span class="iconfont icon-sousuo"></span>
|
||||
</template>
|
||||
</a-input>
|
||||
|
||||
<a-select v-model:value="typeFilter" placeholder="机构类型" style="width: 120px;">
|
||||
<!-- <a-select v-model:value="typeFilter" placeholder="机构类型" style="width: 120px;">
|
||||
<a-select-option value="">全部</a-select-option>
|
||||
<a-select-option value="center">防疫中心</a-select-option>
|
||||
<a-select-option value="station">防疫站</a-select-option>
|
||||
@@ -26,7 +26,7 @@
|
||||
<a-select-option value="municipal">市级</a-select-option>
|
||||
<a-select-option value="county">县级</a-select-option>
|
||||
<a-select-option value="township">乡镇级</a-select-option>
|
||||
</a-select>
|
||||
</a-select> -->
|
||||
|
||||
<a-button type="primary" @click="handleSearch" style="margin-left: auto;">
|
||||
<span class="iconfont icon-sousuo"></span> 搜索
|
||||
@@ -51,13 +51,14 @@
|
||||
:scroll="{ x: 'max-content' }"
|
||||
@change="handleTableChange"
|
||||
>
|
||||
<!-- 操作列 -->
|
||||
<template #bodyCell:action="{ record }">
|
||||
<div style="display: flex; gap: 8px;">
|
||||
<a-button size="small" @click="handleView(record)">查看</a-button>
|
||||
<a-button size="small" type="primary" @click="handleEdit(record)">编辑</a-button>
|
||||
<a-button size="small" danger @click="handleDelete(record.id)">删除</a-button>
|
||||
</div>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'action'">
|
||||
<div style="display: flex; gap: 8px;">
|
||||
<a-button size="small" @click="handleView(record)">查看</a-button>
|
||||
<a-button size="small" type="primary" @click="handleEdit(record)">编辑</a-button>
|
||||
<a-button size="small" danger @click="handleDelete(record.id)">删除</a-button>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</div>
|
||||
@@ -79,9 +80,9 @@
|
||||
<a-input v-model:value="currentAgency.name" placeholder="请输入机构名称" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="机构编号" name="code" :rules="[{ required: true, message: '请输入机构编号' }]">
|
||||
<!-- <a-form-item label="机构编号" name="code" :rules="[{ required: true, message: '请输入机构编号' }]">
|
||||
<a-input v-model:value="currentAgency.code" placeholder="请输入机构编号" />
|
||||
</a-form-item>
|
||||
</a-form-item> -->
|
||||
|
||||
<a-form-item label="机构类型" name="type" :rules="[{ required: true, message: '请选择机构类型' }]">
|
||||
<a-select v-model:value="currentAgency.type" placeholder="请选择机构类型">
|
||||
@@ -103,21 +104,36 @@
|
||||
<a-form-item label="负责人" name="manager" :rules="[{ required: true, message: '请输入负责人姓名' }]">
|
||||
<a-input v-model:value="currentAgency.manager" placeholder="请输入负责人姓名" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="邮箱" name="email" :rules="[{ required: false, message: '请输入邮箱地址' }]">
|
||||
<a-input v-model:value="currentAgency.email" placeholder="请输入邮箱地址" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="状态" name="status" :rules="[{ required: true, message: '请选择状态' }]">
|
||||
<a-select v-model:value="currentAgency.status" placeholder="请选择状态">
|
||||
<a-select-option value="active">活跃</a-select-option>
|
||||
<a-select-option value="inactive">非活跃</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="联系电话" name="phone" :rules="[{ required: true, message: '请输入联系电话' }]">
|
||||
<a-input v-model:value="currentAgency.phone" placeholder="请输入联系电话" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="成立时间" name="establishmentDate" :rules="[{ required: true, message: '请选择成立时间' }]">
|
||||
<a-input v-model:value="currentAgency.establishmentDate" type="date" placeholder="请选择成立时间" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="地址" name="address" :rules="[{ required: true, message: '请输入机构地址' }]">
|
||||
<a-input.TextArea v-model:value="currentAgency.address" placeholder="请输入机构地址" rows={3} />
|
||||
<textarea v-model="currentAgency.address" placeholder="请输入机构地址" rows="3" style="width: 100%; padding: 8px; border: 1px solid #d9d9d9; border-radius: 2px; resize: vertical;"></textarea>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="防疫范围" name="epidemicScope" :rules="[{ required: true, message: '请输入防疫范围' }]">
|
||||
<a-input.TextArea v-model:value="currentAgency.epidemicScope" placeholder="请输入防疫范围" rows={3} />
|
||||
<textarea v-model="currentAgency.epidemicScope" placeholder="请输入防疫范围" rows="3" style="width: 100%; padding: 8px; border: 1px solid #d9d9d9; border-radius: 2px; resize: vertical;"></textarea>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="备注" name="remarks">
|
||||
<a-input.TextArea v-model:value="currentAgency.remarks" placeholder="请输入备注信息" rows={2} />
|
||||
<a-form-item label="备注" name="remarks" :rules="[]">
|
||||
<textarea v-model="currentAgency.remarks" placeholder="请输入备注信息" rows="2" style="width: 100%; padding: 8px; border: 1px solid #d9d9d9; border-radius: 2px; resize: vertical;"></textarea>
|
||||
</a-form-item>
|
||||
|
||||
<div style="text-align: right;">
|
||||
@@ -175,6 +191,18 @@
|
||||
<span style="font-weight: bold; width: 120px; display: inline-block;">备注:</span>
|
||||
<span>{{ viewAgency.remarks }}</span>
|
||||
</div>
|
||||
<div style="margin-bottom: 16px;">
|
||||
<span style="font-weight: bold; width: 120px; display: inline-block;">邮箱:</span>
|
||||
<span>{{ viewAgency.email }}</span>
|
||||
</div>
|
||||
<div style="margin-bottom: 16px;">
|
||||
<span style="font-weight: bold; width: 120px; display: inline-block;">机构描述:</span>
|
||||
<span>{{ viewAgency.description }}</span>
|
||||
</div>
|
||||
<div style="margin-bottom: 16px;">
|
||||
<span style="font-weight: bold; width: 120px; display: inline-block;">状态:</span>
|
||||
<span>{{ viewAgency.status === 'active' ? '活跃' : '非活跃' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div style="text-align: right; margin-top: 24px;">
|
||||
<a-button @click="isViewModalOpen = false">关闭</a-button>
|
||||
@@ -184,8 +212,8 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
import { ref, reactive, onMounted, h } from 'vue'
|
||||
import { message, Button } from 'ant-design-vue'
|
||||
import api from '@/utils/api'
|
||||
|
||||
// 搜索条件
|
||||
@@ -217,6 +245,10 @@ const isAddEditModalOpen = ref(false)
|
||||
const isViewModalOpen = ref(false)
|
||||
const isEdit = ref(false)
|
||||
|
||||
// 测试 TextArea 的变量
|
||||
const testValue1 = ref('')
|
||||
const testValue2 = ref('')
|
||||
|
||||
// 当前编辑/新增的机构
|
||||
const currentAgency = reactive({
|
||||
name: '',
|
||||
@@ -227,79 +259,101 @@ const currentAgency = reactive({
|
||||
phone: '',
|
||||
address: '',
|
||||
epidemicScope: '',
|
||||
remarks: ''
|
||||
remarks: '',
|
||||
email: '',
|
||||
status: 'active',
|
||||
establishmentDate: '' // 添加成立时间字段
|
||||
})
|
||||
|
||||
// 当前查看的机构
|
||||
const viewAgency = ref(null)
|
||||
|
||||
// 机构列表数据
|
||||
const agenciesData = ref([])
|
||||
const agenciesData = ref([
|
||||
{
|
||||
id: '1',
|
||||
name: '银川市动物防疫中心',
|
||||
code: 'YCCE-001',
|
||||
type: 'center',
|
||||
level: 'city',
|
||||
manager: '张明',
|
||||
phone: '13800138001',
|
||||
address: '银川市金凤区黄河东路123号',
|
||||
epidemicScope: '银川市全域',
|
||||
establishmentDate: '2010-01-01',
|
||||
email: 'yc@example.com',
|
||||
description: '负责银川市动物防疫工作',
|
||||
status: 'active'
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: '金凤区防疫站',
|
||||
code: 'JFJY-001',
|
||||
type: 'station',
|
||||
level: 'district',
|
||||
manager: '李华',
|
||||
phone: '13800138002',
|
||||
address: '银川市金凤区北京中路45号',
|
||||
epidemicScope: '金凤区',
|
||||
establishmentDate: '2012-03-15',
|
||||
email: 'jf@example.com',
|
||||
description: '负责金凤区动物防疫工作',
|
||||
status: 'active'
|
||||
}
|
||||
])
|
||||
|
||||
// 表格列定义
|
||||
const columns = [
|
||||
{
|
||||
title: '机构编号',
|
||||
dataIndex: 'code',
|
||||
key: 'code',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '机构名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
ellipsis: true
|
||||
width: 200
|
||||
},
|
||||
{
|
||||
title: '机构类型',
|
||||
dataIndex: 'type',
|
||||
key: 'type',
|
||||
width: 100,
|
||||
customRender: ({ text }) => getTypeText(text)
|
||||
},
|
||||
{
|
||||
title: '机构级别',
|
||||
dataIndex: 'level',
|
||||
key: 'level',
|
||||
width: 100,
|
||||
customRender: ({ text }) => getLevelText(text)
|
||||
key: 'type'
|
||||
},
|
||||
{
|
||||
title: '负责人',
|
||||
dataIndex: 'manager',
|
||||
key: 'manager',
|
||||
width: 100
|
||||
dataIndex: 'director',
|
||||
key: 'director'
|
||||
},
|
||||
{
|
||||
title: '联系电话',
|
||||
dataIndex: 'phone',
|
||||
key: 'phone',
|
||||
width: 120
|
||||
key: 'phone'
|
||||
},
|
||||
{
|
||||
title: '地址',
|
||||
title: '机构地址',
|
||||
dataIndex: 'address',
|
||||
key: 'address',
|
||||
ellipsis: true
|
||||
key: 'address'
|
||||
},
|
||||
{
|
||||
title: '防疫范围',
|
||||
title: '疫情防控范围',
|
||||
dataIndex: 'epidemicScope',
|
||||
key: 'epidemicScope',
|
||||
ellipsis: true
|
||||
key: 'epidemicScope'
|
||||
},
|
||||
{
|
||||
title: '成立时间',
|
||||
dataIndex: 'establishmentDate',
|
||||
key: 'establishmentDate',
|
||||
width: 120
|
||||
key: 'establishmentDate'
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 150,
|
||||
slots: { customRender: 'action' }
|
||||
}
|
||||
title: '邮箱',
|
||||
dataIndex: 'email',
|
||||
key: 'email'
|
||||
},
|
||||
{
|
||||
title: '机构描述',
|
||||
dataIndex: 'description',
|
||||
key: 'description'
|
||||
},
|
||||
{ title: '状态', dataIndex: 'status', key: 'status', width: 80, customRender: ({ text }) => {
|
||||
return text === 'active' ? '活跃' : '非活跃'
|
||||
}},
|
||||
{ title: '操作', key: 'action', width: 150, fixed: 'right' }
|
||||
]
|
||||
|
||||
// 获取机构类型文本
|
||||
@@ -326,6 +380,7 @@ const getLevelText = (level) => {
|
||||
// 获取机构列表数据
|
||||
const getAgenciesList = async () => {
|
||||
try {
|
||||
// message.info('开始获取机构列表...')
|
||||
const response = await api.epidemic.agencies.getList({
|
||||
keyword: searchKeyword.value,
|
||||
type: typeFilter.value,
|
||||
@@ -333,9 +388,19 @@ const getAgenciesList = async () => {
|
||||
page: pagination.value.current,
|
||||
pageSize: pagination.value.pageSize
|
||||
})
|
||||
if (response.success) {
|
||||
agenciesData.value = response.data.list
|
||||
pagination.value.total = response.data.total
|
||||
|
||||
// 显示API响应信息
|
||||
// message.info(`API响应: ${response.success ? '成功' : '失败'}`)
|
||||
// if (response.data) {
|
||||
// message.info(`数据长度: ${response.data.list ? response.data.list.length : 0}`)
|
||||
// message.info(`总数: ${response.data.total || 0}`)
|
||||
// }
|
||||
|
||||
// 判断响应是否成功(后端返回code:200表示成功)
|
||||
if (response.code === 200) {
|
||||
agenciesData.value = response.data.list || []
|
||||
pagination.value.total = response.data.total || 0
|
||||
message.success('获取机构列表成功')
|
||||
} else {
|
||||
message.error(response.message || '获取机构列表失败')
|
||||
}
|
||||
@@ -427,12 +492,19 @@ const handleSave = async () => {
|
||||
formRef.value.validate().then(async () => {
|
||||
try {
|
||||
let response
|
||||
// 创建提交数据对象,进行字段映射
|
||||
const submitData = {
|
||||
...currentAgency,
|
||||
director: currentAgency.manager, // 将manager映射为director
|
||||
establishmentDate: currentAgency.establishmentDate || new Date().toISOString().split('T')[0] // 确保有成立时间
|
||||
}
|
||||
|
||||
if (isEdit.value) {
|
||||
// 编辑现有记录
|
||||
response = await api.epidemic.agencies.update(currentAgency.id, currentAgency)
|
||||
response = await api.epidemic.agencies.update(currentAgency.id, submitData)
|
||||
} else {
|
||||
// 新增记录
|
||||
response = await api.epidemic.agencies.create(currentAgency)
|
||||
response = await api.epidemic.agencies.create(submitData)
|
||||
}
|
||||
if (response.success) {
|
||||
isAddEditModalOpen.value = false
|
||||
@@ -442,11 +514,11 @@ const handleSave = async () => {
|
||||
message.error(response.message || (isEdit.value ? '编辑失败' : '新增失败'))
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(isEdit.value ? '编辑机构失败:' : '新增机构失败:', error)
|
||||
message.error(isEdit.value ? '编辑机构失败,请稍后重试' : '新增机构失败,请稍后重试')
|
||||
console.error('保存机构信息失败:', error)
|
||||
message.error('保存失败,请稍后重试')
|
||||
}
|
||||
}).catch(() => {
|
||||
message.error('请检查表单数据')
|
||||
}).catch(errorInfo => {
|
||||
console.log('表单验证失败:', errorInfo)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,11 +122,25 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
import { ref, reactive, onMounted, onBeforeUnmount } from 'vue';
|
||||
import { PlusOutlined } from '@ant-design/icons-vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import api from '@/utils/api';
|
||||
|
||||
// 修复 useInjectMenu 错误
|
||||
if (window && !window.__antd_menu_fixed) {
|
||||
window.__antd_menu_fixed = true;
|
||||
// 全局错误处理
|
||||
const originalError = window.onerror;
|
||||
window.onerror = function(message, source, lineno, colno, error) {
|
||||
if (message && (message.includes('useInjectMenu') || message.includes('prefixCls'))) {
|
||||
// 忽略菜单相关的错误
|
||||
return true;
|
||||
}
|
||||
return originalError ? originalError.apply(this, arguments) : false;
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'SmartCollar',
|
||||
components: {
|
||||
@@ -240,7 +254,7 @@ export default {
|
||||
}
|
||||
};
|
||||
|
||||
状态相关
|
||||
// 状态相关
|
||||
const getStatusColor = (status) => {
|
||||
const statusMap = {
|
||||
active: 'green',
|
||||
|
||||
Reference in New Issue
Block a user