Explorar o código

style: 统一代码格式和类型定义,测试eslint --fix, 还是有报错

feige996 hai 10 meses
pai
achega
227f19a93c

+ 30 - 30
.github/release.yml

@@ -1,31 +1,31 @@
 categories:
-  - title: '🚀 新功能'
-    labels: ['feat', 'feature']
-  - title: '🛠️ 修复'
-    labels: ['fix', 'bugfix']
-  - title: '💅 样式'
-    labels: ['style']
-  - title: '📄 文档'
-    labels: ['docs']
-  - title: '⚡️ 性能'
-    labels: ['perf']
-  - title: '🧪 测试'
-    labels: ['test']
-  - title: '♻️ 重构'
-    labels: ['refactor']
-  - title: '📦 构建'
-    labels: ['build']
-  - title: '🚨 补丁'
-    labels: ['patch', 'hotfix']
-  - title: '🌐 发布'
-    labels: ['release', 'publish']
-  - title: '🔧 流程'
-    labels: ['ci', 'cd', 'workflow']
-  - title: '⚙️ 配置'
-    labels: ['config', 'chore']
-  - title: '📁 文件'
-    labels: ['file']
-  - title: '🎨 格式化'
-    labels: ['format']
-  - title: '🔀 其他'
-    labels: ['other', 'misc']
+  - title: 🚀 新功能
+    labels: [feat, feature]
+  - title: 🛠️ 修复
+    labels: [fix, bugfix]
+  - title: 💅 样式
+    labels: [style]
+  - title: 📄 文档
+    labels: [docs]
+  - title: ⚡️ 性能
+    labels: [perf]
+  - title: 🧪 测试
+    labels: [test]
+  - title: ♻️ 重构
+    labels: [refactor]
+  - title: 📦 构建
+    labels: [build]
+  - title: 🚨 补丁
+    labels: [patch, hotfix]
+  - title: 🌐 发布
+    labels: [release, publish]
+  - title: 🔧 流程
+    labels: [ci, cd, workflow]
+  - title: ⚙️ 配置
+    labels: [config, chore]
+  - title: 📁 文件
+    labels: [file]
+  - title: 🎨 格式化
+    labels: [format]
+  - title: 🔀 其他
+    labels: [other, misc]

+ 16 - 16
manifest.config.ts

@@ -1,6 +1,6 @@
+import path from 'node:path'
 // manifest.config.ts
 import { defineManifestConfig } from '@uni-helper/vite-plugin-uni-manifest'
-import path from 'node:path'
 import { loadEnv } from 'vite'
 
 // 获取环境变量的范例
