页面跳转,跳转拦截

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 path: string
name?: string name?: string
type: string type: string
params?: Record<string, any> isTab: boolean
query?: Record<string, any>
} }

View File

@ -4,7 +4,10 @@
<div <div
class="link-item border border-br px-5 py-[5px] rounded-[3px] cursor-pointer mr-[10px] mb-[10px]" class="link-item border border-br px-5 py-[5px] rounded-[3px] cursor-pointer mr-[10px] mb-[10px]"
v-for="(item, index) in linkList" 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" :key="index"
@click="handleSelect(item)" @click="handleSelect(item)"
> >
@ -32,16 +35,65 @@ const linkList = ref([
{ {
path: '/pages/index/index', path: '/pages/index/index',
name: '商城首页', name: '商城首页',
type: LinkTypeEnum.SHOP_PAGES type: LinkTypeEnum.SHOP_PAGES,
isTab: true
}, },
{ {
path: '/pages/news/news', path: '/pages/news/news',
name: '文章资讯', name: '文章资讯',
type: LinkTypeEnum.SHOP_PAGES type: LinkTypeEnum.SHOP_PAGES,
isTab: true
}, },
{ {
path: '/pages/user/user', path: '/pages/user/user',
name: '个人中心', 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 type: LinkTypeEnum.SHOP_PAGES
} }
]) ])

View File

@ -16,7 +16,7 @@ export const addUnit = (value: string | number, unit = 'px') => {
* @return {Boolean} * @return {Boolean}
*/ */
export const isEmpty = (value: unknown) => { 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 * @description
* @return { Promise } * @return { Promise }
*/ */
export function getArticleCate() { export function getArticleCate() {
return request.get({ url: '/article/category' }) return request.get({ url: '/article/category' })
@ -10,7 +10,7 @@ export function getArticleCate() {
/** /**
* @description * @description
* @return { Promise } * @return { Promise }
*/ */
export function getArticleList(data: Record<string, any>) { export function getArticleList(data: Record<string, any>) {
return request.get({ url: '/article/list', data: data }) return request.get({ url: '/article/list', data: data })
@ -18,8 +18,8 @@ export function getArticleList(data: Record<string, any>) {
/** /**
* @description * @description
* @param { number } id * @param { number } id
* @return { Promise } * @return { Promise }
*/ */
export function getArticleDetail(data: { id: number }) { export function getArticleDetail(data: { id: number }) {
return request.get({ url: '/article/detail', data: data }) return request.get({ url: '/article/detail', data: data })
@ -27,25 +27,25 @@ export function getArticleDetail(data: { id: number }) {
/** /**
* @description * @description
* @param { number } articleId * @param { number } articleId
* @return { Promise } * @return { Promise }
*/ */
export function addCollect(data: { articleId: number }) { 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 * @description
* @param { number } id * @param { number } id
* @return { Promise } * @return { Promise }
*/ */
export function cancelCollect(data: { articleId: number }) { 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 * @description
* @return { Promise } * @return { Promise }
*/ */
export function getCollect() { export function getCollect() {
return request.get({ url: '/article/collect' }) return request.get({ url: '/article/collect' })

View File

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

View File

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

View File

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

View File

@ -9,7 +9,11 @@
indicator-active-color="#4173ff" indicator-active-color="#4173ff"
:autoplay="true" :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 <u-image
mode="aspectFit" mode="aspectFit"
width="100%" width="100%"
@ -24,6 +28,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { useAppStore } from '@/stores/app' import { useAppStore } from '@/stores/app'
import { navigateTo } from '@/utils/util'
const props = defineProps({ const props = defineProps({
content: { content: {
@ -35,6 +40,9 @@ const props = defineProps({
default: () => ({}) default: () => ({})
} }
}) })
const handleClick = (link: any) => {
navigateTo(link)
}
const { getImageUrl } = useAppStore() const { getImageUrl } = useAppStore()
</script> </script>

View File

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

View File

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

View File

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

View File

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

View File

@ -1,3 +1,5 @@
import { isObject } from '@vue/shared'
/** /**
* @description ctx * @description ctx
* @param { String } selector '.app' | '#app' * @param { String } selector '.app' | '#app'
@ -23,3 +25,82 @@ export const getRect = (selector: string, all = false, context?: any) => {
.exec() .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)
}