feat: 大量升级,v2.0.0

This commit is contained in:
菲鸽
2024-04-17 15:32:15 +08:00
parent 09fbee72aa
commit 28caa1dea3
37 changed files with 233 additions and 297 deletions

View File

@@ -1,6 +0,0 @@
<!-- 本文件会自动导入 -->
<template>
<span>
<slot />
</span>
</template>

42
src/hooks/useRequest.ts Normal file
View File

@@ -0,0 +1,42 @@
type IUseRequestOptions<T> = {
/** 是否立即执行如果是则在onLoad执行 */
immediate?: boolean
/** 初始化数据 */
initialData?: T
}
/**
* useRequest是一个定制化的请求钩子用于处理异步请求和响应。
* @param func 一个执行异步请求的函数返回一个包含响应数据的Promise。
* @param options 包含请求选项的对象 {immediate, initialData}。
* @param options.immediate 是否立即执行请求默认为true。
* @param options.initialData 初始化数据默认为undefined。
* @returns 返回一个对象{loading, error, data, run},包含请求的加载状态、错误信息、响应数据和手动触发请求的函数。
*/
export default function useRequest<T>(
func: () => Promise<IResData<T>>,
options: IUseRequestOptions<T> = { immediate: true },
) {
const loading = ref(false)
const error = ref(false)
const data = ref<T>()
const run = async () => {
loading.value = true
func()
.then((res) => {
data.value = res.data
error.value = false
})
.catch((err) => {
error.value = err
})
.finally(() => {
loading.value = false
})
}
onLoad(() => {
options.immediate && run()
})
return { loading, error, data, run }
}

9
src/i18n.d.ts vendored
View File

@@ -1,9 +0,0 @@
/* eslint-disable no-unused-vars */
export {}
declare module 'vue' {
interface ComponentCustomProperties {
$t: (key: string, opt?: Record<string, any>) => string
$tm: (key: string, opt?: Record<string, any>) => [] | { [p: string]: any }
}
}

View File

@@ -1,2 +1,3 @@
export { routeInterceptor } from './route'
export { requestInterceptor } from './request'
export { prototypeInterceptor } from './prototype'

View File

@@ -0,0 +1,13 @@
export const prototypeInterceptor = {
install() {
// 解决低版本手机不识别 array.at() 导致运行报错的问题
if (typeof Array.prototype.at !== 'function') {
// eslint-disable-next-line no-extend-native
Array.prototype.at = function (index: number) {
if (index < 0) return this[this.length + index]
if (index >= this.length) return undefined
return this[index]
}
}
},
}

View File

@@ -1,13 +1,16 @@
/* eslint-disable no-param-reassign */
import qs from 'qs'
import { useUserStore } from '@/store'
import { platform } from '@/utils/platform'
export type CustomRequestOptions = UniApp.RequestOptions & {
query?: Record<string, any>
/** 出错时是否隐藏错误提示 */
hideErrorToast?: boolean
} & IUniUploadFileOptions // 添加uni.uploadFile参数类型
// 请求基地址
const baseURL = import.meta.env.VITE_SERVER_BASEURL
// 请求基地址
const baseUrl = import.meta.env.VITE_SERVER_BASEURL
// 拦截器配置
const httpInterceptor = {
@@ -22,19 +25,19 @@ const httpInterceptor = {
options.url += `?${queryStr}`
}
}
// 1. 非 http 开头需拼接地址
// 非 http 开头需拼接地址
if (!options.url.startsWith('http')) {
options.url = baseURL + options.url
options.url = baseUrl + options.url
// TIPS: 如果需要对接多个后端服务,也可以在这里处理,拼接成所需要的地址
}
// 2. 请求超时
// 1. 请求超时
options.timeout = 10000 // 10s
// 3. 添加小程序端请求头标识
// 2. (可选)添加小程序端请求头标识
options.header = {
platform: 'mp-weixin', // 可选与 uniapp 定义的平台一致,告诉后台来源
platform, // 可选与 uniapp 定义的平台一致,告诉后台来源
...options.header,
}
// 4. 添加 token 请求头标识
// 3. 添加 token 请求头标识
const userStore = useUserStore()
const { token } = userStore.userInfo as unknown as IUserInfo
if (token) {

View File

@@ -21,7 +21,7 @@ const isDev = import.meta.env.DEV
const navigateToInterceptor = {
// 注意这里的url是 '/' 开头的,如 '/pages/index/index',跟 'pages.json' 里面的 path 不同
invoke({ url }: { url: string }) {
console.log(url) // /pages/route-interceptor/index?name=feige&age=30
// console.log(url) // /pages/route-interceptor/index?name=feige&age=30
const path = url.split('?')[0]
let needLoginPages: string[] = []
// 为了防止开发时出现BUG这里每次都获取一下。生产环境可以移到函数外性能更好
@@ -30,18 +30,17 @@ const navigateToInterceptor = {
} else {
needLoginPages = _needLoginPages
}
console.log(needLoginPages.includes(path))
if (needLoginPages.includes(path)) {
const isLogin = isLogined()
if (isLogin) {
return true
}
const redirectRoute = `${loginRoute}?redirect=${encodeURIComponent(url)}`
uni.navigateTo({ url: redirectRoute })
return false
const isNeedLogin = needLoginPages.includes(path)
if (!isNeedLogin) {
return true
}
return true
const hasLogin = isLogined()
if (hasLogin) {
return true
}
const redirectRoute = `${loginRoute}?redirect=${encodeURIComponent(url)}`
uni.navigateTo({ url: redirectRoute })
return false
},
}

View File

@@ -3,10 +3,3 @@
<slot />
</view>
</template>
<style lang="scss">
.default-layout {
height: 100vh;
overflow: auto;
}
</style>

View File

@@ -1,5 +1,5 @@
<template>
<view class="text-center p-4">
<view class="demo-layout">
<slot />
</view>
</template>

View File

@@ -1,8 +1,7 @@
import { createSSRApp } from 'vue'
import App from './App.vue'
import store from './store'
import { routeInterceptor, requestInterceptor } from './interceptors'
import 'virtual:svg-icons-register'
import { routeInterceptor, requestInterceptor, prototypeInterceptor } from './interceptors'
import 'virtual:uno.css'
import '@/style/index.scss'
@@ -11,6 +10,7 @@ export function createApp() {
app.use(store)
app.use(routeInterceptor)
app.use(requestInterceptor)
app.use(prototypeInterceptor)
return {
app,
}

View File

@@ -1,6 +1,6 @@
{
"name": "unibest",
"appid": "H5871D791",
"name": "unibest-base",
"appid": "H57F2ACE4",
"description": "",
"versionName": "1.0.0",
"versionCode": "100",
@@ -71,7 +71,6 @@
"enable": false
},
"vueVersion": "3",
"locale": "zh-Hans",
"h5": {
"router": {
"base": "/"

View File

@@ -1,19 +0,0 @@
# 分包配置
`vite.config.ts` 中进行配置。
```ts
import { defineConfig } from 'vite'
import UniPages from '@uni-helper/vite-plugin-uni-pages'
export default defineConfig({
plugins: [
UniPages({
// ... 其他配置
subPackages: [
'src/pages-sub', // 是个数组,可以配置多个
],
}),
],
})
```

View File

@@ -59,6 +59,14 @@
"style": {
"navigationBarTitleText": "请求"
}
},
{
"path": "pages/index/request2",
"type": "page",
"layout": "demo",
"style": {
"navigationBarTitleText": "请求"
}
}
],
"subPackages": []

View File

@@ -16,27 +16,19 @@
鸽友们好我是
<text class="text-red-500">菲鸽</text>
</view>
<view class="text-center mt-8">
<view class="text-center mt-8 text-#fff">
<wd-button type="primary" @click="gotoPage('request')">去请求页</wd-button>
<wd-button type="primary" @click="gotoPage('request2')" class="ml-2">
去请求页2 (请求状态一体化)
</wd-button>
</view>
<view class="text-center py-4">
当前平台是
<text class="text-red-500">{{ PLATFORM.platform }}</text>
</view>
<view class="text-center desc mt-10">设计稿样式编写</view>
<view class="text-center desc">设计稿是750pxcss里面全部写rpx 即可</view>
</view>
</template>
<script lang="ts" setup>
import PLATFORM from '@/utils/platform'
// 获取屏幕边界到安全区域距离
const { safeAreaInsets } = uni.getSystemInfoSync()
console.log(PLATFORM)
const gotoPage = (page: string) => {
uni.navigateTo({
url: `/pages/index/${page}`,

View File

@@ -19,16 +19,21 @@
<view class="text-center text-2xl mt-2 mb-8">最好用的 uniapp 开发模板</view>
<view class="text-justify max-w-100 m-auto text-4 indent mb-2">{{ description }}</view>
<view class="mt-8 text-center">
<text class="text-green-400">当前模板分支base</text>
<view class="text-center mt-8">
当前平台是
<text class="text-green-500">{{ PLATFORM.platform }}</text>
</view>
<view class="text-center mt-4">
模板分支是
<text class="text-green-500">base</text>
</view>
</view>
</template>
<script lang="ts" setup>
import PLATFORM from '@/utils/platform'
// 获取屏幕边界到安全区域距离
const { safeAreaInsets } = uni.getSystemInfoSync()
const author = ref('菲鸽')
const description = ref(
'unibest 是一个集成了多种工具和技术的 uniapp 开发模板,由 uniapp + Vue3 + Ts + Vite4 + UnoCss + UniUI + VSCode 构建,模板具有代码提示、自动格式化、统一配置、代码片段等功能,并内置了许多常用的基本组件和基本功能,让你编写 uniapp 拥有 best 体验。',

View File

@@ -8,35 +8,35 @@
</route>
<template>
<view class="mt-6">
<!-- http://localhost:9000/#/pages/index/request -->
<button @click="getFoo" class="my-4">测试 GET 请求</button>
<view class="text-xl">请求数据如下</view>
<view class="text-green h-10">{{ JSON.stringify(data) }}</view>
<view class="text-xl">完整数据</view>
<view class="text-green h-20">{{ JSON.stringify(originalData) }}</view>
<button @click="postFoo" class="my-4">测试 POST 请求</button>
<view class="text-xl">请求数据如下</view>
<view class="text-green h-10">{{ JSON.stringify(data2) }}</view>
<button class="my-8" type="warn" @click="reset">一键清空数据</button>
<view class="p-6 text-center">
<view class="my-2">使用的是 laf 云后台</view>
<view class="text-green-400">我的推荐码可以获得佣金</view>
<!-- #ifdef H5 -->
<view class="my-2 text-center">
<a class="my-2 text-center" :href="recommendUrl" target="_blank">{{ recommendUrl }}</a>
<view class="my-2">
<a class="my-2" :href="recommendUrl" target="_blank">{{ recommendUrl }}</a>
</view>
<!-- #endif -->
<!-- #ifndef H5 -->
<view class="my-2 text-left text-sm">{{ recommendUrl }}</view>
<!-- #endif -->
<!-- http://localhost:9000/#/pages/index/request -->
<button @click="getFoo" class="my-6">1.测试 GET 请求</button>
<view class="text-xl">请求数据如下</view>
<view class="text-green h-10">{{ JSON.stringify(data) }}</view>
<view class="text-xl">完整数据</view>
<view class="text-green h-16">{{ JSON.stringify(originalData) }}</view>
<button @click="postFoo" class="my-6">2.测试 POST 请求</button>
<view class="text-xl">请求数据如下</view>
<view class="text-green h-10">{{ JSON.stringify(data2) }}</view>
<button class="my-6" type="warn" @click="reset">3.一键清空数据</button>
</view>
</template>
<script lang="ts" setup>
import { getFooAPI, postFooAPI, IFooItem } from '@/service/foo'
import { getFooAPI, postFooAPI, IFooItem } from '@/service/index/foo'
const recommendUrl = ref('http://laf.run/signup?code=ohaOgIX')
@@ -44,6 +44,7 @@ onLoad(() => {
getFoo()
postFoo()
})
const originalData = ref<IResData<IFooItem>>()
const data = ref<IFooItem>()
const getFoo = async () => {

View File

@@ -0,0 +1,30 @@
<route lang="json5">
{
layout: 'demo',
style: {
navigationBarTitleText: '请求',
},
}
</route>
<template>
<view class="p-6 text-center">
<!-- http://localhost:9000/#/pages/index/request -->
<button @click="getFoo" class="my-6">测试 GET 请求</button>
<view class="text-xl">请求数据如下</view>
<view v-if="loading" class="text-blue h-10">加载中...</view>
<view v-else class="text-green h-10">{{ JSON.stringify(data) }}</view>
<button class="my-6" type="warn" @click="reset">一键清空数据</button>
</view>
</template>
<script lang="ts" setup>
import { getFooAPI, IFooItem } from '@/service/index/foo'
const { loading, data, run } = useRequest<IFooItem>(() => getFooAPI('菲鸽'), { immediate: true })
const getFoo = () => run()
const reset = () => {
data.value = undefined
}
</script>

14
src/shime-uni.d.ts vendored
View File

@@ -1,14 +0,0 @@
export {}
declare module 'vue' {
type Hooks = App.AppInstance & Page.PageInstance
interface ComponentCustomOptions extends Hooks {
$uv?: any
}
}
declare global {
interface Uni {
$uv?: any
}
}

14
src/types/global.d.ts vendored Normal file
View File

@@ -0,0 +1,14 @@
declare const __UNI_PLATFORM__:
| 'h5'
| 'app'
| 'mp-alipay'
| 'mp-baidu'
| 'mp-jd'
| 'mp-kuaishou'
| 'mp-lark'
| 'mp-qq'
| 'mp-toutiao'
| 'mp-weixin'
| 'quickapp-webview'
| 'quickapp-webview-huawei'
| 'quickapp-webview-union'

View File

@@ -1,5 +1,3 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable no-unused-vars */
// 全局要用的类型放到这里
type IResData<T> = {

View File

@@ -22,10 +22,11 @@ export const http = <T>(options: CustomRequestOptions) => {
reject(res)
} else {
// 其他错误 -> 根据后端错误信息轻提示
uni.showToast({
icon: 'none',
title: (res.data as IResData<T>).msg || '请求错误',
})
!options.hideErrorToast &&
uni.showToast({
icon: 'none',
title: (res.data as IResData<T>).msg || '请求错误',
})
reject(res)
}
},

View File

@@ -8,7 +8,7 @@ export const getIsTabbar = () => {
return false
}
const pages = getCurrentPages()
const lastPage = getArrElementByIdx(pages, -1)
const lastPage = pages.at(-1)
const currPath = lastPage.route
return !!pagesJson.tabBar.list.find((e) => e.pagePath === currPath)
}
@@ -22,7 +22,7 @@ export const currRoute = () => {
const pages = getCurrentPages()
console.log('pages:', pages)
const lastPage = getArrElementByIdx(pages, -1)
const lastPage = pages.at(-1)
const currRoute = (lastPage as any).$page
// console.log('lastPage.$page:', currRoute)
// console.log('lastPage.$page.fullpath:', currRoute.fullPath)
@@ -105,9 +105,3 @@ export const getNeedLoginPages = (): string[] => getAllPages('needLogin').map((p
* 只得到 path 数组
*/
export const needLoginPages: string[] = getAllPages('needLogin').map((page) => page.path)
export const getArrElementByIdx = (arr: any[], index: number) => {
if (index < 0) return arr[arr.length + index]
if (index >= arr.length) return undefined
return arr[index]
}