Merge remote-tracking branch 'origin/main'

main
liutao 1 day ago
commit d29171e1d5

@ -25,6 +25,7 @@ export interface DvRepairVO {
replacementParts?: string // 更换配件
repairContent?: string // 维修内容
repairedImages?: string // 维修后图片,逗号分隔
repairReporter?: string // 报修人员
acceptedBy: string // 维修人员
confirmBy: string // 验收人员
faultLevel?: string // 故障等级

@ -17,6 +17,7 @@ export interface MoldRepairVO {
finishDate: Date
confirmDate: Date
repairResult: string
repairReporter?: string // 报修人员
acceptedBy: string
confirmBy: string
status: string

@ -48,5 +48,10 @@ export const TaskManagementApi = {
exportTaskManagement: async (params: any) => {
return await request.download({ url: `/mes/mold-task-management/export-excel`, params })
},
updateTaskManagementEnabled: async (id: number | string, enabled: string) => {
const data = { id, enabled }
return await request.put({ url: `/mes/mold-task-management/update-enabled`, data })
}
}

@ -54,6 +54,10 @@ export const TicketManagementApi = {
return await request.put({ url: `/mes/mold-ticket-results/batchUpdate`, data })
},
exportTicketManagement: async (params: any) => {
return await request.download({ url: `/mes/mold-ticket-management/export-excel`, params })
},
getInspectionByMoldId: async (params: { moldId: number; startTime?: string; endTime?: string }) => {
return await request.get({ url: `/mes/mold-ticket-management/getInspectionByMoldId`, params })
},

@ -2236,6 +2236,7 @@ export default {
machineryTypeId: 'Device Type',
device: 'Device',
component: 'Key Component',
repairReporter: 'Repair Reporter',
acceptedBy: 'Repairer',
confirmBy: 'Inspector',
faultLevel: 'Failure Level',
@ -2284,6 +2285,7 @@ export default {
placeholderRepairCode: 'Please input repair order no',
placeholderRepairName: 'Please input repair order name',
placeholderMachineryName: 'Please input device name',
placeholderRepairReporter: 'Please select repair reporter',
placeholderAcceptedBy: 'Please input repairer',
placeholderConfirmBy: 'Please input inspector',
placeholderStatus: 'Please select order status',
@ -3617,6 +3619,7 @@ export default {
moldCode: 'Mold Code',
moldName: 'Mold Name',
repairUser: 'Repair User',
repairReporter: 'Repair Reporter',
confirmUser: 'Acceptance User',
requireDate: 'Request Date',
finishDate: 'Finish Date',
@ -3660,6 +3663,7 @@ export default {
placeholderMold: 'Please select mold',
placeholderAcceptUser: 'Please select repair user',
placeholderConfirmUser: 'Please select acceptance user',
placeholderRepairReporter: 'Please select repair reporter',
placeholderRequireDate: 'Select request date',
placeholderFinishDate: 'Select finish date',
placeholderConfirmDate: 'Select acceptance date',
@ -3828,6 +3832,7 @@ export default {
operatorName: 'Operator',
taskTime: 'Job Time',
taskEndTime: 'Planned End Time',
taskTimeRange: 'Job Time',
createTime: 'Create Time',
index: 'Index',
remark: 'Remark',
@ -3837,10 +3842,16 @@ export default {
placeholderPlanType: 'Please select type',
placeholderJobStatus: 'Please select job status',
placeholderJobResult: 'Please select result',
placeholderOperatorName: 'Please select operator',
placeholderTaskTime: 'Please select job start time',
placeholderTaskEndTime: 'Please select job end time',
query: 'Query',
reset: 'Reset',
cancelConfirm: 'Confirm cancel selected tasks?',
cancelSuccess: 'Cancel task successful',
cancelOnlyUnworkedTip: 'Only unworked tickets can be canceled',
export: 'Export',
exportFilename: 'Mold Work Order Inquiry.xls',
inspectResultTitlePrefix: 'Inspection Result-',
inspectResultTitle: 'Inspection Result'
},

@ -2198,6 +2198,7 @@ export default {
cancelReason: '取消原因',
cancelConfirm: '确认取消选中的任务吗?',
cancelSuccess: '取消任务成功',
cancelOnlyUnworkedTip: '只有未作业状态的工单才能取消任务',
cancelFail: '取消任务失败',
cancelOnlyUnworkedTip: '只有未作业状态的工单才能取消任务',
selectAllDecisionError: '请先为所有待检测记录选择通过或不通过',
@ -2229,6 +2230,7 @@ export default {
machineryTypeId: '设备类型',
device: '设备',
component: '关键件',
repairReporter: '报修人员',
acceptedBy: '维修人员',
confirmBy: '验收人员',
faultLevel: '故障等级',
@ -2277,6 +2279,7 @@ export default {
placeholderRepairCode: '请输入维修单编号',
placeholderRepairName: '请输入维修单名称',
placeholderMachineryName: '请输入设备名称',
placeholderRepairReporter: '请选择报修人员',
placeholderAcceptedBy: '请输入维修人员',
placeholderConfirmBy: '请输入验收人员',
placeholderStatus: '请选择单据状态',
@ -3087,6 +3090,7 @@ export default {
moldCode: '模具编码',
moldName: '模具名称',
repairUser: '维修人员',
repairReporter: '报修人员',
confirmUser: '验收人员',
requireDate: '报修日期',
finishDate: '完成日期',
@ -3130,6 +3134,7 @@ export default {
placeholderMold: '请选择模具',
placeholderAcceptUser: '请选择维修人员',
placeholderConfirmUser: '请选择验收人员',
placeholderRepairReporter: '请选择报修人员',
placeholderRequireDate: '选择报修日期',
placeholderFinishDate: '选择完成日期',
placeholderConfirmDate: '选择验收日期',
@ -3298,6 +3303,7 @@ export default {
operatorName: '作业人',
taskTime: '作业时间',
taskEndTime: '计划结束作业时间',
taskTimeRange: '作业时间',
createTime: '创建时间',
index: '序号',
remark: '备注',
@ -3307,10 +3313,16 @@ export default {
placeholderPlanType: '请选择类型',
placeholderJobStatus: '请选择作业状态',
placeholderJobResult: '请选择结果',
placeholderOperatorName: '请选择作业人',
placeholderTaskTime: '请选择作业开始时间',
placeholderTaskEndTime: '请选择作业结束时间',
query: '查询',
reset: '重置',
cancelConfirm: '确认取消选中的任务吗?',
cancelSuccess: '取消任务成功',
cancelOnlyUnworkedTip: '只有未作业状态的工单才能取消任务',
export: '导出',
exportFilename: '模具工单查询.xls',
inspectResultTitlePrefix: '检验结果-',
inspectResultTitle: '检验结果'
},

@ -245,6 +245,16 @@
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item :label="t('MoldManagement.MoldRepair.repairReporter')" prop="repairReporter">
<el-select
v-model="repairFormData.repairReporter" filterable clearable
:placeholder="t('MoldManagement.MoldRepair.placeholderRepairReporter')"
class="!w-full">
<el-option v-for="item in users" :key="String(item.id)" :label="item.nickname" :value="String(item.id)" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item :label="t('MoldManagement.MoldRepair.repairUser')" prop="acceptedBy">
<el-select
@ -493,6 +503,7 @@ import { getSimpleUserList, type UserVO } from '@/api/system/user'
import { DICT_TYPE, getStrDictOptions } from '@/utils/dict'
import { isHexColor } from '@/utils/color'
import { dateFormatter } from '@/utils/formatTime'
import { useUserStore } from '@/store/modules/user'
defineOptions({ name: 'MoldMaintainView' })
@ -508,6 +519,7 @@ const emit = defineEmits<{
const { t } = useI18n()
const message = useMessage()
const userStore = useUserStore()
const submitLoading = ref(false)
const maintainFormRef = ref()
@ -538,6 +550,7 @@ const formModel = computed(() => ({
projectForm: taskFormData.projectForm,
repairName: repairFormData.repairName,
requireDate: repairFormData.requireDate,
repairReporter: repairFormData.repairReporter,
faultLevel: repairFormData.faultLevel,
shutdown: repairFormData.shutdown,
faultPhenomenon: repairFormData.faultPhenomenon,
@ -562,6 +575,7 @@ const repairFormData = reactive({
repairCode: undefined as string | undefined,
repairName: undefined as string | undefined,
requireDate: undefined as number | string | undefined,
repairReporter: undefined as string | undefined,
acceptedBy: undefined as string | undefined,
confirmBy: undefined as string | undefined,
faultLevel: undefined as string | undefined,
@ -879,6 +893,12 @@ const selectMaintainType = async (type: number) => {
if (type === 3 && !repairFormData.requireDate) {
repairFormData.requireDate = Date.now()
}
if (type === 3 && !repairFormData.repairReporter) {
const currentUserId = userStore.getUser?.id
if (currentUserId !== undefined && currentUserId !== null && Number(currentUserId) > 0) {
repairFormData.repairReporter = String(currentUserId)
}
}
handleMaintainTypeChange()
//
await initOptions()
@ -933,6 +953,7 @@ const submitForm = async () => {
requireDate: repairFormData.requireDate,
repairResult: '',
repairStatus: '',
repairReporter: normalizeUserId(repairFormData.repairReporter),
acceptedBy: normalizeUserId(repairFormData.acceptedBy),
confirmBy: normalizeUserId(repairFormData.confirmBy),
faultLevel: repairFormData.faultLevel,
@ -951,6 +972,7 @@ const submitForm = async () => {
repairFormData.repairCode = undefined
repairFormData.repairName = undefined
repairFormData.requireDate = Date.now()
repairFormData.repairReporter = undefined
repairFormData.acceptedBy = undefined
repairFormData.confirmBy = undefined
repairFormData.faultLevel = undefined
@ -995,6 +1017,15 @@ const open = async () => {
repairFormData.requireDate = Date.now()
replaceNetFormData.pressureNetTime = getCurrentDateTime()
await initOptions()
if (!userStore.getIsSetUser) {
try {
await userStore.setUserInfoAction()
} catch (e) {}
}
const currentUserId = userStore.getUser?.id
if (currentUserId !== undefined && currentUserId !== null && Number(currentUserId) > 0) {
repairFormData.repairReporter = String(currentUserId)
}
}
defineExpose({ open })

@ -182,6 +182,9 @@
<div class="device-ledger-history-item-row"><span
class="device-ledger-history-item-label">{{ t('MoldManagement.MoldBrandDetail.requireDate') }}</span><span
class="device-ledger-history-item-value">{{ formatHistoryTime(row.requireDate) }}</span></div>
<div class="device-ledger-history-item-row"><span
class="device-ledger-history-item-label">{{ t('MoldManagement.MoldRepair.repairReporter') }}</span><span
class="device-ledger-history-item-value">{{ row.repairReporterName ?? row.repairReporter ?? '-' }}</span></div>
<div class="device-ledger-history-item-row"><span
class="device-ledger-history-item-label">{{ t('MoldManagement.MoldRepair.repairUser') }}</span><span
class="device-ledger-history-item-value">{{ row.acceptedByName ?? row.acceptedName ?? row.acceptedBy ?? '-' }}</span></div>

@ -51,7 +51,11 @@
</el-table-column>
<el-table-column label="调出库区" min-width="125">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.fromAreaId`" :rules="formRules.fromAreaId" class="mb-0px!">
<el-form-item
:prop="`${$index}.fromAreaId`"
:rules="formRules.fromAreaId"
class="mb-0px!"
>
<el-select
v-model="row.fromAreaId"
clearable
@ -106,7 +110,12 @@
placeholder="请选择调入仓库"
@change="onChangeToWarehouse(row)"
>
<el-option v-for="item in getToWarehouseOptions(row)" :key="item.id" :label="item.name" :value="item.id" />
<el-option
v-for="item in getToWarehouseOptions(row)"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
</template>
@ -166,7 +175,12 @@
<el-button @click="handleAdd" round>+ 添加调拨产品</el-button>
</el-row>
<Dialog :title="productSelectTitle" v-model="productDialogVisible" width="900px" class="stock-move-product-dialog">
<Dialog
:title="productSelectTitle"
v-model="productDialogVisible"
width="900px"
class="stock-move-product-dialog"
>
<el-form :model="productQueryParams" :inline="true" class="-mb-15px">
<el-form-item :label="t('ErpStock.Item.code')">
<el-input
@ -193,20 +207,29 @@
<el-table
v-loading="productDialogLoading"
:data="productDialogList"
row-key="id"
:row-key="getProductOptionRowKey"
:stripe="true"
:show-overflow-tooltip="true"
@row-click="handleProductDialogRowClick"
>
<el-table-column width="55" align="center">
<template #default="{ row }">
<el-radio v-model="selectedProductId" :label="row.id">&nbsp;</el-radio>
<el-radio v-model="selectedProductId" :label="getProductOptionId(row)">&nbsp;</el-radio>
</template>
</el-table-column>
<el-table-column :label="t('ErpStock.Item.code')" prop="barCode" min-width="160" />
<el-table-column :label="productColumnLabel" prop="name" min-width="160" />
<el-table-column :label="t('ErpStock.Item.spec')" prop="standard" min-width="120" />
<el-table-column :label="t('ErpStock.Item.category')" prop="subCategoryName" min-width="120" />
<el-table-column
:label="t('ErpStock.Item.category')"
prop="subCategoryName"
min-width="120"
/>
<el-table-column
:label="t('ErpStock.Stock.stockDisplay')"
prop="stockDisplay"
min-width="120"
/>
<el-table-column :label="t('ErpStock.Item.unit')" prop="unitName" min-width="80" />
</el-table>
<div class="product-dialog-pagination">
@ -229,6 +252,7 @@
import { ProductApi } from '@/api/erp/product/product'
import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse'
import { StockMoveApi } from '@/api/erp/stock/move'
import { StockApi } from '@/api/erp/stock/stock'
import { erpCountInputFormatter, getSumValue } from '@/utils'
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
@ -245,17 +269,31 @@ const formData = ref<any[]>([])
const sameAreaMessage = '调出库区和调入库区不能相同'
const formRules = reactive({
inId: [{ required: true, message: '调度编号不能为空', trigger: 'submit' }],
fromWarehouseId: [{ required: true, message: t('ErpStock.Move.item.validatorFromWarehouseRequired'), trigger: 'submit' }],
fromWarehouseId: [
{
required: true,
message: t('ErpStock.Move.item.validatorFromWarehouseRequired'),
trigger: 'submit'
}
],
fromAreaId: [
{ required: true, message: t('ErpStock.Item.validatorAreaRequired'), trigger: 'submit' },
{ validator: validateDifferentArea, trigger: ['change', 'submit'] }
],
toWarehouseId: [{ required: true, message: t('ErpStock.Move.item.validatorToWarehouseRequired'), trigger: 'submit' }],
toWarehouseId: [
{
required: true,
message: t('ErpStock.Move.item.validatorToWarehouseRequired'),
trigger: 'submit'
}
],
toAreaId: [
{ required: true, message: t('ErpStock.Item.validatorAreaRequired'), trigger: 'submit' },
{ validator: validateDifferentArea, trigger: ['change', 'submit'] }
],
productId: [{ required: true, message: t('ErpStock.Item.validatorProductRequired'), trigger: 'submit' }],
productId: [
{ required: true, message: t('ErpStock.Item.validatorProductRequired'), trigger: 'submit' }
],
count: [
{ required: true, message: t('ErpStock.Item.validatorCountRequired'), trigger: 'submit' },
{ validator: validateStockMoveCount, trigger: ['change', 'submit'] }
@ -269,11 +307,12 @@ const productDialogVisible = ref(false)
const productDialogLoading = ref(false)
const productDialogList = ref<any[]>([])
const productDialogTotal = ref(0)
const selectedProductId = ref<number>()
const selectedProductId = ref<number | string>()
const productQueryParams = reactive({
pageNo: 1,
pageSize: 10,
categoryType: undefined as number | undefined,
stockNotZero: true,
barCode: undefined as string | undefined,
name: undefined as string | undefined
})
@ -319,7 +358,9 @@ function getSummaries(param: SummaryMethodProps) {
return
}
if (column.property === 'count') {
sums[index] = erpCountInputFormatter(getSumValue(data.map((item) => Number(item[column.property]))))
sums[index] = erpCountInputFormatter(
getSumValue(data.map((item) => Number(item[column.property])))
)
} else {
sums[index] = ''
}
@ -359,7 +400,11 @@ function handleDelete(index) {
}
function isSameMoveArea(row) {
return row.fromAreaId !== undefined && row.toAreaId !== undefined && String(row.fromAreaId) === String(row.toAreaId)
return (
row.fromAreaId !== undefined &&
row.toAreaId !== undefined &&
String(row.fromAreaId) === String(row.toAreaId)
)
}
function validateDifferentArea(rule, _value, callback) {
@ -427,7 +472,9 @@ function warnIfSameArea(row) {
function validateAreaFields(row) {
const rowIndex = formData.value.indexOf(row)
if (rowIndex < 0) return
formRef.value?.validateField([`${rowIndex}.fromAreaId`, `${rowIndex}.toAreaId`]).catch(() => undefined)
formRef.value
?.validateField([`${rowIndex}.fromAreaId`, `${rowIndex}.toAreaId`])
.catch(() => undefined)
}
async function handleFromAreaChange(row) {
@ -491,8 +538,9 @@ async function getProductDialogList() {
productDialogLoading.value = true
try {
productQueryParams.categoryType = props.categoryType
const data = await ProductApi.getProductPage(productQueryParams)
productDialogList.value = data?.list || []
productQueryParams.stockNotZero = true
const data = await StockApi.getStockPage(productQueryParams)
productDialogList.value = normalizeStockProductOptions(data?.list || [])
productDialogTotal.value = data?.total || 0
} finally {
productDialogLoading.value = false
@ -505,12 +553,14 @@ function handleProductDialogQuery() {
}
function handleProductDialogRowClick(row: any) {
selectedProductId.value = row.id
selectedProductId.value = getProductOptionId(row)
}
async function confirmProductSelect() {
if (props.disabled) return
const product = productDialogList.value.find((item) => item.id === selectedProductId.value)
const product = productDialogList.value.find(
(item) => String(getProductOptionId(item)) === String(selectedProductId.value)
)
if (!product || !currentSelectRow.value) return
fillRowByProduct(currentSelectRow.value, product)
await loadProductStockList(currentSelectRow.value)
@ -518,11 +568,11 @@ async function confirmProductSelect() {
}
function fillRowByProduct(row, product) {
row.productId = product.id
row.productName = product.name
row.productUnitName = product.unitName
row.productId = getProductOptionId(product)
row.productName = product.name || product.productName
row.productUnitName = product.unitName || product.purchaseUnitName
row.purchaseUnitName = product.purchaseUnitName
row.unitName = product.unitName
row.unitName = product.unitName || product.purchaseUnitName
row.productBarCode = product.barCode
row.fromWarehouseId = undefined
row.fromAreaId = undefined
@ -564,6 +614,34 @@ async function loadOptions() {
}
}
function getProductOptionId(item) {
return item?.productId ?? item?.id
}
function getProductOptionRowKey(row) {
return [getProductOptionId(row), row.warehouseId, row.areaId, row.stockId || row.id]
.filter((item) => item !== undefined && item !== null && item !== '')
.join('-')
}
function normalizeStockProductOptions(list) {
const map = new Map()
;(list || []).forEach((item) => {
const productId = getProductOptionId(item)
if (!productId || map.has(String(productId))) return
map.set(String(productId), {
...item,
id: productId,
productId,
name: item.name || item.productName,
unitName: item.unitName || item.purchaseUnitName,
subCategoryName: item.subCategoryName || item.categoryName,
stockDisplay: item.stockDisplay || item.totalBaseCount || item.count || item.stockCount
})
})
return Array.from(map.values())
}
function normalizeProductStockList(data) {
if (Array.isArray(data)) return data
if (Array.isArray(data?.list)) return data.list
@ -597,7 +675,9 @@ async function fillProductStockAreaInfo(stockList) {
stockList
.filter((item) => Number(getStockWarehouseId(item)) === Number(warehouseId))
.forEach((item) => {
const area = areaList.find((areaItem) => Number(areaItem.id) === Number(getStockAreaId(item)))
const area = areaList.find(
(areaItem) => Number(areaItem.id) === Number(getStockAreaId(item))
)
if (!area) return
item.areaCode = area.areaCode
item.areaName = area.areaName
@ -624,7 +704,9 @@ function getFromWarehouseOptions(row) {
return appendOptionIfMissing(
Array.from(warehouseMap.values()),
row.fromWarehouseId,
row.fromWarehouseName ? { warehouseId: row.fromWarehouseId, warehouseName: row.fromWarehouseName } : undefined,
row.fromWarehouseName
? { warehouseId: row.fromWarehouseId, warehouseName: row.fromWarehouseName }
: undefined,
getStockWarehouseId
)
}
@ -668,9 +750,11 @@ function getToWarehouseOptions(row) {
}
function getToAreaOptions(row) {
const areaOptions = Array.isArray(row.toAreaList) && row.toAreaList.length > 0
? row.toAreaList
: warehouseList.value.find((item) => Number(item.id) === Number(row.toWarehouseId))?.areaList || []
const areaOptions =
Array.isArray(row.toAreaList) && row.toAreaList.length > 0
? row.toAreaList
: warehouseList.value.find((item) => Number(item.id) === Number(row.toWarehouseId))
?.areaList || []
return appendOptionIfMissing(
areaOptions,
row.toAreaId,

@ -345,23 +345,21 @@ const buildTreeFromApi = (orgs: ApiTreeOrg[]): DeviceTreeNode[] => {
return Array.isArray(orgTree) ? orgTree.map(toOrgNode) : []
}
const hasOrgClassInSubtree = (node: DeviceTreeNode, targetOrgClass: string): boolean => {
const hasEquipmentInSubtree = (node: DeviceTreeNode): boolean => {
const children = Array.isArray(node?.children) ? node.children : []
for (const child of children) {
if (child?.orgClass === targetOrgClass) return true
if (hasOrgClassInSubtree(child, targetOrgClass)) return true
if (child?.tag === 'equipment') return true
if (hasEquipmentInSubtree(child)) return true
}
return false
}
const buildDefaultExpandedKeys = (nodes: DeviceTreeNode[], stopOrgClass: string): string[] => {
const buildDefaultExpandedKeys = (nodes: DeviceTreeNode[]): string[] => {
const keys: string[] = []
const walk = (list: DeviceTreeNode[]) => {
for (const node of list) {
if (node?.type === 'device' && node?.orgClass && node.orgClass !== stopOrgClass) {
if (hasOrgClassInSubtree(node, stopOrgClass)) {
keys.push(node.id)
}
if (node?.type === 'device' && node?.tag !== 'equipment' && hasEquipmentInSubtree(node)) {
keys.push(node.id)
}
const children = Array.isArray(node?.children) ? node.children : []
if (children.length) walk(children)
@ -388,7 +386,7 @@ const loadTree = async () => {
filterNoDeviceLine: 1
})
treeData.value = buildTreeFromApi(extractApiOrgs(res))
defaultExpandedKeys.value = buildDefaultExpandedKeys(treeData.value, 'pipeline')
defaultExpandedKeys.value = buildDefaultExpandedKeys(treeData.value)
await nextTick()
treeRef.value?.setExpandedKeys?.(defaultExpandedKeys.value)
if (keyword.value) {

@ -57,6 +57,20 @@
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item :label="t('EquipmentManagement.DvRepair.repairReporter')" prop="repairReporter">
<el-select
v-model="formData.repairReporter"
filterable
clearable
:placeholder="t('EquipmentManagement.DvRepair.placeholderRepairReporter')"
class="!w-full"
:disabled="isRepairMetaReadonly"
>
<el-option v-for="item in users" :key="String(item.id)" :label="item.nickname" :value="String(item.id)" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item :label="t('EquipmentManagement.DvRepair.acceptedBy')" prop="acceptedBy">
<el-select
@ -383,6 +397,7 @@ import { DeviceLedgerApi, DeviceLedgerVO } from '@/api/mes/deviceledger'
import { RepairItemsApi } from '@/api/mes/repairItems'
import { getSimpleUserList, UserVO } from '@/api/system/user'
import { DICT_TYPE, getStrDictOptions } from '@/utils/dict'
import { useUserStore } from '@/store/modules/user'
/** 设备维修记录 表单 */
defineOptions({ name: 'DvRepairForm' })
@ -409,6 +424,7 @@ interface DvRepairFormData extends Partial<DvRepairVO> {
const { t } = useI18n()
const message = useMessage()
const userStore = useUserStore()
const createDefaultFormData = (): DvRepairFormData => ({
id: undefined,
@ -436,6 +452,7 @@ const createDefaultFormData = (): DvRepairFormData => ({
replacementParts: undefined,
repairContent: undefined,
repairedImages: '',
repairReporter: undefined,
acceptedBy: undefined,
confirmBy: undefined,
faultLevel: undefined,
@ -855,6 +872,7 @@ const open = async (type: string, id?: number) => {
repairedImages: normalizeImageString(detail?.repairedImages),
acceptedBy: normalizeUserId(detail?.acceptedBy),
confirmBy: normalizeUserId(detail?.confirmBy),
repairReporter: normalizeUserId(detail?.repairReporter),
faultLevel: detail?.faultLevel === undefined || detail?.faultLevel === null ? undefined : String(detail?.faultLevel)
}
@ -889,6 +907,17 @@ const open = async (type: string, id?: number) => {
formLoading.value = false
}
} else {
if (formType.value === 'create') {
if (!userStore.getIsSetUser) {
try {
await userStore.setUserInfoAction()
} catch (e) {}
}
const currentUserId = userStore.getUser?.id
if (currentUserId !== undefined && currentUserId !== null && Number(currentUserId) > 0) {
formData.value.repairReporter = String(currentUserId)
}
}
await nextTick()
formRef.value?.clearValidate?.()
}
@ -921,6 +950,7 @@ const submitForm = async () => {
const data = { ...(formData.value as DvRepairFormData) } as DvRepairFormData & Record<string, any>
data.acceptedBy = normalizeUserId(data.acceptedBy)
data.confirmBy = normalizeUserId(data.confirmBy)
data.repairReporter = normalizeUserId(data.repairReporter)
data.faultLevel = data.faultLevel === undefined || data.faultLevel === null || String(data.faultLevel).trim() === '' ? undefined : String(data.faultLevel)
data.faultImages = normalizeImageString(data.faultImages)
data.repairedImages = normalizeImageString(data.repairedImages)

@ -174,6 +174,7 @@
prop="confirmDate"
:formatter="dateFormatter2"
width="110px" sortable />
<el-table-column :label="t('EquipmentManagement.DvRepair.repairReporter')" align="center" prop="repairReporter" minWidth="150px"/>
<el-table-column :label="t('EquipmentManagement.DvRepair.acceptedBy')" align="center" prop="acceptedBy" minWidth="150px"/>
<el-table-column :label="t('EquipmentManagement.DvRepair.confirmBy')" align="center" prop="confirmBy" minWidth="150px"/>
<!-- <el-table-column label="备注" align="center" prop="remark" /> -->

@ -8,9 +8,18 @@
</el-form-item>
<el-form-item :label="t('EnergyManagement.EnergyDeviceCheck.searchOrgLabel')" prop="orgId">
<el-select v-model="queryParams.orgId" filterable clearable :placeholder="t('EnergyManagement.EnergyDeviceCheck.searchOrgPlaceholder')" class="!w-240px">
<el-option v-for="opt in orgOptions" :key="String(opt.value)" :label="opt.label" :value="opt.value" />
</el-select>
<el-tree-select
v-model="queryParams.orgId"
:data="orgSelectTree"
:props="orgTreeSelectProps"
filterable
check-strictly
clearable
class="!w-240px"
:placeholder="t('EnergyManagement.EnergyDeviceCheck.searchOrgPlaceholder')"
:loading="analysisLoading"
:render-after-expand="false"
/>
</el-form-item>
<el-form-item :label="t('EnergyManagement.EnergyDeviceCheck.searchTimeRangeLabel')" prop="timeRange">
@ -93,7 +102,7 @@ v-if="getPointDetailsRows(scope.row).length" :data="getPointDetailsRows(scope.ro
<script setup lang="ts">
import download from '@/utils/download'
import { EnergyDeviceApi, EnergyDeviceDataRecordVO } from '@/api/mes/energydevice'
import { OrganizationApi, OrganizationVO } from '@/api/mes/organization'
import { OrganizationApi } from '@/api/mes/organization'
defineOptions({ name: 'EnergyDeviceCheckRecord' })
@ -118,7 +127,59 @@ const updatePlanTableMaxHeight = async () => {
const expandRowKeys = ref<Array<string | number>>([])
const selectedIds = ref<Array<number | string>>([])
const orgOptions = ref<{ label: string; value: string | number; raw?: OrganizationVO }[]>([])
const analysisLoading = ref(false)
type AnalysisOrgNode = {
id: number | string
name: string
orgClass?: string
parentId?: number | string | null
children?: AnalysisOrgNode[]
}
type OrgSelectNode = {
id: number | string
name: string
orgClass?: string
parentId?: number | string | null
children?: OrgSelectNode[]
}
const orgSelectTree = ref<OrgSelectNode[]>([])
const orgTreeSelectProps = {
label: 'name',
children: 'children',
value: 'id'
}
const normalizeAnalysisTree = (nodes: any[] = []): AnalysisOrgNode[] => {
return nodes.map((node) => ({
id: node?.id,
name: String(node?.name ?? ''),
orgClass: node?.orgClass ? String(node.orgClass) : undefined,
parentId: node?.parentId ?? undefined,
children: Array.isArray(node?.children) ? normalizeAnalysisTree(node.children) : undefined
}))
}
const buildOrgSelectTree = (nodes: AnalysisOrgNode[] = []): OrgSelectNode[] => {
return nodes.map((node) => ({
id: node.id,
name: node.name,
orgClass: node.orgClass,
parentId: node.parentId,
children: Array.isArray(node.children) ? buildOrgSelectTree(node.children) : undefined
}))
}
const extractAnalysisOrgs = (res: any): AnalysisOrgNode[] => {
if (Array.isArray(res)) return normalizeAnalysisTree(res)
if (Array.isArray(res?.data)) return normalizeAnalysisTree(res.data)
if (Array.isArray(res?.result)) return normalizeAnalysisTree(res.result)
if (Array.isArray(res?.list)) return normalizeAnalysisTree(res.list)
return []
}
const getDisabledTime = () => {
const all = Array.from({ length: 60 }, (_, i) => i)
@ -288,18 +349,26 @@ const handleExport = async () => {
}
}
const loadOrgOptions = async () => {
if (orgOptions.value.length) return
const data: any = await OrganizationApi.getOrganizationList({})
const rows = (Array.isArray(data) ? data : data?.list ?? data?.data ?? []) as OrganizationVO[]
orgOptions.value = rows
.filter((r) => r?.id !== undefined && r?.name)
.map((r) => ({ label: r.name, value: r.id, raw: r }))
const loadAnalysis = async () => {
if (orgSelectTree.value.length > 0) {
return
}
analysisLoading.value = true
try {
const res = await OrganizationApi.deviceParameterAnalysis({
showDevices: 0,
filterNoDeviceLine: 0
})
const analysisTree = extractAnalysisOrgs(res)
orgSelectTree.value = buildOrgSelectTree(analysisTree)
} finally {
analysisLoading.value = false
}
}
/** 初始化 **/
onMounted(async () => {
await loadOrgOptions()
await loadAnalysis()
await getList()
updatePlanTableMaxHeight()
window.addEventListener('resize', updatePlanTableMaxHeight)

@ -21,10 +21,24 @@
/>
</el-form-item>
<el-form-item :label="t('EnergyManagement.EnergyType.dialogUnitLabel')" prop="unit">
<el-input
v-model="formData.unit"
:placeholder="t('EnergyManagement.EnergyType.dialogUnitPlaceholder')"
/>
<el-select v-model="formData.unit" clearable
:placeholder="t('EnergyManagement.EnergyType.dialogUnitPlaceholder')" class="!w-full">
<el-option v-for="item in unitList" :key="item.id" :label="item.name" :value="item.name" />
<template #footer>
<div v-if="!isAddingUnit" class="px-10px py-6px">
<el-button text bg size="small" @click.stop="onAddUnit">
+ 新增单位
</el-button>
</div>
<div v-else class="px-10px py-6px">
<el-input v-model="unitInputName" size="small" placeholder="请输入单位名称" class="mb-6px" />
<div class="flex gap-6px">
<el-button type="primary" size="small" @click.stop="onConfirmAddUnit">确定</el-button>
<el-button size="small" @click.stop="clearAddUnit">取消</el-button>
</div>
</div>
</template>
</el-select>
</el-form-item>
<el-form-item :label="t('EnergyManagement.EnergyType.dialogIsEnableLabel')" prop="isEnable">
<el-radio-group v-model="formData.isEnable">
@ -57,6 +71,8 @@
<script setup lang="ts">
import {DICT_TYPE, getBoolDictOptions} from '@/utils/dict'
import { EnergyTypeApi, EnergyTypeVO } from '@/api/mes/energytype'
import { ProductUnitApi, ProductUnitVO } from '@/api/erp/product/unit'
import { CommonStatusEnum } from '@/utils/constants'
/** 能耗类型 表单 */
defineOptions({ name: 'EnergyTypeForm' })
@ -84,12 +100,58 @@ const formRules = reactive({
})
const formRef = ref() // Ref
//
const unitList = ref<ProductUnitVO[]>([])
const isAddingUnit = ref(false)
const unitInputName = ref('')
const onAddUnit = () => {
isAddingUnit.value = true
}
const onConfirmAddUnit = async () => {
if (!unitInputName.value.trim()) {
message.warning('请输入单位名称')
return
}
formLoading.value = true
try {
await ProductUnitApi.createProductUnit({
name: unitInputName.value.trim(),
status: CommonStatusEnum.ENABLE,
primaryFlag: 'Y'
} as ProductUnitVO)
//
const newList = await ProductUnitApi.getProductUnitSimpleList()
unitList.value = newList
const newUnit = newList.find((u: any) => u.name === unitInputName.value.trim())
if (newUnit) {
formData.value.unit = newUnit.name
}
clearAddUnit()
message.success('新增单位成功')
} finally {
formLoading.value = false
}
}
const clearAddUnit = () => {
unitInputName.value = ''
isAddingUnit.value = false
}
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
try {
unitList.value = await ProductUnitApi.getProductUnitSimpleList()
} catch {
unitList.value = []
}
//
if (id) {
formLoading.value = true

@ -19,13 +19,12 @@
@click="openCriticalComponentDialog" />
</el-form-item>
<el-form-item :label="t('MoldManagement.MoldOperate.productionLine')" prop="lineId" v-if="formData.operateType != null">
<el-input :model-value="displayLineName" readonly />
<el-input :model-value="displayLineName" disabled />
</el-form-item>
<!-- 上模手动选择模具 -->
<el-form-item
:label="t('MoldManagement.MoldOperate.mold')"
prop="moldId"
:required="String(formData.operateType) === '1'"
v-if="formData.operateType == 1"
>
<el-input
@ -37,7 +36,7 @@
</el-form-item>
<!-- 下模自动带出该设备的在机模具 -->
<el-form-item label="在机模具" v-if="formData.operateType == 2">
<el-input :model-value="currentDeviceMoldText" readonly />
<el-input :model-value="currentDeviceMoldText" disabled />
</el-form-item>
<el-form-item :label="t('MoldManagement.MoldOperate.operateTime')" prop="operateTime">
<el-date-picker
@ -215,26 +214,13 @@ const formData = ref<MoldOperateFormData>({
remark: undefined,
})
const validateMoldId = (_rule: any, value: any, callback: (error?: Error) => void) => {
if (String(formData.value.operateType) !== '1') {
callback()
return
}
const hasValue = value !== undefined && value !== null && value !== ''
if (!hasValue) {
callback(new Error(t('MoldManagement.MoldOperate.validatorMoldRequired')))
} else {
callback()
}
}
const formRules = reactive({
const formRules = computed(() => ({
operateType: [{ required: true, message: t('MoldManagement.MoldOperate.validatorOperateTypeRequired'), trigger: 'blur' }],
deviceId: [{ required: true, message: t('MoldManagement.MoldOperate.validatorDeviceRequired'), trigger: 'change' }],
moldId: [{ validator: validateMoldId, trigger: 'change' }],
moldId: [{ required: true, message: formType.value === 'create' ? '关联模具不能为空' : t('MoldManagement.MoldOperate.validatorMoldRequired'), trigger: 'change' }],
operateTime: [{ required: true, message: t('MoldManagement.MoldOperate.validatorOperateTimeRequired'), trigger: 'blur' }],
operatorId: [{ required: true, message: t('MoldManagement.MoldOperate.validatorOperatorRequired'), trigger: 'change' }],
})
}))
const formRef = ref() // Ref
/** 打开弹窗 */
@ -409,11 +395,13 @@ watch(
return
}
formData.value.deviceId = undefined as any
formData.value.lineId = undefined as any
formData.value.moldId = undefined as any
ids.value = []
moldIds.value = []
selectedDeviceRows.value = []
selectedMoldRows.value = []
displayTopCategory.value = ''
if (!val) {
return
}
@ -599,7 +587,9 @@ const handleDeviceSelectConfirm = async (payload: { ids: (number | string)[]; ro
} else {
selectedDeviceRows.value = []
formData.value.deviceId = undefined
formData.value.lineId = undefined
ids.value = []
displayTopCategory.value = ''
}
nextTick(() => {
formRef.value?.clearValidate?.('deviceId')
@ -792,8 +782,12 @@ const openCriticalComponentDialog = async () => {
}
const openMoldSelectDialog = () => {
searchMoldParams.code=''
searchMoldParams.name=''
if (!formData.value.deviceId) {
message.warning('请先选择设备')
return
}
searchMoldParams.code = ''
searchMoldParams.name = ''
const rows = selectedMoldRows.value.map((item) => ({ ...item, id: Number(item.id) }))
moldSelectDialogRef.value?.open(rows)
}

@ -188,8 +188,9 @@
>
<template #default="scope">
<el-switch
:model-value="scope.row.enabled === true || scope.row.enabled === 'true'"
:model-value="isTaskEnabled(scope.row)"
:before-change="() => handleBeforeEnabledChange(scope.row)"
@click.stop
@change="(val) => handleEnabledChange(scope.row, val)"
/>
</template>
@ -258,7 +259,6 @@
<script setup lang="ts">
import { ElMessageBox } from 'element-plus'
import { DICT_TYPE } from '@/utils/dict'
import { dateFormatter, dateFormatter2 } from '@/utils/formatTime'
import download from '@/utils/download'
import { TaskManagementApi, TaskManagementVO } from '@/api/mes/taskManagement'
@ -403,7 +403,12 @@ const openForm = (type: string, row?: TaskManagementVO) => {
formRef.value.open(type, row)
}
const isTaskEnabled = (row: TaskManagementVO) => row.enabled === true || (row.enabled as any) === 'true'
const isTaskEnabled = (row: TaskManagementVO) => {
const value = (row as any)?.enabled
if (typeof value === 'boolean') return value
const text = String(value ?? '').toLowerCase().trim()
return text === 'true' || text === '1' || text === 'yes'
}
const handleDelete = async (id?: number) => {
if (!id) return
@ -457,12 +462,13 @@ const handleBeforeEnabledChange = async (row: TaskManagementVO) => {
return false
}
const handleEnabledChange = async (row: TaskManagementVO, value: boolean) => {
const handleEnabledChange = async (row: TaskManagementVO, value: string | number | boolean) => {
if (!row.id) return
const enabled = value === true || value === 'true' || value === '1' || value === 1
const oldEnabled = row.enabled
row.enabled = value
row.enabled = enabled
try {
await TaskManagementApi.updateTaskManagementEnabled(String(row.id), value ? 'true' : 'false')
await TaskManagementApi.updateTaskManagementEnabled(String(row.id), enabled ? 'true' : 'false')
message.success(t('EquipmentManagement.TaskManagement.updateEnabledSuccess'))
} catch {
row.enabled = oldEnabled

@ -57,6 +57,17 @@
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item :label="t('MoldManagement.MoldRepair.repairReporter')" prop="repairReporter">
<el-select
v-model="formData.repairReporter" filterable clearable
:placeholder="t('MoldManagement.MoldRepair.placeholderRepairReporter')"
class="!w-full"
:disabled="isRepairMetaReadonly">
<el-option v-for="item in users" :key="String(item.id)" :label="item.nickname" :value="String(item.id)" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item :label="t('MoldManagement.MoldRepair.repairUser')" prop="acceptedBy">
<el-select
@ -347,6 +358,7 @@ import { MoldRepairApi, MoldRepairVO } from '@/api/mold/moldrepair'
import { MoldBrandApi, MoldVO } from '@/api/erp/mold'
import { getSimpleUserList, UserVO } from '@/api/system/user'
import { DICT_TYPE, getStrDictOptions } from '@/utils/dict'
import { useUserStore } from '@/store/modules/user'
defineOptions({ name: 'MoldRepairForm' })
@ -356,6 +368,7 @@ interface MoldRepairFormData extends Partial<MoldRepairVO> {
isCode?: boolean
faultLevel?: string
faultImages?: string
repairReporter?: string
repairResult?: string
repairStatus?: string
faultPhenomenon?: string
@ -388,6 +401,7 @@ const createDefaultFormData = (): MoldRepairFormData => ({
shutdown: undefined,
faultImages: '',
faultReason: undefined,
repairReporter: undefined,
acceptedBy: undefined,
confirmBy: undefined,
status: undefined,
@ -402,6 +416,7 @@ const createDefaultFormData = (): MoldRepairFormData => ({
const { t } = useI18n()
const message = useMessage()
const userStore = useUserStore()
const dialogTitle = ref('')
const formLoading = ref(false)
@ -706,6 +721,7 @@ const open = async (type: string, id?: number) => {
;(formData.value as any).acceptedBy = normalizeUserId((formData.value as any).acceptedBy)
;(formData.value as any).confirmBy = normalizeUserId((formData.value as any).confirmBy)
;(formData.value as any).repairReporter = normalizeUserId((formData.value as any).repairReporter)
;(formData.value as any).moldCode = (formData.value as any).moldCode ?? (formData.value as any).machineryCode
;(formData.value as any).moldName = (formData.value as any).moldName ?? (formData.value as any).machineryName
@ -730,6 +746,20 @@ const open = async (type: string, id?: number) => {
isHydrating.value = false
formLoading.value = false
}
} else {
if (formType.value === 'create') {
if (!userStore.getIsSetUser) {
try {
await userStore.setUserInfoAction()
} catch (e) {}
}
const currentUserId = userStore.getUser?.id
if (currentUserId !== undefined && currentUserId !== null && Number(currentUserId) > 0) {
formData.value.repairReporter = String(currentUserId)
}
}
await nextTick()
formRef.value?.clearValidate?.()
}
}
defineExpose({ open })
@ -748,6 +778,9 @@ const submitForm = async () => {
data.faultImages = Array.isArray(data.faultImages) ? data.faultImages.join(',') : (data.faultImages ?? '')
data.repairedImages = Array.isArray(data.repairedImages) ? data.repairedImages.join(',') : (data.repairedImages ?? '')
data.repairResult = data.repairStatus
data.acceptedBy = normalizeUserId(data.acceptedBy)
data.confirmBy = normalizeUserId(data.confirmBy)
data.repairReporter = normalizeUserId(data.repairReporter)
if (formType.value === 'repair') {
data.status = '1'
}

@ -160,6 +160,7 @@
sortable />
<!-- <el-table-column :label="t('MoldManagement.MoldRepair.repairResult')" align="center" prop="repairResult" min-width="160" /> -->
<el-table-column :label="t('MoldManagement.MoldRepair.repairReporter')" align="center" prop="repairReporter" min-width="140" />
<el-table-column :label="t('MoldManagement.MoldRepair.acceptUser')" align="center" prop="acceptedBy" min-width="140" />
<el-table-column :label="t('MoldManagement.MoldRepair.confirmUserShort')" align="center" prop="confirmBy" min-width="140" />

@ -53,7 +53,7 @@
class="!w-320px"
/>
</el-form-item>
<!-- <el-form-item :label="t('EquipmentManagement.TaskManagement.cronExpression')" prop="cronExpression">
<el-form-item :label="t('EquipmentManagement.TaskManagement.cronExpression')" prop="cronExpression">
<template #label>
<Tooltip
title="Cron 表达式"
@ -61,7 +61,7 @@
/>
</template>
<crontab v-model="formData.cronExpression" />
</el-form-item> -->
</el-form-item>
<el-form-item :label="t('EquipmentManagement.TaskManagement.operableUsers')" prop="operableUsers">
<el-select
v-model="formData.operableUsers"

@ -88,10 +88,15 @@
<el-table-column :label="t('EquipmentManagement.TaskManagement.projectForm')" align="center" prop="projectFormName" min-width="140" sortable />
<!-- <el-table-column :label="t('EquipmentManagement.TaskManagement.startDate')" align="center" prop="startDate" :formatter="dateFormatter2" width="120" sortable /> -->
<el-table-column :label="t('EquipmentManagement.TaskManagement.planEndDate')" align="center" prop="endDate" :formatter="dateFormatter2" width="150" sortable />
<!-- <el-table-column :label="t('EquipmentManagement.TaskManagement.cronExpression')" align="center" prop="cronExpression" min-width="180" /> -->
<el-table-column :label="t('EquipmentManagement.TaskManagement.enabled')" align="center" prop="enabled" width="90">
<el-table-column :label="t('EquipmentManagement.TaskManagement.cronExpression')" align="center" prop="cronExpression" min-width="180" />
<el-table-column :label="t('EquipmentManagement.TaskManagement.enabled')" align="center" prop="enabled" width="110">
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.enabled" />
<el-switch
:model-value="isTaskEnabled(scope.row)"
:before-change="() => handleBeforeEnabledChange(scope.row)"
@click.stop
@change="(val) => handleEnabledChange(scope.row, val)"
/>
</template>
</el-table-column>
<el-table-column :label="t('EquipmentManagement.TaskManagement.creatorName')" align="center" prop="creatorName" width="120" sortable />
@ -294,6 +299,34 @@ const handleCreateTicket = async (row?: TaskManagementVO) => {
}
}
const handleBeforeEnabledChange = async (row: TaskManagementVO) => {
const isEnabled = isTaskEnabled(row)
if (isEnabled) return true
const cronExpression = (row as any)?.cronExpression
if (typeof cronExpression === 'string' && cronExpression.trim()) return true
await ElMessageBox.alert(t('EquipmentManagement.TaskManagement.selectCronBeforeEnable'), t('EquipmentManagement.TaskManagement.cronAlertTitle'), {
type: 'warning',
confirmButtonText: t('EquipmentManagement.TaskManagement.cronAlertConfirm'),
closeOnClickModal: false,
closeOnPressEscape: false
})
return false
}
const handleEnabledChange = async (row: TaskManagementVO, value: string | number | boolean) => {
if (!row.id) return
const enabled = value === true || value === 'true' || value === '1' || value === 1
const oldEnabled = row.enabled
row.enabled = enabled
try {
await TaskManagementApi.updateTaskManagementEnabled(String(row.id), enabled ? 'true' : 'false')
message.success(t('EquipmentManagement.TaskManagement.updateEnabledSuccess'))
} catch {
row.enabled = oldEnabled
message.error(t('EquipmentManagement.TaskManagement.updateEnabledFail'))
}
}
const handleExport = async () => {
try {
await message.exportConfirm()

@ -4,6 +4,17 @@
<div class="ticket-result-header">
<el-button @click="handleClose">{{ t('common.back') }}</el-button>
<span class="ticket-result-title">{{ pageTitle }}</span>
<div class="ticket-result-actions">
<el-button
v-if="String(jobStatus) === '0'"
type="primary"
@click="handleSave"
:loading="submitLoading"
:disabled="hasImageUploading"
>
{{ t('MoldManagement.TicketResultDialog.save') }}
</el-button>
</div>
</div>
<el-descriptions :title="t('MoldManagement.MoldWorkOrderInquiry.basicInfo')" :column="4" border>
@ -141,14 +152,8 @@
v-model:page-size="queryParams.pageSize" :background="true" :page-sizes="[10, 20, 30, 50, 100]" :pager-count="7"
:total="total" class="mt-15px mb-15px flex justify-end" layout="total, sizes, prev, pager, next, jumper"
@size-change="handleSizeChange" @current-change="handleCurrentChange" />
<div class="ticket-result-footer">
<el-button v-if="String(jobStatus) === '0'" type="primary" @click="handleSave" :loading="submitLoading"
:disabled="hasImageUploading">
{{ t('MoldManagement.TicketResultDialog.save') }}
</el-button>
</div>
</ContentWrap>
</div>
</template>
@ -386,9 +391,9 @@ const parseImages = (value: any): string[] => {
color: var(--el-text-color-primary);
}
.ticket-result-footer {
.ticket-result-actions {
margin-left: auto;
display: flex;
justify-content: flex-end;
gap: 12px;
}
</style>

@ -41,6 +41,27 @@
<el-option v-for="opt in jobResultOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
</el-select>
</el-form-item>
<el-form-item :label="t('MoldManagement.MoldWorkOrderInquiry.operatorName')" prop="operator" v-show="showAllFilters">
<el-select
v-model="queryParams.operator"
filterable
:placeholder="t('MoldManagement.MoldWorkOrderInquiry.placeholderOperatorName')"
clearable
class="!w-240px"
>
<el-option v-for="item in users" :key="String(item.id)" :label="item.nickname" :value="String(item.id)" />
</el-select>
</el-form-item>
<el-form-item :label="t('MoldManagement.MoldWorkOrderInquiry.taskTimeRange')" prop="taskTimeRange" v-show="showAllFilters">
<el-date-picker
v-model="queryParams.taskTimeRange"
value-format="YYYY-MM-DD HH:mm:ss"
type="datetimerange"
:start-placeholder="t('MoldManagement.MoldWorkOrderInquiry.placeholderTaskTime')"
:end-placeholder="t('MoldManagement.MoldWorkOrderInquiry.placeholderTaskEndTime')"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-240px" />
</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" />
@ -54,13 +75,16 @@
<el-button type="primary" @click="handleQuery">
<Icon icon="ep:search" class="mr-5px" /> {{ t('MoldManagement.MoldWorkOrderInquiry.query') }}
</el-button>
<el-button type="success" plain @click="handleExport" :loading="exportLoading">
<Icon icon="ep:download" class="mr-5px" /> {{ t('MoldManagement.MoldWorkOrderInquiry.export') }}
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<ContentWrap>
<div class="mb-10px">
<el-button type="warning" plain @click="handleBatchCancel" :disabled="!selectedIds.length" :loading="cancelLoading">
<el-button type="warning" plain @click="handleBatchCancel" :disabled="isCancelDisabled" :loading="cancelLoading">
{{ t('MoldManagement.MoldWorkOrderInquiry.cancelTask') }}
</el-button>
</div>
@ -125,6 +149,7 @@ import { dateFormatter } from '@/utils/formatTime'
import { getStrDictOptions } from '@/utils/dict'
import { useDictStoreWithOut } from '@/store/modules/dict'
import { TicketManagementApi, TicketManagementVO } from '@/api/mold/ticketManagement'
import { getSimpleUserList, UserVO } from '@/api/system/user'
import TicketResultDialog from '@/views/mold/workOrderInquiry/components/TicketResultDialog.vue'
const { t } = useI18n()
@ -139,8 +164,8 @@ const planTypeOptions = [
{ label: t('MoldManagement.MoldWorkOrderInquiry.planTypeMaintain'), value: '2' }
]
const jobResultOptions = [
{ label: t('MoldManagement.MoldWorkOrderInquiry.jobResultOk'), value: 'OK' },
{ label: t('MoldManagement.MoldWorkOrderInquiry.jobResultNg'), value: 'NG' }
{ label: t('MoldManagement.MoldWorkOrderInquiry.jobResultOk'), value: '1' },
{ label: t('MoldManagement.MoldWorkOrderInquiry.jobResultNg'), value: '2' }
]
const loading = ref(true)
@ -159,7 +184,10 @@ const updatePlanTableMaxHeight = async () => {
planTableMaxHeight.value = Math.min(window.innerHeight, Math.max(240, Math.floor(availableHeight)))
}
const selectedIds = ref<number[]>([])
const selectedRows = ref<TicketManagementVO[]>([])
const cancelLoading = ref(false)
const exportLoading = ref(false)
const users = ref<UserVO[]>([])
const resultVisible = ref(false)
const selectedResultRow = ref<TicketManagementVO>()
const resultTitle = computed(() => {
@ -175,22 +203,36 @@ const queryParams = reactive({
pageSize: 10,
planNo: undefined as string | undefined,
planType: undefined as string | undefined,
jobStatus: undefined as string | undefined,
jobResult: undefined as string | undefined
jobStatus: '0' as string | undefined,
jobResult: undefined as string | undefined,
operator: undefined as string | undefined,
taskTimeRange: [] as string[]
})
const queryFormRef = ref()
const showAllFilters = ref(false)
const filterCount = 4
const filterCount = 6
const UNWORKED_JOB_STATUS = '0'
const CANCELED_JOB_STATUS = '4'
const toggleFilters = () => {
showAllFilters.value = !showAllFilters.value
updatePlanTableMaxHeight()
}
const buildQueryParams = () => {
const { taskTimeRange, ...params } = queryParams
return {
...params,
taskTime: taskTimeRange?.[0],
taskEndTime: taskTimeRange?.[1]
}
}
const getList = async () => {
loading.value = true
try {
const data = await TicketManagementApi.getTicketManagementPage(queryParams)
const data = await TicketManagementApi.getTicketManagementPage(buildQueryParams())
list.value = data.list
total.value = data.total
} finally {
@ -210,13 +252,22 @@ const resetQuery = () => {
}
const handleSelectionChange = (rows: TicketManagementVO[]) => {
selectedRows.value = rows
selectedIds.value = rows
.map((r) => r.id)
.filter((id): id is number => typeof id === 'number')
}
const isUnworkedTicket = (row?: TicketManagementVO) => String(row?.jobStatus ?? '') === UNWORKED_JOB_STATUS
const hasUncancelableSelection = computed(() => selectedRows.value.some((row) => !isUnworkedTicket(row)))
const isCancelDisabled = computed(() => !selectedIds.value.length || hasUncancelableSelection.value)
const handleBatchCancel = async () => {
if (!selectedIds.value.length) return
if (hasUncancelableSelection.value) {
message.warning(t('MoldManagement.MoldWorkOrderInquiry.cancelOnlyUnworkedTip'))
return
}
try {
const { value } = await ElMessageBox.prompt('请输入取消原因', t('MoldManagement.MoldWorkOrderInquiry.cancelTask'), {
confirmButtonText: t('common.ok'),
@ -227,11 +278,12 @@ const handleBatchCancel = async () => {
cancelLoading.value = true
await TicketManagementApi.batchUpdateTicketStatus({
ids: selectedIds.value.join(','),
jobStatus: '4',
jobStatus: CANCELED_JOB_STATUS,
cancelReason: value
})
message.success(t('MoldManagement.MoldWorkOrderInquiry.cancelSuccess'))
selectedIds.value = []
selectedRows.value = []
await getList()
} catch {
} finally {
@ -239,6 +291,23 @@ const handleBatchCancel = async () => {
}
}
const handleExport = async () => {
try {
await message.exportConfirm()
exportLoading.value = true
const params: any = {
...buildQueryParams(),
ids: selectedIds.value.length ? selectedIds.value.join(',') : undefined
}
const data = await TicketManagementApi.exportTicketManagement(params)
const download = (await import('@/utils/download')).default
download.excel(data, t('MoldManagement.MoldWorkOrderInquiry.exportFilename'))
} catch {
} finally {
exportLoading.value = false
}
}
const handleRowClick = (row: TicketManagementVO, column: any) => {
if (column?.type === 'selection') return
if (!row?.id) return
@ -259,6 +328,7 @@ const handleResultSuccess = async () => {
onMounted(async () => {
await dictStore.setDictMap()
users.value = await getSimpleUserList()
await getList()
updatePlanTableMaxHeight()
window.addEventListener("resize", updatePlanTableMaxHeight)
@ -268,3 +338,4 @@ onBeforeUnmount(() => {
window.removeEventListener("resize", updatePlanTableMaxHeight)
})
</script>

Loading…
Cancel
Save