diff --git a/manifest.config.ts b/manifest.config.ts
index 6f3c7d9..edf4b5c 100644
--- a/manifest.config.ts
+++ b/manifest.config.ts
@@ -6,143 +6,143 @@ import { loadEnv } from 'vite'
// 手动解析命令行参数获取 mode
function getMode() {
- const args = process.argv.slice(2)
- const modeFlagIndex = args.findIndex(arg => arg === '--mode')
- return modeFlagIndex !== -1 ? args[modeFlagIndex + 1] : args[0] === 'build' ? 'production' : 'development' // 默认 development
+ const args = process.argv.slice(2)
+ const modeFlagIndex = args.findIndex(arg => arg === '--mode')
+ return modeFlagIndex !== -1 ? args[modeFlagIndex + 1] : args[0] === 'build' ? 'production' : 'development' // 默认 development
}
// 获取环境变量的范例
const env = loadEnv(getMode(), path.resolve(process.cwd(), 'env'))
const {
- VITE_APP_TITLE,
- VITE_UNI_APPID,
- VITE_WX_APPID,
- VITE_APP_PUBLIC_BASE,
- VITE_FALLBACK_LOCALE,
+ VITE_APP_TITLE,
+ VITE_UNI_APPID,
+ VITE_WX_APPID,
+ VITE_APP_PUBLIC_BASE,
+ VITE_FALLBACK_LOCALE,
} = 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': {
- router: {
- // base: VITE_APP_PUBLIC_BASE,
- },
- },
- /* 5+App特有相关 */
- 'app-plus': {
- usingComponents: true,
- nvueStyleCompiler: 'uni-app',
- compilerVersion: 3,
- compatible: {
- ignoreVersion: true,
- },
- splashscreen: {
- alwaysShowBeforeRender: true,
- waiting: true,
- autoclose: true,
- delay: 0,
- },
- /* 模块配置 */
- modules: {},
- /* 应用发布信息 */
- distribute: {
- /* android打包配置 */
- android: {
- minSdkVersion: 30,
- targetSdkVersion: 30,
- abiFilters: ['armeabi-v7a', 'arm64-v8a'],
- permissions: [
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- ],
- },
- /* ios打包配置 */
- ios: {},
- /* SDK配置 */
- sdkConfigs: {},
- /* 图标配置 */
- icons: {
- android: {
- hdpi: 'static/app/icons/72x72.png',
- xhdpi: 'static/app/icons/96x96.png',
- xxhdpi: 'static/app/icons/144x144.png',
- xxxhdpi: 'static/app/icons/192x192.png',
- },
- ios: {
- appstore: 'static/app/icons/1024x1024.png',
- ipad: {
- 'app': 'static/app/icons/76x76.png',
- 'app@2x': 'static/app/icons/152x152.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@2x': 'static/app/icons/58x58.png',
- 'spotlight': 'static/app/icons/40x40.png',
- 'spotlight@2x': 'static/app/icons/80x80.png',
- },
- iphone: {
- 'app@2x': 'static/app/icons/120x120.png',
- 'app@3x': 'static/app/icons/180x180.png',
- 'notification@2x': 'static/app/icons/40x40.png',
- 'notification@3x': 'static/app/icons/60x60.png',
- 'settings@2x': 'static/app/icons/58x58.png',
- 'settings@3x': 'static/app/icons/87x87.png',
- 'spotlight@2x': 'static/app/icons/80x80.png',
- 'spotlight@3x': 'static/app/icons/120x120.png',
- },
- },
- },
- },
- },
- /* 快应用特有相关 */
- 'quickapp': {},
- /* 小程序特有相关 */
- 'mp-weixin': {
- appid: VITE_WX_APPID,
- setting: {
- urlCheck: false,
- // 是否启用 ES6 转 ES5
- es6: true,
- minified: true,
- },
- optimization: {
- subPackages: true,
- },
- // styleIsolation: 'shared',
- usingComponents: true,
- // __usePrivacyCheck__: true,
- },
- 'mp-alipay': {
- usingComponents: true,
- styleIsolation: 'shared',
- },
- 'mp-baidu': {
- usingComponents: true,
- },
- 'mp-toutiao': {
- usingComponents: true,
- },
- 'uniStatistics': {
- enable: false,
- },
- 'vueVersion': '3',
+ '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,
+ },
+ },
+ /* 5+App特有相关 */
+ 'app-plus': {
+ usingComponents: true,
+ nvueStyleCompiler: 'uni-app',
+ compilerVersion: 3,
+ compatible: {
+ ignoreVersion: true,
+ },
+ splashscreen: {
+ alwaysShowBeforeRender: true,
+ waiting: true,
+ autoclose: true,
+ delay: 0,
+ },
+ /* 模块配置 */
+ modules: {},
+ /* 应用发布信息 */
+ distribute: {
+ /* android打包配置 */
+ android: {
+ minSdkVersion: 30,
+ targetSdkVersion: 30,
+ abiFilters: ['armeabi-v7a', 'arm64-v8a'],
+ permissions: [
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ '',
+ ],
+ },
+ /* ios打包配置 */
+ ios: {},
+ /* SDK配置 */
+ sdkConfigs: {},
+ /* 图标配置 */
+ icons: {
+ android: {
+ hdpi: 'static/app/icons/72x72.png',
+ xhdpi: 'static/app/icons/96x96.png',
+ xxhdpi: 'static/app/icons/144x144.png',
+ xxxhdpi: 'static/app/icons/192x192.png',
+ },
+ ios: {
+ appstore: 'static/app/icons/1024x1024.png',
+ ipad: {
+ 'app': 'static/app/icons/76x76.png',
+ 'app@2x': 'static/app/icons/152x152.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@2x': 'static/app/icons/58x58.png',
+ 'spotlight': 'static/app/icons/40x40.png',
+ 'spotlight@2x': 'static/app/icons/80x80.png',
+ },
+ iphone: {
+ 'app@2x': 'static/app/icons/120x120.png',
+ 'app@3x': 'static/app/icons/180x180.png',
+ 'notification@2x': 'static/app/icons/40x40.png',
+ 'notification@3x': 'static/app/icons/60x60.png',
+ 'settings@2x': 'static/app/icons/58x58.png',
+ 'settings@3x': 'static/app/icons/87x87.png',
+ 'spotlight@2x': 'static/app/icons/80x80.png',
+ 'spotlight@3x': 'static/app/icons/120x120.png',
+ },
+ },
+ },
+ },
+ },
+ /* 快应用特有相关 */
+ 'quickapp': {},
+ /* 小程序特有相关 */
+ 'mp-weixin': {
+ appid: VITE_WX_APPID,
+ setting: {
+ urlCheck: false,
+ // 是否启用 ES6 转 ES5
+ es6: true,
+ minified: true,
+ },
+ optimization: {
+ subPackages: true,
+ },
+ // styleIsolation: 'shared',
+ usingComponents: true,
+ // __usePrivacyCheck__: true,
+ },
+ 'mp-alipay': {
+ usingComponents: true,
+ styleIsolation: 'shared',
+ },
+ 'mp-baidu': {
+ usingComponents: true,
+ },
+ 'mp-toutiao': {
+ usingComponents: true,
+ },
+ 'uniStatistics': {
+ enable: false,
+ },
+ 'vueVersion': '3',
})
diff --git a/pages.config.ts b/pages.config.ts
index 1aa275e..7c4b179 100644
--- a/pages.config.ts
+++ b/pages.config.ts
@@ -2,22 +2,22 @@ import { defineUniPages } from '@uni-helper/vite-plugin-uni-pages'
import { tabBar } from './src/tabbar/config'
export default defineUniPages({
- globalStyle: {
- navigationStyle: 'default',
- navigationBarTitleText: 'unibest',
- navigationBarBackgroundColor: '#f8f8f8',
- navigationBarTextStyle: 'black',
- backgroundColor: '#FFFFFF',
- },
- easycom: {
- autoscan: true,
- custom: {
- '^fg-(.*)': '@/components/fg-$1/fg-$1.vue',
- '^wd-(.*)': 'wot-design-uni/components/wd-$1/wd-$1.vue',
- '^(?!z-paging-refresh|z-paging-load-more)z-paging(.*)':
- 'z-paging/components/z-paging$1/z-paging$1.vue',
- },
- },
- // tabbar 的配置统一在 “./src/tabbar/config.ts” 文件中
- tabBar: tabBar as any,
+ globalStyle: {
+ navigationStyle: 'default',
+ navigationBarTitleText: 'unibest',
+ navigationBarBackgroundColor: '#f8f8f8',
+ navigationBarTextStyle: 'black',
+ backgroundColor: '#FFFFFF',
+ },
+ easycom: {
+ autoscan: true,
+ custom: {
+ '^fg-(.*)': '@/components/fg-$1/fg-$1.vue',
+ '^wd-(.*)': 'wot-design-uni/components/wd-$1/wd-$1.vue',
+ '^(?!z-paging-refresh|z-paging-load-more)z-paging(.*)':
+ 'z-paging/components/z-paging$1/z-paging$1.vue',
+ },
+ },
+ // tabbar 的配置统一在 “./src/tabbar/config.ts” 文件中
+ tabBar: tabBar as any,
})
diff --git a/src/hooks/useUpload.ts b/src/hooks/useUpload.ts
index 3080d5a..e7dc6d7 100644
--- a/src/hooks/useUpload.ts
+++ b/src/hooks/useUpload.ts
@@ -8,153 +8,153 @@ type TImage = 'png' | 'jpg' | 'jpeg' | 'webp' | '*'
type TFile = 'doc' | 'docx' | 'ppt' | 'zip' | 'xls' | 'xlsx' | 'txt' | TImage
interface TOptions {
- formData?: Record
- maxSize?: number
- accept?: T extends 'image' ? TImage[] : TFile[]
- fileType?: T
- success?: (params: any) => void
- error?: (err: any) => void
+ formData?: Record
+ maxSize?: number
+ accept?: T extends 'image' ? TImage[] : TFile[]
+ fileType?: T
+ success?: (params: any) => void
+ error?: (err: any) => void
}
export default function useUpload(options: TOptions = {} as TOptions) {
- const {
- formData = {},
- maxSize = 5 * 1024 * 1024,
- accept = ['*'],
- fileType = 'image',
- success,
- error: onError,
- } = options
+ const {
+ formData = {},
+ maxSize = 5 * 1024 * 1024,
+ accept = ['*'],
+ fileType = 'image',
+ success,
+ error: onError,
+ } = options
- const loading = ref(false)
- const error = ref(null)
- const data = ref(null)
+ const loading = ref(false)
+ const error = ref(null)
+ const data = ref(null)
- const handleFileChoose = ({ tempFilePath, size }: { tempFilePath: string, size: number }) => {
- if (size > maxSize) {
- uni.showToast({
- title: `文件大小不能超过 ${maxSize / 1024 / 1024}MB`,
- icon: 'none',
- })
- return
- }
+ const handleFileChoose = ({ tempFilePath, size }: { tempFilePath: string, size: number }) => {
+ if (size > maxSize) {
+ uni.showToast({
+ title: `文件大小不能超过 ${maxSize / 1024 / 1024}MB`,
+ icon: 'none',
+ })
+ return
+ }
- // const fileExtension = file?.tempFiles?.name?.split('.').pop()?.toLowerCase()
- // const isTypeValid = accept.some((type) => type === '*' || type.toLowerCase() === fileExtension)
+ // const fileExtension = file?.tempFiles?.name?.split('.').pop()?.toLowerCase()
+ // const isTypeValid = accept.some((type) => type === '*' || type.toLowerCase() === fileExtension)
- // if (!isTypeValid) {
- // uni.showToast({
- // title: `仅支持 ${accept.join(', ')} 格式的文件`,
- // icon: 'none',
- // })
- // return
- // }
+ // if (!isTypeValid) {
+ // uni.showToast({
+ // title: `仅支持 ${accept.join(', ')} 格式的文件`,
+ // icon: 'none',
+ // })
+ // return
+ // }
- loading.value = true
- uploadFile({
- tempFilePath,
- formData,
- onSuccess: (res) => {
- const { data: _data } = JSON.parse(res)
- data.value = _data
- // console.log('上传成功', res)
- success?.(_data)
- },
- onError: (err) => {
- error.value = err
- onError?.(err)
- },
- onComplete: () => {
- loading.value = false
- },
- })
- }
+ loading.value = true
+ uploadFile({
+ tempFilePath,
+ formData,
+ onSuccess: (res) => {
+ const { data: _data } = JSON.parse(res)
+ data.value = _data
+ // console.log('上传成功', res)
+ success?.(_data)
+ },
+ onError: (err) => {
+ error.value = err
+ onError?.(err)
+ },
+ onComplete: () => {
+ loading.value = false
+ },
+ })
+ }
- const run = () => {
- // 微信小程序从基础库 2.21.0 开始, wx.chooseImage 停止维护,请使用 uni.chooseMedia 代替。
- // 微信小程序在2023年10月17日之后,使用本API需要配置隐私协议
- const chooseFileOptions = {
- count: 1,
- success: (res: any) => {
- console.log('File selected successfully:', res)
- // 小程序中res:{errMsg: "chooseImage:ok", tempFiles: [{fileType: "image", size: 48976, tempFilePath: "http://tmp/5iG1WpIxTaJf3ece38692a337dc06df7eb69ecb49c6b.jpeg"}]}
- // h5中res:{errMsg: "chooseImage:ok", tempFilePaths: "blob:http://localhost:9000/f74ab6b8-a14d-4cb6-a10d-fcf4511a0de5", tempFiles: [File]}
- // h5的File有以下字段:{name: "girl.jpeg", size: 48976, type: "image/jpeg"}
- // App中res:{errMsg: "chooseImage:ok", tempFilePaths: "file:///Users/feige/xxx/gallery/1522437259-compressed-IMG_0006.jpg", tempFiles: [File]}
- // App的File有以下字段:{path: "file:///Users/feige/xxx/gallery/1522437259-compressed-IMG_0006.jpg", size: 48976}
- let tempFilePath = ''
- let size = 0
- // #ifdef MP-WEIXIN
- tempFilePath = res.tempFiles[0].tempFilePath
- size = res.tempFiles[0].size
- // #endif
- // #ifndef MP-WEIXIN
- tempFilePath = res.tempFilePaths[0]
- size = res.tempFiles[0].size
- // #endif
- handleFileChoose({ tempFilePath, size })
- },
- fail: (err: any) => {
- console.error('File selection failed:', err)
- error.value = err
- onError?.(err)
- },
- }
+ const run = () => {
+ // 微信小程序从基础库 2.21.0 开始, wx.chooseImage 停止维护,请使用 uni.chooseMedia 代替。
+ // 微信小程序在2023年10月17日之后,使用本API需要配置隐私协议
+ const chooseFileOptions = {
+ count: 1,
+ success: (res: any) => {
+ console.log('File selected successfully:', res)
+ // 小程序中res:{errMsg: "chooseImage:ok", tempFiles: [{fileType: "image", size: 48976, tempFilePath: "http://tmp/5iG1WpIxTaJf3ece38692a337dc06df7eb69ecb49c6b.jpeg"}]}
+ // h5中res:{errMsg: "chooseImage:ok", tempFilePaths: "blob:http://localhost:9000/f74ab6b8-a14d-4cb6-a10d-fcf4511a0de5", tempFiles: [File]}
+ // h5的File有以下字段:{name: "girl.jpeg", size: 48976, type: "image/jpeg"}
+ // App中res:{errMsg: "chooseImage:ok", tempFilePaths: "file:///Users/feige/xxx/gallery/1522437259-compressed-IMG_0006.jpg", tempFiles: [File]}
+ // App的File有以下字段:{path: "file:///Users/feige/xxx/gallery/1522437259-compressed-IMG_0006.jpg", size: 48976}
+ let tempFilePath = ''
+ let size = 0
+ // #ifdef MP-WEIXIN
+ tempFilePath = res.tempFiles[0].tempFilePath
+ size = res.tempFiles[0].size
+ // #endif
+ // #ifndef MP-WEIXIN
+ tempFilePath = res.tempFilePaths[0]
+ size = res.tempFiles[0].size
+ // #endif
+ handleFileChoose({ tempFilePath, size })
+ },
+ fail: (err: any) => {
+ console.error('File selection failed:', err)
+ error.value = err
+ onError?.(err)
+ },
+ }
- if (fileType === 'image') {
- // #ifdef MP-WEIXIN
- uni.chooseMedia({
- ...chooseFileOptions,
- mediaType: ['image'],
- })
- // #endif
+ if (fileType === 'image') {
+ // #ifdef MP-WEIXIN
+ uni.chooseMedia({
+ ...chooseFileOptions,
+ mediaType: ['image'],
+ })
+ // #endif
- // #ifndef MP-WEIXIN
- uni.chooseImage(chooseFileOptions)
- // #endif
- }
- else {
- uni.chooseFile({
- ...chooseFileOptions,
- type: 'all',
- })
- }
- }
+ // #ifndef MP-WEIXIN
+ uni.chooseImage(chooseFileOptions)
+ // #endif
+ }
+ else {
+ uni.chooseFile({
+ ...chooseFileOptions,
+ type: 'all',
+ })
+ }
+ }
- return { loading, error, data, run }
+ return { loading, error, data, run }
}
async function uploadFile({
- tempFilePath,
- formData,
- onSuccess,
- onError,
- onComplete,
+ tempFilePath,
+ formData,
+ onSuccess,
+ onError,
+ onComplete,
}: {
- tempFilePath: string
- formData: Record
- onSuccess: (data: any) => void
- onError: (err: any) => void
- onComplete: () => void
+ tempFilePath: string
+ formData: Record
+ onSuccess: (data: any) => void
+ onError: (err: any) => void
+ onComplete: () => void
}) {
- uni.uploadFile({
- url: VITE_UPLOAD_BASEURL,
- filePath: tempFilePath,
- name: 'file',
- formData,
- success: (uploadFileRes) => {
- try {
- const data = uploadFileRes.data
- onSuccess(data)
- }
- catch (err) {
- onError(err)
- }
- },
- fail: (err) => {
- console.error('Upload failed:', err)
- onError(err)
- },
- complete: onComplete,
- })
+ uni.uploadFile({
+ url: VITE_UPLOAD_BASEURL,
+ filePath: tempFilePath,
+ name: 'file',
+ formData,
+ success: (uploadFileRes) => {
+ try {
+ const data = uploadFileRes.data
+ onSuccess(data)
+ }
+ catch (err) {
+ onError(err)
+ }
+ },
+ fail: (err) => {
+ console.error('Upload failed:', err)
+ onError(err)
+ },
+ complete: onComplete,
+ })
}
diff --git a/src/http/alova.ts b/src/http/alova.ts
index 005b54b..360ba19 100644
--- a/src/http/alova.ts
+++ b/src/http/alova.ts
@@ -9,103 +9,103 @@ import { ContentTypeEnum, ResultEnum, ShowMessage } from './tools/enum'
// 配置动态Tag
export const API_DOMAINS = {
- DEFAULT: import.meta.env.VITE_SERVER_BASEURL,
- SECONDARY: import.meta.env.VITE_API_SECONDARY_URL,
+ DEFAULT: import.meta.env.VITE_SERVER_BASEURL,
+ SECONDARY: import.meta.env.VITE_API_SECONDARY_URL,
}
/**
* 创建请求实例
*/
const { onAuthRequired, onResponseRefreshToken } = createServerTokenAuthentication<
- typeof VueHook,
- typeof uniappRequestAdapter
+ typeof VueHook,
+ typeof uniappRequestAdapter
>({
- refreshTokenOnError: {
- isExpired: (error) => {
- return error.response?.status === ResultEnum.Unauthorized
- },
- handler: async () => {
- try {
- // await authLogin();
- }
- catch (error) {
- // 切换到登录页
- await uni.reLaunch({ url: '/pages/common/login/index' })
- throw error
- }
- },
- },
+ refreshTokenOnError: {
+ isExpired: (error) => {
+ return error.response?.status === ResultEnum.Unauthorized
+ },
+ handler: async () => {
+ try {
+ // await authLogin();
+ }
+ catch (error) {
+ // 切换到登录页
+ await uni.reLaunch({ url: '/pages/common/login/index' })
+ throw error
+ }
+ },
+ },
})
/**
* alova 请求实例
*/
const alovaInstance = createAlova({
- baseURL: import.meta.env.VITE_APP_PROXY_PREFIX,
- ...AdapterUniapp(),
- timeout: 5000,
- statesHook: VueHook,
+ baseURL: import.meta.env.VITE_APP_PROXY_PREFIX,
+ ...AdapterUniapp(),
+ timeout: 5000,
+ statesHook: VueHook,
- beforeRequest: onAuthRequired((method) => {
- // 设置默认 Content-Type
- method.config.headers = {
- ContentType: ContentTypeEnum.JSON,
- Accept: 'application/json, text/plain, */*',
- ...method.config.headers,
- }
+ beforeRequest: onAuthRequired((method) => {
+ // 设置默认 Content-Type
+ method.config.headers = {
+ ContentType: ContentTypeEnum.JSON,
+ Accept: 'application/json, text/plain, */*',
+ ...method.config.headers,
+ }
- const { config } = method
- const ignoreAuth = !config.meta?.ignoreAuth
- console.log('ignoreAuth===>', ignoreAuth)
- // 处理认证信息 自行处理认证问题
- if (ignoreAuth) {
- const token = 'getToken()'
- if (!token) {
- throw new Error('[请求错误]:未登录')
- }
- // method.config.headers.token = token;
- }
+ const { config } = method
+ const ignoreAuth = !config.meta?.ignoreAuth
+ console.log('ignoreAuth===>', ignoreAuth)
+ // 处理认证信息 自行处理认证问题
+ if (ignoreAuth) {
+ const token = 'getToken()'
+ if (!token) {
+ throw new Error('[请求错误]:未登录')
+ }
+ // method.config.headers.token = token;
+ }
- // 处理动态域名
- if (config.meta?.domain) {
- method.baseURL = config.meta.domain
- console.log('当前域名', method.baseURL)
- }
- }),
+ // 处理动态域名
+ if (config.meta?.domain) {
+ method.baseURL = config.meta.domain
+ console.log('当前域名', method.baseURL)
+ }
+ }),
- responded: onResponseRefreshToken((response, method) => {
- const { config } = method
- const { requestType } = config
- const {
- statusCode,
- data: rawData,
- errMsg,
- } = response as UniNamespace.RequestSuccessCallbackResult
+ responded: onResponseRefreshToken((response, method) => {
+ const { config } = method
+ const { requestType } = config
+ const {
+ statusCode,
+ data: rawData,
+ errMsg,
+ } = response as UniNamespace.RequestSuccessCallbackResult
- // 处理特殊请求类型(上传/下载)
- if (requestType === 'upload' || requestType === 'download') {
- return response
- }
+ // 处理特殊请求类型(上传/下载)
+ if (requestType === 'upload' || requestType === 'download') {
+ return response
+ }
- // 处理 HTTP 状态码错误
- if (statusCode !== 200) {
- const errorMessage = ShowMessage(statusCode) || `HTTP请求错误[${statusCode}]`
- console.error('errorMessage===>', errorMessage)
- toast.error(errorMessage)
- throw new Error(`${errorMessage}:${errMsg}`)
- }
+ // 处理 HTTP 状态码错误
+ if (statusCode !== 200) {
+ const errorMessage = ShowMessage(statusCode) || `HTTP请求错误[${statusCode}]`
+ console.error('errorMessage===>', errorMessage)
+ toast.error(errorMessage)
+ throw new Error(`${errorMessage}:${errMsg}`)
+ }
- // 处理业务逻辑错误
- const { code, message, data } = rawData as IResponse
- if (code !== ResultEnum.Success) {
- if (config.meta?.toast !== false) {
- toast.warning(message)
- }
- throw new Error(`请求错误[${code}]:${message}`)
- }
- // 处理成功响应,返回业务数据
- return data
- }),
+ // 处理业务逻辑错误
+ const { code, message, data } = rawData as IResponse
+ if (code !== ResultEnum.Success) {
+ if (config.meta?.toast !== false) {
+ toast.warning(message)
+ }
+ throw new Error(`请求错误[${code}]:${message}`)
+ }
+ // 处理成功响应,返回业务数据
+ return data
+ }),
})
export const http = alovaInstance
diff --git a/src/http/http.ts b/src/http/http.ts
index 98c7324..846b0eb 100644
--- a/src/http/http.ts
+++ b/src/http/http.ts
@@ -1,47 +1,47 @@
import type { CustomRequestOptions } from '@/http/types'
export function http(options: CustomRequestOptions) {
- // 1. 返回 Promise 对象
- return new Promise>((resolve, reject) => {
- uni.request({
- ...options,
- dataType: 'json',
- // #ifndef MP-WEIXIN
- responseType: 'json',
- // #endif
- // 响应成功
- success(res) {
- // 状态码 2xx,参考 axios 的设计
- if (res.statusCode >= 200 && res.statusCode < 300) {
- // 2.1 提取核心数据 res.data
- resolve(res.data as IResData)
- }
- else if (res.statusCode === 401) {
- // 401错误 -> 清理用户信息,跳转到登录页
- // userStore.clearUserInfo()
- // uni.navigateTo({ url: '/pages/login/login' })
- reject(res)
- }
- else {
- // 其他错误 -> 根据后端错误信息轻提示
- !options.hideErrorToast
- && uni.showToast({
- icon: 'none',
- title: (res.data as IResData).msg || '请求错误',
- })
- reject(res)
- }
- },
- // 响应失败
- fail(err) {
- uni.showToast({
- icon: 'none',
- title: '网络错误,换个网络试试',
- })
- reject(err)
- },
- })
- })
+ // 1. 返回 Promise 对象
+ return new Promise>((resolve, reject) => {
+ uni.request({
+ ...options,
+ dataType: 'json',
+ // #ifndef MP-WEIXIN
+ responseType: 'json',
+ // #endif
+ // 响应成功
+ success(res) {
+ // 状态码 2xx,参考 axios 的设计
+ if (res.statusCode >= 200 && res.statusCode < 300) {
+ // 2.1 提取核心数据 res.data
+ resolve(res.data as IResData)
+ }
+ else if (res.statusCode === 401) {
+ // 401错误 -> 清理用户信息,跳转到登录页
+ // userStore.clearUserInfo()
+ // uni.navigateTo({ url: '/pages/login/login' })
+ reject(res)
+ }
+ else {
+ // 其他错误 -> 根据后端错误信息轻提示
+ !options.hideErrorToast
+ && uni.showToast({
+ icon: 'none',
+ title: (res.data as IResData).msg || '请求错误',
+ })
+ reject(res)
+ }
+ },
+ // 响应失败
+ fail(err) {
+ uni.showToast({
+ icon: 'none',
+ title: '网络错误,换个网络试试',
+ })
+ reject(err)
+ },
+ })
+ })
}
/**
@@ -52,13 +52,13 @@ export function http(options: CustomRequestOptions) {
* @returns
*/
export function httpGet(url: string, query?: Record, header?: Record, options?: Partial) {
- return http({
- url,
- query,
- method: 'GET',
- header,
- ...options,
- })
+ return http({
+ url,
+ query,
+ method: 'GET',
+ header,
+ ...options,
+ })
}
/**
@@ -70,40 +70,40 @@ export function httpGet(url: string, query?: Record, header?: Re
* @returns
*/
export function httpPost(url: string, data?: Record, query?: Record, header?: Record, options?: Partial) {
- return http({
- url,
- query,
- data,
- method: 'POST',
- header,
- ...options,
- })
+ return http({
+ url,
+ query,
+ data,
+ method: 'POST',
+ header,
+ ...options,
+ })
}
/**
* PUT 请求
*/
export function httpPut(url: string, data?: Record, query?: Record, header?: Record, options?: Partial) {
- return http({
- url,
- data,
- query,
- method: 'PUT',
- header,
- ...options,
- })
+ return http({
+ url,
+ data,
+ query,
+ method: 'PUT',
+ header,
+ ...options,
+ })
}
/**
* DELETE 请求(无请求体,仅 query)
*/
export function httpDelete(url: string, query?: Record, header?: Record, options?: Partial) {
- return http({
- url,
- query,
- method: 'DELETE',
- header,
- ...options,
- })
+ return http({
+ url,
+ query,
+ method: 'DELETE',
+ header,
+ ...options,
+ })
}
http.get = httpGet
diff --git a/src/http/interceptor.ts b/src/http/interceptor.ts
index 357780b..c06aed1 100644
--- a/src/http/interceptor.ts
+++ b/src/http/interceptor.ts
@@ -9,57 +9,57 @@ const baseUrl = getEnvBaseUrl()
// 拦截器配置
const httpInterceptor = {
- // 拦截前触发
- invoke(options: CustomRequestOptions) {
- // 接口请求支持通过 query 参数配置 queryString
- if (options.query) {
- const queryStr = stringifyQuery(options.query)
- if (options.url.includes('?')) {
- options.url += `&${queryStr}`
- }
- else {
- options.url += `?${queryStr}`
- }
- }
- // 非 http 开头需拼接地址
- if (!options.url.startsWith('http')) {
- // #ifdef H5
- // console.log(__VITE_APP_PROXY__)
- if (JSON.parse(__VITE_APP_PROXY__)) {
- // 自动拼接代理前缀
- options.url = import.meta.env.VITE_APP_PROXY_PREFIX + options.url
- }
- else {
- options.url = baseUrl + options.url
- }
- // #endif
- // 非H5正常拼接
- // #ifndef H5
- options.url = baseUrl + options.url
- // #endif
- // TIPS: 如果需要对接多个后端服务,也可以在这里处理,拼接成所需要的地址
- }
- // 1. 请求超时
- options.timeout = 10000 // 10s
- // 2. (可选)添加小程序端请求头标识
- options.header = {
- platform, // 可选,与 uniapp 定义的平台一致,告诉后台来源
- ...options.header,
- }
- // 3. 添加 token 请求头标识
- const userStore = useUserStore()
- const { token } = userStore.userInfo as unknown as IUserInfo
- if (token) {
- options.header.Authorization = `Bearer ${token}`
- }
- },
+ // 拦截前触发
+ invoke(options: CustomRequestOptions) {
+ // 接口请求支持通过 query 参数配置 queryString
+ if (options.query) {
+ const queryStr = stringifyQuery(options.query)
+ if (options.url.includes('?')) {
+ options.url += `&${queryStr}`
+ }
+ else {
+ options.url += `?${queryStr}`
+ }
+ }
+ // 非 http 开头需拼接地址
+ if (!options.url.startsWith('http')) {
+ // #ifdef H5
+ // console.log(__VITE_APP_PROXY__)
+ if (JSON.parse(__VITE_APP_PROXY__)) {
+ // 自动拼接代理前缀
+ options.url = import.meta.env.VITE_APP_PROXY_PREFIX + options.url
+ }
+ else {
+ options.url = baseUrl + options.url
+ }
+ // #endif
+ // 非H5正常拼接
+ // #ifndef H5
+ options.url = baseUrl + options.url
+ // #endif
+ // TIPS: 如果需要对接多个后端服务,也可以在这里处理,拼接成所需要的地址
+ }
+ // 1. 请求超时
+ options.timeout = 10000 // 10s
+ // 2. (可选)添加小程序端请求头标识
+ options.header = {
+ platform, // 可选,与 uniapp 定义的平台一致,告诉后台来源
+ ...options.header,
+ }
+ // 3. 添加 token 请求头标识
+ const userStore = useUserStore()
+ const { token } = userStore.userInfo as unknown as IUserInfo
+ if (token) {
+ options.header.Authorization = `Bearer ${token}`
+ }
+ },
}
export const requestInterceptor = {
- install() {
- // 拦截 request 请求
- uni.addInterceptor('request', httpInterceptor)
- // 拦截 uploadFile 文件上传
- uni.addInterceptor('uploadFile', httpInterceptor)
- },
+ install() {
+ // 拦截 request 请求
+ uni.addInterceptor('request', httpInterceptor)
+ // 拦截 uploadFile 文件上传
+ uni.addInterceptor('uploadFile', httpInterceptor)
+ },
}
diff --git a/src/main.ts b/src/main.ts
index a357275..9562a55 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -9,13 +9,14 @@ import '@/style/index.scss'
import 'virtual:uno.css'
export function createApp() {
- const app = createSSRApp(App)
- app.use(store)
- app.use(routeInterceptor)
- app.use(requestInterceptor)
- app.use(VueQueryPlugin)
+ const app = createSSRApp(App)
+ app.use(store)
+ app.use(routeInterceptor)
+ app.use(requestInterceptor)
+ app.use(VueQueryPlugin)
+ app.provide('OSS', '/src/static/')
- return {
- app,
- }
+ return {
+ app,
+ }
}
diff --git a/src/pages.json b/src/pages.json
index 86b05f7..107f0e6 100644
--- a/src/pages.json
+++ b/src/pages.json
@@ -15,7 +15,7 @@
}
},
"tabBar": {
- "custom": true,
+ "custom": false,
"color": "#999999",
"selectedColor": "#018d71",
"backgroundColor": "#F8F8F8",
@@ -27,15 +27,21 @@
"list": [
{
"iconPath": "static/tabbar/home.png",
- "selectedIconPath": "static/tabbar/homeHL.png",
+ "selectedIconPath": "static/tabbar/home_s.png",
"pagePath": "pages/index/index",
"text": "首页"
},
{
- "iconPath": "static/tabbar/example.png",
- "selectedIconPath": "static/tabbar/exampleHL.png",
- "pagePath": "pages/about/about",
- "text": "关于"
+ "iconPath": "static/tabbar/reserve.png",
+ "selectedIconPath": "static/tabbar/reserve_s.png",
+ "pagePath": "pages/reserve/reserve",
+ "text": "预约"
+ },
+ {
+ "iconPath": "static/tabbar/my.png",
+ "selectedIconPath": "static/tabbar/my_s.png",
+ "pagePath": "pages/my/my",
+ "text": "我的"
}
]
},
@@ -72,6 +78,24 @@
"style": {
"navigationBarTitleText": "Vue Query 请求演示"
}
+ },
+ {
+ "path": "pages/my/my",
+ "type": "page",
+ "layout": "tabbar",
+ "style": {
+ "navigationStyle": "custom",
+ "navigationBarTitleText": "我的"
+ }
+ },
+ {
+ "path": "pages/reserve/reserve",
+ "type": "page",
+ "layout": "tabbar",
+ "style": {
+ "navigationStyle": "custom",
+ "navigationBarTitleText": "预约"
+ }
}
],
"subPackages": [
@@ -89,4 +113,4 @@
]
}
]
-}
+}
\ No newline at end of file
diff --git a/src/pages/index/index.vue b/src/pages/index/index.vue
index 08b1284..bbd085a 100644
--- a/src/pages/index/index.vue
+++ b/src/pages/index/index.vue
@@ -1,122 +1,86 @@
-
-{
- "layout": "tabbar",
- "style": {
- // 'custom' 表示开启自定义导航栏,默认 'default'
- "navigationStyle": "custom",
- "navigationBarTitleText": "首页"
- }
-}
-
-
-
+{
+ "layout": "tabbar",
+ "style": {
+ // 'custom' 表示开启自定义导航栏,默认 'default'
+ "navigationStyle": "custom",
+ "navigationBarTitleText": "首页"
+ }
+}
-
-
-
-
-
- unibest
-
-
- 最好用的 uniapp 开发模板
-
+
+
+
+
+
+ 上海
+
+
+
+
+
+
+
+
+
+
-
- {{ description }}
-
-
- 作者:
-
- 菲鸽
-
-
-
- 官网地址:
-
- https://unibest.tech
-
-
-
-
-
-
- 新手请看必看章节1:
-
-
-
-
-
- 新手请看必看章节1:
-
- https://unibest.tech/base/3-plugin
-
-
-
-
-
-
- 新手请看必看章节2:
-
-
-
-
-
- 新手请看必看章节2:
-
- https://unibest.tech/base/14-faq
-
-
-
-
-
-
- UI组件按钮
-
-
-
- UI组件官网:
- https://wot-design-uni.cn
-
-
-
+
+
+ 123--{{ index }}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/pages/my/my.vue b/src/pages/my/my.vue
new file mode 100644
index 0000000..47eb572
--- /dev/null
+++ b/src/pages/my/my.vue
@@ -0,0 +1,120 @@
+
+{
+ "layout": "tabbar",
+ "style": {
+ // 'custom' 表示开启自定义导航栏,默认 'default'
+ "navigationStyle": "custom",
+ "navigationBarTitleText": "我的"
+ }
+}
+
+
+
+
+
+
+
+ unibest
+
+
+ 最好用的 uniapp 开发模板
+
+
+
+ {{ description }}
+
+
+ 作者:
+
+ 菲鸽
+
+
+
+ 官网地址:
+
+ https://unibest.tech
+
+
+
+
+
+
+ 新手请看必看章节1:
+
+
+
+
+
+ 新手请看必看章节1:
+
+ https://unibest.tech/base/3-plugin
+
+
+
+
+
+
+ 新手请看必看章节2:
+
+
+
+
+
+ 新手请看必看章节2:
+
+ https://unibest.tech/base/14-faq
+
+
+
+
+
+
+ UI组件按钮
+
+
+
+ UI组件官网:
+ https://wot-design-uni.cn
+
+
+
+
+
+
diff --git a/src/pages/reserve/reserve.vue b/src/pages/reserve/reserve.vue
new file mode 100644
index 0000000..31cec65
--- /dev/null
+++ b/src/pages/reserve/reserve.vue
@@ -0,0 +1,120 @@
+
+{
+ "layout": "tabbar",
+ "style": {
+ // 'custom' 表示开启自定义导航栏,默认 'default'
+ "navigationStyle": "custom",
+ "navigationBarTitleText": "预约"
+ }
+}
+
+
+
+
+
+
+
+ unibest
+
+
+ 最好用的 uniapp 开发模板
+
+
+
+ {{ description }}
+
+
+ 作者:
+
+ 菲鸽
+
+
+
+ 官网地址:
+
+ https://unibest.tech
+
+
+
+
+
+
+ 新手请看必看章节1:
+
+
+
+
+
+ 新手请看必看章节1:
+
+ https://unibest.tech/base/3-plugin
+
+
+
+
+
+
+ 新手请看必看章节2:
+
+
+
+
+
+ 新手请看必看章节2:
+
+ https://unibest.tech/base/14-faq
+
+
+
+
+
+
+ UI组件按钮
+
+
+
+ UI组件官网:
+ https://wot-design-uni.cn
+
+
+
+
+
+
diff --git a/src/static/icon/icon_arrow_down.png b/src/static/icon/icon_arrow_down.png
new file mode 100644
index 0000000..eb2e2bd
Binary files /dev/null and b/src/static/icon/icon_arrow_down.png differ
diff --git a/src/static/images/home_bg.png b/src/static/images/home_bg.png
new file mode 100644
index 0000000..561998a
Binary files /dev/null and b/src/static/images/home_bg.png differ
diff --git a/src/static/tabbar/example.png b/src/static/tabbar/example.png
deleted file mode 100644
index fd1e942..0000000
Binary files a/src/static/tabbar/example.png and /dev/null differ
diff --git a/src/static/tabbar/exampleHL.png b/src/static/tabbar/exampleHL.png
deleted file mode 100644
index 7501011..0000000
Binary files a/src/static/tabbar/exampleHL.png and /dev/null differ
diff --git a/src/static/tabbar/home.png b/src/static/tabbar/home.png
index 8f82e21..2fa5c0a 100644
Binary files a/src/static/tabbar/home.png and b/src/static/tabbar/home.png differ
diff --git a/src/static/tabbar/homeHL.png b/src/static/tabbar/homeHL.png
deleted file mode 100644
index 26d3761..0000000
Binary files a/src/static/tabbar/homeHL.png and /dev/null differ
diff --git a/src/static/tabbar/home_s.png b/src/static/tabbar/home_s.png
new file mode 100644
index 0000000..b58714d
Binary files /dev/null and b/src/static/tabbar/home_s.png differ
diff --git a/src/static/tabbar/my.png b/src/static/tabbar/my.png
new file mode 100644
index 0000000..104beff
Binary files /dev/null and b/src/static/tabbar/my.png differ
diff --git a/src/static/tabbar/my_s.png b/src/static/tabbar/my_s.png
new file mode 100644
index 0000000..85a80c3
Binary files /dev/null and b/src/static/tabbar/my_s.png differ
diff --git a/src/static/tabbar/personal.png b/src/static/tabbar/personal.png
deleted file mode 100644
index 0a569a2..0000000
Binary files a/src/static/tabbar/personal.png and /dev/null differ
diff --git a/src/static/tabbar/personalHL.png b/src/static/tabbar/personalHL.png
deleted file mode 100644
index 8c3e66e..0000000
Binary files a/src/static/tabbar/personalHL.png and /dev/null differ
diff --git a/src/static/tabbar/reserve.png b/src/static/tabbar/reserve.png
new file mode 100644
index 0000000..9f817e7
Binary files /dev/null and b/src/static/tabbar/reserve.png differ
diff --git a/src/static/tabbar/reserve_s.png b/src/static/tabbar/reserve_s.png
new file mode 100644
index 0000000..dc9c686
Binary files /dev/null and b/src/static/tabbar/reserve_s.png differ
diff --git a/src/static/tabbar/scan.png b/src/static/tabbar/scan.png
deleted file mode 100644
index f0f60c2..0000000
Binary files a/src/static/tabbar/scan.png and /dev/null differ
diff --git a/src/store/index.ts b/src/store/index.ts
index 74b1b2f..6a276cd 100644
--- a/src/store/index.ts
+++ b/src/store/index.ts
@@ -3,12 +3,12 @@ import { createPersistedState } from 'pinia-plugin-persistedstate' // 数据持
const store = createPinia()
store.use(
- createPersistedState({
- storage: {
- getItem: uni.getStorageSync,
- setItem: uni.setStorageSync,
- },
- }),
+ createPersistedState({
+ storage: {
+ getItem: uni.getStorageSync,
+ setItem: uni.setStorageSync,
+ },
+ }),
)
export default store
diff --git a/src/store/user.ts b/src/store/user.ts
index cec931a..78c815c 100644
--- a/src/store/user.ts
+++ b/src/store/user.ts
@@ -2,110 +2,110 @@ import type { IUserInfoVo } from '@/api/types/login'
import { defineStore } from 'pinia'
import { ref } from 'vue'
import {
- getUserInfo as _getUserInfo,
- login as _login,
- logout as _logout,
- wxLogin as _wxLogin,
- getWxCode,
+ getUserInfo as _getUserInfo,
+ login as _login,
+ logout as _logout,
+ wxLogin as _wxLogin,
+ getWxCode,
} from '@/api/login'
import { toast } from '@/utils/toast'
// 初始化状态
const userInfoState: IUserInfoVo = {
- id: 0,
- username: '',
- avatar: '/static/images/default-avatar.png',
- token: '',
+ id: 0,
+ username: '',
+ avatar: '/static/images/default-avatar.png',
+ token: '',
}
export const useUserStore = defineStore(
- 'user',
- () => {
- // 定义用户信息
- const userInfo = ref({ ...userInfoState })
- // 设置用户信息
- const setUserInfo = (val: IUserInfoVo) => {
- console.log('设置用户信息', val)
- // 若头像为空 则使用默认头像
- if (!val.avatar) {
- val.avatar = userInfoState.avatar
- }
- else {
- val.avatar = 'https://oss.laf.run/ukw0y1-site/avatar.jpg?feige'
- }
- userInfo.value = val
- }
- const setUserAvatar = (avatar: string) => {
- userInfo.value.avatar = avatar
- console.log('设置用户头像', avatar)
- console.log('userInfo', userInfo.value)
- }
- // 删除用户信息
- const removeUserInfo = () => {
- userInfo.value = { ...userInfoState }
- uni.removeStorageSync('userInfo')
- uni.removeStorageSync('token')
- }
- /**
- * 获取用户信息
- */
- const getUserInfo = async () => {
- const res = await _getUserInfo()
- const userInfo = res.data
- setUserInfo(userInfo)
- uni.setStorageSync('userInfo', userInfo)
- uni.setStorageSync('token', userInfo.token)
- // TODO 这里可以增加获取用户路由的方法 根据用户的角色动态生成路由
- return res
- }
- /**
- * 用户登录
- * @param credentials 登录参数
- * @returns R
- */
- const login = async (credentials: {
- username: string
- password: string
- code: string
- uuid: string
- }) => {
- const res = await _login(credentials)
- console.log('登录信息', res)
- toast.success('登录成功')
- await getUserInfo()
- return res
- }
+ 'user',
+ () => {
+ // 定义用户信息
+ const userInfo = ref({ ...userInfoState })
+ // 设置用户信息
+ const setUserInfo = (val: IUserInfoVo) => {
+ console.log('设置用户信息', val)
+ // 若头像为空 则使用默认头像
+ if (!val.avatar) {
+ val.avatar = userInfoState.avatar
+ }
+ else {
+ val.avatar = 'https://oss.laf.run/ukw0y1-site/avatar.jpg?feige'
+ }
+ userInfo.value = val
+ }
+ const setUserAvatar = (avatar: string) => {
+ userInfo.value.avatar = avatar
+ console.log('设置用户头像', avatar)
+ console.log('userInfo', userInfo.value)
+ }
+ // 删除用户信息
+ const removeUserInfo = () => {
+ userInfo.value = { ...userInfoState }
+ uni.removeStorageSync('userInfo')
+ uni.removeStorageSync('token')
+ }
+ /**
+ * 获取用户信息
+ */
+ const getUserInfo = async () => {
+ const res = await _getUserInfo()
+ const userInfo = res.data
+ setUserInfo(userInfo)
+ uni.setStorageSync('userInfo', userInfo)
+ uni.setStorageSync('token', userInfo.token)
+ // TODO 这里可以增加获取用户路由的方法 根据用户的角色动态生成路由
+ return res
+ }
+ /**
+ * 用户登录
+ * @param credentials 登录参数
+ * @returns R
+ */
+ const login = async (credentials: {
+ username: string
+ password: string
+ code: string
+ uuid: string
+ }) => {
+ const res = await _login(credentials)
+ console.log('登录信息', res)
+ toast.success('登录成功')
+ await getUserInfo()
+ return res
+ }
- /**
- * 退出登录 并 删除用户信息
- */
- const logout = async () => {
- _logout()
- removeUserInfo()
- }
- /**
- * 微信登录
- */
- const wxLogin = async () => {
- // 获取微信小程序登录的code
- const data = await getWxCode()
- console.log('微信登录code', data)
+ /**
+ * 退出登录 并 删除用户信息
+ */
+ const logout = async () => {
+ _logout()
+ removeUserInfo()
+ }
+ /**
+ * 微信登录
+ */
+ const wxLogin = async () => {
+ // 获取微信小程序登录的code
+ const data = await getWxCode()
+ console.log('微信登录code', data)
- const res = await _wxLogin(data)
- await getUserInfo()
- return res
- }
+ const res = await _wxLogin(data)
+ await getUserInfo()
+ return res
+ }
- return {
- userInfo,
- login,
- wxLogin,
- getUserInfo,
- setUserAvatar,
- logout,
- }
- },
- {
- persist: true,
- },
+ return {
+ userInfo,
+ login,
+ wxLogin,
+ getUserInfo,
+ setUserAvatar,
+ logout,
+ }
+ },
+ {
+ persist: true,
+ },
)
diff --git a/src/tabbar/config.ts b/src/tabbar/config.ts
index 94c4020..27cddca 100644
--- a/src/tabbar/config.ts
+++ b/src/tabbar/config.ts
@@ -3,11 +3,11 @@ import type { TabBar } from '@uni-helper/vite-plugin-uni-pages'
type NativeTabBarItem = TabBar['list'][0]
type CustomTabBarItem = (Pick & {
- iconType: 'uniUi' | 'uiLib' | 'unocss' | 'iconfont' | 'image' // 不建议用 image 模式,需要配置2张图
- icon: any // 其实是 string 类型,这里是为了避免 ts 报错 (tabbar/index.vue 里面 uni-icons 那行)
- activeIcon?: string // 只有在 image 模式下才需要,传递的是高亮的图片(PS: 不建议用 image 模式)
- badge?: number | 'dot' // badge 显示一个数字或 小红点(样式可以直接在 tabbar/index.vue 里面修改)
- isBulge?: boolean // 是否是中间的鼓包tabbarItem
+ iconType: 'uniUi' | 'uiLib' | 'unocss' | 'iconfont' | 'image' // 不建议用 image 模式,需要配置2张图
+ icon: any // 其实是 string 类型,这里是为了避免 ts 报错 (tabbar/index.vue 里面 uni-icons 那行)
+ activeIcon?: string // 只有在 image 模式下才需要,传递的是高亮的图片(PS: 不建议用 image 模式)
+ badge?: number | 'dot' // badge 显示一个数字或 小红点(样式可以直接在 tabbar/index.vue 里面修改)
+ isBulge?: boolean // 是否是中间的鼓包tabbarItem
})
/**
@@ -20,14 +20,14 @@ type CustomTabBarItem = (Pick & {
* 温馨提示:本文件的任何代码更改了之后,都需要重新运行,否则 pages.json 不会更新导致配置不生效
*/
export const TABBAR_MAP = {
- NO_TABBAR: 0,
- NATIVE_TABBAR: 1,
- CUSTOM_TABBAR_WITH_CACHE: 2,
- CUSTOM_TABBAR_WITHOUT_CACHE: 3,
+ NO_TABBAR: 0,
+ NATIVE_TABBAR: 1,
+ CUSTOM_TABBAR_WITH_CACHE: 2,
+ CUSTOM_TABBAR_WITHOUT_CACHE: 3,
}
// TODO: 1/3. 通过这里切换使用tabbar的策略
-export const selectedTabbarStrategy = TABBAR_MAP.CUSTOM_TABBAR_WITH_CACHE
+export const selectedTabbarStrategy = TABBAR_MAP.NATIVE_TABBAR
// TODO: 2/3. 更新下面的 tabbar 配置
// 如果是使用 NO_TABBAR(0),nativeTabbarList 和 customTabbarList 都不生效(里面的配置不用管)
@@ -35,90 +35,102 @@ export const selectedTabbarStrategy = TABBAR_MAP.CUSTOM_TABBAR_WITH_CACHE
// 如果是使用 CUSTOM_TABBAR(2,3),nativeTabbarList 不生效(里面的配置不用管)
// pagePath 是 nativeTabbarList 和 customTabbarList 的关联点,如果没有对应上,会有问题!!
export const nativeTabbarList: NativeTabBarItem[] = [
- {
- iconPath: 'static/tabbar/home.png',
- selectedIconPath: 'static/tabbar/homeHL.png',
- pagePath: 'pages/index/index',
- text: '首页',
- },
- {
- iconPath: 'static/tabbar/example.png',
- selectedIconPath: 'static/tabbar/exampleHL.png',
- pagePath: 'pages/about/about',
- text: '关于',
- },
+ {
+ iconPath: 'static/tabbar/home.png',
+ selectedIconPath: 'static/tabbar/home_s.png',
+ pagePath: 'pages/index/index',
+ text: '首页',
+ },
+ {
+ iconPath: 'static/tabbar/reserve.png',
+ selectedIconPath: 'static/tabbar/reserve_s.png',
+ pagePath: 'pages/reserve/reserve',
+ text: '预约',
+ },
+ {
+ iconPath: 'static/tabbar/my.png',
+ selectedIconPath: 'static/tabbar/my_s.png',
+ pagePath: 'pages/my/my',
+ text: '我的',
+ },
+ // {
+ // iconPath: 'static/tabbar/example.png',
+ // selectedIconPath: 'static/tabbar/exampleHL.png',
+ // pagePath: 'pages/about/about',
+ // text: '关于',
+ // },
]
// pagePath 是 nativeTabbarList 和 customTabbarList 的关联点,如果没有对应上,会有问题!!
// 如果希望通过接口调用 customTabbarList,可以在 tabbar/index.vue 文件里面调用接口
// 本文件因为需要提前编译生成 pages.json, 接口拦截还不生效,无法正常调用接口
export const customTabbarList: CustomTabBarItem[] = [
- {
- // text 和 pagePath 可以自己直接写,也可以通过索引从 nativeTabbarList 中获取
- text: '首页',
- pagePath: 'pages/index/index', // pagePath 是两者的关联点
- // 本框架内置了 uniapp 官方UI库 (uni-ui)的图标库
- // 使用方式如:
- // 图标列表地址:https://uniapp.dcloud.net.cn/component/uniui/uni-icons.html
- iconType: 'uniUi',
- icon: 'home',
- // badge: 'dot',
- },
- {
- text: nativeTabbarList[1].text,
- pagePath: nativeTabbarList[1].pagePath, // pagePath 是两者的关联点
- // 注意 unocss 图标需要如下处理:(二选一)
- // 1)在fg-tabbar.vue页面上引入一下并注释掉(见tabbar/index.vue代码第2行)
- // 2)配置到 unocss.config.ts 的 safelist 中
- iconType: 'unocss',
- icon: 'i-carbon-code',
- // badge: 10,
- },
+ {
+ // text 和 pagePath 可以自己直接写,也可以通过索引从 nativeTabbarList 中获取
+ text: '首页',
+ pagePath: 'pages/index/index', // pagePath 是两者的关联点
+ // 本框架内置了 uniapp 官方UI库 (uni-ui)的图标库
+ // 使用方式如:
+ // 图标列表地址:https://uniapp.dcloud.net.cn/component/uniui/uni-icons.html
+ iconType: 'uniUi',
+ icon: 'home',
+ // badge: 'dot',
+ },
+ {
+ text: nativeTabbarList[1].text,
+ pagePath: nativeTabbarList[1].pagePath, // pagePath 是两者的关联点
+ // 注意 unocss 图标需要如下处理:(二选一)
+ // 1)在fg-tabbar.vue页面上引入一下并注释掉(见tabbar/index.vue代码第2行)
+ // 2)配置到 unocss.config.ts 的 safelist 中
+ iconType: 'unocss',
+ icon: 'i-carbon-code',
+ // badge: 10,
+ },
- // {
- // pagePath: 'pages/mine/index',
- // text: '我的',
- // // 注意 iconfont 图标需要额外加上 'iconfont',如下
- // iconType: 'iconfont',
- // icon: 'iconfont icon-my',
- // },
- // {
- // pagePath: 'pages/index/index',
- // text: '首页',
- // // 使用 ‘image’时,需要配置 icon + iconActive 2张图片(不推荐)
- // // 既然已经用了自定义tabbar了,就不建议用图片了,所以不推荐
- // iconType: 'image',
- // icon: '/static/tabbar/home.png',
- // iconActive: '/static/tabbar/homeHL.png',
- // },
+ // {
+ // pagePath: 'pages/mine/index',
+ // text: '我的',
+ // // 注意 iconfont 图标需要额外加上 'iconfont',如下
+ // iconType: 'iconfont',
+ // icon: 'iconfont icon-my',
+ // },
+ // {
+ // pagePath: 'pages/index/index',
+ // text: '首页',
+ // // 使用 ‘image’时,需要配置 icon + iconActive 2张图片(不推荐)
+ // // 既然已经用了自定义tabbar了,就不建议用图片了,所以不推荐
+ // iconType: 'image',
+ // icon: '/static/tabbar/home.png',
+ // iconActive: '/static/tabbar/homeHL.png',
+ // },
]
// NATIVE_TABBAR(1) 和 CUSTOM_TABBAR_WITH_CACHE(2) 时,需要tabbar缓存
/** 是否启用 tabbar 缓存 */
export const tabbarCacheEnable
- = [TABBAR_MAP.NATIVE_TABBAR, TABBAR_MAP.CUSTOM_TABBAR_WITH_CACHE].includes(selectedTabbarStrategy)
+ = [TABBAR_MAP.NATIVE_TABBAR, TABBAR_MAP.CUSTOM_TABBAR_WITH_CACHE].includes(selectedTabbarStrategy)
// CUSTOM_TABBAR_WITH_CACHE(2) 和 CUSTOM_TABBAR_WITHOUT_CACHE(3) 时,启用自定义tabbar
/** 是否启用自定义 tabbar */
export const customTabbarEnable
- = [TABBAR_MAP.CUSTOM_TABBAR_WITH_CACHE, TABBAR_MAP.CUSTOM_TABBAR_WITHOUT_CACHE].includes(selectedTabbarStrategy)
+ = [TABBAR_MAP.CUSTOM_TABBAR_WITH_CACHE, TABBAR_MAP.CUSTOM_TABBAR_WITHOUT_CACHE].includes(selectedTabbarStrategy)
// CUSTOM_TABBAR_WITH_CACHE(2)时,需要隐藏原生tabbar
/** 是否需要隐藏原生 tabbar */
export const nativeTabbarNeedHide = selectedTabbarStrategy === TABBAR_MAP.CUSTOM_TABBAR_WITH_CACHE
const _tabbar: TabBar = {
- // 只有微信小程序支持 custom。App 和 H5 不生效
- custom: selectedTabbarStrategy === TABBAR_MAP.CUSTOM_TABBAR_WITH_CACHE,
- color: '#999999',
- selectedColor: '#018d71',
- backgroundColor: '#F8F8F8',
- borderStyle: 'black',
- height: '50px',
- fontSize: '10px',
- iconWidth: '24px',
- spacing: '3px',
- list: nativeTabbarList as unknown as TabBar['list'],
+ // 只有微信小程序支持 custom。App 和 H5 不生效
+ custom: selectedTabbarStrategy === TABBAR_MAP.CUSTOM_TABBAR_WITH_CACHE,
+ color: '#999999',
+ selectedColor: '#018d71',
+ backgroundColor: '#F8F8F8',
+ borderStyle: 'black',
+ height: '50px',
+ fontSize: '10px',
+ iconWidth: '24px',
+ spacing: '3px',
+ list: nativeTabbarList as unknown as TabBar['list'],
}
export const tabbarList = nativeTabbarList
diff --git a/src/uni.scss b/src/uni.scss
index 21b9e5f..bc750e1 100644
--- a/src/uni.scss
+++ b/src/uni.scss
@@ -75,3 +75,6 @@ $uni-color-subtitle: #555; // 二级标题颜色
$uni-font-size-subtitle: 18px;
$uni-color-paragraph: #3f536e; // 文章段落颜色
$uni-font-size-paragraph: 15px;
+
+$cz-page-background: #F6F7F9; // 页面背景色
+$OSS: '/src/static/';
diff --git a/src/utils/index.ts b/src/utils/index.ts
index 3aa8e52..79a9e29 100644
--- a/src/utils/index.ts
+++ b/src/utils/index.ts
@@ -3,11 +3,11 @@ import { tabbarList } from '@/tabbar/config'
import { isMpWeixin } from './platform'
export function getLastPage() {
- // getCurrentPages() 至少有1个元素,所以不再额外判断
- // const lastPage = getCurrentPages().at(-1)
- // 上面那个在低版本安卓中打包会报错,所以改用下面这个【虽然我加了 src/interceptions/prototype.ts,但依然报错】
- const pages = getCurrentPages()
- return pages[pages.length - 1]
+ // getCurrentPages() 至少有1个元素,所以不再额外判断
+ // const lastPage = getCurrentPages().at(-1)
+ // 上面那个在低版本安卓中打包会报错,所以改用下面这个【虽然我加了 src/interceptions/prototype.ts,但依然报错】
+ const pages = getCurrentPages()
+ return pages[pages.length - 1]
}
/**
@@ -16,25 +16,25 @@ export function getLastPage() {
* redirectPath 如 '/pages/demo/base/route-interceptor'
*/
export function currRoute() {
- const lastPage = getLastPage()
- const currRoute = (lastPage as any).$page
- // console.log('lastPage.$page:', currRoute)
- // console.log('lastPage.$page.fullpath:', currRoute.fullPath)
- // console.log('lastPage.$page.options:', currRoute.options)
- // console.log('lastPage.options:', (lastPage as any).options)
- // 经过多端测试,只有 fullPath 靠谱,其他都不靠谱
- const { fullPath } = currRoute as { fullPath: string }
- // console.log(fullPath)
- // eg: /pages/login/index?redirect=%2Fpages%2Fdemo%2Fbase%2Froute-interceptor (小程序)
- // eg: /pages/login/index?redirect=%2Fpages%2Froute-interceptor%2Findex%3Fname%3Dfeige%26age%3D30(h5)
- return getUrlObj(fullPath)
+ const lastPage = getLastPage()
+ const currRoute = (lastPage as any).$page
+ // console.log('lastPage.$page:', currRoute)
+ // console.log('lastPage.$page.fullpath:', currRoute.fullPath)
+ // console.log('lastPage.$page.options:', currRoute.options)
+ // console.log('lastPage.options:', (lastPage as any).options)
+ // 经过多端测试,只有 fullPath 靠谱,其他都不靠谱
+ const { fullPath } = currRoute as { fullPath: string }
+ // console.log(fullPath)
+ // eg: /pages/login/index?redirect=%2Fpages%2Fdemo%2Fbase%2Froute-interceptor (小程序)
+ // eg: /pages/login/index?redirect=%2Fpages%2Froute-interceptor%2Findex%3Fname%3Dfeige%26age%3D30(h5)
+ return getUrlObj(fullPath)
}
function ensureDecodeURIComponent(url: string) {
- if (url.startsWith('%')) {
- return ensureDecodeURIComponent(decodeURIComponent(url))
- }
- return url
+ if (url.startsWith('%')) {
+ return ensureDecodeURIComponent(decodeURIComponent(url))
+ }
+ return url
}
/**
* 解析 url 得到 path 和 query
@@ -42,22 +42,22 @@ function ensureDecodeURIComponent(url: string) {
* 输出: {path: /pages/login/index, query: {redirect: /pages/demo/base/route-interceptor}}
*/
export function getUrlObj(url: string) {
- const [path, queryStr] = url.split('?')
- // console.log(path, queryStr)
+ const [path, queryStr] = url.split('?')
+ // console.log(path, queryStr)
- if (!queryStr) {
- return {
- path,
- query: {},
- }
- }
- const query: Record = {}
- queryStr.split('&').forEach((item) => {
- const [key, value] = item.split('=')
- // console.log(key, value)
- query[key] = ensureDecodeURIComponent(value) // 这里需要统一 decodeURIComponent 一下,可以兼容h5和微信y
- })
- return { path, query }
+ if (!queryStr) {
+ return {
+ path,
+ query: {},
+ }
+ }
+ const query: Record = {}
+ queryStr.split('&').forEach((item) => {
+ const [key, value] = item.split('=')
+ // console.log(key, value)
+ query[key] = ensureDecodeURIComponent(value) // 这里需要统一 decodeURIComponent 一下,可以兼容h5和微信y
+ })
+ return { path, query }
}
/**
* 得到所有的需要登录的 pages,包括主包和分包的
@@ -65,49 +65,49 @@ export function getUrlObj(url: string) {
* 如果没有传 key,则表示所有的 pages,如果传递了 key, 则表示通过 key 过滤
*/
export function getAllPages(key = 'needLogin') {
- // 这里处理主包
- const mainPages = pages
- .filter(page => !key || page[key])
- .map(page => ({
- ...page,
- path: `/${page.path}`,
- }))
+ // 这里处理主包
+ const mainPages = pages
+ .filter(page => !key || page[key])
+ .map(page => ({
+ ...page,
+ path: `/${page.path}`,
+ }))
- // 这里处理分包
- const subPages: any[] = []
- subPackages.forEach((subPageObj) => {
- // console.log(subPageObj)
- const { root } = subPageObj
+ // 这里处理分包
+ const subPages: any[] = []
+ subPackages.forEach((subPageObj) => {
+ // console.log(subPageObj)
+ const { root } = subPageObj
- subPageObj.pages
- .filter(page => !key || page[key])
- .forEach((page: { path: string } & Record) => {
- subPages.push({
- ...page,
- path: `/${root}/${page.path}`,
- })
- })
- })
- const result = [...mainPages, ...subPages]
- // console.log(`getAllPages by ${key} result: `, result)
- return result
+ subPageObj.pages
+ .filter(page => !key || page[key])
+ .forEach((page: { path: string } & Record) => {
+ subPages.push({
+ ...page,
+ path: `/${root}/${page.path}`,
+ })
+ })
+ })
+ const result = [...mainPages, ...subPages]
+ // console.log(`getAllPages by ${key} result: `, result)
+ return result
}
export function isCurrentPageTabbar() {
- const routeObj = currRoute()
- return tabbarList.some(item => `/${item.pagePath}` === routeObj.path)
+ const routeObj = currRoute()
+ return tabbarList.some(item => `/${item.pagePath}` === routeObj.path)
}
export function getCurrentPageI18nKey() {
- const routeObj = currRoute()
- const currPage = pages.find(page => `/${page.path}` === routeObj.path)
- if (!currPage) {
- console.warn('路由不正确')
- return ''
- }
- console.log(currPage)
- console.log(currPage.style.navigationBarTitleText)
- return currPage.style.navigationBarTitleText
+ const routeObj = currRoute()
+ const currPage = pages.find(page => `/${page.path}` === routeObj.path)
+ if (!currPage) {
+ console.warn('路由不正确')
+ return ''
+ }
+ console.log(currPage)
+ console.log(currPage.style.navigationBarTitleText)
+ return currPage.style.navigationBarTitleText
}
/**
@@ -126,65 +126,75 @@ export const needLoginPages: string[] = getAllPages('needLogin').map(page => pag
* 根据微信小程序当前环境,判断应该获取的 baseUrl
*/
export function getEnvBaseUrl() {
- // 请求基准地址
- let baseUrl = import.meta.env.VITE_SERVER_BASEURL
+ // 请求基准地址
+ let baseUrl = import.meta.env.VITE_SERVER_BASEURL
- // # 有些同学可能需要在微信小程序里面根据 develop、trial、release 分别设置上传地址,参考代码如下。
- const VITE_SERVER_BASEURL__WEIXIN_DEVELOP = 'https://ukw0y1.laf.run'
- const VITE_SERVER_BASEURL__WEIXIN_TRIAL = 'https://ukw0y1.laf.run'
- const VITE_SERVER_BASEURL__WEIXIN_RELEASE = 'https://ukw0y1.laf.run'
+ // # 有些同学可能需要在微信小程序里面根据 develop、trial、release 分别设置上传地址,参考代码如下。
+ const VITE_SERVER_BASEURL__WEIXIN_DEVELOP = 'https://ukw0y1.laf.run'
+ const VITE_SERVER_BASEURL__WEIXIN_TRIAL = 'https://ukw0y1.laf.run'
+ const VITE_SERVER_BASEURL__WEIXIN_RELEASE = 'https://ukw0y1.laf.run'
- // 微信小程序端环境区分
- if (isMpWeixin) {
- const {
- miniProgram: { envVersion },
- } = uni.getAccountInfoSync()
+ // 微信小程序端环境区分
+ if (isMpWeixin) {
+ const {
+ miniProgram: { envVersion },
+ } = uni.getAccountInfoSync()
- switch (envVersion) {
- case 'develop':
- baseUrl = VITE_SERVER_BASEURL__WEIXIN_DEVELOP || baseUrl
- break
- case 'trial':
- baseUrl = VITE_SERVER_BASEURL__WEIXIN_TRIAL || baseUrl
- break
- case 'release':
- baseUrl = VITE_SERVER_BASEURL__WEIXIN_RELEASE || baseUrl
- break
- }
- }
+ switch (envVersion) {
+ case 'develop':
+ baseUrl = VITE_SERVER_BASEURL__WEIXIN_DEVELOP || baseUrl
+ break
+ case 'trial':
+ baseUrl = VITE_SERVER_BASEURL__WEIXIN_TRIAL || baseUrl
+ break
+ case 'release':
+ baseUrl = VITE_SERVER_BASEURL__WEIXIN_RELEASE || baseUrl
+ break
+ }
+ }
- return baseUrl
+ return baseUrl
}
/**
* 根据微信小程序当前环境,判断应该获取的 UPLOAD_BASEURL
*/
export function getEnvBaseUploadUrl() {
- // 请求基准地址
- let baseUploadUrl = import.meta.env.VITE_UPLOAD_BASEURL
+ // 请求基准地址
+ let baseUploadUrl = import.meta.env.VITE_UPLOAD_BASEURL
- const VITE_UPLOAD_BASEURL__WEIXIN_DEVELOP = 'https://ukw0y1.laf.run/upload'
- const VITE_UPLOAD_BASEURL__WEIXIN_TRIAL = 'https://ukw0y1.laf.run/upload'
- const VITE_UPLOAD_BASEURL__WEIXIN_RELEASE = 'https://ukw0y1.laf.run/upload'
+ const VITE_UPLOAD_BASEURL__WEIXIN_DEVELOP = 'https://ukw0y1.laf.run/upload'
+ const VITE_UPLOAD_BASEURL__WEIXIN_TRIAL = 'https://ukw0y1.laf.run/upload'
+ const VITE_UPLOAD_BASEURL__WEIXIN_RELEASE = 'https://ukw0y1.laf.run/upload'
- // 微信小程序端环境区分
- if (isMpWeixin) {
- const {
- miniProgram: { envVersion },
- } = uni.getAccountInfoSync()
+ // 微信小程序端环境区分
+ if (isMpWeixin) {
+ const {
+ miniProgram: { envVersion },
+ } = uni.getAccountInfoSync()
- switch (envVersion) {
- case 'develop':
- baseUploadUrl = VITE_UPLOAD_BASEURL__WEIXIN_DEVELOP || baseUploadUrl
- break
- case 'trial':
- baseUploadUrl = VITE_UPLOAD_BASEURL__WEIXIN_TRIAL || baseUploadUrl
- break
- case 'release':
- baseUploadUrl = VITE_UPLOAD_BASEURL__WEIXIN_RELEASE || baseUploadUrl
- break
- }
- }
+ switch (envVersion) {
+ case 'develop':
+ baseUploadUrl = VITE_UPLOAD_BASEURL__WEIXIN_DEVELOP || baseUploadUrl
+ break
+ case 'trial':
+ baseUploadUrl = VITE_UPLOAD_BASEURL__WEIXIN_TRIAL || baseUploadUrl
+ break
+ case 'release':
+ baseUploadUrl = VITE_UPLOAD_BASEURL__WEIXIN_RELEASE || baseUploadUrl
+ break
+ }
+ }
- return baseUploadUrl
+ return baseUploadUrl
}
+
+export function getNavBarHeight() {
+ const systemInfo = uni.getSystemInfoSync()
+ const statusBarHeight = systemInfo.statusBarHeight; // 状态栏高度(单位:px)
+ const titleBarHeight = 44; // 默认导航栏标题高度(iOS/Android 一般为 44px)
+ const navbarHeight = statusBarHeight + titleBarHeight; // 完整的导航栏高度
+
+ console.log("🚀 ~ getNavBarHeight ~ navbarHeight:", navbarHeight)
+ return navbarHeight
+}
\ No newline at end of file
diff --git a/src/utils/uploadFile.ts b/src/utils/uploadFile.ts
index 416d39c..643b053 100644
--- a/src/utils/uploadFile.ts
+++ b/src/utils/uploadFile.ts
@@ -20,8 +20,8 @@ import { toast } from './toast'
* 上传文件的URL配置
*/
export const uploadFileUrl = {
- /** 用户头像上传地址 */
- USER_AVATAR: `${import.meta.env.VITE_SERVER_BASEURL}/user/avatar`,
+ /** 用户头像上传地址 */
+ USER_AVATAR: `${import.meta.env.VITE_SERVER_BASEURL}/user/avatar`,
}
/**
@@ -32,35 +32,35 @@ export const uploadFileUrl = {
* @param options 上传选项
*/
export function useFileUpload(url: string, filePath: string, formData: Record = {}, options: Omit = {}) {
- return useUpload(
- url,
- formData,
- {
- ...options,
- sourceType: ['album'],
- sizeType: ['original'],
- },
- filePath,
- )
+ return useUpload(
+ url,
+ formData,
+ {
+ ...options,
+ sourceType: ['album'],
+ sizeType: ['original'],
+ },
+ filePath,
+ )
}
export interface UploadOptions {
- /** 最大可选择的图片数量,默认为1 */
- count?: number
- /** 所选的图片的尺寸,original-原图,compressed-压缩图 */
- sizeType?: Array<'original' | 'compressed'>
- /** 选择图片的来源,album-相册,camera-相机 */
- sourceType?: Array<'album' | 'camera'>
- /** 文件大小限制,单位:MB */
- maxSize?: number //
- /** 上传进度回调函数 */
- onProgress?: (progress: number) => void
- /** 上传成功回调函数 */
- onSuccess?: (res: Record) => void
- /** 上传失败回调函数 */
- onError?: (err: Error | UniApp.GeneralCallbackResult) => void
- /** 上传完成回调函数(无论成功失败) */
- onComplete?: () => void
+ /** 最大可选择的图片数量,默认为1 */
+ count?: number
+ /** 所选的图片的尺寸,original-原图,compressed-压缩图 */
+ sizeType?: Array<'original' | 'compressed'>
+ /** 选择图片的来源,album-相册,camera-相机 */
+ sourceType?: Array<'album' | 'camera'>
+ /** 文件大小限制,单位:MB */
+ maxSize?: number //
+ /** 上传进度回调函数 */
+ onProgress?: (progress: number) => void
+ /** 上传成功回调函数 */
+ onSuccess?: (res: Record) => void
+ /** 上传失败回调函数 */
+ onError?: (err: Error | UniApp.GeneralCallbackResult) => void
+ /** 上传完成回调函数(无论成功失败) */
+ onComplete?: () => void
}
/**
@@ -72,150 +72,150 @@ export interface UploadOptions {
* @returns 上传状态和控制对象
*/
export function useUpload(url: string, formData: Record = {}, options: UploadOptions = {},
- /** 直接传入文件路径,跳过选择器 */
- directFilePath?: string) {
- /** 上传中状态 */
- const loading = ref(false)
- /** 上传错误状态 */
- const error = ref(false)
- /** 上传成功后的响应数据 */
- const data = ref()
- /** 上传进度(0-100) */
- const progress = ref(0)
+ /** 直接传入文件路径,跳过选择器 */
+ directFilePath?: string) {
+ /** 上传中状态 */
+ const loading = ref(false)
+ /** 上传错误状态 */
+ const error = ref(false)
+ /** 上传成功后的响应数据 */
+ const data = ref()
+ /** 上传进度(0-100) */
+ const progress = ref(0)
- /** 解构上传选项,设置默认值 */
- const {
- /** 最大可选择的图片数量 */
- count = 1,
- /** 所选的图片的尺寸 */
- sizeType = ['original', 'compressed'],
- /** 选择图片的来源 */
- sourceType = ['album', 'camera'],
- /** 文件大小限制(MB) */
- maxSize = 10,
- /** 进度回调 */
- onProgress,
- /** 成功回调 */
- onSuccess,
- /** 失败回调 */
- onError,
- /** 完成回调 */
- onComplete,
- } = options
+ /** 解构上传选项,设置默认值 */
+ const {
+ /** 最大可选择的图片数量 */
+ count = 1,
+ /** 所选的图片的尺寸 */
+ sizeType = ['original', 'compressed'],
+ /** 选择图片的来源 */
+ sourceType = ['album', 'camera'],
+ /** 文件大小限制(MB) */
+ maxSize = 10,
+ /** 进度回调 */
+ onProgress,
+ /** 成功回调 */
+ onSuccess,
+ /** 失败回调 */
+ onError,
+ /** 完成回调 */
+ onComplete,
+ } = options
- /**
- * 检查文件大小是否超过限制
- * @param size 文件大小(字节)
- * @returns 是否通过检查
- */
- const checkFileSize = (size: number) => {
- const sizeInMB = size / 1024 / 1024
- if (sizeInMB > maxSize) {
- toast.warning(`文件大小不能超过${maxSize}MB`)
- return false
- }
- return true
- }
- /**
- * 触发文件选择和上传
- * 根据平台使用不同的选择器:
- * - 微信小程序使用 chooseMedia
- * - 其他平台使用 chooseImage
- */
- const run = () => {
- if (directFilePath) {
- // 直接使用传入的文件路径
- loading.value = true
- progress.value = 0
- uploadFile({
- url,
- tempFilePath: directFilePath,
- formData,
- data,
- error,
- loading,
- progress,
- onProgress,
- onSuccess,
- onError,
- onComplete,
- })
- return
- }
+ /**
+ * 检查文件大小是否超过限制
+ * @param size 文件大小(字节)
+ * @returns 是否通过检查
+ */
+ const checkFileSize = (size: number) => {
+ const sizeInMB = size / 1024 / 1024
+ if (sizeInMB > maxSize) {
+ toast.warning(`文件大小不能超过${maxSize}MB`)
+ return false
+ }
+ return true
+ }
+ /**
+ * 触发文件选择和上传
+ * 根据平台使用不同的选择器:
+ * - 微信小程序使用 chooseMedia
+ * - 其他平台使用 chooseImage
+ */
+ const run = () => {
+ if (directFilePath) {
+ // 直接使用传入的文件路径
+ loading.value = true
+ progress.value = 0
+ uploadFile({
+ url,
+ tempFilePath: directFilePath,
+ formData,
+ data,
+ error,
+ loading,
+ progress,
+ onProgress,
+ onSuccess,
+ onError,
+ onComplete,
+ })
+ return
+ }
- // #ifdef MP-WEIXIN
- // 微信小程序环境下使用 chooseMedia API
- uni.chooseMedia({
- count,
- mediaType: ['image'], // 仅支持图片类型
- sourceType,
- success: (res) => {
- const file = res.tempFiles[0]
- // 检查文件大小是否符合限制
- if (!checkFileSize(file.size))
- return
+ // #ifdef MP-WEIXIN
+ // 微信小程序环境下使用 chooseMedia API
+ uni.chooseMedia({
+ count,
+ mediaType: ['image'], // 仅支持图片类型
+ sourceType,
+ success: (res) => {
+ const file = res.tempFiles[0]
+ // 检查文件大小是否符合限制
+ if (!checkFileSize(file.size))
+ return
- // 开始上传
- loading.value = true
- progress.value = 0
- uploadFile({
- url,
- tempFilePath: file.tempFilePath,
- formData,
- data,
- error,
- loading,
- progress,
- onProgress,
- onSuccess,
- onError,
- onComplete,
- })
- },
- fail: (err) => {
- console.error('选择媒体文件失败:', err)
- error.value = true
- onError?.(err)
- },
- })
- // #endif
+ // 开始上传
+ loading.value = true
+ progress.value = 0
+ uploadFile({
+ url,
+ tempFilePath: file.tempFilePath,
+ formData,
+ data,
+ error,
+ loading,
+ progress,
+ onProgress,
+ onSuccess,
+ onError,
+ onComplete,
+ })
+ },
+ fail: (err) => {
+ console.error('选择媒体文件失败:', err)
+ error.value = true
+ onError?.(err)
+ },
+ })
+ // #endif
- // #ifndef MP-WEIXIN
- // 非微信小程序环境下使用 chooseImage API
- uni.chooseImage({
- count,
- sizeType,
- sourceType,
- success: (res) => {
- console.log('选择图片成功:', res)
+ // #ifndef MP-WEIXIN
+ // 非微信小程序环境下使用 chooseImage API
+ uni.chooseImage({
+ count,
+ sizeType,
+ sourceType,
+ success: (res) => {
+ console.log('选择图片成功:', res)
- // 开始上传
- loading.value = true
- progress.value = 0
- uploadFile({
- url,
- tempFilePath: res.tempFilePaths[0],
- formData,
- data,
- error,
- loading,
- progress,
- onProgress,
- onSuccess,
- onError,
- onComplete,
- })
- },
- fail: (err) => {
- console.error('选择图片失败:', err)
- error.value = true
- onError?.(err)
- },
- })
- // #endif
- }
+ // 开始上传
+ loading.value = true
+ progress.value = 0
+ uploadFile({
+ url,
+ tempFilePath: res.tempFilePaths[0],
+ formData,
+ data,
+ error,
+ loading,
+ progress,
+ onProgress,
+ onSuccess,
+ onError,
+ onComplete,
+ })
+ },
+ fail: (err) => {
+ console.error('选择图片失败:', err)
+ error.value = true
+ onError?.(err)
+ },
+ })
+ // #endif
+ }
- return { loading, error, data, progress, run }
+ return { loading, error, data, progress, run }
}
/**
@@ -223,28 +223,28 @@ export function useUpload(url: string, formData: Record
* @template T 上传成功后返回的数据类型
*/
interface UploadFileOptions {
- /** 上传地址 */
- url: string
- /** 临时文件路径 */
- tempFilePath: string
- /** 额外的表单数据 */
- formData: Record
- /** 上传成功后的响应数据 */
- data: Ref
- /** 上传错误状态 */
- error: Ref
- /** 上传中状态 */
- loading: Ref
- /** 上传进度(0-100) */
- progress: Ref
- /** 上传进度回调 */
- onProgress?: (progress: number) => void
- /** 上传成功回调 */
- onSuccess?: (res: Record) => void
- /** 上传失败回调 */
- onError?: (err: Error | UniApp.GeneralCallbackResult) => void
- /** 上传完成回调 */
- onComplete?: () => void
+ /** 上传地址 */
+ url: string
+ /** 临时文件路径 */
+ tempFilePath: string
+ /** 额外的表单数据 */
+ formData: Record
+ /** 上传成功后的响应数据 */
+ data: Ref
+ /** 上传错误状态 */
+ error: Ref
+ /** 上传中状态 */
+ loading: Ref
+ /** 上传进度(0-100) */
+ progress: Ref
+ /** 上传进度回调 */
+ onProgress?: (progress: number) => void
+ /** 上传成功回调 */
+ onSuccess?: (res: Record) => void
+ /** 上传失败回调 */
+ onError?: (err: Error | UniApp.GeneralCallbackResult) => void
+ /** 上传完成回调 */
+ onComplete?: () => void
}
/**
@@ -253,72 +253,72 @@ interface UploadFileOptions {
* @param options 上传选项
*/
function uploadFile({
- url,
- tempFilePath,
- formData,
- data,
- error,
- loading,
- progress,
- onProgress,
- onSuccess,
- onError,
- onComplete,
+ url,
+ tempFilePath,
+ formData,
+ data,
+ error,
+ loading,
+ progress,
+ onProgress,
+ onSuccess,
+ onError,
+ onComplete,
}: UploadFileOptions) {
- try {
- // 创建上传任务
- const uploadTask = uni.uploadFile({
- url,
- filePath: tempFilePath,
- name: 'file', // 文件对应的 key
- formData,
- header: {
- // H5环境下不需要手动设置Content-Type,让浏览器自动处理multipart格式
- // #ifndef H5
- 'Content-Type': 'multipart/form-data',
- // #endif
- },
- // 确保文件名称合法
- success: (uploadFileRes) => {
- console.log('上传文件成功:', uploadFileRes)
- try {
- // 解析响应数据
- const { data: _data } = JSON.parse(uploadFileRes.data)
- // 上传成功
- data.value = _data as T
- onSuccess?.(_data)
- }
- catch (err) {
- // 响应解析错误
- console.error('解析上传响应失败:', err)
- error.value = true
- onError?.(new Error('上传响应解析失败'))
- }
- },
- fail: (err) => {
- // 上传请求失败
- console.error('上传文件失败:', err)
- error.value = true
- onError?.(err)
- },
- complete: () => {
- // 无论成功失败都执行
- loading.value = false
- onComplete?.()
- },
- })
+ try {
+ // 创建上传任务
+ const uploadTask = uni.uploadFile({
+ url,
+ filePath: tempFilePath,
+ name: 'file', // 文件对应的 key
+ formData,
+ header: {
+ // H5环境下不需要手动设置Content-Type,让浏览器自动处理multipart格式
+ // #ifndef H5
+ 'Content-Type': 'multipart/form-data',
+ // #endif
+ },
+ // 确保文件名称合法
+ success: (uploadFileRes) => {
+ console.log('上传文件成功:', uploadFileRes)
+ try {
+ // 解析响应数据
+ const { data: _data } = JSON.parse(uploadFileRes.data)
+ // 上传成功
+ data.value = _data as T
+ onSuccess?.(_data)
+ }
+ catch (err) {
+ // 响应解析错误
+ console.error('解析上传响应失败:', err)
+ error.value = true
+ onError?.(new Error('上传响应解析失败'))
+ }
+ },
+ fail: (err) => {
+ // 上传请求失败
+ console.error('上传文件失败:', err)
+ error.value = true
+ onError?.(err)
+ },
+ complete: () => {
+ // 无论成功失败都执行
+ loading.value = false
+ onComplete?.()
+ },
+ })
- // 监听上传进度
- uploadTask.onProgressUpdate((res) => {
- progress.value = res.progress
- onProgress?.(res.progress)
- })
- }
- catch (err) {
- // 创建上传任务失败
- console.error('创建上传任务失败:', err)
- error.value = true
- loading.value = false
- onError?.(new Error('创建上传任务失败'))
- }
+ // 监听上传进度
+ uploadTask.onProgressUpdate((res) => {
+ progress.value = res.progress
+ onProgress?.(res.progress)
+ })
+ }
+ catch (err) {
+ // 创建上传任务失败
+ console.error('创建上传任务失败:', err)
+ error.value = true
+ loading.value = false
+ onError?.(new Error('创建上传任务失败'))
+ }
}
diff --git a/uno.config.ts b/uno.config.ts
index 5055f45..45163a3 100644
--- a/uno.config.ts
+++ b/uno.config.ts
@@ -1,66 +1,66 @@
// https://www.npmjs.com/package/@uni-helper/unocss-preset-uni
import { presetUni } from '@uni-helper/unocss-preset-uni'
import {
- defineConfig,
- presetAttributify,
- presetIcons,
- transformerDirectives,
- transformerVariantGroup,
+ defineConfig,
+ presetAttributify,
+ presetIcons,
+ transformerDirectives,
+ transformerVariantGroup,
} from 'unocss'
export default defineConfig({
- presets: [
- presetUni({
- attributify: {
- // prefix: 'fg-', // 如果加前缀,则需要在代码里面使用 `fg-` 前缀,如:
- prefixedOnly: true,
- },
- }),
- presetIcons({
- scale: 1.2,
- warn: true,
- extraProperties: {
- 'display': 'inline-block',
- 'vertical-align': 'middle',
- },
- }),
- // 支持css class属性化
- presetAttributify(),
- ],
- transformers: [
- // 启用指令功能:主要用于支持 @apply、@screen 和 theme() 等 CSS 指令
- transformerDirectives(),
- // 启用 () 分组功能
- // 支持css class组合,eg: `测试 unocss
`
- transformerVariantGroup(),
- ],
- shortcuts: [
- {
- center: 'flex justify-center items-center',
- },
- ],
- // 动态图标需要在这里配置,或者写在vue页面中注释掉
- safelist: ['i-carbon-code'],
- rules: [
- [
- 'p-safe',
- {
- padding:
- 'env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left)',
- },
- ],
- ['pt-safe', { 'padding-top': 'env(safe-area-inset-top)' }],
- ['pb-safe', { 'padding-bottom': 'env(safe-area-inset-bottom)' }],
- ],
- theme: {
- colors: {
- /** 主题色,用法如: text-primary */
- primary: 'var(--wot-color-theme,#0957DE)',
- },
- fontSize: {
- /** 提供更小号的字体,用法如:text-2xs */
- '2xs': ['20rpx', '28rpx'],
- '3xs': ['18rpx', '26rpx'],
- },
- },
+ presets: [
+ presetUni({
+ attributify: {
+ // prefix: 'fg-', // 如果加前缀,则需要在代码里面使用 `fg-` 前缀,如:
+ prefixedOnly: true,
+ },
+ }),
+ presetIcons({
+ scale: 1.2,
+ warn: true,
+ extraProperties: {
+ 'display': 'inline-block',
+ 'vertical-align': 'middle',
+ },
+ }),
+ // 支持css class属性化
+ presetAttributify(),
+ ],
+ transformers: [
+ // 启用指令功能:主要用于支持 @apply、@screen 和 theme() 等 CSS 指令
+ transformerDirectives(),
+ // 启用 () 分组功能
+ // 支持css class组合,eg: `测试 unocss
`
+ transformerVariantGroup(),
+ ],
+ shortcuts: [
+ {
+ center: 'flex justify-center items-center',
+ },
+ ],
+ // 动态图标需要在这里配置,或者写在vue页面中注释掉
+ safelist: ['i-carbon-code'],
+ rules: [
+ [
+ 'p-safe',
+ {
+ padding:
+ 'env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left)',
+ },
+ ],
+ ['pt-safe', { 'padding-top': 'env(safe-area-inset-top)' }],
+ ['pb-safe', { 'padding-bottom': 'env(safe-area-inset-bottom)' }],
+ ],
+ theme: {
+ colors: {
+ /** 主题色,用法如: text-primary */
+ primary: 'var(--wot-color-theme,#0957DE)',
+ },
+ fontSize: {
+ /** 提供更小号的字体,用法如:text-2xs */
+ '2xs': ['20rpx', '28rpx'],
+ '3xs': ['18rpx', '26rpx'],
+ },
+ },
})
diff --git a/vite.config.ts b/vite.config.ts
index 59e6086..1d11e9b 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -25,159 +25,159 @@ import ViteRestart from 'vite-plugin-restart'
// https://vitejs.dev/config/
export default ({ command, mode }) => {
- // @see https://unocss.dev/
- // const UnoCSS = (await import('unocss/vite')).default
- // console.log(mode === process.env.NODE_ENV) // true
+ // @see https://unocss.dev/
+ // const UnoCSS = (await import('unocss/vite')).default
+ // console.log(mode === process.env.NODE_ENV) // true
- // mode: 区分生产环境还是开发环境
- console.log('command, mode -> ', command, mode)
- // pnpm dev:h5 时得到 => serve development
- // pnpm build:h5 时得到 => build production
- // pnpm dev:mp-weixin 时得到 => build development (注意区别,command为build)
- // pnpm build:mp-weixin 时得到 => build production
- // pnpm dev:app 时得到 => build development (注意区别,command为build)
- // pnpm build:app 时得到 => build production
- // dev 和 build 命令可以分别使用 .env.development 和 .env.production 的环境变量
+ // mode: 区分生产环境还是开发环境
+ console.log('command, mode -> ', command, mode)
+ // pnpm dev:h5 时得到 => serve development
+ // pnpm build:h5 时得到 => build production
+ // pnpm dev:mp-weixin 时得到 => build development (注意区别,command为build)
+ // pnpm build:mp-weixin 时得到 => build production
+ // pnpm dev:app 时得到 => build development (注意区别,command为build)
+ // pnpm build:app 时得到 => build production
+ // dev 和 build 命令可以分别使用 .env.development 和 .env.production 的环境变量
- const { UNI_PLATFORM } = process.env
- console.log('UNI_PLATFORM -> ', UNI_PLATFORM) // 得到 mp-weixin, h5, app 等
+ const { UNI_PLATFORM } = process.env
+ console.log('UNI_PLATFORM -> ', UNI_PLATFORM) // 得到 mp-weixin, h5, app 等
- const env = loadEnv(mode, path.resolve(process.cwd(), 'env'))
- const {
- VITE_APP_PORT,
- VITE_SERVER_BASEURL,
- VITE_DELETE_CONSOLE,
- VITE_SHOW_SOURCEMAP,
- VITE_APP_PUBLIC_BASE,
- VITE_APP_PROXY,
- VITE_APP_PROXY_PREFIX,
- } = env
- console.log('环境变量 env -> ', env)
+ const env = loadEnv(mode, path.resolve(process.cwd(), 'env'))
+ const {
+ VITE_APP_PORT,
+ VITE_SERVER_BASEURL,
+ VITE_DELETE_CONSOLE,
+ VITE_SHOW_SOURCEMAP,
+ VITE_APP_PUBLIC_BASE,
+ VITE_APP_PROXY,
+ VITE_APP_PROXY_PREFIX,
+ } = env
+ console.log('环境变量 env -> ', env)
- return defineConfig({
- envDir: './env', // 自定义env目录
- base: VITE_APP_PUBLIC_BASE,
- plugins: [
- UniPages({
- exclude: ['**/components/**/**.*'],
- // homePage 通过 vue 文件的 route-block 的type="home"来设定
- // pages 目录为 src/pages,分包目录不能配置在pages目录下
- subPackages: ['src/pages-sub'], // 是个数组,可以配置多个,但是不能为pages里面的目录
- dts: 'src/types/uni-pages.d.ts',
- }),
- UniLayouts(),
- UniPlatform(),
- UniManifest(),
- // UniXXX 需要在 Uni 之前引入
- {
- // 临时解决 dcloudio 官方的 @dcloudio/uni-mp-compiler 出现的编译 BUG
- // 参考 github issue: https://github.com/dcloudio/uni-app/issues/4952
- // 自定义插件禁用 vite:vue 插件的 devToolsEnabled,强制编译 vue 模板时 inline 为 true
- name: 'fix-vite-plugin-vue',
- configResolved(config) {
- const plugin = config.plugins.find(p => p.name === 'vite:vue')
- if (plugin && plugin.api && plugin.api.options) {
- plugin.api.options.devToolsEnabled = false
- }
- },
- },
- UnoCSS(),
- AutoImport({
- imports: ['vue', 'uni-app'],
- dts: 'src/types/auto-import.d.ts',
- dirs: ['src/hooks'], // 自动导入 hooks
- vueTemplate: true, // default false
- }),
- // Optimization 插件需要 page.json 文件,故应在 UniPages 插件之后执行
- Optimization({
- enable: {
- 'optimization': true,
- 'async-import': true,
- 'async-component': true,
- },
- dts: {
- base: 'src/types',
- },
- logger: false,
- }),
+ return defineConfig({
+ envDir: './env', // 自定义env目录
+ base: VITE_APP_PUBLIC_BASE,
+ plugins: [
+ UniPages({
+ exclude: ['**/components/**/**.*'],
+ // homePage 通过 vue 文件的 route-block 的type="home"来设定
+ // pages 目录为 src/pages,分包目录不能配置在pages目录下
+ subPackages: ['src/pages-sub'], // 是个数组,可以配置多个,但是不能为pages里面的目录
+ dts: 'src/types/uni-pages.d.ts',
+ }),
+ UniLayouts(),
+ UniPlatform(),
+ UniManifest(),
+ // UniXXX 需要在 Uni 之前引入
+ {
+ // 临时解决 dcloudio 官方的 @dcloudio/uni-mp-compiler 出现的编译 BUG
+ // 参考 github issue: https://github.com/dcloudio/uni-app/issues/4952
+ // 自定义插件禁用 vite:vue 插件的 devToolsEnabled,强制编译 vue 模板时 inline 为 true
+ name: 'fix-vite-plugin-vue',
+ configResolved(config) {
+ const plugin = config.plugins.find(p => p.name === 'vite:vue')
+ if (plugin && plugin.api && plugin.api.options) {
+ plugin.api.options.devToolsEnabled = false
+ }
+ },
+ },
+ UnoCSS(),
+ AutoImport({
+ imports: ['vue', 'uni-app'],
+ dts: 'src/types/auto-import.d.ts',
+ dirs: ['src/hooks'], // 自动导入 hooks
+ vueTemplate: true, // default false
+ }),
+ // Optimization 插件需要 page.json 文件,故应在 UniPages 插件之后执行
+ Optimization({
+ enable: {
+ 'optimization': true,
+ 'async-import': true,
+ 'async-component': true,
+ },
+ dts: {
+ base: 'src/types',
+ },
+ logger: false,
+ }),
- ViteRestart({
- // 通过这个插件,在修改vite.config.js文件则不需要重新运行也生效配置
- restart: ['vite.config.js'],
- }),
- // h5环境增加 BUILD_TIME 和 BUILD_BRANCH
- UNI_PLATFORM === 'h5' && {
- name: 'html-transform',
- transformIndexHtml(html) {
- return html.replace('%BUILD_TIME%', dayjs().format('YYYY-MM-DD HH:mm:ss'))
- },
- },
- // 打包分析插件,h5 + 生产环境才弹出
- 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({
- extensions: ['vue'],
- deep: true, // 是否递归扫描子目录,
- directoryAsNamespace: false, // 是否把目录名作为命名空间前缀,true 时组件名为 目录名+组件名,
- dts: 'src/types/components.d.ts', // 自动生成的组件类型声明文件路径(用于 TypeScript 支持)
- }),
- Uni(),
- ],
- define: {
- __UNI_PLATFORM__: JSON.stringify(UNI_PLATFORM),
- __VITE_APP_PROXY__: JSON.stringify(VITE_APP_PROXY),
- },
- css: {
- postcss: {
- plugins: [
- // autoprefixer({
- // // 指定目标浏览器
- // overrideBrowserslist: ['> 1%', 'last 2 versions'],
- // }),
- ],
- },
- },
+ ViteRestart({
+ // 通过这个插件,在修改vite.config.js文件则不需要重新运行也生效配置
+ restart: ['vite.config.js'],
+ }),
+ // h5环境增加 BUILD_TIME 和 BUILD_BRANCH
+ UNI_PLATFORM === 'h5' && {
+ name: 'html-transform',
+ transformIndexHtml(html) {
+ return html.replace('%BUILD_TIME%', dayjs().format('YYYY-MM-DD HH:mm:ss'))
+ },
+ },
+ // 打包分析插件,h5 + 生产环境才弹出
+ 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({
+ extensions: ['vue'],
+ deep: true, // 是否递归扫描子目录,
+ directoryAsNamespace: false, // 是否把目录名作为命名空间前缀,true 时组件名为 目录名+组件名,
+ dts: 'src/types/components.d.ts', // 自动生成的组件类型声明文件路径(用于 TypeScript 支持)
+ }),
+ Uni(),
+ ],
+ define: {
+ __UNI_PLATFORM__: JSON.stringify(UNI_PLATFORM),
+ __VITE_APP_PROXY__: JSON.stringify(VITE_APP_PROXY),
+ },
+ css: {
+ postcss: {
+ plugins: [
+ // autoprefixer({
+ // // 指定目标浏览器
+ // overrideBrowserslist: ['> 1%', 'last 2 versions'],
+ // }),
+ ],
+ },
+ },
- resolve: {
- alias: {
- '@': path.join(process.cwd(), './src'),
- '@img': path.join(process.cwd(), './src/static/images'),
- },
- },
- server: {
- host: '0.0.0.0',
- hmr: true,
- port: Number.parseInt(VITE_APP_PORT, 10),
- // 仅 H5 端生效,其他端不生效(其他端走build,不走devServer)
- proxy: JSON.parse(VITE_APP_PROXY)
- ? {
- [VITE_APP_PROXY_PREFIX]: {
- target: VITE_SERVER_BASEURL,
- changeOrigin: true,
- rewrite: path => path.replace(new RegExp(`^${VITE_APP_PROXY_PREFIX}`), ''),
- },
- }
- : undefined,
- },
- esbuild: {
- drop: VITE_DELETE_CONSOLE === 'true' ? ['console', 'debugger'] : ['debugger'],
- },
- build: {
- sourcemap: false,
- // 方便非h5端调试
- // sourcemap: VITE_SHOW_SOURCEMAP === 'true', // 默认是false
- target: 'es6',
- // 开发环境不用压缩
- minify: mode === 'development' ? false : 'esbuild',
+ resolve: {
+ alias: {
+ '@': path.join(process.cwd(), './src'),
+ '@img': path.join(process.cwd(), './src/static/images'),
+ },
+ },
+ server: {
+ host: '0.0.0.0',
+ hmr: true,
+ port: Number.parseInt(VITE_APP_PORT, 10),
+ // 仅 H5 端生效,其他端不生效(其他端走build,不走devServer)
+ proxy: JSON.parse(VITE_APP_PROXY)
+ ? {
+ [VITE_APP_PROXY_PREFIX]: {
+ target: VITE_SERVER_BASEURL,
+ changeOrigin: true,
+ rewrite: path => path.replace(new RegExp(`^${VITE_APP_PROXY_PREFIX}`), ''),
+ },
+ }
+ : undefined,
+ },
+ esbuild: {
+ drop: VITE_DELETE_CONSOLE === 'true' ? ['console', 'debugger'] : ['debugger'],
+ },
+ build: {
+ sourcemap: false,
+ // 方便非h5端调试
+ // sourcemap: VITE_SHOW_SOURCEMAP === 'true', // 默认是false
+ target: 'es6',
+ // 开发环境不用压缩
+ minify: mode === 'development' ? false : 'esbuild',
- },
- })
+ },
+ })
}