|
|
@@ -1,17 +1,151 @@
|
|
|
<template>
|
|
|
- <MpWebviewShell>
|
|
|
+ <MpWebviewShell @ready="onShellReady">
|
|
|
<header class="mp-wv-header">
|
|
|
<div class="mp-wv-header__row">
|
|
|
- <h1 class="mp-wv-header__title">{{ title }}</h1>
|
|
|
+ <button class="mp-wv-header__back" type="button" aria-label="返回详情" @click="goBack">
|
|
|
+ ←
|
|
|
+ </button>
|
|
|
+ <h1 class="mp-wv-header__title">版本历史</h1>
|
|
|
</div>
|
|
|
+ <div v-if="quoteNo" class="mp-wv-header__sub">{{ quoteNo }}</div>
|
|
|
</header>
|
|
|
+
|
|
|
+ <div
|
|
|
+ v-if="loading"
|
|
|
+ class="mp-plan-form-loading mp-plan-form-loading--page"
|
|
|
+ role="status"
|
|
|
+ aria-live="polite"
|
|
|
+ aria-busy="true"
|
|
|
+ >
|
|
|
+ <div class="mp-plan-form-loading__orb" aria-hidden="true">
|
|
|
+ <span class="mp-plan-form-loading__dot" />
|
|
|
+ </div>
|
|
|
+ <p class="mp-plan-form-loading__title">正在加载版本历史</p>
|
|
|
+ <p class="mp-plan-form-loading__desc">请稍候…</p>
|
|
|
+ </div>
|
|
|
+ <div v-else-if="errorText" class="mp-wv-empty">{{ errorText }}</div>
|
|
|
+ <div v-else-if="!versions.length" class="mp-wv-empty">
|
|
|
+ <div class="mp-wv-empty__title">暂无版本历史</div>
|
|
|
+ </div>
|
|
|
+ <div v-else class="mp-wv-detail-body">
|
|
|
+ <article
|
|
|
+ v-for="item in versions"
|
|
|
+ :key="String(item.id)"
|
|
|
+ class="mp-wv-card"
|
|
|
+ @click="goView(item)"
|
|
|
+ >
|
|
|
+ <div class="mp-wv-card__tags">
|
|
|
+ <el-tag v-if="Number(item.isLatest) === 1" type="success" size="small">当前版本</el-tag>
|
|
|
+ <el-tag v-else type="info" size="small">历史版本</el-tag>
|
|
|
+ <el-tag :type="statusTagType(item.status)" size="small">{{ statusLabel(item.status) }}</el-tag>
|
|
|
+ </div>
|
|
|
+ <div class="mp-wv-card__title">{{ item.version || '—' }}</div>
|
|
|
+ <div class="mp-wv-card__meta">{{ item.customerName || '—' }}</div>
|
|
|
+ <div class="mp-wv-card__meta">
|
|
|
+ {{ formatQuoteMoney(item.finalAmount ?? item.totalAmount) }} ·
|
|
|
+ {{ item.createTime || item.quoteDate || '—' }}
|
|
|
+ </div>
|
|
|
+ </article>
|
|
|
+ </div>
|
|
|
</MpWebviewShell>
|
|
|
</template>
|
|
|
+
|
|
|
<script setup lang="ts">
|
|
|
- import { computed } from 'vue'
|
|
|
- import { useRoute } from 'vue-router'
|
|
|
+ import { ref } from 'vue'
|
|
|
+ import { useRoute, useRouter } from 'vue-router'
|
|
|
import MpWebviewShell from '@/layouts/MpWebviewShell.vue'
|
|
|
+ import { getQuote, queryVersions } from '@/api/crm/quote'
|
|
|
+ import { formatQuoteMoney } from '@/utils/mp-crm-quote-card'
|
|
|
+ import { useDictStore } from '@/store/modules/dict'
|
|
|
import '@/styles/mp-webview.scss'
|
|
|
+
|
|
|
const route = useRoute()
|
|
|
- const title = computed(() => String(route.meta.title || ''))
|
|
|
+ const router = useRouter()
|
|
|
+ const dictStore = useDictStore()
|
|
|
+
|
|
|
+ const loading = ref(true)
|
|
|
+ const errorText = ref('')
|
|
|
+ const quoteNo = ref('')
|
|
|
+ const versions = ref<any[]>([])
|
|
|
+
|
|
|
+ function statusLabel(status?: string) {
|
|
|
+ const raw = status || ''
|
|
|
+ return dictStore.getLabel('crm_quote_status', raw) || raw || '—'
|
|
|
+ }
|
|
|
+
|
|
|
+ function statusTagType(status?: string) {
|
|
|
+ return dictStore.getTagType('crm_quote_status', status || '') as
|
|
|
+ | 'success'
|
|
|
+ | 'warning'
|
|
|
+ | 'info'
|
|
|
+ | 'primary'
|
|
|
+ | 'danger'
|
|
|
+ }
|
|
|
+
|
|
|
+ async function loadVersions() {
|
|
|
+ const id = String(route.params.id || '').trim()
|
|
|
+ if (!id) {
|
|
|
+ errorText.value = '缺少报价单 ID'
|
|
|
+ loading.value = false
|
|
|
+ return
|
|
|
+ }
|
|
|
+ loading.value = true
|
|
|
+ try {
|
|
|
+ const detailRes = await getQuote(id)
|
|
|
+ const detail = ((detailRes as any)?.data ?? detailRes) || {}
|
|
|
+ quoteNo.value = String(detail.quoteNo || '')
|
|
|
+ if (!quoteNo.value) {
|
|
|
+ errorText.value = '无法获取报价单号'
|
|
|
+ versions.value = []
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const verRes = await queryVersions(quoteNo.value)
|
|
|
+ const data = (verRes as any)?.data ?? verRes
|
|
|
+ versions.value = Array.isArray(data) ? data : data?.list || data?.rows || []
|
|
|
+ errorText.value = ''
|
|
|
+ } catch (error) {
|
|
|
+ versions.value = []
|
|
|
+ errorText.value = error instanceof Error ? error.message : '加载失败'
|
|
|
+ } finally {
|
|
|
+ loading.value = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ function goBack() {
|
|
|
+ const id = String(route.params.id || '').trim()
|
|
|
+ if (id) {
|
|
|
+ void router.push({ path: `/m/crm/quote/${id}`, query: { from: 'manage' } })
|
|
|
+ return
|
|
|
+ }
|
|
|
+ void router.back()
|
|
|
+ }
|
|
|
+
|
|
|
+ function goView(item: { id?: string | number }) {
|
|
|
+ const vid = String(item.id || '').trim()
|
|
|
+ if (!vid) return
|
|
|
+ void router.push({ path: `/m/crm/quote/${vid}`, query: { from: 'manage' } })
|
|
|
+ }
|
|
|
+
|
|
|
+ function onShellReady() {
|
|
|
+ void loadVersions()
|
|
|
+ }
|
|
|
</script>
|
|
|
+
|
|
|
+<style scoped lang="scss">
|
|
|
+ .mp-wv-card {
|
|
|
+ margin-bottom: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .mp-wv-card__tags {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: 6px;
|
|
|
+ margin-bottom: 6px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .mp-wv-card__title {
|
|
|
+ font-size: 15px;
|
|
|
+ font-weight: 700;
|
|
|
+ color: #087f57;
|
|
|
+ }
|
|
|
+</style>
|