实现国资管理系统基础数据获取

This commit is contained in:
2025-11-04 20:50:56 +08:00
parent b959ce3331
commit 4d2f73e8a1
6 changed files with 731 additions and 206 deletions

View File

@@ -231,7 +231,19 @@ const router = createRouter({
children: [
{
path: '',
redirect: '/admin/business/state-assets/main/province-check'
redirect: '/admin/business/state-assets/main/in-use-assets'
},
{
path: 'in-use-assets',
name: 'admin-business-state-assets-in-use-assets',
component: () => import('../views/Admin/Business/InUseAssetsSearchView.vue'),
meta: { requiresAuth: true }
},
{
path: 'book-assets',
name: 'admin-business-state-assets-book-assets',
component: () => import('../views/Admin/Business/BookAssetsView.vue'),
meta: { requiresAuth: true }
},
{
path: 'province-check',

View File

@@ -1,8 +1,3 @@
/**
* 资产清查API服务
* 基于参考文件 zcqc2025.js 的API调用逻辑
*/
// API基础配置
const API_BASE_URL = 'https://www.tcjwj.com/sz/logintest/jwjDataService.asmx'
const TABLE_NAME = 'Zcqc_2025_Zckp'
@@ -29,41 +24,66 @@ function parseApiResponse(data) {
/**
* 构建查询条件JSON字符串
* @param {string} tabType - 标签类型 (all, uncheck, nochange, profit, loss, adjust, error)
* @param {string} tabType - 标签类型 (all, unchecked, no-change, surplus, loss, adjustment, error-pending)
* @param {string} quickSearch - 快速搜索关键词
* @param {Object} queryForm - 高级查询条件
* @returns {string} 查询条件JSON字符串
*/
function buildSearchJson(tabType = 'all', quickSearch = '') {
export function buildSearchJson(tabType = 'all', quickSearch = '', queryForm = {}) {
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 (tabType === 'unchecked') {
searchJson += ',{"column":"PdTypes","operator":"=","value":""}'
} else if (tabType === 'no-change') {
searchJson += ',{"column":"PdTypes","operator":"<>","value":""}'
} else if (tabType === 'surplus') {
searchJson += ',{"column":"PdTypes","operator":"=","value":"盘盈"}'
} else if (tabType === 'loss') {
searchJson += ',{"column":"PdTypes","operator":"=","value":"损失"}'
} else if (tabType === 'adjustment') {
searchJson += ',{"column":"PdTypes","operator":"=","value":"错账调整"}'
} else if (tabType === 'error-pending') {
searchJson += ',{"column":"PdTypes","operator":"=","value":"错误待处理"}'
}
// 添加快速搜索条件
// 快速搜索条件
if (quickSearch && quickSearch.trim()) {
searchJson += `,{"column":"Fixtureno","operator":"like","value":"${quickSearch.trim()}"}`
}
// 高级查询条件
if (queryForm.assetType) {
searchJson += `,{"column":"ZcType","operator":"=","value":"${queryForm.assetType}"}`
}
if (queryForm.useStatus) {
searchJson += `,{"column":"State","operator":"=","value":"${queryForm.useStatus}"}`
}
if (queryForm.useDept) {
searchJson += `,{"column":"Office","operator":"like","value":"${queryForm.useDept}"}`
}
if (queryForm.assetCodeFrom) {
searchJson += `,{"column":"Fixtureno","operator":">=","value":"${queryForm.assetCodeFrom}"}`
}
if (queryForm.assetCodeTo) {
searchJson += `,{"column":"Fixtureno","operator":"<=","value":"${queryForm.assetCodeTo}"}`
}
if (queryForm.assetName) {
searchJson += `,{"column":"Name","operator":"like","value":"${queryForm.assetName}"}`
}
if (queryForm.keeper) {
searchJson += `,{"column":"UserName","operator":"like","value":"${queryForm.keeper}"}`
}
if (queryForm.location) {
searchJson += `,{"column":"Field2","operator":"like","value":"${queryForm.location}"}`
}
if (queryForm.priceFrom !== null && queryForm.priceFrom !== undefined && queryForm.priceFrom !== '') {
searchJson += `,{"column":"Price","operator":">=","value":"${queryForm.priceFrom}"}`
}
if (queryForm.priceTo !== null && queryForm.priceTo !== undefined && queryForm.priceTo !== '') {
searchJson += `,{"column":"Price","operator":"<=","value":"${queryForm.priceTo}"}`
}
if (queryForm.specificReason) {
searchJson += `,{"column":"BdkRemarks","operator":"like","value":"${queryForm.specificReason}"}`
}
searchJson += ']'
return searchJson
}
@@ -88,7 +108,8 @@ export async function getAssetsData(params = {}) {
const {
tabType = 'all',
pageIndex = 1,
quickSearch = ''
quickSearch = '',
queryForm = {}
} = params
const loginCode = getLoginCode()
@@ -96,8 +117,8 @@ export async function getAssetsData(params = {}) {
throw new Error('未找到登录状态,请先登录')
}
const searchJson = buildSearchJson(tabType, quickSearch)
const searchJson = buildSearchJson(tabType, quickSearch, queryForm)
const formData = new URLSearchParams()
formData.append('tablename', TABLE_NAME)
formData.append('loginCode', loginCode)
@@ -137,7 +158,7 @@ export async function getAssetDetail(assetId) {
}
const searchJson = `[{"column":"ID","operator":"=","value":"${assetId}"}]`
const formData = new URLSearchParams()
formData.append('tablename', TABLE_NAME)
formData.append('loginCode', loginCode)
@@ -167,58 +188,100 @@ export async function getAssetDetail(assetId) {
}
/**
* 资产数据字段映射
* 将API返回的字段映射为更友好的显示名称
* 在用资产查询ZCsearch_all_New
* @param {Object} params
* @param {string} params.searchValue 查询关键词(可为空)
* @param {number} params.pageIndex 页码从1开始
* @param {string} params.userType 用户类型,默认“管理员”
* @returns {Promise<{ Tcount:number, PageIndex:number, PageTotal:number, Num:number, total:number, DataList:Array }>} 响应数据
*/
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'
export async function searchInUseAssets({ searchValue = '', pageIndex = 1, userType = '管理员' } = {}) {
const loginCode = getLoginCode()
if (!loginCode) {
throw new Error('未找到登录状态,请先登录')
}
const formData = new URLSearchParams()
formData.append('LoginCode', loginCode)
formData.append('userType', userType)
formData.append('searchValue', searchValue)
formData.append('pageIndex', String(pageIndex))
formData.append('syr', "")
try {
const response = await fetch(`${API_BASE_URL}/ZCsearch_all_New`, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: formData.toString()
})
if (!response.ok) {
throw new Error(`HTTP错误: ${response.status}`)
}
const text = await response.text()
// 响应可能是纯JSON或<string>包装的JSON
let payload
try {
payload = JSON.parse(text)
} catch (_) {
const parsed = parseApiResponse(text)
payload = parsed
}
// 期望为数组包裹一个对象
const obj = Array.isArray(payload) ? payload[0] || {} : (payload || {})
const {
Tcount = 0,
PageIndex = pageIndex,
PageTotal = 0,
Num = 0,
total = 0,
DataList = []
} = obj
return { Tcount, PageIndex, PageTotal, Num, total, DataList }
} catch (error) {
console.error('在用资产查询失败:', error)
throw error
}
}
/**
* 转换资产数据格式
* @param {Object} rawAsset - 原始资产数据
* @returns {Object} 转换后的资产数据
* 获取部门列表
* @returns {Promise<Array>} 部门列表数组
*/
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
export async function getDeptList() {
const loginCode = getLoginCode()
if (!loginCode) {
throw new Error('未找到登录状态,请先登录')
}
const searchJson = `[{ "column": "classify", "operator": "=", "Value": "使用部门" }]`
const formData = new URLSearchParams()
formData.append('tablename', "classify")
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()
return parseApiResponse(data)
} catch (error) {
console.error('获取部门列表失败:', error)
throw error
}
}
/**
* 批量转换资产数据
* @param {Array} rawAssets - 原始资产数据数组
* @returns {Array} 转换后的资产数据数组
*/
export function transformAssetsData(rawAssets) {
return rawAssets.map(transformAssetData)
}

View File

@@ -0,0 +1,21 @@
<template>
<div class="book-assets-view">
<el-card>
<template #header>
<div class="card-header">
<span>账上资产盘点</span>
</div>
</template>
<el-empty description="开发中:账上资产盘点" />
</el-card>
</div>
</template>
<script setup>
// 预留:后续实现账上资产盘点功能
</script>
<style scoped>
.book-assets-view { padding: 16px; }
.card-header { font-weight: 600; }
</style>

View File

@@ -0,0 +1,115 @@
<template>
<div class="inuse-assets-search">
<div class="action-bar">
<el-input v-model="searchValue" placeholder="输入关键字(可留空)" clearable style="width: 260px; margin-right: 8px;" />
<el-button type="primary" :loading="loading" @click="handleSearch">查询</el-button>
</div>
<el-table :data="tableData" v-loading="loading" border stripe height="calc(100vh - 220px)"
@selection-change="handleSelectionChange" class="assets-table">
<el-table-column type="selection" width="50" fixed="left" align="center" :selectable="rowSelectable" />
<el-table-column type="index" label="序号" width="70" fixed="left" align="center" show-overflow-tooltip
:index="(index) => index === 0 ? '' : index" />
<el-table-column prop="ZICFLID" label="资产类型" width="90" align="center" show-overflow-tooltip />
<el-table-column prop="SORTGBID" label="国标分类" width="120" align="center" show-overflow-tooltip />
<el-table-column prop="BILLCODE" label="资产编号" width="150" align="center" show-overflow-tooltip />
<el-table-column prop="ZICMC" label="资产名称" width="200" align="center" show-overflow-tooltip />
<el-table-column prop="GUIGXH" label="型号" width="120" align="center" show-overflow-tooltip />
<el-table-column prop="SHUL" label="数量/面积" width="120" align="center" show-overflow-tooltip />
<el-table-column prop="JILDW" label="单位" width="100" align="center" show-overflow-tooltip />
<el-table-column prop="price" label="原值" width="130" align="center" show-overflow-tooltip />
<el-table-column prop="SHIYBMID" label="使用部门" width="150" align="center" show-overflow-tooltip />
<el-table-column prop="SHIYRID" label="保管人" width="130" align="center" show-overflow-tooltip />
<el-table-column prop="CUNFDDID" label="存放地点" width="150" align="center" show-overflow-tooltip />
<el-table-column prop="SHIYFXID" label="使用方向" width="130" align="center" show-overflow-tooltip />
<el-table-column prop="buydate" label="购置日期" width="120" align="center" show-overflow-tooltip />
<el-table-column prop="optiondate" label="登记日期" width="120" align="center" show-overflow-tooltip />
<el-table-column prop="state" label="现状" width="120" align="center" show-overflow-tooltip />
<el-table-column prop="QUDFSID" label="取得方式" width="120" align="center" show-overflow-tooltip />
</el-table>
<div class="pagination">
<el-pagination v-model:current-page="pagination.currentPage" :page-size="pagination.pageSize"
layout="total, prev, pager, next, jumper" :total="pagination.total" @current-change="handlePageChange"
class="custom-pagination" />
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import { searchInUseAssets } from '@/services/assetsApi'
const loading = ref(false)
const searchValue = ref('')
const tableData = ref([])
const selectedRows = ref([])
const pagination = ref({ currentPage: 1, pageSize: 50, total: 0 })
const rowSelectable = (row) => !row.__isSummary
const loadData = async () => {
loading.value = true
try {
const { Tcount, PageIndex, Num, total, DataList } = await searchInUseAssets({
searchValue: searchValue.value.trim(),
pageIndex: pagination.value.currentPage,
userType: '管理员'
})
// 赋值分页总数
pagination.value.total = Number(Tcount || 0)
pagination.value.currentPage = Number(PageIndex || 1)
// 在每页数据第一条插入合计行
const summaryRow = {
__isSummary: true,
ZICMC: '合计:',
SHUL: Num ?? 0,
price: total ?? 0
}
tableData.value = [summaryRow, ...(Array.isArray(DataList) ? DataList : [])]
} catch (e) {
console.error(e)
ElMessage.error('加载在用资产数据失败')
} finally {
loading.value = false
}
}
const handleSearch = () => {
pagination.value.currentPage = 1
loadData()
}
const handleSelectionChange = (rows) => {
selectedRows.value = rows
}
const handlePageChange = (p) => {
pagination.value.currentPage = p
loadData()
}
onMounted(() => loadData())
</script>
<style scoped>
.inuse-assets-search {
background: #fff;
border-radius: 8px;
padding: 16px 16px 0 16px;
}
.action-bar {
margin-bottom: 10px;
}
.pagination {
display: flex;
justify-content: center;
padding: 14px 0;
}
</style>

View File

@@ -26,7 +26,7 @@
</div>
<div class="action-right">
<div class="quick-search">
<el-input v-model="quickSearch" placeholder="输入资产编号快速查询" style="width: 200px; margin-right: 10px;"
<el-input v-model="quickSearch" placeholder="输入资产编号快速查询" style="width: 220px; margin-right: 10px;"
@keyup.enter="handleQuickSearch" clearable>
<template #append>
<el-button :icon="Search" @click="handleQuickSearch" />
@@ -38,47 +38,39 @@
<!-- 表格区域 -->
<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 :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" align="center" />
<el-table-column type="index" label="序号" width="80" fixed="left" align="center" />
<el-table-column prop="Classifyno" label="资产分类" width="120" show-overflow-tooltip fixed="left"
align="center" />
<el-table-column prop="Fixtureno" label="内部编号" width="150" show-overflow-tooltip fixed="left"
align="center" />
<el-table-column prop="Name" label="资产名称" width="200" show-overflow-tooltip fixed="left" align="center" />
<el-table-column prop="Specify" label="规格型号" width="150" show-overflow-tooltip align="center" />
<el-table-column prop="Src" label="取得方式" width="120" align="center" />
<el-table-column prop="Buydate" label="取得日期" width="120" align="center" />
<el-table-column prop="ZcType" label="归口类别" width="120" align="center" />
<el-table-column prop="Office" label="使用部门" width="150" show-overflow-tooltip align="center" />
<el-table-column prop="UserName" label="使用人" width="100" show-overflow-tooltip align="center" />
<el-table-column prop="Field2" label="存放地点" width="150" show-overflow-tooltip align="center" />
<el-table-column prop="State" label="使用状况" width="100" align="center" />
<el-table-column prop="IsOutZc" label="是否账外" width="100" align="center" />
<el-table-column label="账面数" align="center">
<el-table-column prop="Num" label="数量" width="80" align="center" />
<el-table-column prop="Price" label="原值" width="120" align="center" />
<el-table-column prop="Ljzj" label="累计折旧" width="120" align="center" />
<el-table-column prop="PriceJz" label="净值" width="120" align="center" />
</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 label="清查数" align="center">
<el-table-column prop="QcNum" label="数量" width="80" align="center" />
<el-table-column prop="QcPrice" label="原值" width="120" align="center" />
<el-table-column prop="QcLjzj" label="累计折旧" width="120" align="center" />
<el-table-column prop="QcPriceJz" label="值" width="120" align="center" />
</el-table-column>
<el-table-column prop="PdTypes" label="变动原因" width="120" align="center" />
<el-table-column prop="BdkRemarks" label="具体原因" width="200" show-overflow-tooltip align="center" />
<el-table-column prop="Remarks" label="备注" width="200" show-overflow-tooltip align="center" />
</el-table>
</div>
@@ -90,19 +82,245 @@
</div>
</div>
</div>
<!-- 查询对话框 -->
<el-dialog v-model="queryDialogVisible" title="查询条件" :before-close="handleCloseQuery">
<el-descriptions :column="2" border>
<el-descriptions-item label="报表类型">
<el-input v-model="queryForm.reportType" readonly />
</el-descriptions-item>
<el-descriptions-item label="资产类型">
<el-select v-model="queryForm.assetType" placeholder="全部" clearable>
<el-option label="全部" value="" />
<el-option label="设备" value="设备" />
<el-option label="家具" value="家具" />
<el-option label="图书" value="图书" />
<el-option label="被服" value="被服" />
<el-option label="文物" value="文物" />
<el-option label="无形" value="无形" />
<el-option label="土地" value="土地" />
<el-option label="房屋" value="房屋" />
<el-option label="动植物" value="动植物" />
</el-select>
</el-descriptions-item>
<el-descriptions-item label="使用状态">
<el-select v-model="queryForm.useStatus" placeholder="全部" clearable>
<el-option label="全部" value="" />
<el-option label="在用" value="在用" />
<el-option label="出租出借" value="出租出借" />
<el-option label="闲置" value="闲置" />
<el-option label="被侵占" value="被侵占" />
<el-option label="待销毁" value="待销毁" />
</el-select>
</el-descriptions-item>
<el-descriptions-item label="使用部门">
<el-select v-model="queryForm.useDept" placeholder="请选择使用部门" filterable clearable style="width: 285px;">
<el-option label="全部" value="" />
<el-option v-for="item in deptList" :key="item" :label="item" :value="item" />
</el-select>
</el-descriptions-item>
<el-descriptions-item label="资产编号">
<div style="display: flex; align-items: center; gap: 8px;">
<el-input v-model="queryForm.assetCodeFrom" placeholder="从" style="flex: 1" />
<span></span>
<el-input v-model="queryForm.assetCodeTo" placeholder="到" style="flex: 1" />
</div>
</el-descriptions-item>
<el-descriptions-item label="资产名称">
<el-input v-model="queryForm.assetName" placeholder="请输入资产名称" clearable />
</el-descriptions-item>
<el-descriptions-item label="保管人">
<el-input v-model="queryForm.keeper" placeholder="请输入保管人" clearable />
</el-descriptions-item>
<el-descriptions-item label="存放地点">
<el-input v-model="queryForm.location" placeholder="请输入存放地点" clearable />
</el-descriptions-item>
<el-descriptions-item label="资产原值">
<div style="display: flex; align-items: center; gap: 8px;">
<el-input v-model="queryForm.priceFrom" placeholder="从" style="flex: 1" :precision="2" />
<span></span>
<el-input v-model="queryForm.priceTo" placeholder="到" style="flex: 1" :precision="2" />
</div>
</el-descriptions-item>
<el-descriptions-item label="具体原因">
<el-input v-model="queryForm.specificReason" placeholder="请输入具体原因" clearable />
</el-descriptions-item>
</el-descriptions>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="handleAdvancedQuery">查询</el-button>
<el-button @click="handleCloseQuery">关闭</el-button>
</div>
</template>
</el-dialog>
<!-- 资产清查盘点弹窗 -->
<el-dialog v-model="inventoryDialogVisible" :title="isAdd ? '新增盘盈' : '资产清查盘点'" width="1100px">
<el-tabs v-model="inventoryActiveTab">
<el-tab-pane label="资产基本信息" name="info">
<el-descriptions :column="3" border>
<el-descriptions-item label="资产分类">
<el-input v-model="inventoryForm.Classifyno" />
</el-descriptions-item>
<el-descriptions-item label="内部编号">
<el-input v-model="inventoryForm.Fixtureno" />
</el-descriptions-item>
<el-descriptions-item label="外部编号">
<el-input v-model="inventoryForm.Code" />
</el-descriptions-item>
<el-descriptions-item label="资产名称">
<el-input v-model="inventoryForm.Name" />
</el-descriptions-item>
<el-descriptions-item label="规格型号">
<el-input v-model="inventoryForm.Specify" />
</el-descriptions-item>
<el-descriptions-item label="取得方式">
<el-select v-model="inventoryForm.Src" placeholder="请选择">
<el-option label="新购" value="新购" />
<el-option label="调拨" value="调拨" />
<el-option label="接受捐赠" value="接受捐赠" />
<el-option label="自建" value="自建" />
<el-option label="置换" value="置换" />
<el-option label="盘盈" value="盘盈" />
<el-option label="自行研制" value="自行研制" />
</el-select>
</el-descriptions-item>
<el-descriptions-item label="取得日期">
<el-input v-model="inventoryForm.Buydate" />
</el-descriptions-item>
<el-descriptions-item label="存放地点">
<el-input v-model="inventoryForm.Field2" />
</el-descriptions-item>
<el-descriptions-item label="使用状况">
<el-select v-model="inventoryForm.State" placeholder="请选择">
<el-option label="在用" value="在用" />
<el-option label="出租出借" value="出租出借" />
<el-option label="闲置" value="闲置" />
<el-option label="被侵占" value="被侵占" />
<el-option label="待处置" value="待处置" />
</el-select>
</el-descriptions-item>
<el-descriptions-item label="是否账外">
<el-select v-model="inventoryForm.IsOutZc" placeholder="请选择">
<el-option label="是" value="是" />
<el-option label="否" value="否" />
</el-select>
</el-descriptions-item>
<el-descriptions-item label="使用部门">
<el-select v-model="inventoryForm.Office" placeholder="请选择使用部门" filterable clearable>
<el-option v-for="item in deptList" :key="item" :label="item" :value="item" />
</el-select>
</el-descriptions-item>
<el-descriptions-item label="保管人">
<el-input v-model="inventoryForm.UserName" />
</el-descriptions-item>
</el-descriptions>
<!-- 账面数 -->
<div style="margin-top: 12px; font-weight: 600;">账面数</div>
<el-descriptions :column="4" border style="margin-top: 8px;">
<el-descriptions-item label="数量/面积">
<el-input-number v-model="inventoryForm.Num" :min="0" controls-position="right" disabled/>
</el-descriptions-item>
<el-descriptions-item label="原值">
<el-input-number v-model="inventoryForm.Price" :min="0" :precision="2" controls-position="right" disabled/>
</el-descriptions-item>
<el-descriptions-item label="累计折旧">
<el-input-number v-model="inventoryForm.Ljzj" :min="0" :precision="2" controls-position="right" disabled/>
</el-descriptions-item>
<el-descriptions-item label="资产净值">
<el-input-number v-model="inventoryForm.PriceJz" :min="0" :precision="2" controls-position="right" disabled/>
</el-descriptions-item>
</el-descriptions>
<!-- 清查数 -->
<div style="margin-top: 12px; font-weight: 600;">清查数</div>
<el-descriptions :column="4" border style="margin-top: 8px;">
<el-descriptions-item label="数量/面积">
<el-input-number v-model="inventoryForm.QcNum" :min="0" @change="limitCheckFields" controls-position="right"/>
</el-descriptions-item>
<el-descriptions-item label="原值">
<el-input-number v-model="inventoryForm.QcPrice" :min="0" :precision="2" @change="limitCheckFields" controls-position="right"/>
</el-descriptions-item>
<el-descriptions-item label="累计折旧">
<el-input-number v-model="inventoryForm.QcLjzj" :min="0" :precision="2" @change="limitCheckFields" controls-position="right"/>
</el-descriptions-item>
<el-descriptions-item label="资产净值">
<el-input-number v-model="inventoryForm.QcPriceJz" :min="0" :precision="2" @change="limitCheckFields" controls-position="right"/>
</el-descriptions-item>
</el-descriptions>
<el-descriptions :column="2" border style="margin-top: 8px;">
<el-descriptions-item label="变动原因">
<el-select v-model="inventoryForm.PdTypes" placeholder="请选择">
<el-option label="盘盈" value="盘盈" />
<el-option label="损失" value="损失" />
<el-option label="错账调整" value="错账调整" />
<el-option label="无盈亏" value="无盈亏" />
</el-select>
</el-descriptions-item>
<el-descriptions-item label="盘亏原因">
<el-input v-model="inventoryForm.BdkRemarks" />
</el-descriptions-item>
<el-descriptions-item label="备注" :span="2">
<el-input v-model="inventoryForm.Remarks" />
</el-descriptions-item>
</el-descriptions>
</el-tab-pane>
<el-tab-pane label="资产照片" name="photo">
<div style="display:flex; gap: 16px;">
<div style="flex:1;">
<div style="font-weight:600; margin-bottom:6px;">整体照片</div>
<el-image style="width: 100%; height: 180px;" fit="contain"
src="http://szzc.tcjwj.com/res/images/Img_kong.jpg" />
<el-button disabled style="margin-top:8px;">上传</el-button>
</div>
<div style="flex:1;">
<div style="font-weight:600; margin-bottom:6px;">前面照片</div>
<el-image style="width: 100%; height: 180px;" fit="contain"
src="http://szzc.tcjwj.com/res/images/Img_kong.jpg" />
<el-button disabled style="margin-top:8px;">上传</el-button>
</div>
<div style="flex:1;">
<div style="font-weight:600; margin-bottom:6px;">背后照片</div>
<el-image style="width: 100%; height: 180px;" fit="contain"
src="http://szzc.tcjwj.com/res/images/Img_kong.jpg" />
<el-button disabled style="margin-top:8px;">上传</el-button>
</div>
</div>
</el-tab-pane>
</el-tabs>
<template #footer>
<div style="display:flex; justify-content: space-between; width:100%;">
<div>
<el-button type="danger" @click="handleLoss" :disabled="isAdd">盘亏</el-button>
<el-button @click="handleNoChange" :disabled="isAdd">无盈亏</el-button>
</div>
<div>
<el-button type="primary" @click="handleInventorySave">保存</el-button>
<el-button @click="handleInventoryCancel">取消</el-button>
</div>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { getAssetsData, transformAssetsData } from '@/services/assetsApi'
import { getAssetsData, getDeptList } from '@/services/assetsApi'
import {
Document,
Plus,
Search
} from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import { onMounted, ref } from 'vue'
import { onMounted, ref, nextTick, reactive } from 'vue'
// 响应式数据
const showDepartmentPanel = ref(true)
@@ -113,53 +331,56 @@ const pageSize = ref(50)
const totalCount = ref(1000)
const selectedRows = ref([])
const quickSearch = ref('')
const deptList = ref()
const isAdd = ref(false)
// 查询对话框相关
const queryDialogVisible = ref(false)
const queryForm = ref({
reportType: '二级部门清查',
assetType: '',
useStatus: '',
useDept: '',
assetCodeFrom: '',
assetCodeTo: '',
assetName: '',
keeper: '',
location: '',
priceFrom: '',
priceTo: '',
specificReason: ''
})
// 表格数据
const tableData = ref([])
// 加载使用部门下拉数据
const loadDeptList = async () => {
try {
const list = await getDeptList()
deptList.value = list
.map(it => `${it.Code}.${it.Name}`)
.filter(Boolean)
} catch (e) {
console.error('获取部门列表失败:', e)
}
}
// 加载函数
const loadTableData = async () => {
loading.value = true
try {
const rawData = await getAssetsData({
tabType: activeTab.value,
const tabType = activeTab.value
const quickSearchV = quickSearch.value.trim()
const queryFormV = queryForm.value
tableData.value = await getAssetsData({
tabType,
pageIndex: currentPage.value,
quickSearch: quickSearch.value
quickSearch: quickSearchV,
queryForm: queryFormV
})
// 转换数据格式
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}`)
console.error('获取数据失败:', error)
ElMessage.error('获取数据失败')
} finally {
loading.value = false
}
@@ -168,17 +389,34 @@ const loadTableData = async () => {
const handleTabClick = (tab) => {
activeTab.value = tab.name
currentPage.value = 1 // 重置到第一页
loadTableData()
// 使用 nextTick 确保 activeTab 更新后再加载数据
nextTick(() => {
loadTableData()
})
}
const handleQuickSearch = () => {
currentPage.value = 1 // 重置到第一页
loadTableData()
}
const handleQuery = () => {
queryDialogVisible.value = true
}
const handleAdvancedQuery = () => {
currentPage.value = 1 // 重置到第一页
queryDialogVisible.value = false
loadTableData()
}
const handleCloseQuery = () => {
queryDialogVisible.value = false
}
const handleAddSurplus = () => {
ElMessage.info('打开增加盘盈对话框')
inventoryDialogVisible.value = true
isAdd.value = true
}
const handleInventoryCheck = () => {
@@ -186,18 +424,15 @@ const handleInventoryCheck = () => {
ElMessage.warning('请先选择要盘点的资产')
return
}
ElMessage.info(`${selectedRows.value.length} 项资产进行盘点`)
// 取多选框选择的最后一笔资产
const asset = selectedRows.value[selectedRows.value.length - 1]
openInventoryDialog(asset)
}
const handleSelectionChange = (selection) => {
selectedRows.value = selection
}
const handleEdit = (row) => {
ElMessage.info(`编辑资产: ${row.assetName}`)
}
const handleSizeChange = (val) => {
pageSize.value = val
currentPage.value = 1 // 重置到第一页
@@ -212,7 +447,111 @@ const handleCurrentChange = (val) => {
// 生命周期
onMounted(() => {
loadTableData()
loadDeptList()
})
// ========== 资产盘点弹窗 ==========
const inventoryDialogVisible = ref(false)
const inventoryActiveTab = ref('info')
const inventoryForm = reactive({
Classifyno: '',
Fixtureno: '',
Code: '',
Name: '',
Specify: '',
Src: '',
Buydate: '',
Field2: '',
State: '',
IsOutZc: '',
Office: '',
UserName: '',
Num: 0,
Price: 0,
Ljzj: 0,
PriceJz: 0,
QcNum: 0,
QcPrice: 0,
QcLjzj: 0,
QcPriceJz: 0,
PdTypes: '',
BdkRemarks: '',
Remarks: ''
})
const openInventoryDialog = (asset) => {
// 预填数据
Object.assign(inventoryForm, {
Classifyno: asset.Classifyno || '',
Fixtureno: asset.Fixtureno || '',
Code: asset.Code || '',
Name: asset.Name || '',
Specify: asset.Specify || '',
Src: asset.Src || '',
Buydate: asset.Buydate || '',
Field2: asset.Field2 || '',
State: asset.State || '',
IsOutZc: asset.IsOutZc || '',
Office: asset.Office || '',
UserName: asset.UserName || '',
Num: Number(asset.Num ?? 0),
Price: Number(asset.Price ?? 0),
Ljzj: Number(asset.Ljzj ?? 0),
PriceJz: Number(asset.PriceJz ?? 0),
QcNum: Number(asset.QcNum ?? 0),
QcPrice: Number(asset.QcPrice ?? 0),
QcLjzj: Number(asset.QcLjzj ?? 0),
QcPriceJz: Number(asset.QcPriceJz ?? 0),
PdTypes: asset.PdTypes || '',
BdkRemarks: asset.BdkRemarks || '',
Remarks: asset.Remarks || ''
})
inventoryActiveTab.value = 'info'
inventoryDialogVisible.value = true
}
const handleNoChange = () => {
inventoryForm.QcNum = inventoryForm.Num
inventoryForm.QcPrice = inventoryForm.Price
inventoryForm.QcLjzj = inventoryForm.Ljzj
inventoryForm.QcPriceJz = inventoryForm.PriceJz
inventoryForm.PdTypes = '无盈亏'
inventoryForm.BdkRemarks = ''
}
const handleLoss = () => {
inventoryForm.QcNum = 0
inventoryForm.QcPrice = 0
inventoryForm.QcLjzj = 0
inventoryForm.QcPriceJz = 0
inventoryForm.PdTypes = '损失'
}
const limitCheckFields = () => {
// 清查数不得大于账面
if (Number(inventoryForm.QcNum) > Number(inventoryForm.Num)) {
inventoryForm.QcNum = inventoryForm.Num
}
if (Number(inventoryForm.QcPrice) > Number(inventoryForm.Price)) {
inventoryForm.QcPrice = inventoryForm.Price
}
if (Number(inventoryForm.QcLjzj) > Number(inventoryForm.Ljzj)) {
inventoryForm.QcLjzj = inventoryForm.Ljzj
}
if (Number(inventoryForm.QcPriceJz) > Number(inventoryForm.PriceJz)) {
inventoryForm.QcPriceJz = inventoryForm.PriceJz
}
}
const handleInventorySave = () => {
// 这里只做示例保存提示
ElMessage.success('已保存盘点数据')
inventoryDialogVisible.value = false
}
const handleInventoryCancel = () => {
inventoryDialogVisible.value = false
}
</script>
<style scoped>
@@ -328,26 +667,6 @@ onMounted(() => {
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 {
@@ -419,4 +738,4 @@ onMounted(() => {
font-size: 12px;
}
}
</style>
</style>

View File

@@ -21,7 +21,7 @@
</el-icon>
<template #title>账上资产盘点</template>
</el-menu-item>
<el-menu-item index="/admin/business/state-assets/province-check" @click="handleMenuClick('province-check')">
<el-menu-item index="province-check" @click="handleMenuClick('province-check')">
<el-icon>
<DataAnalysis />
</el-icon>
@@ -38,6 +38,7 @@
<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-item>{{ currentModuleName }}</el-breadcrumb-item>
</el-breadcrumb>
<div class="header-actions">
@@ -68,7 +69,7 @@
<script setup>
import { ref, computed, onMounted } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { Fold, Expand, HomeFilled } from '@element-plus/icons-vue'
import { Fold, Expand, HomeFilled, Search, Document, DataAnalysis, Back } from '@element-plus/icons-vue'
const router = useRouter()
const route = useRoute()
@@ -87,7 +88,7 @@ const userInfo = ref({
const moduleNames = {
'in-use-assets': '在用资产查询',
'book-assets': '账上资产盘点',
'province-assets': '全省资产清查'
'province-check': '全省资产清查'
}
// 当前激活的菜单项
@@ -95,13 +96,11 @@ 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'
if (path.includes('/province-check')) return 'province-check'
return 'in-use-assets'
})
const currentModuleName = computed(() => {
return moduleNames[activeMenu.value] || '国资管理系统'
})
const currentModuleName = computed(() => moduleNames[activeMenu.value])
// 切换侧边栏折叠状态
const toggleCollapse = () => {
@@ -110,11 +109,7 @@ const toggleCollapse = () => {
// 菜单点击处理
const handleMenuClick = (index) => {
if (index === 'province-check') {
router.push('/admin/business/state-assets/province-check')
} else {
router.push(`/admin/business/state-assets/${index}`)
}
router.push(`/admin/business/state-assets/main/${index}`)
}
// 返回登录页面