diff --git a/.cursor/rules/development-workflow.mdc b/.cursor/rules/development-workflow.mdc index 7a8c901..4da3f43 100644 --- a/.cursor/rules/development-workflow.mdc +++ b/.cursor/rules/development-workflow.mdc @@ -5,6 +5,7 @@ 2. 开发环境: - H5: `pnpm dev` 或 `pnpm dev:h5` - 微信小程序: `pnpm dev:mp` + - 支付宝小程序: `pnpm dev:mp-alipay` - APP: `pnpm dev:app` ## 代码规范 @@ -15,7 +16,8 @@ ## 构建和部署 - H5 构建:`pnpm build:h5` -- 小程序构建:`pnpm build:mp` +- 微信小程序构建:`pnpm build:mp` +- 支付宝小程序构建:`pnpm build:mp-alipay` - APP 构建:`pnpm build:app` - 类型检查:`pnpm type-check` diff --git a/.cursor/rules/project-overview.mdc b/.cursor/rules/project-overview.mdc index 335b480..f0d613e 100644 --- a/.cursor/rules/project-overview.mdc +++ b/.cursor/rules/project-overview.mdc @@ -8,7 +8,7 @@ alwaysApply: true ## 项目特点 - 支持 H5、小程序、APP 多平台开发 - 使用最新的前端技术栈 -- 内置约定式路由、layout布局、请求封装等功能 +- 内置约定式路由、layout布局、请求封装、登录拦截、自定义tabbar等功能 - 无需依赖 HBuilderX,支持命令行开发 ## 核心配置文件 @@ -26,9 +26,11 @@ alwaysApply: true - `src/http/` - HTTP 请求封装 - `src/store/` - 状态管理 - `src/tabbar/` - 底部导航栏 +- `src/App.ku.vue` - 全局根组件(类似 App.vue 里面的 template作用) ## 开发命令 - `pnpm dev` - 开发 H5 版本 - `pnpm dev:mp` - 开发微信小程序 +- `pnpm dev:mp-alipay` - 开发支付宝小程序(含钉钉) - `pnpm dev:app` - 开发 APP 版本 - `pnpm build` - 构建生产版本 diff --git a/.cursor/rules/uni-app-patterns.mdc b/.cursor/rules/uni-app-patterns.mdc index 956566d..143b0b6 100644 --- a/.cursor/rules/uni-app-patterns.mdc +++ b/.cursor/rules/uni-app-patterns.mdc @@ -3,12 +3,12 @@ ## 页面开发 - 页面文件放在 [src/pages/](mdc:src/pages/) 目录下 - 使用约定式路由,文件名即路由路径 -- 页面配置在仅需要在 `route-block` 中配置标题等内容即可,会自动生成到 `pages.json` 中 +- 页面配置在仅需要在 宏`definePage` 中配置标题等内容即可,会自动生成到 `pages.json` 中 ## 组件开发 -- 组件文件放在 [src/components/](mdc:src/components/) 目录下 +- 组件文件放在 [src/components/](mdc:src/components/) 或者 [src/pages/xx/components/](mdc:src/pages/xx/components/) 目录下 - 使用 uni-app 内置组件和第三方组件库 -- 支持 wot-design-uni\uv-ui\uview-plus 等多种第三方组件库 和 z-paging 组件 +- 支持 wot-ui\uview-pro\uv-ui\sard-ui\uview-plus 等多种第三方组件库 和 z-paging 组件 - 自定义组件遵循 uni-app 组件规范 ## 平台适配 diff --git a/.cursor/rules/vue-typescript-patterns.mdc b/.cursor/rules/vue-typescript-patterns.mdc index f726299..d81cc8f 100644 --- a/.cursor/rules/vue-typescript-patterns.mdc +++ b/.cursor/rules/vue-typescript-patterns.mdc @@ -4,10 +4,11 @@ - 使用 Composition API 和 ` diff --git a/src/App.vue b/src/App.vue index 9c47bc2..0ea6924 100644 --- a/src/App.vue +++ b/src/App.vue @@ -3,10 +3,10 @@ import { onHide, onLaunch, onShow } from '@dcloudio/uni-app' import { navigateToInterceptor } from '@/router/interceptor' onLaunch((options) => { - console.log('App Launch', options) + console.log('App.vue onLaunch', options) }) onShow((options) => { - console.log('App Show', options) + console.log('App.vue onShow', options) // 处理直接进入页面路由的情况:如h5直接输入路由、微信小程序分享后进入等 // https://github.com/unibest-tech/unibest/issues/192 if (options?.path) { @@ -22,16 +22,5 @@ onHide(() => { diff --git a/src/hooks/useScroll.md b/src/hooks/useScroll.md new file mode 100644 index 0000000..bb2eace --- /dev/null +++ b/src/hooks/useScroll.md @@ -0,0 +1,116 @@ +# 上拉刷新和下拉加载更多 + +在 unibest 框架中,我们通过组合 `useScroll` Hook 可结合 `scroll-view` 组件来轻松实现上拉刷新和下拉加载更多的功能。 +场景一 页面滚动 + +``` +definePage({ + style: { + navigationBarTitleText: '上拉刷新和下拉加载更多', + enablePullDownRefresh: true, + onReachBottomDistance: 100, + }, +}) +``` + +场景二 局部滚动 结合 `scroll-view` + +## 关键文件 + +- `src/hooks/useScroll.ts`: 提供了核心的滚动逻辑处理 Hook。 +- `src/pages-sub/demo/scroll.vue`: 一个具体的实现示例页面。 + +## `useScroll` Hook + +`useScroll` 是一个 Vue Composition API Hook,它封装了处理下拉刷新和上拉加载的通用逻辑。 + +### 主要功能 + +- **管理加载状态**: 自动处理 `loading`(加载中)、`finished`(已加载全部)和 `error`(加载失败)等状态。 +- **分页逻辑**: 内部维护分页参数(页码 `page` 和每页数量 `pageSize`)。 +- **事件处理**: 提供 `onScrollToLower`(滚动到底部)、`onRefresherRefresh`(下拉刷新)等方法,用于在视图层触发。 +- **数据合并**: 自动将新加载的数据追加到现有列表 `list` 中。 + +### 使用方法 + +```typescript +import { useScroll } from '@/hooks/useScroll' +import { getList } from '@/service/list' // 你的数据请求API + +const { + list, // 响应式的数据列表 + loading, // 是否加载中 + finished, // 是否已全部加载 + error, // 是否加载失败 + onScrollToLower, // 滚动到底部时触发的事件 + onRefresherRefresh, // 下拉刷新时触发的事件 +} = useScroll(getList) // 将获取数据的API函数传入 +``` + +## `scroll-view` 组件 + +`scroll-view` 是 uni-app 提供的可滚动视图区域组件,它提供了一系列属性来支持下拉刷新和上拉加载。 + +### 关键属性 + +- `scroll-y`: 允许纵向滚动。 +- `refresher-enabled`: 启用下拉刷新。 +- `refresher-triggered`: 控制下拉刷新动画的显示与隐藏,通过 `loading` 状态绑定。 +- `@scrolltolower`: 滚动到底部时触发的事件,绑定 `onScrollToLower` 方法。 +- `@refresherrefresh`: 触发下拉刷新时触发的事件,绑定 `onRefresherRefresh` 方法。 + +## 示例代码 + +以下是 `src/pages-sub/demo/scroll.vue` 中的核心代码,展示了如何将 `useScroll` 和 `scroll-view` 结合使用。 + +```vue + + + + + +``` + +## 实现步骤总结 + +1. **创建API**: 确保你有一个返回分页数据的API请求函数(例如 `getList`),它应该接受页码和页面大小作为参数。 +2. **调用 `useScroll`**: 在你的页面脚本中,导入并调用 `useScroll` Hook,将你的API函数作为参数传入。 +3. **模板绑定**: + - 使用 `scroll-view` 组件作为滚动容器。 + - 将其 `refresher-triggered` 属性绑定到 `useScroll` 返回的 `loading` 状态。 + - 将其 `@scrolltolower` 事件绑定到 `onScrollToLower` 方法。 + - 将其 `@refresherrefresh` 事件绑定到 `onRefresherRefresh` 方法。 +4. **渲染列表**: 使用 `v-for` 指令渲染 `useScroll` 返回的 `list` 数组。 +5. **添加加载提示**: 根据 `loading`, `finished`, `error` 状态,在列表底部显示不同的提示信息,提升用户体验。 + +通过以上步骤,你就可以在项目中快速集成一个功能完善、体验良好的上拉刷新和下拉加载列表。 \ No newline at end of file diff --git a/src/http/alova.ts b/src/http/alova.ts index 133f6af..b7b9ff6 100644 --- a/src/http/alova.ts +++ b/src/http/alova.ts @@ -4,7 +4,7 @@ import AdapterUniapp from '@alova/adapter-uniapp' import { createAlova } from 'alova' import { createServerTokenAuthentication } from 'alova/client' import VueHook from 'alova/vue' -import { LOGIN_PAGE } from '@/router/config' +import { toLoginPage } from '@/utils/toLoginPage' import { ContentTypeEnum, ResultEnum, ShowMessage } from './tools/enum' // 配置动态Tag @@ -31,7 +31,7 @@ const { onAuthRequired, onResponseRefreshToken } = createServerTokenAuthenticati } catch (error) { // 切换到登录页 - await uni.reLaunch({ url: LOGIN_PAGE }) + toLoginPage({ mode: 'reLaunch' }) throw error } }, diff --git a/src/http/http.ts b/src/http/http.ts index eafe8e0..88f8508 100644 --- a/src/http/http.ts +++ b/src/http/http.ts @@ -1,9 +1,9 @@ import type { IDoubleTokenRes } from '@/api/types/login' import type { CustomRequestOptions, IResponse } from '@/http/types' import { nextTick } from 'vue' -import { LOGIN_PAGE } from '@/router/config' import { useTokenStore } from '@/store/token' import { isDoubleTokenMode } from '@/utils' +import { toLoginPage } from '@/utils/toLoginPage' import { ResultEnum } from './tools/enum' // 刷新 token 状态管理 @@ -32,7 +32,7 @@ export function http(options: CustomRequestOptions) { if (!isDoubleTokenMode) { // 未启用双token策略,清理用户信息,跳转到登录页 tokenStore.logout() - uni.navigateTo({ url: LOGIN_PAGE }) + toLoginPage() return reject(res) } @@ -80,7 +80,7 @@ export function http(options: CustomRequestOptions) { await tokenStore.logout() // 跳转到登录页 setTimeout(() => { - uni.navigateTo({ url: LOGIN_PAGE }) + toLoginPage() }, 2000) } finally { @@ -96,9 +96,12 @@ export function http(options: CustomRequestOptions) { if (res.statusCode >= 200 && res.statusCode < 300) { // 处理业务逻辑错误 if (code !== ResultEnum.Success0 && code !== ResultEnum.Success200) { - throw new Error(`请求错误[${code}]:${responseData.message || responseData.msg}`) + uni.showToast({ + icon: 'none', + title: responseData.msg || responseData.message || '请求错误', + }) } - return resolve(responseData.data as T) + return resolve(responseData.data) } // 处理其他错误 diff --git a/src/http/types.ts b/src/http/types.ts index 42ac8e9..8187822 100644 --- a/src/http/types.ts +++ b/src/http/types.ts @@ -7,6 +7,9 @@ export type CustomRequestOptions = UniApp.RequestOptions & { hideErrorToast?: boolean } & IUniUploadFileOptions // 添加uni.uploadFile参数类型 +/** 主要提供给 openapi-ts-request 生成的代码使用 */ +export type CustomRequestOptions_ = Omit + export interface HttpRequestResult { promise: Promise requestTask: UniApp.RequestTask diff --git a/src/http/vue-query.ts b/src/http/vue-query.ts index 31d1eb3..69ca80d 100644 --- a/src/http/vue-query.ts +++ b/src/http/vue-query.ts @@ -4,7 +4,7 @@ import { http } from './http' /* * openapi-ts-request 工具的 request 跨客户端适配方法 */ -export default function request( +export default function request( url: string, options: Omit & { params?: Record @@ -26,5 +26,5 @@ export default function request( delete requestOptions.headers } - return http(requestOptions) + return http(requestOptions) } diff --git a/src/layouts/default.vue b/src/layouts/default.vue index 88a55d4..ba4672f 100644 --- a/src/layouts/default.vue +++ b/src/layouts/default.vue @@ -1,10 +1,3 @@ - - diff --git a/src/pages-fg/404/README.md b/src/pages-fg/404/README.md deleted file mode 100644 index ecc8aa4..0000000 --- a/src/pages-fg/404/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# 404 页面 - -`404页面` 只有在路由不存在时才会显示,如果您不需要可以删除该页面。但是建议保留。 \ No newline at end of file diff --git a/src/pages-fg/404/index.vue b/src/pages-fg/404/index.vue deleted file mode 100644 index 533e259..0000000 --- a/src/pages-fg/404/index.vue +++ /dev/null @@ -1,30 +0,0 @@ - - - - - diff --git a/src/pages-fg/REAME.md b/src/pages-fg/REAME.md deleted file mode 100644 index 55479de..0000000 --- a/src/pages-fg/REAME.md +++ /dev/null @@ -1,3 +0,0 @@ -# pages-fg 说明 - -为了尽量减少主包的大小,一些无关紧要但经常需要的页面(如登录页、注册页、404页等)放在了 `pages-fg` 目录下。 diff --git a/src/pages-fg/login/README.md b/src/pages-fg/login/README.md deleted file mode 100644 index c851a76..0000000 --- a/src/pages-fg/login/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# 登录页 -需要输入账号、密码/验证码的登录页。 - -## 适用性 - -本页面主要用于 `h5` 和 `APP`。 - -小程序通常有平台的登录方式 `uni.login` 通常用不到登录页,所以不适用于 `小程序`。(即默认情况下,小程序环境是不会走登录拦截逻辑的。) - -但是如果您的小程序也需要现实的 `登录页` 那也是可以使用的。 - -在 `src/router/config.ts` 中有一个变量 `LOGIN_PAGE_ENABLE_IN_MP` 来控制是否在小程序中使用 `H5的登录页`。 - -更多信息请看 `src/router` 文件夹的内容。 - -## 登录跳转 - -目前登录的跳转逻辑主要在 `src/router/interceptor.ts` 和 `src/pages/login/login.vue` 里面,默认会在登录后自动重定向到来源/配置的页面。 - -如果与您的业务不符,您可以自行修改。 diff --git a/src/pages-fg/login/login.vue b/src/pages-fg/login/login.vue deleted file mode 100644 index 0fa5e95..0000000 --- a/src/pages-fg/login/login.vue +++ /dev/null @@ -1,87 +0,0 @@ - - - - - diff --git a/src/pages-fg/login/register.vue b/src/pages-fg/login/register.vue deleted file mode 100644 index e9809f0..0000000 --- a/src/pages-fg/login/register.vue +++ /dev/null @@ -1,34 +0,0 @@ - - - - - diff --git a/src/pages-sub/about/about.vue b/src/pages-sub/about/about.vue deleted file mode 100644 index 005200d..0000000 --- a/src/pages-sub/about/about.vue +++ /dev/null @@ -1,135 +0,0 @@ - - - diff --git a/src/pages-sub/about/alova.vue b/src/pages-sub/about/alova.vue deleted file mode 100644 index 4b0c43f..0000000 --- a/src/pages-sub/about/alova.vue +++ /dev/null @@ -1,53 +0,0 @@ - - - - - diff --git a/src/pages-sub/about/components/Upload.vue b/src/pages-sub/about/components/Upload.vue deleted file mode 100644 index 09547f5..0000000 --- a/src/pages-sub/about/components/Upload.vue +++ /dev/null @@ -1,25 +0,0 @@ - - - diff --git a/src/pages-sub/about/components/VBindCss.vue b/src/pages-sub/about/components/VBindCss.vue deleted file mode 100644 index bc5a048..0000000 --- a/src/pages-sub/about/components/VBindCss.vue +++ /dev/null @@ -1,28 +0,0 @@ - - - - - diff --git a/src/pages-sub/about/components/request-openapi.vue b/src/pages-sub/about/components/request-openapi.vue deleted file mode 100644 index 64fb095..0000000 --- a/src/pages-sub/about/components/request-openapi.vue +++ /dev/null @@ -1,64 +0,0 @@ - - - diff --git a/src/pages-sub/about/components/request.vue b/src/pages-sub/about/components/request.vue deleted file mode 100644 index 73db16b..0000000 --- a/src/pages-sub/about/components/request.vue +++ /dev/null @@ -1,75 +0,0 @@ - - - diff --git a/src/pages-sub/demo/components/request.vue b/src/pages-sub/demo/components/request.vue deleted file mode 100644 index 7d7bff1..0000000 --- a/src/pages-sub/demo/components/request.vue +++ /dev/null @@ -1,48 +0,0 @@ - - - diff --git a/src/pages-sub/demo/index.vue b/src/pages-sub/demo/index.vue deleted file mode 100644 index 3d51c9a..0000000 --- a/src/pages-sub/demo/index.vue +++ /dev/null @@ -1,40 +0,0 @@ - - - - - diff --git a/src/pages-sub/demo/scroll.vue b/src/pages-sub/demo/scroll.vue deleted file mode 100644 index 7961a30..0000000 --- a/src/pages-sub/demo/scroll.vue +++ /dev/null @@ -1,72 +0,0 @@ - - - diff --git a/src/pages/index/index.vue b/src/pages/index/index.vue index 687d096..27b81b8 100644 --- a/src/pages/index/index.vue +++ b/src/pages/index/index.vue @@ -1,7 +1,4 @@ diff --git a/src/pages/me/me.vue b/src/pages/me/me.vue index c43a47c..5df9e2e 100644 --- a/src/pages/me/me.vue +++ b/src/pages/me/me.vue @@ -1,214 +1,13 @@ - - diff --git a/src/router/config.ts b/src/router/config.ts deleted file mode 100644 index 2d0e52d..0000000 --- a/src/router/config.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { getAllPages } from '@/utils' - -export const LOGIN_STRATEGY_MAP = { - DEFAULT_NO_NEED_LOGIN: 0, // 黑名单策略,默认可以进入APP - DEFAULT_NEED_LOGIN: 1, // 白名单策略,默认不可以进入APP,需要强制登录 -} -// TODO: 1/3 登录策略,默认使用`无需登录策略`,即默认不需要登录就可以访问 -export const LOGIN_STRATEGY = LOGIN_STRATEGY_MAP.DEFAULT_NO_NEED_LOGIN -export const isNeedLoginMode = LOGIN_STRATEGY === LOGIN_STRATEGY_MAP.DEFAULT_NEED_LOGIN - -export const LOGIN_PAGE = '/pages-fg/login/login' -export const REGISTER_PAGE = '/pages-fg/login/register' -export const NOT_FOUND_PAGE = '/pages-fg/404/index' - -export const LOGIN_PAGE_LIST = [LOGIN_PAGE, REGISTER_PAGE] - -// 在 definePage 里面配置了 excludeLoginPath 的页面,功能与 EXCLUDE_LOGIN_PATH_LIST 相同 -export const excludeLoginPathList = getAllPages('excludeLoginPath').map(page => page.path) - -// 排除在外的列表,白名单策略指白名单列表,黑名单策略指黑名单列表 -// TODO: 2/3 在 definePage 配置 excludeLoginPath,或者在下面配置 EXCLUDE_LOGIN_PATH_LIST -export const EXCLUDE_LOGIN_PATH_LIST = [ - '/pages/xxx/index', // 示例值 - '/pages-sub/xxx/index', // 示例值 - ...excludeLoginPathList, // 都是以 / 开头的 path -] - -// 在小程序里面是否使用H5的登录页,默认为 false -// 如果为 true 则复用 h5 的登录逻辑 -// TODO: 3/3 确定自己的登录页是否需要在小程序里面使用 -export const LOGIN_PAGE_ENABLE_IN_MP = false diff --git a/src/router/interceptor.ts b/src/router/interceptor.ts index 714fea4..b4092d5 100644 --- a/src/router/interceptor.ts +++ b/src/router/interceptor.ts @@ -1,23 +1,12 @@ -import { isMp } from '@uni-helper/uni-env' /** * by 菲鸽 on 2025-08-19 * 路由拦截,通常也是登录拦截 * 黑、白名单的配置,请看 config.ts 文件, EXCLUDE_LOGIN_PATH_LIST */ -import { useTokenStore } from '@/store/token' -import { isPageTabbar, tabbarStore } from '@/tabbar/store' -import { getAllPages, getLastPage, HOME_PAGE, parseUrlToObj } from '@/utils/index' -import { EXCLUDE_LOGIN_PATH_LIST, isNeedLoginMode, LOGIN_PAGE, LOGIN_PAGE_ENABLE_IN_MP, NOT_FOUND_PAGE } from './config' +import { tabbarStore } from '@/tabbar/store' +import { getAllPages, getLastPage, parseUrlToObj } from '@/utils/index' export const FG_LOG_ENABLE = false -export function judgeIsExcludePath(path: string) { - const isDev = import.meta.env.DEV - if (!isDev) { - return EXCLUDE_LOGIN_PATH_LIST.includes(path) - } - const allExcludeLoginPages = getAllPages('excludeLoginPath') // dev 环境下,需要每次都重新获取,否则新配置就不会生效 - return EXCLUDE_LOGIN_PATH_LIST.includes(path) || (isDev && allExcludeLoginPages.some(page => page.path === path)) -} export const navigateToInterceptor = { // 注意,这里的url是 '/' 开头的,如 '/pages/index/index',跟 'pages.json' 里面的 path 不同 @@ -44,76 +33,19 @@ export const navigateToInterceptor = { } // 处理路由不存在的情况 - if (getAllPages().every(page => page.path !== path) && path !== '/') { + if (path !== '/' && !getAllPages().some(page => page.path !== path)) { console.warn('路由不存在:', path) - uni.navigateTo({ url: NOT_FOUND_PAGE }) return false // 明确表示阻止原路由继续执行 } + // 插件页面 + if (url.startsWith('plugin://')) { + FG_LOG_ENABLE && console.log('路由拦截器 4: plugin:// 路径 ==>', url) + path = url + } + // 处理直接进入路由非首页时,tabbarIndex 不正确的问题 tabbarStore.setAutoCurIdx(path) - - // 小程序里面使用平台自带的登录,则不走下面的逻辑 - if (isMp && !LOGIN_PAGE_ENABLE_IN_MP) { - return true // 明确表示允许路由继续执行 - } - - const tokenStore = useTokenStore() - FG_LOG_ENABLE && console.log('tokenStore.hasLogin:', tokenStore.hasLogin) - - // 不管黑白名单,登录了就直接去吧(但是当前不能是登录页) - if (tokenStore.hasLogin) { - if (path !== LOGIN_PAGE) { - return true // 明确表示允许路由继续执行 - } - else { - console.log('已经登录,但是还在登录页', myQuery.redirect) - const url = myQuery.redirect || HOME_PAGE - if (isPageTabbar(url)) { - uni.switchTab({ url }) - } - else { - uni.navigateTo({ url }) - } - return false // 明确表示阻止原路由继续执行 - } - } - let fullPath = path - - if (Object.keys(myQuery).length) { - fullPath += `?${Object.keys(myQuery).map(key => `${key}=${myQuery[key]}`).join('&')}` - } - const redirectUrl = `${LOGIN_PAGE}?redirect=${encodeURIComponent(fullPath)}` - - // #region 1/2 默认需要登录的情况(白名单策略) --------------------------- - if (isNeedLoginMode) { - // 需要登录里面的 EXCLUDE_LOGIN_PATH_LIST 表示白名单,可以直接通过 - if (judgeIsExcludePath(path)) { - return true // 明确表示允许路由继续执行 - } - // 否则需要重定向到登录页 - else { - if (path === LOGIN_PAGE) { - return true // 明确表示允许路由继续执行 - } - FG_LOG_ENABLE && console.log('1 isNeedLogin(白名单策略) redirectUrl:', redirectUrl) - uni.navigateTo({ url: redirectUrl }) - return false // 明确表示阻止原路由继续执行 - } - } - // #endregion 1/2 默认需要登录的情况(白名单策略) --------------------------- - - // #region 2/2 默认不需要登录的情况(黑名单策略) --------------------------- - else { - // 不需要登录里面的 EXCLUDE_LOGIN_PATH_LIST 表示黑名单,需要重定向到登录页 - if (judgeIsExcludePath(path)) { - FG_LOG_ENABLE && console.log('2 isNeedLogin(黑名单策略) redirectUrl:', redirectUrl) - uni.navigateTo({ url: redirectUrl }) - return false // 修改为false,阻止原路由继续执行 - } - return true // 明确表示允许路由继续执行 - } - // #endregion 2/2 默认不需要登录的情况(黑名单策略) --------------------------- }, } diff --git a/src/service/info.ts b/src/service/info.ts index b3f8e6b..fe09da5 100644 --- a/src/service/info.ts +++ b/src/service/info.ts @@ -1,17 +1,13 @@ /* eslint-disable */ // @ts-ignore import request from '@/http/vue-query'; -import { CustomRequestOptions } from '@/http/types'; +import { CustomRequestOptions_ } from '@/http/types'; import * as API from './types'; /** 用户信息 GET /user/info */ -export async function infoUsingGet({ - options, -}: { - options?: CustomRequestOptions; -}) { - return request('/user/info', { +export function infoUsingGet({ options }: { options?: CustomRequestOptions_ }) { + return request('/user/info', { method: 'GET', ...(options || {}), }); diff --git a/src/service/listAll.ts b/src/service/listAll.ts index 92ba293..bc1c683 100644 --- a/src/service/listAll.ts +++ b/src/service/listAll.ts @@ -1,18 +1,17 @@ /* eslint-disable */ // @ts-ignore import request from '@/http/vue-query'; -import { CustomRequestOptions } from '@/http/types'; +import { CustomRequestOptions_ } from '@/http/types'; import * as API from './types'; -const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)); /** 用户列表 GET /user/listAll */ -export async function listAllUsingGet({ +export function listAllUsingGet({ options, }: { - options?: CustomRequestOptions; + options?: CustomRequestOptions_; }) { - return request('/user/listAll', { + return request('/user/listAll', { method: 'GET', ...(options || {}), }); diff --git a/src/static/my-icons/copyright.svg b/src/static/my-icons/copyright.svg new file mode 100644 index 0000000..8e69a8c --- /dev/null +++ b/src/static/my-icons/copyright.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/store/index.ts b/src/store/index.ts index d5e3770..fe2ead1 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -1,4 +1,4 @@ -import { createPinia } from 'pinia' +import { createPinia, setActivePinia } from 'pinia' import { createPersistedState } from 'pinia-plugin-persistedstate' // 数据持久化 const store = createPinia() @@ -10,10 +10,11 @@ store.use( }, }), ) +// 立即激活 Pinia 实例, 这样即使在 app.use(store)之前调用 store 也能正常工作 (解决APP端白屏问题) +setActivePinia(store) export default store // 模块统一导出 -export * from './theme' export * from './token' export * from './user' diff --git a/src/store/theme.ts b/src/store/theme.ts deleted file mode 100644 index c3f1c55..0000000 --- a/src/store/theme.ts +++ /dev/null @@ -1,42 +0,0 @@ -import type { ConfigProviderThemeVars } from 'wot-design-uni' - -import { defineStore } from 'pinia' - -export const useThemeStore = defineStore( - 'theme-store', - () => { - /** 主题 */ - const theme = ref<'light' | 'dark'>('light') - - /** 主题变量 */ - const themeVars = ref({ - // colorTheme: 'red', - // buttonPrimaryBgColor: '#07c160', - // buttonPrimaryColor: '#07c160', - }) - - /** 设置主题变量 */ - const setThemeVars = (partialVars: Partial) => { - themeVars.value = { ...themeVars.value, ...partialVars } - } - - /** 切换主题 */ - const toggleTheme = () => { - theme.value = theme.value === 'light' ? 'dark' : 'light' - } - - return { - /** 设置主题变量 */ - setThemeVars, - /** 切换主题 */ - toggleTheme, - /** 主题变量 */ - themeVars, - /** 主题 */ - theme, - } - }, - { - persist: true, - }, -) diff --git a/src/tabbar/README.md b/src/tabbar/README.md index c2b89eb..07d161d 100644 --- a/src/tabbar/README.md +++ b/src/tabbar/README.md @@ -5,17 +5,19 @@ `tabbar` 分为 `4 种` 情况: - 0 `无 tabbar`,只有一个页面入口,底部无 `tabbar` 显示;常用语临时活动页。 -- 1 `原生 tabbar`,使用 `switchTab` 切换 tabbar,`tabbar` 页面有缓存。 - - 优势:原生自带的 tabbar,最先渲染,有缓存。 + +- 1 `原生 tabbar`,使用 `switchTab` 切换 `tabbar`,`tabbar` 页面有缓存。 + - 优势:原生自带的 `tabbar`,最先渲染,有缓存。 - 劣势:只能使用 2 组图片来切换选中和非选中状态,修改颜色只能重新换图片(或者用 iconfont)。 -- 2 `有缓存自定义 tabbar`,使用 `switchTab` 切换 tabbar,`tabbar` 页面有缓存。使用了第三方 UI 库的 `tabbar` 组件,并隐藏了原生 `tabbar` 的显示。 + +- 2 `有缓存自定义 tabbar`,使用 `switchTab` 切换 `tabbar`,`tabbar` 页面有缓存。使用了第三方 UI 库的 `tabbar` 组件,并隐藏了原生 `tabbar` 的显示。 - 优势:可以随意配置自己想要的 `svg icon`,切换字体颜色方便。有缓存。可以实现各种花里胡哨的动效等。 - - 劣势:首次点击 tababr 会闪烁。 + - 劣势:首次点击 `tabbar` 会闪烁。 + - 3 `无缓存自定义 tabbar`,使用 `navigateTo` 切换 `tabbar`,`tabbar` 页面无缓存。使用了第三方 UI 库的 `tabbar` 组件。 - 优势:可以随意配置自己想要的 svg icon,切换字体颜色方便。可以实现各种花里胡哨的动效等。 - 劣势:首次点击 `tababr` 会闪烁,无缓存。 - > 注意:花里胡哨的效果需要自己实现,本模版不提供。 ## tabbar 配置说明 @@ -28,6 +30,7 @@ `config.ts` 专门配置 `nativeTabbarList` 和 `customTabbarList` 的相关信息,请按照文件里面的注释配置相关项。 使用 `原生tabbar` 时,不需要关心下面2个文件: + - `store.ts` ,专门给 `自定义 tabbar` 提供状态管理,代码几乎不需要修改。 - `index.vue` ,专门给 `自定义 tabbar` 提供渲染逻辑,代码可以稍微修改,以符合自己的需求。 @@ -42,6 +45,7 @@ "icon": "home", } ``` + - unocss 图标 ```js @@ -54,6 +58,7 @@ icon: 'i-carbon-code', } ``` + - iconfont 图标 ```js @@ -64,6 +69,7 @@ icon: 'iconfont icon-my', } ``` + - image 本地图片 ```js diff --git a/src/tabbar/config.ts b/src/tabbar/config.ts index 2656ea4..141c07a 100644 --- a/src/tabbar/config.ts +++ b/src/tabbar/config.ts @@ -1,4 +1,5 @@ import type { TabBar } from '@uni-helper/vite-plugin-uni-pages' +import type { CustomTabBarItem, NativeTabBarItem } from './types' /** * tabbar 选择的策略,更详细的介绍见 tabbar.md 文件 @@ -22,8 +23,6 @@ export const TABBAR_STRATEGY_MAP = { // 如果是使用 CUSTOM_TABBAR(2,3),只需要配置 customTabbarList,nativeTabbarList 不生效 export const selectedTabbarStrategy = TABBAR_STRATEGY_MAP.CUSTOM_TABBAR_WITH_CACHE -type NativeTabBarItem = TabBar['list'][number] - // TODO: 2/3. 使用 NATIVE_TABBAR 时,更新下面的 tabbar 配置 export const nativeTabbarList: NativeTabBarItem[] = [ { @@ -40,18 +39,6 @@ export const nativeTabbarList: NativeTabBarItem[] = [ }, ] -// badge 显示一个数字或 小红点(样式可以直接在 tabbar/index.vue 里面修改) -export type CustomTabBarItemBadge = number | 'dot' - -export interface CustomTabBarItem { - text: string - pagePath: string - iconType: 'uiLib' | 'unocss' | 'iconfont' | 'image' // 不建议用 image 模式,需要配置2张图 - icon: any // 其实是 string 类型,这里是为了避免 ts 报错 (tabbar/index.vue 里面 uni-icons 那行) - iconActive?: string // 只有在 image 模式下才需要,传递的是高亮的图片(PS: 不建议用 image 模式) - badge?: CustomTabBarItemBadge - isBulge?: boolean // 是否是中间的鼓包tabbarItem -} // TODO: 3/3. 使用 CUSTOM_TABBAR(2,3) 时,更新下面的 tabbar 配置 // 如果需要配置鼓包,需要在 'tabbar/store.ts' 里面设置,最后在 `tabbar/index.vue` 里面更改鼓包的图片 export const customTabbarList: CustomTabBarItem[] = [ diff --git a/src/tabbar/index.vue b/src/tabbar/index.vue index c600530..20f2f10 100644 --- a/src/tabbar/index.vue +++ b/src/tabbar/index.vue @@ -1,6 +1,6 @@