Compare commits

...

2 Commits

Author SHA1 Message Date
kkk-ops 9674e024d1 merge 2 weeks ago
kkk-ops 06779b0ab8 首页 2 weeks ago

@ -1,5 +1,5 @@
# 标题
VITE_APP_TITLE=生产运营管理系统
VITE_APP_TITLE=数字化智能中控平台
# 项目本地运行端口号
VITE_PORT=8088

@ -7,11 +7,11 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="keywords"
content="生产运营管理系统"
content="数字化智能中控平台"
/>
<meta
name="description"
content="生产运营管理系统"
content="数字化智能中控平台"
/>
<title>%VITE_APP_TITLE%</title>
</head>

@ -0,0 +1,35 @@
import request from '@/config/axios'
export interface DashboardProductVO {
taskItems: ItemVO[]
planItems: ItemVO[]
}
export interface ItemVO {
key: string
label: string
value: number
}
export interface DeviceStatusVO {
key: string
label: string
value: number
level: string
}
// 编码生成记录 API
export const DashboardApi = {
// 查询编码生成记录分页
getProduction: async (params: any) => {
return await request.get({ url: `/mes/dashboard/getProduction`, params })
},
getPlan: async () => {
return await request.get({ url: `/mes/dashboard/getPlan` })
},
getDevice: async () => {
return await request.get({ url: `/mes/dashboard/getDevice` })
},
}

@ -75,5 +75,9 @@ export const DeviceLedgerApi = {
},
exportSpareBased: async (params) => {
return await request.download({ url: `/mes/device-ledger/export-spare-based`, params })
},
exportMold: async (params) => {
return await request.download({ url: `/mes/device-ledger/export-mold`, params })
}
}

@ -88,4 +88,9 @@ export const PlanApi = {
getPlanByStatus: async (status: number) => {
return await request.get({ url: `/mes/plan/getByStatus?status=` + status })
},
// 根据质检类型查询生产计划
getPlanByTicketType: async (status: number) => {
return await request.get({ url: `/mes/plan/getByTicketType?status=` + status })
},
}

