fix(erp-frontend-vue): resolve TypeScript build errors (duplicate ids, unused vars, null guards, type mismatches)

Made-with: Cursor
This commit is contained in:
panchengyong
2026-03-01 16:40:38 +08:00
parent 10b6d0099a
commit e45616a09b
28 changed files with 45 additions and 49 deletions

View File

@@ -57,10 +57,6 @@ export interface ProductionPlan {
slaveList?: PlanLine[]
/** 部门名称(单据视图) */
deptName?: string
/** 操作员/业务人员(单据视图表头) */
operatorName?: string
/** 审核日期 */
approveDate?: string
/** 物料清单BOM运算结果详情页只读 */
mbomList?: MbomLine[]
/** 补料清单(详情页只读) */

View File

@@ -67,6 +67,9 @@ export interface EbomLine {
delFlag?: string
/** 前端临时字段 */
_isNew?: boolean
/** 扩展属性(后端可能返回 attr1/attr2 等) */
attr1?: string
attr2?: string
}
/** 查询参数 */

View File

@@ -10,7 +10,7 @@ const whiteList = ['/login', '/register']
const DEV_SKIP_AUTH = import.meta.env.DEV && !import.meta.env.VITE_REQUIRE_AUTH
// 路由守卫
router.beforeEach(async (to, from, next) => {
router.beforeEach(async (to, _from, next) => {
// 设置页面标题
document.title = to.meta.title ? `${to.meta.title} - ERP系统` : 'ERP系统'

View File

@@ -432,6 +432,7 @@ async function handleUpdate(row?: MdItem) {
resetForm()
await getTreeselect()
const itemId = row?.itemId || ids.value[0]
if (!itemId) return
const res = await getMdItem(itemId)
Object.assign(form, res.data)
optType.value = 'edit'

View File

@@ -218,6 +218,7 @@ function handleAdd() {
async function handleUpdate(row?: UnitMeasure) {
resetForm()
const measureId = row?.measureId || ids.value[0]
if (!measureId) return
const res = await getUnitMeasure(measureId)
Object.assign(form, res.data)
dialogTitle.value = '修改计量单位'

View File

@@ -209,6 +209,7 @@ function handleAdd() {
async function handleUpdate(row?: Workshop) {
resetForm()
const workshopId = row?.workshopId || ids.value[0]
if (!workshopId) return
const res = await getWorkshop(workshopId)
Object.assign(form, res.data)
dialogTitle.value = '修改车间'

View File

@@ -230,6 +230,7 @@ async function handleUpdate(row?: Workstation) {
resetForm()
await getWorkshops()
const workstationId = row?.workstationId || ids.value[0]
if (!workstationId) return
const res = await getWorkstation(workstationId)
Object.assign(form, res.data)
dialogTitle.value = '修改工作站'

View File

@@ -41,7 +41,7 @@
<el-tag :type="getStatusType(form.status)" size="small">{{ getStatusLabel(form.status) }}</el-tag>
</el-descriptions-item>
<el-descriptions-item label="业务类型">{{ getBusinessTypeLabel(form.businessType) }}</el-descriptions-item>
<el-descriptions-item label="供应方式">{{ getSupplyTypeLabel(form.supplyType) }}</el-descriptions-item>
<el-descriptions-item label="供应方式">{{ getSupplyTypeLabel(form.supplyType ?? '') }}</el-descriptions-item>
<el-descriptions-item label="计划单号">
<el-link v-if="form.planId" type="primary" @click="goPlan(form.planId)">{{ form.planCode }}</el-link>
<span v-else>{{ form.planCode || '-' }}</span>
@@ -52,7 +52,7 @@
<el-descriptions-item label="主计量">{{ form.unitName || '-' }}</el-descriptions-item>
<el-descriptions-item label="生产数量">{{ formatNumber(form.quantity) }}</el-descriptions-item>
<el-descriptions-item label="下发车间">{{ form.workshopName || '-' }}</el-descriptions-item>
<el-descriptions-item label="下发状态">{{ getIssueStatusLabel(form.issueStatus) }}</el-descriptions-item>
<el-descriptions-item label="下发状态">{{ getIssueStatusLabel(form.issueStatus ?? '') }}</el-descriptions-item>
<el-descriptions-item label="审核人">{{ form.approverName || '-' }}</el-descriptions-item>
<el-descriptions-item label="审核日期">{{ form.approveDate || '-' }}</el-descriptions-item>
<el-descriptions-item label="备注" :span="3">{{ form.remark || '-' }}</el-descriptions-item>

View File

@@ -237,11 +237,11 @@ function handleAdd() {
ElMessage.info('新增零部件订单功能开发中')
}
function handleView(row: PartsOrder) {
function handleView(_row: PartsOrder) {
ElMessage.info('查看零部件订单详情')
}
function handleProgress(row: PartsOrder) {
function handleProgress(_row: PartsOrder) {
ElMessage.info('查看生产进度')
}

View File

@@ -652,7 +652,7 @@
import { ref, reactive, computed, onMounted, watch, nextTick } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Check, Finished, Upload, Plus, Edit, ArrowLeft, ArrowRight, View } from '@element-plus/icons-vue'
import { Check, Finished, Upload, Plus, Edit, ArrowLeft, ArrowRight } from '@element-plus/icons-vue'
import {
getProductionPlanDetail,
getProductionPlanList,
@@ -1166,7 +1166,7 @@ async function handleConfirmImport() {
firstOrder = detail
formData.salesOrderId = detail.orderId
formData.salesOrderCode = detail.orderCode
formData.salesUserName = detail.userName ?? detail.salesmanName ?? detail.salesUserName ?? ''
formData.salesUserName = detail.userName ?? detail.salesmanName ?? ''
formData.deliveryDate = detail.deliveryDate || ''
}
if (detail.lines && detail.lines.length > 0) {
@@ -1353,7 +1353,7 @@ async function handleSave() {
if (isAdd.value) {
const res = await createProductionPlan(formData)
ElMessage.success('保存成功')
const planId = res?.planId ?? res?.data?.planId
const planId = res?.planId
if (planId != null) {
formData.planId = planId
router.replace(`/production/plan-order/edit/${planId}`)

View File

@@ -357,8 +357,7 @@ import {
BUSINESS_STATUS_OPTIONS,
type ProductionPlan,
type PlanDetailView,
type PlanQuery,
type MbomLine
type PlanQuery
} from '@/api/productionPlan'
const router = useRouter()

View File

@@ -291,7 +291,7 @@
</template>
</el-table-column>
<el-table-column v-if="isEditMode" label="操作" width="100" align="center" fixed="right">
<template #default="{ row, $index }">
<template #default="{ $index }">
<el-button type="primary" link size="small" @click="handleCopyLine($index)">复制</el-button>
<el-popconfirm title="确认删除该行?" @confirm="handleDeleteLine($index)">
<template #reference>
@@ -355,7 +355,6 @@
<!-- 层级表格父行=生产计划子行=物料明细 -->
<el-table
ref="importTableRef"
v-loading="importLoading"
:data="importPlanList"
stripe
@@ -524,7 +523,6 @@ const showImportDialog = ref(false)
const importLoading = ref(false)
const importPlanList = ref<(ImportPlanRow & { rowKey: string })[]>([])
const expandedRowKeys = ref<string[]>([])
const importTableRef = ref()
const selectedImportRows = ref<ImportPlanRow[]>([])
/** 子行选择key=parentRowKey, value=选中的子行列表 */
const childSelectionMap = ref<Record<string, ImportPlanMaterial[]>>({})

View File

@@ -634,7 +634,7 @@ function handleExport() {
async function confirmExport() {
exportLoading.value = true
try {
const blob = await exportPurchasePlan(queryParams)
const blob = (await exportPurchasePlan(queryParams)).data
const url = window.URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url

View File

@@ -190,8 +190,8 @@ function formatNumber(val: number | undefined): string {
function handleDateChange(val: string[] | null) {
if (val && val.length === 2) {
queryParams.beginDate = val[0]
queryParams.endDate = val[1]
queryParams.beginDate = val[0] ?? ''
queryParams.endDate = val[1] ?? ''
} else {
queryParams.beginDate = ''
queryParams.endDate = ''

View File

@@ -170,8 +170,8 @@ function formatNumber(val: number | undefined): string {
function handleDateChange(val: string[] | null) {
if (val && val.length === 2) {
queryParams.beginDate = val[0]
queryParams.endDate = val[1]
queryParams.beginDate = val[0] ?? ''
queryParams.endDate = val[1] ?? ''
} else {
queryParams.beginDate = ''
queryParams.endDate = ''

View File

@@ -728,7 +728,7 @@ async function handleQuickIssue() {
if (!formData.workorderId) return
try {
await ElMessageBox.confirm('是否根据BOM物料自动创建领料单', '一键领料', { type: 'info' })
const issueId = await quickIssue(formData.workorderId)
await quickIssue(formData.workorderId)
ElMessage.success('领料单创建成功')
await loadIssueList()
} catch (error: any) {

View File

@@ -722,6 +722,7 @@ function handleSelectItem(selected: MdItem) {
const idx = editingLineIndex.value
if (idx < 0 || !form.lines) return
const row = form.lines[idx]
if (!row) return
row.itemId = selected.itemId ?? 0
row.itemCode = selected.itemCode ?? ''
row.itemName = selected.itemName ?? ''

View File

@@ -182,8 +182,7 @@ import {
unapprovePurchaseOrder,
STATUS_MAP,
BUSINESS_STATUS_MAP,
type PurchaseOrder,
type PurchaseOrderQuery
type PurchaseOrder
} from '@/api/purchaseOrder'
const router = useRouter()

View File

@@ -481,7 +481,6 @@ const levelOptions = VENDOR_LEVEL_OPTIONS
const importDialogVisible = ref(false)
const importUpdateSupport = ref(false)
const importLoading = ref(false)
const uploadRef = ref()
const importFile = ref<File | null>(null)
// ============ 方法 ============
@@ -598,7 +597,7 @@ async function handleEdit(row: Supplier) {
/** 修改按钮(工具栏) */
async function handleUpdate() {
if (selectedRows.value.length !== 1) return
await handleEdit(selectedRows.value[0])
await handleEdit(selectedRows.value[0]!)
}
/** 删除单个 */

View File

@@ -407,7 +407,6 @@ const isReadonly = computed(() => mode.value === 'view' || form.status === 'APPR
const collapsed = ref(false)
const saveLoading = ref(false)
const formRef = ref()
const form = reactive<any>({
bomId: undefined,

View File

@@ -115,7 +115,7 @@ const handleSearch = () => { pagination.page = 1; loadData() }
const handleReset = () => { searchForm.code = ''; searchForm.customerName = ''; searchForm.status = ''; handleSearch() }
const handleAdd = () => router.push('/sales/deliver/new')
const handleView = (row: Deliver) => ElMessage.info(`查看发货单: ${row.code}`)
const handleDelete = async (row: Deliver) => { await deleteDeliver(row.id); ElMessage.success('删除成功'); loadData() }
const handleDelete = async (row: Deliver) => { await deleteDeliver(row.id!); ElMessage.success('删除成功'); loadData() }
const handleExport = () => ElMessage.info('导出功能开发中')
onMounted(() => loadData())

View File

@@ -113,7 +113,7 @@ const loadData = async () => {
const handleSearch = () => { pagination.page = 1; loadData() }
const handleReset = () => { searchForm.code = ''; searchForm.customerName = ''; searchForm.status = ''; handleSearch() }
const handleAdd = () => router.push('/sales/invoice/new')
const handleDelete = async (row: Invoice) => { await deleteInvoice(row.id); ElMessage.success('删除成功'); loadData() }
const handleDelete = async (row: Invoice) => { await deleteInvoice(row.id!); ElMessage.success('删除成功'); loadData() }
const handleExport = () => ElMessage.info('导出功能开发中')
onMounted(() => loadData())

View File

@@ -107,7 +107,7 @@ const loadData = async () => {
const handleSearch = () => { pagination.page = 1; loadData() }
const handleReset = () => { searchForm.code = ''; searchForm.customerName = ''; searchForm.status = ''; handleSearch() }
const handleAdd = () => router.push('/sales/saleback/new')
const handleDelete = async (row: Saleback) => { await deleteSaleback(row.id); ElMessage.success('删除成功'); loadData() }
const handleDelete = async (row: Saleback) => { await deleteSaleback(row.id!); ElMessage.success('删除成功'); loadData() }
const handleExport = () => ElMessage.info('导出功能开发中')
onMounted(() => loadData())

View File

@@ -208,6 +208,7 @@ function handleAdd() {
async function handleUpdate(row?: Post) {
resetForm()
const postId = row?.postId || ids.value[0]
if (!postId) return
const res = await getPost(postId)
Object.assign(form, res.data)
dialogTitle.value = '修改岗位'

View File

@@ -246,6 +246,7 @@ function handleAdd() {
async function handleUpdate(row?: Role) {
resetForm()
const roleId = row?.roleId || ids.value[0]
if (!roleId) return
const res = await getRole(roleId)
Object.assign(form, res.data)
dialogTitle.value = '修改角色'

View File

@@ -242,7 +242,7 @@
</template>
</el-table-column>
<el-table-column label="操作" width="120" align="center" v-if="!isView && formData.status === 'PREPARE'">
<template #default="{ row, $index }">
<template #default="{ $index }">
<el-button type="primary" link @click="handleEditDetail($index)">明细</el-button>
<el-popconfirm title="确认删除此行?" @confirm="handleDeleteLine($index)">
<template #reference>
@@ -418,7 +418,6 @@
<el-button @click="workorderSearch.workorderCode = ''; workorderSearch.workorderName = ''; workorderSearch.productName = ''; loadWorkorders()">重置</el-button>
</div>
<el-table
ref="workorderTableRef"
v-loading="workorderLoading"
:data="workorderList"
stripe
@@ -465,7 +464,6 @@
<el-button @click="itemSearch.itemCode = ''; itemSearch.itemName = ''; loadItems()">重置</el-button>
</div>
<el-table
ref="itemTableRef"
v-loading="itemLoading"
:data="itemList"
stripe
@@ -507,7 +505,6 @@
<el-button @click="clientSearch.clientCode = ''; clientSearch.clientName = ''; loadClients()">重置</el-button>
</div>
<el-table
ref="clientTableRef"
v-loading="clientLoading"
:data="clientList"
stripe
@@ -548,7 +545,6 @@
<el-button @click="workstationSearch.workstationCode = ''; workstationSearch.workstationName = ''; loadWorkstations()">重置</el-button>
</div>
<el-table
ref="workstationTableRef"
v-loading="workstationLoading"
:data="workstationList"
stripe
@@ -707,7 +703,6 @@ const workorderSearch = reactive({ workorderCode: '', workorderName: '', product
const workorderList = ref<any[]>([])
const workorderLoading = ref(false)
const selectedWorkorder = ref<any>(null)
const workorderTableRef = ref()
async function loadWorkorders() {
workorderLoading.value = true
@@ -752,7 +747,6 @@ const itemSearch = reactive({ itemCode: '', itemName: '' })
const itemList = ref<any[]>([])
const itemLoading = ref(false)
const selectedItem = ref<any>(null)
const itemTableRef = ref()
async function loadItems() {
itemLoading.value = true
@@ -779,6 +773,7 @@ function confirmItemSelect() {
const idx = itemSelectTargetIndex.value
if (idx >= 0 && idx < lineList.value.length) {
const line = lineList.value[idx]
if (!line) return
line.itemId = row.itemId
line.itemCode = row.itemCode
line.itemName = row.itemName
@@ -804,7 +799,6 @@ const clientSearch = reactive({ clientCode: '', clientName: '' })
const clientList = ref<any[]>([])
const clientLoading = ref(false)
const selectedClient = ref<any>(null)
const clientTableRef = ref()
async function loadClients() {
clientLoading.value = true
@@ -850,7 +844,6 @@ const workstationSearch = reactive({ workstationCode: '', workstationName: '' })
const workstationList = ref<any[]>([])
const workstationLoading = ref(false)
const selectedWorkstation = ref<any>(null)
const workstationTableRef = ref()
async function loadWorkstations() {
workstationLoading.value = true
@@ -1024,6 +1017,7 @@ function handleEditDetail(lineIndex: number) {
async function handleDeleteLine(lineIndex: number) {
const line = lineList.value[lineIndex]
if (!line) return
try {
// 如果已保存到后端,调用删除接口
if (line.lineId) {
@@ -1094,6 +1088,7 @@ function handleAddDetail() {
async function handleDeleteDetail(detailIndex: number) {
const allDetails = currentDetailList.value
const detail = allDetails[detailIndex]
if (!detail) return
try {
if (detail.detailId) {
await deleteIssueDetail(detail.detailId)

View File

@@ -296,6 +296,7 @@ function handleEditSelected() {
return
}
const row = selectedRows.value[0]
if (!row) return
if (row.status !== 'PREPARE') {
ElMessage.warning('只能修改草稿状态的单据')
return

View File

@@ -14,40 +14,40 @@ export default defineConfig({
strictPort: false, // 端口被占用时自动尝试下一个可用端口
proxy: {
'/api': {
target: 'http://localhost:8080',
target: 'http://118.31.75.148:8090',
changeOrigin: true
},
'/erp': {
target: 'http://localhost:8080',
target: 'http://118.31.75.148:8090',
changeOrigin: true
},
'/mes': {
target: 'http://localhost:8080',
target: 'http://118.31.75.148:8090',
changeOrigin: true
},
'/system': {
target: 'http://localhost:8080',
target: 'http://118.31.75.148:8090',
changeOrigin: true
},
// 登录相关接口代理
'/login': {
target: 'http://localhost:8080',
target: 'http://118.31.75.148:8090',
changeOrigin: true
},
'/logout': {
target: 'http://localhost:8080',
target: 'http://118.31.75.148:8090',
changeOrigin: true
},
'/captchaImage': {
target: 'http://localhost:8080',
target: 'http://118.31.75.148:8090',
changeOrigin: true
},
'/getInfo': {
target: 'http://localhost:8080',
target: 'http://118.31.75.148:8090',
changeOrigin: true
},
'/register': {
target: 'http://localhost:8080',
target: 'http://118.31.75.148:8090',
changeOrigin: true
}
}