Ver Fonte

feat: 小程序登录

张明明 há 1 ano atrás
pai
commit
72087516df

+ 3 - 0
.env

@@ -0,0 +1,3 @@
+VITE_ENABLE_MOCK=false
+VITE_API_PREFIX=/api
+VITE_PROXY_ENDPOINT=https://bright.yilibili.com/api

+ 2 - 0
.gitignore

@@ -19,3 +19,5 @@ dist
 *.njsproj
 *.sln
 *.sw?
+
+.env

+ 0 - 13
README.md

@@ -1,15 +1,3 @@
-<p align="center">
-  <img src="https://github.com/uni-helper/vitesse-uni-app/raw/main/.github/images/preview.png" width="300"/>
-</p>
-
-<h2 align="center">
-Vitesse for uni-app
-</h2>
-<p align="center">
-  <a href="https://vitesse-uni-app.netlify.app/">📱 在线预览</a>
-  <a href="https://vitesse-docs.netlify.app/">📖 阅读文档</a>
-</p>
-
 ## 特性
 
 - ⚡️ [Vue 3](https://github.com/vuejs/core), [Vite](https://github.com/vitejs/vite), [pnpm](https://pnpm.io/), [esbuild](https://github.com/evanw/esbuild) - 就是快!
@@ -20,7 +8,6 @@ Vitesse for uni-app
 
 - 📑 [布局系统](./src/layouts)
 
-
 - 😃 [各种图标集为你所用](https://github.com/antfu/unocss/tree/main/packages/preset-icons)
 
 - 🔥 使用 [新的 `<script setup>` 语法](https://github.com/vuejs/rfcs/pull/227)

+ 6 - 2
package.json

@@ -60,7 +60,11 @@
     "@dcloudio/uni-mp-xhs": "3.0.0-4020920240930001",
     "@dcloudio/uni-quickapp-webview": "3.0.0-4020920240930001",
     "@dcloudio/uni-ui": "^1.5.7",
+    "@uni-helper/axios-adapter": "^1.5.2",
     "@vueuse/core": "^11.2.0",
+    "axios": "^1.7.7",
+    "pinia": "^2.2.6",
+    "pinia-plugin-persistedstate": "^4.1.3",
     "vue": "~3.4.38",
     "vue-i18n": "^9.14.1"
   },
@@ -109,6 +113,6 @@
     "pre-commit": "pnpm lint-staged"
   },
   "lint-staged": {
-    "*": "eslint --fix"
+    "*": "eslint"
   }
-}
+}

Diff do ficheiro suprimidas por serem muito extensas
+ 320 - 134
pnpm-lock.yaml


+ 1 - 1
project.config.json

@@ -25,4 +25,4 @@
     "tabIndent": "insertSpaces",
     "tabSize": 2
   }
-}
+}

+ 1 - 1
project.private.config.json

@@ -3,4 +3,4 @@
   "setting": {
     "compileHotReLoad": true
   }
-}
+}

+ 8 - 1
src/App.vue

@@ -1,5 +1,12 @@
 <script setup lang="ts">
-onLaunch(() => {})
+import { useAppStore } from '@/stores/app'
+
+onLaunch(() => {
+  const authStore = useAppStore()
+  if (authStore.token === ' ') {
+    authStore.login()
+  }
+})
 </script>
 
 <template>

+ 70 - 0
src/api/httpClient.ts

@@ -0,0 +1,70 @@
+import { useAppStore } from '@/stores/app'
+import { createUniAppAxiosAdapter } from '@uni-helper/axios-adapter'
+import axios from 'axios'
+
+const instance = axios.create({
+  baseURL: import.meta.env.VITE_API_URL,
+  adapter: createUniAppAxiosAdapter(),
+})
+
+export default {
+  get: async <T>(uri: string, params?: object) => {
+    return (await instance.get<T>(uri, { params })).data
+  },
+  post: async <T>(uri: string, data: object = {}) => {
+    return (await instance.post<T>(uri, data)).data
+  },
+  put: async <T>(uri: string, data: object) => {
+    return (await instance.put<T>(uri, data)).data
+  },
+  uploadFile: async <T>(uri: string, filePath: string) => {
+    return new Promise<T>((resolve, reject) => {
+      uni.uploadFile({
+        url: import.meta.env.VITE_API_URL + uri,
+        header: {
+          Authorization: `Bearer ${useAppStore().token}`,
+        },
+        filePath,
+        name: 'file',
+        success: (res) => {
+          // json序列化
+          resolve(JSON.parse(res.data) as T)
+        },
+        fail: (error) => {
+          reject(error)
+        },
+      })
+    })
+  },
+}
+
+instance.interceptors.response.use(
+  (response) => {
+    if (response.data.code) {
+      uni.showToast({
+        title: response.data.message,
+        icon: 'fail',
+        duration: 2000,
+      })
+      return Promise.reject(new Error(response.data.message))
+    }
+    return response
+  },
+  async (error) => {
+    if (error.response.data.code === 401) {
+      const appStore = useAppStore()
+      await appStore.login()
+      return instance.request(error.config)
+    }
+
+    return Promise.reject(error)
+  },
+)
+
+instance.interceptors.request.use((config) => {
+  const appStore = useAppStore()
+  if (appStore.token) {
+    config.headers.set('Authorization', `Bearer ${appStore.token}`)
+  }
+  return config
+})

+ 6 - 0
src/api/token.ts

@@ -0,0 +1,6 @@
+import type { CreateTokenRequest } from '@/model/token'
+import httpClient from './httpClient'
+
+export function createToken(createTokenRequest: CreateTokenRequest) {
+  return httpClient.post<{ token: string }>('/tokens', createTokenRequest)
+}

+ 2 - 1
src/auto-imports.d.ts

@@ -35,6 +35,7 @@ declare global {
   const extendRef: typeof import('@vueuse/core')['extendRef']
   const getCurrentInstance: typeof import('vue')['getCurrentInstance']
   const getCurrentScope: typeof import('vue')['getCurrentScope']
+  const getSafeHeight: typeof import('./utils/index')['getSafeHeight']
   const h: typeof import('vue')['h']
   const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch']
   const inject: typeof import('vue')['inject']
@@ -351,6 +352,7 @@ declare module 'vue' {
     readonly extendRef: UnwrapRef<typeof import('@vueuse/core')['extendRef']>
     readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']>
     readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']>
+    readonly getSafeHeight: UnwrapRef<typeof import('./utils/index')['getSafeHeight']>
     readonly h: UnwrapRef<typeof import('vue')['h']>
     readonly ignorableWatch: UnwrapRef<typeof import('@vueuse/core')['ignorableWatch']>
     readonly inject: UnwrapRef<typeof import('vue')['inject']>
@@ -609,7 +611,6 @@ declare module 'vue' {
     readonly useWindowFocus: UnwrapRef<typeof import('@vueuse/core')['useWindowFocus']>
     readonly useWindowScroll: UnwrapRef<typeof import('@vueuse/core')['useWindowScroll']>
     readonly useWindowSize: UnwrapRef<typeof import('@vueuse/core')['useWindowSize']>
-    readonly utils: UnwrapRef<typeof import('./utils/index')['default']>
     readonly watch: UnwrapRef<typeof import('vue')['watch']>
     readonly watchArray: UnwrapRef<typeof import('@vueuse/core')['watchArray']>
     readonly watchAtMost: UnwrapRef<typeof import('@vueuse/core')['watchAtMost']>

+ 4 - 0
src/main.ts

@@ -1,10 +1,14 @@
+import { createPinia } from 'pinia'
 import { createSSRApp } from 'vue'
 import App from './App.vue'
 import './styles/tailwind.css'
 
 export function createApp() {
+  const pinia = createPinia()
   const app = createSSRApp(App)
+  app.use(pinia)
   return {
     app,
+    pinia,
   }
 }

+ 4 - 0
src/model/token.ts

@@ -0,0 +1,4 @@
+export interface CreateTokenRequest {
+  username: string
+  password: string
+}

+ 1 - 1
src/pages/pet-manual/index.vue

@@ -3,7 +3,7 @@
 import bg from '@/static/image/feed-plan/bg.png'
 import circle from '@/static/image/feed-plan/circle.png'
 import message from '@/static/image/feed-plan/message.png'
-import {getSafeHeight} from '@/utils'
+import { getSafeHeight } from '@/utils'
 
 interface ListItem {
   img: string

+ 39 - 0
src/stores/app.ts

@@ -0,0 +1,39 @@
+import { createToken } from '@/api/token'
+import { defineStore } from 'pinia'
+import { computed, ref } from 'vue'
+
+export const useAppStore = defineStore(
+  'app',
+  () => {
+    const token = ref('')
+
+    const login = () => {
+      uni.showLoading({ title: '登录中' })
+      return new Promise<void>((resolve, reject) => {
+        uni.login({
+          provider: 'weixin',
+          success: async (result) => {
+            const data = await createToken(result.code)
+            token.value = data.token
+            uni.hideLoading()
+            resolve()
+          },
+          fail: async (error) => {
+            uni.hideLoading()
+            reject(error)
+          },
+        })
+      })
+    }
+
+    const isLogin = computed(() => {
+      return !!token.value
+    })
+
+    return {
+      token,
+      isLogin,
+      login,
+    }
+  },
+)

+ 1 - 1
src/utils/index.ts

@@ -6,5 +6,5 @@ function getSafeHeight(): number {
 }
 
 export {
-  getSafeHeight
+  getSafeHeight,
 }

Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff