Files
shanxia2.0/miniprogram/pages/pl/cert/detail.vue
T
2026-07-18 09:14:02 +08:00

164 lines
4.7 KiB
Vue

<script setup>
import { ref, computed } from 'vue'
import { onLoad, onShow } from '@dcloudio/uni-app'
import { getPlan, updateProductCerts, setHazardCertReady } from '@/api/pl'
import { chooseAndUploadImages } from '@/utils/upload'
import { dash, planCardSub, hasPurchaseCert, certReadyLabel } from '@/utils/plLabels'
import { PAGE_PATHS } from '@/config/api'
const id = ref('')
const detail = ref(null)
const acting = ref(false)
const products = computed(() =>
Array.isArray(detail.value?.products) ? detail.value.products : []
)
const goBack = () => {
uni.navigateBack({
fail: () => uni.navigateTo({ url: PAGE_PATHS.plCertList })
})
}
const load = async () => {
if (!id.value) return
try {
detail.value = await getPlan(id.value)
} catch (e) {
uni.showToast({ title: e.message || '加载失败', icon: 'none' })
}
}
const certUrls = (p) => {
const raw = p.purchaseCertUrl || p.purchase_cert_url || ''
return String(raw)
.split(',')
.map((s) => s.trim())
.filter(Boolean)
}
const preview = (urls, index) => {
uni.previewImage({ urls, current: urls[index] || urls[0] })
}
const uploadForProduct = async (product) => {
const current = certUrls(product)
acting.value = true
try {
const added = await chooseAndUploadImages({
folder: 'pl-purchase-cert',
maxCount: 6,
currentUrls: current
})
if (!added.length) return
const nextUrls = current.concat(added)
await updateProductCerts(id.value, [
{
id: product.id,
purchaseCertUrl: nextUrls.join(',')
}
])
uni.showToast({ title: '已上传', icon: 'success' })
await load()
} catch (e) {
uni.showToast({ title: e.message || '上传失败', icon: 'none' })
} finally {
acting.value = false
}
}
const markReady = (ready) => {
uni.showModal({
title: ready ? '标记证书齐备' : '取消齐备',
content: ready ? '确认该计划危化品证书已齐备?' : '确认取消证书齐备标记?',
success: async (r) => {
if (!r.confirm) return
acting.value = true
try {
await setHazardCertReady(id.value, ready)
uni.showToast({ title: '已更新', icon: 'success' })
load()
} catch (e) {
uni.showToast({ title: e.message || '操作失败', icon: 'none' })
} finally {
acting.value = false
}
}
})
}
onLoad((q) => {
id.value = q?.id || ''
})
onShow(() => load())
</script>
<template>
<view class="mp-page mp-page--sub mp-page--with-bottom">
<view class="mp-header mp-header--pl">
<text class="mp-subpage-back" @click="goBack">← 返回</text>
<text class="mp-header__title" style="margin-top: 16rpx">购买证上传</text>
</view>
<view v-if="detail" class="mp-detail-hero">
<view class="mp-detail-hero__top">
<view>
<text class="mp-detail-hero__title">{{ dash(detail.planNo) }}</text>
<text class="mp-detail-hero__sub">{{ planCardSub(detail) }}</text>
</view>
<text class="mp-tag" :class="'mp-tag--' + certReadyLabel(detail.hazardCertReady).tag">
{{ certReadyLabel(detail.hazardCertReady).text }}
</text>
</view>
</view>
<view class="mp-block">
<text class="mp-block__title">产品购买证</text>
<mp-empty v-if="!products.length" compact title="暂无产品明细" />
<view v-for="p in products" :key="p.id" class="mp-block__panel" style="margin-bottom: 24rpx">
<view class="mp-kv">
<text class="mp-kv__label">{{ dash(p.productName) }}</text>
<text class="mp-kv__value">{{ hasPurchaseCert(p) ? '已上传' : '未上传' }}</text>
</view>
<view class="mp-photo-row" style="margin-top: 16rpx">
<view
v-for="(url, idx) in certUrls(p)"
:key="url + idx"
class="mp-photo-item"
@click="preview(certUrls(p), idx)"
>
<image :src="url" mode="aspectFill" />
</view>
<view
class="mp-photo-add"
:class="{ 'mp-photo-add--disabled': acting }"
@click="uploadForProduct(p)"
>
<text>+</text>
<text style="font-size: 22rpx">拍照</text>
</view>
</view>
</view>
</view>
<view class="mp-bottom-bar">
<button
v-if="!detail?.hazardCertReady"
class="mp-btn mp-btn--primary mp-btn--block"
:disabled="acting"
@click="markReady(true)"
>
标记证书齐备
</button>
<button
v-else
class="mp-btn mp-btn--ghost mp-btn--block"
:disabled="acting"
@click="markReady(false)"
>
取消齐备
</button>
</view>
</view>
</template>