@@ -14,14 +14,14 @@ const {
 } = env
 
 export default defineManifestConfig({
-  name: VITE_APP_TITLE,
-  appid: VITE_UNI_APPID,
-  description: '',
-  versionName: '1.0.0',
-  versionCode: '100',
-  transformPx: false,
-  locale: VITE_FALLBACK_LOCALE, // 'zh-Hans'
-  h5: {
+  'name': VITE_APP_TITLE,
+  'appid': VITE_UNI_APPID,
+  'description': '',
+  'versionName': '1.0.0',
+  'versionCode': '100',
+  'transformPx': false,
+  'locale': VITE_FALLBACK_LOCALE, // 'zh-Hans'
+  'h5': {
     router: {
       base: VITE_APP_PUBLIC_BASE,
     },
@@ -82,14 +82,14 @@ export default defineManifestConfig({
         ios: {
           appstore: 'static/app/icons/1024x1024.png',
           ipad: {
-            app: 'static/app/icons/76x76.png',
+            'app': 'static/app/icons/76x76.png',
             'app@2x': 'static/app/icons/152x152.png',
-            notification: 'static/app/icons/20x20.png',
+            'notification': 'static/app/icons/20x20.png',
             'notification@2x': 'static/app/icons/40x40.png',
             'proapp@2x': 'static/app/icons/167x167.png',
-            settings: 'static/app/icons/29x29.png',
+            'settings': 'static/app/icons/29x29.png',
             'settings@2x': 'static/app/icons/58x58.png',
-            spotlight: 'static/app/icons/40x40.png',
+            'spotlight': 'static/app/icons/40x40.png',
             'spotlight@2x': 'static/app/icons/80x80.png',
           },
           iphone: {
@@ -107,7 +107,7 @@ export default defineManifestConfig({
     },
   },
   /* 快应用特有相关 */
-  quickapp: {},
+  'quickapp': {},
   /* 小程序特有相关 */
   'mp-weixin': {
     appid: VITE_WX_APPID,
@@ -130,8 +130,8 @@ export default defineManifestConfig({
   'mp-toutiao': {
     usingComponents: true,
   },
-  uniStatistics: {
+  'uniStatistics': {
     enable: false,
   },
-  vueVersion: '3',
+  'vueVersion': '3',
 })

+ 1 - 1
scripts/postupgrade.js

@@ -3,7 +3,7 @@
 // # 只需要执行下面的命令即可
 
 // eslint-disable-next-line @typescript-eslint/no-var-requires
-const { exec } = require('child_process')
+const { exec } = require('node:child_process')
 
 // 定义要执行的命令
 const dependencies = [

+ 2 - 2
src/App.vue

@@ -1,7 +1,7 @@
 <script setup lang="ts">
-import { onLaunch, onShow, onHide } from '@dcloudio/uni-app'
-import 'abortcontroller-polyfill/dist/abortcontroller-polyfill-only'
+import { onHide, onLaunch, onShow } from '@dcloudio/uni-app'
 import { usePageAuth } from '@/hooks/usePageAuth'
+import 'abortcontroller-polyfill/dist/abortcontroller-polyfill-only'
 
 usePageAuth()
 

+ 11 - 11
src/api/login.ts

@@ -1,4 +1,4 @@
-import { ICaptcha, IUpdateInfo, IUpdatePassword, IUserInfoVo, IUserLogin } from './login.typings'
+import type { ICaptcha, IUpdateInfo, IUpdatePassword, IUserInfoVo, IUserLogin } from './login.typings'
 import { http } from '@/utils/http'
 
 /**
@@ -15,7 +15,7 @@ export interface ILoginForm {
  * 获取验证码
  * @returns ICaptcha 验证码
  */
-export const getCode = () => {
+export function getCode() {
   return http.get<ICaptcha>('/user/getCode')
 }
 
@@ -23,35 +23,35 @@ export const getCode = () => {
  * 用户登录
  * @param loginForm 登录表单
  */
-export const login = (loginForm: ILoginForm) => {
+export function login(loginForm: ILoginForm) {
   return http.post<IUserLogin>('/user/login', loginForm)
 }
 
 /**
  * 获取用户信息
  */
-export const getUserInfo = () => {
+export function getUserInfo() {
   return http.get<IUserInfoVo>('/user/info')
 }
 
 /**
  * 退出登录
  */
-export const logout = () => {
+export function logout() {
   return http.get<void>('/user/logout')
 }
 
 /**
  * 修改用户信息
  */
-export const updateInfo = (data: IUpdateInfo) => {
+export function updateInfo(data: IUpdateInfo) {
   return http.post('/user/updateInfo', data)
 }
 
 /**
  * 修改用户密码
  */
-export const updateUserPassword = (data: IUpdatePassword) => {
+export function updateUserPassword(data: IUpdatePassword) {
   return http.post('/user/updatePassword', data)
 }
 
@@ -59,12 +59,12 @@ export const updateUserPassword = (data: IUpdatePassword) => {
  * 获取微信登录凭证
  * @returns Promise 包含微信登录凭证(code)
  */
-export const getWxCode = () => {
+export function getWxCode() {
   return new Promise<UniApp.LoginRes>((resolve, reject) => {
     uni.login({
       provider: 'weixin',
-      success: (res) => resolve(res),
-      fail: (err) => reject(new Error(err)),
+      success: res => resolve(res),
+      fail: err => reject(new Error(err)),
     })
   })
 }
@@ -78,6 +78,6 @@ export const getWxCode = () => {
  * @param params 微信登录参数,包含code
  * @returns Promise 包含登录结果
  */
-export const wxLogin = (data: { code: string }) => {
+export function wxLogin(data: { code: string }) {
   return http.post<IUserLogin>('/user/wxLogin', data)
 }

+ 6 - 6
src/api/login.typings.ts

@@ -1,7 +1,7 @@
 /**
  * 用户信息
  */
-export type IUserInfoVo = {
+export interface IUserInfoVo {
   id: number
   username: string
   avatar: string
@@ -11,7 +11,7 @@ export type IUserInfoVo = {
 /**
  * 登录返回的信息
  */
-export type IUserLogin = {
+export interface IUserLogin {
   id: string
   username: string
   token: string
@@ -20,7 +20,7 @@ export type IUserLogin = {
 /**
  * 获取验证码
  */
-export type ICaptcha = {
+export interface ICaptcha {
   captchaEnabled: boolean
   uuid: string
   image: string
@@ -28,7 +28,7 @@ export type ICaptcha = {
 /**
  * 上传成功的信息
  */
-export type IUploadSuccessInfo = {
+export interface IUploadSuccessInfo {
   fileId: number
   originalName: string
   fileName: string
@@ -41,7 +41,7 @@ export type IUploadSuccessInfo = {
 /**
  * 更新用户信息
  */
-export type IUpdateInfo = {
+export interface IUpdateInfo {
   id: number
   name: string
   sex: string
@@ -49,7 +49,7 @@ export type IUpdateInfo = {
 /**
  * 更新用户信息
  */
-export type IUpdatePassword = {
+export interface IUpdatePassword {
   id: number
   oldPassword: string
   newPassword: string

+ 1 - 1
src/env.d.ts

@@ -2,7 +2,7 @@
 /// <reference types="vite-svg-loader" />
 
 declare module '*.vue' {
-  import { DefineComponent } from 'vue'
+  import type { DefineComponent } from 'vue'
   // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
   const component: DefineComponent<{}, {}, any>
   export default component

+ 4 - 3
src/hooks/usePageAuth.ts

@@ -1,10 +1,10 @@
 import { onLoad } from '@dcloudio/uni-app'
-import { needLoginPages as _needLoginPages, getNeedLoginPages } from '@/utils'
 import { useUserStore } from '@/store'
+import { needLoginPages as _needLoginPages, getNeedLoginPages } from '@/utils'
 
 const loginRoute = import.meta.env.VITE_LOGIN_URL
 const isDev = import.meta.env.DEV
-const isLogined = () => {
+function isLogined() {
   const userStore = useUserStore()
   return !!userStore.userInfo.username
 }
@@ -20,7 +20,8 @@ export function usePageAuth() {
     let needLoginPages: string[] = []
     if (isDev) {
       needLoginPages = getNeedLoginPages()
-    } else {
+    }
+    else {
       needLoginPages = _needLoginPages
     }
 

+ 2 - 2
src/hooks/useRequest.ts

@@ -1,6 +1,6 @@
-import { UnwrapRef } from 'vue'
+import type { UnwrapRef } from 'vue'
 
-type IUseRequestOptions<T> = {
+interface IUseRequestOptions<T> {
   /** 是否立即执行 */
   immediate?: boolean
   /** 初始化数据 */

+ 7 - 5
src/hooks/useUpload.ts

@@ -7,7 +7,7 @@ type TfileType = 'image' | 'file'
 type TImage = 'png' | 'jpg' | 'jpeg' | 'webp' | '*'
 type TFile = 'doc' | 'docx' | 'ppt' | 'zip' | 'xls' | 'xlsx' | 'txt' | TImage
 
-type TOptions<T extends TfileType> = {
+interface TOptions<T extends TfileType> {
   formData?: Record<string, any>
   maxSize?: number
   accept?: T extends 'image' ? TImage[] : TFile[]
@@ -72,7 +72,8 @@ export default function useUpload<T extends TfileType>(options: TOptions<T> = {}
       // #ifndef MP-WEIXIN
       uni.chooseImage(chooseFileOptions)
       // #endif
-    } else {
+    }
+    else {
       uni.chooseFile({
         ...chooseFileOptions,
         type: 'all',
@@ -80,7 +81,7 @@ export default function useUpload<T extends TfileType>(options: TOptions<T> = {}
     }
   }
 
-  const handleFileChoose = ({ tempFilePath, size }: { tempFilePath: string; size: number }) => {
+  const handleFileChoose = ({ tempFilePath, size }: { tempFilePath: string, size: number }) => {
     if (size > maxSize) {
       uni.showToast({
         title: `文件大小不能超过 ${maxSize / 1024 / 1024}MB`,
@@ -102,7 +103,7 @@ export default function useUpload<T extends TfileType>(options: TOptions<T> = {}
 
     loading.value = true
     uploadFile({
-      tempFilePath: tempFilePath,
+      tempFilePath,
       formData,
       onSuccess: (res) => {
         const { data: _data } = JSON.parse(res)
@@ -145,7 +146,8 @@ async function uploadFile({
       try {
         const data = uploadFileRes.data
         onSuccess(data)
-      } catch (err) {
+      }
+      catch (err) {
         onError(err)
       }
     },

+ 2 - 2
src/interceptors/index.ts

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

+ 4 - 2
src/interceptors/prototype.ts

@@ -4,8 +4,10 @@ export const prototypeInterceptor = {
     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
+        if (index < 0)
+          return this[this.length + index]
+        if (index >= this.length)
+          return undefined
         return this[index]
       }
     }

+ 5 - 4
src/interceptors/request.ts

@@ -1,8 +1,7 @@
-/* eslint-disable no-param-reassign */
 import qs from 'qs'
 import { useUserStore } from '@/store'
-import { platform } from '@/utils/platform'
 import { getEnvBaseUrl } from '@/utils'
+import { platform } from '@/utils/platform'
 
 export type CustomRequestOptions = UniApp.RequestOptions & {
   query?: Record<string, any>
@@ -22,7 +21,8 @@ const httpInterceptor = {
       const queryStr = qs.stringify(options.query)
       if (options.url.includes('?')) {
         options.url += `&${queryStr}`
-      } else {
+      }
+      else {
         options.url += `?${queryStr}`
       }
     }
@@ -33,7 +33,8 @@ const httpInterceptor = {
       if (JSON.parse(__VITE_APP_PROXY__)) {
         // 自动拼接代理前缀
         options.url = import.meta.env.VITE_APP_PROXY_PREFIX + options.url
-      } else {
+      }
+      else {
         options.url = baseUrl + options.url
       }
       // #endif

+ 4 - 3
src/interceptors/route.ts

@@ -5,12 +5,12 @@
  * 我这里应为大部分都可以随便进入,所以使用黑名单
  */
 import { useUserStore } from '@/store'
-import { needLoginPages as _needLoginPages, getNeedLoginPages, getLastPage } from '@/utils'
+import { needLoginPages as _needLoginPages, getLastPage, getNeedLoginPages } from '@/utils'
 
 // TODO Check
 const loginRoute = import.meta.env.VITE_LOGIN_URL
 
-const isLogined = () => {
+function isLogined() {
   const userStore = useUserStore()
   return !!userStore.userInfo.username
 }
@@ -37,7 +37,8 @@ const navigateToInterceptor = {
     // 为了防止开发时出现BUG,这里每次都获取一下。生产环境可以移到函数外,性能更好
     if (isDev) {
       needLoginPages = getNeedLoginPages()
-    } else {
+    }
+    else {
       needLoginPages = _needLoginPages
     }
     const isNeedLogin = needLoginPages.includes(path)

+ 8 - 8
src/layouts/default.vue

@@ -1,11 +1,3 @@
-<template>
-  <wd-config-provider :themeVars="themeVars">
-    <slot />
-    <wd-toast />
-    <wd-message-box />
-  </wd-config-provider>
-</template>
-
 <script lang="ts" setup>
 import type { ConfigProviderThemeVars } from 'wot-design-uni'
 
@@ -15,3 +7,11 @@ const themeVars: ConfigProviderThemeVars = {
   // buttonPrimaryColor: '#07c160',
 }
 </script>
+
+<template>
+  <wd-config-provider :theme-vars="themeVars">
+    <slot />
+    <wd-toast />
+    <wd-message-box />
+  </wd-config-provider>
+</template>

+ 8 - 8
src/layouts/demo.vue

@@ -1,11 +1,3 @@
-<template>
-  <wd-config-provider :themeVars="themeVars">
-    <slot />
-    <wd-toast />
-    <wd-message-box />
-  </wd-config-provider>
-</template>
-
 <script lang="ts" setup>
 import type { ConfigProviderThemeVars } from 'wot-design-uni'
 
@@ -15,3 +7,11 @@ const themeVars: ConfigProviderThemeVars = {
   // buttonPrimaryColor: '#07c160',
 }
 </script>
+
+<template>
+  <wd-config-provider :theme-vars="themeVars">
+    <slot />
+    <wd-toast />
+    <wd-message-box />
+  </wd-config-provider>
+</template>

+ 38 - 38
src/layouts/fg-tabbar/fg-tabbar.vue

@@ -1,11 +1,43 @@
+<script setup lang="ts">
+import { tabbarStore } from './tabbar'
+// 'i-carbon-code',
+import { tabbarList as _tabBarList, cacheTabbarEnable, selectedTabbarStrategy } from './tabbarList'
+
+const customTabbarEnable = selectedTabbarStrategy === 1 || selectedTabbarStrategy === 2
+/** tabbarList 里面的 path 从 pages.config.ts 得到 */
+const tabbarList = _tabBarList.map(item => ({ ...item, path: `/${item.pagePath}` }))
+function selectTabBar({ value: index }: { value: number }) {
+  const url = tabbarList[index].path
+  tabbarStore.setCurIdx(index)
+  if (cacheTabbarEnable) {
+    uni.switchTab({ url })
+  }
+  else {
+    uni.navigateTo({ url })
+  }
+}
+onLoad(() => {
+  // 解决原生 tabBar 未隐藏导致有2个 tabBar 的问题
+  const hideRedundantTabbarEnable = selectedTabbarStrategy === 1
+  hideRedundantTabbarEnable
+  && uni.hideTabBar({
+    fail(err) {
+      console.log('hideTabBar fail: ', err)
+    },
+    success(res) {
+      console.log('hideTabBar success: ', res)
+    },
+  })
+})
+</script>
+
 <template>
   <wd-tabbar
     v-if="customTabbarEnable"
-    fixed
+
     v-model="tabbarStore.curIdx"
-    bordered
-    safeAreaInsetBottom
-    placeholder
+
+    bordered safeareainsetbottom placeholder fixed
     @change="selectTabBar"
   >
     <block v-for="(item, idx) in tabbarList" :key="item.path">
@@ -13,7 +45,7 @@
         v-if="item.iconType === 'wot'"
         :title="item.text"
         :icon="item.icon"
-      ></wd-tabbar-item>
+      />
       <wd-tabbar-item
         v-else-if="item.iconType === 'unocss' || item.iconType === 'iconfont'"
         :title="item.text"
@@ -23,7 +55,7 @@
             h-40rpx
             w-40rpx
             :class="[item.icon, idx === tabbarStore.curIdx ? 'is-active' : 'is-inactive']"
-          ></view>
+          />
         </template>
       </wd-tabbar-item>
       <wd-tabbar-item v-else-if="item.iconType === 'local'" :title="item.text">
@@ -34,35 +66,3 @@
     </block>
   </wd-tabbar>
 </template>
-
-<script setup lang="ts">
-// 'i-carbon-code',
-import { tabbarList as _tabBarList, cacheTabbarEnable, selectedTabbarStrategy } from './tabbarList'
-import { tabbarStore } from './tabbar'
-
-const customTabbarEnable = selectedTabbarStrategy === 1 || selectedTabbarStrategy === 2
-/** tabbarList 里面的 path 从 pages.config.ts 得到 */
-const tabbarList = _tabBarList.map((item) => ({ ...item, path: `/${item.pagePath}` }))
-function selectTabBar({ value: index }: { value: number }) {
-  const url = tabbarList[index].path
-  tabbarStore.setCurIdx(index)
-  if (cacheTabbarEnable) {
-    uni.switchTab({ url })
-  } else {
-    uni.navigateTo({ url })
-  }
-}
-onLoad(() => {
-  // 解决原生 tabBar 未隐藏导致有2个 tabBar 的问题
-  const hideRedundantTabbarEnable = selectedTabbarStrategy === 1
-  hideRedundantTabbarEnable &&
-    uni.hideTabBar({
-      fail(err) {
-        console.log('hideTabBar fail: ', err)
-      },
-      success(res) {
-        console.log('hideTabBar success: ', res)
-      },
-    })
-})
-</script>

+ 10 - 10
src/layouts/tabbar.vue

@@ -1,15 +1,6 @@
-<template>
-  <wd-config-provider :themeVars="themeVars">
-    <slot />
-    <fg-tabbar />
-    <wd-toast />
-    <wd-message-box />
-  </wd-config-provider>
-</template>
-
 <script lang="ts" setup>
-import FgTabbar from './fg-tabbar/fg-tabbar.vue'
 import type { ConfigProviderThemeVars } from 'wot-design-uni'
+import FgTabbar from './fg-tabbar/fg-tabbar.vue'
 
 const themeVars: ConfigProviderThemeVars = {
   // colorTheme: 'red',
@@ -17,3 +8,12 @@ const themeVars: ConfigProviderThemeVars = {
   // buttonPrimaryColor: '#07c160',
 }
 </script>
+
+<template>
+  <wd-config-provider :theme-vars="themeVars">
+    <slot />
+    <FgTabbar />
+    <wd-toast />
+    <wd-message-box />
+  </wd-config-provider>
+</template>

+ 3 - 3
src/main.ts

@@ -1,11 +1,11 @@
-import '@/style/index.scss'
 import { VueQueryPlugin } from '@tanstack/vue-query'
-import 'virtual:uno.css'
 import { createSSRApp } from 'vue'
-
 import App from './App.vue'
 import { prototypeInterceptor, requestInterceptor, routeInterceptor } from './interceptors'
+
 import store from './store'
+import '@/style/index.scss'
+import 'virtual:uno.css'
 
 export function createApp() {
   const app = createSSRApp(App)

+ 1 - 1
src/manifest.json

@@ -110,4 +110,4 @@
       "base": "/"
     }
   }
-}
+}

+ 10 - 6
src/pages-sub/demo/index.vue

@@ -7,17 +7,21 @@
 }
 </route>
 
+<script lang="ts" setup>
+// code here
+</script>
+
 <template>
   <view class="text-center">
-    <view class="m-8">http://localhost:9000/#/pages-sub/demo/index</view>
-    <view class="text-green-500">分包页面demo</view>
+    <view class="m-8">
+      http://localhost:9000/#/pages-sub/demo/index
+    </view>
+    <view class="text-green-500">
+      分包页面demo
+    </view>
   </view>
 </template>
 
-<script lang="ts" setup>
-// code here
-</script>
-
 <style lang="scss" scoped>
 //
 </style>

+ 1 - 1
src/pages.json

@@ -62,4 +62,4 @@
     }
   ],
   "subPackages": []
-}
+}

+ 13 - 11
src/pages/about/about.vue

@@ -7,17 +7,6 @@
 }
 </route>
 
-<template>
-  <view>
-    <view class="text-center text-3xl mt-8">
-      鸽友们好,我是
-      <text class="text-red-500">菲鸽</text>
-    </view>
-    <RequestComp />
-    <UploadComp />
-  </view>
-</template>
-
 <script lang="ts" setup>
 import RequestComp from './components/request.vue'
 import UploadComp from './components/upload.vue'
@@ -33,6 +22,19 @@ const { safeAreaInsets } = uni.getSystemInfoSync()
 console.log('about')
 </script>
 
+<template>
+  <view>
+    <view class="mt-8 text-center text-3xl">
+      鸽友们好,我是
+      <text class="text-red-500">
+        菲鸽
+      </text>
+    </view>
+    <RequestComp />
+    <UploadComp />
+  </view>
+</template>
+
 <style lang="scss" scoped>
 .test-css {
   // 16rpx=>0.5rem

+ 47 - 30
src/pages/about/components/request.vue

@@ -7,36 +7,9 @@
 }
 </route>
 
-<template>
-  <view class="p-6 text-center">
-    <view class="my-2">使用的是 laf 云后台</view>
-    <view class="text-green-400">我的推荐码,可以获得佣金</view>
-
-    <!-- #ifdef H5 -->
-    <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 -->
-    <wd-button @click="run" class="my-6">发送请求</wd-button>
-    <view class="h-16">
-      <view v-if="loading">loading...</view>
-      <block v-else>
-        <view class="text-xl">请求数据如下</view>
-        <view class="text-green leading-8">{{ JSON.stringify(data) }}</view>
-      </block>
-    </view>
-    <wd-button type="error" @click="reset" class="my-6" :disabled="!data">重置数据</wd-button>
-  </view>
-</template>
-
 <script lang="ts" setup>
-import { getFooAPI, postFooAPI, IFooItem } from '@/service/index/foo'
+import type { IFooItem } from '@/service/index/foo'
+import { getFooAPI } from '@/service/index/foo'
 // import { findPetsByStatusQueryOptions } from '@/service/app'
 // import { useQuery } from '@tanstack/vue-query'
 
@@ -61,7 +34,51 @@ const { loading, error, data, run } = useRequest<IFooItem>(() => getFooAPI('菲
 //   refetch,
 // } = useQuery(findPetsByStatusQueryOptions({ params: { status: ['available'] } }))
 
-const reset = () => {
+function reset() {
   data.value = initialData
 }
 </script>
+
+<template>
+  <view class="p-6 text-center">
+    <view class="my-2">
+      使用的是 laf 云后台
+    </view>
+    <view class="text-green-400">
+      我的推荐码,可以获得佣金
+    </view>
+
+    <!-- #ifdef H5 -->
+    <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 -->
+    <wd-button class="my-6" @click="run">
+      发送请求
+    </wd-button>
+    <view class="h-16">
+      <view v-if="loading">
+        loading...
+      </view>
+      <block v-else>
+        <view class="text-xl">
+          请求数据如下
+        </view>
+        <view class="text-green leading-8">
+          {{ JSON.stringify(data) }}
+        </view>
+      </block>
+    </view>
+    <wd-button type="error" class="my-6" :disabled="!data" @click="reset">
+      重置数据
+    </wd-button>
+  </view>
+</template>

+ 16 - 8
src/pages/about/components/upload.vue

@@ -7,13 +7,25 @@
 }
 </route>
 
+<script lang="ts" setup>
+const { loading, data, run } = useUpload()
+</script>
+
 <template>
   <view class="p-4 text-center">
-    <wd-button @click="run">选择图片并上传</wd-button>
-    <view v-if="loading" class="text-blue h-10">上传...</view>
+    <wd-button @click="run">
+      选择图片并上传
+    </wd-button>
+    <view v-if="loading" class="h-10 text-blue">
+      上传...
+    </view>
     <template v-else>
-      <view class="m-2">上传后返回的接口数据:</view>
-      <view class="m-2">{{ data }}</view>
+      <view class="m-2">
+        上传后返回的接口数据:
+      </view>
+      <view class="m-2">
+        {{ data }}
+      </view>
       <view v-if="data" class="h-80 w-full">
         <image :src="data.url" mode="scaleToFill" />
       </view>
@@ -21,10 +33,6 @@
   </view>
 </template>
 
-<script lang="ts" setup>
-const { loading, data, run } = useUpload()
-</script>
-
 <style lang="scss" scoped>
 //
 </style>

+ 30 - 19
src/pages/index/index.vue

@@ -9,25 +9,6 @@
   },
 }
 </route>
-<template>
-  <view class="bg-white pt-2 px-4" :style="{ marginTop: safeAreaInsets?.top + 'px' }">
-    <view class="mt-12">
-      <image src="/static/logo.svg" alt="" class="w-28 h-28 block mx-auto" />
-    </view>
-    <view class="text-center text-4xl text-[#d14328] mt-4">unibest</view>
-    <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="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'
@@ -69,3 +50,33 @@ onLoad(() => {
 
 console.log('index')
 </script>
+
+<template>
+  <view class="bg-white px-4 pt-2" :style="{ marginTop: `${safeAreaInsets?.top}px` }">
+    <view class="mt-12">
+      <image src="/static/logo.svg" alt="" class="mx-auto block h-28 w-28" />
+    </view>
+    <view class="mt-4 text-center text-4xl text-[#d14328]">
+      unibest
+    </view>
+    <view class="mb-8 mt-2 text-center text-2xl">
+      最好用的 uniapp 开发模板
+    </view>
+
+    <view class="m-auto mb-2 max-w-100 text-justify indent text-4">
+      {{ description }}
+    </view>
+    <view class="mt-8 text-center">
+      当前平台是:
+      <text class="text-green-500">
+        {{ PLATFORM.platform }}
+      </text>
+    </view>
+    <view class="mt-4 text-center">
+      模板分支是:
+      <text class="text-green-500">
+        base
+      </text>
+    </view>
+  </view>
+</template>

+ 6 - 5
src/service/index/foo.ts

@@ -1,27 +1,28 @@
 import { http } from '@/utils/http'
+
 export interface IFooItem {
   id: string
   name: string
 }
 
 /** GET 请求 */
-export const getFooAPI = (name: string) => {
+export function getFooAPI(name: string) {
   return http.get<IFooItem>('/foo', { name })
 }
 /** GET 请求;支持 传递 header 的范例 */
-export const getFooAPI2 = (name: string) => {
+export function getFooAPI2(name: string) {
   return http.get<IFooItem>('/foo', { name }, { 'Content-Type-100': '100' })
 }
 
 /** POST 请求 */
-export const postFooAPI = (name: string) => {
+export function postFooAPI(name: string) {
   return http.post<IFooItem>('/foo', { name })
 }
 /** POST 请求;需要传递 query 参数的范例;微信小程序经常有同时需要query参数和body参数的场景 */
-export const postFooAPI2 = (name: string) => {
+export function postFooAPI2(name: string) {
   return http.post<IFooItem>('/foo', { name })
 }
 /** POST 请求;支持 传递 header 的范例 */
-export const postFooAPI3 = (name: string) => {
+export function postFooAPI3(name: string) {
   return http.post<IFooItem>('/foo', { name }, { name }, { 'Content-Type-100': '100' })
 }

+ 7 - 6
src/store/user.ts

@@ -1,14 +1,14 @@
+import type { IUserInfoVo } from '@/api/login.typings'
+import { defineStore } from 'pinia'
+import { ref } from 'vue'
 import {
-  login as _login,
   getUserInfo as _getUserInfo,
-  wxLogin as _wxLogin,
+  login as _login,
   logout as _logout,
+  wxLogin as _wxLogin,
   getWxCode,
 } from '@/api/login'
-import { defineStore } from 'pinia'
-import { ref } from 'vue'
 import { toast } from '@/utils/toast'
-import { IUserInfoVo } from '@/api/login.typings'
 
 // 初始化状态
 const userInfoState: IUserInfoVo = {
@@ -29,7 +29,8 @@ export const useUserStore = defineStore(
       // 若头像为空 则使用默认头像
       if (!val.avatar) {
         val.avatar = userInfoState.avatar
-      } else {
+      }
+      else {
         val.avatar = 'https://oss.laf.run/ukw0y1-site/avatar.jpg?feige'
       }
       userInfo.value = val

+ 3 - 3
src/typings.d.ts

@@ -1,14 +1,14 @@
 // 全局要用的类型放到这里
 
 declare global {
-  type IResData<T> = {
+  interface IResData<T> {
     code: number
     msg: string
     data: T
   }
 
   // uni.uploadFile文件上传参数
-  type IUniUploadFileOptions = {
+  interface IUniUploadFileOptions {
     file?: File
     files?: UniApp.UploadFileOptionFiles[]
     filePath?: string
@@ -16,7 +16,7 @@ declare global {
     formData?: any
   }
 
-  type IUserInfo = {
+  interface IUserInfo {
     nickname?: string
     avatar?: string
     /** 微信的 openid,非微信没有这个字段 */

+ 1 - 1
src/typings.ts

@@ -6,7 +6,7 @@ export enum TestEnum {
 }
 
 // uni.uploadFile文件上传参数
-export type IUniUploadFileOptions = {
+export interface IUniUploadFileOptions {
   file?: File
   files?: UniApp.UploadFileOptionFiles[]
   filePath?: string

+ 15 - 35
src/utils/http.ts

@@ -1,6 +1,6 @@
-import { CustomRequestOptions } from '@/interceptors/request'
+import type { CustomRequestOptions } from '@/interceptors/request'
 
-export const http = <T>(options: CustomRequestOptions) => {
+export function http<T>(options: CustomRequestOptions) {
   // 1. 返回 Promise 对象
   return new Promise<IResData<T>>((resolve, reject) => {
     uni.request({
@@ -15,18 +15,20 @@ export const http = <T>(options: CustomRequestOptions) => {
         if (res.statusCode >= 200 && res.statusCode < 300) {
           // 2.1 提取核心数据 res.data
           resolve(res.data as IResData<T>)
-        } else if (res.statusCode === 401) {
+        }
+        else if (res.statusCode === 401) {
           // 401错误  -> 清理用户信息,跳转到登录页
           // userStore.clearUserInfo()
           // uni.navigateTo({ url: '/pages/login/login' })
           reject(res)
-        } else {
+        }
+        else {
           // 其他错误 -> 根据后端错误信息轻提示
-          !options.hideErrorToast &&
-            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)
         }
       },
@@ -49,12 +51,7 @@ export const http = <T>(options: CustomRequestOptions) => {
  * @param header 请求头,默认为json格式
  * @returns
  */
-export const httpGet = <T>(
-  url: string,
-  query?: Record<string, any>,
-  header?: Record<string, any>,
-  options?: Partial<CustomRequestOptions>,
-) => {
+export function httpGet<T>(url: string, query?: Record<string, any>, header?: Record<string, any>, options?: Partial<CustomRequestOptions>) {
   return http<T>({
     url,
     query,
@@ -72,13 +69,7 @@ export const httpGet = <T>(
  * @param header 请求头,默认为json格式
  * @returns
  */
-export const httpPost = <T>(
-  url: string,
-  data?: Record<string, any>,
-  query?: Record<string, any>,
-  header?: Record<string, any>,
-  options?: Partial<CustomRequestOptions>,
-) => {
+export function httpPost<T>(url: string, data?: Record<string, any>, query?: Record<string, any>, header?: Record<string, any>, options?: Partial<CustomRequestOptions>) {
   return http<T>({
     url,
     query,
@@ -91,13 +82,7 @@ export const httpPost = <T>(
 /**
  * PUT 请求
  */
-export const httpPut = <T>(
-  url: string,
-  data?: Record<string, any>,
-  query?: Record<string, any>,
-  header?: Record<string, any>,
-  options?: Partial<CustomRequestOptions>,
-) => {
+export function httpPut<T>(url: string, data?: Record<string, any>, query?: Record<string, any>, header?: Record<string, any>, options?: Partial<CustomRequestOptions>) {
   return http<T>({
     url,
     data,
@@ -111,12 +96,7 @@ export const httpPut = <T>(
 /**
  * DELETE 请求(无请求体,仅 query)
  */
-export const httpDelete = <T>(
-  url: string,
-  query?: Record<string, any>,
-  header?: Record<string, any>,
-  options?: Partial<CustomRequestOptions>,
-) => {
+export function httpDelete<T>(url: string, query?: Record<string, any>, header?: Record<string, any>, options?: Partial<CustomRequestOptions>) {
   return http<T>({
     url,
     query,

+ 12 - 12
src/utils/index.ts

@@ -1,7 +1,7 @@
 import { pages, subPackages } from '@/pages.json'
 import { isMpWeixin } from './platform'
 
-export const getLastPage = () => {
+export function getLastPage() {
   // getCurrentPages() 至少有1个元素,所以不再额外判断
   // const lastPage = getCurrentPages().at(-1)
   // 上面那个在低版本安卓中打包会报错,所以改用下面这个【虽然我加了 src/interceptions/prototype.ts,但依然报错】
@@ -14,7 +14,7 @@ export const getLastPage = () => {
  * path 如 '/pages/login/index'
  * redirectPath 如 '/pages/demo/base/route-interceptor'
  */
-export const currRoute = () => {
+export function currRoute() {
   const lastPage = getLastPage()
   const currRoute = (lastPage as any).$page
   // console.log('lastPage.$page:', currRoute)
@@ -29,7 +29,7 @@ export const currRoute = () => {
   return getUrlObj(fullPath)
 }
 
-const ensureDecodeURIComponent = (url: string) => {
+function ensureDecodeURIComponent(url: string) {
   if (url.startsWith('%')) {
     return ensureDecodeURIComponent(decodeURIComponent(url))
   }
@@ -40,7 +40,7 @@ const ensureDecodeURIComponent = (url: string) => {
  * 比如输入url: /pages/login/index?redirect=%2Fpages%2Fdemo%2Fbase%2Froute-interceptor
  * 输出: {path: /pages/login/index, query: {redirect: /pages/demo/base/route-interceptor}}
  */
-export const getUrlObj = (url: string) => {
+export function getUrlObj(url: string) {
   const [path, queryStr] = url.split('?')
   // console.log(path, queryStr)
 
@@ -63,11 +63,11 @@ export const getUrlObj = (url: string) => {
  * 这里设计得通用一点,可以传递 key 作为判断依据,默认是 needLogin, 与 route-block 配对使用
  * 如果没有传 key,则表示所有的 pages,如果传递了 key, 则表示通过 key 过滤
  */
-export const getAllPages = (key = 'needLogin') => {
+export function getAllPages(key = 'needLogin') {
   // 这里处理主包
   const mainPages = pages
-    .filter((page) => !key || page[key])
-    .map((page) => ({
+    .filter(page => !key || page[key])
+    .map(page => ({
       ...page,
       path: `/${page.path}`,
     }))
@@ -79,7 +79,7 @@ export const getAllPages = (key = 'needLogin') => {
     const { root } = subPageObj
 
     subPageObj.pages
-      .filter((page) => !key || page[key])
+      .filter(page => !key || page[key])
       .forEach((page: { path: string } & Record<string, any>) => {
         subPages.push({
           ...page,
@@ -96,18 +96,18 @@ export const getAllPages = (key = 'needLogin') => {
  * 得到所有的需要登录的 pages,包括主包和分包的
  * 只得到 path 数组
  */
-export const getNeedLoginPages = (): string[] => getAllPages('needLogin').map((page) => page.path)
+export const getNeedLoginPages = (): string[] => getAllPages('needLogin').map(page => page.path)
 
 /**
  * 得到所有的需要登录的 pages,包括主包和分包的
  * 只得到 path 数组
  */
-export const needLoginPages: string[] = getAllPages('needLogin').map((page) => page.path)
+export const needLoginPages: string[] = getAllPages('needLogin').map(page => page.path)
 
 /**
  * 根据微信小程序当前环境,判断应该获取的 baseUrl
  */
-export const getEnvBaseUrl = () => {
+export function getEnvBaseUrl() {
   // 请求基准地址
   let baseUrl = import.meta.env.VITE_SERVER_BASEURL
 
@@ -136,7 +136,7 @@ export const getEnvBaseUrl = () => {
 /**
  * 根据微信小程序当前环境,判断应该获取的 UPLOAD_BASEURL
  */
-export const getEnvBaseUploadUrl = () => {
+export function getEnvBaseUploadUrl() {
   // 请求基准地址
   let baseUploadUrl = import.meta.env.VITE_UPLOAD_BASEURL
 

+ 11 - 9
src/utils/request.ts

@@ -1,11 +1,11 @@
-import { CustomRequestOptions } from '@/interceptors/request'
+import type { CustomRequestOptions } from '@/interceptors/request'
 
 /**
  * 请求方法: 主要是对 uni.request 的封装,去适配 openapi-ts-request 的 request 方法
  * @param options 请求参数
  * @returns 返回 Promise 对象
  */
-const http = <T>(options: CustomRequestOptions) => {
+function http<T>(options: CustomRequestOptions) {
   // 1. 返回 Promise 对象
   return new Promise<T>((resolve, reject) => {
     uni.request({
@@ -20,18 +20,20 @@ const http = <T>(options: CustomRequestOptions) => {
         if (res.statusCode >= 200 && res.statusCode < 300) {
           // 2.1 提取核心数据 res.data
           resolve(res.data as T)
-        } else if (res.statusCode === 401) {
+        }
+        else if (res.statusCode === 401) {
           // 401错误  -> 清理用户信息,跳转到登录页
           // userStore.clearUserInfo()
           // uni.navigateTo({ url: '/pages/login/login' })
           reject(res)
-        } else {
+        }
+        else {
           // 其他错误 -> 根据后端错误信息轻提示
-          !options.hideErrorToast &&
-            uni.showToast({
-              icon: 'none',
-              title: (res.data as T & { msg?: string })?.msg || '请求错误',
-            })
+          !options.hideErrorToast
+          && uni.showToast({
+            icon: 'none',
+            title: (res.data as T & { msg?: string })?.msg || '请求错误',
+          })
           reject(res)
         }
       },

+ 2 - 2
src/utils/toast.ts

@@ -21,8 +21,8 @@ export function showToast(options: ToastOptions | string) {
     position: 'middle',
     message: '',
   }
-  const mergedOptions =
-    typeof options === 'string'
+  const mergedOptions
+    = typeof options === 'string'
       ? { ...defaultOptions, message: options }
       : { ...defaultOptions, ...options }
   // 映射position到uniapp支持的格式

+ 10 - 16
src/utils/uploadFile.ts

@@ -21,7 +21,7 @@ import { toast } from './toast'
  */
 export const uploadFileUrl = {
   /** 用户头像上传地址 */
-  USER_AVATAR: import.meta.env.VITE_SERVER_BASEURL + '/user/avatar',
+  USER_AVATAR: `${import.meta.env.VITE_SERVER_BASEURL}/user/avatar`,
 }
 
 /**
@@ -31,12 +31,7 @@ export const uploadFileUrl = {
  * @param formData 额外表单数据
  * @param options 上传选项
  */
-export const useFileUpload = <T = string>(
-  url: string,
-  filePath: string,
-  formData: Record<string, any> = {},
-  options: Omit<UploadOptions, 'sourceType' | 'sizeType' | 'count'> = {},
-) => {
+export function useFileUpload<T = string>(url: string, filePath: string, formData: Record<string, any> = {}, options: Omit<UploadOptions, 'sourceType' | 'sizeType' | 'count'> = {}) {
   return useUpload<T>(
     url,
     formData,
@@ -76,13 +71,9 @@ export interface UploadOptions {
  * @param options 上传选项
  * @returns 上传状态和控制对象
  */
-export const useUpload = <T = string>(
-  url: string,
-  formData: Record<string, any> = {},
-  options: UploadOptions = {},
+export function useUpload<T = string>(url: string, formData: Record<string, any> = {}, options: UploadOptions = {},
   /** 直接传入文件路径,跳过选择器 */
-  directFilePath?: string,
-) => {
+  directFilePath?: string) {
   /** 上传中状态 */
   const loading = ref(false)
   /** 上传错误状态 */
@@ -161,7 +152,8 @@ export const useUpload = <T = string>(
       success: (res) => {
         const file = res.tempFiles[0]
         // 检查文件大小是否符合限制
-        if (!checkFileSize(file.size)) return
+        if (!checkFileSize(file.size))
+          return
 
         // 开始上传
         loading.value = true
@@ -295,7 +287,8 @@ function uploadFile<T>({
           // 上传成功
           data.value = _data as T
           onSuccess?.(_data)
-        } catch (err) {
+        }
+        catch (err) {
           // 响应解析错误
           console.error('解析上传响应失败:', err)
           error.value = true
@@ -320,7 +313,8 @@ function uploadFile<T>({
       progress.value = res.progress
       onProgress?.(res.progress)
     })
-  } catch (err) {
+  }
+  catch (err) {
     // 创建上传任务失败
     console.error('创建上传任务失败:', err)
     error.value = true

+ 12 - 12
tsconfig.json

@@ -1,21 +1,15 @@
 {
   "compilerOptions": {
     "composite": true,
-    "skipLibCheck": true,
+    "lib": ["esnext", "dom"],
+    "baseUrl": ".",
     "module": "ESNext",
     "moduleResolution": "Node",
-    "resolveJsonModule": true,
-    "noImplicitThis": true,
-    "allowSyntheticDefaultImports": true,
-    "allowJs": true,
-    "sourceMap": true,
-    "baseUrl": ".",
     "paths": {
       "@/*": ["./src/*"],
       "@img/*": ["./src/static/*"]
     },
-    "outDir": "dist",
-    "lib": ["esnext", "dom"],
+    "resolveJsonModule": true,
     "types": [
       "@dcloudio/types",
       "@uni-helper/uni-types",
@@ -23,12 +17,17 @@
       "wot-design-uni/global.d.ts",
       "z-paging/types",
       "./src/typings.d.ts"
-    ]
+    ],
+    "allowJs": true,
+    "noImplicitThis": true,
+    "sourceMap": true,
+    "skipLibCheck": true,
+    "allowSyntheticDefaultImports": true,
+    "outDir": "dist"
   },
   "vueCompilerOptions": {
     "plugins": ["@uni-helper/uni-types/volar-plugin"]
   },
-  "exclude": ["node_modules"],
   "include": [
     "src/**/*.ts",
     "src/**/*.js",
@@ -37,5 +36,6 @@
     "src/**/*.jsx",
     "src/**/*.vue",
     "src/**/*.json"
-  ]
+  ],
+  "exclude": ["node_modules"]
 }

+ 2 - 2
uno.config.ts

@@ -2,8 +2,8 @@
 import { presetUni } from '@uni-helper/unocss-preset-uni'
 import {
   defineConfig,
-  presetIcons,
   presetAttributify,
+  presetIcons,
   transformerDirectives,
   transformerVariantGroup,
 } from 'unocss'
@@ -20,7 +20,7 @@ export default defineConfig({
       scale: 1.2,
       warn: true,
       extraProperties: {
-        display: 'inline-block',
+        'display': 'inline-block',
         'vertical-align': 'middle',
       },
     }),

+ 3 - 2
vite-plugins/copyNativeRes.ts

@@ -1,5 +1,5 @@
+import path from 'node:path'
 import fs from 'fs-extra'
-import path from 'path'
 
 export function copyNativeRes() {
   const waitPath = path.resolve(__dirname, '../src/nativeResources')
@@ -31,7 +31,8 @@ export function copyNativeRes() {
         console.log(
           `[copyNativeRes] 成功将 nativeResources 目录中的资源移动到构建目录:${buildPath}`,
         )
-      } catch (error) {
+      }
+      catch (error) {
         console.error(`[copyNativeRes] 复制资源失败:`, error)
       }
     },

+ 9 - 7
vite-plugins/updatePackageJson.ts

@@ -1,14 +1,15 @@
 // src/plugins/updatePackageJson.ts
-import { Plugin } from 'vite'
-import fs from 'fs/promises'
-import path from 'path'
+import type { Plugin } from 'vite'
+import fs from 'node:fs/promises'
+import path from 'node:path'
 
-const updatePackageJson = (): Plugin => {
+function updatePackageJson(): Plugin {
   return {
     name: 'update-package-json',
     async buildStart() {
       // 只在生产环境构建时执行
-      if (process.env.NODE_ENV !== 'production') return
+      if (process.env.NODE_ENV !== 'production')
+        return
 
       const packageJsonPath = path.resolve(process.cwd(), 'package.json')
 
@@ -21,10 +22,11 @@ const updatePackageJson = (): Plugin => {
         packageJson['update-time'] = new Date().toISOString().split('T')[0] // YYYY-MM-DD
 
         // 写回文件(保持 2 空格缩进)
-        await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n', 'utf-8')
+        await fs.writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\n`, 'utf-8')
 
         console.log(`[update-package-json] 更新时间戳: ${packageJson['update-time']}`)
-      } catch (error) {
+      }
+      catch (error) {
         console.error('[update-package-json] 插件执行失败:', error)
       }
     },

+ 19 - 20
vite.config.ts

@@ -1,27 +1,26 @@
-import Uni from '@dcloudio/vite-plugin-uni'
-import dayjs from 'dayjs'
 import path from 'node:path'
-import { defineConfig, loadEnv } from 'vite'
-// @see https://uni-helper.js.org/vite-plugin-uni-pages
-import UniPages from '@uni-helper/vite-plugin-uni-pages'
+import Uni from '@dcloudio/vite-plugin-uni'
+import Components from '@uni-helper/vite-plugin-uni-components'
 // @see https://uni-helper.js.org/vite-plugin-uni-layouts
 import UniLayouts from '@uni-helper/vite-plugin-uni-layouts'
+// @see https://github.com/uni-helper/vite-plugin-uni-manifest
+import UniManifest from '@uni-helper/vite-plugin-uni-manifest'
+// @see https://uni-helper.js.org/vite-plugin-uni-pages
+import UniPages from '@uni-helper/vite-plugin-uni-pages'
 // @see https://github.com/uni-helper/vite-plugin-uni-platform
 // 需要与 @uni-helper/vite-plugin-uni-pages 插件一起使用
 import UniPlatform from '@uni-helper/vite-plugin-uni-platform'
-// @see https://github.com/uni-helper/vite-plugin-uni-manifest
-import UniManifest from '@uni-helper/vite-plugin-uni-manifest'
 /**
  * 分包优化、模块异步跨包调用、组件异步跨包引用
  * @see https://github.com/uni-ku/bundle-optimizer
  */
 import Optimization from '@uni-ku/bundle-optimizer'
+import dayjs from 'dayjs'
 import { visualizer } from 'rollup-plugin-visualizer'
 import AutoImport from 'unplugin-auto-import/vite'
+import { defineConfig, loadEnv } from 'vite'
 import ViteRestart from 'vite-plugin-restart'
-import { copyNativeRes } from './vite-plugins/copyNativeRes'
 import updatePackageJson from './vite-plugins/updatePackageJson'
-import Components from '@uni-helper/vite-plugin-uni-components'
 
 // https://vitejs.dev/config/
 export default async ({ command, mode }) => {
@@ -75,7 +74,7 @@ export default async ({ command, mode }) => {
         // 自定义插件禁用 vite:vue 插件的 devToolsEnabled,强制编译 vue 模板时 inline 为 true
         name: 'fix-vite-plugin-vue',
         configResolved(config) {
-          const plugin = config.plugins.find((p) => p.name === 'vite:vue')
+          const plugin = config.plugins.find(p => p.name === 'vite:vue')
           if (plugin && plugin.api && plugin.api.options) {
             plugin.api.options.devToolsEnabled = false
           }
@@ -91,7 +90,7 @@ export default async ({ command, mode }) => {
       // Optimization 插件需要 page.json 文件,故应在 UniPages 插件之后执行
       Optimization({
         enable: {
-          optimization: true,
+          'optimization': true,
           'async-import': true,
           'async-component': true,
         },
@@ -113,14 +112,14 @@ export default async ({ command, mode }) => {
         },
       },
       // 打包分析插件,h5 + 生产环境才弹出
-      UNI_PLATFORM === 'h5' &&
-        mode === 'production' &&
-        visualizer({
-          filename: './node_modules/.cache/visualizer/stats.html',
-          open: true,
-          gzipSize: true,
-          brotliSize: true,
-        }),
+      UNI_PLATFORM === 'h5'
+      && mode === 'production'
+      && visualizer({
+        filename: './node_modules/.cache/visualizer/stats.html',
+        open: true,
+        gzipSize: true,
+        brotliSize: true,
+      }),
       // 只有在 app 平台时才启用 copyNativeRes 插件
       // UNI_PLATFORM === 'app' && copyNativeRes(),
       Components({
@@ -163,7 +162,7 @@ export default async ({ command, mode }) => {
             [VITE_APP_PROXY_PREFIX]: {
               target: VITE_SERVER_BASEURL,
               changeOrigin: true,
-              rewrite: (path) => path.replace(new RegExp(`^${VITE_APP_PROXY_PREFIX}`), ''),
+              rewrite: path => path.replace(new RegExp(`^${VITE_APP_PROXY_PREFIX}`), ''),
             },
           }
         : undefined,