页面跳转,跳转拦截

This commit is contained in:
Jason 2022-09-09 14:44:55 +08:00
parent cda8b3e3b3
commit cc8fa61bea
15 changed files with 233 additions and 47 deletions

View File

@ -7,5 +7,6 @@ export interface Link {
path: string
name?: string
type: string
params?: Record<string, any>
isTab: boolean
query?: Record<string, any>
}

View File

@ -4,7 +4,10 @@
<div
class="link-item border border-br px-5 py-[5px] rounded-[3px] cursor-pointer mr-[10px] mb-[10px]"
v-for="(item, index) in linkList"
:class="{ 'border-primary text-primary': modelValue.path == item.path }"
:class="{
'border-primary text-primary':
modelValue.path == item.path && modelValue.name == item.name
}"
:key="index"
@click="handleSelect(item)"
>
@ -32,16 +35,65 @@ const linkList = ref([
{
path: '/pages/index/index',
name: '商城首页',
type: LinkTypeEnum.SHOP_PAGES
type: LinkTypeEnum.SHOP_PAGES,
isTab: true
},
{
path: '/pages/news/news',
name: '文章资讯',
type: LinkTypeEnum.SHOP_PAGES
type: LinkTypeEnum.SHOP_PAGES,
isTab: true
},
{
path: '/pages/user/user',
name: '个人中心',
type: LinkTypeEnum.SHOP_PAGES,
isTab: true
},
{
path: '/pages/collection/collection',
name: '我的收藏',
type: LinkTypeEnum.SHOP_PAGES
},
{
path: '/pages/customer_service/customer_service',
name: '联系客服',
type: LinkTypeEnum.SHOP_PAGES
},
{
path: '/pages/user_set/user_set',
name: '个人设置',
type: LinkTypeEnum.SHOP_PAGES
},
{
path: '/pages/as_us/as_us',
name: '关于我们',
type: LinkTypeEnum.SHOP_PAGES
},
{
path: '/pages/user_data/user_data',
name: '个人资料',
type: LinkTypeEnum.SHOP_PAGES
},
{
path: '/pages/agreement/agreement',
name: '隐私政策',
query: {
type: 'privacy'
},
type: LinkTypeEnum.SHOP_PAGES
},
{
path: '/pages/agreement/agreement',
name: '服务协议',
query: {
type: 'service'
},
type: LinkTypeEnum.SHOP_PAGES
},
{
path: '/pages/search/search',
name: '搜索',
type: LinkTypeEnum.SHOP_PAGES
}
])

View File

