Compare commits

..

No commits in common. "main" and "base" have entirely different histories.
main ... base

16 changed files with 56 additions and 140 deletions

View File

@ -42,39 +42,3 @@ jobs:
git checkout base-sard-ui git checkout base-sard-ui
git merge main --no-ff -m "Auto merge main into base-sard-ui" git merge main --no-ff -m "Auto merge main into base-sard-ui"
git push origin base-sard-ui git push origin base-sard-ui
merge-to-base-uv-ui:
name: Merge main into base-uv-ui
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GH_TOKEN_AUTO_MERGE }}
- name: Merge main into base-uv-ui
run: |
git config user.name "GitHub Actions"
git config user.email "actions@github.com"
git checkout base-uv-ui
git merge main --no-ff -m "Auto merge main into base-uv-ui"
git push origin base-uv-ui
merge-to-base-uview-plus:
name: Merge main into base-uview-plus
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GH_TOKEN_AUTO_MERGE }}
- name: Merge main into base-uview-plus
run: |
git config user.name "GitHub Actions"
git config user.email "actions@github.com"
git checkout base-uview-plus
git merge main --no-ff -m "Auto merge main into base-uview-plus"
git push origin base-uview-plus

2
.gitignore vendored
View File

@ -27,7 +27,7 @@ dist
docs/.vitepress/dist docs/.vitepress/dist
docs/.vitepress/cache docs/.vitepress/cache
src/types types
# lock 文件还是不要了,我主要的版本写死就好了 # lock 文件还是不要了,我主要的版本写死就好了
# pnpm-lock.yaml # pnpm-lock.yaml

35
.vscode/settings.json vendored
View File

@ -41,7 +41,6 @@
"tabbar", "tabbar",
"Toutiao", "Toutiao",
"unibest", "unibest",
"uview",
"uvui", "uvui",
"Wechat", "Wechat",
"WechatMiniprogram", "WechatMiniprogram",
@ -53,29 +52,29 @@
"explorer.fileNesting.patterns": { "explorer.fileNesting.patterns": {
"README.md": "index.html,favicon.ico,robots.txt,CHANGELOG.md", "README.md": "index.html,favicon.ico,robots.txt,CHANGELOG.md",
"pages.config.ts": "manifest.config.ts,openapi-ts-request.config.ts", "pages.config.ts": "manifest.config.ts,openapi-ts-request.config.ts",
"package.json": "tsconfig.json,pnpm-lock.yaml,pnpm-workspace.yaml,LICENSE,.gitattributes,.gitignore,.gitpod.yml,CNAME,.npmrc,.browserslistrc", "package.json": "pnpm-lock.yaml,pnpm-workspace.yaml,LICENSE,.gitattributes,.gitignore,.gitpod.yml,CNAME,.npmrc,.browserslistrc",
"eslint.config.mjs": ".commitlintrc.*,.prettier*,.editorconfig,.commitlint.cjs,.eslint*" "eslint.config.mjs": "tsconfig.json,.commitlintrc.*,.prettier*,.editorconfig,.commitlint.cjs,.eslint*"
}, },
// // //
// "prettier.enable": true, "prettier.enable": true,
// "editor.formatOnSave": true, "editor.formatOnSave": true,
// // //
// "editor.codeActionsOnSave": { "editor.codeActionsOnSave": {
// "source.fixAll": "explicit", "source.fixAll": "explicit",
// "source.fixAll.eslint": "explicit", "source.fixAll.eslint": "explicit",
// "source.fixAll.stylelint": "explicit" "source.fixAll.stylelint": "explicit"
// }, },
// Disable the default formatter, use eslint instead // Disable the default formatter, use eslint instead
"prettier.enable": false, // "prettier.enable": false,
"editor.formatOnSave": false, // "editor.formatOnSave": false,
// Auto fix // Auto fix
"editor.codeActionsOnSave": { // "editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit", // "source.fixAll.eslint": "explicit",
"source.organizeImports": "never" // "source.organizeImports": "never"
}, // },
// Silent the stylistic rules in you IDE, but still auto fix them // Silent the stylistic rules in you IDE, but still auto fix them
"eslint.rules.customizations": [ "eslint.rules.customizations": [

View File

@ -27,12 +27,12 @@
" },", " },",
"}", "}",
"</route>\n", "</route>\n",
"<script lang=\"ts\" setup>",
"//$3",
"</script>\n",
"<template>", "<template>",
" <view class=\"\">$2</view>", " <view class=\"\">$2</view>",
"</template>\n", "</template>\n",
"<script lang=\"ts\" setup>",
"//$3",
"</script>\n",
"<style lang=\"scss\" scoped>", "<style lang=\"scss\" scoped>",
"//$4", "//$4",
"</style>\n", "</style>\n",
@ -41,28 +41,16 @@
"Print unibest style": { "Print unibest style": {
"scope": "vue", "scope": "vue",
"prefix": "st", "prefix": "st",
"body": [ "body": ["<style lang=\"scss\" scoped>", "//", "</style>\n"],
"<style lang=\"scss\" scoped>",
"//",
"</style>\n"
],
}, },
"Print unibest script": { "Print unibest script": {
"scope": "vue", "scope": "vue",
"prefix": "sc", "prefix": "sc",
"body": [ "body": ["<script lang=\"ts\" setup>", "//$3", "</script>\n"],
"<script lang=\"ts\" setup>",
"//$3",
"</script>\n"
],
}, },
"Print unibest template": { "Print unibest template": {
"scope": "vue", "scope": "vue",
"prefix": "te", "prefix": "te",
"body": [ "body": ["<template>", " <view class=\"\">$1</view>", "</template>\n"],
"<template>",
" <view class=\"\">$1</view>",
"</template>\n"
],
}, },
} }

View File

@ -1,7 +1,7 @@
{ {
"name": "unibest", "name": "unibest",
"type": "commonjs", "type": "commonjs",
"version": "3.1.0", "version": "3.0.0",
"description": "unibest - 最好的 uniapp 开发模板", "description": "unibest - 最好的 uniapp 开发模板",
"update-time": "2025-06-21", "update-time": "2025-06-21",
"author": { "author": {
@ -98,6 +98,7 @@
"js-cookie": "^3.0.5", "js-cookie": "^3.0.5",
"pinia": "2.0.36", "pinia": "2.0.36",
"pinia-plugin-persistedstate": "3.2.1", "pinia-plugin-persistedstate": "3.2.1",
"qs": "6.5.3",
"vue": "^3.4.21", "vue": "^3.4.21",
"wot-design-uni": "^1.9.1", "wot-design-uni": "^1.9.1",
"z-paging": "2.8.7" "z-paging": "2.8.7"

9
pnpm-lock.yaml generated
View File

@ -82,6 +82,9 @@ importers:
pinia-plugin-persistedstate: pinia-plugin-persistedstate:
specifier: 3.2.1 specifier: 3.2.1
version: 3.2.1(pinia@2.0.36(typescript@5.7.2)(vue@3.5.15(typescript@5.7.2))) version: 3.2.1(pinia@2.0.36(typescript@5.7.2)(vue@3.5.15(typescript@5.7.2)))
qs:
specifier: 6.5.3
version: 6.5.3
vue: vue:
specifier: ^3.4.21 specifier: ^3.4.21
version: 3.5.15(typescript@5.7.2) version: 3.5.15(typescript@5.7.2)
@ -5437,6 +5440,10 @@ packages:
resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==}
engines: {node: '>=0.6'} engines: {node: '>=0.6'}
qs@6.5.3:
resolution: {integrity: sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==}
engines: {node: '>=0.6'}
quansync@0.2.10: quansync@0.2.10:
resolution: {integrity: sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A==} resolution: {integrity: sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A==}
@ -13250,6 +13257,8 @@ snapshots:
dependencies: dependencies:
side-channel: 1.0.6 side-channel: 1.0.6
qs@6.5.3: {}
quansync@0.2.10: {} quansync@0.2.10: {}
querystringify@2.2.0: {} querystringify@2.2.0: {}

View File

@ -1,4 +1,4 @@
import type { ICaptcha, IUpdateInfo, IUpdatePassword, IUserInfoVo, IUserLogin } from './types/login' import type { ICaptcha, IUpdateInfo, IUpdatePassword, IUserInfoVo, IUserLogin } from './login.typings'
import { http } from '@/utils/http' import { http } from '@/utils/http'
/** /**

3
src/env.d.ts vendored
View File

@ -29,6 +29,3 @@ interface ImportMetaEnv {
interface ImportMeta { interface ImportMeta {
readonly env: ImportMetaEnv readonly env: ImportMetaEnv
} }
declare const __VITE_APP_PROXY__: 'true' | 'false'
declare const __UNI_PLATFORM__: 'app' | 'h5' | 'mp-alipay' | 'mp-baidu' | 'mp-kuaishou' | 'mp-lark' | 'mp-qq' | 'mp-tiktok' | 'mp-weixin' | 'mp-xiaochengxu'

View File

@ -1,7 +1,7 @@
import qs from 'qs'
import { useUserStore } from '@/store' import { useUserStore } from '@/store'
import { getEnvBaseUrl } from '@/utils' import { getEnvBaseUrl } from '@/utils'
import { platform } from '@/utils/platform' import { platform } from '@/utils/platform'
import { stringifyQuery } from '@/utils/queryString'
export type CustomRequestOptions = UniApp.RequestOptions & { export type CustomRequestOptions = UniApp.RequestOptions & {
query?: Record<string, any> query?: Record<string, any>
@ -18,7 +18,7 @@ const httpInterceptor = {
invoke(options: CustomRequestOptions) { invoke(options: CustomRequestOptions) {
// 接口请求支持通过 query 参数配置 queryString // 接口请求支持通过 query 参数配置 queryString
if (options.query) { if (options.query) {
const queryStr = stringifyQuery(options.query) const queryStr = qs.stringify(options.query)
if (options.url.includes('?')) { if (options.url.includes('?')) {
options.url += `&${queryStr}` options.url += `&${queryStr}`
} }

View File

@ -1,16 +1,16 @@
# tabbar 说明 # tabbar 说明
`tabbar` 分为 `4 ` 情况: tabbar 分为4种情况
- `完全原生 tabbar`,使用 `switchTab` 切换 tabbar`tabbar` 页面有缓存。 - 完全原生tabbar使用 switchTab 切换 tabbartabbar页面有缓存。
- 优势原生自带的tabbar最先渲染有缓存。 - 优势原生自带的tabbar最先渲染有缓存。
- 劣势只能使用2组图片来切换选中和非选中状态修改颜色只能重新换图片或者用iconfont - 劣势只能使用2组图片来切换选中和非选中状态修改颜色只能重新换图片或者用iconfont
- `半自定义 tabbar`,使用 `switchTab` 切换 tabbar`tabbar` 页面有缓存。使用了第三方 UI 库的 `tabbar` 组件,并隐藏了原生 `tabbar` 的显示。 - 半自定义tabbar使用 switchTab 切换 tabbartabbar页面有缓存。使用了第三方UI库的 tabbar 组件,并隐藏了原生 tabbar 的显示。
- 优势:可以随意配置自己想要的 `svg icon`,切换字体颜色方便。有缓存。可以实现各种花里胡哨的动效等。 - 优势:可以随意配置自己想要的 svg icon切换字体颜色方便。有缓存。可以实现各种花里胡哨的动效等。
- 劣势首次点击tababr会闪烁。 - 劣势首次点击tababr会闪烁。
- `全自定义 tabbar`,使用 `navigateTo` 切换 `tabbar``tabbar` 页面无缓存。使用了第三方 UI 库的 `tabbar` 组件。 - 全自定义tabbar使用 navigateTo 切换tabbartabbar页面无缓存。使用了第三方UI库的 tabbar 组件。
- 优势:可以随意配置自己想要的 svg icon切换字体颜色方便。可以实现各种花里胡哨的动效等。 - 优势:可以随意配置自己想要的 svg icon切换字体颜色方便。可以实现各种花里胡哨的动效等。
- 劣势:首次点击 `tababr` 会闪烁,无缓存。 - 劣势首次点击tababr会闪烁无缓存。
- ` tabbar`,只有一个页面入口,底部无 `tabbar` 显示;常用语临时活动页。 - 无tabbar只有一个页面入口底部无tabbar显示常用语临时活动页。
> 注意:花里胡哨的效果需要自己实现,本模版不提供。 > 注意:花里胡哨的效果需要自己实现,本模版不提供。

View File

@ -1,9 +1,9 @@
/** /**
* tabbar tabbar.md * tabbar tabbar.md
* 0: 'NATIVE_TABBAR' `完全原生 tabbar` * 0: 'NATIVE_TABBAR'
* 2: 'FULL_CUSTOM_TABBAR' `全自定义 tabbar` * 2: 'FULL_CUSTOM_TABBAR'
* 1: 'HALF_CUSTOM_TABBAR' `半自定义 tabbar` * 1: 'HALF_CUSTOM_TABBAR'
* 3: 'NO_TABBAR' `无 tabbar` * 3: 'NO_TABBAR'
* *
* pages.json * pages.json
*/ */

View File

@ -30,7 +30,7 @@
"pagePath": "pages/index/index", "pagePath": "pages/index/index",
"text": "首页", "text": "首页",
"icon": "home", "icon": "home",
"iconType": "uiLib" "iconType": "wot"
}, },
{ {
"iconPath": "static/tabbar/example.png", "iconPath": "static/tabbar/example.png",

View File

@ -53,7 +53,7 @@ console.log('index')
<template> <template>
<view class="bg-white px-4 pt-2" :style="{ marginTop: `${safeAreaInsets?.top}px` }"> <view class="bg-white px-4 pt-2" :style="{ marginTop: `${safeAreaInsets?.top}px` }">
<view class="mt-10"> <view class="mt-12">
<image src="/static/logo.svg" alt="" class="mx-auto block h-28 w-28" /> <image src="/static/logo.svg" alt="" class="mx-auto block h-28 w-28" />
</view> </view>
<view class="mt-4 text-center text-4xl text-[#d14328]"> <view class="mt-4 text-center text-4xl text-[#d14328]">
@ -66,19 +66,6 @@ console.log('index')
<view class="m-auto mb-2 max-w-100 text-justify indent text-4"> <view class="m-auto mb-2 max-w-100 text-justify indent text-4">
{{ description }} {{ description }}
</view> </view>
<view class="mt-4 text-center">
作者
<text class="text-green-500">
菲鸽
</text>
</view>
<view class="mt-4 text-center">
官网地址
<text class="text-green-500">
https://unibest.tech
</text>
</view>
<view class="mt-6 h-1px bg-#eee" />
<view class="mt-8 text-center"> <view class="mt-8 text-center">
当前平台是 当前平台是
<text class="text-green-500"> <text class="text-green-500">

View File

@ -1,4 +1,4 @@
import type { IUserInfoVo } from '@/api/types/login' import type { IUserInfoVo } from '@/api/login.typings'
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { ref } from 'vue' import { ref } from 'vue'
import { import {

View File

@ -1,29 +0,0 @@
/**
* URL查询字符串 qs
*
* @param obj
* @returns
*/
export function stringifyQuery(obj: Record<string, any>): string {
if (!obj || typeof obj !== 'object' || Array.isArray(obj))
return ''
return Object.entries(obj)
.filter(([_, value]) => value !== undefined && value !== null)
.map(([key, value]) => {
// 对键进行编码
const encodedKey = encodeURIComponent(key)
// 处理数组类型
if (Array.isArray(value)) {
return value
.filter(item => item !== undefined && item !== null)
.map(item => `${encodedKey}=${encodeURIComponent(item)}`)
.join('&')
}
// 处理基本类型
return `${encodedKey}=${encodeURIComponent(value)}`
})
.join('&')
}