|
|
@@ -2,16 +2,159 @@
|
|
|
<MpWebviewShell>
|
|
|
<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="goList">
|
|
|
+ ←
|
|
|
+ </button>
|
|
|
+ <h1 class="mp-wv-header__title">{{ pageTitle }}</h1>
|
|
|
</div>
|
|
|
</header>
|
|
|
+ <div
|
|
|
+ v-if="contentLoading || bootLoading"
|
|
|
+ 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">{{ loadingCopy.title }}</p>
|
|
|
+ <p class="mp-plan-form-loading__desc">{{ loadingCopy.desc }}</p>
|
|
|
+ <div class="mp-plan-form-loading__skel" aria-hidden="true">
|
|
|
+ <div class="mp-wv-skel mp-wv-skel--block" />
|
|
|
+ <div class="mp-wv-skel mp-wv-skel--mid" />
|
|
|
+ <div class="mp-wv-skel mp-wv-skel--line" />
|
|
|
+ <div class="mp-wv-skel mp-wv-skel--short" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div v-else-if="bootError" class="mp-wv-empty">{{ bootError }}</div>
|
|
|
+ <ContractFormDialog
|
|
|
+ v-if="formReady"
|
|
|
+ v-show="!contentLoading"
|
|
|
+ :key="formKey"
|
|
|
+ variant="page"
|
|
|
+ :visible="true"
|
|
|
+ :edit-id="editId"
|
|
|
+ :copy-source="copySource"
|
|
|
+ @loading-change="onLoadingChange"
|
|
|
+ @success="onSuccess"
|
|
|
+ @update:visible="onVisibleChange"
|
|
|
+ />
|
|
|
</MpWebviewShell>
|
|
|
</template>
|
|
|
+
|
|
|
<script setup lang="ts">
|
|
|
- import { computed } from 'vue'
|
|
|
- import { useRoute } from 'vue-router'
|
|
|
+ import { computed, ref, watch } from 'vue'
|
|
|
+ import { useRoute, useRouter } from 'vue-router'
|
|
|
import MpWebviewShell from '@/layouts/MpWebviewShell.vue'
|
|
|
+ import ContractFormDialog from '@/views/crm/contract/components/ContractFormDialog.vue'
|
|
|
+ import { getContract, type ContractVO } from '@/api/crm/contract'
|
|
|
+ import { MP_CRM_CONTRACT_LIST_PATH } from '@/utils/mp-webview'
|
|
|
import '@/styles/mp-webview.scss'
|
|
|
+
|
|
|
const route = useRoute()
|
|
|
- const title = computed(() => String(route.meta.title || ''))
|
|
|
+ const router = useRouter()
|
|
|
+ const contentLoading = ref(true)
|
|
|
+ const bootLoading = ref(false)
|
|
|
+ const bootError = ref('')
|
|
|
+ const formReady = ref(false)
|
|
|
+ const copySource = ref<ContractVO | null>(null)
|
|
|
+
|
|
|
+ const pageMode = computed<'add' | 'edit' | 'copy'>(() => {
|
|
|
+ if (route.name === 'MpCrmContractEdit') return 'edit'
|
|
|
+ const copyFrom = String(route.query.copyFrom || '').trim()
|
|
|
+ if (copyFrom) return 'copy'
|
|
|
+ return 'add'
|
|
|
+ })
|
|
|
+
|
|
|
+ const pageTitle = computed(() => {
|
|
|
+ if (pageMode.value === 'copy') return '复制合同'
|
|
|
+ if (pageMode.value === 'edit') return '编辑合同'
|
|
|
+ return String(route.meta.title || '新增合同')
|
|
|
+ })
|
|
|
+
|
|
|
+ const editId = computed(() => {
|
|
|
+ if (pageMode.value !== 'edit') return null
|
|
|
+ const id = String(route.params.id || '').trim()
|
|
|
+ return id || null
|
|
|
+ })
|
|
|
+
|
|
|
+ const copyFromId = computed(() => {
|
|
|
+ if (pageMode.value !== 'copy') return null
|
|
|
+ const id = String(route.query.copyFrom || '').trim()
|
|
|
+ return id || null
|
|
|
+ })
|
|
|
+
|
|
|
+ const formKey = computed(
|
|
|
+ () =>
|
|
|
+ `${String(route.name || '')}-${pageMode.value}-${editId.value || ''}-${copyFromId.value || ''}`
|
|
|
+ )
|
|
|
+
|
|
|
+ const loadingCopy = computed(() => {
|
|
|
+ if (pageMode.value === 'edit') {
|
|
|
+ return { title: '正在加载合同', desc: '请稍候,正在获取合同详情…' }
|
|
|
+ }
|
|
|
+ if (pageMode.value === 'copy') {
|
|
|
+ return { title: '正在复制合同', desc: '请稍候,正在预填原单数据…' }
|
|
|
+ }
|
|
|
+ return { title: '正在准备表单', desc: '请稍候,正在初始化主数据…' }
|
|
|
+ })
|
|
|
+
|
|
|
+ async function bootForm() {
|
|
|
+ formReady.value = false
|
|
|
+ bootError.value = ''
|
|
|
+ copySource.value = null
|
|
|
+ contentLoading.value = true
|
|
|
+
|
|
|
+ if (pageMode.value === 'copy' && copyFromId.value) {
|
|
|
+ bootLoading.value = true
|
|
|
+ try {
|
|
|
+ const res = await getContract(copyFromId.value)
|
|
|
+ copySource.value = ((res as any)?.data ?? res) as ContractVO
|
|
|
+ formReady.value = true
|
|
|
+ } catch (error) {
|
|
|
+ bootError.value = error instanceof Error ? error.message : '加载复制来源失败'
|
|
|
+ } finally {
|
|
|
+ bootLoading.value = false
|
|
|
+ }
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ formReady.value = true
|
|
|
+ }
|
|
|
+
|
|
|
+ watch(
|
|
|
+ formKey,
|
|
|
+ () => {
|
|
|
+ void bootForm()
|
|
|
+ },
|
|
|
+ { immediate: true }
|
|
|
+ )
|
|
|
+
|
|
|
+ function onLoadingChange(loading: boolean) {
|
|
|
+ contentLoading.value = loading
|
|
|
+ }
|
|
|
+
|
|
|
+ function goList() {
|
|
|
+ void router.replace(MP_CRM_CONTRACT_LIST_PATH)
|
|
|
+ }
|
|
|
+
|
|
|
+ function onVisibleChange(visible: boolean) {
|
|
|
+ if (!visible) goList()
|
|
|
+ }
|
|
|
+
|
|
|
+ function onSuccess() {
|
|
|
+ if (pageMode.value === 'edit' && editId.value) {
|
|
|
+ void router.replace(`/m/crm/contract/${editId.value}`)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ goList()
|
|
|
+ }
|
|
|
</script>
|
|
|
+
|
|
|
+<style scoped lang="scss">
|
|
|
+ :deep(.contract-form-dialog--page) {
|
|
|
+ position: relative;
|
|
|
+ z-index: 1;
|
|
|
+ }
|
|
|
+</style>
|