This commit is contained in:
2026-10-22 11:56:54 +08:00
parent 090431b409
commit 3e77c3976e
40 changed files with 976 additions and 241 deletions
@@ -93,17 +93,28 @@ defineExpose({ busy })
<div v-loading="busy" class="density-dialog-sections">
<LoadErrorState v-if="error" compact title="车辆资料操作失败" :message="error.message" :show-retry="!pending && !corrupted" @retry="load"><template #details><ApiErrorMeta :details="error" /></template></LoadErrorState>
<div v-if="pending" role="status">有图片尚未确认保存。<el-button v-if="pending.versionConflict" :disabled="busy || !editable" @click="refreshBinding">刷新版本并保存已上传图片</el-button><el-button v-else :disabled="busy || !editable" @click="recover">核对原请求并继续保存</el-button></div>
<section v-for="role in roles" :key="role.slot" class="density-dialog-section">
<h3 class="density-dialog-section__title">{{ role.label }}</h3>
<div v-for="photo in snapshot?.photos.filter(item => item.slot === role.slot) || []" :key="photo.fileId"><el-button link :disabled="busy" @click="view(photo)">{{ photo.fileName }}</el-button></div>
<span v-if="snapshot && !snapshot.photos.some(item => item.slot === role.slot)">未上传</span>
<label v-if="editable" class="photo-upload">上传/替换<input type="file" accept="image/jpeg,image/png" :aria-label="role.label" :disabled="busy || Boolean(pending)" @change="upload(role.slot, $event)" /></label>
</section>
<table class="density-table fuel-documents-table" aria-label="油耗图片"><thead><tr><th class="photo-actions">操作</th><th class="photo-category">图片类别</th><th>文件名称</th><th class="photo-time">保存时间</th></tr></thead><tbody>
<tr v-for="role in roles" :key="role.slot">
<td><label v-if="editable" class="photo-upload" :class="{ 'is-disabled': busy || Boolean(pending) }">上传/替换<input type="file" accept="image/jpeg,image/png" :aria-label="role.label" :disabled="busy || Boolean(pending)" @change="upload(role.slot, $event)" /></label><span v-else>—</span></td>
<td>{{ role.label }}</td>
<td><div v-for="photo in snapshot?.photos.filter(item => item.slot === role.slot) || []" :key="photo.fileId"><el-button link :disabled="busy" @click="view(photo)">{{ photo.fileName }}</el-button></div><span v-if="!snapshot?.photos.some(item => item.slot === role.slot)">未上传</span></td>
<td><div v-for="photo in snapshot?.photos.filter(item => item.slot === role.slot) || []" :key="photo.fileId">{{ photo.savedAt?.replace('T', ' ') || '—' }}</div><span v-if="!snapshot?.photos.some(item => item.slot === role.slot)">—</span></td>
</tr>
</tbody></table>
<img v-if="preview" :src="preview" alt="油耗图片预览" class="photo-preview" />
</div>
</template>
<style scoped>
.photo-upload { display: block; margin-top: var(--admin-space-3); }
.photo-upload input { margin-left: var(--admin-space-3); }
.fuel-documents-table { table-layout: fixed; }
.fuel-documents-table td { overflow-wrap: anywhere; }
.fuel-documents-table :deep(.el-button > span) { white-space: normal; text-align: left; overflow-wrap: anywhere; }
.photo-actions { width: 110px; }
.photo-category { width: 160px; }
.photo-time { width: 190px; }
.photo-upload { position: relative; display: inline-flex; color: var(--el-color-primary); cursor: pointer; }
.photo-upload input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; }
.photo-upload:focus-within { outline: 2px solid var(--el-color-primary); outline-offset: 2px; }
.photo-upload.is-disabled { color: var(--el-text-color-disabled); cursor: not-allowed; }
.photo-upload.is-disabled input { cursor: not-allowed; }
.photo-preview { display: block; max-width: 100%; max-height: 400px; object-fit: contain; }
</style>