添加银行政府后端接口

This commit is contained in:
2025-09-25 15:53:44 +08:00
parent b17bdcc24c
commit 5b6b7e0a96
60 changed files with 5345 additions and 1920 deletions

View File

@@ -4,7 +4,7 @@ import axios from 'axios'
// 创建axios实例
const instance = axios.create({
baseURL: '/api',
baseURL: 'http://localhost:5352/api',
timeout: 10000,
headers: {
'Content-Type': 'application/json'
@@ -43,26 +43,40 @@ instance.interceptors.response.use(
const userStore = useUserStore()
userStore.logout()
window.location.href = '/login'
message.error('登录已过期,请重新登录')
import('ant-design-vue').then(({ message }) => {
message.error('登录已过期,请重新登录')
})
break
case 403:
message.error('没有权限执行此操作')
import('ant-design-vue').then(({ message }) => {
message.error('没有权限执行此操作')
})
break
case 404:
message.error('请求的资源不存在')
import('ant-design-vue').then(({ message }) => {
message.error('请求的资源不存在')
})
break
case 500:
message.error('服务器内部错误')
import('ant-design-vue').then(({ message }) => {
message.error('服务器内部错误')
})
break
default:
message.error(error.response.data.message || '请求失败')
import('ant-design-vue').then(({ message }) => {
message.error(error.response.data.message || '请求失败')
})
}
} else if (error.request) {
// 请求发出但没有收到响应
message.error('网络错误,请检查网络连接')
import('ant-design-vue').then(({ message }) => {
message.error('网络错误,请检查网络连接')
})
} else {
// 请求配置出错
message.error('请求配置错误')
import('ant-design-vue').then(({ message }) => {
message.error('请求配置错误')
})
}
return Promise.reject(error)
}
@@ -217,6 +231,35 @@ const api = {
updateSettings: (data) => instance.put('/system/settings', data),
// 获取日志列表
getLogs: (params) => instance.get('/system/logs', { params })
},
// 政府管理相关API
government: {
// 行政人员管理
adminStaff: {
// 获取行政人员列表
getList: (params) => instance.get('/government/admin-staff', { params }),
// 创建行政人员
create: (data) => instance.post('/government/admin-staff', data),
// 更新行政人员
update: (id, data) => instance.put(`/government/admin-staff/${id}`, data),
// 删除行政人员
delete: (id) => instance.delete(`/government/admin-staff/${id}`),
// 重置行政人员密码
resetPassword: (id) => instance.post(`/government/admin-staff/${id}/reset-password`)
},
// 部门管理
departments: {
// 获取部门列表
getList: (params) => instance.get('/government/departments', { params })
},
// 岗位管理
positions: {
// 获取岗位列表
getList: (params) => instance.get('/government/positions', { params })
}
}
}

View File

