This commit is contained in:
范鹏 2024-12-31 10:19:20 +08:00
parent 9c7d326caf
commit 3b77a4bfa9
36 changed files with 323 additions and 383 deletions

View File

@ -2,7 +2,7 @@ module.exports = {
env: {
browser: true,
es2021: true,
node: true,
node: true
},
extends: [
'eslint:recommended',
@ -15,23 +15,23 @@ module.exports = {
// 1. 接入 prettier 的规则
'prettier',
'plugin:prettier/recommended',
'./.eslintrc-auto-import.json',
'./.eslintrc-auto-import.json'
],
overrides: [
{
env: {
node: true,
node: true
},
files: ['.eslintrc.{js,cjs}'],
parserOptions: {
sourceType: 'script',
},
},
sourceType: 'script'
}
}
],
parserOptions: {
ecmaVersion: 'latest',
parser: '@typescript-eslint/parser',
sourceType: 'module',
sourceType: 'module'
},
plugins: [
'@typescript-eslint',
@ -39,7 +39,7 @@ module.exports = {
// 2. 加入 prettier 的 eslint 插件
'prettier',
// eslint-import-resolver-typescript 插件,@see https://www.npmjs.com/package/eslint-import-resolver-typescript
'import',
'import'
],
rules: {
// 3. 注意要加上这一句,开启 prettier 自动修复的功能
@ -50,7 +50,7 @@ module.exports = {
'import/extensions': [
'error',
'ignorePackages',
{ js: 'never', jsx: 'never', ts: 'never', tsx: 'never' },
{ js: 'never', jsx: 'never', ts: 'never', tsx: 'never' }
],
// 只允许1个默认导出关闭否则不能随意export xxx
'import/prefer-default-export': ['off'],
@ -71,16 +71,16 @@ module.exports = {
'@typescript-eslint/no-unused-vars': 'off',
// 避免 `eslint` 对于 `typescript` 函数重载的误报
'no-redeclare': 'off',
'@typescript-eslint/no-redeclare': 'error',
'@typescript-eslint/no-redeclare': 'error'
},
// eslint-import-resolver-typescript 插件,@see https://www.npmjs.com/package/eslint-import-resolver-typescript
settings: {
'import/parsers': {
'@typescript-eslint/parser': ['.ts', '.tsx'],
'@typescript-eslint/parser': ['.ts', '.tsx']
},
'import/resolver': {
typescript: {},
},
typescript: {}
}
},
globals: {
$t: true,
@ -92,6 +92,6 @@ module.exports = {
UniHelper: true,
Page: true,
App: true,
NodeJS: true,
},
NodeJS: true
}
}

View File

@ -1,19 +1,30 @@
// @see https://prettier.io/docs/en/options
module.exports = {
singleQuote: true,
printWidth: 100,
tabWidth: 2,
useTabs: false,
semi: false,
trailingComma: 'all',
trailingComma: 'none',
endOfLine: 'auto',
quoteProps: 'as-needed',
jsxSingleQuote: false,
bracketSpacing: true,
jsxBracketSameLine: false,
bracketSameLine: false,
arrowParens: 'avoid',
embeddedLanguageFormatting: 'auto',
vueIndentScriptAndStyle: true,
singleAttributePerLine: false,
requirePragma: false,
insertPragma: false,
proseWrap: 'preserve',
htmlWhitespaceSensitivity: 'ignore',
overrides: [
{
files: '*.json',
options: {
trailingComma: 'none',
},
},
],
trailingComma: 'none'
}
}
]
}

View File

@ -9,19 +9,19 @@ module.exports = {
'stylelint-config-recommended-scss',
'stylelint-config-recommended-vue/scss',
'stylelint-config-html/vue',
'stylelint-config-recess-order',
'stylelint-config-recess-order'
],
plugins: ['stylelint-prettier'],
overrides: [
// 扫描 .vue/html 文件中的<style>标签内的样式
{
files: ['**/*.{vue,html}'],
customSyntax: 'postcss-html',
customSyntax: 'postcss-html'
},
{
files: ['**/*.{css,scss}'],
customSyntax: 'postcss-scss',
},
customSyntax: 'postcss-scss'
}
],
// 自定义规则
rules: {
@ -30,21 +30,21 @@ module.exports = {
'selector-pseudo-class-no-unknown': [
true,
{
ignorePseudoClasses: ['global', 'export', 'v-deep', 'deep'],
},
ignorePseudoClasses: ['global', 'export', 'v-deep', 'deep']
}
],
'unit-no-unknown': [
true,
{
ignoreUnits: ['rpx'],
},
ignoreUnits: ['rpx']
}
],
// 处理小程序page标签不认识的问题
'selector-type-no-unknown': [
true,
{
ignoreTypes: ['page'],
},
ignoreTypes: ['page']
}
],
'comment-empty-line-before': 'never', // never|always|always-multi-line|never-multi-line
'custom-property-empty-line-before': 'never',
@ -53,6 +53,6 @@ module.exports = {
'no-duplicate-selectors': null,
'scss/comment-no-empty': null,
'selector-class-pattern': null,
'font-family-no-missing-generic-family-keyword': null,
},
'font-family-no-missing-generic-family-keyword': null
}
}

View File

@ -1,86 +1,23 @@
<p align="center">
<a href="https://github.com/feige996/unibest">
<img width="160" src="./src/static/logo.svg">
</a>
</p>
<h1 align="center">
<a href="https://github.com/feige996/unibest" target="_blank">unibest - 最好的 uniapp 开发框架</a>
</h1>
<div align="center">
旧仓库 codercup 进不去了star 也拿不回来,这里也展示一下那个地址的 star.
[![GitHub Repo stars](https://img.shields.io/github/stars/codercup/unibest?style=flat&logo=github)](https://github.com/codercup/unibest)
[![GitHub forks](https://img.shields.io/github/forks/codercup/unibest?style=flat&logo=github)](https://github.com/codercup/unibest)
</div>
<div align="center">
[![GitHub Repo stars](https://img.shields.io/github/stars/feige996/unibest?style=flat&logo=github)](https://github.com/feige996/unibest)
[![GitHub forks](https://img.shields.io/github/forks/feige996/unibest?style=flat&logo=github)](https://github.com/feige996/unibest)
[![star](https://gitee.com/feige996/unibest/badge/star.svg?theme=dark)](https://gitee.com/feige996/unibest/stargazers)
[![fork](https://gitee.com/feige996/unibest/badge/fork.svg?theme=dark)](https://gitee.com/feige996/unibest/members)
![node version](https://img.shields.io/badge/node-%3E%3D18-green)
![pnpm version](https://img.shields.io/badge/pnpm-%3E%3D7.30-green)
![GitHub package.json version (subfolder of monorepo)](https://img.shields.io/github/package-json/v/feige996/unibest)
![GitHub License](https://img.shields.io/github/license/feige996/unibest)
</div>
`unibest` —— 最好的 `uniapp` 开发模板,由 `uniapp` + `Vue3` + `Ts` + `Vite5` + `UnoCss` + `wot-ui` + `z-paging` 构成,使用了最新的前端技术栈,无需依靠 `HBuilderX`,通过命令行方式运行 `web``小程序``App`(编辑器推荐 `VSCode`,可选 `webstorm`)。
`unibest` 是一个 uniapp 跨端解决方案,由 `uniapp` + `Vue3` + `Ts` + `Vite4` + `UnoCss` + `VSCode`(可选 `webstorm`) 实现。它使用了最新的前端技术栈,可以通过命令行方式运行 `web``小程序``App`,同时也支持 `HBuilderX` 运行,当前版本为 `HBuilderX` 运行版本。如需通过命令行运行,请安装命令行版(<a href="https://github.com/codercup/unibest" target="_blank">unibest</a>)。
`unibest` 内置了 `约定式路由``layout布局``请求封装``请求拦截``登录拦截``UnoCSS``i18n多语言` 等基础功能,提供了 `代码提示``自动格式化``统一配置``代码片段` 等辅助功能,让你编写 `uniapp` 拥有 `best` 体验 `unibest 的由来`)。
![](https://raw.githubusercontent.com/andreasbm/readme/master/screenshots/lines/rainbow.png)
<p align="center">
<a href="https://unibest.tech/" target="_blank">📖 文档地址(new)</a>
<span style="margin:0 10px;">|</span>
<a href="https://feige996.github.io/hello-unibest/" target="_blank">📱 DEMO 地址</a>
</p>
---
注意旧的地址 [codercup](https://github.com/codercup/unibest) 我进不去了,使用新的 [feige996](https://github.com/feige996/unibest)。PR和 issue 也请使用新地址,否则无法合并。
## ⚙️ 环境
- node>=18
- pnpm>=7.30
- Vue Official>=2.1.10
- TypeScript>=5.0
## &#x1F4C2; 快速开始
## &#x1F4C2; 安装
执行 `pnpm create unibest` 创建项目
```bash
# HBuilderX 模板,方便使用 uniCloud 云开发 (未来可以对接 uni-app x)
pnpm create unibest my-project -t hbx-base # hbx的base模板
pnpm create unibest my-project -t hbx-demo # hbx的demo模板包含所有的demo
执行 `pnpm i` 安装依赖
# 执行 `pnpm i` 安装依赖
pnpm i
```
执行 `pnpm dev` 运行 `H5`
## 📦 使用 `HBuilderX` 打开
## 📦 运行(支持热更新)
- web平台 `pnpm dev:h5`, 然后打开 [http://localhost:9000/](http://localhost:9000/)。
- weixin平台`pnpm dev:mp-weixin` 然后打开微信开发者工具,导入本地文件夹,选择本项目的`dist/dev/mp-weixin` 文件。
- APP平台`pnpm dev:app`, 然后打开 `HBuilderX`,导入刚刚生成的`dist/dev/app` 文件夹,选择运行到模拟器(开发时优先使用),或者运行的安卓/ios基座。
## 🔗 发布
- web平台 `pnpm build:h5`,打包后的文件在 `dist/build/h5`可以放到web服务器如nginx运行。如果最终不是放在根目录可以在 `manifest.config.ts` 文件的 `h5.router.base` 属性进行修改。
- weixin平台`pnpm build:mp-weixin`, 打包后的文件在 `dist/build/mp-weixin`,然后通过微信开发者工具导入,并点击右上角的“上传”按钮进行上传。
- APP平台`pnpm build:app`, 然后打开 `HBuilderX`,导入刚刚生成的`dist/build/app` 文件夹,选择发行 - APP云打包。
## 📄 License
[MIT](https://opensource.org/license/mit/)
Copyright (c) 2024 菲鸽
## 捐赠
<p align='center'>
<img alt="special sponsor appwrite" src="./screenshots/pay-1.png" height="330" style="display:inline-block; height:330px;">
<img alt="special sponsor appwrite" src="./screenshots/pay-2.png" height="330" style="display:inline-block; height:330px; margin-left:10px;">
</p>
`HBuilderX` 运行(支持热更新)或 编译

View File

@ -10,7 +10,7 @@ const {
VITE_UNI_APPID,
VITE_WX_APPID,
VITE_APP_PUBLIC_BASE,
VITE_FALLBACK_LOCALE,
VITE_FALLBACK_LOCALE
} = env
export default defineManifestConfig({
@ -23,8 +23,8 @@ export default defineManifestConfig({
locale: VITE_FALLBACK_LOCALE, // 'zh-Hans'
h5: {
router: {
base: VITE_APP_PUBLIC_BASE,
},
base: VITE_APP_PUBLIC_BASE
}
},
/* 5+App特有相关 */
'app-plus': {
@ -32,13 +32,13 @@ export default defineManifestConfig({
nvueStyleCompiler: 'uni-app',
compilerVersion: 3,
compatible: {
ignoreVersion: true,
ignoreVersion: true
},
splashscreen: {
alwaysShowBeforeRender: true,
waiting: true,
autoclose: true,
delay: 0,
delay: 0
},
/* 模块配置 */
modules: {},
@ -46,7 +46,7 @@ export default defineManifestConfig({
distribute: {
/* android打包配置 */
android: {
minSdkVersion: 30,
minSdkVersion: 29,
targetSdkVersion: 30,
abiFilters: ['armeabi-v7a', 'arm64-v8a'],
permissions: [
@ -64,8 +64,8 @@ export default defineManifestConfig({
'<uses-permission android:name="android.permission.WAKE_LOCK"/>',
'<uses-permission android:name="android.permission.FLASHLIGHT"/>',
'<uses-feature android:name="android.hardware.camera"/>',
'<uses-permission android:name="android.permission.WRITE_SETTINGS"/>',
],
'<uses-permission android:name="android.permission.WRITE_SETTINGS"/>'
]
},
/* ios打包配置 */
ios: {},
@ -77,7 +77,7 @@ export default defineManifestConfig({
hdpi: 'static/app/icons/72x72.png',
xhdpi: 'static/app/icons/96x96.png',
xxhdpi: 'static/app/icons/144x144.png',
xxxhdpi: 'static/app/icons/192x192.png',
xxxhdpi: 'static/app/icons/192x192.png'
},
ios: {
appstore: 'static/app/icons/1024x1024.png',
@ -90,7 +90,7 @@ export default defineManifestConfig({
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',
'spotlight@2x': 'static/app/icons/80x80.png'
},
iphone: {
'app@2x': 'static/app/icons/120x120.png',
@ -100,11 +100,11 @@ export default defineManifestConfig({
'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',
},
},
},
},
'spotlight@3x': 'static/app/icons/120x120.png'
}
}
}
}
},
/* 快应用特有相关 */
quickapp: {},
@ -112,23 +112,23 @@ export default defineManifestConfig({
'mp-weixin': {
appid: VITE_WX_APPID,
setting: {
urlCheck: false,
urlCheck: false
},
usingComponents: true,
usingComponents: true
// __usePrivacyCheck__: true,
},
'mp-alipay': {
usingComponents: true,
styleIsolation: 'shared',
styleIsolation: 'shared'
},
'mp-baidu': {
usingComponents: true,
usingComponents: true
},
'mp-toutiao': {
usingComponents: true,
usingComponents: true
},
uniStatistics: {
enable: false,
enable: false
},
vueVersion: '3',
vueVersion: '3'
})

View File

@ -1,23 +1,7 @@
{
"name": "starwork-uniapp",
"type": "commonjs",
"version": "2.5.4",
"description": "unibest - 最好的 uniapp 开发模板",
"author": {
"name": "feige996",
"zhName": "菲鸽",
"email": "1020103647@qq.com",
"github": "https://github.com/feige996",
"gitee": "https://gitee.com/feige996"
},
"license": "MIT",
"repository": "https://github.com/feige996/unibest",
"repository-gitee": "https://gitee.com/feige996/unibest",
"repository-deprecated": "https://github.com/codercup/unibest",
"bugs": {
"url": "https://github.com/feige996/unibest/issues"
},
"homepage": "https://feige996.github.io/unibest/",
"version": "1.0.0",
"engines": {
"node": ">=18",
"pnpm": ">=7.30"

View File

@ -6,38 +6,50 @@ export default defineUniPages({
navigationBarTitleText: 'unibest',
navigationBarBackgroundColor: '#f8f8f8',
navigationBarTextStyle: 'black',
backgroundColor: '#FFFFFF',
backgroundColor: '#FFFFFF'
},
easycom: {
autoscan: true,
custom: {
'^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',
},
'z-paging/components/z-paging$1/z-paging$1.vue'
}
},
tabBar: {
color: '#999999',
selectedColor: '#018d71',
backgroundColor: '#F8F8F8',
color: '#0d0f10',
selectedColor: '#255cf7',
backgroundColor: '#FFFFFF',
borderStyle: 'black',
height: '50px',
fontSize: '10px',
iconWidth: '24px',
spacing: '3px',
spacing: '5px',
list: [
{
iconPath: 'static/tabbar/home.png',
selectedIconPath: 'static/tabbar/homeHL.png',
pagePath: 'pages/index/index',
text: '首页',
pagePath: 'pages/home/home',
text: '首页'
},
{
iconPath: 'static/tabbar/home.png',
selectedIconPath: 'static/tabbar/homeHL.png',
pagePath: 'pages/workbench/workbench',
text: '工作台'
},
{
iconPath: 'static/tabbar/home.png',
selectedIconPath: 'static/tabbar/homeHL.png',
pagePath: 'pages/notification/notification',
text: '消息'
},
{
iconPath: 'static/tabbar/example.png',
selectedIconPath: 'static/tabbar/exampleHL.png',
pagePath: 'pages/about/about',
text: '关于',
},
],
},
pagePath: 'pages/mine/mine',
text: '我的'
}
]
}
})

Binary file not shown.

Before

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

View File

@ -19,7 +19,7 @@ const dependencies = [
'@dcloudio/uni-mp-xhs',
'@dcloudio/uni-quickapp-webview',
// i18n模板要注释掉下面的
'vue-i18n',
'vue-i18n'
]
// 使用exec执行命令

View File

@ -1,58 +1,58 @@
<script setup lang="ts">
import { onLaunch, onShow, onHide } from '@dcloudio/uni-app'
import { onLaunch, onShow, onHide } from '@dcloudio/uni-app'
onLaunch(() => {
console.log('App Launch')
})
onShow(() => {
console.log('App Show')
})
onHide(() => {
console.log('App Hide')
})
onLaunch(() => {
console.log('App Launch')
})
onShow(() => {
console.log('App Show')
})
onHide(() => {
console.log('App Hide')
})
</script>
<style lang="scss">
/* stylelint-disable selector-type-no-unknown */
button::after {
border: none;
}
/* stylelint-disable selector-type-no-unknown */
button::after {
border: none;
}
swiper,
scroll-view {
flex: 1;
height: 100%;
overflow: hidden;
}
swiper,
scroll-view {
flex: 1;
height: 100%;
overflow: hidden;
}
image {
width: 100%;
height: 100%;
vertical-align: middle;
}
image {
width: 100%;
height: 100%;
vertical-align: middle;
}
// 使 unocss: text-ellipsis
.ellipsis {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
// 使 unocss: text-ellipsis
.ellipsis {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
//
.ellipsis-2 {
display: -webkit-box;
overflow: hidden;
text-overflow: ellipsis;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
//
.ellipsis-2 {
display: -webkit-box;
overflow: hidden;
text-overflow: ellipsis;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
//
.ellipsis-3 {
display: -webkit-box;
overflow: hidden;
text-overflow: ellipsis;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
}
//
.ellipsis-3 {
display: -webkit-box;
overflow: hidden;
text-overflow: ellipsis;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
}
</style>

View File

@ -17,7 +17,7 @@ type IUseRequestOptions<T> = {
*/
export default function useRequest<T>(
func: () => Promise<IResData<T>>,
options: IUseRequestOptions<T> = { immediate: false },
options: IUseRequestOptions<T> = { immediate: false }
) {
const loading = ref(false)
const error = ref(false)
@ -25,12 +25,12 @@ export default function useRequest<T>(
const run = async () => {
loading.value = true
return func()
.then((res) => {
.then(res => {
data.value = res.data as UnwrapRef<T>
error.value = false
return data.value
})
.catch((err) => {
.catch(err => {
error.value = err
throw err
})

View File

@ -19,29 +19,29 @@ export default function useUpload<T = string>(formData: Record<string, any> = {}
uni.chooseMedia({
count: 1,
mediaType: ['image'],
success: (res) => {
success: res => {
loading.value = true
const tempFilePath = res.tempFiles[0].tempFilePath
uploadFile<T>({ tempFilePath, formData, data, error, loading })
},
fail: (err) => {
fail: err => {
console.error('uni.chooseMedia err->', err)
error.value = true
},
}
})
// #endif
// #ifndef MP-WEIXIN
uni.chooseImage({
count: 1,
success: (res) => {
success: res => {
loading.value = true
const tempFilePath = res.tempFilePaths[0]
uploadFile<T>({ tempFilePath, formData, data, error, loading })
},
fail: (err) => {
fail: err => {
console.error('uni.chooseImage err->', err)
error.value = true
},
}
})
// #endif
}
@ -55,15 +55,15 @@ function uploadFile<T>({ tempFilePath, formData, data, error, loading }) {
filePath: tempFilePath,
name: 'file',
formData,
success: (uploadFileRes) => {
success: uploadFileRes => {
data.value = uploadFileRes.data as T
},
fail: (err) => {
fail: err => {
console.error('uni.uploadFile err->', err)
error.value = true
},
complete: () => {
loading.value = false
},
}
})
}

View File

@ -9,5 +9,5 @@ export const prototypeInterceptor = {
return this[index]
}
}
},
}
}

View File

@ -47,7 +47,7 @@ const httpInterceptor = {
// 2. (可选)添加小程序端请求头标识
options.header = {
platform, // 可选,与 uniapp 定义的平台一致,告诉后台来源
...options.header,
...options.header
}
// 3. 添加 token 请求头标识
const userStore = useUserStore()
@ -55,7 +55,7 @@ const httpInterceptor = {
if (token) {
options.header.Authorization = `Bearer ${token}`
}
},
}
}
export const requestInterceptor = {
@ -64,5 +64,5 @@ export const requestInterceptor = {
uni.addInterceptor('request', httpInterceptor)
// 拦截 uploadFile 文件上传
uni.addInterceptor('uploadFile', httpInterceptor)
},
}
}

View File

@ -1,5 +1,4 @@
/**
* by on 2024-03-06
*
*
* 便使
@ -41,7 +40,7 @@ const navigateToInterceptor = {
const redirectRoute = `${loginRoute}?redirect=${encodeURIComponent(url)}`
uni.navigateTo({ url: redirectRoute })
return false
},
}
}
export const routeInterceptor = {
@ -49,5 +48,5 @@ export const routeInterceptor = {
uni.addInterceptor('navigateTo', navigateToInterceptor)
uni.addInterceptor('reLaunch', navigateToInterceptor)
uni.addInterceptor('redirectTo', navigateToInterceptor)
},
}
}

View File

@ -7,11 +7,11 @@
</template>
<script lang="ts" setup>
import type { ConfigProviderThemeVars } from 'wot-design-uni'
import type { ConfigProviderThemeVars } from 'wot-design-uni'
const themeVars: ConfigProviderThemeVars = {
// colorTheme: 'red',
// buttonPrimaryBgColor: '#07c160',
// buttonPrimaryColor: '#07c160',
}
const themeVars: ConfigProviderThemeVars = {
// colorTheme: 'red',
// buttonPrimaryBgColor: '#07c160',
// buttonPrimaryColor: '#07c160',
}
</script>

View File

@ -7,11 +7,11 @@
</template>
<script lang="ts" setup>
import type { ConfigProviderThemeVars } from 'wot-design-uni'
import type { ConfigProviderThemeVars } from 'wot-design-uni'
const themeVars: ConfigProviderThemeVars = {
// colorTheme: 'red',
// buttonPrimaryBgColor: '#07c160',
// buttonPrimaryColor: '#07c160',
}
const themeVars: ConfigProviderThemeVars = {
// colorTheme: 'red',
// buttonPrimaryBgColor: '#07c160',
// buttonPrimaryColor: '#07c160',
}
</script>

View File

@ -12,6 +12,6 @@ export function createApp() {
app.use(requestInterceptor)
app.use(prototypeInterceptor)
return {
app,
app
}
}

View File

@ -35,7 +35,7 @@
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
],
"minSdkVersion": 30,
"minSdkVersion": 29,
"targetSdkVersion": 30,
"abiFilters": [
"armeabi-v7a",
@ -108,4 +108,4 @@
"base": "/unibest/"
}
}
}
}

View File

@ -1,20 +0,0 @@
<route lang="json5" type="page">
{
style: { navigationBarTitleText: '分包页面 标题' },
}
</route>
<template>
<view class="text-center">
<view class="m-8">http://localhost:9000/#/pages-sub/demo/index</view>
<view class="text-green-500">分包页面demo</view>
</view>
</template>
<script lang="ts" setup>
// code here
</script>
<style lang="scss" scoped>
//
</style>

View File

@ -14,26 +14,38 @@
}
},
"tabBar": {
"color": "#999999",
"selectedColor": "#018d71",
"backgroundColor": "#F8F8F8",
"color": "#0d0f10",
"selectedColor": "#255cf7",
"backgroundColor": "#FFFFFF",
"borderStyle": "black",
"height": "50px",
"fontSize": "10px",
"iconWidth": "24px",
"spacing": "3px",
"spacing": "5px",
"list": [
{
"iconPath": "static/tabbar/home.png",
"selectedIconPath": "static/tabbar/homeHL.png",
"pagePath": "pages/index/index",
"pagePath": "pages/home/home",
"text": "首页"
},
{
"iconPath": "static/tabbar/home.png",
"selectedIconPath": "static/tabbar/homeHL.png",
"pagePath": "pages/workbench/workbench",
"text": "工作台"
},
{
"iconPath": "static/tabbar/home.png",
"selectedIconPath": "static/tabbar/homeHL.png",
"pagePath": "pages/notification/notification",
"text": "消息"
},
{
"iconPath": "static/tabbar/example.png",
"selectedIconPath": "static/tabbar/exampleHL.png",
"pagePath": "pages/about/about",
"text": "关于"
"pagePath": "pages/mine/mine",
"text": "我的"
}
]
},
@ -55,4 +67,4 @@
}
],
"subPackages": []
}
}

View File

@ -1,8 +1,8 @@
<route lang="json5">
{
style: {
navigationBarTitleText: '关于',
},
navigationBarTitleText: '关于'
}
}
</route>
@ -21,16 +21,16 @@
</template>
<script lang="ts" setup>
import RequestComp from './components/request.vue'
import UploadComp from './components/upload.vue'
import RequestComp from './components/request.vue'
import UploadComp from './components/upload.vue'
//
const { safeAreaInsets } = uni.getSystemInfoSync()
//
const { safeAreaInsets } = uni.getSystemInfoSync()
</script>
<style lang="scss" scoped>
.test-css {
// mt-4=>1rem=>16px;
margin-top: 16px;
}
.test-css {
// mt-4=>1rem=>16px;
margin-top: 16px;
}
</style>

View File

@ -2,8 +2,8 @@
{
layout: 'demo',
style: {
navigationBarTitleText: '请求',
},
navigationBarTitleText: '请求'
}
}
</route>
@ -36,21 +36,21 @@
</template>
<script lang="ts" setup>
import { getFooAPI, postFooAPI, IFooItem } from '@/service/index/foo'
import { getFooAPI, postFooAPI, IFooItem } from '@/service/index/foo'
const recommendUrl = ref('http://laf.run/signup?code=ohaOgIX')
const recommendUrl = ref('http://laf.run/signup?code=ohaOgIX')
// const initialData = {
// name: 'initialData',
// id: '1234',
// }
const initialData = undefined
// Service
const { loading, error, data, run } = useRequest<IFooItem>(() => getFooAPI('菲鸽'), {
immediate: true,
initialData,
})
const reset = () => {
data.value = initialData
}
// const initialData = {
// name: 'initialData',
// id: '1234',
// }
const initialData = undefined
// Service
const { loading, error, data, run } = useRequest<IFooItem>(() => getFooAPI('菲鸽'), {
immediate: true,
initialData
})
const reset = () => {
data.value = initialData
}
</script>

View File

@ -2,8 +2,8 @@
{
layout: 'default',
style: {
navigationBarTitleText: '上传-状态一体化',
},
navigationBarTitleText: '上传-状态一体化'
}
}
</route>
@ -22,9 +22,9 @@
</template>
<script lang="ts" setup>
const { loading, data, run } = useUpload({ user: '菲鸽' })
const { loading, data, run } = useUpload({ user: '菲鸽' })
</script>
<style lang="scss" scoped>
//
//
</style>

View File

@ -3,8 +3,8 @@
{
style: {
navigationStyle: 'custom',
navigationBarTitleText: '首页',
},
navigationBarTitleText: '首页'
}
}
</route>
<template>
@ -31,26 +31,26 @@
</template>
<script lang="ts" setup>
import PLATFORM from '@/utils/platform'
import PLATFORM from '@/utils/platform'
defineOptions({
name: 'Home',
})
defineOptions({
name: 'Home'
})
//
const { safeAreaInsets } = uni.getSystemInfoSync()
const author = ref('菲鸽')
const description = ref(
'unibest 是一个集成了多种工具和技术的 uniapp 开发模板,由 uniapp + Vue3 + Ts + Vite4 + UnoCss + UniUI + VSCode 构建,模板具有代码提示、自动格式化、统一配置、代码片段等功能,并内置了许多常用的基本组件和基本功能,让你编写 uniapp 拥有 best 体验。',
)
// uni API
onLoad(() => {
console.log(author)
})
//
const { safeAreaInsets } = uni.getSystemInfoSync()
const author = ref('菲鸽')
const description = ref(
'unibest 是一个集成了多种工具和技术的 uniapp 开发模板,由 uniapp + Vue3 + Ts + Vite4 + UnoCss + UniUI + VSCode 构建,模板具有代码提示、自动格式化、统一配置、代码片段等功能,并内置了许多常用的基本组件和基本功能,让你编写 uniapp 拥有 best 体验。'
)
// uni API
onLoad(() => {
console.log(author)
})
</script>
<style>
.main-title-color {
color: #d14328;
}
.main-title-color {
color: #d14328;
}
</style>

View File

@ -6,9 +6,9 @@ store.use(
createPersistedState({
storage: {
getItem: uni.getStorageSync,
setItem: uni.setStorageSync,
},
}),
setItem: uni.setStorageSync
}
})
)
export default store

View File

@ -26,10 +26,10 @@ export const useUserStore = defineStore(
setUserInfo,
clearUserInfo,
isLogined,
reset,
reset
}
},
{
persist: true,
},
persist: true
}
)

View File

@ -10,7 +10,7 @@ interface NavigateToOptions {
interface RedirectToOptions extends NavigateToOptions {}
interface SwitchTabOptions {
url: "/pages/index/index" | "/pages/about/about"
url: "/pages/home/home" | "/pages/workbench/workbench" | "/pages/notification/notification" | "/pages/mine/mine"
}
type ReLaunchOptions = NavigateToOptions | SwitchTabOptions;

View File

@ -25,5 +25,5 @@ type IUserInfo = {
enum TestEnum {
A = 'a',
B = 'b',
B = 'b'
}

View File

@ -25,7 +25,7 @@ export const http = <T>(options: CustomRequestOptions) => {
!options.hideErrorToast &&
uni.showToast({
icon: 'none',
title: (res.data as IResData<T>).msg || '请求错误',
title: (res.data as IResData<T>).msg || '请求错误'
})
reject(res)
}
@ -34,10 +34,10 @@ export const http = <T>(options: CustomRequestOptions) => {
fail(err) {
uni.showToast({
icon: 'none',
title: '网络错误,换个网络试试',
title: '网络错误,换个网络试试'
})
reject(err)
},
}
})
})
}
@ -52,7 +52,7 @@ export const httpGet = <T>(url: string, query?: Record<string, any>) => {
return http<T>({
url,
query,
method: 'GET',
method: 'GET'
})
}
@ -66,13 +66,13 @@ export const httpGet = <T>(url: string, query?: Record<string, any>) => {
export const httpPost = <T>(
url: string,
data?: Record<string, any>,
query?: Record<string, any>,
query?: Record<string, any>
) => {
return http<T>({
url,
query,
data,
method: 'POST',
method: 'POST'
})
}

View File

@ -20,7 +20,7 @@ export const getIsTabbar = () => {
}
const lastPage = getLastPage()
const currPath = lastPage.route
return !!tabBar.list.find((e) => e.pagePath === currPath)
return !!tabBar.list.find(e => e.pagePath === currPath)
}
/**
@ -61,11 +61,11 @@ export const getUrlObj = (url: string) => {
if (!queryStr) {
return {
path,
query: {},
query: {}
}
}
const query: Record<string, string> = {}
queryStr.split('&').forEach((item) => {
queryStr.split('&').forEach(item => {
const [key, value] = item.split('=')
// console.log(key, value)
query[key] = ensureDecodeURIComponent(value) // 这里需要统一 decodeURIComponent 一下可以兼容h5和微信y
@ -81,24 +81,24 @@ export const getAllPages = (key = 'needLogin') => {
// 这里处理主包
const mainPages = [
...pages
.filter((page) => !key || page[key])
.map((page) => ({
.filter(page => !key || page[key])
.map(page => ({
...page,
path: `/${page.path}`,
})),
path: `/${page.path}`
}))
]
// 这里处理分包
const subPages: any[] = []
subPackages.forEach((subPageObj) => {
subPackages.forEach(subPageObj => {
// console.log(subPageObj)
const { root } = subPageObj
subPageObj.pages
.filter((page) => !key || page[key])
.filter(page => !key || page[key])
.forEach((page: { path: string } & Record<string, any>) => {
subPages.push({
...page,
path: `/${root}/${page.path}`,
path: `/${root}/${page.path}`
})
})
})
@ -111,13 +111,13 @@ export const getAllPages = (key = 'needLogin') => {
* pages
* path
*/
export const getNeedLoginPages = (): string[] => getAllPages('needLogin').map((page) => page.path)
export const getNeedLoginPages = (): string[] => getAllPages('needLogin').map(page => page.path)
/**
* pages
* path
*/
export const needLoginPages: string[] = getAllPages('needLogin').map((page) => page.path)
export const needLoginPages: string[] = getAllPages('needLogin').map(page => page.path)
/**
* BaseUrl
@ -129,7 +129,7 @@ export const getEnvBaseUrl = () => {
// 小程序端环境区分
if (isMp) {
const {
miniProgram: { envVersion },
miniProgram: { envVersion }
} = uni.getAccountInfoSync()
switch (envVersion) {
@ -158,7 +158,7 @@ export const getEnvBaseUploadUrl = () => {
// 小程序端环境区分
if (isMp) {
const {
miniProgram: { envVersion },
miniProgram: { envVersion }
} = uni.getAccountInfoSync()
switch (envVersion) {

View File

@ -12,6 +12,6 @@ const PLATFORM = {
platform,
isH5,
isApp,
isMp,
isMp
}
export default PLATFORM

View File

@ -6,7 +6,7 @@ import {
presetAttributify,
presetIcons,
transformerDirectives,
transformerVariantGroup,
transformerVariantGroup
} from 'unocss'
import { presetApplet, presetRemRpx, transformerAttributify } from 'unocss-applet'
@ -25,7 +25,7 @@ if (isMp) {
// 非小程序用官方预设
presetUno(),
// 支持css class属性化
presetAttributify(),
presetAttributify()
)
}
export default defineConfig({
@ -37,9 +37,9 @@ export default defineConfig({
warn: true,
extraProperties: {
display: 'inline-block',
'vertical-align': 'middle',
},
}),
'vertical-align': 'middle'
}
})
// 将颜色函数 (rgb()和hsl()) 从空格分隔转换为逗号分隔更好的兼容性app端example
// `rgb(255 0 0)` -> `rgb(255, 0, 0)`
// `rgba(255 0 0 / 0.5)` -> `rgba(255, 0, 0, 0.5)`
@ -63,20 +63,25 @@ export default defineConfig({
transformerAttributify({
// 解决与第三方框架样式冲突问题
prefixedOnly: true,
prefix: 'fg',
}),
prefix: 'fg'
})
],
rules: [
[
'p-safe',
{
padding:
'env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left)',
},
'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)' }],
],
['custom-color-black', { color: '#0d0f10' }],
['custom-color-grey', { color: '#505253' }],
['custom-color-blue', { color: '#255cf7' }],
['custom-bg-blue', { backGround: '#255cf7' }],
['custom-bg-default', { backGround: '#f3f5fa' }]
]
})
/**

View File

@ -8,7 +8,7 @@ export function copyNativeRes() {
'../dist',
process.env.NODE_ENV === 'production' ? 'build' : 'dev',
process.env.UNI_PLATFORM!,
'nativeResources',
'nativeResources'
)
return {
@ -29,11 +29,11 @@ export function copyNativeRes() {
// 执行文件夹复制
await fs.copy(waitPath, buildPath)
console.log(
`[copyNativeRes] 成功将 nativeResources 目录中的资源移动到构建目录:${buildPath}`,
`[copyNativeRes] 成功将 nativeResources 目录中的资源移动到构建目录:${buildPath}`
)
} catch (error) {
console.error(`[copyNativeRes] 复制资源失败:`, error)
}
},
}
}
}

View File

@ -43,7 +43,7 @@ export default ({ command, mode }) => {
VITE_DELETE_CONSOLE,
VITE_SHOW_SOURCEMAP,
VITE_APP_PROXY,
VITE_APP_PROXY_PREFIX,
VITE_APP_PROXY_PREFIX
} = env
console.log('环境变量 env -> ', env)
@ -57,7 +57,7 @@ export default ({ command, mode }) => {
// homePage 通过 vue 文件的 route-block 的type="home"来设定
// pages 目录为 src/pages分包目录不能配置在pages目录下
// subPackages: ['src/pages-sub'], // 是个数组可以配置多个但是不能为pages里面的目录
dts: 'src/types/uni-pages.d.ts',
dts: 'src/types/uni-pages.d.ts'
}),
UniLayouts(),
UniPlatform(),
@ -70,11 +70,11 @@ export default ({ command, mode }) => {
// 自定义插件禁用 vite:vue 插件的 devToolsEnabled强制编译 vue 模板时 inline 为 true
name: 'fix-vite-plugin-vue',
configResolved(config) {
const plugin = config.plugins.find((p) => p.name === 'vite:vue')
const plugin = config.plugins.find(p => p.name === 'vite:vue')
if (plugin && plugin.api && plugin.api.options) {
plugin.api.options.devToolsEnabled = false
}
},
}
},
UnoCSS(),
AutoImport({
@ -82,19 +82,19 @@ export default ({ command, mode }) => {
dts: 'src/types/auto-import.d.ts',
dirs: ['src/hooks'], // 自动导入 hooks
eslintrc: { enabled: true },
vueTemplate: true, // default false
vueTemplate: true // default false
}),
ViteRestart({
// 通过这个插件在修改vite.config.js文件则不需要重新运行也生效配置
restart: ['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' &&
@ -103,14 +103,14 @@ export default ({ command, mode }) => {
filename: './node_modules/.cache/visualizer/stats.html',
open: true,
gzipSize: true,
brotliSize: true,
brotliSize: true
}),
// 只有在 app 平台时才启用 copyNativeRes 插件
UNI_PLATFORM === 'app' && copyNativeRes(),
UNI_PLATFORM === 'app' && copyNativeRes()
],
define: {
__UNI_PLATFORM__: JSON.stringify(UNI_PLATFORM),
__VITE_APP_PROXY__: JSON.stringify(VITE_APP_PROXY),
__VITE_APP_PROXY__: JSON.stringify(VITE_APP_PROXY)
},
css: {
postcss: {
@ -119,15 +119,15 @@ export default ({ command, mode }) => {
// // 指定目标浏览器
// overrideBrowserslist: ['> 1%', 'last 2 versions'],
// }),
],
},
]
}
},
resolve: {
alias: {
'@': path.join(process.cwd(), './src'),
'@img': path.join(process.cwd(), './src/static/images'),
},
'@img': path.join(process.cwd(), './src/static/images')
}
},
server: {
host: '0.0.0.0',
@ -139,10 +139,10 @@ export default ({ command, mode }) => {
[VITE_APP_PROXY_PREFIX]: {
target: VITE_SERVER_BASEURL,
changeOrigin: true,
rewrite: (path) => path.replace(new RegExp(`^${VITE_APP_PROXY_PREFIX}`), ''),
},
rewrite: path => path.replace(new RegExp(`^${VITE_APP_PROXY_PREFIX}`), '')
}
}
: undefined,
: undefined
},
build: {
// 方便非h5端调试
@ -153,9 +153,9 @@ export default ({ command, mode }) => {
terserOptions: {
compress: {
drop_console: VITE_DELETE_CONSOLE === 'true',
drop_debugger: true,
},
},
},
drop_debugger: true
}
}
}
})
}