From 80adf052e0b58abd634ca9b67f8569ccc468c430 Mon Sep 17 00:00:00 2001
From: yyb <995253665@qq.com>
Date: 星期一, 23 三月 2026 15:11:36 +0800
Subject: [PATCH] Merge branch 'dev_银川_中盛建材' of http://114.132.189.42:9002/r/product-inventory-management into dev_银川_中盛建材
---
src/views/productionManagement/productionReporting/reportingDialog.vue | 1647 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 1,647 insertions(+), 0 deletions(-)
diff --git a/src/views/productionManagement/productionReporting/reportingDialog.vue b/src/views/productionManagement/productionReporting/reportingDialog.vue
new file mode 100644
index 0000000..1c8ad3f
--- /dev/null
+++ b/src/views/productionManagement/productionReporting/reportingDialog.vue
@@ -0,0 +1,1647 @@
+<template>
+ <div class="reporting-page">
+ <!-- 椤甸潰澶撮儴 -->
+ <PageHeader content="鐢熶骇宸ュ崟鎶ュ伐">
+ </PageHeader>
+ <!-- 姝ラ鎸囩ず鍣� -->
+ <div class="step-indicator">
+ <div v-for="(step, index) in steps"
+ :key="index"
+ class="step-item"
+ :class="{
+ 'active': index === activeStep,
+ 'completed': index < activeStep
+ }">
+ <div class="step-circle">
+ <span v-if="index < activeStep"
+ class="step-check">
+ <el-icon>
+ <Check />
+ </el-icon>
+ </span>
+ <span v-else
+ class="step-number">{{ index + 1 }}</span>
+ </div>
+ <div class="step-content">
+ <div class="step-title">{{ step.title }}</div>
+ <div class="step-description">{{ step.description }}</div>
+ </div>
+ <div class="step-line"
+ v-if="index < steps.length - 1"></div>
+ </div>
+ </div>
+ <!-- 椤甸潰鍐呭 -->
+ <div class="page-content">
+ <!-- 绗竴姝ワ細閫夋嫨鐢熶骇璁㈠崟 -->
+ <div v-if="activeStep === 0"
+ class="step-panel">
+ <div class="panel-header">
+ <div>
+ <h3 class="panel-title">閫夋嫨鐢熶骇璁㈠崟</h3>
+ <p class="panel-subtitle">璇蜂粠浠ヤ笅鍒楄〃涓�夋嫨闇�瑕佹姤宸ョ殑鐢熶骇璁㈠崟</p>
+ </div>
+ <div class="header-actions">
+ <el-button @click="activeStep--"
+ v-if="activeStep > 0"
+ :disabled="isSubmitting">
+ <el-icon>
+ <ArrowLeft />
+ </el-icon> 涓婁竴姝�
+ </el-button>
+ <el-button type="primary"
+ @click="handleNextStep"
+ v-if="activeStep < 3"
+ :disabled="isSubmitting">
+ 涓嬩竴姝� <el-icon>
+ <ArrowRight />
+ </el-icon>
+ </el-button>
+ </div>
+ </div>
+ <el-form :model="form"
+ ref="formRef"
+ class="form-container">
+ <el-form-item label="鐢熶骇璁㈠崟"
+ prop="orderId"
+ required>
+ <el-select v-model="orderId"
+ placeholder="璇烽�夋嫨鐢熶骇璁㈠崟"
+ clearable
+ filterable
+ class="form-select"
+ :loading="orderLoading"
+ @change="handleOrderChange">
+ <el-option v-for="order in orderList"
+ :key="order.id"
+ :label="`${order.npsNo} - ${order.productName} ${order.model}`"
+ :value="order.id" />
+ </el-select>
+ </el-form-item>
+ </el-form>
+ </div>
+ <!-- 绗簩姝ワ細濉啓鍩虹淇℃伅 -->
+ <div v-else-if="activeStep === 1"
+ class="step-panel">
+ <div class="panel-header">
+ <div>
+ <h3 class="panel-title">濉啓鍩虹淇℃伅</h3>
+ <p class="panel-subtitle">璇峰~鍐欐姤宸ョ殑鍩烘湰淇℃伅</p>
+ </div>
+ <div class="header-actions">
+ <el-button @click="activeStep--"
+ v-if="activeStep > 0"
+ :disabled="isSubmitting">
+ <el-icon>
+ <ArrowLeft />
+ </el-icon> 涓婁竴姝�
+ </el-button>
+ <el-button type="primary"
+ @click="handleNextStep"
+ v-if="activeStep < 3"
+ :disabled="isSubmitting">
+ 涓嬩竴姝� <el-icon>
+ <ArrowRight />
+ </el-icon>
+ </el-button>
+ </div>
+ </div>
+ <el-form :model="form"
+ :rules="rules"
+ ref="formRef"
+ class="form-container">
+ <div class="form-grid">
+ <el-form-item label="鐢熶骇璁㈠崟鍙�"
+ prop="npsNo"
+ class="form-item">
+ <el-input disabled
+ v-model="form.npsNo"
+ class="form-input" />
+ </el-form-item>
+ <el-form-item label="浜у搧缂栫爜"
+ prop="materialCode"
+ class="form-item">
+ <el-input disabled
+ v-model="form.materialCode"
+ class="form-input" />
+ </el-form-item>
+ <el-form-item label="浜у搧鍚嶇О"
+ prop="productName"
+ class="form-item">
+ <el-input disabled
+ v-model="form.productName"
+ class="form-input" />
+ </el-form-item>
+ <el-form-item label="瑙勬牸"
+ prop="specification"
+ class="form-item">
+ <el-input disabled
+ v-model="form.specification"
+ class="form-input" />
+ </el-form-item>
+ <el-form-item label="鍒涘缓鏃堕棿"
+ prop="createTime"
+ class="form-item">
+ <el-date-picker disabled
+ v-model="form.createTime"
+ type="datetime"
+ placeholder="璇烽�夋嫨鍒涘缓鏃堕棿"
+ class="form-input" />
+ </el-form-item>
+ <el-form-item label="鐝粍"
+ prop="teamName"
+ required
+ class="form-item">
+ <el-select v-model="form.teamName"
+ placeholder="璇烽�夋嫨鐝粍"
+ class="form-select">
+ <el-option label="鐧界彮"
+ value="鐧界彮" />
+ <el-option label="澶滅彮"
+ value="澶滅彮" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="鍒涘缓浜�"
+ prop="createBy"
+ required
+ class="form-item">
+ <el-select v-model="form.createBy"
+ placeholder="璇烽�夋嫨鍒涘缓浜�"
+ class="form-select"
+ :loading="userLoading">
+ <el-option v-for="user in userList"
+ :key="user.id"
+ :label="user.nickName || user.userName"
+ :value="user.nickName || user.userName" />
+ </el-select>
+ </el-form-item>
+ </div>
+ </el-form>
+ </div>
+ <!-- 绗笁姝ワ細鏌ョ湅宸ュ簭鍙傛暟 -->
+ <div v-else-if="activeStep === 2"
+ class="step-panel process-panel">
+ <div class="panel-header">
+ <div>
+ <h3 class="panel-title">宸ュ簭鍙傛暟绠$悊</h3>
+ <p class="panel-subtitle">璇锋煡鐪嬪苟濉啓鍚勫伐搴忕殑鍙傛暟淇℃伅</p>
+ </div>
+ <div class="header-actions">
+ <el-button @click="activeStep--"
+ v-if="activeStep > 0"
+ :disabled="isSubmitting">
+ <el-icon>
+ <ArrowLeft />
+ </el-icon> 涓婁竴姝�
+ </el-button>
+ <el-button type="primary"
+ @click="handleNextStep"
+ v-if="activeStep < 3"
+ :disabled="isSubmitting">
+ 涓嬩竴姝� <el-icon>
+ <ArrowRight />
+ </el-icon>
+ </el-button>
+ </div>
+ </div>
+ <div class="process-container">
+ <!-- 宸︿晶宸ュ簭瀵艰埅 -->
+ <div class="process-nav">
+ <div v-for="process in processList"
+ :key="process.processId"
+ class="process-nav-item"
+ :class="{ 'active': activeProcessId === process.processId + '' }"
+ @click="handleProcessClick(process.processId)">
+ <span class="process-name">{{ process.processName }}</span>
+ <span class="process-badge"
+ v-if="getProcessInfo(parseInt(process.processId)).postPersonnel">
+ {{ getProcessInfo(parseInt(process.processId)).postPersonnel }}
+ </span>
+ </div>
+ </div>
+ <!-- 鍙充晶宸ュ簭鍐呭 -->
+ <div class="process-content">
+ <div v-if="activeProcessId"
+ class="process-details">
+ <!-- 鍥哄畾鍙傛暟 -->
+ <div class="param-section">
+ <div class="section-header">
+ <h4 class="section-title">宸ュ簭鍩烘湰淇℃伅</h4>
+ </div>
+ <div class="param-form">
+ <el-form :label-position="'top'">
+ <div class="form-grid">
+ <el-form-item label="宀椾綅浜哄憳"
+ class="form-item">
+ <el-select v-model="getProcessInfo(parseInt(activeProcessId)).postPersonnel"
+ placeholder="璇烽�夋嫨宀椾綅浜哄憳"
+ class="form-select"
+ :loading="userLoading">
+ <el-option v-for="user in userList"
+ :key="user.id"
+ :label="user.nickName || user.userName"
+ :value="user.nickName || user.userName" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="璁惧寮傚父鎯呭喌"
+ class="form-item">
+ <el-input v-model="getProcessInfo(parseInt(activeProcessId)).equipmentAbnormality"
+ placeholder="璇疯緭鍏ヨ澶囧紓甯告儏鍐�"
+ type="textarea"
+ :rows="2"
+ class="form-textarea" />
+ </el-form-item>
+ <el-form-item label="褰撶彮璁惧澶勭疆"
+ class="form-item">
+ <el-input v-model="getProcessInfo(parseInt(activeProcessId)).equipmentHandling"
+ placeholder="璇疯緭鍏ュ綋鐝澶囧缃�"
+ type="textarea"
+ :rows="2"
+ class="form-textarea" />
+ </el-form-item>
+ <el-form-item label="宸ヨ壓浜哄憳浜ゅ緟"
+ class="form-item">
+ <el-input v-model="getProcessInfo(parseInt(activeProcessId)).processInstructions"
+ placeholder="璇疯緭鍏ュ伐鑹轰汉鍛樹氦寰�"
+ type="textarea"
+ :rows="2"
+ class="form-textarea" />
+ </el-form-item>
+ <el-form-item label="涓婁紶鏂囦欢"
+ class="form-item"
+ :span="24">
+ <el-upload class="upload-demo upload-block"
+ action="#"
+ :on-preview="handlePreview"
+ :on-remove="handleRemove"
+ :file-list="getProcessInfo(parseInt(activeProcessId)).files || []"
+ :auto-upload="false"
+ :accept="'.jpg,.png'"
+ :max-size="500000"
+ :on-change="handleFileChange">
+ <el-button type="primary"
+ :icon="Upload">鐐瑰嚮涓婁紶</el-button>
+ <template #tip>
+ <div class="el-upload__tip">
+ 鍙兘涓婁紶jpg/png鏂囦欢锛屼笖涓嶈秴杩�500kb
+ </div>
+ </template>
+ </el-upload>
+ </el-form-item>
+ </div>
+ </el-form>
+ </div>
+ </div>
+ <!-- BOM淇℃伅 -->
+ <div class="param-section"
+ v-if="getProcessStructures(parseInt(activeProcessId)).length > 0">
+ <div class="section-header">
+ <h4 class="section-title">BOM淇℃伅</h4>
+ </div>
+ <div class="param-form">
+ <el-form :label-position="'top'">
+ <div class="form-grid">
+ <el-form-item v-for="item in getProcessStructures(parseInt(activeProcessId))"
+ :key="item.id"
+ :label="`${item.productName} ${item.model}`"
+ class="form-item">
+ <div class="consumable-input-group">
+ <el-input-number v-model="getProcessInfo(parseInt(activeProcessId)).consumables[item.id]"
+ :min="0"
+ :model-value="getConsumableValue(parseInt(activeProcessId), item.id)"
+ @change="val => getProcessInfo(parseInt(activeProcessId)).consumables[item.id] = val"
+ class="consumable-input" />
+ <span class="consumable-unit">{{ item.unit }}</span>
+ </div>
+ </el-form-item>
+ </div>
+ </el-form>
+ </div>
+ </div>
+ <!-- 鍙傛暟缁勫垪琛� -->
+ <div class="param-section">
+ <div class="section-header">
+ <h4 class="section-title">鍙傛暟缁勭鐞�</h4>
+ <div class="section-actions">
+ <el-switch v-model="useTableView"
+ active-text="琛ㄦ牸瑙嗗浘"
+ inactive-text="鍗$墖瑙嗗浘"
+ inline-prompt />
+ <el-button type="primary"
+ @click="addParamGroup(parseInt(activeProcessId))"
+ :icon="Plus">
+ 鏂板鍙傛暟缁�
+ </el-button>
+ </div>
+ </div>
+ <!-- 鍗$墖瑙嗗浘 -->
+ <div v-if="!useTableView"
+ class="param-cards">
+ <div v-for="(group, index) in form.paramGroups[activeProcessId] || []"
+ :key="index"
+ class="param-card">
+ <div class="card-header">
+ <span class="card-title">鍙傛暟缁� {{ index + 1 }}</span>
+ <el-button type="danger"
+ size="small"
+ @click="removeParamGroup(parseInt(activeProcessId), index)"
+ v-if="(form.paramGroups[activeProcessId] || []).length > 1"
+ circle>
+ <el-icon>
+ <Delete />
+ </el-icon>
+ </el-button>
+ </div>
+ <div class="card-body">
+ <div class="param-grid">
+ <el-form-item v-for="param in params"
+ :key="param.id"
+ :label="param.paramName"
+ :label-width="120"
+ :required="param.isRequired"
+ :prop="`paramGroups.${activeProcessId}.${index}.${param.id}`"
+ :rules="param.isRequired ? [{ required: true, message: `璇疯緭鍏�${param.paramName}`, trigger: 'blur' }] : []"
+ class="param-item">
+ <template v-if="param.paramType == '1'">
+ <!-- 鏁板瓧绫诲瀷 -->
+ <div class="param-input-group">
+ <el-input-number v-model="form.paramGroups[activeProcessId][index][param.id]"
+ controls-position="right"
+ :precision="getPrecision(param.paramFormat)"
+ class="param-input" />
+ <span v-if="param.unit && param.unit != '/'"
+ class="param-unit">
+ {{ param.unit }}
+ </span>
+ </div>
+ </template>
+ <template v-else-if="param.paramType == '2'">
+ <!-- 鏂囨湰绫诲瀷 -->
+ <div class="param-input-group">
+ <el-input v-model="form.paramGroups[activeProcessId][index][param.id]"
+ class="param-input" />
+ <span v-if="param.unit && param.unit != '/'"
+ class="param-unit">
+ {{ param.unit }}
+ </span>
+ </div>
+ </template>
+ <template v-else-if="param.paramType == '3'">
+ <!-- 瀛楀吀绫诲瀷 -->
+ <div class="param-input-group">
+ <el-select v-model="form.paramGroups[activeProcessId][index][param.id]"
+ placeholder="璇烽�夋嫨"
+ class="param-select"
+ style="width: 100%">
+ <el-option v-for="option in dictOptions[param.paramFormat] || []"
+ :key="option.dictValue"
+ :label="option.dictLabel"
+ :value="option.dictValue" />
+ </el-select>
+ <span v-if="param.unit && param.unit != '/'"
+ class="param-unit">
+ {{ param.unit }}
+ </span>
+ </div>
+ </template>
+ <template v-else-if="param.paramType == '4'">
+ <!-- 鏃ユ湡绫诲瀷 -->
+ <div class="param-input-group">
+ <el-date-picker :value-format="param.paramFormat"
+ :format="param.paramFormat"
+ :type="param.paramFormat=='YYYY-MM-DD'?'date':'datetime'"
+ v-model="form.paramGroups[activeProcessId][index][param.id]"
+ class="param-input" />
+ <span v-if="param.unit && param.unit != '/'"
+ class="param-unit">
+ {{ param.unit }}
+ </span>
+ </div>
+ </template>
+ <template v-else>
+ <!-- 鍏朵粬绫诲瀷 -->
+ <div class="param-input-group">
+ <el-input v-model="form.paramGroups[activeProcessId][index][param.id]"
+ class="param-input" />
+ <span v-if="param.unit && param.unit != '/'"
+ class="param-unit">
+ {{ param.unit }}
+ </span>
+ </div>
+ </template>
+ </el-form-item>
+ </div>
+ </div>
+ </div>
+ </div>
+ <!-- 琛ㄦ牸瑙嗗浘 -->
+ <div v-else
+ class="param-table">
+ <el-table :data="form.paramGroups[activeProcessId] || []"
+ style="width: 100%"
+ class="table-view">
+ <!-- 鎿嶄綔鍒� -->
+ <el-table-column label="鎿嶄綔"
+ width="100"
+ fixed>
+ <template #default="{ $index }">
+ <el-button type="danger"
+ size="small"
+ @click="removeParamGroup(parseInt(activeProcessId), $index)"
+ circle>
+ <el-icon>
+ <Delete />
+ </el-icon>
+ </el-button>
+ </template>
+ </el-table-column>
+ <!-- 鍙傛暟鍒� -->
+ <el-table-column v-for="param in params"
+ :key="param.id"
+ :min-width="200">
+ <template #header>
+ <span :class="{ 'required-label': param.isRequired }">{{ param.paramName }}</span>
+ </template>
+ <template #default="{ row }">
+ <template v-if="param.paramType == '1'">
+ <!-- 鏁板瓧绫诲瀷 -->
+ <el-input-number v-model="row[param.id]"
+ controls-position="right"
+ :precision="getPrecision(param.paramFormat)"
+ class="table-input" />
+ </template>
+ <template v-else-if="param.paramType == '2'">
+ <!-- 鏂囨湰绫诲瀷 -->
+ <el-input v-model="row[param.id]"
+ class="table-input" />
+ </template>
+ <template v-else-if="param.paramType == '3'">
+ <!-- 瀛楀吀绫诲瀷 -->
+ <el-select v-model="row[param.id]"
+ placeholder="璇烽�夋嫨"
+ class="table-select">
+ <el-option v-for="option in dictOptions[param.paramFormat] || []"
+ :key="option.dictValue"
+ :label="option.dictLabel"
+ :value="option.dictValue" />
+ </el-select>
+ </template>
+ <template v-else-if="param.paramType == '4'">
+ <!-- 鏃ユ湡绫诲瀷 -->
+ <el-date-picker :value-format="param.paramFormat"
+ :format="param.paramFormat"
+ width="100%"
+ :type="param.paramFormat=='YYYY-MM-DD'?'date':'datetime'"
+ v-model="row[param.id]"
+ class="table-input table-select" />
+ </template>
+ <template v-else>
+ <!-- 鍏朵粬绫诲瀷 -->
+ <el-input v-model="row[param.id]"
+ class="table-input" />
+ </template>
+ </template>
+ </el-table-column>
+ </el-table>
+ </div>
+ <!-- 鏂板鍙傛暟缁勬寜閽� -->
+ <!-- <div class="param-actions">
+ <el-button type="primary"
+ @click="addParamGroup(parseInt(activeProcessId))"
+ :icon="Plus">
+ 鏂板鍙傛暟缁�
+ </el-button>
+ </div> -->
+ </div>
+ </div>
+ <div v-else
+ class="empty-process">
+ <el-empty description="璇烽�夋嫨涓�涓伐搴�"
+ :image-size="120" />
+ </div>
+ </div>
+ </div>
+ </div>
+ <!-- 绗洓姝ワ細濉啓浜ч噺淇℃伅 -->
+ <div v-else-if="activeStep === 3"
+ class="step-panel">
+ <div class="panel-header">
+ <div>
+ <h3 class="panel-title">濉啓浜ч噺淇℃伅</h3>
+ <p class="panel-subtitle">璇峰~鍐欐湰娆℃姤宸ョ殑浜ч噺鏁版嵁</p>
+ </div>
+ <div class="header-actions">
+ <el-button @click="activeStep--"
+ v-if="activeStep > 0"
+ :disabled="isSubmitting">
+ <el-icon>
+ <ArrowLeft />
+ </el-icon> 涓婁竴姝�
+ </el-button>
+ <el-button type="primary"
+ @click="handleSubmit"
+ v-if="activeStep === 3"
+ :loading="isSubmitting">
+ <el-icon v-if="!isSubmitting">
+ <Check />
+ </el-icon>
+ <el-icon v-else>
+ <Loading />
+ </el-icon>
+ {{ isSubmitting ? '鎻愪氦涓�...' : '纭鎻愪氦' }}
+ </el-button>
+ </div>
+ </div>
+ <el-form :model="form"
+ :rules="rules"
+ ref="formRef"
+ :label-position="'top'"
+ class="form-container">
+ <div class="form-grid1">
+ <el-form-item label="浜у嚭鏂归噺"
+ prop="outputVolume"
+ required
+ class="form-item">
+ <div class="volume-input-group">
+ <el-input-number v-model="form.outputVolume"
+ :min="0"
+ :precision="2"
+ @change="handleVolumeChange"
+ class="volume-input" />
+ <span class="volume-unit">鏂�</span>
+ </div>
+ </el-form-item>
+ <el-form-item label="涓嶅悎鏍兼柟閲�"
+ prop="unqualifiedVolume"
+ required
+ class="form-item">
+ <div class="volume-input-group">
+ <el-input-number v-model="form.unqualifiedVolume"
+ :min="0"
+ :precision="2"
+ @change="handleVolumeChange"
+ class="volume-input" />
+ <span class="volume-unit">鏂�</span>
+ </div>
+ </el-form-item>
+ <el-form-item label="瀹屾垚鏂归噺"
+ prop="completedVolume"
+ required
+ class="form-item">
+ <div class="volume-input-group">
+ <el-input-number v-model="form.completedVolume"
+ :min="0"
+ :precision="2"
+ class="volume-input" />
+ <span class="volume-unit">鏂�</span>
+ </div>
+ </el-form-item>
+ </div>
+ </el-form>
+ </div>
+ </div>
+ <!-- 搴曢儴鎸夐挳 -->
+ </div>
+</template>
+
+<script setup>
+ import { ref, reactive, computed, watch, onMounted } from "vue";
+ import { ElMessage, ElEmpty } from "element-plus";
+ import { useRouter, useRoute } from "vue-router";
+ import { getDicts } from "@/api/system/dict/data";
+ import { productOrderListPage } from "@/api/productionManagement/productionOrder.js";
+ import { productionRecordAdd } from "@/api/productionManagement/productProcessRoute.js";
+ import { userListNoPage } from "@/api/system/user.js";
+ import { getInfo } from "@/api/login.js";
+ import {
+ Check,
+ Close,
+ Delete,
+ Plus,
+ ArrowLeft,
+ ArrowRight,
+ Loading,
+ Upload,
+ } from "@element-plus/icons-vue";
+
+ const router = useRouter();
+
+ // 浠庤矾鐢卞弬鏁拌幏鍙栨暟鎹�
+ const route = useRoute();
+ const data = route.query.data ? JSON.parse(route.query.data) : {};
+
+ const dialogTitle = computed(() => (data.id ? "缂栬緫鎶ュ伐" : "鏂板鎶ュ伐"));
+
+ const formRef = ref(null);
+ const isSubmitting = ref(false);
+ const orderLoading = ref(false);
+ const processLoading = ref(false);
+ const activeStep = ref(0);
+
+ const steps = [
+ { title: "閫夋嫨鐢熶骇璁㈠崟", description: "閫夋嫨闇�瑕佹姤宸ョ殑鐢熶骇璁㈠崟" },
+ { title: "濉啓鍩虹淇℃伅", description: "濉啓鎶ュ伐鐨勫熀鏈俊鎭�" },
+ { title: "鏌ョ湅宸ュ簭鍙傛暟", description: "濉啓鍚勫伐搴忕殑鍙傛暟淇℃伅" },
+ { title: "濉啓浜ч噺淇℃伅", description: "濉啓鏈鎶ュ伐鐨勪骇閲忔暟鎹�" },
+ ];
+
+ // 璁$畻褰撳墠宸ュ簭鐨勫弬鏁扮粍鏁伴噺
+ const paramGroupCount = computed(() => {
+ if (!activeProcessId.value) return 0;
+ return (form.paramGroups[activeProcessId.value] || []).length;
+ });
+
+ const orderId = ref(data.orderId || "");
+ const processId = ref(data.processId || "");
+ const activeProcessId = ref("");
+ const orderList = ref([]);
+ const processList = ref([]);
+ const params = ref([]);
+ const dictOptions = ref({});
+ const userList = ref([]);
+ const userLoading = ref(false);
+ const useTableView = ref(false); // 鎺у埗鏄惁浣跨敤琛ㄦ牸瑙嗗浘
+
+ const form = reactive({
+ id: data.id || undefined,
+ orderId: data.orderId || "",
+ npsNo: data.npsNo || "",
+ teamName: data.teamName || "鐧界彮",
+ materialCode: data.materialCode || "",
+ productName: data.productName || "",
+ specification: data.specification || "",
+ outputVolume: data.outputVolume || 0,
+ unqualifiedVolume: data.unqualifiedVolume || 0,
+ completedVolume: data.completedVolume || 0,
+ createBy: data.createBy || "褰撳墠鐧诲綍浜�",
+ createTime: data.createTime || new Date(),
+ paramGroups: data.paramGroups || {}, // 瀛樺偍姣忎釜宸ュ簭鐨勫弬鏁扮粍
+ processInfo: data.processInfo || {}, // 瀛樺偍姣忎釜宸ュ簭鐨勫熀鏈俊鎭�
+ });
+
+ const rules = {
+ teamName: [{ required: true, message: "璇烽�夋嫨鐝粍", trigger: "blur" }],
+ outputVolume: [
+ { required: true, message: "璇疯緭鍏ヤ骇鍑烘柟閲�", trigger: "blur" },
+ ],
+ unqualifiedVolume: [
+ { required: true, message: "璇疯緭鍏ヤ笉鍚堟牸鏂归噺", trigger: "blur" },
+ ],
+ completedVolume: [
+ { required: true, message: "璇疯緭鍏ュ畬鎴愭柟閲�", trigger: "blur" },
+ ],
+ createBy: [{ required: true, message: "璇疯緭鍏ュ垱寤轰汉", trigger: "blur" }],
+ };
+
+ // 鍔犺浇鐢熶骇璁㈠崟鍒楄〃
+ const loadOrders = () => {
+ orderLoading.value = true;
+ productOrderListPage({ pageNum: 1, pageSize: 100 })
+ .then(res => {
+ orderList.value = res.data.records || [];
+ })
+ .finally(() => {
+ orderLoading.value = false;
+ });
+ };
+ const handleVolumeChange = () => {
+ form.completedVolume = form.outputVolume - form.unqualifiedVolume;
+ };
+
+ // 澶勭悊鐢熶骇璁㈠崟閫夋嫨
+ const handleOrderChange = val => {
+ if (val) {
+ const order = orderList.value.find(item => item.id === val);
+ if (order) {
+ form.orderId = val;
+ form.npsNo = order.npsNo;
+ form.materialCode = order.materialCode;
+ form.productName = order.productName;
+ form.specification = order.model;
+ }
+ // 鍔犺浇宸ュ簭鍒楄〃
+ loadProcesses(val);
+ } else {
+ form.orderId = "";
+ form.npsNo = "";
+ form.materialCode = "";
+ form.productName = "";
+ form.specification = "";
+ processId.value = "";
+ activeProcessId.value = "";
+ processList.value = [];
+ params.value = [];
+ form.params = {};
+ }
+ };
+
+ // 鍔犺浇宸ュ簭鍒楄〃
+ const loadProcesses = orderId => {
+ processLoading.value = true;
+ // 璋冪敤鏂扮殑鎺ュ彛
+ productionRecordAdd(orderId)
+ .then(res => {
+ if (res.code === 200) {
+ const data = res.data;
+ // 鎻愬彇宸ュ簭鍒楄〃
+ processList.value = data.productionOrderRouteItemVos || [];
+ // 瀛樺偍宸ュ簭缁撴瀯鏁版嵁
+ form.processStructures = {};
+ processList.value.forEach(process => {
+ form.processStructures[process.processId] =
+ process.orderStructureVos || [];
+ });
+ // 濡傛灉鏈夊伐搴忥紝榛樿閫夋嫨绗竴涓�
+ if (processList.value.length > 0) {
+ const firstProcess = processList.value[0];
+ activeProcessId.value = firstProcess.processId + "";
+ processId.value = firstProcess.processId;
+ form.processId = firstProcess.processId;
+ // 鍔犺浇绗竴涓伐搴忕殑鍙傛暟
+ loadParams(firstProcess.processId, orderId);
+ }
+ }
+ })
+ .finally(() => {
+ processLoading.value = false;
+ });
+ };
+
+ // 澶勭悊宸ュ簭瀵艰埅鐐瑰嚮
+ const handleProcessClick = selectedProcessId => {
+ activeProcessId.value = selectedProcessId + "";
+ processId.value = selectedProcessId;
+ form.processId = selectedProcessId;
+ // 鍔犺浇鍙傛暟鍒楄〃
+ loadParams(selectedProcessId, form.orderId);
+ };
+
+ // 鑾峰彇宸ュ簭鍩烘湰淇℃伅锛屼笉瀛樺湪鍒欏垵濮嬪寲
+ const getProcessInfo = processId => {
+ if (!form.processInfo) {
+ form.processInfo = {};
+ }
+ if (!form.processInfo[processId]) {
+ form.processInfo[processId] = {
+ postPersonnel: "",
+ equipmentAbnormality: "",
+ equipmentHandling: "",
+ processInstructions: "",
+ files: [],
+ consumables: {},
+ };
+ }
+ return form.processInfo[processId];
+ };
+
+ // 鑾峰彇宸ュ簭缁撴瀯鏁版嵁锛圔OM鍒楄〃锛�
+ const getProcessStructures = processId => {
+ return form.processStructures && form.processStructures[processId]
+ ? form.processStructures[processId]
+ : [];
+ };
+
+ // 鑾峰彇娑堣�楀搧鏁伴噺锛岄粯璁や负0
+ const getConsumableValue = (processId, itemId) => {
+ const processInfo = getProcessInfo(processId);
+ if (!processInfo.consumables[itemId]) {
+ processInfo.consumables[itemId] = 0;
+ }
+ return processInfo.consumables[itemId];
+ };
+
+ // 澶勭悊鏂囦欢棰勮
+ const handlePreview = file => {
+ // 妫�鏌ユ槸鍚︽槸鍥剧墖鏂囦欢
+ if (file.raw && file.raw.type.startsWith("image/")) {
+ // 鍒涘缓鍥剧墖棰勮
+ const imageUrl = URL.createObjectURL(file.raw);
+ const image = new Image();
+ image.src = imageUrl;
+
+ // 鍒涘缓棰勮瀹瑰櫒
+ const previewContainer = document.createElement("div");
+ previewContainer.style.position = "fixed";
+ previewContainer.style.top = "0";
+ previewContainer.style.left = "0";
+ previewContainer.style.width = "100%";
+ previewContainer.style.height = "100%";
+ previewContainer.style.backgroundColor = "rgba(0, 0, 0, 0.8)";
+ previewContainer.style.display = "flex";
+ previewContainer.style.alignItems = "center";
+ previewContainer.style.justifyContent = "center";
+ previewContainer.style.zIndex = "9999";
+ previewContainer.style.cursor = "pointer";
+
+ // 娣诲姞鍥剧墖
+ previewContainer.appendChild(image);
+ image.style.maxWidth = "90%";
+ image.style.maxHeight = "90%";
+
+ // 娣诲姞鍏抽棴鍔熻兘
+ previewContainer.addEventListener("click", () => {
+ URL.revokeObjectURL(imageUrl);
+ document.body.removeChild(previewContainer);
+ });
+
+ // 娣诲姞鍒版枃妗�
+ document.body.appendChild(previewContainer);
+ }
+ };
+
+ // 澶勭悊鏂囦欢鍒犻櫎
+ const handleRemove = (file, fileList) => {
+ const processId = parseInt(activeProcessId.value);
+ if (processId) {
+ const processInfo = getProcessInfo(processId);
+ processInfo.files = fileList;
+ }
+ };
+
+ // 澶勭悊鏂囦欢鍙樻洿
+ const handleFileChange = (file, fileList) => {
+ const processId = parseInt(activeProcessId.value);
+ if (processId) {
+ const processInfo = getProcessInfo(processId);
+ processInfo.files = fileList;
+ }
+ };
+
+ // 鑾峰彇瀛楀吀鏁版嵁
+ const getDictOptions = async dictType => {
+ if (!dictType) return [];
+ if (dictOptions.value[dictType]) return dictOptions.value[dictType];
+
+ try {
+ const res = await getDicts(dictType);
+ if (res.code === 200) {
+ dictOptions.value[dictType] = res.data;
+ return res.data;
+ }
+ return [];
+ } catch (error) {
+ console.error("鑾峰彇瀛楀吀鏁版嵁澶辫触:", error);
+ return [];
+ }
+ };
+
+ // 鍔犺浇鍙傛暟鍒楄〃
+ const loadParams = (processId, orderId) => {
+ // 浠庡凡鍔犺浇鐨勫伐搴忔暟鎹腑鑾峰彇鍙傛暟鍒楄〃
+ const process = processList.value.find(
+ p => p.processId === parseInt(processId)
+ );
+ if (process) {
+ params.value = process.orderRouteItemParaVos || [];
+
+ // 鍒濆鍖栧弬鏁扮粍
+ if (!form.paramGroups[processId]) {
+ form.paramGroups[processId] = [];
+ }
+ // 濡傛灉娌℃湁鍙傛暟缁勶紝娣诲姞涓�涓粯璁ゅ弬鏁扮粍
+ if (form.paramGroups[processId].length === 0) {
+ const defaultGroup = {};
+ for (const param of params.value) {
+ defaultGroup[param.id] = param.standardValue || "";
+ // 濡傛灉鏄瓧鍏哥被鍨嬪弬鏁帮紝鑾峰彇瀛楀吀鏁版嵁
+ if (param.paramType == "3" && param.paramFormat) {
+ getDictOptions(param.paramFormat);
+ }
+ }
+ form.paramGroups[processId].push(defaultGroup);
+ }
+ }
+ };
+
+ // 鑾峰彇灏忔暟绮惧害
+ const getPrecision = format => {
+ if (!format) return 2;
+ const match = format.match(/\.(\d+)/);
+ return match ? parseInt(match[1].length) : 2;
+ };
+
+ // 澶勭悊涓嬩竴姝�
+ const handleNextStep = () => {
+ if (activeStep.value === 0) {
+ // 绗竴姝ワ細楠岃瘉鐢熶骇璁㈠崟閫夋嫨
+ if (!orderId.value) {
+ ElMessage.error("璇烽�夋嫨鐢熶骇璁㈠崟");
+ return;
+ }
+ activeStep.value = 1;
+ } else if (activeStep.value === 1) {
+ // 绗簩姝ワ細楠岃瘉鍩虹淇℃伅
+ formRef.value.validate(valid => {
+ if (valid) {
+ activeStep.value = 2;
+ }
+ });
+ } else if (activeStep.value === 2) {
+ // 绗笁姝ワ細楠岃瘉鍙傛暟蹇呭~椤�
+ let isValid = true;
+ let errorMessage = "";
+
+ // 閬嶅巻鎵�鏈夊伐搴�
+ for (const process of processList.value) {
+ const processId = process.processId;
+ const paramGroups = form.paramGroups[processId] || [];
+ const processParams = process.orderRouteItemParaVos || [];
+
+ // 鑾峰彇蹇呭~鍙傛暟
+ const requiredParams = processParams.filter(p => p.isRequired);
+
+ if (requiredParams.length > 0) {
+ // 妫�鏌ユ瘡涓弬鏁扮粍涓殑蹇呭~鍙傛暟
+ for (
+ let groupIndex = 0;
+ groupIndex < paramGroups.length;
+ groupIndex++
+ ) {
+ const group = paramGroups[groupIndex];
+ for (const param of requiredParams) {
+ const value = group[param.id];
+ if (value === undefined || value === null || value === "") {
+ isValid = false;
+ errorMessage = `宸ュ簭銆�${process.processName}銆戝弬鏁扮粍${
+ groupIndex + 1
+ }鐨勩��${param.paramName}銆戜负蹇呭~椤筦;
+ break;
+ }
+ }
+ if (!isValid) break;
+ }
+ }
+ if (!isValid) break;
+ }
+
+ if (!isValid) {
+ ElMessage.error(errorMessage);
+ return;
+ }
+
+ activeStep.value = 3;
+ }
+ };
+
+ // 澶勭悊鎻愪氦
+ const handleSubmit = () => {
+ formRef.value.validate(valid => {
+ if (valid) {
+ isSubmitting.value = true;
+ // 杩欓噷鍙互璋冪敤API杩涜鎻愪氦
+ setTimeout(() => {
+ ElMessage.success(data.id ? "淇敼鎴愬姛" : "鏂板鎴愬姛");
+ router.back();
+ isSubmitting.value = false;
+ }, 1000);
+ }
+ });
+ };
+
+ // 澶勭悊鍙栨秷
+ const handleCancel = () => {
+ router.back();
+ };
+
+ // 鏂板鍙傛暟缁�
+ const addParamGroup = processId => {
+ if (!form.paramGroups[processId]) {
+ form.paramGroups[processId] = [];
+ }
+ // 鍒涘缓涓�涓柊鐨勫弬鏁扮粍锛屼娇鐢ㄩ粯璁ゅ��
+ const newGroup = {};
+ params.value.forEach(param => {
+ newGroup[param.id] = param.standardValue || "";
+ });
+ form.paramGroups[processId].push(newGroup);
+ };
+
+ // 鍒犻櫎鍙傛暟缁�
+ const removeParamGroup = (processId, index) => {
+ if (form.paramGroups[processId] && form.paramGroups[processId].length > 1) {
+ form.paramGroups[processId].splice(index, 1);
+ }
+ };
+
+ // 鍔犺浇鐢ㄦ埛鍒楄〃
+ const loadUsers = () => {
+ userLoading.value = true;
+ userListNoPage()
+ .then(res => {
+ userList.value = res.data || [];
+ })
+ .finally(() => {
+ userLoading.value = false;
+ });
+ };
+
+ // 鑾峰彇褰撳墠鐧诲綍浜轰俊鎭�
+ const getCurrentUser = async () => {
+ try {
+ const res = await getInfo();
+ if (res && res.user) {
+ form.createBy = res.user.nickName || res.user.userName;
+ }
+ } catch (error) {
+ console.error("鑾峰彇褰撳墠鐧诲綍浜轰俊鎭け璐�:", error);
+ }
+ };
+
+ // 鍒濆鍖�
+ const init = () => {
+ // 鏃犺鏂板杩樻槸缂栬緫锛岄兘鍔犺浇璁㈠崟鍒楄〃鍜岀敤鎴峰垪琛�
+ loadOrders();
+ loadUsers();
+ getCurrentUser();
+
+ if (data.id) {
+ // 缂栬緫鏃惰缃〃鍗曟暟鎹�
+ Object.assign(form, data);
+ // 璁剧疆orderId
+ orderId.value = data.orderId || "";
+ // 濡傛灉鏈夎鍗旾D锛屽姞杞藉伐搴忓拰鍙傛暟
+ if (data.orderId) {
+ // 妯℃嫙閫夋嫨璁㈠崟鐨勬搷浣滐紝瑙﹀彂鏁版嵁鍔犺浇
+ setTimeout(() => {
+ handleOrderChange(data.orderId);
+ }, 100);
+ }
+ } else {
+ // 鏂板鏃惰缃粯璁ゅ��
+ form.createTime = new Date();
+ }
+ // 濮嬬粓浠庣涓�姝ュ紑濮�
+ activeStep.value = 0;
+ };
+
+ // 椤甸潰鍔犺浇鏃跺垵濮嬪寲
+ onMounted(() => {
+ init();
+ });
+</script>
+
+<style scoped>
+ /* 椤甸潰瀹瑰櫒 */
+ .reporting-page {
+ min-height: 100vh;
+ padding: 24px;
+ background-color: #f0f2f5;
+ }
+
+ /* 椤甸潰澶撮儴 */
+ .page-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 32px;
+ padding-bottom: 16px;
+ border-bottom: 1px solid #e8e8e8;
+ }
+
+ .page-title {
+ margin: 0;
+ font-size: 24px;
+ font-weight: 600;
+ color: #1f2329;
+ }
+
+ .header-actions {
+ display: flex;
+ gap: 12px;
+ }
+
+ /* 姝ラ鎸囩ず鍣� */
+ .step-indicator {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 32px;
+ padding: 0 16px;
+ padding-top: 16px;
+ }
+
+ .step-item {
+ display: flex;
+ align-items: center;
+ flex: 1;
+ position: relative;
+ }
+
+ .step-circle {
+ width: 40px;
+ height: 40px;
+ border-radius: 50%;
+ background-color: #f0f0f0;
+ color: #999;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 16px;
+ font-weight: 600;
+ z-index: 2;
+ transition: all 0.3s ease;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+ }
+
+ .step-item.active .step-circle {
+ background-color: #1890ff;
+ color: white;
+ box-shadow: 0 0 0 8px rgba(24, 144, 255, 0.1);
+ }
+
+ .step-item.completed .step-circle {
+ background-color: #52c41a;
+ color: white;
+ box-shadow: 0 0 0 8px rgba(82, 196, 26, 0.1);
+ }
+
+ .step-check {
+ font-size: 20px;
+ }
+
+ .step-content {
+ margin-left: 16px;
+ flex: 1;
+ }
+
+ .step-title {
+ font-size: 14px;
+ font-weight: 600;
+ color: #666;
+ margin-bottom: 4px;
+ transition: color 0.3s ease;
+ }
+
+ .step-item.active .step-title {
+ color: #1890ff;
+ }
+
+ .step-item.completed .step-title {
+ color: #52c41a;
+ }
+
+ .step-description {
+ font-size: 12px;
+ color: #999;
+ }
+
+ .step-line {
+ position: absolute;
+ top: 20px;
+ left: 50%;
+ right: -50%;
+ height: 2px;
+ background-color: #e8e8e8;
+ z-index: 1;
+ transition: all 0.3s ease;
+ }
+
+ .step-item.completed .step-line {
+ background-color: #52c41a;
+ }
+
+ /* 椤甸潰鍐呭 */
+ .page-content {
+ background-color: white;
+ border-radius: 12px;
+ padding: 0;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
+ margin-bottom: 32px;
+ overflow: hidden;
+ }
+
+ /* 姝ラ闈㈡澘 */
+ .step-panel {
+ padding: 32px;
+ }
+
+ .panel-header {
+ margin-bottom: 24px;
+ display: flex;
+ justify-content: space-between;
+ align-items: flex-start;
+ }
+
+ .panel-title {
+ font-size: 18px;
+ font-weight: 600;
+ color: #1f2329;
+ margin: 0 0 8px 0;
+ }
+
+ .panel-subtitle {
+ font-size: 14px;
+ color: #666;
+ margin: 0;
+ }
+
+ .header-actions {
+ display: flex;
+ gap: 12px;
+ align-items: center;
+ }
+
+ /* 琛ㄥ崟瀹瑰櫒 */
+ .form-container {
+ width: 100%;
+ }
+
+ /* 涓婁紶缁勪欢鏍峰紡 */
+ .upload-block {
+ display: block;
+ }
+
+ .upload-block .el-upload__tip {
+ margin-top: 8px;
+ }
+
+ /* BOM杈撳叆缁勬牱寮� */
+ .consumable-input-group {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ }
+
+ .consumable-input {
+ flex: 1;
+ }
+
+ .consumable-unit {
+ font-size: 14px;
+ color: #666;
+ white-space: nowrap;
+ }
+
+ /* 蹇呭~鏍囪瘑鏍峰紡 */
+ .required-label::before {
+ content: "*";
+ color: #f56c6c;
+ margin-right: 4px;
+ }
+
+ .form-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
+ gap: 20px;
+ }
+ .form-grid1 {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(400px, 1fr));
+ gap: 20px;
+ }
+
+ .form-item {
+ margin-bottom: 0;
+ }
+
+ .form-select,
+ .form-input {
+ width: 100%;
+ }
+
+ .form-textarea {
+ width: 100%;
+ resize: vertical;
+ }
+
+ /* 浜ч噺杈撳叆缁� */
+ .volume-input-group {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ }
+
+ .volume-input {
+ flex: 1;
+ width: 100%;
+ }
+
+ .volume-unit {
+ font-size: 14px;
+ color: #666;
+ white-space: nowrap;
+ }
+
+ /* 宸ュ簭瀹瑰櫒 */
+ .process-container {
+ display: flex;
+ gap: 24px;
+ min-height: 500px;
+ }
+
+ /* 宸ュ簭瀵艰埅 */
+ .process-nav {
+ width: 200px;
+ background-color: #fafafa;
+ border-radius: 8px;
+ padding: 16px;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
+ overflow-y: auto;
+ }
+
+ .process-nav-item {
+ padding: 12px 16px;
+ margin-bottom: 8px;
+ border-radius: 6px;
+ cursor: pointer;
+ transition: all 0.3s ease;
+ font-size: 14px;
+ font-weight: 500;
+ color: #666;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ }
+
+ .process-nav-item:hover {
+ background-color: #e6f7ff;
+ color: #1890ff;
+ }
+
+ .process-nav-item.active {
+ background-color: #1890ff;
+ color: white;
+ box-shadow: 0 2px 8px rgba(24, 144, 255, 0.3);
+ }
+
+ .process-badge {
+ font-size: 12px;
+ background-color: rgba(255, 255, 255, 0.2);
+ padding: 2px 8px;
+ border-radius: 10px;
+ }
+
+ /* 宸ュ簭鍐呭 */
+ .process-content {
+ flex: 1;
+ overflow-y: auto;
+ }
+
+ .empty-process {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 400px;
+ }
+
+ /* 鍙傛暟閮ㄥ垎 */
+ .param-section {
+ margin-bottom: 32px;
+ padding: 24px;
+ background-color: #fafafa;
+ border-radius: 8px;
+ }
+
+ .section-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 16px;
+ }
+
+ .section-title {
+ font-size: 16px;
+ font-weight: 600;
+ color: #1f2329;
+ margin: 0;
+ }
+
+ .section-actions {
+ display: flex;
+ gap: 8px;
+ }
+
+ /* 鍙傛暟琛ㄥ崟 */
+ .param-form {
+ background-color: white;
+ padding: 20px;
+ border-radius: 8px;
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
+ }
+
+ /* 鍙傛暟鍗$墖 */
+ .param-cards {
+ display: flex;
+ flex-direction: column;
+ gap: 16px;
+ }
+
+ .param-card {
+ background-color: white;
+ border-radius: 8px;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
+ overflow: hidden;
+ transition: all 0.3s ease;
+ }
+
+ .param-card:hover {
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
+ transform: translateY(-2px);
+ }
+
+ .card-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 16px 20px;
+ background-color: #fafafa;
+ border-bottom: 1px solid #e8e8e8;
+ }
+
+ .card-title {
+ font-size: 14px;
+ font-weight: 600;
+ color: #1f2329;
+ }
+
+ .card-body {
+ padding: 20px;
+ }
+
+ /* 鍙傛暟缃戞牸 */
+ .param-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
+ gap: 16px;
+ }
+
+ .param-item {
+ margin-bottom: 0;
+ }
+
+ .param-input-group {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ width: 100%;
+ }
+
+ .param-input,
+ .param-select {
+ flex: 1;
+ }
+
+ .param-unit {
+ font-size: 14px;
+ color: #666;
+ white-space: nowrap;
+ }
+
+ /* 琛ㄦ牸瑙嗗浘 */
+ .param-table {
+ margin: 16px 0;
+ }
+
+ .table-view {
+ border-radius: 8px;
+ overflow: hidden;
+ }
+
+ .table-view th {
+ background-color: #fafafa;
+ font-weight: 600;
+ }
+
+ .table-input,
+ .table-select {
+ width: 100%;
+ }
+
+ /* 鍙傛暟鎿嶄綔 */
+ .param-actions {
+ margin-top: 16px;
+ display: flex;
+ justify-content: flex-end;
+ }
+
+ /* 椤甸潰搴曢儴 */
+ .page-footer {
+ display: flex;
+ justify-content: center;
+ padding: 24px;
+ background-color: white;
+ border-top: 1px solid #e8e8e8;
+ border-radius: 0 0 12px 12px;
+ }
+
+ .footer-actions {
+ display: flex;
+ gap: 12px;
+ }
+
+ /* 鍝嶅簲寮忚璁� */
+ @media (max-width: 1024px) {
+ .form-grid {
+ grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
+ }
+
+ .param-grid {
+ grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
+ }
+ }
+
+ @media (max-width: 768px) {
+ .reporting-page {
+ padding: 16px;
+ }
+
+ .step-indicator {
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 16px;
+ padding: 0;
+ }
+
+ .step-item {
+ flex-direction: row;
+ width: 100%;
+ }
+
+ .step-line {
+ display: none;
+ }
+
+ .step-panel {
+ padding: 20px;
+ }
+
+ .form-grid {
+ grid-template-columns: 1fr;
+ }
+
+ .process-container {
+ flex-direction: column;
+ }
+
+ .process-nav {
+ width: 100%;
+ margin-bottom: 16px;
+ }
+
+ .param-grid {
+ grid-template-columns: 1fr;
+ }
+
+ .footer-actions {
+ flex-direction: column;
+ width: 100%;
+ }
+
+ .footer-actions button {
+ width: 100%;
+ }
+ }
+
+ /* 婊氬姩鏉℃牱寮� */
+ .process-nav::-webkit-scrollbar,
+ .process-content::-webkit-scrollbar {
+ width: 6px;
+ height: 6px;
+ }
+
+ .process-nav::-webkit-scrollbar-track,
+ .process-content::-webkit-scrollbar-track {
+ background: #f1f1f1;
+ border-radius: 3px;
+ }
+
+ .process-nav::-webkit-scrollbar-thumb,
+ .process-content::-webkit-scrollbar-thumb {
+ background: #c1c1c1;
+ border-radius: 3px;
+ }
+
+ .process-nav::-webkit-scrollbar-thumb:hover,
+ .process-content::-webkit-scrollbar-thumb:hover {
+ background: #a8a8a8;
+ }
+
+ /* 鍔ㄧ敾鏁堟灉 */
+ @keyframes fadeIn {
+ from {
+ opacity: 0;
+ transform: translateY(10px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+ }
+
+ .step-panel {
+ animation: fadeIn 0.3s ease;
+ }
+
+ /* 鍔犺浇鐘舵�� */
+ .loading-overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: rgba(255, 255, 255, 0.8);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 9999;
+ }
+</style>
\ No newline at end of file
--
Gitblit v1.9.3