vue性能优化
1. 单一页面里组件过多导致页面访问过慢!!!
在初次进入页面时,只加载必要的组件,其他组件在需要时才进行加载。
思路: 通过import()动态引入组件,
vue
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
ref="queryFormRef"
:inline="true"
:model="queryParams"
class="-mb-15px"
label-width="68px"
>
<el-form-item label="任务名称" prop="name">
<el-select
v-model="queryParams.name"
placeholder="请选择任务名称"
clearable
filterable
class="!w-210px"
>
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.ERP_TASK_NAME_TYPE)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="任务描述" prop="description">
<el-input v-model="queryParams.description" placeholder="请输入任务描述" />
</el-form-item>
<el-form-item label="执行人" prop="ownerUserId">
<el-select
v-model="queryParams.ownerUserId"
filterable
clearable
class="!w-210px">
<el-option
v-for="item in userOptions"
:key="item.id"
:label="item.nickname"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="打卡时间" prop="clockInTime">
<el-date-picker
v-model="queryParams.clockInTime"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择打卡时间"
class="!w-210px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery">
<Icon class="mr-5px" icon="ep:search" />
搜索
</el-button>
<el-button @click="resetQuery">
<Icon class="mr-5px" icon="ep:refresh" />
重置
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table :header-cell-style="$tableHeaderCellStyle()" v-loading="loading" :data="list" :border="true">
<el-table-column label="序号" align="center" type="index" width="100" />
<el-table-column align="center" label="任务类型" prop="category" width="180" sortable>
<template #default="{ row }">
<dict-tag
v-if="row.category"
:type="DICT_TYPE.TODO_TASK_TYPE"
:value="row.category"
/>
<div v-else>{{ '-' }}</div>
</template>
</el-table-column>
<el-table-column label="任务描述" align="center" prop="description" sortable>
<template #default="scope">
<div v-if="isFormattedDescription(scope.row.description)">
【{{ getDescriptionPart(scope.row.description, 0) }}】-
<dict-tag
:type="DICT_TYPE.CRM_SERVICE_TYPE"
:value="getDescriptionPart(scope.row.description, 1)"
/>
-
<dict-tag
:type="DICT_TYPE.CRM_VISIT_PURPOSE"
:value="getDescriptionPart(scope.row.description, 2)"
/>
</div>
<div v-else>
{{ scope.row.description?scope.row.description:'-' }}
</div>
</template>
</el-table-column>
<el-table-column
align="center"
label="任务名称"
prop="name"
width="150"
sortable
>
<template #default="{ row }">
<dict-tag
:type="DICT_TYPE.ERP_TASK_NAME_TYPE"
:value="row.name"
/>
</template>
</el-table-column>
<el-table-column
align="center"
label="执行人"
prop="processInstance.startUser.nickname"
width="100"
sortable
/>
<el-table-column
:formatter="dateFormatter"
align="center"
label="任务创建时间"
prop="createTime"
sortable
/>
<el-table-column align="center" label="操作" fixed="right" width="120">
<template #default="scope">
<el-button link type="primary" @click="handleAudit(scope.row,'check')">处理</el-button>
<el-button link @click="handleAudit(scope.row,'view')">详情</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
v-model:limit="queryParams.pageSize"
v-model:page="queryParams.pageNo"
:total="total"
@pagination="getList"
/>
</ContentWrap>
<component
:is="asyncComponent"
ref="componentRef"
@success="getList"
/>
<!-- 对话框 -->
<el-dialog
v-model="dialogVisible"
:title="dialogTile"
width="70%"
@close="resetForm"
>
<el-form :model="formData" ref="formRef">
<el-button type="primary" @click="handleOut" v-if="isStockOut" :disabled="formType == 'view'" style="margin-bottom: 10px;">出库</el-button>
<el-button type="primary" @click="handleIn" v-if="!isStockOut" :disabled="formType == 'view'" style="margin-bottom: 10px;">入库</el-button>
<div class="form-section">
<h4 class="section-title">申请的备件信息</h4>
<productApplyForm ref="productApplyFormRef" v-model="formData.productApplyData" :is-task="true" />
</div>
</el-form>
<template #footer>
<el-button @click="dialogVisible = false">关闭</el-button>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { dateFormatter } from '@/utils/formatTime'
import * as TaskApi from '@/api/bpm/task'
import { CategoryApi, CategoryVO } from '@/api/bpm/category'
import { FaultWarrantyApi } from '@/api/erp/faultwarranty'
import { getStrDictOptions, DICT_TYPE } from '@/utils/dict'
import * as UserApi from '@/api/system/user'
import { StockApi } from '@/api/erp/stock/stock'
import { ProductApi } from '@/api/erp/product/product'
import { ref, reactive, onMounted, onActivated } from 'vue'
import { useRouter } from 'vue-router'
import productApplyForm from '@/views/erp/order/workorder/productApplyForm.vue'
const asyncComponent = ref(null)
// 当前执行node命令时文件夹的地址(工作目录)
defineOptions({ name: 'BpmTodoTask' })
const { push } = useRouter()
const userOptions = ref<UserApi.UserVO[]>([])
const loading = ref(true)
const total = ref(0)
const list = ref([])
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
description: "",
name: '',
category: undefined,
ownerUserId: undefined,
clockInTime: undefined,
createTime: []
})
const queryFormRef = ref()
const productApplyFormRef = ref()
const categoryList = ref<CategoryVO[]>([])
const dialogVisible = ref(false)
const formData = reactive({
type: undefined,
stockDOS: [],
productApplyData: []
})
const formRef = ref(null)
const dialogTile = ref()
const taskId = ref()
const temporaryNumber = ref()
const formType = ref()
const isStockOut = ref(false)
const componentRef = ref(null)
const getCurrentComponent = async (url: string) => {
try{
const module = await import(url);
asyncComponent.value = module.default;
await nextTick()
} catch(e){
console.log(e)
}
}
const handleOut = async () => {
const module = await import('@/views/erp/stock/stock/components/StockOutForm.vue')
asyncComponent.value = module.default;
await nextTick()
componentRef.value?.open(null, taskId.value,temporaryNumber.value,formData.productApplyData)
}
const handleIn = async () => {
const module = await import('@/views/erp/stock/stock/components/StockInForm.vue')
asyncComponent.value = module.default;
await nextTick()
componentRef.value?.open(null, taskId.value,temporaryNumber.value, formData.productApplyData)
}
const hanldeStockout = () => {
dialogVisible.value = false
getList()
}
const resetForm = () => {
if (formRef.value) {
formRef.value?.resetFields()
}
}
const getList = async () => {
loading.value = true
try {
const data = await TaskApi.getTaskTodoPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
const loadUsers = async () => {
try {
userOptions.value = await UserApi.getSimpleUserList()
} finally {
}
}
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
const isFormattedDescription = (desc) => {
return desc?.split('-').length === 3
}
const getDescriptionPart = (desc, index) => {
return desc.split('-')[index] || ''
}
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
const handleAudit = async (row: any, type: any) => {
taskId.value = row.id
if(row.name == "1" || row.name == '17') {
const module = await import('@/views/crm/visitrecord/VisitRecordForm.vue')
asyncComponent.value = module.default;
await nextTick()
if(type == 'view') {
componentRef.value?.open('view', row.parentTaskId, true, true, null, row.id, +row.parentTaskId,null,null,row.name)
} else {
componentRef.value?.open('update', row.parentTaskId, true, false, row.id, +row.parentTaskId,null,null,row.name)
}
}
if(row.name == '2' || row.name == '3') {
const module = await import('@/views/crm/visitCheck/VisitCheckForm.vue')
asyncComponent.value = module.default;
await nextTick()
if(type == 'view') {
componentRef.value?.open('view', row.parentTaskId, true, true, row.id, +row.parentTaskId,null,null,row.name)
} else {
componentRef.value?.open('update', row.parentTaskId, true, false, row.id, +row.parentTaskId,null,null,row.name)
}
}
if(row.name == "4") {
if(type == 'view') {
const module = await import('@/views/project/order/faultwarranty/FaultWarrantyForm.vue')
asyncComponent.value = module.default;
await nextTick()
componentRef.value?.open('view', row.parentTaskId)
} else {
const module = await import('@/views/project/order/faultwarranty/components/FaultCheckForm.vue')
asyncComponent.value = module.default;
await nextTick()
let deviceList = []
try {
const data = await FaultWarrantyApi.getFaultWarranty(+row.parentTaskId)
deviceList = data.faultWarrantyDevice
componentRef.value?.open('update', row, row.parentTaskId, false, true, null, null, deviceList, data)
} catch(e) {
console.error(e)
}
}
}
if(row.name == "8") {
if(type == 'view') {
const module = await import('@/views/erp/order/workorder/RepairWorkOrderView.vue')
asyncComponent.value = module.default;
await nextTick()
componentRef.value?.open('view', row.parentTaskId, null)
} else {
const module = await import('@/views/erp/order/workorder/RepairWorkOrderForm.vue')
asyncComponent.value = module.default;
await nextTick()
componentRef.value?.open('update', row.parentTaskId, null, null, row.id)
}
}
if(row.name == "5") {
if(type == 'view') {
const module = await import('@/views/erp/order/workorder/RepairWorkOrderView.vue')
asyncComponent.value = module.default;
await nextTick()
componentRef.value?.open('view', row.parentTaskId, null, null, row.id)
} else {
const module = await import('@/views/erp/order/workorder/RepairWorkOrderForm.vue')
asyncComponent.value = module.default;
await nextTick()
componentRef.value?.open('update', row.parentTaskId, null, null, row.id)
}
}
if(row.name == "9") {
const module = await import('@/views/erp/outsourcing/outWorkorder/components/DetectionInformationForm.vue')
asyncComponent.value = module.default;
await nextTick()
if(type == 'view') {
componentRef.value?.open('view', row.parentTaskId, row.id)
} else {
componentRef.value?.open('update', row.parentTaskId, row.id)
}
}
if(row.name == "23") {
const module = await import('@/views/erp/outsourcing/outWorkorder/components/Apply.vue')
asyncComponent.value = module.default;
await nextTick()
if(type == 'view') {
componentRef.value?.open('view', row.parentTaskId, row.id)
} else {
componentRef.value?.open('create', row.parentTaskId, row.id)
}
}
if(row.name == "16") {
dialogTile.value = '入库'
isStockOut.value = false
const id = row.parentTaskId
if(type == 'view') {
dialogVisible.value = true
formType.value = type
let res = await StockApi.getStockTemporary({temporaryNumber: id, pageNo: 1, pageSize: 100})
formData.productApplyData = res.list
} else {
formType.value = type
dialogVisible.value = true
formData.productApplyData = []
temporaryNumber.value = id
try {
let res = await StockApi.getStockTemporary({temporaryNumber: id, pageNo: 1, pageSize: 100})
formData.productApplyData = res.list
if(res.list[0]?.productId) {
Object.assign(formData, res.list)
const list = res.list.map(item => ({
...item,
stockQuantity: item.productQuantity
}))
formData.stockDOS = list
formData.direction = formData.stockDOS[0]?.direction
formData.temporaryNumber = id
}
} catch(e) {
console.error(e)
}
}
}
if(row.name == '15') {
dialogTile.value = '出库'
isStockOut.value = true
formData.productApplyData = []
if(type == 'view') {
formType.value = type
const id = row.parentTaskId
dialogVisible.value = true
let res = await StockApi.getStockTemporary({temporaryNumber: id, pageNo: 1, pageSize: 100})
formData.productApplyData = res.list
} else {
formType.value = type
dialogVisible.value = true
const id = row.parentTaskId
temporaryNumber.value = id
try {
let res = await StockApi.getStockTemporary({temporaryNumber: id, pageNo: 1, pageSize: 100})
formData.productApplyData = res.list
if(res.list[0]?.productId) {
Object.assign(formData, res.list)
const list = res.list.map(item => ({
...item,
stockQuantity: item.productQuantity
}))
formData.stockDOS = list
formData.direction = formData.stockDOS[0]?.direction
formData.temporaryNumber = id
} else {
const categoryIdList = res.list.map(item => item.categoryId)
if(categoryIdList?.length > 0) {
const data = await ProductApi.getByCategory({categoryIds: categoryIdList.join(','), pageNo: 1, pageSize: 100})
const productList = data.list.map(item => ({
productId: item.id,
productName: item.name,
stockQuantity: item.productQuantity,
...item
}))
formData.stockDOS = productList
formData.direction = res.list[0]?.direction
formData.temporaryNumber = id
}
}
} catch(e) {
console.error(e)
}
}
}
if(row.name == "12") {
dialogTile.value = '委外信息完善'
const module = await import('@/views/erp/outsourcing/outWorkorder/components/TrackingNumber.vue')
asyncComponent.value = module.default;
await nextTick()
if(type == 'view') {
componentRef.value?.open('view', +row.parentTaskId, taskId.value)
} else {
componentRef.value?.open('update', +row.parentTaskId, taskId.value)
}
}
if(row.name == "13") {
const module = await import('@/views/project/initiation/components/projectPayTodo.vue')
asyncComponent.value = module.default;
await nextTick()
dialogTile.value = '费用支付'
if(type == 'view') {
componentRef.value?.open('view', row.parentTaskId, null, row.id)
} else {
componentRef.value?.open('update', +row.parentTaskId, null, row.id)
}
}
if(row.category == "4") {
if(type == 'check') {
push({
name: 'BpmProcessInstanceDetail',
query: {
id: row.processInstanceId,
processInstanceId: row.processInstanceId.split('-')[1],
name: row.name
}
})
} else {
if(row.name == 100) {
const module = await import('@/views/crm/customerfirst/CustomerForm.vue')
asyncComponent.value = module.default;
await nextTick()
componentRef.value?.open('view', row.processInstanceId.split('-')[1])
}
if(row.name == 101) {
const module = await import('@/views/erp/purchase/supplier/SupplierForm.vue')
asyncComponent.value = module.default;
await nextTick()
componentRef.value?.open('view', row.processInstanceId.split('-')[1])
}
if(row.name == 200) {
const module = await import('@/views/crm/visitCheck/VisitCheckForm.vue')
asyncComponent.value = module.default;
await nextTick()
componentRef.value?.open('view', row.processInstanceId.split('-')[1])
}
if(row.name == 300) {
const module = await import('@/views/crm/visitCheck/VisitCheckForm.vue')
asyncComponent.value = module.default;
await nextTick()
componentRef.value?.open('view', row.processInstanceId.split('-')[1])
}
if(row.name == 301) {
const module = await import('@/views/crm/business/components/BussinessProject.vue')
asyncComponent.value = module.default;
await nextTick()
componentRef.value?.open('view', row.processInstanceId.split('-')[1])
}
if(row.name == 400) {
const module = await import('@/views/erp/outsourcing/outWorkorder/OutsourcingWorkOrderForm.vue')
asyncComponent.value = module.default;
await nextTick()
componentRef.value?.open('view', row.processInstanceId.split('-')[1])
}
if(row.name == 401) {
const module = await import('@/views/erp/lending/out/BorrowRecordsForm.vue')
asyncComponent.value = module.default;
await nextTick()
componentRef.value?.open('view', row.processInstanceId.split('-')[1])
}
if(row.name == 102) {
const module = await import('@/views/erp/device/ib/DeviceViewForm.vue')
asyncComponent.value = module.default;
await nextTick()
componentRef.value.open('view',row.processInstanceId.split('-')[1],null,null,'Todo')
}
}
}
}
onMounted(async () => {
await getList()
await loadUsers()
categoryList.value = await CategoryApi.getCategorySimpleList()
})
onActivated(async () => {
await getList()
})
</script>
<style scoped>
.form-section {
padding: 16px;
margin-bottom: 24px;
background-color: #fff;
border: 1px solid #ebeef5;
border-radius: 4px;
}
.section-title {
padding: 12px 16px;
margin: -16px -16px 16px;
font-size: 14px;
font-weight: 500;
color: #303133;
background-color: #f5f7fa;
border-bottom: 1px solid #ebeef5;
}
.el-radio {
margin-right: 15px;
}
</style>