实现国资管理框架,资产清查数据获取

This commit is contained in:
2025-11-03 18:22:42 +08:00
parent 5a1daebbd9
commit b959ce3331
10 changed files with 1595 additions and 353 deletions

2
.gitignore vendored
View File

@@ -166,3 +166,5 @@ coverage
*.sw?
*.tsbuildinfo
/src/components/*

View File

@@ -218,35 +218,41 @@ const router = createRouter({
]
},
{
path: '/admin/business',
name: 'admin-business',
component: () => import('../views/Admin/BusinessManagementView.vue'),
path: '/admin/business/state-assets',
name: 'admin-business-state-assets',
component: () => import('../views/Admin/Business/StateAssetsView.vue'),
meta: { requiresAuth: true }
},
{
path: '/admin/business/state-assets/main',
name: 'admin-business-state-assets-main',
component: () => import('../views/Admin/Business/StateAssetsMainView.vue'),
meta: { requiresAuth: true },
children: [
{
path: '',
redirect: '/admin/business/state-assets'
redirect: '/admin/business/state-assets/main/province-check'
},
{
path: 'state-assets',
name: 'admin-business-state-assets',
component: () => import('../views/Admin/Business/StateAssetsView.vue'),
meta: { requiresAuth: true }
},
{
path: 'library',
name: 'admin-business-library',
component: () => import('../views/Admin/Business/LibraryView.vue'),
meta: { requiresAuth: true }
},
{
path: 'laboratory',
name: 'admin-business-laboratory',
component: () => import('../views/Admin/Business/LaboratoryView.vue'),
path: 'province-check',
name: 'admin-business-state-assets-province-check',
component: () => import('../views/Admin/Business/ProvinceAssetsCheckView.vue'),
meta: { requiresAuth: true }
}
]
},
{
path: '/admin/business/library',
name: 'admin-business-library',
component: () => import('../views/Admin/Business/LibraryView.vue'),
meta: { requiresAuth: true }
},
{
path: '/admin/business/laboratory',
name: 'admin-business-laboratory',
component: () => import('../views/Admin/Business/LaboratoryView.vue'),
meta: { requiresAuth: true }
},
{
path: '/home',
name: 'home',
@@ -275,10 +281,10 @@ const router = createRouter({
// 路由守卫
router.beforeEach((to, from, next) => {
const authStore = useAuthStore()
// 初始化认证状态
authStore.initAuth()
// 检查是否需要认证
if (to.meta.requiresAuth) {
if (authStore.isLoggedIn && authStore.checkToken()) {

224
src/services/assetsApi.js Normal file
View File

@@ -0,0 +1,224 @@
/**
* 资产清查API服务
* 基于参考文件 zcqc2025.js 的API调用逻辑
*/
// API基础配置
const API_BASE_URL = 'https://www.tcjwj.com/sz/logintest/jwjDataService.asmx'
const TABLE_NAME = 'Zcqc_2025_Zckp'
/**
* 解析API返回的数据
* @param {string} data - API返回的原始数据
* @returns {Array} 解析后的JSON数组
*/
function parseApiResponse(data) {
try {
const startIndex = data.indexOf('[')
const endIndex = data.indexOf(']</string>')
if (startIndex === -1 || endIndex === -1) {
console.error('API响应格式错误:', data)
return []
}
return JSON.parse(data.slice(startIndex, endIndex + 1))
} catch (error) {
console.error('解析API响应失败:', error)
return []
}
}
/**
* 构建查询条件JSON字符串
* @param {string} tabType - 标签类型 (all, uncheck, nochange, profit, loss, adjust, error)
* @param {string} quickSearch - 快速搜索关键词
* @returns {string} 查询条件JSON字符串
*/
function buildSearchJson(tabType = 'all', quickSearch = '') {
let searchJson = '[{"column":"ID","operator":">=","value":"0"}'
// 根据标签类型添加过滤条件
switch (tabType) {
case 'uncheck':
searchJson += ',{"column":"PdTypes","operator":"=","value":""}'
break
case 'nochange':
searchJson += ',{"column":"PdTypes","operator":"=","value":"无盈亏"}'
break
case 'profit':
searchJson += ',{"column":"PdTypes","operator":"=","value":"盘盈"}'
break
case 'loss':
searchJson += ',{"column":"PdTypes","operator":"=","value":"损失"}'
break
case 'adjust':
searchJson += ',{"column":"PdTypes","operator":"=","value":"错账调整"}'
break
case 'error':
searchJson += ',{"column":"PdTypes","operator":"=","value":"错误待处理"}'
break
// 'all' 不需要额外条件
}
// 添加快速搜索条件
if (quickSearch && quickSearch.trim()) {
searchJson += `,{"column":"Fixtureno","operator":"like","value":"${quickSearch.trim()}"}`
}
searchJson += ']'
return searchJson
}
/**
* 获取登录状态
* @returns {string|null} 登录代码
*/
function getLoginCode() {
return localStorage.getItem('loginState') || localStorage.getItem('loginCode')
}
/**
* 获取资产清查数据
* @param {Object} params - 查询参数
* @param {string} params.tabType - 标签类型
* @param {number} params.pageIndex - 页码 (从1开始)
* @param {string} params.quickSearch - 快速搜索关键词
* @returns {Promise<Array>} 资产数据数组
*/
export async function getAssetsData(params = {}) {
const {
tabType = 'all',
pageIndex = 1,
quickSearch = ''
} = params
const loginCode = getLoginCode()
if (!loginCode) {
throw new Error('未找到登录状态,请先登录')
}
const searchJson = buildSearchJson(tabType, quickSearch)
const formData = new URLSearchParams()
formData.append('tablename', TABLE_NAME)
formData.append('loginCode', loginCode)
formData.append('nowpageindex', pageIndex.toString())
formData.append('serializeJson', searchJson)
try {
const response = await fetch(`${API_BASE_URL}/ReTurnZcpdMain`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: formData.toString()
})
if (!response.ok) {
throw new Error(`HTTP错误: ${response.status}`)
}
const data = await response.text()
return parseApiResponse(data)
} catch (error) {
console.error('获取资产数据失败:', error)
throw error
}
}
/**
* 获取单个资产详情
* @param {string|number} assetId - 资产ID
* @returns {Promise<Object|null>} 资产详情对象
*/
export async function getAssetDetail(assetId) {
const loginCode = getLoginCode()
if (!loginCode) {
throw new Error('未找到登录状态,请先登录')
}
const searchJson = `[{"column":"ID","operator":"=","value":"${assetId}"}]`
const formData = new URLSearchParams()
formData.append('tablename', TABLE_NAME)
formData.append('loginCode', loginCode)
formData.append('nowpageindex', '1')
formData.append('serializeJson', searchJson)
try {
const response = await fetch(`${API_BASE_URL}/ReTurnZcpdMain`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: formData.toString()
})
if (!response.ok) {
throw new Error(`HTTP错误: ${response.status}`)
}
const data = await response.text()
const assets = parseApiResponse(data)
return assets.length > 0 ? assets[0] : null
} catch (error) {
console.error('获取资产详情失败:', error)
throw error
}
}
/**
* 资产数据字段映射
* 将API返回的字段映射为更友好的显示名称
*/
export const ASSET_FIELD_MAP = {
ID: 'id',
Classifyno: 'classification',
Fixtureno: 'internalNumber',
Code: 'externalNumber',
Name: 'name',
Specify: 'specification',
Src: 'acquisitionMethod',
Buydate: 'acquisitionDate',
ZcType: 'assetType',
Office: 'department',
UserName: 'user',
Field2: 'location',
State: 'status',
IsOutZc: 'isOffBook',
Num: 'bookQuantity',
Price: 'bookOriginalValue',
Ljzj: 'bookAccumulatedDepreciation',
PriceJz: 'bookNetValue',
QcNum: 'checkQuantity',
QcPrice: 'checkOriginalValue',
QcLjzj: 'checkAccumulatedDepreciation',
QcPriceJz: 'checkNetValue',
PdTypes: 'changeReason',
BdkRemarks: 'specificReason',
Remarks: 'remarks'
}
/**
* 转换资产数据格式
* @param {Object} rawAsset - 原始资产数据
* @returns {Object} 转换后的资产数据
*/
export function transformAssetData(rawAsset) {
const transformed = {}
Object.keys(ASSET_FIELD_MAP).forEach(key => {
const mappedKey = ASSET_FIELD_MAP[key]
transformed[mappedKey] = rawAsset[key] || ''
})
return transformed
}
/**
* 批量转换资产数据
* @param {Array} rawAssets - 原始资产数据数组
* @returns {Array} 转换后的资产数据数组
*/
export function transformAssetsData(rawAssets) {
return rawAssets.map(transformAssetData)
}