@ -16,7 +16,7 @@ export const addUnit = (value: string | number, unit = 'px') => {
* @return {Boolean}
*/
export const isEmpty = (value: unknown) => {
return value !== null && value !== '' && typeof value !== 'undefined'
return value == null && typeof value == 'undefined'
}
/**

View File

@ -2,7 +2,7 @@ import request from '@/utils/request'
/**
* @description
* @return { Promise }
* @return { Promise }
*/
export function getArticleCate() {
return request.get({ url: '/article/category' })
@ -10,7 +10,7 @@ export function getArticleCate() {
/**
* @description
* @return { Promise }
* @return { Promise }
*/
export function getArticleList(data: Record<string, any>) {
return request.get({ url: '/article/list', data: data })
@ -18,8 +18,8 @@ export function getArticleList(data: Record<string, any>) {
/**
* @description
* @param { number } id
* @return { Promise }
* @param { number } id
* @return { Promise }
*/
export function getArticleDetail(data: { id: number }) {
return request.get({ url: '/article/detail', data: data })
@ -27,25 +27,25 @@ export function getArticleDetail(data: { id: number }) {
/**
* @description
* @param { number } articleId
* @return { Promise }
* @param { number } articleId
* @return { Promise }
*/
export function addCollect(data: { articleId: number }) {
return request.post({ url: '/article/addCollect', data: data })
return request.post({ url: '/article/addCollect', data: data }, { isAuth: true })
}
/**
* @description
* @param { number } id
* @return { Promise }
* @param { number } id
* @return { Promise }
*/
export function cancelCollect(data: { articleId: number }) {
return request.post({ url: '/article/cancelCollect', data: data })
return request.post({ url: '/article/cancelCollect', data: data }, { isAuth: true })
}
/**
* @description
* @return { Promise }
* @return { Promise }
*/
export function getCollect() {
return request.get({ url: '/article/collect' })

View File

@ -9,7 +9,11 @@
indicator-active-color="#4173ff"
:autoplay="true"
>
<swiper-item v-for="(item, index) in content.data" :key="index">
<swiper-item
v-for="(item, index) in content.data"
:key="index"
@click="handleClick(item.link)"
>
<u-image
mode="aspectFit"
width="100%"
@ -23,6 +27,7 @@
<script setup lang="ts">
import { useAppStore } from '@/stores/app'
import { navigateTo } from '@/utils/util'
const props = defineProps({
content: {
@ -35,6 +40,9 @@ const props = defineProps({
}
})
const { getImageUrl } = useAppStore()
const handleClick = (link: any) => {
navigateTo(link)
}
</script>
<style></style>

View File

@ -11,6 +11,7 @@
v-for="(item, index) in content.data"
:key="index"
class="flex flex-col items-center w-1/4 mb-[15px]"
@click="handleClick(item.link)"
>
<u-image width="52" height="52" :src="getImageUrl(item.image)" alt="" />
<div class="mt-[7px]">{{ item.name }}</div>
@ -21,6 +22,7 @@
v-for="(item, index) in content.data"
:key="index"
class="flex items-center border-light border-solid border-0 border-b h-[100rpx] px-[24rpx]"
@click="handleClick(item.link)"
>
<u-image width="48" height="48" :src="item.image" alt="" />
<div class="ml-[20rpx] flex-1">{{ item.name }}</div>
@ -33,6 +35,7 @@
</template>
<script lang="ts" setup>
import { useAppStore } from '@/stores/app'
import { navigateTo } from '@/utils/util'
const props = defineProps({
content: {
@ -45,6 +48,9 @@ const props = defineProps({
}
})
const { getImageUrl } = useAppStore()
const handleClick = (link: any) => {
navigateTo(link)
}
</script>
<style lang="scss"></style>

View File

@ -5,6 +5,7 @@
v-for="(item, index) in content.data"
:key="index"
class="flex flex-col items-center w-1/5 mb-[30rpx]"
@click="handleClick(item.link)"
>
<u-image width="41px" height="41px" :src="getImageUrl(item.image)" alt="" />
<view class="mt-[14rpx]">{{ item.name }}</view>
@ -15,6 +16,7 @@
<script setup lang="ts">
import { useAppStore } from '@/stores/app'
import { navigateTo } from '@/utils/util'
const props = defineProps({
content: {
@ -27,6 +29,9 @@ const props = defineProps({
}
})
const handleClick = (link: any) => {
navigateTo(link)
}
const { getImageUrl } = useAppStore()
</script>

View File

@ -9,7 +9,11 @@
indicator-active-color="#4173ff"
:autoplay="true"
>
<swiper-item v-for="(item, index) in content.data" :key="index">
<swiper-item
v-for="(item, index) in content.data"
:key="index"
@click="handleClick(item.limk)"
>
<u-image
mode="aspectFit"
width="100%"
@ -24,6 +28,7 @@
<script setup lang="ts">
import { useAppStore } from '@/stores/app'
import { navigateTo } from '@/utils/util'
const props = defineProps({
content: {
@ -35,6 +40,9 @@ const props = defineProps({
default: () => ({})
}
})
const handleClick = (link: any) => {
navigateTo(link)
}
const { getImageUrl } = useAppStore()
</script>

View File

@ -1,10 +1,10 @@
<template>
<div class="user-info flex items-center px-[50rpx]">
<div class="user-info flex px-[50rpx] justify-between py-[50rpx]">
<navigator
v-if="isLogin"
class="flex items-center"
hover-class="none"
url="/pages/login/login"
url="/pages/user_data/user_data"
>
<u-avatar :src="user.avatar" :size="120"></u-avatar>
<div class="text-white text-3xl ml-[20rpx]">{{ user.nickname }}</div>
@ -13,6 +13,9 @@
<u-avatar src="/static/images/user/default_avatar.png" :size="120"></u-avatar>
<div class="text-white text-3xl ml-[20rpx]">未登录</div>
</navigator>
<navigator v-if="isLogin" hover-class="none" url="/pages/user_set/user_set">
<u-icon name="setting" color="#fff" :size="58"></u-icon>
</navigator>
</div>
</template>
<script lang="ts" setup>

View File

@ -90,6 +90,9 @@
"style": {
"navigationBarTitleText": "搜索"
}
},
{
"path": "pages/webview/webview"
}
],
"globalStyle": {

View File

@ -0,0 +1,16 @@
<template>
<web-view :src="url" />
</template>
<script setup lang="ts">
import { onLoad } from '@dcloudio/uni-app'
import { ref } from 'vue'
const url = ref('')
onLoad((options) => {
url.value = options.url!
})
</script>
<style></style>

View File

@ -1,31 +1,27 @@
import { getToken } from '@/utils/auth'
import { generateRoutes } from './transformPages'
const routes = generateRoutes()
export default async function () {
const list = ['navigateTo', 'redirectTo', 'reLaunch', 'switchTab']
list.forEach((item) => {
uni.addInterceptor(item, {
invoke(e) {
// 获取要跳转的页面路径url去掉"?"和"?"后的参数)
const url = e.url.split('?')[0]
const currentRoute = routes.find((item) => {
return url === item.path
export const routes = generateRoutes()
const list = ['navigateTo', 'redirectTo', 'reLaunch', 'switchTab']
list.forEach((item) => {
uni.addInterceptor(item, {
invoke(e) {
// 获取要跳转的页面路径url去掉"?"和"?"后的参数)
const url = e.url.split('?')[0]
const currentRoute = routes.find((item) => {
return url === item.path
})
// 需要登录并且没有token
if (currentRoute?.auth && !getToken()) {
uni.navigateTo({
url: '/pages/login/login'
})
// 需要登录并且没有token
if (currentRoute?.isAuth && !getToken()) {
uni.navigateTo({
url: '/pages/login/login'
})
return false
}
return e
},
fail(err) {
// 失败回调拦截
console.log(err)
return false
}
})
return e
},
fail(err) {
// 失败回调拦截
console.log(err)
}
})
}
})

View File

@ -23,7 +23,7 @@ const requestHooks: RequestHooks = {
return options
},
responseInterceptorsHook(response, config) {
const { isTransformResponse, isReturnDefaultResponse } = config
const { isTransformResponse, isReturnDefaultResponse, isAuth } = config
//返回默认响应,当需要获取响应头及其他数据时可使用
if (isReturnDefaultResponse) {
@ -54,6 +54,11 @@ const requestHooks: RequestHooks = {
case RequestCodeEnum.TOKEN_INVALID:
case RequestCodeEnum.TOKEN_EMPTY:
logout()
if (isAuth && !getToken()) {
uni.navigateTo({
url: '/pages/login/login'
})
}
return Promise.reject()
default:
@ -77,6 +82,7 @@ const defaultOptions: HttpRequestOptions = {
ignoreCancel: false,
// 是否携带token
withToken: true,
isAuth: false,
requestHooks: requestHooks
}

View File

@ -14,6 +14,7 @@ export interface RequestConfig {
urlPrefix: string
ignoreCancel: boolean
withToken: boolean
isAuth: boolean
}
export interface RequestHooks {

View File

@ -1,3 +1,5 @@
import { isObject } from '@vue/shared'
/**
* @description ctx
* @param { String } selector '.app' | '#app'
@ -23,3 +25,82 @@ export const getRect = (selector: string, all = false, context?: any) => {
.exec()
})
}
/**
* @description
*/
export function currentPage() {
const pages = getCurrentPages()
const currentPage = pages[pages.length - 1]
return currentPage || {}
}
/**
* @description
*/
interface Link {
path: string
name?: string
type: string
isTab: boolean
query?: Record<string, any>
}
export enum LinkTypeEnum {
'SHOP_PAGES' = 'shop',
'CUSTOM_LINK' = 'custom'
}
export function navigateTo(link: Link) {
console.log(objectToQuery(link.query), link)
let url: string
switch (link.type) {
case LinkTypeEnum.SHOP_PAGES:
url = link.query ? `${link.path}?${objectToQuery(link.query)}` : link.path
if (link.isTab) {
uni.switchTab({ url })
} else {
uni.navigateTo({ url })
}
break
case LinkTypeEnum.CUSTOM_LINK:
uni.navigateTo({ url: `/pages/webview/webview?url=${link.path}` })
}
}
/**
* @description
* @param {unknown} value
* @return {Boolean}
*/
export const isEmpty = (value: unknown) => {
return value == null && typeof value == 'undefined'
}
/**
* @description Query语法
* @param { Object } params
* @return {string} Query语法
*/
export function objectToQuery(params: Record<string, any>): string {
let query = ''
for (const props of Object.keys(params)) {
const value = params[props]
const part = encodeURIComponent(props) + '='
if (!isEmpty(value)) {
console.log(encodeURIComponent(props), isObject(value))
if (isObject(value)) {
for (const key of Object.keys(value)) {
if (!isEmpty(value[key])) {
const params = props + '[' + key + ']'
const subPart = encodeURIComponent(params) + '='
query += subPart + encodeURIComponent(value[key]) + '&'
}
}
} else {
console.log(part + encodeURIComponent(value), '####')
query += part + encodeURIComponent(value) + '&'
}
}
}
return query.slice(0, -1)
}