@ -73,7 +73,7 @@ watch(
<div
v-if="show"
:class="[
'ml-10px text-16px font-700',
'ml-10px text-14px font-700',
{
'text-[var(--logo-title-text-color)]': layout === 'classic',
'text-[var(--top-header-text-color)]':

@ -114,7 +114,7 @@ export default {
small: '小'
},
login: {
welcome: '欢迎使用必硕生产运营管理系统',
welcome: '欢迎使用必硕数字化智能中控平台',
message: '必硕智能“纸”为绿色生活',
tenantname: '租户名称',
username: '用户名',

@ -2,9 +2,9 @@
<div class="home-page">
<div class="home-welcome">
<div class="home-welcome-left">
<div class="home-welcome-title text-white!">欢迎使用您的云上数字工厂</div>
<div class="home-welcome-title text-white!">欢迎您使用必硕数字化智能中控平台</div>
<div class="home-welcome-desc text-white! opacity-80">
云上数字工厂可以整合您工厂所有设备自动化信息化的教据帮助您对工厂和生产进行建模管理统一主教报及应用集成打造您工厂的教字中心和业务中心并且与产业链相关系统协同不断提升您的智能制造能力
必硕数字化智能中控平台以生产运营为核心统一整合生产计划数据采集仓储设备能源模具质量配方及报表分析等关键业务模块实现从计划到执行从设备到制品从数据到决策的全流程数字化管理
</div>
</div>
<div class="home-welcome-right">
@ -35,12 +35,12 @@ v-model="productionOverviewRange" type="daterange" unlink-panels value-format="Y
<div class="production-overview-value production-overview-value-primary">{{ item.value }}</div>
</div>
</el-col>
<el-col :span="4" class="production-overview-group production-overview-group-right">
<!-- <el-col :span="4" class="production-overview-group production-overview-group-right">
<div v-for="item in productionOverviewRight" :key="item.key" class="production-overview-item">
<div class="production-overview-label">{{ item.label }}</div>
<div class="production-overview-value">{{ item.value }}</div>
</div>
</el-col>
</el-col> -->
</el-row>
</el-card>
<el-card shadow="never" class="home-section">
@ -50,9 +50,13 @@ v-model="productionOverviewRange" type="daterange" unlink-panels value-format="Y
<el-carousel height="190px" arrow="always" indicator-position="none" :interval="15000" class="progress-carousel">
<el-carousel-item v-for="(group, index) in productionProgressGroups" :key="index">
<el-row :gutter="16">
<el-col v-for="item in group" :key="item.id" :xl="8" :lg="8" :md="8" :sm="12" :xs="24">
<el-col v-for="item in group" :key="item.id" :xl="8" :lg="8" :md="8" :sm="12" :xs="24">
<div class="progress-card">
<div class="progress-card-header">生产工单 {{ item.orderNo }}</div>
<div class="progress-card-header">生产计划 {{ item.code }}
<el-tag :type="getPlanStatusTagType(item.status)" effect="light">
{{ getPlanStatusLabel(item.status) }}
</el-tag>
</div>
<div class="progress-card-body">
<div class="progress-col">
<div class="progress-row">
@ -60,46 +64,66 @@ v-model="productionOverviewRange" type="daterange" unlink-panels value-format="Y
<span class="progress-value">{{ item.productName }}</span>
</div>
<div class="progress-row">
<span class="progress-label">任务数量</span>
<span class="progress-value">-</span>
<span class="progress-label">计划数量</span>
<span class="progress-value">{{ item.planNumber }}</span>
</div>
<div class="progress-row">
<span class="progress-label">客户简称</span>
<span class="progress-value">-</span>
<span class="progress-label">生产线</span>
<span class="progress-value">{{ item.feedingPipelineName }}</span>
</div>
<div class="progress-row">
<span class="progress-label">交货时间</span>
<span class="progress-value">{{ item.planEndTime }}</span>
<span class="progress-label">计划开始时间</span>
<span class="progress-value">{{ formatDate(item.planStartTime) }}</span>
</div>
<div class="progress-row">
<span class="progress-label">投产时间</span>
<span class="progress-value">{{ item.planStartTime }}</span>
<span class="progress-label">计划结束时间</span>
<span class="progress-value">{{ formatDate(item.planEndTime) }}</span>
</div>
</div>
<div class="progress-col">
<div class="progress-row">
<span class="progress-label">产品型号</span>
<span class="progress-value">-</span>
<span class="progress-label">完工数量</span>
<span class="progress-value">{{ item.wangongNumber }}</span>
</div>
<div class="progress-row">
<span class="progress-label">完成数量</span>
<span class="progress-value">-</span>
<span class="progress-label">合格数量</span>
<span class="progress-value">{{ item.passNumber }}</span>
</div>
<div class="progress-row">
<span class="progress-label">完成进度</span>
<span class="progress-value">{{ item.completeRate }}%</span>
<span class="progress-label">不合格数量</span>
<span class="progress-value">{{ item.noPassNumber }}%</span>
</div>
<div class="progress-row">
<span class="progress-label">工单状态</span>
<span class="progress-value">{{ item.statusText }}</span>
<span class="progress-label">合格率</span>
<span class="progress-value">{{ item.passRate }}</span>
</div>
<div class="progress-row">
<span class="progress-label">完工时间</span>
<span class="progress-value">-</span>
<span class="progress-label">实际结束时间</span>
<span class="progress-value">{{ formatDate(item.endTime) }}</span>
</div>
</div>
</div>
</div>
</el-col>
</el-row>
</el-carousel-item>
</el-carousel>
</el-card>
<el-card shadow="never" class="home-section">
<div class="section-header">
<div class="section-title">待办任务</div>
</div>
<el-carousel height="160px" arrow="always" indicator-position="none" class="todo-carousel" :interval="15000">
<el-carousel-item v-for="(group, index) in todoTaskGroups" :key="index">
<el-row :gutter="16">
<el-col v-for="item in group" :key="item.id" :xl="6" :lg="6" :md="12" :sm="12" :xs="24">
<div class="todo-card">
<div class="todo-title">{{ item.name }}</div>
<div class="todo-sub">任务编号{{ item.id }}</div>
<div class="todo-sub">任务类型{{ item.type }}优先级{{ item.priority }}</div>
<div class="todo-sub">计划时间{{ item.planTime }}</div>
<div class="todo-sub">责任部门{{ item.owner }}</div>
</div>
</el-col>
</el-row>
</el-carousel-item>
@ -110,10 +134,10 @@ v-model="productionOverviewRange" type="daterange" unlink-panels value-format="Y
<el-card shadow="never" class="device-alarm-card">
<div class="section-header">
<div class="section-title">设备</div>
<div class="section-actions">
<!-- <div class="section-actions">
<el-button type="default" size="small">查看文档</el-button>
<el-button type="primary" size="small">添加设备</el-button>
</div>
</div> -->
</div>
<el-row :gutter="12" class="mt-16px">
<el-col v-for="item in deviceStatusCards" :key="item.key" :span="8">
@ -128,7 +152,7 @@ v-model="productionOverviewRange" type="daterange" unlink-panels value-format="Y
<el-col :xl="12" :lg="12" :md="24" :sm="24" :xs="24" class="device-alarm-col mt-16px xl:mt-0 lg:mt-0">
<el-card shadow="never" class="device-alarm-card">
<div class="section-header">
<div class="section-title">告警</div>
<div class="section-title">模具</div>
</div>
<el-row :gutter="12" class="mt-16px">
<el-col v-for="item in alarmStatusCards" :key="item.key" :span="8">
@ -143,12 +167,12 @@ v-model="productionOverviewRange" type="daterange" unlink-panels value-format="Y
</el-row>
<el-card shadow="never" class="home-section">
<div class="section-header">
<div class="section-title">设备整体情况</div>
<div>
<div class="section-title">采集设备整体情况</div>
<!-- <div>
<el-date-picker
v-model="deviceOverviewRange" type="daterange" unlink-panels value-format="YYYY-MM-DD"
start-placeholder="开始日期" end-placeholder="结束日期" size="small" />
</div>
</div> -->
</div>
<el-row class="device-overview-row" :gutter="0">
<el-col v-for="item in deviceOverviewTop" :key="item.key" :span="2">
@ -165,26 +189,6 @@ v-model="deviceOverviewRange" type="daterange" unlink-panels value-format="YYYY-
</el-col>
</el-row>
</el-card>
<el-card shadow="never" class="home-section">
<div class="section-header">
<div class="section-title">待办任务</div>
</div>
<el-carousel height="160px" arrow="always" indicator-position="none" class="todo-carousel" :interval="15000">
<el-carousel-item v-for="(group, index) in todoTaskGroups" :key="index">
<el-row :gutter="16">
<el-col v-for="item in group" :key="item.id" :xl="6" :lg="6" :md="12" :sm="12" :xs="24">
<div class="todo-card">
<div class="todo-title">{{ item.name }}</div>
<div class="todo-sub">任务编号{{ item.id }}</div>
<div class="todo-sub">任务类型{{ item.type }}优先级{{ item.priority }}</div>
<div class="todo-sub">计划时间{{ item.planTime }}</div>
<div class="todo-sub">责任部门{{ item.owner }}</div>
</div>
</el-col>
</el-row>
</el-carousel-item>
</el-carousel>
</el-card>
<el-row :gutter="16" class="home-section">
<el-col :xl="8" :lg="8" :md="24" :sm="24" :xs="24" class="mb-16px">
<el-card shadow="never">
@ -217,7 +221,7 @@ v-model="deviceOverviewRange" type="daterange" unlink-panels value-format="YYYY-
</el-card>
</el-col>
</el-row>
<el-row :gutter="16" class="home-section" justify="space-between">
<!-- <el-row :gutter="16" class="home-section" justify="space-between">
<el-col :xl="16" :lg="16" :md="24" :sm="24" :xs="24" class="mb-16px">
<el-card shadow="never">
<template #header>
@ -227,8 +231,8 @@ v-model="deviceOverviewRange" type="daterange" unlink-panels value-format="YYYY-
</template>
<Echart :options="barOptionsData" :height="260" />
</el-card>
</el-col>
<el-col :xl="8" :lg="8" :md="24" :sm="24" :xs="24">
</el-col> -->
<!-- <el-col :xl="8" :lg="8" :md="24" :sm="24" :xs="24">
<el-card shadow="never" class="mb-16px">
<template #header>
<div class="h-3 flex justify-between">
@ -276,8 +280,8 @@ v-model="deviceOverviewRange" type="daterange" unlink-panels value-format="YYYY-
</div>
</el-skeleton>
</el-card>
</el-col>
</el-row>
</el-col> -->
<!-- </el-row> -->
<!-- 旧首页布局保留已通过新模块替代展示 -->
</div>
</template>
@ -315,7 +319,8 @@ import {
import { HomeApi } from '@/api/home/info'
import { WeatherVO } from '@/api/home/info'
import bannerImg from '@/assets/imgs/banner.png'
import { DashboardApi,DashboardProductVO,DeviceStatusVO } from '@/api/dashboard'
import { formatDate } from '@/utils/formatTime'
defineOptions({ name: 'Home' })
const { t } = useI18n()
@ -339,7 +344,8 @@ const productionOverviewRange = ref<string[]>([])
const deviceOverview = ref<DeviceOverview>(deviceOverviewMock)
const deviceOverviewRange = ref<string[]>([])
const productionProgressTab = ref('all')
const productionProgressList = ref<ProductionProgressItem[]>(productionProgressMock)
const productionProgressList = ref<ProductionProgressItem[]>()
const todoTaskList = ref<TodoTask[]>(todoTasksMock)
const deviceStatus = ref<DeviceStatusSummary>(deviceStatusMock)
const alarmStatus = ref<AlarmStatusSummary>(alarmStatusMock)
@ -352,64 +358,24 @@ const formatPercent = (value: number | undefined | null) => {
return `${value}%`
}
const productionOverviewLeft = computed(() => [
{
key: 'orderCount',
label: '生产订单数',
value: productionOverview.value.orderCount
},
{
key: 'runningOrderCount',
label: '生产工单数',
value: productionOverview.value.runningOrderCount
},
{
key: 'startedOrderCount',
label: '开工工单数',
value: productionOverview.value.startedOrderCount
},
{
key: 'shutdownOrderCount',
label: '完工工单数',
value: productionOverview.value.shutdownOrderCount
}
])
const productionOverviewLeft = ref([])
const productionOverviewCenter = computed(() => [
{
key: 'plannedOutput',
label: '计划生产数量',
value: productionOverview.value.plannedOutput?.toLocaleString()
},
{
key: 'completedOutput',
label: '完成生产数量',
value: productionOverview.value.completedOutput?.toLocaleString()
},
{
key: 'completionRate',
label: '完工率',
value: formatPercent(productionOverview.value.qualifiedRate)
},
{
key: 'qualifiedRate',
label: '合格率',
value: formatPercent(productionOverview.value.alarmRate)
}
])
const productionOverviewCenter = ref([])
const productionOverviewRight = computed(() => [
{
key: 'attendanceCount',
label: '出勤人数',
value: productionOverview.value.onTimeRate ?? 0
},
{
key: 'attendanceRate',
label: '出勤率',
value: formatPercent(productionOverview.value.onTimeRate)
}
])
const plan = ref<ProductionProgressItem[]>([])
// const productionOverviewRight = computed(() => [
// {
// key: 'attendanceCount',
// label: '',
// value: productionOverview.value.onTimeRate ?? 0
// },
// {
// key: 'attendanceRate',
// label: '',
// value: formatPercent(productionOverview.value.onTimeRate)
// }
// ])
const deviceOverviewTop = computed(() => [
{
@ -471,26 +437,26 @@ const deviceOverviewBottom = computed(() => [
value: 0
}
])
const deviceStatusCards = computed(() => [
{
key: 'inactive',
label: '非活动',
value: deviceStatus.value.inactive,
level: 'mini-danger'
},
{
key: 'active',
label: '活动',
value: deviceStatus.value.active,
level: 'mini-normal'
},
{
key: 'total',
label: '总数',
value: deviceStatus.value.total,
level: 'mini-total'
}
])
// const deviceStatusCards = computed(() => [
// {
// key: 'inactive',
// label: '',
// value: deviceStatus.value.inactive,
// level: 'mini-danger'
// },
// {
// key: 'active',
// label: '',
// value: deviceStatus.value.active,
// level: 'mini-normal'
// },
// {
// key: 'total',
// label: '',
// value: deviceStatus.value.total,
// level: 'mini-total'
// }
// ])
const alarmStatusCards = computed(() => [
{
key: 'serious',
@ -518,7 +484,7 @@ const groupBySize = <T,>(list: T[], size: number) => {
}
return result
}
const productionProgressGroups = computed(() => groupBySize(filteredProductionProgressList.value, 3))
const todoTaskGroups = computed(() => groupBySize(todoTaskList.value, 4))
//
let totalSate = reactive<WorkplaceTotal>({
@ -531,6 +497,9 @@ const weatherList = ref<WeatherVO[]>([])
const weatherEnable = ref(false)
const todayWeather = ref({} as WeatherVO)
let weatherCity = ""
const production = ref({} as DashboardProductVO)
const productionProgressGroups = computed(() => groupBySize(plan.value, 3))
const deviceStatusCards = ref<DeviceStatusVO[]>([])
/** 初始化 **/
onMounted(async () => {
//
@ -541,9 +510,28 @@ onMounted(async () => {
todayWeather.value = weatherList.value[0]
weatherCity = data.city
}
production.value = await DashboardApi.getProduction(productionOverviewRange)
plan.value = await DashboardApi.getPlan()
deviceStatusCards.value = await DashboardApi.getDevice()
productionOverviewLeft.value = production.value.taskItems
productionOverviewCenter.value = production.value.planItems
})
const getPlanStatusLabel = (value: any) => {
const v = value === '' || value === null || value === undefined ? undefined : String(value)
if (v == '1') return '已排产'
if (v == '2') return '试产'
if (v == '3') return '量产'
return '-'
}
const getPlanStatusTagType = (value: any) => {
const v = value === '' || value === null || value === undefined ? undefined : String(value)
if (v === '1') return 'success'
if (v === '0') return 'warning'
return 'info'
}
const getCount = async () => {
const data = {
project: 40,
@ -958,6 +946,14 @@ getAllApi()
top: 50%;
transform: translateY(-50%);
}
/* 左箭头往右移动 */
.progress-carousel :deep(.el-carousel__arrow--left) {
transform: translate(30px, -50%); /* X轴移动30pxY轴居中 */
}
/* 右箭头往左移动 */
.progress-carousel :deep(.el-carousel__arrow--right) {
transform: translate(-30px, -50%); /* X轴移动-30pxY轴居中 */
}
.progress-carousel :deep(.el-carousel__arrow--left) {
left: -8px;

@ -262,44 +262,6 @@ export const productionOverviewMock = {
onTimeRate: 0
}
export const productionProgressMock = [
{
id: 'SCGD00000036',
orderNo: 'SCGD00000036',
productName: '大中型模具',
statusText: '生产中',
planStartTime: '2021-05-28 18:40:10',
planEndTime: '2021-06-05 18:40:10',
completeRate: 8.33
},
{
id: 'SCGD00000037',
orderNo: 'SCGD00000037',
productName: '大型注塑模具',
statusText: '排产中',
planStartTime: '2021-05-28 18:40:10',
planEndTime: '2021-06-10 18:40:10',
completeRate: 6.86
},
{
id: 'SCGD00000033',
orderNo: 'SCGD00000033',
productName: '模具零件加工',
statusText: '生产中',
planStartTime: '2021-04-02 17:50:12',
planEndTime: '2021-04-10 17:50:12',
completeRate: 57.58
},
{
id: 'SCGD00000040',
orderNo: 'SCGD00000040',
productName: '试模工单',
statusText: '待开工',
planStartTime: '2021-06-15 08:30:00',
planEndTime: '2021-06-20 18:00:00',
completeRate: 0
}
]
export const deviceStatusMock = {
inactive: 2,

@ -68,12 +68,18 @@ export type ProductionOverview = {
export type ProductionProgressItem = {
id: string
orderNo: string
code: string
productName: string
statusText: string
planStartTime: string
planEndTime: string
completeRate: number
planNumber: number
feedingPipelineName: string
planStartTime: Date
planEndTime: Date
wangongNumber: number
passNumber: number
noPassNumber: number
passRate: number
endTime: Date
status: number
}
export type DeviceStatusSummary = {

@ -8,12 +8,34 @@
v-loading="formLoading"
:disabled="disabled"
>
<el-form-item prop="code">
<template #label>
<span>
入库单号
<el-tooltip content="入库单号" placement="top">
<Icon icon="ep:question-filled" />
</el-tooltip>
</span>
</template>
<el-row :gutter="10" style="width: 100%;">
<el-col :xs="24" :sm="18" :md="16" :lg="14" :xl="12">
<el-input
:disabled="formData.isCode == true || formType === 'update'"
v-model="formData.no"
placeholder="编码保存后自动生成"
/>
</el-col>
<el-col :xs="24" :sm="6" :md="4" :lg="3" :xl="2">
<div>
<el-switch
v-model="formData.isCode"
:disabled="formType === 'update'"
/>
</div>
</el-col>
</el-row>
</el-form-item>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="入库单号" prop="no">
<el-input disabled v-model="formData.no" placeholder="保存时自动生成" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="入库类型" prop="inType">
<el-select
@ -117,7 +139,9 @@ const formData = ref({
inType: undefined,
remark: undefined,
fileUrl: '',
items: []
items: [],
isCode: undefined,
no: undefined
})
const formRules = reactive({
inTime: [{ required: true, message: '入库时间不能为空', trigger: 'blur' }],
@ -208,7 +232,9 @@ const resetForm = () => {
inTime: undefined,
remark: undefined,
fileUrl: undefined,
items: []
items: [],
isCode: true,
no: undefined
}
formRef.value?.resetFields()
}

@ -6,10 +6,10 @@
<el-table-column label="单位" align="center" prop="unitName" />
<el-table-column label="需求量" align="center" prop="number" />
<el-table-column label="库存" align="center" prop="stockNumber" />
<el-table-column label="车间仓库存" align="center" prop="stockWorkshopNumber" />
<!-- <el-table-column label="车间仓库存" align="center" prop="stockWorkshopNumber" /> -->
</el-table>
<template #footer>
<el-button @click="openForm" type="primary" :disabled="loading"> </el-button>
<!-- <el-button @click="openForm" type="primary" :disabled="loading"> </el-button> -->
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>

@ -396,6 +396,13 @@ type="success" plain :loading="spareExportLoading" @click="handleExportSpareBase
</el-table>
</el-tab-pane>
<el-tab-pane label="模具" name="mold">
<div class="device-ledger-tab-toolbar">
<el-button
type="success" plain :loading="moldExportLoading" @click="handleExportMold"
v-hasPermi="['mes:device-ledger:export']">
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</div>
<el-table v-loading="loading" :data="detailData?.moldList" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="编码" align="center" prop="code" min-width="140" />
<el-table-column label="名称" align="center" prop="name" min-width="140" />
@ -449,6 +456,7 @@ const queryFormRef = ref() // 搜索的表单
const exportLoading = ref(false) //
const criticalExportLoading = ref(false)
const spareExportLoading = ref(false)
const moldExportLoading = ref(false)
const inspectionExportLoading = ref(false)
const inspectionDateRange = ref<string[] | undefined>(undefined)
const maintainExportLoading = ref(false)
@ -946,6 +954,7 @@ const handleExportCriticalComponent = async () => {
}
}
//
const handleExportSpareBased = async () => {
if (!selectedDetailId.value) {
message.error('请先选择设备')
@ -962,6 +971,23 @@ const handleExportSpareBased = async () => {
}
}
//
const handleExportMold = async () => {
if (!selectedDetailId.value) {
message.error('请先选择设备')
return
}
try {
await message.exportConfirm()
moldExportLoading.value = true
const data = await DeviceLedgerApi.exportMold({ id: selectedDetailId.value })
download.excel(data, '模具.xls')
} catch {
} finally {
moldExportLoading.value = false
}
}
const handleExportInspection = async () => {
if (!selectedDetailId.value) {
message.error('请先选择设备')
@ -1083,7 +1109,7 @@ onMounted(async () => {
.device-ledger-tab-toolbar {
margin-bottom: 8px;
text-align: right;
text-align: left;
}
.device-ledger-history-items {

@ -43,7 +43,7 @@ type="success" plain @click="handleExport" :loading="exportLoading"
@current-change="handleCurrentChange"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="50" align="center" />
<!-- <el-table-column type="selection" width="50" align="center" /> -->
<el-table-column label="表编码" align="center" prop="code" />
<el-table-column label="表名称" align="center" prop="name" />
<el-table-column label="能耗类型" align="center" prop="deviceTypeName" />

@ -44,7 +44,7 @@ ref="tableRef" v-loading="loading" :data="list" :stripe="true" :show-overflow-to
<template #default="scope">
<el-table
v-if="getPointDetailsRows(scope.row).length" :data="getPointDetailsRows(scope.row)"
:show-overflow-tooltip="true" size="small" border>
:show-overflow-tooltip="true" size="small" border :header-cell-style="{ background: '#f5f7fa', color: '#909399' }">
<el-table-column label="参数名称" prop="pointName" min-width="140" />
<el-table-column label="最早采集值" prop="earliestValue" min-width="120" />
<el-table-column label="最早采集时间" prop="earliestTime" min-width="170" />
@ -63,11 +63,11 @@ v-if="getPointDetailsRows(scope.row).length" :data="getPointDetailsRows(scope.ro
<el-table-column label="能源类型" align="center" prop="deviceTypeName" min-width="100" />
<el-table-column label="所属区域" align="center" prop="orgName" min-width="100" />
<el-table-column label="能源用量" align="center" prop="energyConsumption" min-width="120" />
<el-table-column label="班次" align="center" min-width="90">
<!-- <el-table-column label="班次" align="center" min-width="90">
<template #default>
<el-tag type="success">早班</el-tag>
</template>
</el-table-column>
</el-table-column> -->
<el-table-column label="开始时间" align="center" min-width="170">
<template #default="scope">
{{ scope.row.startTime ?? scope.row.earliestDataTime ?? '-' }}

@ -7,9 +7,34 @@
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="单号:" prop="feedingRecordCode">
<el-input disabled v-model="formData.feedingRecordCode" placeholder="保存自动生成单号" />
</el-form-item>
<el-form-item prop="feedingRecordCode">
<template #label>
<span>
单号
<el-tooltip content="单号" placement="top">
<Icon icon="ep:question-filled" />
</el-tooltip>
</span>
</template>
<el-row :gutter="10" style="width: 100%;">
<el-col :xs="24" :sm="18" :md="16" :lg="14" :xl="12">
<el-input
:disabled="formData.isCode == true || formType === 'update'"
v-model="formData.feedingRecordCode"
placeholder="编码保存后自动生成"
/>
</el-col>
<el-col :xs="24" :sm="6" :md="4" :lg="3" :xl="2">
<div>
<el-switch
v-model="formData.isCode"
:disabled="formType === 'update'"
/>
</div>
</el-col>
</el-row>
</el-form-item>
<!-- <el-form-item label="制浆线:" prop="feedingPipeline">
<el-tree-select
v-model="formData.feedingPipeline"
@ -91,6 +116,7 @@
type="date"
value-format="x"
placeholder="选择投料时间"
class="!w-full"
/>
</el-form-item>
<el-form-item label="备注:" prop="remark">
@ -174,6 +200,7 @@ const formData = ref({
userId: undefined,
remark: undefined,
recordStatus: undefined,
isCode: undefined
})
const formRules = reactive({
feedingType: [{ required: true, message: '投料类型不能为空', trigger: 'blur' }],
@ -271,6 +298,7 @@ const resetForm = () => {
userId: undefined,
remark: undefined,
recordStatus: undefined,
isCode: true
}
recordData.value = []
formRef.value?.resetFields()
@ -281,7 +309,7 @@ const getOrganizationTree = async () => {
organizationTree.value = []
const req = {orgClass:'pipeline'}
const data = await OrganizationApi.getOrganizationList(req)
const root: Tree = { id: 0, name: '顶级产线工位', children: [] }
const root: Tree = { id: 0, name: '顶级组织', children: [] }
root.children = handleTree(data, 'id', 'parentId')
organizationTree.value.push(root)
}

@ -7,17 +7,34 @@
label-width="100px"
v-loading="formLoading"
>
<el-form-item prop="code">
<template #label>
<span>
编码
<el-tooltip content="生产任务单编码规则" placement="top">
<Icon icon="ep:question-filled" />
</el-tooltip>
</span>
</template>
<el-input disabled v-model="formData.code" placeholder="保存自动生成" />
</el-form-item>
<el-form-item prop="code">
<template #label>
<span>
编码
<el-tooltip content="厂区结构编码" placement="top">
<Icon icon="ep:question-filled" />
</el-tooltip>
</span>
</template>
<el-row :gutter="10" style="width: 100%;">
<el-col :xs="24" :sm="18" :md="16" :lg="14" :xl="12">
<el-input
:disabled="formData.isCode == true || formType === 'update'"
v-model="formData.code"
placeholder="编码保存后自动生成"
/>
</el-col>
<el-col :xs="24" :sm="6" :md="4" :lg="3" :xl="2">
<div>
<el-switch
v-model="formData.isCode"
:disabled="formType === 'update'"
/>
</div>
</el-col>
</el-row>
</el-form-item>
<el-form-item label="父组织" prop="parentId">
<el-tree-select
v-model="formData.parentId"
@ -142,7 +159,8 @@ const formData = ref({
isEnable: undefined,
status: undefined,
orgClass: undefined,
orgType: undefined
orgType: undefined,
isCode: undefined
})
const formRules = reactive({
name: [{ required: true, message: '组织名称不能为空', trigger: 'blur' }],
@ -211,7 +229,8 @@ const resetForm = () => {
isEnable: undefined,
status: undefined,
orgClass: undefined,
orgType: undefined
orgType: undefined,
isCode: true
}
formRef.value?.resetFields()
}

@ -50,15 +50,23 @@
</el-tooltip>
</span>
</template>
<div style="display: flex; align-items: center; gap: 10px">
<el-input
:disabled="formData.isCode == true || formType === 'update'"
v-model="formData.code"
placeholder="编码保存后自动生成"
style="min-width: 600px"
/>
<el-switch v-model="formData.isCode" :disabled="formType === 'update'"/>
</div>
<el-row :gutter="10" class="!w-full">
<el-col :xs="24" :sm="18" :md="16" :lg="14" :xl="12">
<el-input
:disabled="formData.isCode == true || formType === 'update'"
v-model="formData.code"
placeholder="编码保存后自动生成"
/>
</el-col>
<el-col :xs="24" :sm="6" :md="4" :lg="3" :xl="2">
<div>
<el-switch
v-model="formData.isCode"
:disabled="formType === 'update'"
/>
</div>
</el-col>
</el-row>
</el-form-item>
<el-form-item label="生产线" prop="feedingPipeline">
<el-tree-select
@ -125,6 +133,7 @@
type="date"
value-format="x"
placeholder="选择计划开始时间"
class="!w-full"
/>
</el-form-item>
<el-form-item label="计划结束" prop="planEndTime">
@ -133,6 +142,7 @@
type="date"
value-format="x"
placeholder="选择计划结束时间"
class="!w-full"
/>
</el-form-item>
<!-- <el-form-item label="班别" prop="groupType">
@ -332,8 +342,10 @@ const getOrganizationTree = async () => {
organizationTree.value = []
const req = {orgClass:'pipeline'}
const data = await OrganizationApi.getOrganizationList(req)
const root: Tree = { id: 0, name: '顶级产线工位', children: [] }
const root: Tree = { id: 0, name: '顶级组织', children: [] }
root.children = handleTree(data, 'id', 'parentId')
organizationTree.value.push(root)
}
</script>

@ -7,24 +7,10 @@
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="任务单" prop="taskId">
<el-select
disabled
v-model="formData.taskId"
clearable
filterable
placeholder="请选择"
@change="handleTaskChange"
>
<el-option
v-for="item in taskList"
:key="item.id"
:label="item.code"
:value="item.id"
/>
</el-select>
<el-form-item label="任务单" prop="taskCode">
<el-input disabled v-model="formData.taskCode" placeholder="请输入任务单" />
</el-form-item>
<el-form-item label="明细项" prop="taskId">
<!-- <el-form-item label="明细项" prop="taskId">
<el-select
disabled
v-model="formData.taskDetailId"
@ -40,6 +26,9 @@
:value="item.id"
/>
</el-select>
</el-form-item> -->
<el-form-item label="明细项" prop="productName">
<el-input disabled v-model="formData.productName" placeholder="请输入产品" />
</el-form-item>
<el-form-item label="计划编码" prop="code">
<el-input disabled v-model="formData.code" placeholder="请输入计划编码" />
@ -168,7 +157,9 @@ const formData = ref({
feedingPipelineName: undefined,
workerId: undefined,
worker: undefined,
isPreProduction: undefined
isPreProduction: undefined,
productName: undefined,
taskCode: undefined
})
const formRef = ref() // Ref
@ -176,11 +167,12 @@ const formRef = ref() // 表单 Ref
/** 打开弹窗 */
const open = async (id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + '详情')
dialogTitle.value = t('详情')
// formType.value = type
editDisable.value = false
resetForm()
formData.value = await PlanApi.getPlan(id)
console.log(formData.value)
}
defineExpose({ open }) // open

@ -165,11 +165,11 @@
<dict-tag :type="DICT_TYPE.MES_PLAN_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="班别" align="center" prop="groupType" sortable>
<!-- <el-table-column label="班别" align="center" prop="groupType" sortable>
<template #default="scope">
<dict-tag :type="DICT_TYPE.MES_GROUP_TYPE" :value="scope.row.groupType" />
</template>
</el-table-column>
</el-table-column> -->
<!-- <el-table-column label="领料人" align="center" prop="productionManagerName" /> -->
<el-table-column label="计划开始时间" align="center" sortable prop="planStartTime" :formatter="dateFormatter2" width="150px"/>
<el-table-column label="计划结束时间" align="center" sortable prop="planEndTime" :formatter="dateFormatter2" width="150px"/>

@ -4,27 +4,35 @@
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
label-width="120px"
v-loading="formLoading"
>
<el-form-item prop="code">
<template #label>
<span>
编码
<el-tooltip content="生产任务单编码规则" placement="top">
任务单编码
<el-tooltip content="任务单编码" placement="top">
<Icon icon="ep:question-filled" />
</el-tooltip>
</span>
</template>
<div style="display: flex; align-items: center; gap: 10px">
<el-input
:disabled="formData.isCode == true || formType === 'update'"
v-model="formData.code"
placeholder="编码保存后自动生成"
style="min-width: 600px"
/>
<el-switch v-model="formData.isCode" :disabled="formType === 'update'"/>
</div>
<el-row :gutter="10" style="width: 100%;">
<el-col :xs="24" :sm="18" :md="16" :lg="14" :xl="12">
<el-input
:disabled="formData.isCode == true || formType === 'update'"
v-model="formData.code"
placeholder="编码保存后自动生成"
/>
</el-col>
<el-col :xs="24" :sm="6" :md="4" :lg="3" :xl="2">
<div>
<el-switch
v-model="formData.isCode"
:disabled="formType === 'update'"
/>
</div>
</el-col>
</el-row>
</el-form-item>
<el-form-item label="交货日期" prop="deliveryDate">
<el-date-picker
@ -32,6 +40,7 @@
type="date"
value-format="x"
placeholder="选择交货日期"
class="!w-full"
/>
</el-form-item>
<el-form-item label="任务类型" prop="taskType">

@ -21,17 +21,32 @@ v-for="dict in getStrDictOptions('mes_zj_task_type')" :key="dict.value" :label="
</el-col>
</el-row>
</el-form-item>
<el-form-item label="工单" prop="ticket">
<el-input v-model="formData.ticket" placeholder="请输入工单" />
<el-form-item label="工单类型" prop="ticketType">
<el-radio-group v-model="formData.ticketType" @change="ticketTypeChange">
<el-radio :label="1">生产过程</el-radio>
<el-radio :label="2">产品入库</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="工序" prop="orgType">
<el-form-item label="生产计划" prop="ticket">
<el-select
v-model="formData.ticket"
clearable
filterable
placeholder="请选择生产计划"
>
<el-option
v-for="item in planList"
:key="item.id"
:label="item.code"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="工序" prop="orgType" v-if="formData.ticketType === 1">
<el-select v-model="formData.orgType" clearable placeholder="请选择工序">
<el-option v-for="item in orgTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="formData.remark" placeholder="请输入备注" />
</el-form-item>
<el-form-item label="负责人" prop="managerId">
<el-select
v-model="formData.managerId"
@ -48,6 +63,9 @@ v-for="dict in getStrDictOptions('mes_zj_task_type')" :key="dict.value" :label="
/>
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="formData.remark" placeholder="请输入备注" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
@ -93,6 +111,7 @@ import { ZjTaskApi, ZjTaskVO } from '@/api/mes/zjtask'
import { ZjSchemaApi, ZjSchemaVO } from '@/api/mes/zjschema'
import { DICT_TYPE, getStrDictOptions } from '@/utils/dict'
import * as UserApi from '@/api/system/user'
import { PlanApi, PlanVO } from '@/api/mes/plan'
defineOptions({ name: 'ZjTaskForm' })
@ -103,6 +122,7 @@ const dialogVisible = ref(false)
const dialogTitle = ref('')
const formLoading = ref(false)
const formType = ref('')
const planList = ref<PlanVO[]>([])
const formData = ref<{ [key: string]: any }>({
id: undefined,
@ -116,6 +136,7 @@ const formData = ref<{ [key: string]: any }>({
remark: undefined,
managerId: undefined,
managerName: undefined,
ticketType: undefined
})
const formRules = reactive({
@ -124,6 +145,7 @@ const formRules = reactive({
schemaId: [{ required: true, message: '检验方案不能为空', trigger: 'change' }],
ticket: [{ required: true, message: '工单不能为空', trigger: 'blur' }],
orgType: [{ required: true, message: '工序不能为空', trigger: 'change' }],
ticketType: [{ required: true, message: '工单类型不能为空', trigger: 'change' }],
})
const formRef = ref()
@ -199,6 +221,7 @@ const resetForm = () => {
remark: undefined,
managerId: undefined,
managerName: undefined,
ticketType: undefined
}
selectedSchemaId.value = undefined
formRef.value?.resetFields()
@ -259,4 +282,11 @@ const submitForm = async () => {
formLoading.value = false
}
}
const ticketTypeChange = async () => {
if (formData.value.ticketType != undefined) {
const data = await PlanApi.getPlanByTicketType(formData.value.ticketType)
planList.value = data || []
}
}
</script>

@ -13,11 +13,11 @@ v-for="dict in getStrDictOptions('mes_zj_task_type')" :key="dict.value" :label="
:value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="工单" prop="ticket">
<!-- <el-form-item label="工单" prop="ticket">
<el-input
v-model="queryParams.ticket" placeholder="请输入工单" clearable @keyup.enter="handleQuery"
class="!w-240px" />
</el-form-item>
</el-form-item> -->
<el-form-item label="工序" prop="orgType">
<el-select v-model="queryParams.orgType" clearable placeholder="请选择工序" class="!w-240px">
<el-option v-for="item in orgTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
@ -74,7 +74,7 @@ type="success" plain @click="handleExport" :loading="exportLoading"
<DictTag :type="'job_status'" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="工单" align="center" prop="ticket" />
<el-table-column label="工单" align="center" prop="ticketCode" />
<el-table-column label="工序" align="center" prop="orgType">
<template #default="scope">
<DictTag :type="DICT_TYPE.MES_ORG_TYPE" :value="scope.row.orgType" />

Loading…
Cancel
Save