View File

@@ -1,39 +1,89 @@
<template>
<div class="laboratory-content">
<el-card>
<template #header>
<div class="card-header">
<span class="card-title">
<el-icon>
<Operation />
</el-icon>
实验室管理
</span>
</div>
</template>
<div class="laboratory-page">
<!-- 页面头部 -->
<div class="page-header">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/admin/dashboard' }">后台首页</el-breadcrumb-item>
<el-breadcrumb-item>业务后台</el-breadcrumb-item>
<el-breadcrumb-item>实验室管理</el-breadcrumb-item>
</el-breadcrumb>
<div class="header-actions">
<el-button @click="goBackToDashboard">
<el-icon>
<ArrowLeft />
</el-icon>
返回后台首页
</el-button>
</div>
</div>
<el-empty description="实验室管理功能开发中..." :image-size="200">
<el-descriptions title="功能说明" :column="1" border>
<el-descriptions-item label="功能模块">实验室管理</el-descriptions-item>
<el-descriptions-item label="主要功能">
实验室信息管理实验设备管理实验项目管理实验预约系统安全管理记录耗材库存管理等
</el-descriptions-item>
<el-descriptions-item label="开发状态">
<el-tag type="warning">待开发</el-tag>
</el-descriptions-item>
</el-descriptions>
</el-empty>
</el-card>
<!-- 页面内容 -->
<div class="page-content">
<el-card>
<template #header>
<div class="card-header">
<span class="card-title">
<el-icon>
<Operation />
</el-icon>
实验室管理
</span>
</div>
</template>
<el-empty description="实验室管理功能开发中..." :image-size="200">
<el-descriptions title="功能说明" :column="1" border>
<el-descriptions-item label="功能模块">实验室管理</el-descriptions-item>
<el-descriptions-item label="主要功能">
实验室信息管理实验设备管理实验项目管理实验预约系统安全管理记录耗材库存管理等
</el-descriptions-item>
<el-descriptions-item label="开发状态">
<el-tag type="warning">待开发</el-tag>
</el-descriptions-item>
</el-descriptions>
</el-empty>
</el-card>
</div>
</div>
</template>
<script setup>
import { Operation } from '@element-plus/icons-vue'
import { useRouter } from 'vue-router'
import { Operation, ArrowLeft } from '@element-plus/icons-vue'
const router = useRouter()
// 返回后台首页
const goBackToDashboard = () => {
router.push('/admin/dashboard')
}
</script>
<style scoped>
.laboratory-content {
padding: 0;
.laboratory-page {
min-height: 100vh;
background-color: #f0f2f5;
padding: 20px;
}
.page-header {
background-color: #fff;
padding: 16px 20px;
margin-bottom: 20px;
border-radius: 8px;
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
display: flex;
justify-content: space-between;
align-items: center;
}
.header-actions {
display: flex;
gap: 12px;
}
.page-content {
background-color: transparent;
}
.card-header {
@@ -48,5 +98,24 @@ import { Operation } from '@element-plus/icons-vue'
display: flex;
align-items: center;
gap: 8px;
color: #303133;
}
/* 响应式设计 */
@media (max-width: 768px) {
.laboratory-page {
padding: 10px;
}
.page-header {
flex-direction: column;
gap: 12px;
align-items: flex-start;
}
.header-actions {
width: 100%;
justify-content: flex-end;
}
}
</style>

View File

@@ -1,39 +1,89 @@
<template>
<div class="library-content">
<el-card>
<template #header>
<div class="card-header">
<span class="card-title">
<el-icon>
<Reading />
</el-icon>
图情管理
</span>
</div>
</template>
<div class="library-page">
<!-- 页面头部 -->
<div class="page-header">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/admin/dashboard' }">后台首页</el-breadcrumb-item>
<el-breadcrumb-item>业务后台</el-breadcrumb-item>
<el-breadcrumb-item>图情管理</el-breadcrumb-item>
</el-breadcrumb>
<div class="header-actions">
<el-button @click="goBackToDashboard">
<el-icon>
<ArrowLeft />
</el-icon>
返回后台首页
</el-button>
</div>
</div>
<el-empty description="图情管理功能开发中..." :image-size="200">
<el-descriptions title="功能说明" :column="1" border>
<el-descriptions-item label="功能模块">图情管理</el-descriptions-item>
<el-descriptions-item label="主要功能">
图书资料管理期刊订阅管理电子资源管理借阅记录管理读者信息管理馆藏统计分析等
</el-descriptions-item>
<el-descriptions-item label="开发状态">
<el-tag type="warning">待开发</el-tag>
</el-descriptions-item>
</el-descriptions>
</el-empty>
</el-card>
<!-- 页面内容 -->
<div class="page-content">
<el-card>
<template #header>
<div class="card-header">
<span class="card-title">
<el-icon>
<Reading />
</el-icon>
图情管理
</span>
</div>
</template>
<el-empty description="图情管理功能开发中..." :image-size="200">
<el-descriptions title="功能说明" :column="1" border>
<el-descriptions-item label="功能模块">图情管理</el-descriptions-item>
<el-descriptions-item label="主要功能">
图书资料管理期刊订阅管理电子资源管理借阅记录管理读者信息管理馆藏统计分析等
</el-descriptions-item>
<el-descriptions-item label="开发状态">
<el-tag type="warning">待开发</el-tag>
</el-descriptions-item>
</el-descriptions>
</el-empty>
</el-card>
</div>
</div>
</template>
<script setup>
import { Reading } from '@element-plus/icons-vue'
import { useRouter } from 'vue-router'
import { Reading, ArrowLeft } from '@element-plus/icons-vue'
const router = useRouter()
// 返回后台首页
const goBackToDashboard = () => {
router.push('/admin/dashboard')
}
</script>
<style scoped>
.library-content {
padding: 0;
.library-page {
min-height: 100vh;
background-color: #f0f2f5;
padding: 20px;
}
.page-header {
background-color: #fff;
padding: 16px 20px;
margin-bottom: 20px;
border-radius: 8px;
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
display: flex;
justify-content: space-between;
align-items: center;
}
.header-actions {
display: flex;
gap: 12px;
}
.page-content {
background-color: transparent;
}
.card-header {
@@ -48,5 +98,24 @@ import { Reading } from '@element-plus/icons-vue'
display: flex;
align-items: center;
gap: 8px;
color: #303133;
}
</style>
/* 响应式设计 */
@media (max-width: 768px) {
.library-page {
padding: 10px;
}
.page-header {
flex-direction: column;
gap: 12px;
align-items: flex-start;
}
.header-actions {
width: 100%;
justify-content: flex-end;
}
}
</style>

View File

@@ -0,0 +1,422 @@
<template>
<div class="province-assets-check">
<!-- 主要内容区域 -->
<div class="main-content">
<!-- 主内容区域 -->
<div class="content-area" :class="{ 'full-width': !showDepartmentPanel }">
<!-- 状态标签栏 -->
<div class="status-tabs">
<el-tabs v-model="activeTab" @tab-click="handleTabClick" class="custom-tabs">
<el-tab-pane label="全部" name="all" />
<el-tab-pane label="未盘点" name="unchecked" />
<el-tab-pane label="无盈亏" name="no-change" />
<el-tab-pane label="盘盈" name="surplus" />
<el-tab-pane label="损失" name="loss" />
<el-tab-pane label="错账调整" name="adjustment" />
<el-tab-pane label="错误待处理" name="error-pending" />
</el-tabs>
</div>
<!-- 操作栏 -->
<div class="action-bar">
<div class="action-left">
<el-button type="primary" :icon="Search" @click="handleQuery">查询</el-button>
<el-button type="success" :icon="Plus" @click="handleAddSurplus">增加盘盈</el-button>
<el-button type="warning" :icon="Document" @click="handleInventoryCheck">资产盘点</el-button>
</div>
<div class="action-right">
<div class="quick-search">
<el-input v-model="quickSearch" placeholder="输入资产编号快速查询" style="width: 200px; margin-right: 10px;"
@keyup.enter="handleQuickSearch" clearable>
<template #append>
<el-button :icon="Search" @click="handleQuickSearch" />
</template>
</el-input>
</div>
</div>
</div>
<!-- 表格区域 -->
<div class="table-container">
<el-table :data="tableData" v-loading="loading" stripe border class="assets-table" height="calc(100vh - 320px)"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" fixed="left" />
<el-table-column prop="serialNumber" label="序号" width="80" fixed="left" />
<el-table-column prop="assetCategory" label="资产分类" width="120" show-overflow-tooltip fixed="left" />
<el-table-column prop="internalNumber" label="内部编号" width="150" show-overflow-tooltip fixed="left" />
<el-table-column prop="assetName" label="资产名称" width="200" show-overflow-tooltip fixed="left" />
<el-table-column prop="acquisitionMethod" label="取得方式" width="120" />
<el-table-column prop="acquisitionDate" label="取得日期" width="120" />
<el-table-column prop="assetType" label="归口类别" width="120" />
<el-table-column prop="usingDepartment" label="使用部门" width="150" show-overflow-tooltip />
<el-table-column prop="user" label="使用人" width="100" />
<el-table-column prop="storageLocation" label="存放地点" width="150" show-overflow-tooltip />
<el-table-column prop="usageStatus" label="使用状况" width="100" />
<el-table-column prop="isOffBook" label="是否账外" width="100" />
<!-- 账面价值组 -->
<el-table-column label="账面价值" align="center">
<el-table-column prop="bookQuantity" label="数量" width="80" />
<el-table-column prop="bookOriginalValue" label="原值" width="120" />
<el-table-column prop="bookAccumulatedDepreciation" label="累计折旧" width="120" />
<el-table-column prop="bookNetValue" label="净值" width="120" />
</el-table-column>
<!-- 盘点价值组 -->
<el-table-column label="盘点价值" align="center">
<el-table-column prop="checkQuantity" label="数量" width="80" />
<el-table-column prop="checkOriginalValue" label="原值" width="120" />
<el-table-column prop="checkAccumulatedDepreciation" label="累计折旧" width="120" />
<el-table-column prop="checkNetValue" label="净值" width="120" />
</el-table-column>
<el-table-column prop="changeReason" label="变动原因" width="120" />
<el-table-column prop="specificReason" label="具体原因" width="200" show-overflow-tooltip />
<el-table-column prop="remarks" label="备注" width="200" show-overflow-tooltip />
<el-table-column label="操作" width="80" fixed="right">
<template #default="scope">
<el-button type="primary" size="small" @click="handleEdit(scope.row)">编辑</el-button>
</template>
</el-table-column>
</el-table>
</div>
<!-- 分页 -->
<div class="pagination-container">
<el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize" :page-sizes="[10, 20, 50, 100]"
:total="totalCount" layout="total, prev, pager, next, jumper" @size-change="handleSizeChange"
@current-change="handleCurrentChange" class="custom-pagination" />
</div>
</div>
</div>
</div>
</template>
<script setup>
import { getAssetsData, transformAssetsData } from '@/services/assetsApi'
import {
Document,
Plus,
Search
} from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import { onMounted, ref } from 'vue'
// 响应式数据
const showDepartmentPanel = ref(true)
const activeTab = ref('all')
const loading = ref(false)
const currentPage = ref(1)
const pageSize = ref(50)
const totalCount = ref(1000)
const selectedRows = ref([])
const quickSearch = ref('')
// 表格数据
const tableData = ref([])
// 加载函数
const loadTableData = async () => {
loading.value = true
try {
const rawData = await getAssetsData({
tabType: activeTab.value,
pageIndex: currentPage.value,
quickSearch: quickSearch.value
})
// 转换数据格式
const transformedData = transformAssetsData(rawData)
// 映射到表格显示格式
tableData.value = transformedData.map((item, index) => ({
id: item.id,
serialNumber: (currentPage.value - 1) * pageSize.value + index + 1,
assetCategory: item.classification || '',
internalNumber: item.internalNumber || '',
assetName: item.name || '',
acquisitionMethod: item.acquisitionMethod || '',
acquisitionDate: item.acquisitionDate || '',
assetType: item.assetType || '',
usingDepartment: item.department || '',
user: item.user || '',
storageLocation: item.location || '',
usageStatus: item.status || '',
isOffBook: item.isOffBook || '否',
bookQuantity: item.bookQuantity || 0,
bookOriginalValue: item.bookOriginalValue || 0,
bookAccumulatedDepreciation: item.bookAccumulatedDepreciation || 0,
bookNetValue: item.bookNetValue || 0,
checkQuantity: item.checkQuantity || 0,
checkOriginalValue: item.checkOriginalValue || 0,
checkAccumulatedDepreciation: item.checkAccumulatedDepreciation || 0,
checkNetValue: item.checkNetValue || 0,
changeReason: item.changeReason || '',
specificReason: item.specificReason || '',
remarks: item.remarks || ''
}))
ElMessage.success(`成功加载 ${rawData.length} 条数据`)
} catch (error) {
console.error('加载数据失败:', error)
ElMessage.error(`加载数据失败: ${error.message}`)
} finally {
loading.value = false
}
}
const handleTabClick = (tab) => {
activeTab.value = tab.name
currentPage.value = 1 // 重置到第一页
loadTableData()
}
const handleQuickSearch = () => {
currentPage.value = 1 // 重置到第一页
loadTableData()
}
const handleAddSurplus = () => {
ElMessage.info('打开增加盘盈对话框')
}
const handleInventoryCheck = () => {
if (selectedRows.value.length === 0) {
ElMessage.warning('请先选择要盘点的资产')
return
}
ElMessage.info(`${selectedRows.value.length} 项资产进行盘点`)
}
const handleSelectionChange = (selection) => {
selectedRows.value = selection
}
const handleEdit = (row) => {
ElMessage.info(`编辑资产: ${row.assetName}`)
}
const handleSizeChange = (val) => {
pageSize.value = val
currentPage.value = 1 // 重置到第一页
loadTableData()
}
const handleCurrentChange = (val) => {
currentPage.value = val
loadTableData()
}
// 生命周期
onMounted(() => {
loadTableData()
})
</script>
<style scoped>
.province-assets-check {
height: 100%;
display: flex;
flex-direction: column;
background: #f5f7fa;
}
.main-content {
flex: 1;
display: flex;
overflow: hidden;
}
/* 主内容区域样式 */
.content-area {
flex: 1;
display: flex;
flex-direction: column;
background: white;
overflow: hidden;
transition: all 0.3s ease;
}
.content-area.full-width {
margin-left: 70px;
}
.status-tabs {
padding: 20px 20px 0;
border-bottom: 1px solid #e4e7ed;
}
.custom-tabs :deep(.el-tabs__header) {
margin: 0;
}
.custom-tabs :deep(.el-tabs__item) {
font-size: 16px;
font-weight: 500;
color: #606266;
transition: all 0.2s ease;
}
.custom-tabs :deep(.el-tabs__item.is-active) {
color: #4682b4;
font-weight: 600;
}
.custom-tabs :deep(.el-tabs__active-bar) {
background: linear-gradient(135deg, #87ceeb 0%, #4682b4 100%);
}
.action-bar {
padding: 16px 20px;
border-bottom: 1px solid #e4e7ed;
background: #fafbfc;
display: flex;
justify-content: space-between;
align-items: center;
}
.action-left {
display: flex;
gap: 12px;
}
.action-right .total-count {
color: #606266;
font-size: 14px;
font-weight: 500;
}
/* 表格样式 */
.table-container {
flex: 1;
padding: 10px;
overflow: hidden;
}
.assets-table {
border-radius: 6px;
overflow: hidden;
}
.assets-table :deep(.el-table__header) {
background: #f8fafc;
}
.assets-table :deep(.el-table__header th) {
background: #f8fafc;
color: #374151;
font-weight: 600;
border-bottom: 2px solid #e5e7eb;
}
.assets-table :deep(.el-table__row:hover) {
background: #f0f9ff;
}
.assets-table :deep(.el-table__row td) {
border-bottom: 1px solid #f0f2f5;
}
/* 分页样式 */
.pagination-container {
padding: 20px;
display: flex;
justify-content: center;
border-top: 1px solid #e4e7ed;
background: #fafbfc;
}
.custom-pagination :deep(.el-pagination__total) {
color: #606266;
font-weight: 500;
}
.custom-pagination :deep(.btn-next),
.custom-pagination :deep(.btn-prev) {
border-radius: 6px;
}
.custom-pagination :deep(.el-pager li) {
border-radius: 6px;
margin: 0 2px;
}
.custom-pagination :deep(.el-pager li.is-active) {
background: linear-gradient(135deg, #87ceeb 0%, #4682b4 100%);
color: white;
}
/* 响应式设计 */
@media (max-width: 1400px) {
.department-panel {
width: 280px;
}
}
@media (max-width: 1200px) {
.department-panel {
width: 240px;
}
.content-area {
margin: 8px;
}
}
@media (max-width: 768px) {
.main-content {
flex-direction: column;
}
.department-panel {
width: 100%;
height: 200px;
border-right: none;
border-bottom: 1px solid #e4e7ed;
}
.department-panel.panel-collapsed {
height: 60px;
width: 100%;
}
.content-area {
margin: 5px;
}
.content-area.full-width {
margin: 5px;
}
.action-bar {
flex-direction: column;
gap: 12px;
align-items: stretch;
}
.action-left {
justify-content: center;
}
.action-right {
text-align: center;
}
}
@media (max-width: 480px) {
.action-left {
flex-direction: column;
gap: 8px;
}
.table-container {
padding: 0 10px;
}
.assets-table {
font-size: 12px;
}
}
</style>

View File

@@ -0,0 +1,381 @@
<template>
<div class="state-assets-main-container">
<el-container>
<!-- 侧边栏 -->
<el-aside :width="isCollapse ? '75px' : '250px'" class="sidebar">
<div class="sidebar-header">
<span v-if="!isCollapse" class="sidebar-title">国资管理系统</span>
<el-button :icon="isCollapse ? Expand : Fold"
@click="toggleCollapse" text class="collapse-btn" />
</div>
<el-menu :default-active="activeMenu" :collapse="isCollapse" :collapse-transition="false" class="sidebar-menu">
<el-menu-item index="in-use-assets" @click="handleMenuClick('in-use-assets')">
<el-icon>
<Search />
</el-icon>
<template #title>在用资产查询</template>
</el-menu-item>
<el-menu-item index="book-assets" @click="handleMenuClick('book-assets')">
<el-icon>
<Document />
</el-icon>
<template #title>账上资产盘点</template>
</el-menu-item>
<el-menu-item index="/admin/business/state-assets/province-check" @click="handleMenuClick('province-check')">
<el-icon>
<DataAnalysis />
</el-icon>
<template #title>全省资产清查</template>
</el-menu-item>
</el-menu>
</el-aside>
<!-- 主内容区 -->
<el-container class="main-container">
<!-- 顶部导航 -->
<el-header class="header">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/admin/dashboard' }">后台首页</el-breadcrumb-item>
<el-breadcrumb-item>业务后台</el-breadcrumb-item>
<el-breadcrumb-item>国资管理</el-breadcrumb-item>
<el-breadcrumb-item>{{ currentModuleName }}</el-breadcrumb-item>
</el-breadcrumb>
<div class="header-actions">
<el-button type="info" @click="goBackToLogin">
<el-icon>
<Back />
</el-icon>
返回登录
</el-button>
<el-button type="primary" @click="goBackHome">
<el-icon>
<HomeFilled />
</el-icon>
返回首页
</el-button>
</div>
</el-header>
<!-- 内容区域 -->
<el-main class="content" style="border-radius: 8px;">
<router-view />
</el-main>
</el-container>
</el-container>
</div>
</template>
<script setup>
import { ref, computed, onMounted } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { Fold, Expand, HomeFilled } from '@element-plus/icons-vue'
const router = useRouter()
const route = useRoute()
// 侧边栏折叠状态
const isCollapse = ref(false)
// 用户信息
const userInfo = ref({
name: '',
loginTime: '',
userType: '',
dwname: ''
})
const moduleNames = {
'in-use-assets': '在用资产查询',
'book-assets': '账上资产盘点',
'province-assets': '全省资产清查'
}
// 当前激活的菜单项
const activeMenu = computed(() => {
const path = route.path
if (path.includes('/in-use-assets')) return 'in-use-assets'
if (path.includes('/book-assets')) return 'book-assets'
if (path.includes('/province-check')) return '/admin/business/state-assets/province-check'
return 'in-use-assets'
})
const currentModuleName = computed(() => {
return moduleNames[activeMenu.value] || '国资管理系统'
})
// 切换侧边栏折叠状态
const toggleCollapse = () => {
isCollapse.value = !isCollapse.value
}
// 菜单点击处理
const handleMenuClick = (index) => {
if (index === 'province-check') {
router.push('/admin/business/state-assets/province-check')
} else {
router.push(`/admin/business/state-assets/${index}`)
}
}
// 返回登录页面
const goBackToLogin = () => {
router.push('/admin/business/state-assets')
}
// 返回首页
const goBackHome = () => {
router.push('/')
}
// 加载用户信息
const loadUserInfo = () => {
userInfo.value = {
name: localStorage.getItem('Name') || '管理员',
loginTime: localStorage.getItem('logindate') ?
new Date(localStorage.getItem('logindate')).toLocaleString() :
new Date().toLocaleString(),
userType: localStorage.getItem('userType') || '系统管理员',
dwname: localStorage.getItem('dwname') || '未设置'
}
}
onMounted(() => {
loadUserInfo()
})
</script>
<style scoped>
.state-assets-main-container {
height: 100vh;
overflow: hidden;
}
.el-container {
height: 100%;
}
/* 侧边栏样式 */
.sidebar {
background: white;
box-shadow: 2px 0 4px rgba(0, 0, 0, 0.1);
transition: width 0.3s ease;
overflow-x: hidden;
scrollbar-width: thin;
scrollbar-color: #c1c1c1 transparent;
}
.sidebar::-webkit-scrollbar {
width: 6px;
}
.sidebar::-webkit-scrollbar-track {
background: transparent;
}
.sidebar::-webkit-scrollbar-thumb {
background-color: #c1c1c1;
border-radius: 3px;
}
.sidebar::-webkit-scrollbar-thumb:hover {
background-color: #a8a8a8;
}
.sidebar-header {
height: 60px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 20px;
background: linear-gradient(135deg, #1976d2 0%, #42a5f5 100%);
border-bottom: 1px solid #eee;
}
.sidebar-title {
color: #fff;
font-size: 18px;
font-weight: 600;
transition: opacity 0.3s ease;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
}
.collapse-btn {
color: #fff !important;
font-size: 18px;
padding: 0;
width: 32px;
}
.collapse-btn:hover {
background-color: rgba(255, 255, 255, 0.1) !important;
}
.sidebar-menu {
border: none;
padding: 10px 0;
background-color: white;
}
.sidebar-menu .el-menu-item {
height: 50px;
line-height: 50px;
margin: 2px 10px;
border-radius: 6px;
transition: all 0.3s;
}
.sidebar-menu .el-menu-item:hover {
background-color: #e3f2fd;
color: #1976d2;
}
.sidebar-menu .el-menu-item.is-active {
background: linear-gradient(135deg, #1976d2 0%, #42a5f5 100%);
color: white;
}
.sidebar-menu .el-menu-item .el-icon {
margin-right: 8px;
font-size: 16px;
}
/* 主容器样式 */
.main-container {
background-color: #f0f2f5;
}
/* 头部样式 */
.header {
background-color: #fff;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 20px;
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
}
.header-actions {
display: flex;
gap: 12px;
}
/* 内容区域样式 */
.content {
overflow-y: auto;
}
.welcome-content {
max-width: 1200px;
margin: 0 auto;
}
.welcome-card {
border-radius: 12px;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
}
.card-header {
display: flex;
align-items: center;
gap: 12px;
}
.header-icon {
font-size: 24px;
color: #1976d2;
}
.card-title {
font-size: 20px;
font-weight: bold;
color: #1976d2;
}
.welcome-info {
padding: 20px 0;
}
.quick-actions {
margin-top: 30px;
}
.quick-actions h3 {
color: #1976d2;
margin-bottom: 20px;
font-size: 18px;
}
.action-cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 20px;
}
.action-card {
cursor: pointer;
transition: all 0.3s ease;
border-radius: 12px;
text-align: center;
padding: 20px;
}
.action-card:hover {
transform: translateY(-4px);
box-shadow: 0 8px 24px rgba(25, 118, 210, 0.2);
}
.action-icon {
font-size: 48px;
color: #1976d2;
margin-bottom: 16px;
}
.action-title {
font-size: 18px;
font-weight: bold;
color: #1976d2;
margin-bottom: 8px;
}
.action-desc {
color: #666;
font-size: 14px;
line-height: 1.5;
}
/* 响应式设计 */
@media (max-width: 768px) {
.sidebar {
position: fixed;
left: 0;
top: 0;
bottom: 0;
z-index: 1000;
}
.header {
padding: 0 10px;
flex-direction: column;
gap: 12px;
height: auto;
padding-top: 12px;
padding-bottom: 12px;
}
.header-actions {
width: 100%;
justify-content: flex-end;
}
.content {
padding: 10px;
}
.action-cards {
grid-template-columns: 1fr;
}
}
</style>

View File

@@ -1,52 +1,365 @@
<template>
<div class="state-assets-content">
<el-card>
<template #header>
<div class="card-header">
<span class="card-title">
<el-icon>
<Shop />
</el-icon>
国资管理
</span>
</div>
</template>
<div class="state-assets-login-container">
<!-- 顶栏 -->
<el-header class="header">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/admin/dashboard' }">后台首页</el-breadcrumb-item>
<el-breadcrumb-item>业务后台</el-breadcrumb-item>
<el-breadcrumb-item>国资管理</el-breadcrumb-item>
<el-breadcrumb-item>系统登录</el-breadcrumb-item>
</el-breadcrumb>
<el-button type="primary" @click="goBackHome" style="width: 100px;">
<el-icon>
<HomeFilled />
</el-icon>
返回首页
</el-button>
</el-header>
<el-empty description="国资管理功能开发中..." :image-size="200">
<el-descriptions title="功能说明" :column="1" border>
<el-descriptions-item label="功能模块">国资管理</el-descriptions-item>
<el-descriptions-item label="主要功能">
国有资产登记管理资产分类统计资产调拨审批资产盘点管理资产折旧计算资产报废处置等
</el-descriptions-item>
<el-descriptions-item label="开发状态">
<el-tag type="warning">待开发</el-tag>
</el-descriptions-item>
</el-descriptions>
</el-empty>
</el-card>
<!-- 登录表单 -->
<el-main class="login-main">
<div class="logo-box">
<el-image src="http://szzc.tcjwj.com/res/images/login/jwjlogo.png" alt="LOGO" class="logo-img" fit="contain"
:hide-on-click-modal="true">
<template #error>
<div class="image-slot">
<el-icon>
<Picture />
</el-icon>
</div>
</template>
</el-image>
<div class="logo-text">国资管理系统</div>
</div>
<el-form ref="loginFormRef" :model="loginForm" :rules="loginRules" class="login-form"
@submit.prevent="handleLogin">
<el-form-item prop="username">
<el-input v-model="loginForm.username" placeholder="请输入用户名" size="large" clearable :prefix-icon="User" />
</el-form-item>
<el-form-item prop="password">
<el-input v-model="loginForm.password" type="password" placeholder="请输入密码" size="large" clearable
show-password :prefix-icon="Lock" />
</el-form-item>
<el-form-item>
<el-button type="primary" size="large" class="login-btn" :loading="isLoading" @click="handleLogin">
<el-icon v-if="!isLoading">
<Check />
</el-icon>
{{ isLoading ? '登录中...' : '登录' }}
</el-button>
</el-form-item>
</el-form>
</el-main>
<!-- 底部联系方式 -->
<el-footer class="footer-bar">
<el-text type="info">联系方式: 0591-87273300</el-text>
</el-footer>
</div>
</template>
<script setup>
import { Shop } from '@element-plus/icons-vue'
import { ref, reactive } from 'vue'
import { useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import {
HomeFilled,
User,
Lock,
Check,
Picture
} from '@element-plus/icons-vue'
const router = useRouter()
// 表单引用
const loginFormRef = ref()
// 表单数据
const loginForm = reactive({
username: '',
password: ''
})
// 表单验证规则
const loginRules = {
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 2, max: 20, message: '用户名长度在 2 到 20 个字符', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 6, max: 20, message: '密码长度在 6 到 20 个字符', trigger: 'blur' }
]
}
// 加载状态
const isLoading = ref(false)
// 返回首页
const goBackHome = () => {
router.push('/admin/dashboard')
}
// 登录处理函数的逻辑
const handleLogin = async () => {
if (!loginFormRef.value) return
try {
// 表单验证
await loginFormRef.value.validate()
} catch (error) {
ElMessage.warning('请正确填写表单信息')
return
}
isLoading.value = true
try {
const url = "https://www.tcjwj.com/sz/logintest/jwjDataService.asmx/Login"
const params = new URLSearchParams()
params.append("loginCode", `${loginForm.username.trim()},${loginForm.password.trim()}`)
const response = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: params.toString(),
})
const data = await response.json()
// 兼容返回格式
let res = data
if (typeof res === "string") {
try {
res = JSON.parse(res)
} catch { }
}
if (
Array.isArray(res) &&
res[0] &&
(res[0].state === "-1" || res[0].state === "-2")
) {
ElMessage.error('用户名或密码有误')
} else if (Array.isArray(res) && res[0] && res[0].state) {
// 保存字段
localStorage.setItem("loginState", res[0].state)
localStorage.setItem("Name", res[0].chinesename || "")
localStorage.setItem("Dwbm", res[0].dwdm || "")
localStorage.setItem("dwname", res[0].dwname || "")
localStorage.setItem("radioCheckVal", "1")
localStorage.setItem("logindate", new Date().toISOString())
localStorage.setItem("state", res[0].state)
localStorage.setItem("NameCode", loginForm.username.trim())
localStorage.setItem("userType", "管理员")
ElMessage.success('登录成功')
// 跳转到国资管理系统主页
router.push('/admin/business/state-assets/main')
} else {
ElMessage.error('登录失败,服务器返回异常')
}
} catch (err) {
ElMessage.error('网络错误或服务器无响应')
console.error(err)
} finally {
isLoading.value = false
}
}
</script>
<style scoped>
.state-assets-content {
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.card-header {
.state-assets-login-container {
min-height: 100vh;
display: flex;
justify-content: space-between;
align-items: center;
flex-direction: column;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
"Helvetica Neue", Arial, sans-serif;
background: linear-gradient(135deg, #f5f8fa 0%, #e8f4f8 100%);
}
.card-title {
.header {
background-color: #fff;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 20px;
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
}
.header-actions {
display: flex;
gap: 12px;
}
.header-title {
font-size: 22px;
font-weight: bold;
letter-spacing: 2px;
color: #1976d2;
}
.login-main {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
padding: 40px 20px;
}
.logo-box {
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 32px;
}
.logo-img {
width: 120px;
height: 120px;
margin-bottom: 12px;
border-radius: 12px;
}
.image-slot {
display: flex;
justify-content: center;
align-items: center;
width: 120px;
height: 120px;
background: #f5f7fa;
color: #909399;
font-size: 30px;
border-radius: 12px;
border: 2px dashed #d3d4d6;
}
.logo-text {
color: #43a047;
font-size: 24px;
font-weight: bold;
letter-spacing: 2px;
text-shadow: 0 2px 4px rgba(67, 160, 71, 0.2);
}
.login-form {
width: 100%;
max-width: 380px;
}
.login-form :deep(.el-form-item) {
margin-bottom: 24px;
}
.login-form :deep(.el-input__wrapper) {
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
transition: all 0.3s ease;
}
.login-form :deep(.el-input__wrapper:hover) {
box-shadow: 0 4px 12px rgba(25, 118, 210, 0.15);
}
.login-form :deep(.el-input.is-focus .el-input__wrapper) {
box-shadow: 0 4px 16px rgba(25, 118, 210, 0.25);
}
.login-btn {
width: 100%;
height: 48px;
border-radius: 12px;
font-size: 18px;
font-weight: bold;
letter-spacing: 1px;
box-shadow: 0 4px 16px rgba(25, 118, 210, 0.3);
transition: all 0.3s ease;
}
.login-btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(25, 118, 210, 0.4);
}
.login-btn:active {
transform: translateY(0);
}
.footer-bar {
background: linear-gradient(135deg, #e3f0fc 0%, #d1e7f7 100%);
height: 50px !important;
display: flex;
align-items: center;
gap: 8px;
justify-content: center;
border-top: 1px solid #e0e6ed;
box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.04);
}
.footer-bar :deep(.el-text) {
font-size: 15px;
letter-spacing: 1px;
}
/* 响应式设计 */
@media (max-width: 768px) {
.header {
padding: 0 16px;
flex-direction: column;
height: auto !important;
padding-top: 12px;
padding-bottom: 12px;
gap: 12px;
}
.header-title {
font-size: 20px;
}
.login-main {
padding: 20px 16px;
}
.logo-img,
.image-slot {
width: 100px;
height: 100px;
}
.logo-text {
font-size: 20px;
}
.login-form {
max-width: 100%;
}
}
@media (max-width: 480px) {
.header-title {
font-size: 18px;
letter-spacing: 1px;
}
.logo-text {
font-size: 18px;
}
.login-btn {
height: 44px;
font-size: 16px;
}
}
</style>

View File

@@ -1,244 +0,0 @@
<template>
<div class="business-management-container">
<el-container>
<!-- 侧边栏 -->
<el-aside :width="isCollapse ? '75px' : '250px'" class="sidebar">
<div class="sidebar-header">
<span v-if="!isCollapse" class="sidebar-title">业务后台</span>
<el-button :style="isCollapse ? 'transform: translateX(10px)' : ''" :icon="isCollapse ? Expand : Fold"
@click="toggleCollapse" text class="collapse-btn" />
</div>
<el-menu :default-active="activeMenu" :collapse="isCollapse" :collapse-transition="false" class="sidebar-menu">
<el-menu-item index="/admin/business/state-assets" @click="handleMenuClick('/admin/business/state-assets')">
<el-icon>
<Shop />
</el-icon>
<template #title>国资管理</template>
</el-menu-item>
<el-menu-item index="/admin/business/library" @click="handleMenuClick('/admin/business/library')">
<el-icon>
<Reading />
</el-icon>
<template #title>图情管理</template>
</el-menu-item>
<el-menu-item index="/admin/business/laboratory" @click="handleMenuClick('/admin/business/laboratory')">
<el-icon>
<Operation />
</el-icon>
<template #title>实验室管理</template>
</el-menu-item>
</el-menu>
</el-aside>
<!-- 主内容区 -->
<el-container class="main-container">
<!-- 顶部导航 -->
<el-header class="header">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/admin/dashboard' }">后台首页</el-breadcrumb-item>
<el-breadcrumb-item>业务后台</el-breadcrumb-item>
<el-breadcrumb-item>{{ currentPageName }}</el-breadcrumb-item>
</el-breadcrumb>
<el-button type="primary" @click="goBackHome">
<el-icon>
<HomeFilled />
</el-icon>
返回首页
</el-button>
</el-header>
<!-- 内容区域 -->
<el-main class="content">
<router-view />
</el-main>
</el-container>
</el-container>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import {
Shop,
Reading,
Operation,
Fold,
Expand,
HomeFilled
} from '@element-plus/icons-vue'
const router = useRouter()
const route = useRoute()
// 侧边栏折叠状态
const isCollapse = ref(false)
// 当前激活的菜单
const activeMenu = computed(() => route.path)
// 当前页面名称
const currentPageName = computed(() => {
const menuMap = {
'/admin/business/state-assets': '国资管理',
'/admin/business/library': '图情管理',
'/admin/business/laboratory': '实验室管理'
}
return menuMap[route.path] || '业务后台'
})
// 切换侧边栏折叠状态
const toggleCollapse = () => {
isCollapse.value = !isCollapse.value
}
// 菜单点击处理
const handleMenuClick = (path) => {
router.push(path)
}
// 返回首页
const goBackHome = () => {
router.push('/admin/dashboard')
}
</script>
<style scoped>
.business-management-container {
height: 100vh;
overflow: hidden;
}
.el-container {
height: 100%;
}
/* 侧边栏样式 */
.sidebar {
background: white;
box-shadow: 2px 0 4px rgba(0, 0, 0, 0.1);
transition: width 0.3s ease;
overflow-x: hidden;
/* 优化滚动条样式 */
scrollbar-width: thin;
scrollbar-color: #c1c1c1 transparent;
}
.sidebar::-webkit-scrollbar {
width: 6px;
}
.sidebar::-webkit-scrollbar-track {
background: transparent;
}
.sidebar::-webkit-scrollbar-thumb {
background-color: #c1c1c1;
border-radius: 3px;
}
.sidebar::-webkit-scrollbar-thumb:hover {
background-color: #a8a8a8;
}
.sidebar-header {
height: 60px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 20px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-bottom: 1px solid #eee;
}
.sidebar-title {
color: #fff;
font-size: 18px;
font-weight: 600;
transition: opacity 0.3s ease;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
}
.collapse-btn {
color: #fff !important;
font-size: 18px;
padding: 0;
min-height: auto;
}
.collapse-btn:hover {
background-color: rgba(255, 255, 255, 0.1) !important;
}
.sidebar-menu {
border: none;
padding: 10px 0;
background-color: white;
}
.sidebar-menu .el-menu-item {
height: 50px;
line-height: 50px;
margin: 2px 10px;
border-radius: 6px;
transition: all 0.3s;
}
.sidebar-menu .el-menu-item:hover {
background-color: #f0f2ff;
color: #667eea;
}
.sidebar-menu .el-menu-item.is-active {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
}
.sidebar-menu .el-menu-item .el-icon {
margin-right: 8px;
font-size: 16px;
}
/* 主容器样式 */
.main-container {
background-color: #f0f2f5;
}
/* 头部样式 */
.header {
background-color: #fff;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 20px;
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
}
/* 内容区域样式 */
.content {
padding: 20px;
overflow-y: auto;
}
/* 响应式设计 */
@media (max-width: 768px) {
.sidebar {
position: fixed;
left: 0;
top: 0;
bottom: 0;
z-index: 1000;
}
.header {
padding: 0 10px;
}
.content {
padding: 10px;
}
}
</style>

View File

@@ -394,7 +394,7 @@
</div>
</el-col>
<el-col :xs="24" :sm="12" :md="6" :lg="6" :xl="6">
<div class="module-card" @click="navigateTo('/admin/business')" @mouseenter="showSubModules('business')"
<div class="module-card" @mouseenter="showSubModules('business')"
@mouseleave="hideSubModules('business')">
<div class="module-header">
<div class="module-icon business-icon">
@@ -833,7 +833,7 @@ const hideSubModules = (module) => {
}
.sub-modules.show {
max-height: 340px;
max-height: 335px;
overflow-y: auto;
}