@@ -1,130 +1,90 @@
<template>
<div class="admin-department-container">
<div class="header">
<div class="title">部门防疫部门</div>
<div class="actions">
<a-button type="primary" class="action-btn">删除部门</a-button>
<a-button type="primary" class="action-btn">新增岗位</a-button>
<template v-for="dept in departments" :key="dept.id">
<div class="header">
<div class="title">部门{{ dept.name }}</div>
<div class="actions">
<a-button type="primary" danger @click="handleDeleteDepartment(dept.id)">删除部门</a-button>
<a-button type="primary" @click="showAddPositionModal(dept.id, dept.name)">新增岗位</a-button>
</div>
</div>
</div>
<a-table :columns="columns" :data-source="departmentData" :pagination="false" class="department-table">
<template #headerCell="{ column }">
<span>{{ column.title }}</span>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'permission'">
<a-tag v-if="record.permission === '已设置权限'" color="success">{{ record.permission }}</a-tag>
<a-tag v-else color="warning">{{ record.permission }}</a-tag>
<a-table :columns="columns" :data-source="formatPositionsData(dept.positions)" :pagination="false" class="department-table">
<template #headerCell="{ column }">
<span>{{ column.title }}</span>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a-button type="link" @click="editPosition(record)">编辑岗位名称</a-button>
<a-button type="link" @click="deletePosition(record)">删除岗位</a-button>
<a-button type="link" @click="setPermission(record)">设置权限</a-button>
</a-space>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'permission'">
<a-tag v-if="record.permission === '已设置权限'" color="success">{{ record.permission }}</a-tag>
<a-tag v-else color="warning">{{ record.permission }}</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a-button type="link" @click="showEditPositionModal(record)">编辑岗位名称</a-button>
<a-button type="link" danger @click="handleDeletePosition(record.id)">删除岗位</a-button>
<a-button type="link" @click="showSetPermissionModal(record)">设置权限</a-button>
</a-space>
</template>
</template>
</template>
</a-table>
<div class="header">
<div class="title">部门检疫部门</div>
<div class="actions">
<a-button type="primary" class="action-btn">删除部门</a-button>
<a-button type="primary" class="action-btn">新增岗位</a-button>
</div>
</div>
<a-table :columns="columns" :data-source="inspectionData" :pagination="false" class="department-table">
<template #headerCell="{ column }">
<span>{{ column.title }}</span>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'permission'">
<a-tag v-if="record.permission === '已设置权限'" color="success">{{ record.permission }}</a-tag>
<a-tag v-else color="warning">{{ record.permission }}</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a-button type="link" @click="editPosition(record)">编辑岗位名称</a-button>
<a-button type="link" @click="deletePosition(record)">删除岗位</a-button>
<a-button type="link" @click="setPermission(record)">设置权限</a-button>
</a-space>
</template>
</template>
</a-table>
<div class="header">
<div class="title">部门冷配管理部门</div>
<div class="actions">
<a-button type="primary" class="action-btn">删除部门</a-button>
<a-button type="primary" class="action-btn">新增岗位</a-button>
</div>
</div>
<a-table :columns="columns" :data-source="coldChainData" :pagination="false" class="department-table">
<template #headerCell="{ column }">
<span>{{ column.title }}</span>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'permission'">
<a-tag v-if="record.permission === '已设置权限'" color="success">{{ record.permission }}</a-tag>
<a-tag v-else color="warning">{{ record.permission }}</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a-button type="link" @click="editPosition(record)">编辑岗位名称</a-button>
<a-button type="link" @click="deletePosition(record)">删除岗位</a-button>
<a-button type="link" @click="setPermission(record)">设置权限</a-button>
</a-space>
</template>
</template>
</a-table>
<div class="header">
<div class="title">部门测试部门</div>
<div class="actions">
<a-button type="primary" class="action-btn">删除部门</a-button>
<a-button type="primary" class="action-btn">新增岗位</a-button>
</div>
</div>
<a-table :columns="columns" :data-source="testingData" :pagination="false" class="department-table">
<template #headerCell="{ column }">
<span>{{ column.title }}</span>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'permission'">
<a-tag v-if="record.permission === '已设置权限'" color="success">{{ record.permission }}</a-tag>
<a-tag v-else color="warning">{{ record.permission }}</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a-button type="link" @click="editPosition(record)">编辑岗位名称</a-button>
<a-button type="link" @click="deletePosition(record)">删除岗位</a-button>
<a-button type="link" @click="setPermission(record)">设置权限</a-button>
</a-space>
</template>
</template>
</a-table>
</a-table>
</template>
<div class="add-department">
<a-button type="primary" @click="showAddDepartmentModal">新增部门</a-button>
</div>
<!-- 新增部门模态框 -->
<a-modal v-model:visible="addDepartmentModalVisible" title="新增部门" @ok="handleAddDepartment" @cancel="handleCancel">
<a-form-model ref="addDepartmentForm" :model="addDepartmentFormData" :rules="addDepartmentRules">
<a-form-model-item label="部门名称" name="name">
<a-input v-model="addDepartmentFormData.name" placeholder="请输入部门名称" />
</a-form-model-item>
<a-form-model-item label="部门描述" name="description">
<a-textarea v-model="addDepartmentFormData.description" placeholder="请输入部门描述" :rows="3" />
</a-form-model-item>
</a-form-model>
</a-modal>
<!-- 新增岗位模态框 -->
<a-modal v-model:visible="addPositionModalVisible" title="新增岗位" @ok="handleAddPosition" @cancel="handleCancel">
<a-form-model ref="addPositionForm" :model="addPositionFormData" :rules="addPositionRules">
<a-form-model-item label="所属部门" name="department_name">
<a-input v-model="addPositionFormData.department_name" disabled />
</a-form-model-item>
<a-form-model-item label="岗位名称" name="name">
<a-input v-model="addPositionFormData.name" placeholder="请输入岗位名称" />
</a-form-model-item>
</a-form-model>
</a-modal>
<!-- 编辑岗位模态框 -->
<a-modal v-model:visible="editPositionModalVisible" title="编辑岗位" @ok="handleEditPosition" @cancel="handleCancel">
<a-form-model ref="editPositionForm" :model="editPositionFormData" :rules="editPositionRules">
<a-form-model-item label="岗位名称" name="name">
<a-input v-model="editPositionFormData.name" placeholder="请输入岗位名称" />
</a-form-model-item>
</a-form-model>
</a-modal>
<!-- 设置权限模态框 -->
<a-modal v-model:visible="setPermissionModalVisible" title="设置权限" @ok="handleSetPermission" @cancel="handleCancel" :width="600">
<div>
<p>岗位: {{ currentPosition?.name }}</p>
<div style="margin-top: 16px;">
<p>权限设置示例</p>
<a-alert type="info" message="实际项目中,这里应该是具体的权限选择界面" />
</div>
</div>
</a-modal>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
import { ref, reactive, onMounted } from 'vue'
import { message } from 'ant-design-vue'
import axios from 'axios'
// 表格列定义
const columns = [
@@ -144,66 +104,212 @@ const columns = [
}
]
// 防疫部门数据
const departmentData = ref([
{
key: '1',
position: '防疫员',
permission: '已设置权限',
},
{
key: '2',
position: '防疫管理员',
permission: '已设置权限',
}
])
// 部门数据
const departments = ref([])
// 检疫部门数据
const inspectionData = ref([
{
key: '1',
position: '检疫员',
permission: '未设置权限',
}
])
// 当前选中的岗位
const currentPosition = ref(null)
// 冷配管理部门数据
const coldChainData = ref([
{
key: '1',
position: '冷配员',
permission: '已设置权限',
}
])
// 模态框控制
const addDepartmentModalVisible = ref(false)
const addPositionModalVisible = ref(false)
const editPositionModalVisible = ref(false)
const setPermissionModalVisible = ref(false)
// 测试部门数据
const testingData = ref([
{
key: '1',
position: '内部测试账号',
permission: '已设置权限',
}
])
// 表单数据
const addDepartmentFormData = reactive({
name: '',
description: ''
})
// 编辑岗位
const editPosition = (record) => {
message.info(`编辑岗位:${record.position}`)
const addPositionFormData = reactive({
department_id: '',
department_name: '',
name: ''
})
const editPositionFormData = reactive({
id: '',
name: ''
})
// 表单验证规则
const addDepartmentRules = {
name: [
{ required: true, message: '请输入部门名称', trigger: 'blur' }
]
}
// 删除岗位
const deletePosition = (record) => {
message.info(`删除岗位:${record.position}`)
const addPositionRules = {
name: [
{ required: true, message: '请输入岗位名称', trigger: 'blur' }
]
}
// 设置权限
const setPermission = (record) => {
message.info(`设置权限:${record.position}`)
const editPositionRules = {
name: [
{ required: true, message: '请输入岗位名称', trigger: 'blur' }
]
}
// 从API获取部门数据
const fetchDepartments = async () => {
try {
const response = await axios.get('/api/government/departments')
departments.value = response.data
} catch (error) {
message.error('获取部门数据失败:' + error.message)
console.error('获取部门数据失败:', error)
}
}
// 格式化岗位数据
const formatPositionsData = (positions) => {
return positions.map(pos => ({
key: pos.id,
id: pos.id,
position: pos.name,
permission: pos.permission
}))
}
// 显示新增部门模态框
const showAddDepartmentModal = () => {
message.info('显示新增部门对话框')
// 重置表单
Object.keys(addDepartmentFormData).forEach(key => {
addDepartmentFormData[key] = ''
})
addDepartmentModalVisible.value = true
}
// 显示新增岗位模态框
const showAddPositionModal = (departmentId, departmentName) => {
// 重置表单
Object.keys(addPositionFormData).forEach(key => {
addPositionFormData[key] = ''
})
addPositionFormData.department_id = departmentId
addPositionFormData.department_name = departmentName
addPositionModalVisible.value = true
}
// 显示编辑岗位模态框
const showEditPositionModal = (record) => {
editPositionFormData.id = record.id
editPositionFormData.name = record.position
editPositionModalVisible.value = true
}
// 显示设置权限模态框
const showSetPermissionModal = (record) => {
currentPosition.value = record
setPermissionModalVisible.value = true
}
// 新增部门
const handleAddDepartment = async () => {
try {
await axios.post('/api/government/departments', {
name: addDepartmentFormData.name,
description: addDepartmentFormData.description
})
message.success('部门创建成功')
addDepartmentModalVisible.value = false
// 重新获取数据
await fetchDepartments()
} catch (error) {
message.error('创建部门失败:' + error.message)
console.error('创建部门失败:', error)
}
}
// 新增岗位
const handleAddPosition = async () => {
try {
await axios.post(`/api/government/departments/${addPositionFormData.department_id}/positions`, {
department_id: addPositionFormData.department_id,
name: addPositionFormData.name
})
message.success('岗位创建成功')
addPositionModalVisible.value = false
// 重新获取数据
await fetchDepartments()
} catch (error) {
message.error('创建岗位失败:' + error.message)
console.error('创建岗位失败:', error)
}
}
// 编辑岗位
const handleEditPosition = async () => {
try {
await axios.put(`/api/government/positions/${editPositionFormData.id}`, {
name: editPositionFormData.name
})
message.success('岗位编辑成功')
editPositionModalVisible.value = false
// 重新获取数据
await fetchDepartments()
} catch (error) {
message.error('编辑岗位失败:' + error.message)
console.error('编辑岗位失败:', error)
}
}
// 删除岗位
const handleDeletePosition = async (positionId) => {
try {
await axios.delete(`/api/government/positions/${positionId}`)
message.success('岗位删除成功')
// 重新获取数据
await fetchDepartments()
} catch (error) {
message.error('删除岗位失败:' + error.message)
console.error('删除岗位失败:', error)
}
}
// 删除部门
const handleDeleteDepartment = async (departmentId) => {
try {
await axios.delete(`/api/government/departments/${departmentId}`)
message.success('部门删除成功')
// 重新获取数据
await fetchDepartments()
} catch (error) {
message.error('删除部门失败:' + error.message)
console.error('删除部门失败:', error)
}
}
// 设置权限
const handleSetPermission = async () => {
try {
await axios.post(`/api/government/positions/${currentPosition.value.id}/permission`, {
permission_details: { basic: ['view', 'edit', 'add'], advanced: ['delete'] }
})
message.success('权限设置成功')
setPermissionModalVisible.value = false
// 重新获取数据
await fetchDepartments()
} catch (error) {
message.error('设置权限失败:' + error.message)
console.error('设置权限失败:', error)
}
}
// 取消操作
const handleCancel = () => {
addDepartmentModalVisible.value = false
addPositionModalVisible.value = false
editPositionModalVisible.value = false
setPermissionModalVisible.value = false
}
// 组件挂载时获取数据
onMounted(() => {
fetchDepartments()
})
</script>
<style scoped>

View File

@@ -1,7 +1,7 @@
<template>
<div class="admin-staff-container">
<div class="header">
<a-button type="primary">新增人员</a-button>
<a-button type="primary" @click="showCreateModal">新增人员</a-button>
<a-input-search
v-model:value="searchValue"
placeholder="请输入员工姓名"
@@ -13,27 +13,106 @@
<a-table :columns="columns" :data-source="staffData" :pagination="pagination" class="staff-table">
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'status'">
<a-switch v-model:checked="record.status" />
<a-switch v-model:checked="record.status" @change="updateStaffStatus(record)" />
</template>
<template v-if="column.key === 'action'">
<a-space>
<a-button type="link" @click="editStaff(record)">编辑</a-button>
<a-button type="link" @click="resetPassword(record)">修改密码</a-button>
<a-button type="link" @click="showEditModal(record)">编辑</a-button>
<a-button type="link" @click="handleResetPassword(record)">修改密码</a-button>
<a-button type="link" danger @click="deleteStaff(record)">删除</a-button>
</a-space>
</template>
</template>
</a-table>
<!-- 新增/编辑模态框 -->
<a-modal
v-model:open="isModalOpen"
:title="modalTitle"
@ok="handleModalOk"
@cancel="handleModalCancel"
>
<a-form :model="formData" layout="vertical">
<a-form-item label="员工姓名">
<a-input v-model:value="formData.name" placeholder="请输入员工姓名" />
</a-form-item>
<a-form-item label="所属部门">
<a-select v-model:value="formData.department_id" placeholder="请选择部门">
<a-select-option v-for="dept in departments" :key="dept.id" :value="dept.id">
{{ dept.name }}
</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="任职岗位">
<a-select v-model:value="formData.position_id" placeholder="请选择岗位">
<a-select-option v-for="pos in positions" :key="pos.id" :value="pos.id">
{{ pos.name }}
</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="联系电话">
<a-input v-model:value="formData.phone" placeholder="请输入联系电话" />
</a-form-item>
<a-form-item label="身份证号码">
<a-input v-model:value="formData.id_card" placeholder="请输入身份证号码" />
</a-form-item>
</a-form>
</a-modal>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
import { message } from 'ant-design-vue'
import { ref, reactive, onMounted } from 'vue'
import { message, Modal } from 'ant-design-vue'
import api from '@/utils/api'
// 搜索值
const searchValue = ref('')
// 员工数据
const staffData = ref([])
// 部门列表
const departments = ref([])
// 岗位列表
const positions = ref([])
// 分页配置
const pagination = reactive({
current: 1,
pageSize: 10,
total: 0,
showSizeChanger: true,
showTotal: (total) => `${total} 条记录`,
onChange: (page, pageSize) => {
pagination.current = page
pagination.pageSize = pageSize
fetchAdminStaffList()
},
onShowSizeChange: (current, pageSize) => {
pagination.current = 1
pagination.pageSize = pageSize
fetchAdminStaffList()
}
})
// 模态框相关
const isModalOpen = ref(false)
const modalTitle = ref('新增行政人员')
const currentStaffId = ref(null)
// 表单数据
const formData = reactive({
name: '',
department_id: '',
position_id: '',
phone: '',
id_card: '',
status: true
})
// 表格列定义
const columns = [
{
@@ -58,8 +137,8 @@ const columns = [
},
{
title: '身份证号码',
dataIndex: 'idCard',
key: 'idCard',
dataIndex: 'id_card',
key: 'id_card',
},
{
title: '账号使用状态',
@@ -68,9 +147,9 @@ const columns = [
},
{
title: '创建时间',
dataIndex: 'createdAt',
key: 'createdAt',
sorter: (a, b) => new Date(a.createdAt) - new Date(b.createdAt),
dataIndex: 'created_at',
key: 'created_at',
sorter: (a, b) => new Date(a.created_at) - new Date(b.created_at),
},
{
title: '操作',
@@ -78,173 +157,166 @@ const columns = [
}
]
// 员工数据
const staffData = ref([
{
key: '1',
name: '内部测试账号',
department: '测试部门',
position: '内部测试账号',
phone: '187****4778',
idCard: '--',
status: true,
createdAt: '2023-11-24 17:24:32'
},
{
key: '2',
name: '扎拉嘎',
department: '冷配管理部门',
position: '冷配员',
phone: '195****9912',
idCard: '--',
status: true,
createdAt: '2023-10-10 13:59:03'
},
{
key: '3',
name: '董立鹏',
department: '防疫部',
position: '防疫管理员',
phone: '151****7022',
idCard: '--',
status: true,
createdAt: '2023-05-19 15:47:54'
},
{
key: '4',
name: '李海涛',
department: '防疫部',
position: '防疫管理员',
phone: '139****6955',
idCard: '--',
status: true,
createdAt: '2023-05-09 14:29:15'
},
{
key: '5',
name: '高凤鸣',
department: '防疫部',
position: '防疫管理员',
phone: '158****4601',
idCard: '--',
status: true,
createdAt: '2023-05-09 14:28:57'
},
{
key: '6',
name: '刘全',
department: '防疫部',
position: '防疫管理员',
phone: '139****6009',
idCard: '--',
status: true,
createdAt: '2023-05-09 14:28:39'
},
{
key: '7',
name: '李志伟',
department: '防疫部',
position: '防疫管理员',
phone: '153****0457',
idCard: '--',
status: true,
createdAt: '2023-05-09 14:28:14'
},
{
key: '8',
name: '李景学',
department: '防疫部',
position: '防疫管理员',
phone: '153****5588',
idCard: '--',
status: true,
createdAt: '2023-05-09 14:27:57'
},
{
key: '9',
name: '王海龙',
department: '防疫部',
position: '防疫管理员',
phone: '150****7222',
idCard: '--',
status: true,
createdAt: '2023-05-09 14:27:39'
},
{
key: '10',
name: '德力根',
department: '防疫部',
position: '防疫管理员',
phone: '150****2938',
idCard: '--',
status: true,
createdAt: '2023-05-09 14:27:22'
},
{
key: '11',
name: '巴日斯',
department: '防疫部',
position: '防疫管理员',
phone: '131****1366',
idCard: '--',
status: true,
createdAt: '2023-05-09 14:27:03'
},
{
key: '12',
name: '邵志勇',
department: '防疫部',
position: '防疫管理员',
phone: '139****0778',
idCard: '--',
status: true,
createdAt: '2023-05-09 14:26:26'
},
{
key: '13',
name: '张日林',
department: '防疫部',
position: '防疫管理员',
phone: '156****6300',
idCard: '--',
status: true,
createdAt: '2023-05-09 14:25:37'
},
{
key: '14',
name: '李燕',
department: '防疫部',
position: '防疫管理员',
phone: '151****1613',
idCard: '--',
status: true,
createdAt: '2023-05-09 14:25:12'
// 获取行政人员列表
const fetchAdminStaffList = async () => {
try {
const params = {
page: pagination.current,
pageSize: pagination.pageSize,
search: searchValue.value
}
const response = await api.government.adminStaff.getList(params)
staffData.value = response.data.map(item => ({
...item,
department: departments.value.find(dept => dept.id === item.department_id)?.name || '',
position: positions.value.find(pos => pos.id === item.position_id)?.name || '',
key: item.id
}))
pagination.total = response.total
} catch (error) {
message.error('获取行政人员列表失败')
console.error('获取行政人员列表失败:', error)
}
])
}
// 分页配置
const pagination = reactive({
current: 1,
pageSize: 10,
total: staffData.value.length,
showSizeChanger: true,
showTotal: (total) => `${total} 条记录`
})
// 获取部门列表
const fetchDepartments = async () => {
try {
const response = await api.government.departments.getList()
departments.value = response.data
} catch (error) {
message.error('获取部门列表失败')
console.error('获取部门列表失败:', error)
}
}
// 获取岗位列表
const fetchPositions = async () => {
try {
const response = await api.government.positions.getList()
positions.value = response.data
} catch (error) {
message.error('获取岗位列表失败')
console.error('获取岗位列表失败:', error)
}
}
// 初始化数据
const initData = async () => {
await fetchDepartments()
await fetchPositions()
await fetchAdminStaffList()
}
// 搜索处理
const onSearch = (value) => {
message.info(`搜索: ${value}`)
searchValue.value = value
pagination.current = 1
fetchAdminStaffList()
}
// 编辑员工
const editStaff = (record) => {
message.info(`编辑员工: ${record.name}`)
// 显示新增模态框
const showCreateModal = () => {
currentStaffId.value = null
modalTitle.value = '新增行政人员'
Object.keys(formData).forEach(key => {
formData[key] = ''
})
formData.status = true
isModalOpen.value = true
}
// 重置密码
const resetPassword = (record) => {
message.info(`重置密码: ${record.name}`)
// 显示编辑模态框
const showEditModal = (record) => {
currentStaffId.value = record.id
modalTitle.value = '编辑行政人员'
formData.name = record.name
formData.department_id = record.department_id
formData.position_id = record.position_id
formData.phone = record.phone
formData.id_card = record.id_card
formData.status = record.status
isModalOpen.value = true
}
// 处理模态框确认
const handleModalOk = async () => {
try {
if (currentStaffId.value) {
// 编辑
await api.government.adminStaff.update(currentStaffId.value, formData)
message.success('编辑行政人员成功')
} else {
// 新增
await api.government.adminStaff.create(formData)
message.success('新增行政人员成功')
}
isModalOpen.value = false
fetchAdminStaffList()
} catch (error) {
message.error(currentStaffId.value ? '编辑行政人员失败' : '新增行政人员失败')
console.error('操作行政人员失败:', error)
}
}
// 处理模态框取消
const handleModalCancel = () => {
isModalOpen.value = false
}
// 更新员工状态
const updateStaffStatus = async (record) => {
try {
await api.government.adminStaff.update(record.id, {
status: record.status
})
message.success('更新状态成功')
} catch (error) {
record.status = !record.status // 回滚状态
message.error('更新状态失败')
console.error('更新状态失败:', error)
}
}
// 处理重置密码
const handleResetPassword = (record) => {
Modal.confirm({
title: '确认重置密码',
content: `确定要重置 ${record.name} 的密码吗?重置后密码将变为 123456`,
onOk: async () => {
try {
await api.government.adminStaff.resetPassword(record.id)
message.success('重置密码成功')
} catch (error) {
message.error('重置密码失败')
console.error('重置密码失败:', error)
}
}
})
}
// 删除员工
const deleteStaff = (record) => {
Modal.confirm({
title: '确认删除',
content: `确定要删除 ${record.name} 吗?`,
onOk: async () => {
try {
await api.government.adminStaff.delete(record.id)
message.success('删除成功')
fetchAdminStaffList()
} catch (error) {
message.error('删除失败')
console.error('删除失败:', error)
}
}
})
}
// 组件挂载时初始化数据
onMounted(() => {
initData()
})
</script>
<style scoped>

View File

@@ -110,43 +110,13 @@
<div class="update-section">
<a-card class="update-card" title="数据更新信息">
<a-list>
<a-list-item>
<a-list-item v-for="(item, index) in updates" :key="index">
<div class="update-item">
<div class="update-icon blue"></div>
<div class="update-content">
<div class="update-title">市场行情数据更新</div>
<div class="update-time">2024-04-10 15:30:00</div>
<div class="update-desc">更新全国主要地区牛肉牛奶饲料价格数据</div>
</div>
</div>
</a-list-item>
<a-list-item>
<div class="update-item">
<div class="update-icon green"></div>
<div class="update-content">
<div class="update-title">养殖户数据同步</div>
<div class="update-time">2024-04-10 10:15:00</div>
<div class="update-desc">新增56家养殖户信息更新32家养殖户状态</div>
</div>
</div>
</a-list-item>
<a-list-item>
<div class="update-item">
<div class="update-icon orange"></div>
<div class="update-content">
<div class="update-title">产品认证数据导入</div>
<div class="update-time">2024-04-09 16:45:00</div>
<div class="update-desc">导入120条生资产品认证信息</div>
</div>
</div>
</a-list-item>
<a-list-item>
<div class="update-item">
<div class="update-icon red"></div>
<div class="update-content">
<div class="update-title">疫病监测数据更新</div>
<div class="update-time">2024-04-09 09:20:00</div>
<div class="update-desc">更新本周疫病监测数据暂无异常情况</div>
<div class="update-title">数据更新</div>
<div class="update-time">{{ item.time }}</div>
<div class="update-desc">{{ item.content }}</div>
</div>
</div>
</a-list-item>
@@ -157,14 +127,22 @@
</template>
<script setup>
import { ref, onMounted } from 'vue'
import * as echarts from 'echarts'
import { ref, onMounted } from 'vue';
import * as echarts from 'echarts';
import axios from 'axios';
// 数据统计
const 养殖户总数 = ref('8,256')
const 存栏总量 = ref('426,831头')
const 交易量 = ref(3.26亿')
const 活跃用户 = ref('12,548')
const 养殖户总数 = ref('0')
const 存栏总量 = ref('0头')
const 交易量 = ref(0')
const 活跃用户 = ref('0')
const updates = ref([])
// 图表数据
const monthlyTrends = ref([])
const categoryDistribution = ref([])
const regionDistribution = ref([])
const scaleDistribution = ref([])
// 图表引用
const mapChartRef = ref(null)
@@ -174,7 +152,7 @@ const categoryChartRef = ref(null)
// 初始化交易量趋势图表
const initTransactionChart = () => {
if (!transactionChartRef.value) return
if (!transactionChartRef.value || !monthlyTrends.value.length) return
const chart = echarts.init(transactionChartRef.value)
@@ -191,7 +169,7 @@ const initTransactionChart = () => {
xAxis: {
type: 'category',
boundaryGap: false,
data: ['1月', '2月', '3月', '4月', '5月', '6月']
data: monthlyTrends.value.map(item => item.month)
},
yAxis: {
type: 'value',
@@ -211,7 +189,7 @@ const initTransactionChart = () => {
emphasis: {
focus: 'series'
},
data: [2.8, 3.1, 3.5, 3.26, 3.4, 3.6],
data: monthlyTrends.value.map(item => item.value / 10000),
itemStyle: {
color: '#3a4de9'
},
@@ -234,7 +212,7 @@ const initTransactionChart = () => {
// 初始化品类占比图表
const initCategoryChart = () => {
if (!categoryChartRef.value) return
if (!categoryChartRef.value || !categoryDistribution.value.length) return
const chart = echarts.init(categoryChartRef.value)
@@ -272,12 +250,7 @@ const initCategoryChart = () => {
labelLine: {
show: false
},
data: [
{ value: 45, name: '肉牛养殖', itemStyle: { color: '#3a4de9' } },
{ value: 30, name: '奶牛养殖', itemStyle: { color: '#4cd137' } },
{ value: 15, name: '犊牛养殖', itemStyle: { color: '#e1b12c' } },
{ value: 10, name: '其他养殖', itemStyle: { color: '#44bd32' } }
]
data: categoryDistribution.value
}
]
}
@@ -291,7 +264,7 @@ const initCategoryChart = () => {
// 初始化养殖区域分布图表
const initMapChart = () => {
if (!mapChartRef.value) return
if (!mapChartRef.value || !regionDistribution.value.length) return
const chart = echarts.init(mapChartRef.value)
@@ -303,7 +276,7 @@ const initMapChart = () => {
legend: {
bottom: '5%',
left: 'center',
data: ['东北地区', '华北地区', '华东地区', '华南地区', '西南地区', '西北地区']
data: regionDistribution.value.map(item => item.name)
},
series: [
{
@@ -330,14 +303,7 @@ const initMapChart = () => {
labelLine: {
show: false
},
data: [
{ value: 28, name: '东北地区', itemStyle: { color: '#3a4de9' } },
{ value: 22, name: '华北地区', itemStyle: { color: '#4cd137' } },
{ value: 18, name: '华东地区', itemStyle: { color: '#e1b12c' } },
{ value: 12, name: '华南地区', itemStyle: { color: '#44bd32' } },
{ value: 15, name: '西南地区', itemStyle: { color: '#0097e6' } },
{ value: 5, name: '西北地区', itemStyle: { color: '#8c7ae6' } }
]
data: regionDistribution.value
}
]
}
@@ -351,7 +317,7 @@ const initMapChart = () => {
// 初始化养殖规模分布图表
const initScaleChart = () => {
if (!scaleChartRef.value) return
if (!scaleChartRef.value || !scaleDistribution.value.length) return
const chart = echarts.init(scaleChartRef.value)
@@ -370,7 +336,7 @@ const initScaleChart = () => {
},
xAxis: {
type: 'category',
data: ['小型养殖场(50头)', '中型养殖场(50-200头)', '大型养殖场(200头)']
data: scaleDistribution.value.map(item => item.name)
},
yAxis: {
type: 'value',
@@ -381,7 +347,7 @@ const initScaleChart = () => {
name: '养殖场数量',
type: 'bar',
barWidth: '60%',
data: [6850, 1250, 156],
data: scaleDistribution.value.map(item => item.value),
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#3a4de9' },
@@ -399,15 +365,41 @@ const initScaleChart = () => {
})
}
// 组件挂载时初始化所有图表
// 从API获取数据
const fetchData = async () => {
try {
const response = await axios.get('/api/government/data-center');
const data = response.data;
// 更新统计数据
养殖户总数.value = data.totalFarmers.toLocaleString();
存栏总量.value = `${data.totalAnimals.toLocaleString()}`;
交易量.value = `¥${(data.totalTransactions / 10000).toFixed(2)}亿`;
活跃用户.value = data.activeUsers.toLocaleString();
// 更新图表数据
monthlyTrends.value = data.monthlyTrends;
categoryDistribution.value = data.categoryDistribution;
regionDistribution.value = data.regionDistribution;
scaleDistribution.value = data.scaleDistribution;
updates.value = data.updates;
// 初始化所有图表
setTimeout(() => {
initTransactionChart();
initCategoryChart();
initMapChart();
initScaleChart();
}, 100);
} catch (error) {
console.error('获取数据失败:', error);
}
}
// 组件挂载时获取数据并初始化图表
onMounted(() => {
setTimeout(() => {
initTransactionChart()
initCategoryChart()
initMapChart()
initScaleChart()
}, 100)
})
fetchData();
});
</script>
<style scoped>

View File

@@ -2,7 +2,7 @@
<div class="market-price-container">
<!-- 产品类型选项卡 -->
<div class="product-tabs">
<a-tabs v-model:activeKey="activeProductTab">
<a-tabs v-model:activeKey="activeProductTab" @change="handleTabChange">
<a-tab-pane key="beef" tab="育肥牛"></a-tab-pane>
<a-tab-pane key="dairy" tab="繁殖牛"></a-tab-pane>
<a-tab-pane key="milk" tab="奶牛"></a-tab-pane>
@@ -17,7 +17,7 @@
<template #title>
<div class="card-title">
<span>本市{{ productTypeText }}价格</span>
<span class="price-date">2025-01-01</span>
<span class="price-date">{{ priceDate }}</span>
</div>
</template>
<div class="price-info">
@@ -26,8 +26,12 @@
<span class="price-unit">/公斤</span>
</div>
<div class="price-change">
<span class="change-value">+0.30</span>
<span class="change-percent">+1.32%</span>
<span class="change-value" :style="{ color: isPriceIncrease ? '#52c41a' : '#ff4d4f' }">
{{ priceChange }}
</span>
<span class="change-percent" :style="{ color: isPriceIncrease ? '#52c41a' : '#ff4d4f' }">
{{ priceChangePercent }}
</span>
</div>
</div>
</a-card>
@@ -50,12 +54,30 @@
</template>
<script setup>
import { ref, computed, onMounted } from 'vue'
import { ref, computed, onMounted, watch } from 'vue'
import * as echarts from 'echarts'
import axios from 'axios'
// 当前选中的产品类型
const activeProductTab = ref('beef')
// 响应式数据
const currentPrice = ref('--')
const priceChange = ref('--')
const priceChangePercent = ref('--')
const priceDate = ref('--')
const priceTrendData = ref([])
const provincePricesData = ref([])
const isPriceIncrease = ref(true)
// 图表引用
const priceChartRef = ref(null)
const provinceChartRef = ref(null)
// 图表实例
let priceChart = null
let provinceChart = null
// 产品类型文本映射
const productTypeText = computed(() => {
const map = {
@@ -66,25 +88,57 @@ const productTypeText = computed(() => {
return map[activeProductTab.value] || '育肥牛'
})
// 当前价格
const currentPrice = ref('--')
// 从后端获取市场行情数据
const fetchMarketPriceData = async (type = 'beef') => {
try {
const response = await axios.get('/api/government/market-price', {
params: { type }
})
const data = response.data
// 更新数据
currentPrice.value = data.currentPrice
priceChange.value = data.priceChange
priceChangePercent.value = data.priceChangePercent
priceDate.value = data.priceDate
priceTrendData.value = data.priceTrend
provincePricesData.value = data.provincePrices
// 判断价格是否上涨
isPriceIncrease.value = data.priceChange.startsWith('+')
// 初始化或更新图表
updatePriceChart()
updateProvinceChart()
} catch (error) {
console.error('获取市场行情数据失败:', error)
}
}
// 图表引用
const priceChartRef = ref(null)
const provinceChartRef = ref(null)
// 初始化价格走势图表
const initPriceChart = () => {
// 初始化或更新价格走势图表
const updatePriceChart = () => {
if (!priceChartRef.value) return
const chart = echarts.init(priceChartRef.value)
// 如果图表实例不存在,则创建
if (!priceChart) {
priceChart = echarts.init(priceChartRef.value)
// 添加窗口大小改变时的响应式调整
window.addEventListener('resize', () => {
if (priceChart) {
priceChart.resize()
}
})
}
// 模拟历史价格数据
const dates = ['2024-12-19', '2024-12-20', '2024-12-21', '2024-12-22', '2024-12-23',
'2024-12-24', '2024-12-25', '2024-12-26', '2024-12-27', '2024-12-28',
'2024-12-29', '2024-12-30', '2024-12-31', '2025-01-01']
// 提取日期和价格数据
const dates = priceTrendData.value.map(item => item.date)
const prices = priceTrendData.value.map(item => item.price)
const prices = [23.10, 20.65, 24.90, 21.78, 22.15, 24.30, 23.20, 21.60, 20.35, 24.05, 23.45, 20.95, 22.50, 21.80]
// 计算Y轴范围
const minPrice = Math.min(...prices) * 0.9
const maxPrice = Math.max(...prices) * 1.1
const option = {
tooltip: {
@@ -111,9 +165,9 @@ const initPriceChart = () => {
},
yAxis: {
type: 'value',
min: 0,
max: 25,
interval: 5
min: Math.floor(minPrice),
max: Math.ceil(maxPrice),
interval: Math.ceil((maxPrice - minPrice) / 5)
},
series: [
{
@@ -136,24 +190,31 @@ const initPriceChart = () => {
]
}
chart.setOption(option)
// 响应式调整
window.addEventListener('resize', () => {
chart.resize()
})
priceChart.setOption(option)
}
// 初始化各省价格对比图表
const initProvinceChart = () => {
// 初始化或更新各省价格对比图表
const updateProvinceChart = () => {
if (!provinceChartRef.value) return
const chart = echarts.init(provinceChartRef.value)
// 如果图表实例不存在,则创建
if (!provinceChart) {
provinceChart = echarts.init(provinceChartRef.value)
// 添加窗口大小改变时的响应式调整
window.addEventListener('resize', () => {
if (provinceChart) {
provinceChart.resize()
}
})
}
// 模拟各省价格数据
const provinces = ['上海市', '云南省', '内蒙古自治区', '北京市', '吉林省', '四川省', '天津市', '宁夏回族自治区', '安徽省', '山东省', '山西省', '广东省', '广西壮族自治区', '新疆维吾尔自治区', '江苏省', '江西省', '河北省', '河南省', '浙江省', '海南省', '湖北省', '湖南省', '甘肃省', '福建省', '贵州省', '辽宁省', '重庆市', '陕西省', '青海省', '黑龙江省']
// 提取省份和价格数据
const provinces = provincePricesData.value.map(item => item.province)
const prices = provincePricesData.value.map(item => item.price)
const prices = [36, 34.85, 34.85, 35.7, 33.26, 34.9, 35.4, 36.51, 33.5, 35.4, 35.8, 35.3, 32.6, 35.8, 34.1, 35.2, 33.2, 36, 35, 35.4, 32, 33.2, 34.8, 32.86, 32.7, 33, 32.8, 33.4, 33, 35.4]
// 计算X轴范围
const maxPrice = Math.max(...prices) * 1.1
const option = {
tooltip: {
@@ -172,8 +233,8 @@ const initProvinceChart = () => {
xAxis: {
type: 'value',
min: 0,
max: 40,
interval: 10
max: Math.ceil(maxPrice),
interval: Math.ceil(maxPrice / 5)
},
yAxis: {
type: 'category',
@@ -198,25 +259,34 @@ const initProvinceChart = () => {
]
}
chart.setOption(option)
// 响应式调整
window.addEventListener('resize', () => {
chart.resize()
})
provinceChart.setOption(option)
}
// 组件挂载时初始化图表
// 处理选项卡切换
const handleTabChange = (key) => {
activeProductTab.value = key
fetchMarketPriceData(key)
}
// 组件挂载时初始化数据和图表
onMounted(() => {
// 设置当前价格
currentPrice.value = '23.10'
// 初始化图表
// 延迟执行确保DOM已完全渲染
setTimeout(() => {
initPriceChart()
initProvinceChart()
fetchMarketPriceData(activeProductTab.value)
}, 100)
})
// 组件卸载时销毁图表实例
const onUnmounted = () => {
if (priceChart) {
priceChart.dispose()
priceChart = null
}
if (provinceChart) {
provinceChart.dispose()
provinceChart = null
}
}
</script>
<style scoped>

View File

@@ -0,0 +1,52 @@
// 从前端目录测试API访问
const axios = require('axios');
// 创建axios实例使用与前端相同的配置
const api = axios.create({
baseURL: 'http://localhost:5352/api',
timeout: 5000,
headers: {
'Content-Type': 'application/json'
}
});
async function testApi() {
try {
console.log('开始从前端目录测试API...');
// 测试行政人员列表API
console.log('\n测试行政人员列表API:');
const adminStaffResponse = await api.get('/government/admin-staff');
console.log(`✅ 行政人员列表API调用成功返回${adminStaffResponse.data.length}条数据`);
// 测试部门列表API
console.log('\n测试部门列表API:');
const departmentResponse = await api.get('/government/departments');
console.log(`✅ 部门列表API调用成功返回${departmentResponse.data.length}条数据`);
// 测试岗位列表API
console.log('\n测试岗位列表API:');
const positionResponse = await api.get('/government/positions');
console.log(`✅ 岗位列表API调用成功返回${positionResponse.data.length}条数据`);
// 测试带有查询参数的API
console.log('\n测试带查询参数的API:');
const filteredResponse = await api.get('/government/admin-staff?page=1&pageSize=3');
console.log(`✅ 带查询参数的API调用成功返回${filteredResponse.data.length}条数据`);
console.log('\n✅ 所有API测试成功完成');
} catch (error) {
console.error('❌ API测试失败:', error.message);
if (error.response) {
console.error('错误状态码:', error.response.status);
console.error('错误数据:', error.response.data);
} else if (error.request) {
console.error('没有收到响应:', error.request);
} else {
console.error('请求配置错误:', error.message);
}
console.error('错误详情:', error);
}
}
testApi();