<template>
<div class="table-box">
<ProTable
ref="proTable"
:columns="columns"
:request-api="getTableList"
:data-callback="dataCallback"
>
</ProTable>
</div>
</template>
<script setup lang="tsx" name="operationLog">
import { ref, reactive, } from "vue";
import ProTable from "@/components/ProTable/index.vue";
import { setValueClildList } from '@/api/modules/public';
import { assetListOpList } from "@/api/modules/assetAllocation";
import { ProTableInstance, ColumnProps } from "@/components/ProTable/interface";
import { Metering } from "@/api/interface";
import { OperationType } from "@/utils/dict";
const emit = defineEmits(['previous-info']);
// ProTable 实例
const proTable = ref<ProTableInstance>();
// 保存 id 的状态
const currentId = ref<string | undefined>(undefined);
// ProTable 请求数据的方法
const getTableList = (params: any) => {
// 添加 id 参数
if (currentId.value) {
params.assetId = currentId.value;
}
if (params.createTime) {
params.startTime = params.createTime[0] + ' 00:00:00';
params.endTime = params.createTime[1] + ' 23:59:59';
delete params.createTime;
}
return assetListOpList(params);
}
const dataCallback = (data: any) => {
return {
list: data.dataList,
total: data.totalCount,
pageNum: data.pageNum,
pageSize: data.pageSize
};
}
interface AssetDetailData {
id?: string;
}
interface DrawerProps {
row?: Partial<AssetDetailData>;
}
const drawerProps = ref<DrawerProps>({
row: {},
})
const refreshTable = () => {
proTable.value!.pageable.pageNum = 1;
proTable.value?.refreshData();
};
// 父组件传过来的数据
const setDrawerProps = async (params: DrawerProps) => {
drawerProps.value = {
...params
}
// 更新 currentId
currentId.value = params.row?.id;
// 手动触发 ProTable 的刷新
await refreshTable();
}
// 表格配置项
const columns = reactive<ColumnProps<Metering.pageList>[]>([
{ prop: "createUserName", label: "操作人" },
{ prop: "userName", label: "操作人",isShow:false, search: { el: "input" }},
{
prop: "optType",
label: "操作类型",
isShow:false,
enum: async () => {
// 获取资产来源
const data = await setValueClildList({ dictCode: 'LOG_OPERATION_TYPE' });
if(data.code != 0) return false
const list = data?.data.filter(item => item.enableStatus == 1);
return { data: list }
},
fieldNames: { label: "itemLabel", value: "itemValue" },
search: { el: "select", props: { filterable: true }},
},
{ prop: "optTypeName", label: "操作类型" },
{ prop: "content", label: "操作内容",search: { el: "input" } },
{ prop: "orderNo",
label: "关联单据",
search: { el: "input" },
copy: false,
render: (scope) => {
return (
<span style="color: #49c625" onClick={() => handleAssetCodeClick(scope.row)}>
{scope.row.orderNo}
</span>
);
}
},
{ prop: "createTime", label: "操作时间",
search: {
el: "date-picker",
span: 2,
props: { type: "daterange", valueFormat: "YYYY-MM-DD" },
}, },
])
const handleAssetCodeClick = async (row: any) => {
emit('previous-info',row); // 触发父组件事件
}
defineExpose({
setDrawerProps
});
</script>
<template>
<el-drawer
v-model="drawerVisible"
:append-to-body="true"
:destroy-on-close="true"
size="70%"
:show-close="false"
:with-header="false"
class="no-header-drawer"
>
<div class="asset_details_header">
<!-- 头部内容 -->
<div class="header_title">
<div class="header_left">
<div class="header_zcInfo">
<span class="header_zcInfo_name">{{ infos.baseInfo.assetName }}</span>
<!-- 资产标记 -->
<span class="header_zcInfo_status" v-if="infos.markTags?.length">
<span v-for="(item, index) in markStatusList" :key="index">
<span class="span-zc" :style="`color:${item.color}`">{{ item.name }}</span>
</span>
</span>
</div>
<div class="header_userInfo">
<span>新增人:{{ infos.baseInfo.createUserName }}</span>
<span>新增时间:{{ infos.baseInfo.createTime }}</span>
<span>修改人:{{ infos.baseInfo.updateUserName }}</span>
<span>修改时间:{{ infos.baseInfo.updateTime }}</span>
</div>
</div>
<div class="header_right">
<div
class="trapezoid-isosceles"
:style="statusStyle"
>
<span>{{ statusText }}</span>
</div>
</div>
</div>
<div class="header_btns">
<el-button
type="primary"
v-if="hasBtnPermission('asset:inventory:update')"
@click="deleteData"
>
<el-icon class="el-icon--left"><Delete /></el-icon>删除
</el-button>
<el-button
type="primary"
@click="openTagPrint"
v-if="hasBtnPermission('asset:inventory:printMark')"
>
<el-icon class="el-icon--left"><Printer /></el-icon>打印资产标签
</el-button>
</div>
</div>
<div class="asset_details_content">
<el-tabs v-model="activeName" class="demo-tabs">
<div class="content-height">
<el-tab-pane label="资产信息" name="first">
<basicDetails ref="basicDetailsRef" @previous-info="previousInfo"/>
</el-tab-pane>
<el-tab-pane label="操作日志" name="second">
<div class="sty-second" :style="{ height: windowHeight+'px' }">
<operationLog ref="operationLogRef" />
</div>
</el-tab-pane>
</div>
</el-tabs>
</div>
</el-drawer>
</template>
<script setup lang="ts" name="assetInfo">
import { ref, computed,nextTick,inject } from "vue";
import { ElMessage } from 'element-plus';
import operationLog from "./operationLog.vue";
import basicDetails from "./basicDetails.vue";
import { markStatusType } from "@/utils/dict";
import { printAssetMark, assetListInfo, deleteAssetList } from "@/api/modules/assetAllocation";
import { useHandleData } from "@/hooks/useHandleData";
import { AssetClassification } from "@/api/interface";
const windowHeight: number = window.innerHeight - 210;
interface DrawerProps {
title: string;
row?: Partial<AssetClassification.pageList>;
isView: boolean;
api?: (params: any) => Promise<any>;
refreshTable?: () => void;
configuration?: any
}
const hasBtnPermission: any = inject('hasBtnPermission');
const previousInfo = (row:any) => {
console.log('rrr',row)
}
const activeName = ref('first');
const drawerVisible = ref(false);
const drawerProps = ref<DrawerProps>({
isView: false,
title: "",
row: {}
});
const infos = ref({
id: "",
baseInfo: {} as any,
markTags: []
});
const markStatusList = ref<Array<{name: string; color: string}>>([]);
const basicDetailsRef = ref();
const operationLogRef = ref();
// 计算属性
const statusStyle = computed(() => {
const status = infos.value.baseInfo?.assetStatus;
const colorMap = {
'1': '#49c625',
'2': '#ff7f00',
'3': '#1890ff'
};
return { 'border-color': colorMap[status] || '#1890ff' };
});
const statusText = computed(() => {
const status = infos.value.baseInfo?.assetStatus;
const textMap = {
'1': '空闲',
'2': '在用',
'3': '借用'
};
return textMap[status] || '';
});
const acceptParams = async (params: DrawerProps) => {
infos.value = { baseInfo: {}, markTags: [], id: "" };
markStatusList.value = [];
drawerProps.value = params;
activeName.value = 'first'
try {
type reqType = {
code?: number,
data?: any,
msg?: string
}
const { code, data, msg } = await assetListInfo({ id: params.row!.id as string }) as reqType;
if (code === 0) {
infos.value = data as any;
drawerVisible.value = true;
// 处理标记状态
if (data.markTags?.length) {
markStatusList.value = data.markTags
.map(tag => {
const status = markStatusType.find(item => item.label === tag);
return status ? { name: tag, color: status.color } : null;
})
.filter(Boolean);
}
nextTick(() => {
basicDetailsRef.value?.setDrawerProps({
row: data,
configuration: params.configuration
});
operationLogRef.value?.setDrawerProps({
row:data
})
});
} else {
ElMessage.error(msg);
}
} catch (error) {
ElMessage.error('获取资产信息失败');
console.error(error);
}
};
// 删除资产
const deleteData = async () => {
await useHandleData(
deleteAssetList,
{ idList: [infos.value.id] },
`确认删除`
);
drawerVisible.value = false;
drawerProps.value.refreshTable?.();
};
// 打印标签
const openTagPrint = async () => {
try {
const { code, msg } = await printAssetMark({
idList: [drawerProps.value!.row!.id],
type: 'baseInfo'
});
if (code === 0) {
ElMessage.success(msg);
drawerProps.value.refreshTable?.();
} else {
ElMessage.error(msg);
}
} catch (error) {
ElMessage.error('打印失败');
console.error(error);
}
};
defineExpose({ acceptParams });
</script>
<style lang="scss" scoped>
.no-header-drawer {
.el-drawer__body {
padding: 0;
.asset_details_header {
.header_title {
border-bottom: 1px solid #ebeef5;
margin: 0 0 12px 0;
display: flex;
padding-bottom: 10px;
.header_left {
flex: 1;
.header_zcInfo {
margin-bottom: 10px;
.header_zcInfo_name {
color: #303133;
font-size: 20px;
font-weight: 600;
padding-right: 15px;
}
.span-zc {
border-radius: 10px;
border: 1px solid;
padding: 2px 5px;
font-size: 12px;
margin-right: 4px;
}
}
.header_userInfo {
color: #606266;
font-size: 14px;
span {
margin-right: 25px;
}
}
}
.header_right {
.trapezoid-isosceles {
content: "";
display: block;
height: 0;
border-width: 0px 19px 35px;
border-style: none solid solid;
position: absolute;
transform: rotate(44deg);
right: -32px;
top: 16px;
width: 94px;
span {
line-height: 35px;
text-align: center;
display: block;
color: #ffffff;
font-size: 18px;
}
}
}
}
}
.asset_details_content {
height: calc(100% - 115px);
overflow-y: auto;
}
}
}
.no-header-drawer {
.el-drawer__body {
padding: 10px 20px;
overflow: hidden;
}
header.el-drawer__header {
border: none !important;
padding: 0 !important;
}
}
</style>
<template>
<div class="table-box">
<ProTable ref="proTable" :columns="columns" :request-api="getTableList" :data-callback="dataCallback">
<!-- 表格 header 按钮 -->
<template #tableHeader="scope">
<el-button type="primary" v-if="hasBtnPermission('asset:inventory:save')"
@click="addNewData('新增资产', 'add', {})">新增资产</el-button>
<el-button type="primary" v-if="hasBtnPermission('asset:inventory:update')"
@click="batcEdit(scope.selectedListIds)">批量编辑</el-button>
<el-button type="primary" v-if="hasBtnPermission('asset:inventory:delete')"
@click="batchDelete(scope.selectedListIds)">批量删除</el-button>
<el-dropdown style="margin-left: 10px" v-if="hasBtnPermission('asset:inventory:downloadData')"
@command="batchExport">
<el-button type="primary">
批量导出<i class="el-icon-arrow-down el-icon--right"></i>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="1">导出所选数据</el-dropdown-item>
<el-dropdown-item command="2">导出全部</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<el-button type="primary" @click="openTagPrint(scope.selectedListIds)"
v-if="hasBtnPermission('asset:inventory:printMark')" style="margin-left: 10px">打印资产标签</el-button>
</template>
<!-- 图片 -->
<template #imageUrl="{ row }">
<div class="more_imgs" v-if="row.imageUrlList && row.imageUrlList.length > 0">
<viewer :images="row.imageUrlList">
<span class="viewImage" v-for="(itemImg, index) in row.imageUrlList" :key="index">
<img v-if="itemImg" :src="itemImg" style="width: 100%; height: 100%" />
</span>
</viewer>
</div>
</template>
<template #operation="scope" v-if="hasBtnPermission('asset:inventory:update')">
<el-button type="primary" link @click="editData('编辑资产', 'edit', scope.row)">编辑</el-button>
</template>
</ProTable>
<!-- 选择新增资产类型 -->
<div class="new-Dialog-type" v-if="dialogFormVisible">
<el-dialog v-model="dialogFormVisible" title="选择资产类型" width="450" draggable>
<el-form ref="ruleFormRef" :model="form" :rules="rules" label-width="93px">
<el-form-item label="类型" prop="type">
<el-select v-model="form.type" placeholder="请选择">
<el-option v-for="item in assetType" :key="item.value" :label="item.label"
:value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="非标准资产" v-if="form.type === 2" prop="nonStandardAssetsId">
<el-select v-model="form.nonStandardAssetsId" placeholder="请选择">
<el-option v-for="item in nonstandardData" :key="item.id" :label="item.name"
:value="item.id" :disabled="item.status == 0"></el-option>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="closeDialog">取消</el-button>
<el-button type="primary" @click="nextTips">下一步</el-button>
</div>
</template>
</el-dialog>
</div>
<!-- 编辑,批量编辑,新增组件 -->
<addAsset ref="addAssetRef" @previous-step="handlePreviousStep" />
<!-- 详情公共组件 -->
<assetInfo ref="assetInfoRef"></assetInfo>
</div>
</template>
<script setup lang="tsx" name="assetInventory">
import { ref, reactive, inject, onMounted, nextTick } from "vue";
import ProTable from "@/components/ProTable/index.vue";
import { assetListData, addAssetList, deleteAssetList, editBatchAssetList, assetListInfo, editAssetList } from "@/api/modules/assetAllocation";
import { ProTableInstance, ColumnProps } from "@/components/ProTable/interface";
import { formatToTree, extractSelectedNodes } from "@/utils/tools";
import { assetClassificationList, getPositionList, setValueClildList, nonstandardList, getOrgSubjectList, getInstitution } from '@/api/modules/public';
import { getUserDepartment } from "@/api/modules/user";
import { assetListType, assetType, markStatusType } from "@/utils/dict";
import addAsset from "./mode/addAsset.vue";
import assetInfo from "./mode/assetInfo.vue";
import { useHandleData } from "@/hooks/useHandleData";
import { ElMessage, FormInstance } from "element-plus";
import { printAssetMark } from "@/api/modules/assetAllocation";
import moment from "moment";
import axios from 'axios';
type nonstandardType = {
id: string,
name: string,
status: number
}
const hasBtnPermission: any = inject('hasBtnPermission');
// ProTable 实例
const proTable = ref<ProTableInstance>();
// 部门级联树数据
const cascaderTreeData = ref([]);
// 子界面需要用到的设置值
const configuration = reactive({
assetCategory: [] as any[], // 资产分类
positionList: [], // 存放地点
departmentList: [] as any[], // 使用部门
sourceList: [] as any[], // 资产来源
nonstandardList: [] as nonstandardType[], // 非标准资产
unitList: [] as any[], // 计量单位
institutionalEntity: [] as any[], //机构主体
assentityList: [] as any[], // 主体
assinstitutional: [] as any[],//机构
})
const selectedIds = ref<string[]>([]); // 在组件顶部定义
// 非标准资产
const nonstandardData = ref<nonstandardType[]>([]);
const assentityList = ref<any[]>([])
const assinstitutional = ref<any[]>([])
// 资产类型弹窗
const dialogFormVisible = ref(false)
type formType = {
type: string | number,
nonStandardAssetsId: string
}
const form = reactive<formType>({
type: '',
nonStandardAssetsId: ''
})
const rules = reactive({
type: [{ required: true, message: "请选择资产类型", trigger: ["blur", "change"] }],
nonStandardAssetsId: [{ required: true, message: "请选择非标准资产", trigger: ["blur", "change"] }],
})
const getTableList = (params: any) => {
if (params.purchaseDate) {
params.purchaseDateStart = params.purchaseDate[0] + ' 00:00:00';
params.purchaseDateEnd = params.purchaseDate[1] + ' 23:59:59';
delete params.purchaseDate;
}
if (params.maintenanceExpirationDate) {
params.maintenanceExpirationDateStart = params.maintenanceExpirationDate[0] + ' 00:00:00';
params.maintenanceExpirationDateEnd = params.maintenanceExpirationDate[1] + ' 23:59:59';
delete params.maintenanceExpirationDate;
}
if (params.useUserNameData) {
params.useUserNameList = params.useUserNameData.split('\n');
delete params.useUserNameData
}
if(params.assetCodeData) {
const filteredArray = params.assetCodeData.split('\n');
params.assetCodeList = filteredArray.filter(item => item.trim() !== '');
delete params.assetCodeData
}
let deptNoList: any[] = [];
// 部门级联数据处理
if (params.useDepartmentId && params.useDepartmentId.length > 0) {
// 根据级联值获取所有选中的部门集合,如果子节点全部选中,父节点也要获取
deptNoList = extractSelectedNodes(params.useDepartmentId, cascaderTreeData.value);
}
if (deptNoList.length > 0) {
params.useDepartmentIdList = deptNoList;
}
delete params.useDepartmentId;
// 清除表格勾选项
if (proTable.value) {
proTable.value.clearSelection();
}
return assetListData(params)
}
const refreshTable = () => {
proTable.value!.pageable.pageNum = 1;
proTable.value?.refreshData();
// 清除表格勾选项
if (proTable.value) {
proTable.value.clearSelection();
}
};
const dataCallback = (data: any) => {
const dataList = data?.dataList || [];
const processedList = dataList.map(item => {
try {
return {
...item,
imageUrlList: typeof item?.imageUrl === 'string' ? item.imageUrl.split(',') : [],
purchaseDate: item.purchaseDate ? item.purchaseDate.split(" ")[0] : ''
};
} catch (error) {
return { ...item, imageUrlList: [] };
}
});
return {
list: processedList,
total: data?.totalCount,
pageNum: data?.page,
pageSize: data?.pageSize
};
};
// 查询计量单位
const getUnitList = async () => {
const response = await setValueClildList({ dictCode: 'UNIT_MEASUREMENT' });
if (Array.isArray(response.data)) {
configuration.unitList = response.data || [];
}
}
// 查询机构主体
const getOrgSubjectListData = async () => {
// 机构
const responseAss = await getInstitution({ id: 'ASS_INSTITUTIONAL' });
const data = responseAss.data || [];
if (Array.isArray(data) && data.length > 0) {
configuration.assinstitutional = data
assinstitutional.value = data
}
// 主体
const response = await getInstitution({ id: 'OFFICIAL_SEAL_ORG' });
const data1 = response.data || [];
if (Array.isArray(data1) && data1.length > 0) {
configuration.assentityList = data1
assentityList.value = data1
}
// 机构主体(二和一接口),用来把主体,机构以及部门三者关联起来,单独调用上面接口,主要是为了排序好看,无语子......
const res = await getOrgSubjectList({}, false);
const data2 = res.data || [];
if (Array.isArray(data) && data.length > 0) {
configuration.institutionalEntity = data2 as any[];
}
}
const formatToDepTree = (arr, pid = 0) => {
let result: any[] = [];
for (let i = 0; i < arr.length; i++) {
if (arr[i].pid === pid) {
arr[i].label = arr[i].name
let children = formatToDepTree(arr, arr[i].workOADepartmentId);
if (children.length > 0) {
arr[i].children = children;
}
result.push(arr[i]);
}
}
return result;
}
// 表格配置项
const columns: ColumnProps[] = [
{
type: "selection",
fixed: "left",
width: 50,
},
{
prop: "assetStatus",
label: "资产状态",
fixed: "left",
minWidth: 100,
enum: assetListType,
search: { el: "select", props: { filterable: true } },
render: scope => {
if (scope.row.assetStatus == '1') {
return (
<span style="color: #49c625">空闲</span>
);
} else if (scope.row.assetStatus == '2') {
return (
<span style="color: #ff7f00">在用</span>
);
} else if (scope.row.assetStatus == '3') {
return (
<span style="color: #1890ff">已处置</span>
);
}
}
},
{
prop: "markStatus",
label: "资产标记",
isShow: false,
enum: markStatusType,
search: { el: "select", props: { filterable: true } },
fieldNames: { label: "label", value: "value" }
},
{
prop: "markTagsName",
label: "资产标记",
fixed: "left",
minWidth: 100,
render: scope => {
if (scope.row.markTags == '0') {
return (
<span style="color: #49c625">派发待领用</span>
);
} else if (scope.row.markTags == '1') {
return (
<span style="color: #ff7f00">领用审批中</span>
);
} else if (scope.row.markTags == '2') {
return (
<span style="color: #ff7f00">退还审批中</span>
);
} else if (scope.row.markTags == '3') {
return (
<span style="color: #ff7f00">借用审批中</span>
);
} else if (scope.row.markTags == '4') {
return (
<span style="color: #1890ff">借用</span>
);
} else if (scope.row.markTags == '5') {
return (
<span style="color: #ff7f00">调拨审批中</span>
);
} else if (scope.row.markTags == '6') {
return (
<span style="color: #ff7f00">维修审批中</span>
);
} else if (scope.row.markTags == '7') {
return (
<span style="color: #ff7f00">处置审批中</span>
);
} else if (scope.row.markTags == '8') {
return (
<span style="color: #ff0000">待处理</span>
);
} else if (scope.row.markTags == '9') {
return (
<span style="color: #ff7f00">归还审批中</span>
);
}
}
},
{
prop: "assetCodeData",
label: "资产编码",
isShow: false,
search: { el: "input", type: 'textarea', placeholder: '多个编码请换行' },
minWidth: 100,
},
{
prop: "assetCode",
label: "资产编码",
fixed: "left",
copy: false,
minWidth: 100,
render: (scope) => {
return (
<span style="color: #49c625" onClick={() => handleAssetCodeClick(scope.row)}>
{scope.row.assetCode}
</span>
);
}
},
{ prop: "imageUrl", label: "图片", minWidth:100, copy: false },
{
prop: "assetCategoryIdList",
label: "资产分类",
isShow:false,
enum: async () => {
// 获取资产分类数据,扁平数据
const { data } = await assetClassificationList({});
if (Array.isArray(data)) {
const treeData = formatToTree(data);
configuration.assetCategory = treeData;
return { data: treeData }
}
return { data: [] }
},
fieldNames: { label: "categoryName", value: "id" },
search: {
el: "tree-select", props: {
filterable: true,
multiple: true,
checkStrictly: true, // 允许选择父节点
nodeKey: "id", // 每个节点的唯一标识字段
props: {
label: "label",
value: "id",
children: "children"
}
}
},
},
{ prop: "assetName", label: "资产名称",isShow:false, search: { el: "input" },minWidth:100 },
{ prop: "assetName", label: "资产名称", fixed: "left",minWidth:100 },
{
prop: "assetCategoryName",
label: "资产分类",
minWidth:100 ,
},
{
prop: "nonStandardAssetsId",
label: "资产类型",
minWidth: 100,
isShow: false,
},
{ prop: "type", label: "资产类型", minWidth: 100, enum: assetType, search: { el: "select", props: { filterable: true } }, },
{ prop: "useUserName", label: "使用人" },
{ prop: "useUserNameData", label: "使用人", isShow: false, search: { el: "input", type: 'textarea', placeholder: '多个使用人请换行' } },
{
prop: "useOrgIdList",
label: "使用机构",
search: {
el: "select", props: {
filterable: true,
multiple: true
}
},
minWidth: 100,
enum: assinstitutional,
isShow: false,
fieldNames: { label: "name", value: "detailCode" },
},
{
prop: "useOrgName",
label: "使用机构",
minWidth: 100,
},
{
prop: "useSubjectId",
label: "使用主体",
search: { el: "select" },
minWidth: 100,
enum: assentityList,
isShow: false,
fieldNames: { label: "remarks", value: "detailCode" },
},
{
prop: "useSubjectName",
label: "使用主体",
minWidth: 100,
},
{
prop: "useDepartmentId", label: "使用部门", isShow: false,
enum: async () => {
// 获取组织架构数据,扁平数据
const { data } = await getUserDepartment();
data.forEach(item => {
item.pid = item.extMap.parentWorkOADepartmentId
item.workOADepartmentId = item.value
item.id = item.value
item.name = item.label
})
// 将组织架构数据处理成树结构
const treeData = formatToDepTree(data);
configuration.departmentList = treeData;
return { data: treeData }
}, search: { el: "cascader", props: { props: { multiple: true } } }
},
{
prop: "useDepartmentName",
label: "使用部门",
minWidth:100 ,
},
{
prop: "storageLocationIdList",
label: "存放地点",
minWidth: 100,
isShow: false,
enum: async () => {
// 获取存放地点
const res = await getPositionList({ pageNum: 1, pageSize: 9999 });
const data = res.data as any;
const deepCopy = JSON.parse(JSON.stringify(data['dataList']));
configuration.positionList = deepCopy;
return { data: data['dataList'] };
},
fieldNames: { label: "position", value: "id" },
search: { el: "select", props: { filterable: true, multiple: true } },
},
{
prop: "storageLocationName",
label: "存放地点",
minWidth: 100,
},
{ prop: "adminName", label: "管理员", search: { el: "input" } },
{ prop: "affiliatedInstitutionName", label: "所属机构", minWidth: 100 },
{
prop: "affiliatedInstitutionIdList", label: "所属机构", isShow: false, search: { el: "select", props: { filterable: true, multiple: true } }, minWidth: 100, enum: assinstitutional,
fieldNames: { label: "name", value: "detailCode" },
},
{ prop: "affiliatedSubjectName", label: "所属主体", minWidth: 100 },
{
prop: "affiliatedSubjectId", label: "所属主体", isShow: false, search: { el: "select" }, minWidth: 100, enum: assentityList,
fieldNames: { label: "remarks", value: "detailCode" }
},
{
prop: "assetSourceTypeList",
label: "资产来源",
isShow: false,
enum: async () => {
// 获取资产来源
const data = await setValueClildList({ dictCode: 'SOURCE_ASSETS' });
configuration.sourceList = data['data'] as any[];
return { data: data['data'] }
},
fieldNames: { label: "itemLabel", value: "itemValue" },
search: { el: "select", props: { filterable: true, multiple: true } },
},
{
prop: "sourceCode",
label: "资产来源",
minWidth: 100,
},
{ prop: "brand", label: "品牌", search: { el: "input" }, },
{ prop: "specificationModel", label: "规格型号", search: { el: "input" }, minWidth: 100 },
{ prop: "serialNumber", label: "序列号", search: { el: "input" } },
{ prop: "measurementUnit", label: "计量单位", minWidth: 100 },
{ prop: "remarks", label: "备注", search: { el: "input" } },
{
prop: "supplierName", label: "供应商", search: { el: "input" },
},
{ prop: "inBoundNo", label: "入库单号", minWidth: 100 },
{
prop: "nonStandardAssetsId",
label: "非标准资产",
enum: async () => {
// 获取非标准资产
const data = await nonstandardList({});
if (Array.isArray(data)) {
nonstandardData.value = data.filter(item => item.status == 1);
configuration.nonstandardList = data
}
return { data: data }
},
isShow: false,
fieldNames: { label: "name", value: "id" },
search: { el: "select", props: { filterable: true } },
},
{
prop: "purchaseDate",
label: "购入日期",
minWidth: 148,
search: {
el: "date-picker",
props: { type: "daterange", valueFormat: "YYYY-MM-DD" },
},
},
{
prop: "maintenanceExpirationDate",
label: "维保到期日期",
isShow: false,
search: {
el: "date-picker",
props: { type: "daterange", valueFormat: "YYYY-MM-DD" },
},
},
{ prop: "operation", label: "操作", fixed: "right", isShow: true, sortable: false }
]
// 批量导出
const batchExport = async (command: any) => {
try {
const selectedIds = proTable.value?.selectedListIds || [];
// 验证选择(如果command不是2,则需要选择数据)
if (command != 2 && selectedIds.length === 0) {
ElMessage.error({ message: `请选择要操作的数据` });
return;
}
const params = {
idList: command === 2 ? [] : selectedIds // command=2表示导出全部
};
const response = await axios.post('/api/asset/inventory/downloadData',
params,
{
responseType: 'blob'
}
);
let filename = `资产清单_${moment().format('YYYYMMDDHHmmss')}.xlsx`;// 设置下载文件的名称
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', filename);
document.body.appendChild(link);
link.click();
link.remove();
// 清除表格勾选项
if (proTable.value) {
proTable.value.clearSelection();
}
} catch (error) {
console.error("导出失败:", error);
}
};
// 批量删除
const batchDelete = async (ids: string[]) => {
if (ids && ids.length === 0) {
ElMessage.error({ message: `请选择要操作的数据` });
return
}
await useHandleData(deleteAssetList, { idList: ids }, `确认删除`);
refreshTable()
}
// 批量编辑
const batcEdit = async (ids: string[]) => {
if (ids && ids.length === 0) {
ElMessage.error({ message: `请选择要操作的数据` });
return;
}
// 从表格中获取当前所有选中的行数据
const selectedRows = proTable.value?.selectedList || [];
const types = selectedRows.map(row => row.type);
const nonStandardAssets = selectedRows.map(row => row.nonStandardAssetsId);
const uniqueTypes = [...new Set(types)];
const uniqueNoStandar = [...new Set(nonStandardAssets)];
if (uniqueTypes.length > 1) {
ElMessage.warning("只能选择相同类型的资产进行批量编辑");
return;
}
if (uniqueNoStandar.length > 1) {
ElMessage.warning("只能选择相同类型的非标准资产进行批量编辑");
return
}
selectedIds.value = ids;
form.type = uniqueTypes.join();
form.nonStandardAssetsId = uniqueNoStandar.join();
editBatchData('批量编辑', 'batchEdit', {});
}
// 打印标签
const openTagPrint = async (ids: string[]) => {
if (ids && ids.length === 0) {
ElMessage.error({ message: `请选择要操作的数据` });
return
}
const data = await printAssetMark({ idList: ids, type: 'baseInfo' });
if (data.code == 0) {
ElMessage.success({ message: data.msg });
refreshTable()
} else {
ElMessage.error({ message: data.msg });
}
}
const closeDialog = () => {
dialogFormVisible.value = false
// 清除表格勾选项
if (proTable.value) {
proTable.value.clearSelection();
}
}
// 子组件的上一步操作
const handlePreviousStep = () => {
dialogFormVisible.value = true; // 重新打开对话框
// if( Type.value == 'batchEdit') {}
// 回显之前选择的数据(form 已在 openDrawer 时保存)
nextTick(() => {
ruleFormRef.value?.clearValidate(); // 清除校验状态
});
// proTable.value!.setCheckedRows(proTable.value?.selectedList); // 回显之前选择的数据
};
const Title = ref("");
const Type = ref('add')
const Row = ref({})
// 新增
const addNewData = (title: string, type: string, row: any = {}) => {
Title.value = title
Type.value = type
Row.value = row
// 清空表单值
form.type = '';
form.nonStandardAssetsId = '';
// 重置表单校验状态
nextTick(() => {
ruleFormRef.value?.resetFields();
});
dialogFormVisible.value = true
}
// 编辑
const editData = async (title: string, type: string, row: any = {}) => {
const { code, data, msg } = await assetListInfo({ id: row.id });
if (code == 0) {
form.type = row.type
form.nonStandardAssetsId = ''
let listData = [data]
Title.value = title
Type.value = type
Row.value = listData
openDrawer()
} else {
ElMessage.error(msg);
}
}
// 批量编辑
const editBatchData = (title: string, type: string, row: any = {}) => {
Title.value = title
Type.value = type
Row.value = row
openDrawer()
}
// 查看详情
const assetInfoRef = ref<InstanceType<typeof addAsset> | null>(null);
const handleAssetCodeClick = async (row: any) => {
const params = {
row: { ...row },
api: deleteAssetList,
configuration: configuration,
refreshTable: () => {
proTable.value!.pageable.pageNum = 1;
proTable.value?.refreshData();
}
}
assetInfoRef.value?.acceptParams(params as any)
}
// 下一步
const nextTips = () => {
ruleFormRef.value!.validate(async valid => {
if (!valid) return;
try {
openDrawer()
} catch (error) {
console.log(error);
}
})
}
// 新增/编辑
const ruleFormRef = ref<FormInstance>();
const addAssetRef = ref<InstanceType<typeof addAsset> | null>(null);
const openDialog = () => {
// 清空表单值
form.type = '';
form.nonStandardAssetsId = '';
// 重置表单校验状态
nextTick(() => {
ruleFormRef.value?.resetFields();
});
dialogFormVisible.value = true
}
const openDrawer = () => {
if (Type.value === 'add') {
dialogFormVisible.value = false
const params = {
title: Title.value,
type: Type.value,
row: { ...Row.value },
form: { ...form },
configuration: configuration,
isView: false,
api: addAssetList,
refreshTable: () => {
proTable.value!.pageable.pageNum = 1;
proTable.value?.refreshData();
}
}
addAssetRef.value?.acceptParams(params)
} else if (Type.value === 'edit') {
const params = {
title: Title.value,
type: Type.value,
// configuration: configuration,
isView: false,
row: {},
form: { ...form },
infoRow: { ...Row.value },
api: editAssetList,
refreshTable: () => {
proTable.value!.pageable.pageNum = 1;
proTable.value?.refreshData();
}
}
addAssetRef.value?.acceptParams(params)
} else {
dialogFormVisible.value = false
const params = {
title: Title.value,
type: Type.value,
configuration: configuration,
isView: false,
form: { ...form },
row: { selectedIds: selectedIds.value },
api: editBatchAssetList,
refreshTable: () => {
proTable.value!.pageable.pageNum = 1;
proTable.value?.refreshData();
}
}
addAssetRef.value?.acceptParams(params)
}
}
onMounted(() => {
getUnitList();
getOrgSubjectListData();
})
</script>
<style lang="scss" scoped>
.more_imgs {
div {
display: inline-flex;
}
.viewImage {
width: 25px;
height: 25px;
cursor: pointer;
}
}
/* 确保选择列可见 */
::v-deep .el-table__fixed-left {
.el-table__cell.is-hidden>* {
visibility: visible !important;
}
.el-checkbox {
display: inline-block;
}
}
</style>
operationLog孙子界面的点击handleAssetCodeClick,并且带参数,在assetInventory界面的assetInfo组件返回中能调用