fix: 登录页签残留、表单校验脱节与仓库入口合并
All checks were successful
Build and Deploy Front / deploy (push) Successful in 6m30s
All checks were successful
Build and Deploy Front / deploy (push) Successful in 6m30s
排除登录路由进页签;FormPro 内部 model 优先;侧栏仓库选择与地址弹窗合并并可切换。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
3642d650db
commit
3bfe6c6a26
@ -223,6 +223,7 @@
|
||||
<template>
|
||||
<a-form
|
||||
ref="formRef"
|
||||
v-bind="$attrs"
|
||||
v-model="formValue"
|
||||
:label-col-props="labelColProps"
|
||||
:layout="formLayout"
|
||||
@ -230,7 +231,6 @@
|
||||
:size="size"
|
||||
:wrapper-col-props="wrapperColProps"
|
||||
class="form-pro-surface"
|
||||
v-bind="$attrs"
|
||||
>
|
||||
<a-row
|
||||
v-if="layout === 'default' || formLayout === 'vertical'"
|
||||
|
||||
@ -120,6 +120,30 @@ async function loadCustomerCode() {
|
||||
}
|
||||
}
|
||||
|
||||
function syncWarehouseOptions(rows: WarehouseDto[]) {
|
||||
warehouseStore.setOptions(
|
||||
rows
|
||||
.filter((row) => row.id != null)
|
||||
.map((row) => ({
|
||||
label: row.warehouseName || String(row.id),
|
||||
value: Number(row.id),
|
||||
})),
|
||||
)
|
||||
}
|
||||
|
||||
function selectWarehouse(item: WarehouseDto) {
|
||||
const id = Number(item.id)
|
||||
if (!id) return
|
||||
if (id === currentId.value) return
|
||||
syncWarehouseOptions(list.value)
|
||||
warehouseStore.setWarehouseId(id)
|
||||
Message.success(
|
||||
t('nav.warehousePeek.switched', {
|
||||
name: item.warehouseName || String(id),
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
async function loadList() {
|
||||
loading.value = true
|
||||
try {
|
||||
@ -128,6 +152,7 @@ async function loadList() {
|
||||
loadCustomerCode(),
|
||||
])
|
||||
list.value = (res.items ?? []).map(normalize).sort(compareWarehouseSort)
|
||||
syncWarehouseOptions(list.value)
|
||||
} catch {
|
||||
list.value = []
|
||||
} finally {
|
||||
@ -171,6 +196,7 @@ watch(
|
||||
{{ t('nav.warehousePeek.tip') }}
|
||||
<span v-if="customerCode" class="peek-tip__code">{{ customerCode }}</span>
|
||||
</p>
|
||||
<p class="peek-hint">{{ t('nav.warehousePeek.selectHint') }}</p>
|
||||
|
||||
<a-spin :loading="loading" class="peek-spin">
|
||||
<div v-if="!orderedList.length && !loading" class="peek-empty">
|
||||
@ -182,6 +208,12 @@ watch(
|
||||
:key="String(item.id)"
|
||||
class="peek-card"
|
||||
:class="{ 'is-current': Number(item.id) === currentId }"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
:aria-pressed="Number(item.id) === currentId"
|
||||
@click="selectWarehouse(item)"
|
||||
@keydown.enter.prevent="selectWarehouse(item)"
|
||||
@keydown.space.prevent="selectWarehouse(item)"
|
||||
>
|
||||
<header class="peek-card__head">
|
||||
<div class="peek-card__title">
|
||||
@ -191,43 +223,53 @@ watch(
|
||||
{{ t('nav.warehousePeek.current') }}
|
||||
</span>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
class="peek-card__copy-all"
|
||||
:title="t('system.warehouseAddress.actions.copy')"
|
||||
@click="copyItem(item)"
|
||||
>
|
||||
<icon-copy />
|
||||
<span>{{ t('nav.warehousePeek.copyAll') }}</span>
|
||||
</button>
|
||||
<div class="peek-card__actions" @click.stop>
|
||||
<button
|
||||
v-if="Number(item.id) !== currentId"
|
||||
type="button"
|
||||
class="peek-card__use"
|
||||
@click="selectWarehouse(item)"
|
||||
>
|
||||
{{ t('nav.warehousePeek.useThis') }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="peek-card__copy-all"
|
||||
:title="t('system.warehouseAddress.actions.copy')"
|
||||
@click="copyItem(item)"
|
||||
>
|
||||
<icon-copy />
|
||||
<span>{{ t('nav.warehousePeek.copyAll') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="peek-card__rows">
|
||||
<div class="peek-row">
|
||||
<span class="peek-row__label">{{ t('system.warehouseAddress.fields.recipient') }}</span>
|
||||
<span class="peek-row__value" :title="displayRecipient(item)">{{ displayRecipient(item) }}</span>
|
||||
<button type="button" class="peek-row__copy" @click="copyField(displayRecipient(item))">
|
||||
<button type="button" class="peek-row__copy" @click.stop="copyField(displayRecipient(item))">
|
||||
<icon-copy />
|
||||
</button>
|
||||
</div>
|
||||
<div class="peek-row">
|
||||
<span class="peek-row__label">{{ t('system.warehouseAddress.fields.contactPhone') }}</span>
|
||||
<span class="peek-row__value" :title="item.contactPhone || '-'">{{ item.contactPhone || '-' }}</span>
|
||||
<button type="button" class="peek-row__copy" @click="copyField(item.contactPhone || '')">
|
||||
<button type="button" class="peek-row__copy" @click.stop="copyField(item.contactPhone || '')">
|
||||
<icon-copy />
|
||||
</button>
|
||||
</div>
|
||||
<div class="peek-row peek-row--address">
|
||||
<span class="peek-row__label">{{ t('system.warehouseAddress.fields.shippingAddress') }}</span>
|
||||
<span class="peek-row__value" :title="displayAddress(item)">{{ displayAddress(item) }}</span>
|
||||
<button type="button" class="peek-row__copy" @click="copyField(displayAddress(item))">
|
||||
<button type="button" class="peek-row__copy" @click.stop="copyField(displayAddress(item))">
|
||||
<icon-copy />
|
||||
</button>
|
||||
</div>
|
||||
<div v-if="item.remark" class="peek-row">
|
||||
<span class="peek-row__label">{{ t('system.warehouseAddress.fields.remark') }}</span>
|
||||
<span class="peek-row__value" :title="item.remark">{{ item.remark }}</span>
|
||||
<button type="button" class="peek-row__copy" @click="copyField(item.remark || '')">
|
||||
<button type="button" class="peek-row__copy" @click.stop="copyField(item.remark || '')">
|
||||
<icon-copy />
|
||||
</button>
|
||||
</div>
|
||||
@ -239,7 +281,7 @@ watch(
|
||||
|
||||
<style scoped lang="less">
|
||||
.peek-tip {
|
||||
margin: 0 0 12px;
|
||||
margin: 0 0 6px;
|
||||
padding: 8px 10px;
|
||||
border-radius: 6px;
|
||||
background: color-mix(in srgb, var(--app-primary-color, #1d7281) 8%, #fff);
|
||||
@ -256,6 +298,13 @@ watch(
|
||||
}
|
||||
}
|
||||
|
||||
.peek-hint {
|
||||
margin: 0 0 12px;
|
||||
color: var(--color-text-3);
|
||||
font-size: 12px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.peek-spin {
|
||||
display: block;
|
||||
width: 100%;
|
||||
@ -276,15 +325,22 @@ watch(
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--color-border-2, #e5e6eb);
|
||||
background: #fff;
|
||||
cursor: pointer;
|
||||
transition: border-color 0.14s ease, background-color 0.14s ease, box-shadow 0.14s ease;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
border-color: color-mix(in srgb, var(--app-primary-color, #1d7281) 28%, transparent);
|
||||
}
|
||||
|
||||
&.is-current {
|
||||
border-color: color-mix(in srgb, var(--app-primary-color, #1d7281) 35%, transparent);
|
||||
background: color-mix(in srgb, var(--app-primary-color, #1d7281) 5%, #fff);
|
||||
box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--app-primary-color, #1d7281) 12%, transparent);
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
&__head {
|
||||
@ -295,6 +351,29 @@ watch(
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
&__actions {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
&__use {
|
||||
height: 26px;
|
||||
padding: 0 8px;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
background: var(--app-primary-color, #1d7281);
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
filter: brightness(1.05);
|
||||
}
|
||||
}
|
||||
|
||||
&__title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@ -129,26 +129,16 @@
|
||||
</div>
|
||||
|
||||
<div class="customer-side-rail__footer-row">
|
||||
<div class="customer-side-rail__warehouse-group">
|
||||
<div class="customer-side-rail__warehouse">
|
||||
<ContactService
|
||||
variant="sider"
|
||||
dropdown-position="tl"
|
||||
trigger="click"
|
||||
content-class="csr-dock-dropdown"
|
||||
:compact="compactLayout"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
class="customer-side-rail__tool customer-side-rail__warehouse-view"
|
||||
:title="t('nav.warehousePeek.title')"
|
||||
:aria-label="t('nav.warehousePeek.title')"
|
||||
@click="openWarehouseAddressPeek"
|
||||
>
|
||||
<icon-eye />
|
||||
</button>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
class="customer-side-rail__warehouse-btn"
|
||||
:class="{ 'is-compact': compactLayout }"
|
||||
:title="warehouseDockTitle"
|
||||
:aria-label="warehouseDockTitle"
|
||||
@click="openWarehouseAddressPeek"
|
||||
>
|
||||
<span class="customer-side-rail__warehouse-btn-text">{{ warehouseDockLabel }}</span>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="customer-side-rail__toggle"
|
||||
@ -175,10 +165,11 @@ import { Message } from '@arco-design/web-vue'
|
||||
import {
|
||||
IconDoubleLeft,
|
||||
IconDoubleRight,
|
||||
IconEye,
|
||||
IconPrinter,
|
||||
} from '@arco-design/web-vue/es/icon'
|
||||
import { useCurrentWarehouseStore } from '@/store'
|
||||
import { useRbacUserStore } from '@/store/modules/rbac-user'
|
||||
import { getWarehouseList } from '@/api/system/warehouse'
|
||||
import { getSubMenuIcon } from '@/utils/menu-icon'
|
||||
import { MENU_NAME_TO_LOCALE_KEY, translateMenuTitle } from '@/utils/menu-i18n'
|
||||
import { openWindow, regexUrl } from '@/utils'
|
||||
@ -209,7 +200,6 @@ import {
|
||||
} from '@/utils/customer-portal-nav'
|
||||
import { resolvePortalDrawerPanel } from '@/views/user/portal-drawer/types'
|
||||
import { openPortalSideDrawer } from '@/views/user/portal-drawer/usePortalSideDrawer'
|
||||
import ContactService from '@/components/ContactService/index.vue'
|
||||
import RightTopMessage from '@/components/top-nav/RightTopMessage.vue'
|
||||
import RightTopUser from '@/components/top-nav/RightTopUser.vue'
|
||||
import WarehouseAddressPeekModal from '@/components/customer-side-rail/WarehouseAddressPeekModal.vue'
|
||||
@ -218,6 +208,7 @@ const { t, te, locale } = useI18n()
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const rbacUserStore = useRbacUserStore()
|
||||
const warehouseStore = useCurrentWarehouseStore()
|
||||
const printConnectionState = useHiprintClientState()
|
||||
|
||||
/** 与 CSS transition 时长一致(Linear 风格约 300ms) */
|
||||
@ -319,10 +310,41 @@ function handleCustomerBalanceChanged() {
|
||||
|
||||
const warehousePeekVisible = ref(false)
|
||||
|
||||
const warehouseDockName = computed(
|
||||
() =>
|
||||
warehouseStore.warehouseName ||
|
||||
t('nav.contactService.selectWarehouse'),
|
||||
)
|
||||
|
||||
const warehouseDockLabel = computed(() => {
|
||||
const name = warehouseDockName.value
|
||||
if (compactLayout.value) return name.slice(0, 1) || '仓'
|
||||
return name
|
||||
})
|
||||
|
||||
const warehouseDockTitle = computed(
|
||||
() => `${t('nav.warehousePeek.title')}: ${warehouseDockName.value}`,
|
||||
)
|
||||
|
||||
function openWarehouseAddressPeek() {
|
||||
warehousePeekVisible.value = true
|
||||
}
|
||||
|
||||
async function ensureWarehouseOptions() {
|
||||
try {
|
||||
const { items } = await getWarehouseList({ page: 1, pageSize: 100 })
|
||||
const list = (items ?? [])
|
||||
.filter((row) => row.id != null)
|
||||
.map((row) => ({
|
||||
label: row.warehouseName || String(row.id),
|
||||
value: Number(row.id),
|
||||
}))
|
||||
warehouseStore.setOptions(list)
|
||||
} catch {
|
||||
/* 侧栏仅展示已缓存仓名,打开弹窗时再拉地址 */
|
||||
}
|
||||
}
|
||||
|
||||
function groupLabel(group: CustomerNavGroup) {
|
||||
if (te(group.labelKey)) return t(group.labelKey)
|
||||
return group.labelFallback
|
||||
@ -469,6 +491,7 @@ watch(activePath, () => {
|
||||
|
||||
onMounted(() => {
|
||||
initHiprintClientState().catch(() => undefined)
|
||||
void ensureWarehouseOptions()
|
||||
window.addEventListener(CUSTOMER_BALANCE_CHANGED_EVENT, handleCustomerBalanceChanged)
|
||||
})
|
||||
|
||||
@ -561,41 +584,46 @@ onUnmounted(() => {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
&__warehouse-group {
|
||||
&__warehouse-btn {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
&__warehouse {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
|
||||
:deep(.contact-service--sider) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
:deep(.contact-service--sider .contact-service__label) {
|
||||
padding-right: 2px;
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&__warehouse-view {
|
||||
width: 26px;
|
||||
height: 30px;
|
||||
margin-left: -1px;
|
||||
border-radius: 0 6px 6px 0;
|
||||
padding: 0 8px;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
background: rgba(255, 255, 255, 0.55);
|
||||
color: var(--color-text-3);
|
||||
color: var(--color-text-2);
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
line-height: 1.2;
|
||||
cursor: pointer;
|
||||
text-align: left;
|
||||
transition: color 0.14s ease, background-color 0.14s ease;
|
||||
|
||||
&:hover {
|
||||
color: var(--app-primary-color);
|
||||
color: var(--app-primary-color, #1d7281);
|
||||
background: rgba(255, 255, 255, 0.92);
|
||||
}
|
||||
|
||||
&.is-compact {
|
||||
flex: 0 0 auto;
|
||||
width: 36px;
|
||||
min-width: 36px;
|
||||
height: 28px;
|
||||
padding: 0;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
&__warehouse-btn-text {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
&__message-slot {
|
||||
@ -1031,41 +1059,14 @@ onUnmounted(() => {
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.customer-side-rail__warehouse-group {
|
||||
.customer-side-rail__warehouse-btn {
|
||||
width: 36px;
|
||||
min-width: 36px;
|
||||
height: 28px;
|
||||
flex: 0 0 auto;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
.customer-side-rail__warehouse {
|
||||
width: 36px;
|
||||
flex: 0 0 auto;
|
||||
|
||||
:deep(.contact-service--sider .contact-service__label) {
|
||||
width: 36px;
|
||||
min-width: 36px;
|
||||
height: 28px;
|
||||
min-height: 28px;
|
||||
padding: 0;
|
||||
border-radius: 6px;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
:deep(.contact-service--sider .contact-service__text) {
|
||||
flex: none;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.customer-side-rail__warehouse-view {
|
||||
width: 28px;
|
||||
height: 24px;
|
||||
margin-left: 0;
|
||||
border-radius: 6px;
|
||||
padding: 0;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
|
||||
@ -352,9 +352,8 @@
|
||||
if (nextRoute.query?._refresh || nextRoute.query?._r) {
|
||||
return;
|
||||
}
|
||||
if (!nextRoute.meta.noAffix) {
|
||||
tabBarStore.updateTabList(nextRoute);
|
||||
}
|
||||
// 登录/官网等独立壳不进页签;具体过滤在 updateTabList
|
||||
tabBarStore.updateTabList(nextRoute);
|
||||
nextTick(() => scrollActiveTagIntoView());
|
||||
}, true);
|
||||
|
||||
|
||||
@ -1699,6 +1699,9 @@ export default {
|
||||
'nav.userMenu.switchLanguage': 'Switch to {lang}',
|
||||
'nav.warehousePeek.title': 'Warehouse address',
|
||||
'nav.warehousePeek.tip': 'Put your customer code on the parcel for warehouse intake',
|
||||
'nav.warehousePeek.selectHint': 'Click a card to switch the shipping warehouse',
|
||||
'nav.warehousePeek.useThis': 'Use',
|
||||
'nav.warehousePeek.switched': 'Switched to {name}',
|
||||
'nav.warehousePeek.current': 'Current',
|
||||
'nav.warehousePeek.copyAll': 'Copy',
|
||||
'nav.warehousePeek.empty': 'No warehouse address yet',
|
||||
|
||||
@ -1455,6 +1455,9 @@ export default {
|
||||
'nav.userMenu.switchLanguage': '切换到{lang}',
|
||||
'nav.warehousePeek.title': '仓库地址',
|
||||
'nav.warehousePeek.tip': '寄件请备注客户编号,便于仓库认领',
|
||||
'nav.warehousePeek.selectHint': '点击卡片可切换当前发货仓库',
|
||||
'nav.warehousePeek.useThis': '选用',
|
||||
'nav.warehousePeek.switched': '已切换为 {name}',
|
||||
'nav.warehousePeek.current': '当前',
|
||||
'nav.warehousePeek.copyAll': '复制',
|
||||
'nav.warehousePeek.empty': '暂无仓库地址',
|
||||
|
||||
@ -33,6 +33,8 @@ const router = createRouter({
|
||||
meta: {
|
||||
requiresAuth: false,
|
||||
loginPortal: 'customer',
|
||||
noAffix: true,
|
||||
hideInMenu: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -42,6 +44,8 @@ const router = createRouter({
|
||||
meta: {
|
||||
requiresAuth: false,
|
||||
loginPortal: 'admin',
|
||||
noAffix: true,
|
||||
hideInMenu: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -61,6 +65,7 @@ const router = createRouter({
|
||||
meta: {
|
||||
requiresAuth: false,
|
||||
hideInMenu: true,
|
||||
noAffix: true,
|
||||
customerPortalOnly: true,
|
||||
locale: 'h5.login.title',
|
||||
},
|
||||
@ -73,6 +78,7 @@ const router = createRouter({
|
||||
meta: {
|
||||
requiresAuth: false,
|
||||
hideInMenu: true,
|
||||
noAffix: true,
|
||||
adminPortalOnly: true,
|
||||
locale: 'h5Admin.login.title',
|
||||
},
|
||||
|
||||
@ -9,6 +9,7 @@ import { isString } from '@/utils/is';
|
||||
import { useRbacUserStore } from '@/store/modules/rbac-user';
|
||||
import { buildMenuTitleMaps, resolveMenuTitleByPath, resolveMenuTitleFromTree } from '@/utils/menu-display';
|
||||
import { translateMenuTitleByPath } from '@/utils/menu-i18n';
|
||||
import { isLoginRouteName } from '@/utils/login-portal';
|
||||
import i18n from '@/locale';
|
||||
import type { MenuTreeDto } from '@/api/rbac';
|
||||
import { TabBarState, TagProps } from './types';
|
||||
@ -56,7 +57,19 @@ const formatTag = (route: RouteLocationNormalized): TagProps => {
|
||||
};
|
||||
};
|
||||
|
||||
const BAN_LIST = [REDIRECT_ROUTE_NAME];
|
||||
const BAN_LIST = [REDIRECT_ROUTE_NAME, 'H5Login', 'H5AdminLogin', 'siteRoot'];
|
||||
|
||||
function shouldSkipTabRoute(route: RouteLocationNormalized): boolean {
|
||||
const name = route.name != null ? String(route.name) : '';
|
||||
if (!name) return true;
|
||||
if (BAN_LIST.includes(name)) return true;
|
||||
if (isLoginRouteName(name)) return true;
|
||||
if (route.meta?.noAffix) return true;
|
||||
if (route.meta?.requiresAuth === false && (route.path === '/login' || route.path === '/admin')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const useTabBarStore = defineStore('tabBar', {
|
||||
state: (): TabBarState => ({
|
||||
@ -104,7 +117,11 @@ const useTabBarStore = defineStore('tabBar', {
|
||||
},
|
||||
|
||||
updateTabList(route: RouteLocationNormalized) {
|
||||
if (BAN_LIST.includes(route.name as string)) return;
|
||||
if (shouldSkipTabRoute(route)) return;
|
||||
// 登录页曾被误写入时清掉,避免登录成功后仍挂着「login」页签
|
||||
this.tagList = this.tagList.filter(
|
||||
(tag) => !isLoginRouteName(tag.name) && tag.name !== 'H5Login' && tag.name !== 'H5AdminLogin',
|
||||
);
|
||||
const next = formatTag(route);
|
||||
const idx = this.tagList.findIndex(
|
||||
(tag) =>
|
||||
@ -131,6 +148,13 @@ const useTabBarStore = defineStore('tabBar', {
|
||||
/** 菜单/标签点击立刻高亮,不等路由 afterEach */
|
||||
previewNavigate(tag: TagProps) {
|
||||
if (!tag?.fullPath && !tag?.name) return;
|
||||
if (
|
||||
isLoginRouteName(tag.name) ||
|
||||
tag.name === 'H5Login' ||
|
||||
tag.name === 'H5AdminLogin'
|
||||
) {
|
||||
return;
|
||||
}
|
||||
this.previewingPath = tag.fullPath || '';
|
||||
this.previewingName = tag.name || '';
|
||||
const exists = this.tagList.some(
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import type { RouteLocationRaw } from 'vue-router';
|
||||
import { isNavigationFailure } from 'vue-router';
|
||||
import router from '@/router';
|
||||
import { useUserStore } from '@/store';
|
||||
import { useUserStore, useTabBarStore } from '@/store';
|
||||
import { ensureDynamicRouterReady } from '@/router/ensure-dynamic-router';
|
||||
import { ensureHeavyPlugins } from '@/plugins/heavy-plugins';
|
||||
import { ensureFullLocaleMessages } from '@/locale';
|
||||
@ -63,6 +63,8 @@ export async function enterSystemAfterLogin(options: {
|
||||
]);
|
||||
|
||||
skipNextPageTransition();
|
||||
// 登录壳不进业务页签;进系统前清空,避免残留「login」标签
|
||||
useTabBarStore().resetTabList();
|
||||
|
||||
try {
|
||||
await router.replace({ ...options.target } as RouteLocationRaw);
|
||||
|
||||
@ -168,9 +168,9 @@ async function handleSubmit() {
|
||||
{{ t('order.waybillManage.changeStatus.modalTip') }}
|
||||
</a-alert>
|
||||
|
||||
<!-- 勿传 :model:FormPro 用内部 formValue;attrs 会覆盖导致输入与校验脱节 -->
|
||||
<FormPro
|
||||
ref="formRef"
|
||||
:model="formState"
|
||||
:item-list="itemList"
|
||||
:row-gutter="16"
|
||||
:default-span="24"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user