You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

343 lines
12 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<ContentWrap>
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" min-label-width="68px">
<el-form-item :label="t('EquipmentManagement.EquipmentKeyItems.code')" prop="code">
<el-input
v-model="queryParams.code" :placeholder="t('EquipmentManagement.EquipmentKeyItems.placeholderCode')"
clearable @keyup.enter="handleQuery" class="!w-240px" />
</el-form-item>
<el-form-item :label="t('EquipmentManagement.EquipmentKeyItems.name')" prop="name">
<el-input
v-model="queryParams.name" :placeholder="t('EquipmentManagement.EquipmentKeyItems.placeholderName')"
clearable @keyup.enter="handleQuery" class="!w-240px" />
</el-form-item>
<el-form-item :label="t('EquipmentManagement.EquipmentKeyItems.description')" prop="description" v-show="showAllFilters">
<el-input
v-model="queryParams.description"
:placeholder="t('EquipmentManagement.EquipmentKeyItems.placeholderDescription')" clearable
@keyup.enter="handleQuery" class="!w-240px" />
</el-form-item>
<el-form-item :label="t('EquipmentManagement.EquipmentKeyItems.remark')" prop="remark" v-show="showAllFilters">
<el-input
v-model="queryParams.remark"
:placeholder="t('EquipmentManagement.EquipmentKeyItems.placeholderRemark')" clearable
@keyup.enter="handleQuery" class="!w-240px" />
</el-form-item>
<el-form-item :label="t('EquipmentManagement.EquipmentKeyItems.createTime')" prop="createTime" v-show="showAllFilters">
<el-date-picker
v-model="queryParams.createTime" value-format="YYYY-MM-DD HH:mm:ss" type="daterange"
:start-placeholder="t('common.startTimeText')" :end-placeholder="t('common.endTimeText')"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" class="!w-220px" />
</el-form-item>
<el-form-item v-if="filterCount > 3">
<el-button type="text" class="text-primary" @click="toggleFilters">
<Icon :icon="showAllFilters ? 'ep:arrow-up' : 'ep:arrow-down'" class="mr-5px" />
{{ showAllFilters ? t('FactoryModeling.FactoryStructure.collapseText') : t('FactoryModeling.FactoryStructure.expandText') }}
</el-button>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery">
<Icon icon="ep:search" class="mr-5px" />
{{ t('common.query') }}
</el-button>
<el-button @click="resetQuery">
<Icon icon="ep:refresh" class="mr-5px" />
{{ t('common.reset') }}
</el-button>
<el-button type="primary" plain @click="openForm('create')" v-hasPermi="['mes:critical-component:create']">
<Icon icon="ep:plus" class="mr-5px" />
{{ t('action.add') }}
</el-button>
<el-button
type="danger" plain @click="handleBatchDelete" :disabled="!selectedIds.length"
v-hasPermi="['mes:critical-component:delete']">
<Icon icon="ep:delete" class="mr-5px" />
{{ t('EquipmentManagement.EquipmentKeyItems.batchDelete') }}
</el-button>
<el-button type="warning" plain @click="openImport" v-hasPermi="['mes:critical-component:import']">
<Icon icon="ep:upload" class="mr-5px" />
{{ t('action.import') }}
</el-button>
<el-button
type="success" plain @click="handleExport" :loading="exportLoading"
v-hasPermi="['mes:critical-component:export']">
<Icon icon="ep:download" class="mr-5px" />
{{ t('action.export') }}
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<ContentWrap>
<el-table
v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" />
<el-table-column
:label="t('EquipmentManagement.EquipmentKeyItems.code')" align="center" prop="code"
min-width="140" sortable />
<el-table-column
:label="t('EquipmentManagement.EquipmentKeyItems.name')" align="center" prop="name"
min-width="140" sortable />
<el-table-column
:label="t('EquipmentManagement.EquipmentKeyItems.deviceSpec')" align="center" prop="deviceSpec"
min-width="140" sortable />
<el-table-column
:label="t('EquipmentManagement.EquipmentKeyItems.description')" align="center" prop="description"
min-width="180" />
<el-table-column
:label="t('EquipmentManagement.EquipmentKeyItems.count')" align="center" prop="count"
min-width="180" />
<el-table-column
:label="t('EquipmentManagement.EquipmentKeyItems.remark')" align="center" prop="remark"
min-width="180" />
<el-table-column
:label="t('EquipmentManagement.EquipmentKeyItems.createTime')" align="center" prop="createTime"
:formatter="dateFormatter" width="180" sortable />
<el-table-column
:label="t('EquipmentManagement.EquipmentKeyItems.operate')" align="center" width="140"
fixed="right">
<template #default="scope">
<el-button
link type="primary" @click="openForm('update', scope.row.id)"
v-hasPermi="['mes:critical-component:update']">
{{ t('EquipmentManagement.EquipmentKeyItems.edit') }}
</el-button>
<el-button
link type="danger" @click="handleDelete(scope.row.id)"
v-hasPermi="['mes:critical-component:delete']">
{{ t('EquipmentManagement.EquipmentKeyItems.delete') }}
</el-button>
</template>
</el-table-column>
</el-table>
<Pagination
:total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
@pagination="getList" />
</ContentWrap>
<CriticalComponentForm ref="formRef" @success="getList" />
<Dialog v-model="importDialogVisible" :title="t('action.import')" width="400">
<el-upload
ref="uploadRef" v-model:file-list="importFileList"
:action="importUrl + '?updateSupport=' + updateSupport" :auto-upload="false" :disabled="importLoading"
:headers="uploadHeaders" :limit="1" :on-error="handleImportError" :on-exceed="handleImportExceed"
:on-success="handleImportSuccess" accept=".xlsx, .xls" drag>
<Icon icon="ep:upload" />
<div class="el-upload__text">
将文件拖到此处,或点击上传
</div>
<template #tip>
<div class="el-upload__tip text-center">
<div class="el-upload__tip">
<el-checkbox v-model="updateSupport" />
是否更新已存在的数据
</div>
<span>仅支持 .xlsx, .xls 格式</span>
<el-link
:underline="false" style="font-size: 12px; vertical-align: baseline" type="primary"
@click="importTemplate">
下载导入模板
</el-link>
</div>
</template>
</el-upload>
<template #footer>
<el-button :disabled="importLoading" type="primary" @click="submitImport">{{ t('common.ok') }}</el-button>
<el-button @click="importDialogVisible = false">{{ t('common.cancel') }}</el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { CriticalComponentApi, CriticalComponentVO } from '@/api/mes/criticalComponent'
import { getAccessToken, getTenantId } from '@/utils/auth'
import CriticalComponentForm from './CriticalComponentForm.vue'
import { ElMessageBox } from 'element-plus'
defineOptions({ name: 'CriticalComponent' })
const message = useMessage()
const { t } = useI18n()
const loading = ref(true)
const list = ref<CriticalComponentVO[]>([])
const total = ref(0)
const exportLoading = ref(false)
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
code: undefined as string | undefined,
name: undefined as string | undefined,
description: undefined as string | undefined,
remark: undefined as string | undefined,
createTime: [] as string[]
})
const queryFormRef = ref()
const selectedIds = ref<number[]>([])
const showAllFilters = ref(false)
const filterCount = 5
const toggleFilters = () => {
showAllFilters.value = !showAllFilters.value
}
const importDialogVisible = ref(false)
const importLoading = ref(false)
const uploadRef = ref()
const importUrl =
import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/mes/critical-component/import'
const uploadHeaders = ref()
const importFileList = ref([])
const updateSupport = ref(0)
const escapeHtml = (value: unknown) => {
return String(value ?? '')
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;')
}
const getList = async () => {
loading.value = true
try {
const data = await CriticalComponentApi.getCriticalComponentPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
const handleSelectionChange = (rows: CriticalComponentVO[]) => {
selectedIds.value = rows.map((r) => r.id).filter((id): id is number => typeof id === 'number')
}
const formRef = ref()
const openForm = (type: 'create' | 'update', id?: number) => {
formRef.value.open(type, id)
}
const openImport = () => {
importDialogVisible.value = true
importLoading.value = false
importFileList.value = []
updateSupport.value = 0
}
const handleDelete = async (id?: number) => {
if (!id) return
try {
await message.delConfirm()
await CriticalComponentApi.deleteCriticalComponent(String(id))
message.success(t('common.delSuccess'))
await getList()
} catch {
}
}
const handleBatchDelete = async () => {
if (!selectedIds.value.length) return
try {
await message.delConfirm()
await CriticalComponentApi.deleteCriticalComponent(selectedIds.value.join(','))
message.success(t('common.delSuccess'))
selectedIds.value = []
await getList()
} catch {
}
}
const handleExport = async () => {
try {
await message.exportConfirm()
exportLoading.value = true
const params = {
...queryParams,
ids: selectedIds.value.length ? selectedIds.value.join(',') : undefined
}
const data = await CriticalComponentApi.exportCriticalComponent(params)
download.excel(data, '设备关键件.xls')
} catch {
} finally {
exportLoading.value = false
}
}
const submitImport = async () => {
if (importFileList.value.length === 0) {
message.error('请选择导入文件')
return
}
uploadHeaders.value = {
Authorization: 'Bearer ' + getAccessToken(),
tenantId: getTenantId()
}
importLoading.value = true
uploadRef.value?.submit()
}
const handleImportSuccess = async (response: any) => {
if (!response || response.code !== 0) {
message.error(response?.msg || '导入失败')
importLoading.value = false
return
}
const failureCodes = response?.data?.failureCodes
if (failureCodes && typeof failureCodes === 'object') {
const entries = Object.entries(failureCodes).filter(([key]) => String(key).trim() !== '')
if (entries.length > 0) {
const detail = entries
.map(([code, err], index) => `${index + 1}. ${escapeHtml(code)}${escapeHtml(err)}`)
.join('<br />')
await ElMessageBox.alert(`以下编码导入失败:<br />${detail}`, t('common.confirmTitle'), {
type: 'error',
dangerouslyUseHTMLString: true,
})
} else {
message.success('导入成功')
}
} else {
message.success('导入成功')
}
importLoading.value = false
importDialogVisible.value = false
getList()
}
const handleImportError = () => {
message.error('导入失败')
importLoading.value = false
}
const handleImportExceed = () => {
message.error('只能上传一个文件')
}
const importTemplate = async () => {
const res = await CriticalComponentApi.importCriticalComponentTemplate()
download.excel(res, '设备关键件导入模板.xls')
}
onMounted(() => {
getList()
})
</script>