页面跳转,跳转拦截
This commit is contained in:
parent
cda8b3e3b3
commit
cc8fa61bea
|
|
@ -7,5 +7,6 @@ export interface Link {
|
|||
path: string
|
||||
name?: string
|
||||
type: string
|
||||
params?: Record<string, any>
|
||||
isTab: boolean
|
||||
query?: Record<string, any>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
])
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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' })
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -90,6 +90,9 @@
|
|||
"style": {
|
||||
"navigationBarTitleText": "搜索"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/webview/webview"
|
||||
}
|
||||
],
|
||||
"globalStyle": {
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ export interface RequestConfig {
|
|||
urlPrefix: string
|
||||
ignoreCancel: boolean
|
||||
withToken: boolean
|
||||
isAuth: boolean
|
||||
}
|
||||
|
||||
export interface RequestHooks {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue