|
|
@@ -64,20 +64,20 @@
|
|
|
<div class="table-row">
|
|
|
<div class="table-cell">
|
|
|
<div class="cell-content">
|
|
|
- <span class="cell-label">搬迁日期:</span>
|
|
|
- <span class="cell-value">{{ formatDate(dailyReportData.dpDate) || '-' }}</span>
|
|
|
+ <span class="cell-label">设计工作量:</span>
|
|
|
+ <span class="cell-value">{{ dailyReportData.workloadDesign || '-' }}</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="table-cell">
|
|
|
<div class="cell-content">
|
|
|
<span class="cell-label">开工日期:</span>
|
|
|
- <span class="cell-value">{{ formatDate(dailyReportData.sgDate) || '-' }}</span>
|
|
|
+ <span class="cell-value">{{ dailyReportData.commencementDate || '-' }}</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="table-cell">
|
|
|
<div class="cell-content">
|
|
|
<span class="cell-label">完工日期:</span>
|
|
|
- <span class="cell-value">{{ formatDate(dailyReportData.wgDate) || '-' }}</span>
|
|
|
+ <span class="cell-value">{{ dailyReportData.completionDate || '-' }}</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -86,13 +86,13 @@
|
|
|
<div class="table-cell">
|
|
|
<div class="cell-content">
|
|
|
<span class="cell-label">施工周期D:</span>
|
|
|
- <span class="cell-value">{{ constructionPeriod || 0 }}</span>
|
|
|
+ <span class="cell-value">{{ dailyReportData.constructionPeriod || '' }}</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="table-cell">
|
|
|
<div class="cell-content">
|
|
|
<span class="cell-label">停待时间D:</span>
|
|
|
- <span class="cell-value">{{ dailyReportData.faultDowntime || 0 }}</span>
|
|
|
+ <span class="cell-value">{{ dailyReportData.idleTime || '' }}</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="table-cell">
|
|
|
@@ -115,6 +115,27 @@
|
|
|
</div>
|
|
|
</ContentWrap>
|
|
|
|
|
|
+ <!-- 实际进度显示区域(新增) -->
|
|
|
+ <ContentWrap class="section-padding" v-if="showActualProgress">
|
|
|
+ <h3 class="progress-title">任务进度</h3>
|
|
|
+ <div class="actual-progress-container">
|
|
|
+ <div v-if="actualProgressData.length > 0">
|
|
|
+ <el-steps direction="horizontal" :active="actualProgressData.length - 1" finish-status="success">
|
|
|
+ <el-step
|
|
|
+ v-for="(step, index) in actualProgressData"
|
|
|
+ :key="index"
|
|
|
+ :title="step.title"
|
|
|
+ :description="step.description"
|
|
|
+ :status="step.status"
|
|
|
+ />
|
|
|
+ </el-steps>
|
|
|
+ </div>
|
|
|
+ <div v-else class="no-progress-data">
|
|
|
+ 暂无实际进度数据
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </ContentWrap>
|
|
|
+
|
|
|
<!-- 第三部分:日报填报表单 -->
|
|
|
<ContentWrap class="section-padding">
|
|
|
<el-form
|
|
|
@@ -320,6 +341,21 @@
|
|
|
</el-col>
|
|
|
</el-row>
|
|
|
|
|
|
+ <el-row>
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-form-item label="当日油耗(L)" prop="dailyFuel">
|
|
|
+ <el-input
|
|
|
+ v-model="formData.dailyFuel"
|
|
|
+ type="text"
|
|
|
+ :min="0"
|
|
|
+ placeholder="自动计算当日油耗"
|
|
|
+ :readonly="isReadonlyMode"
|
|
|
+ @blur="formatDailyFuel"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
<!-- 第三行:当日生产动态 -->
|
|
|
<el-row>
|
|
|
<el-col :span="24">
|
|
|
@@ -444,6 +480,91 @@
|
|
|
</el-form>
|
|
|
</ContentWrap>
|
|
|
|
|
|
+ <!-- 油耗信息区域 - 当有油耗数据时显示 -->
|
|
|
+ <ContentWrap class="fuel-consumption-section" v-if="showFuelConsumption">
|
|
|
+ <h2 class="text-lg font-semibold mb-4">油耗信息</h2>
|
|
|
+
|
|
|
+ <div class="fuel-consumption-table">
|
|
|
+ <el-table
|
|
|
+ :data="fuelConsumptionData"
|
|
|
+ border
|
|
|
+ style="width: 100%"
|
|
|
+ class="fuel-consumption-el-table"
|
|
|
+ table-layout="fixed"
|
|
|
+ :key="fuelTableKey"
|
|
|
+ row-key="deviceId"
|
|
|
+ >
|
|
|
+ <!-- 车辆编码 -->
|
|
|
+ <el-table-column
|
|
|
+ prop="deviceCode"
|
|
|
+ label="车辆编码"
|
|
|
+ align="center"
|
|
|
+ :show-overflow-tooltip="false"
|
|
|
+ width="120"
|
|
|
+ />
|
|
|
+
|
|
|
+ <!-- 车辆名称 -->
|
|
|
+ <el-table-column
|
|
|
+ prop="deviceName"
|
|
|
+ label="车辆名称"
|
|
|
+ align="center"
|
|
|
+ :show-overflow-tooltip="false"
|
|
|
+ width="150"
|
|
|
+ />
|
|
|
+
|
|
|
+ <!-- 发生日期 -->
|
|
|
+ <el-table-column
|
|
|
+ label="发生日期"
|
|
|
+ align="center"
|
|
|
+ :show-overflow-tooltip="false"
|
|
|
+ width="120"
|
|
|
+ >
|
|
|
+ <template #default="scope">
|
|
|
+ {{ formatDate(scope.row.queryDate) }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+
|
|
|
+ <!-- 中航北斗油耗 -->
|
|
|
+ <el-table-column
|
|
|
+ label="中航北斗油耗(L)"
|
|
|
+ align="center"
|
|
|
+ width="140"
|
|
|
+ >
|
|
|
+ <template #default="scope">
|
|
|
+ {{ formatNumber(scope.row.zhbdFuel, 2) }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+
|
|
|
+ <!-- 实际油耗 -->
|
|
|
+ <el-table-column
|
|
|
+ label="实际油耗(L)"
|
|
|
+ align="center"
|
|
|
+ width="140"
|
|
|
+ >
|
|
|
+ <template #default="scope">
|
|
|
+ <!-- 编辑模式下显示输入框 -->
|
|
|
+ <el-input
|
|
|
+ v-if="!isReadonlyMode"
|
|
|
+ v-model="scope.row.customFuel"
|
|
|
+ type="text"
|
|
|
+ :min="0"
|
|
|
+ placeholder="请输入实际油耗"
|
|
|
+ @blur="handleCustomFuelChange(scope.row)"
|
|
|
+ style="width: 100%"
|
|
|
+ size="small"
|
|
|
+ @focus="handleFuelInputFocus(scope.row)"
|
|
|
+ :key="scope.row.deviceId"
|
|
|
+ />
|
|
|
+ <!-- 只读模式下显示数值 -->
|
|
|
+ <span v-else>
|
|
|
+ {{ formatNumber(scope.row.customFuel, 2) }}
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </div>
|
|
|
+ </ContentWrap>
|
|
|
+
|
|
|
<!-- 平台井工作量区域 - 只在平台井的详情或审批模式下显示 -->
|
|
|
<ContentWrap class="platform-workload-section" v-if="(isDetailMode || isApprovalMode) && dailyReportData?.platformWell === 1">
|
|
|
<h2 class="text-lg font-semibold mb-4">平台井工作量</h2>
|
|
|
@@ -618,9 +739,17 @@ const formLoading = ref(false)
|
|
|
const formRef = ref()
|
|
|
const id = params.id // 瑞都日报id
|
|
|
|
|
|
+const fuelTableKey = ref(0) // 用于强制重新渲染表格
|
|
|
+
|
|
|
+// 添加一个新的响应式变量用于输入
|
|
|
+const dailyFuelInput = ref('')
|
|
|
+
|
|
|
// 日报数据
|
|
|
const dailyReportData = ref<any>({})
|
|
|
|
|
|
+// 修改 reportFuels 的 watch,添加标志位避免自动覆盖
|
|
|
+const dailyFuelManuallyModified = ref(false)
|
|
|
+
|
|
|
// 添加模式判断计算属性
|
|
|
const isApprovalMode = computed(() => params.mode === 'approval')
|
|
|
const isDetailMode = computed(() => params.mode === 'detail')
|
|
|
@@ -680,6 +809,15 @@ const pageTitle = computed(() => {
|
|
|
}
|
|
|
})
|
|
|
|
|
|
+// 处理输入框获取焦点事件
|
|
|
+const handleFuelInputFocus = (fuelItem: any) => {
|
|
|
+ // 如果 customFuel 是空的,确保它显示默认值
|
|
|
+ if (!fuelItem.customFuel || fuelItem.customFuel === '') {
|
|
|
+ const zhbdValue = parseFloat(fuelItem.zhbdFuel);
|
|
|
+ fuelItem.customFuel = !isNaN(zhbdValue) ? formatNumber(zhbdValue, 2) : '0.00';
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
// 模式提示信息
|
|
|
const modeNotice = computed(() => {
|
|
|
if (isApprovalMode.value) {
|
|
|
@@ -742,6 +880,7 @@ const initPlatformData = (reportData: any) => {
|
|
|
|
|
|
return existingData || {
|
|
|
taskId: platform.id,
|
|
|
+ dailyFuel: platform.dailyFuel || '',
|
|
|
reportId: platform.reportId, // 使用接口返回的 reportId
|
|
|
wellName: platform.wellName,
|
|
|
rdStatus: platform.rdStatus || '', // 初始为空
|
|
|
@@ -840,6 +979,7 @@ const formData = ref({
|
|
|
rdStatus: '', // 施工状态
|
|
|
deviceIds: [] as number[], // 设备ID数组
|
|
|
techniqueIds: [], // 施工工艺
|
|
|
+ dailyFuel: '', // 当日油耗
|
|
|
productionStatus: '', // 当日生产动态
|
|
|
nextPlan: '', // 下步工作计划
|
|
|
externalRental: '', // 外租设备
|
|
|
@@ -848,7 +988,8 @@ const formData = ref({
|
|
|
// 添加动态字段对象
|
|
|
dynamicFields: {} as Record<string, any>,
|
|
|
// 附件列表
|
|
|
- attachments: [] as any[]
|
|
|
+ attachments: [] as any[],
|
|
|
+ reportFuels: [] as any[] // 油耗信息数组
|
|
|
})
|
|
|
|
|
|
// 添加上传成功处理函数
|
|
|
@@ -1061,6 +1202,34 @@ const openDeviceDialog = async () => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+// 修改格式化函数,改为失去焦点时触发
|
|
|
+const formatDailyFuel = () => {
|
|
|
+ if (!dailyFuelInput.value || dailyFuelInput.value.trim() === '') {
|
|
|
+ formData.value.dailyFuel = ''
|
|
|
+ dailyFuelInput.value = ''
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 移除非数字字符(除了小数点)
|
|
|
+ const cleaned = dailyFuelInput.value.replace(/[^\d.]/g, '')
|
|
|
+
|
|
|
+ // 确保只有一个小数点
|
|
|
+ const parts = cleaned.split('.')
|
|
|
+ if (parts.length > 2) {
|
|
|
+ dailyFuelInput.value = parts[0] + '.' + parts.slice(1).join('')
|
|
|
+ }
|
|
|
+
|
|
|
+ const numValue = parseFloat(dailyFuelInput.value)
|
|
|
+ if (!isNaN(numValue)) {
|
|
|
+ // 限制到两位小数
|
|
|
+ formData.value.dailyFuel = formatNumber(numValue, 2)
|
|
|
+ dailyFuelInput.value = formData.value.dailyFuel
|
|
|
+ } else {
|
|
|
+ formData.value.dailyFuel = ''
|
|
|
+ dailyFuelInput.value = ''
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
// 处理穿梭框变化
|
|
|
const handleTransferChange = (value: number[], direction: string, movedKeys: number[]) => {
|
|
|
// 可以添加额外的处理逻辑
|
|
|
@@ -1099,14 +1268,6 @@ const initDeviceData = (reportData: any) => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// 表单验证规则
|
|
|
-/* const formRules = reactive({
|
|
|
- timeRange: [{ required: true, message: '时间节点不能为空', trigger: 'change' }],
|
|
|
- rdStatus: [{ required: true, message: '施工状态不能为空', trigger: 'change' }],
|
|
|
- techniqueIds: [{ required: true, message: '施工工艺不能为空', trigger: 'change' }],
|
|
|
- productionStatus: [{ required: true, message: '当日生产动态不能为空', trigger: 'blur' }]
|
|
|
-}) */
|
|
|
-
|
|
|
const formRules = computed(() => {
|
|
|
// 判断是否为虚拟项目
|
|
|
const isVirtualProject = dailyReportData.value.virtualProject === 'Y'
|
|
|
@@ -1114,7 +1275,33 @@ const formRules = computed(() => {
|
|
|
// 基础校验规则(时间节点、当日生产动态始终必填)
|
|
|
const rules = {
|
|
|
timeRange: [{ required: true, message: '时间节点不能为空', trigger: 'change' }],
|
|
|
- productionStatus: [{ required: true, message: '当日生产动态不能为空', trigger: 'blur' }]
|
|
|
+ productionStatus: [{ required: true, message: '当日生产动态不能为空', trigger: 'blur' }],
|
|
|
+ nextPlan: [{ required: true, message: '下步工作计划不能为空', trigger: 'blur' }],
|
|
|
+ dailyFuel: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ message: '当日油耗不能为空',
|
|
|
+ trigger: 'blur'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ validator: (rule: any, value: any, callback: any) => {
|
|
|
+ if (value === '' || value === null || value === undefined) {
|
|
|
+ callback()
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ const numValue = Number(value)
|
|
|
+ if (isNaN(numValue)) {
|
|
|
+ callback(new Error('当日油耗必须是数字'))
|
|
|
+ } else if (numValue < 0) {
|
|
|
+ callback(new Error('当日油耗不能小于0'))
|
|
|
+ } else {
|
|
|
+ callback()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ trigger: 'blur'
|
|
|
+ }
|
|
|
+ ]
|
|
|
}
|
|
|
|
|
|
// 非虚拟项目时,添加施工状态、施工工艺的必填校验
|
|
|
@@ -1228,7 +1415,15 @@ const submitForm = async () => {
|
|
|
extProperty: extProperties,
|
|
|
deviceIds: formData.value.deviceIds, // 设备ID集合
|
|
|
// 在填报模式下也提交审批意见字段
|
|
|
- opinion: isEditMode.value ? approvalForm.opinion : undefined
|
|
|
+ opinion: isEditMode.value ? approvalForm.opinion : undefined,
|
|
|
+ // 将油耗数据格式化为后端需要的格式
|
|
|
+ /* reportFuels: formData.value.reportFuels.map(fuel => ({
|
|
|
+ ...fuel,
|
|
|
+ // 确保 customFuel 是数字格式
|
|
|
+ customFuel: fuel.customFuel ? parseFloat(fuel.customFuel) : null
|
|
|
+ })), */
|
|
|
+ // 确保当日油耗是数字格式
|
|
|
+ dailyFuel: formData.value.dailyFuel ? parseFloat(formData.value.dailyFuel) : 0
|
|
|
}
|
|
|
|
|
|
// 删除不需要复制的字段
|
|
|
@@ -1255,6 +1450,12 @@ const submitForm = async () => {
|
|
|
bizId: pair.reportId // 替换 bizId 为当前平台井的 reportId
|
|
|
}))
|
|
|
|
|
|
+ // 车辆油耗:复制并修改 reportId 为当前 pair 的 reportId
|
|
|
+ platformData.reportFuels = (baseData.reportFuels || []).map(reportFuel => ({
|
|
|
+ ...reportFuel, // 深拷贝单个油耗
|
|
|
+ reportId: pair.reportId // 替换 reportId 为当前平台井的 reportId
|
|
|
+ }))
|
|
|
+
|
|
|
// 重新构建 dynamicFields(如果需要)
|
|
|
const dynamicFields = {}
|
|
|
if (platformData.extProperty && platformData.extProperty.length > 0) {
|
|
|
@@ -1482,6 +1683,25 @@ watch(() => formData.value.techniqueIds, async (newTechniqueIds, oldTechniqueIds
|
|
|
}
|
|
|
}, { deep: true })
|
|
|
|
|
|
+// 监听 formData.dailyFuel 变化,同步到输入变量
|
|
|
+watch(() => formData.value.dailyFuel, (newVal) => {
|
|
|
+ if (newVal !== null && newVal !== undefined && newVal !== '') {
|
|
|
+ // 将数字转换为字符串显示,但不干扰输入
|
|
|
+ dailyFuelInput.value = String(newVal)
|
|
|
+ } else {
|
|
|
+ dailyFuelInput.value = ''
|
|
|
+ }
|
|
|
+ dailyFuelManuallyModified.value = true
|
|
|
+}, { immediate: true })
|
|
|
+
|
|
|
+// 监听reportFuels的变化,自动更新当日油耗
|
|
|
+watch(() => formData.value.reportFuels, (newFuels) => {
|
|
|
+ // 只有在编辑模式且用户没有手动修改过当日油耗时才自动计算
|
|
|
+ if (!isReadonlyMode.value) {
|
|
|
+ calculateAndUpdateDailyFuel();
|
|
|
+ }
|
|
|
+}, { deep: true })
|
|
|
+
|
|
|
// 更新当前平台井的 extProperty
|
|
|
const updateCurrentPlatformExtProperty = () => {
|
|
|
if (!currentPlatformId.value) return
|
|
|
@@ -1555,7 +1775,7 @@ const loadPlatformData = (platformId: number) => {
|
|
|
if (platformData) {
|
|
|
// 更新表单字段
|
|
|
formData.value.rdStatus = platformData.rdStatus || ''
|
|
|
- // formData.value.techniqueIds = platformData.techniqueIds ? [...platformData.techniqueIds] : []
|
|
|
+ // formData.value.dailyFuel = platformData.dailyFuel ? [...platformData.dailyFuel] : []
|
|
|
// 将施工工艺数值转换为对应的标签
|
|
|
if (platformData.techniqueIds && Array.isArray(platformData.techniqueIds)) {
|
|
|
// 如果是数字数组,转换为字符串数组(与数据字典格式匹配)
|
|
|
@@ -1564,6 +1784,15 @@ const loadPlatformData = (platformId: number) => {
|
|
|
formData.value.techniqueIds = platformData.techniqueIds ? [...platformData.techniqueIds] : []
|
|
|
}
|
|
|
|
|
|
+ // 在详情或审批模式下,更新 dailyFuel 为当前平台井的值
|
|
|
+ if (isDetailMode.value || isApprovalMode.value) {
|
|
|
+ // 使用平台井的 dailyFuel 值
|
|
|
+ const platformDailyFuel = platformData.dailyFuel || ''
|
|
|
+ formData.value.dailyFuel = platformDailyFuel ? formatNumber(platformDailyFuel, 2) : ''
|
|
|
+ // 同步更新输入框
|
|
|
+ dailyFuelInput.value = formData.value.dailyFuel
|
|
|
+ }
|
|
|
+
|
|
|
// 更新动态属性
|
|
|
if (platformData.extProperty && platformData.extProperty.length > 0) {
|
|
|
const dynamicFields: Record<string, any> = {}
|
|
|
@@ -1581,6 +1810,12 @@ const loadPlatformData = (platformId: number) => {
|
|
|
formData.value.rdStatus = ''
|
|
|
formData.value.techniqueIds = []
|
|
|
formData.value.dynamicFields = {}
|
|
|
+
|
|
|
+ // 在详情或审批模式下,清空 dailyFuel
|
|
|
+ if (isDetailMode.value || isApprovalMode.value) {
|
|
|
+ formData.value.dailyFuel = ''
|
|
|
+ dailyFuelInput.value = ''
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -1603,6 +1838,48 @@ const getCurrentExtProperties = () => {
|
|
|
})
|
|
|
}
|
|
|
|
|
|
+// 是否显示实际进度
|
|
|
+const showActualProgress = computed(() => {
|
|
|
+ // 在所有模式下都显示,如果有数据就显示
|
|
|
+ return dailyReportData.value?.taskProgresses && dailyReportData.value.taskProgresses.length > 0
|
|
|
+})
|
|
|
+
|
|
|
+// 实际进度数据
|
|
|
+const actualProgressData = computed(() => {
|
|
|
+ if (!dailyReportData.value?.taskProgresses || !Array.isArray(dailyReportData.value.taskProgresses)) {
|
|
|
+ return []
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将 taskProgresses 转换为 el-steps 需要的格式
|
|
|
+ return dailyReportData.value.taskProgresses.map((progress: any, index: number) => {
|
|
|
+ // 格式化日期:如果只有日期部分,使用日期格式;如果有时间,使用日期时间格式
|
|
|
+ let formattedDate = ''
|
|
|
+ if (progress.createTime) {
|
|
|
+ // 判断日期格式,如果包含时间则显示完整时间,否则只显示日期
|
|
|
+ if (progress.createTime.includes(' ')) {
|
|
|
+ // 已经是完整的日期时间格式
|
|
|
+ formattedDate = progress.createTime
|
|
|
+ } else {
|
|
|
+ // 只有日期部分
|
|
|
+ formattedDate = progress.createTime
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 构建标题:日期 + 状态
|
|
|
+ const title = formattedDate && progress.rdStatusLabel
|
|
|
+ ? `${formattedDate} ${progress.rdStatusLabel}`
|
|
|
+ : progress.rdStatusLabel || '未知状态'
|
|
|
+
|
|
|
+ return {
|
|
|
+ title: title,
|
|
|
+ description: '', // 可以根据需要添加描述信息
|
|
|
+ status: undefined, // el-steps 会自动计算状态
|
|
|
+ // 保留原始数据,便于调试
|
|
|
+ rawData: progress
|
|
|
+ }
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
// 初始化表单数据
|
|
|
const initFormData = (reportData: any) => {
|
|
|
// 处理附件数据格式转换
|
|
|
@@ -1632,6 +1909,7 @@ const initFormData = (reportData: any) => {
|
|
|
platformWell: reportData.platformWell,
|
|
|
rdStatus: reportData.rdStatus || '',
|
|
|
techniqueIds: techniqueIds,
|
|
|
+ dailyFuel: reportData.dailyFuel, // 当日油耗默认值
|
|
|
productionStatus: reportData.productionStatus || '',
|
|
|
nextPlan: reportData.nextPlan || '',
|
|
|
externalRental: reportData.externalRental || '',
|
|
|
@@ -1670,10 +1948,119 @@ const initFormData = (reportData: any) => {
|
|
|
// 初始化设备数据
|
|
|
initDeviceData(reportData)
|
|
|
|
|
|
- // 如果是平台井模式且有数据,初始化 platformWellPairs 中的第一个平台井数据
|
|
|
- /* if (reportData.platformWell === 1 && formData.value.platformId) {
|
|
|
- loadPlatformData(formData.value.platformId)
|
|
|
- } */
|
|
|
+ // 初始化油耗数据 - 根据模式选择数据源
|
|
|
+ if (isDetailMode.value || isApprovalMode.value) {
|
|
|
+ // 详情或审批模式:优先使用 reportedFuels
|
|
|
+ let fuelSource = reportData.reportedFuels;
|
|
|
+
|
|
|
+ if (fuelSource && Array.isArray(fuelSource) && fuelSource.length > 0) {
|
|
|
+ // 处理每个油耗数据项,设置 customFuel 的默认值并确保格式正确
|
|
|
+ const processedFuels = fuelSource.map((fuel: any) => {
|
|
|
+ // 创建全新的对象,避免引用共享
|
|
|
+ const newFuel = {
|
|
|
+ ...fuel, // 使用展开运算符创建浅拷贝
|
|
|
+ // 确保每个字段都有独立的值
|
|
|
+ createTime: fuel.createTime,
|
|
|
+ updateTime: fuel.updateTime,
|
|
|
+ creator: fuel.creator,
|
|
|
+ updater: fuel.updater,
|
|
|
+ deleted: fuel.deleted,
|
|
|
+ id: fuel.id,
|
|
|
+ type: fuel.type,
|
|
|
+ reportId: fuel.reportId,
|
|
|
+ deviceId: fuel.deviceId,
|
|
|
+ deviceCode: fuel.deviceCode,
|
|
|
+ yfDeviceCode: fuel.yfDeviceCode,
|
|
|
+ deviceName: fuel.deviceName,
|
|
|
+ carId: fuel.carId,
|
|
|
+ zhbdFuel: fuel.zhbdFuel,
|
|
|
+ customFuel: null, // 初始化为null
|
|
|
+ queryDate: fuel.queryDate,
|
|
|
+ remark: fuel.remark
|
|
|
+ };
|
|
|
+
|
|
|
+ let customFuelValue;
|
|
|
+
|
|
|
+ // 如果 customFuel 不为空,确保它是字符串格式并已正确格式化
|
|
|
+ if (fuel.customFuel !== null && fuel.customFuel !== undefined) {
|
|
|
+ const numValue = parseFloat(fuel.customFuel);
|
|
|
+ customFuelValue = !isNaN(numValue) ? formatNumber(numValue, 2) : '0.00';
|
|
|
+ } else {
|
|
|
+ // 如果 customFuel 为空,则使用 zhbdFuel 的值
|
|
|
+ const zhbdValue = parseFloat(fuel.zhbdFuel);
|
|
|
+ customFuelValue = !isNaN(zhbdValue) ? formatNumber(zhbdValue, 2) : '0.00';
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ ...newFuel,
|
|
|
+ customFuel: customFuelValue
|
|
|
+ };
|
|
|
+ });
|
|
|
+
|
|
|
+ formData.value.reportFuels = processedFuels;
|
|
|
+
|
|
|
+ // 计算初始的当日油耗
|
|
|
+ calculateTotalDailyFuel();
|
|
|
+ } else {
|
|
|
+ // 如果 reportedFuels 不存在或为空,设置空数组
|
|
|
+ formData.value.reportFuels = [];
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 编辑模式:优先使用 reportedFuels,不存在则使用 reportFuels
|
|
|
+ let fuelSource = reportData.reportedFuels || reportData.reportFuels || [];
|
|
|
+
|
|
|
+ if (fuelSource && Array.isArray(fuelSource) && fuelSource.length > 0) {
|
|
|
+ // 处理每个油耗数据项,设置 customFuel 的默认值并确保格式正确
|
|
|
+ const processedFuels = fuelSource.map((fuel: any) => {
|
|
|
+ // 创建全新的对象,避免引用共享
|
|
|
+ const newFuel = {
|
|
|
+ ...fuel, // 使用展开运算符创建浅拷贝
|
|
|
+ // 确保每个字段都有独立的值
|
|
|
+ createTime: fuel.createTime,
|
|
|
+ updateTime: fuel.updateTime,
|
|
|
+ creator: fuel.creator,
|
|
|
+ updater: fuel.updater,
|
|
|
+ deleted: fuel.deleted,
|
|
|
+ id: fuel.id,
|
|
|
+ type: fuel.type,
|
|
|
+ reportId: fuel.reportId,
|
|
|
+ deviceId: fuel.deviceId,
|
|
|
+ deviceCode: fuel.deviceCode,
|
|
|
+ yfDeviceCode: fuel.yfDeviceCode,
|
|
|
+ deviceName: fuel.deviceName,
|
|
|
+ carId: fuel.carId,
|
|
|
+ zhbdFuel: fuel.zhbdFuel,
|
|
|
+ customFuel: null, // 初始化为null
|
|
|
+ queryDate: fuel.queryDate,
|
|
|
+ remark: fuel.remark
|
|
|
+ };
|
|
|
+
|
|
|
+ let customFuelValue;
|
|
|
+
|
|
|
+ // 如果 customFuel 不为空,确保它是字符串格式并已正确格式化
|
|
|
+ if (fuel.customFuel !== null && fuel.customFuel !== undefined && fuel.customFuel !== '') {
|
|
|
+ const numValue = parseFloat(fuel.customFuel);
|
|
|
+ customFuelValue = !isNaN(numValue) ? formatNumber(numValue, 2) : '0.00';
|
|
|
+ } else {
|
|
|
+ // 如果 customFuel 为空,则使用 zhbdFuel 的值
|
|
|
+ const zhbdValue = parseFloat(fuel.zhbdFuel);
|
|
|
+ customFuelValue = !isNaN(zhbdValue) ? formatNumber(zhbdValue, 2) : '0.00';
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ ...newFuel,
|
|
|
+ customFuel: customFuelValue
|
|
|
+ };
|
|
|
+ });
|
|
|
+
|
|
|
+ formData.value.reportFuels = processedFuels;
|
|
|
+
|
|
|
+ // 计算初始的当日油耗
|
|
|
+ calculateTotalDailyFuel();
|
|
|
+ } else {
|
|
|
+ formData.value.reportFuels = [];
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
@@ -1689,6 +2076,13 @@ onMounted(async () => {
|
|
|
const response = await IotRdDailyReportApi.getIotRdDailyReport(id)
|
|
|
dailyReportData.value = response || {}
|
|
|
initFormData(dailyReportData.value)
|
|
|
+
|
|
|
+ // 确保油耗数据在初始化后立即渲染
|
|
|
+ await nextTick()
|
|
|
+ // 强制更新油耗数据
|
|
|
+ if (formData.value.reportFuels && formData.value.reportFuels.length > 0) {
|
|
|
+ formData.value.reportFuels = [...formData.value.reportFuels]
|
|
|
+ }
|
|
|
}
|
|
|
} catch (error) {
|
|
|
console.error('初始化数据失败:', error)
|
|
|
@@ -1724,6 +2118,207 @@ const getWorkloadColumns = () => {
|
|
|
return columns;
|
|
|
};
|
|
|
|
|
|
+// 添加一个深拷贝油耗数据的辅助函数
|
|
|
+const deepCopyFuelData = (fuelData: any) => {
|
|
|
+ if (!fuelData) return null;
|
|
|
+
|
|
|
+ return {
|
|
|
+ createTime: fuelData.createTime,
|
|
|
+ updateTime: fuelData.updateTime,
|
|
|
+ creator: fuelData.creator,
|
|
|
+ updater: fuelData.updater,
|
|
|
+ deleted: fuelData.deleted,
|
|
|
+ id: fuelData.id,
|
|
|
+ type: fuelData.type,
|
|
|
+ reportId: fuelData.reportId,
|
|
|
+ deviceId: fuelData.deviceId,
|
|
|
+ deviceCode: fuelData.deviceCode,
|
|
|
+ yfDeviceCode: fuelData.yfDeviceCode,
|
|
|
+ deviceName: fuelData.deviceName,
|
|
|
+ carId: fuelData.carId,
|
|
|
+ zhbdFuel: fuelData.zhbdFuel,
|
|
|
+ customFuel: fuelData.customFuel,
|
|
|
+ queryDate: fuelData.queryDate,
|
|
|
+ remark: fuelData.remark
|
|
|
+ };
|
|
|
+};
|
|
|
+
|
|
|
+// 强制刷新表格
|
|
|
+const refreshFuelTable = () => {
|
|
|
+ fuelTableKey.value += 1;
|
|
|
+}
|
|
|
+
|
|
|
+// 计算当日油耗的默认值
|
|
|
+const calculateDailyFuel = (reportData: any) => {
|
|
|
+ let dailyFuelValue = 0
|
|
|
+
|
|
|
+ // 如果有接口返回的dailyFuel,优先使用
|
|
|
+ if (reportData.dailyFuel !== null && reportData.dailyFuel !== undefined) {
|
|
|
+ dailyFuelValue = Number(reportData.dailyFuel)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果reportFuels有数据,累加zhbdFuel的值
|
|
|
+ if (reportData.reportFuels && Array.isArray(reportData.reportFuels) && reportData.reportFuels.length > 0) {
|
|
|
+ const totalZhbdFuel = reportData.reportFuels.reduce((sum: number, item: any) => {
|
|
|
+ const zhbdFuelValue = Number(item.zhbdFuel) || 0
|
|
|
+ return sum + zhbdFuelValue
|
|
|
+ }, 0)
|
|
|
+
|
|
|
+ // 只有当累计值大于0时才覆盖原有的dailyFuel值
|
|
|
+ if (totalZhbdFuel > 0) {
|
|
|
+ dailyFuelValue = totalZhbdFuel
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return formatNumber(dailyFuelValue, 2)
|
|
|
+}
|
|
|
+
|
|
|
+// 处理当日油耗输入
|
|
|
+const handleDailyFuelInput = () => {
|
|
|
+ // 确保保留两位小数
|
|
|
+ if (formData.value.dailyFuel !== '') {
|
|
|
+ const numValue = parseFloat(formData.value.dailyFuel)
|
|
|
+ if (!isNaN(numValue)) {
|
|
|
+ formData.value.dailyFuel = numValue.toFixed(2)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 添加数字格式化函数
|
|
|
+const formatNumber = (value: any, decimalPlaces: number = 2) => {
|
|
|
+ if (value === null || value === undefined || value === '' || value === 'NaN') {
|
|
|
+ return '0.00';
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果已经是字符串,尝试转换为数字
|
|
|
+ if (typeof value === 'string') {
|
|
|
+ // 移除可能的非数字字符
|
|
|
+ const cleaned = value.replace(/[^\d.-]/g, '');
|
|
|
+ const num = Number(cleaned);
|
|
|
+ if (isNaN(num)) {
|
|
|
+ return '0.00';
|
|
|
+ }
|
|
|
+ return num.toFixed(decimalPlaces);
|
|
|
+ }
|
|
|
+
|
|
|
+ const num = Number(value);
|
|
|
+ if (isNaN(num)) {
|
|
|
+ return '0.00';
|
|
|
+ }
|
|
|
+
|
|
|
+ return num.toFixed(decimalPlaces)
|
|
|
+}
|
|
|
+
|
|
|
+// 新增:计算并更新当日油耗的方法
|
|
|
+const calculateAndUpdateDailyFuel = () => {
|
|
|
+ if (!formData.value.reportFuels || !Array.isArray(formData.value.reportFuels)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 计算所有车辆的实际油耗总和
|
|
|
+ const totalCustomFuel = formData.value.reportFuels.reduce((sum: number, item: any) => {
|
|
|
+ const customFuelValue = Number(item.customFuel) || 0;
|
|
|
+ return sum + customFuelValue;
|
|
|
+ }, 0);
|
|
|
+
|
|
|
+ // 只有当累计的实际油耗大于0时,才更新当日油耗
|
|
|
+ if (totalCustomFuel > 0 && !isReadonlyMode.value) {
|
|
|
+ formData.value.dailyFuel = formatNumber(totalCustomFuel, 2);
|
|
|
+ // 更新输入框显示
|
|
|
+ if (dailyFuelInput.value) {
|
|
|
+ dailyFuelInput.value = formData.value.dailyFuel;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 添加计算属性:获取油耗数据显示数据源
|
|
|
+const fuelConsumptionData = computed(() => {
|
|
|
+ // 所有模式都统一使用 formData.value.reportFuels 作为数据源
|
|
|
+ // 因为 formData.value.reportFuels 在 initFormData 中已经正确处理了所有情况
|
|
|
+ return formData.value.reportFuels || [];
|
|
|
+});
|
|
|
+
|
|
|
+// 判断是否显示油耗信息区域
|
|
|
+const showFuelConsumption = computed(() => {
|
|
|
+ const data = fuelConsumptionData.value;
|
|
|
+ return data && Array.isArray(data) && data.length > 0;
|
|
|
+});
|
|
|
+
|
|
|
+// 重新计算当日油耗const formatNumber
|
|
|
+const calculateTotalDailyFuel = () => {
|
|
|
+ if (!formData.value.reportFuels || !Array.isArray(formData.value.reportFuels)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 计算所有车辆的实际油耗总和
|
|
|
+ const totalCustomFuel = formData.value.reportFuels.reduce((sum: number, item: any) => {
|
|
|
+ const customFuelValue = Number(item.customFuel) || 0;
|
|
|
+ return sum + customFuelValue;
|
|
|
+ }, 0);
|
|
|
+
|
|
|
+ // 只有当累计的实际油耗大于0时,才自动更新当日油耗
|
|
|
+ if (totalCustomFuel > 0 && !isReadonlyMode.value) {
|
|
|
+ formData.value.dailyFuel = formatNumber(totalCustomFuel, 2);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 处理实际油耗变化
|
|
|
+const handleCustomFuelChange = (fuelItem: any) => {
|
|
|
+ // 获取当前输入的值
|
|
|
+ let value = fuelItem.customFuel;
|
|
|
+
|
|
|
+ // 如果输入为空,则重置为zhbdFuel的值
|
|
|
+ if (value === '' || value === null || value === undefined) {
|
|
|
+ fuelItem.customFuel = formatNumber(fuelItem.zhbdFuel, 2);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 移除非数字字符(除了小数点)
|
|
|
+ const cleaned = value.toString().replace(/[^\d.]/g, '');
|
|
|
+
|
|
|
+ // 确保只有一个小数点
|
|
|
+ const parts = cleaned.split('.');
|
|
|
+ let formattedValue = cleaned;
|
|
|
+ if (parts.length > 2) {
|
|
|
+ formattedValue = parts[0] + '.' + parts.slice(1).join('');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 转换为数字并格式化为两位小数
|
|
|
+ const numValue = parseFloat(formattedValue);
|
|
|
+ if (!isNaN(numValue)) {
|
|
|
+ // 限制到两位小数
|
|
|
+ fuelItem.customFuel = formatNumber(numValue, 2);
|
|
|
+ } else {
|
|
|
+ // 如果转换失败,设置为0.00
|
|
|
+ fuelItem.customFuel = '0.00';
|
|
|
+ }
|
|
|
+
|
|
|
+ // 同步更新 formData.reportFuels 中的数据
|
|
|
+ // 确保通过 deviceId 正确找到并更新对应的记录
|
|
|
+ if (formData.value.reportFuels && fuelItem.deviceId) {
|
|
|
+ const index = formData.value.reportFuels.findIndex(
|
|
|
+ item => item.deviceId === fuelItem.deviceId
|
|
|
+ );
|
|
|
+
|
|
|
+ if (index !== -1) {
|
|
|
+ // 创建新对象,避免引用问题
|
|
|
+ const updatedFuel = {
|
|
|
+ ...formData.value.reportFuels[index],
|
|
|
+ customFuel: fuelItem.customFuel
|
|
|
+ };
|
|
|
+
|
|
|
+ // 使用 Vue.set 或直接赋值确保响应性
|
|
|
+ formData.value.reportFuels[index] = updatedFuel;
|
|
|
+
|
|
|
+ // 强制刷新表格
|
|
|
+ fuelTableKey.value += 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 手动触发当日油耗的重新计算
|
|
|
+ calculateAndUpdateDailyFuel();
|
|
|
+}
|
|
|
+
|
|
|
// 详情 审批 平台井 获取工作量值
|
|
|
const getWorkloadValue = (platform, identifier) => {
|
|
|
if (!platform.extProperty) return '';
|
|
|
@@ -2195,4 +2790,167 @@ const handleApprove = async (action: 'pass' | 'reject') => {
|
|
|
width: 100%;
|
|
|
}
|
|
|
|
|
|
+/* 油耗信息区域样式 */
|
|
|
+.fuel-consumption-section {
|
|
|
+ padding-left: 0px;
|
|
|
+ padding-right: 0px;
|
|
|
+ margin-top: 20px;
|
|
|
+}
|
|
|
+
|
|
|
+/* 强制表格宽度为100% */
|
|
|
+:deep(.fuel-consumption-el-table) {
|
|
|
+ width: 100% !important;
|
|
|
+ min-width: 100% !important;
|
|
|
+}
|
|
|
+
|
|
|
+/* 确保表格内部元素也充满宽度 */
|
|
|
+:deep(.fuel-consumption-el-table .el-table) {
|
|
|
+ width: 100% !important;
|
|
|
+ min-width: 100% !important;
|
|
|
+}
|
|
|
+
|
|
|
+/* 强制设置表头宽度为100% */
|
|
|
+:deep(.fuel-consumption-el-table .el-table__header) {
|
|
|
+ width: 100% !important;
|
|
|
+ min-width: 100% !important;
|
|
|
+}
|
|
|
+
|
|
|
+/* 表头不换行 */
|
|
|
+:deep(.fuel-consumption-el-table .el-table__header-wrapper th) {
|
|
|
+ white-space: nowrap;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ overflow: hidden;
|
|
|
+ background-color: #f5f7fa;
|
|
|
+ color: #606266;
|
|
|
+ font-weight: bold;
|
|
|
+}
|
|
|
+
|
|
|
+/* 强制设置表格主体宽度为100% */
|
|
|
+:deep(.fuel-consumption-el-table .el-table__body) {
|
|
|
+ width: 100% !important;
|
|
|
+ min-width: 100% !important;
|
|
|
+}
|
|
|
+
|
|
|
+/* 表头和表体都设置为100%宽度 */
|
|
|
+:deep(.fuel-consumption-el-table .el-table__header-wrapper),
|
|
|
+:deep(.fuel-consumption-el-table .el-table__body-wrapper) {
|
|
|
+ width: 100% !important;
|
|
|
+}
|
|
|
+
|
|
|
+/* 单元格内容居中 */
|
|
|
+:deep(.fuel-consumption-el-table .el-table__body-wrapper td) {
|
|
|
+ text-align: center;
|
|
|
+ white-space: nowrap;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ overflow: hidden;
|
|
|
+}
|
|
|
+
|
|
|
+/* 实际油耗输入框样式 */
|
|
|
+:deep(.fuel-consumption-el-table .el-input__inner) {
|
|
|
+ text-align: center;
|
|
|
+ padding: 0 5px;
|
|
|
+ height: 28px;
|
|
|
+ line-height: 28px;
|
|
|
+}
|
|
|
+
|
|
|
+/* 只读模式下的数值显示 */
|
|
|
+.fuel-consumption-el-table .readonly-value {
|
|
|
+ color: #606266;
|
|
|
+ font-weight: normal;
|
|
|
+}
|
|
|
+
|
|
|
+/* 强制设置表格宽度为100% */
|
|
|
+:deep(.fuel-consumption-el-table .el-table) {
|
|
|
+ width: 100% !important;
|
|
|
+}
|
|
|
+
|
|
|
+/* 表格容器填满父容器 */
|
|
|
+.fuel-consumption-table {
|
|
|
+ width: 100%;
|
|
|
+ overflow-x: auto;
|
|
|
+}
|
|
|
+
|
|
|
+/* 响应式调整 */
|
|
|
+@media (max-width: 768px) {
|
|
|
+ .fuel-consumption-section {
|
|
|
+ padding-left: 10px;
|
|
|
+ padding-right: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.fuel-consumption-el-table .el-table__header-wrapper th),
|
|
|
+ :deep(.fuel-consumption-el-table .el-table__body-wrapper td) {
|
|
|
+ padding: 8px 5px;
|
|
|
+ font-size: 12px;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* 当日油耗输入框样式优化 */
|
|
|
+:deep(.el-form-item .el-input-number) {
|
|
|
+ width: 100%;
|
|
|
+}
|
|
|
+
|
|
|
+/* 当日油耗字段在只读模式下的样式 */
|
|
|
+:deep(.is-disabled .el-input__inner[type="number"]) {
|
|
|
+ background-color: #f5f7fa;
|
|
|
+ border-color: #e4e7ed;
|
|
|
+ color: #606266;
|
|
|
+ cursor: not-allowed;
|
|
|
+}
|
|
|
+
|
|
|
+/* 实际进度区域样式 */
|
|
|
+.actual-progress-container {
|
|
|
+ margin-top: 10px;
|
|
|
+ padding: 20px;
|
|
|
+ border: 1px solid #e6e6e6;
|
|
|
+ border-radius: 8px;
|
|
|
+ background-color: #fafafa;
|
|
|
+}
|
|
|
+
|
|
|
+.progress-title {
|
|
|
+ margin: 0 0 16px 0;
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #67c23a; /* 实际进度使用绿色标题 */
|
|
|
+}
|
|
|
+
|
|
|
+.no-progress-data {
|
|
|
+ text-align: center;
|
|
|
+ padding: 20px 0;
|
|
|
+ color: #909399;
|
|
|
+ font-style: italic;
|
|
|
+}
|
|
|
+
|
|
|
+/* 调整步骤组件样式以适应水平布局 */
|
|
|
+:deep(.actual-progress-container .el-steps--horizontal) {
|
|
|
+ flex-wrap: nowrap;
|
|
|
+ overflow-x: auto;
|
|
|
+ padding-bottom: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+:deep(.actual-progress-container .el-step__title) {
|
|
|
+ font-size: 12px;
|
|
|
+ line-height: 1.4;
|
|
|
+ white-space: nowrap;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ max-width: 120px;
|
|
|
+}
|
|
|
+
|
|
|
+/* 确保步骤容器有足够空间 */
|
|
|
+:deep(.actual-progress-container .el-step) {
|
|
|
+ flex-basis: auto;
|
|
|
+ flex-shrink: 0;
|
|
|
+}
|
|
|
+
|
|
|
+/* 响应式调整 */
|
|
|
+@media (max-width: 768px) {
|
|
|
+ :deep(.actual-progress-container .el-step__title) {
|
|
|
+ font-size: 11px;
|
|
|
+ max-width: 100px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .actual-progress-container {
|
|
|
+ padding: 15px;
|
|
|
+ }
|
|
|
+}
|
|
|
</style>
|