develop
xjs 2025-02-25 09:12:58 +08:00
commit 3607732513
140 changed files with 20354 additions and 0 deletions

106
.commitlintrc.cjs Normal file
View File

@ -0,0 +1,106 @@
const fs = require('fs')
const path = require('path')
const { execSync } = require('child_process')
const scopes = fs
.readdirSync(path.resolve(__dirname, 'src'), { withFileTypes: true })
.filter((dirent) => dirent.isDirectory())
.map((dirent) => dirent.name.replace(/s$/, ''))
// precomputed scope
const scopeComplete = execSync('git status --porcelain || true')
.toString()
.trim()
.split('\n')
.find((r) => ~r.indexOf('M src'))
?.replace(/(\/)/g, '%%')
?.match(/src%%((\w|-)*)/)?.[1]
?.replace(/s$/, '')
module.exports = {
ignores: [(commit) => commit.includes('init')],
extends: ['@commitlint/config-conventional'],
rules: {
'body-leading-blank': [2, 'always'],
'footer-leading-blank': [1, 'always'],
'header-max-length': [2, 'always', 108],
'subject-empty': [2, 'never'],
'type-empty': [2, 'never'],
'subject-case': [0],
'type-enum': [
2,
'always',
[
'feat',
'fix',
'perf',
'style',
'docs',
'test',
'refactor',
'build',
'ci',
'chore',
'revert',
'wip',
'workflow',
'types',
'release',
],
],
},
prompt: {
/** @use `pnpm commit :f` */
alias: {
f: 'docs: fix typos',
r: 'docs: update README',
s: 'style: update code format',
b: 'build: bump dependencies',
c: 'chore: update config',
},
customScopesAlign: !scopeComplete ? 'top' : 'bottom',
defaultScope: scopeComplete,
scopes: [...scopes, 'mock'],
allowEmptyIssuePrefixs: false,
allowCustomIssuePrefixs: false,
// English
typesAppend: [
{ value: 'wip', name: 'wip: work in process' },
{ value: 'workflow', name: 'workflow: workflow improvements' },
{ value: 'types', name: 'types: type definition file changes' },
],
// 中英文对照版
// messages: {
// type: '选择你要提交的类型 :',
// scope: '选择一个提交范围 (可选):',
// customScope: '请输入自定义的提交范围 :',
// subject: '填写简短精炼的变更描述 :\n',
// body: '填写更加详细的变更描述 (可选)。使用 "|" 换行 :\n',
// breaking: '列举非兼容性重大的变更 (可选)。使用 "|" 换行 :\n',
// footerPrefixsSelect: '选择关联issue前缀 (可选):',
// customFooterPrefixs: '输入自定义issue前缀 :',
// footer: '列举关联issue (可选) 例如: #31, #I3244 :\n',
// confirmCommit: '是否提交或修改commit ?',
// },
// types: [
// { value: 'feat', name: 'feat: 新增功能' },
// { value: 'fix', name: 'fix: 修复缺陷' },
// { value: 'docs', name: 'docs: 文档变更' },
// { value: 'style', name: 'style: 代码格式' },
// { value: 'refactor', name: 'refactor: 代码重构' },
// { value: 'perf', name: 'perf: 性能优化' },
// { value: 'test', name: 'test: 添加疏漏测试或已有测试改动' },
// { value: 'build', name: 'build: 构建流程、外部依赖变更 (如升级 npm 包、修改打包配置等)' },
// { value: 'ci', name: 'ci: 修改 CI 配置、脚本' },
// { value: 'revert', name: 'revert: 回滚 commit' },
// { value: 'chore', name: 'chore: 对构建过程或辅助工具和库的更改 (不影响源文件、测试用例)' },
// { value: 'wip', name: 'wip: 正在开发中' },
// { value: 'workflow', name: 'workflow: 工作流程改进' },
// { value: 'types', name: 'types: 类型定义文件修改' },
// ],
// emptyScopesAlias: 'empty: 不填写',
// customScopesAlias: 'custom: 自定义',
},
}

13
.editorconfig Normal file
View File

@ -0,0 +1,13 @@
root = true
[*] # 表示所有文件适用
charset = utf-8 # 设置文件字符集为 utf-8
indent_style = space # 缩进风格tab | space
indent_size = 2 # 缩进大小
end_of_line = lf # 控制换行类型(lf | cr | crlf)
trim_trailing_whitespace = true # 去除行首的任意空白字符
insert_final_newline = true # 始终在文件末尾插入一个新行
[*.md] # 表示仅 md 文件适用以下规则
max_line_length = off # 关闭最大行长度限制
trim_trailing_whitespace = false # 关闭末尾空格修剪

1
.eslintignore Normal file
View File

@ -0,0 +1 @@
src/uni_modules/

107
.eslintrc-auto-import.json Normal file
View File

@ -0,0 +1,107 @@
{
"globals": {
"Component": true,
"ComponentPublicInstance": true,
"ComputedRef": true,
"EffectScope": true,
"ExtractDefaultPropTypes": true,
"ExtractPropTypes": true,
"ExtractPublicPropTypes": true,
"InjectionKey": true,
"PropType": true,
"Ref": true,
"VNode": true,
"WritableComputedRef": true,
"computed": true,
"createApp": true,
"customRef": true,
"defineAsyncComponent": true,
"defineComponent": true,
"effectScope": true,
"getCurrentInstance": true,
"getCurrentScope": true,
"h": true,
"inject": true,
"isProxy": true,
"isReactive": true,
"isReadonly": true,
"isRef": true,
"markRaw": true,
"nextTick": true,
"onActivated": true,
"onAddToFavorites": true,
"onBackPress": true,
"onBeforeMount": true,
"onBeforeUnmount": true,
"onBeforeUpdate": true,
"onDeactivated": true,
"onError": true,
"onErrorCaptured": true,
"onHide": true,
"onLaunch": true,
"onLoad": true,
"onMounted": true,
"onNavigationBarButtonTap": true,
"onNavigationBarSearchInputChanged": true,
"onNavigationBarSearchInputClicked": true,
"onNavigationBarSearchInputConfirmed": true,
"onNavigationBarSearchInputFocusChanged": true,
"onPageNotFound": true,
"onPageScroll": true,
"onPullDownRefresh": true,
"onReachBottom": true,
"onReady": true,
"onRenderTracked": true,
"onRenderTriggered": true,
"onResize": true,
"onScopeDispose": true,
"onServerPrefetch": true,
"onShareAppMessage": true,
"onShareTimeline": true,
"onShow": true,
"onTabItemTap": true,
"onThemeChange": true,
"onUnhandledRejection": true,
"onUnload": true,
"onUnmounted": true,
"onUpdated": true,
"provide": true,
"reactive": true,
"readonly": true,
"ref": true,
"resolveComponent": true,
"shallowReactive": true,
"shallowReadonly": true,
"shallowRef": true,
"toRaw": true,
"toRef": true,
"toRefs": true,
"toValue": true,
"triggerRef": true,
"unref": true,
"useAttrs": true,
"useCssModule": true,
"useCssVars": true,
"useRequest": true,
"useSlots": true,
"useUpload": true,
"useUpload2": true,
"watch": true,
"watchEffect": true,
"watchPostEffect": true,
"watchSyncEffect": true,
"DirectiveBinding": true,
"MaybeRef": true,
"MaybeRefOrGetter": true,
"onWatcherCleanup": true,
"useId": true,
"useModel": true,
"useTemplateRef": true,
"tabbarList": true,
"iphoneBottom": true,
"useNavbarWeixin": true,
"cities": true,
"getCities": true,
"useCityInfo": true
}
}

97
.eslintrc.cjs Normal file
View File

@ -0,0 +1,97 @@
module.exports = {
env: {
browser: true,
es2021: true,
node: true,
},
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:vue/vue3-essential',
// eslint-plugin-import 插件, @see https://www.npmjs.com/package/eslint-plugin-import
'plugin:import/recommended',
// eslint-config-airbnb-base 插件 已经改用 eslint-config-standard 插件
'standard',
// 1. 接入 prettier 的规则
'prettier',
'plugin:prettier/recommended',
'./.eslintrc-auto-import.json',
],
overrides: [
{
env: {
node: true,
},
files: ['.eslintrc.{js,cjs}'],
parserOptions: {
sourceType: 'script',
},
},
],
parserOptions: {
ecmaVersion: 'latest',
parser: '@typescript-eslint/parser',
sourceType: 'module',
},
plugins: [
'@typescript-eslint',
'vue',
// 2. 加入 prettier 的 eslint 插件
'prettier',
// eslint-import-resolver-typescript 插件,@see https://www.npmjs.com/package/eslint-import-resolver-typescript
'import',
],
rules: {
// 3. 注意要加上这一句,开启 prettier 自动修复的功能
'prettier/prettier': 'error',
// turn on errors for missing imports
'import/no-unresolved': 'off',
// 对后缀的检测,否则 import 一个ts文件也会报错需要手动添加'.ts', 增加了下面的配置后就不用了
'import/extensions': [
'error',
'ignorePackages',
{ js: 'never', jsx: 'never', ts: 'never', tsx: 'never' },
],
// 只允许1个默认导出关闭否则不能随意export xxx
'import/prefer-default-export': ['off'],
'no-console': ['off'],
// 'no-unused-vars': ['off'],
// '@typescript-eslint/no-unused-vars': ['off'],
// 解决vite.config.ts报错问题
'import/no-extraneous-dependencies': 'off',
'no-plusplus': 'off',
'no-shadow': 'off',
'vue/multi-word-component-names': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'no-underscore-dangle': 'off',
'no-use-before-define': 'off',
'no-undef': 'off',
'no-unused-vars': 'off',
'no-param-reassign': 'off',
'@typescript-eslint/no-unused-vars': 'off',
// 避免 `eslint` 对于 `typescript` 函数重载的误报
'no-redeclare': 'off',
'@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'],
},
'import/resolver': {
typescript: {},
},
},
globals: {
$t: true,
uni: true,
UniApp: true,
wx: true,
WechatMiniprogram: true,
getCurrentPages: true,
UniHelper: true,
Page: true,
App: true,
NodeJS: true,
},
}

41
.github/workflows/auto-merge.yml vendored Normal file
View File

@ -0,0 +1,41 @@
name: Auto Merge Base to Other Branches
on:
push:
branches:
- base
workflow_dispatch: # 手动触发
jobs:
auto-merge:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
fetch-depth: 0
token: ${{ secrets.GH_TOKEN_AUTO_MERGE }}
- name: Merge base into main
run: |
git config user.name "GitHub Actions"
git config user.email "actions@github.com"
git checkout main
git merge base --no-ff -m "Auto merge base into main"
git push origin main
- name: Merge base into i18n
run: |
git config user.name "GitHub Actions"
git config user.email "actions@github.com"
git checkout i18n
git merge base --no-ff -m "Auto merge base into i18n"
git push origin i18n
- name: Merge base into tabbar
run: |
git config user.name "GitHub Actions"
git config user.email "actions@github.com"
git checkout tabbar
git merge base --no-ff -m "Auto merge base into tabbar"
git push origin tabbar

42
.gitignore vendored Normal file
View File

@ -0,0 +1,42 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
*.local
# Editor directories and files
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
.hbuilderx
.stylelintcache
.eslintcache
docs/.vitepress/dist
docs/.vitepress/cache
# lock 文件还是不要了,我主要的版本写死就好了
# pnpm-lock.yaml
# package-lock.json
# TIPS如果某些文件已经加入了版本管理现在重新加入 .gitignore 是不生效的,需要执行下面的操作
# `git rm -r --cached .` 然后提交 commit 即可。
# git rm -r --cached file1 file2 ## 针对某些文件
# git rm -r --cached dir1 dir2 ## 针对某些文件夹
# git rm -r --cached . ## 针对所有文件
# 更新 uni-app 官方版本
# npx @dcloudio/uvm@latest

5
.husky/commit-msg Normal file
View File

@ -0,0 +1,5 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
# Run the commit-msg hook
npx --no-install commitlint --edit

5
.husky/pre-commit Normal file
View File

@ -0,0 +1,5 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
# Run the pre-commit hook
npx --no-install -- lint-staged

6
.npmrc Normal file
View File

@ -0,0 +1,6 @@
# registry = https://registry.npmjs.org
registry = https://registry.npmmirror.com
strict-peer-dependencies=false
auto-install-peers=true
shamefully-hoist=true

12
.prettierignore Normal file
View File

@ -0,0 +1,12 @@
# unplugin-auto-import 生成的类型文件,每次提交都改变,所以加入这里吧,与 .gitignore 配合使用
auto-import.d.ts
# vite-plugin-uni-pages 生成的类型文件,每次切换分支都一堆不同的,所以直接 .gitignore
uni-pages.d.ts
# 插件生成的文件
src/pages.json
src/manifest.json
# 忽略自动生成文件
src/service/app/**

19
.prettierrc.cjs Normal file
View File

@ -0,0 +1,19 @@
// @see https://prettier.io/docs/en/options
module.exports = {
singleQuote: true,
printWidth: 100,
tabWidth: 2,
useTabs: false,
semi: false,
trailingComma: 'all',
endOfLine: 'auto',
htmlWhitespaceSensitivity: 'ignore',
overrides: [
{
files: '*.json',
options: {
trailingComma: 'none',
},
},
],
}

1
.stylelintignore Normal file
View File

@ -0,0 +1 @@
src/uni_modules/

58
.stylelintrc.cjs Normal file
View File

@ -0,0 +1,58 @@
// .stylelintrc.cjs
module.exports = {
root: true,
extends: [
// stylelint-config-standard 替换成了更宽松的 stylelint-config-recommended
'stylelint-config-recommended',
// stylelint-config-standard-scss 替换成了更宽松的 stylelint-config-recommended-scss
'stylelint-config-recommended-scss',
'stylelint-config-recommended-vue/scss',
'stylelint-config-html/vue',
'stylelint-config-recess-order',
],
plugins: ['stylelint-prettier'],
overrides: [
// 扫描 .vue/html 文件中的<style>标签内的样式
{
files: ['**/*.{vue,html}'],
customSyntax: 'postcss-html',
},
{
files: ['**/*.{css,scss}'],
customSyntax: 'postcss-scss',
},
],
// 自定义规则
rules: {
'prettier/prettier': true,
// 允许 global 、export 、v-deep等伪类
'selector-pseudo-class-no-unknown': [
true,
{
ignorePseudoClasses: ['global', 'export', 'v-deep', 'deep'],
},
],
'unit-no-unknown': [
true,
{
ignoreUnits: ['rpx'],
},
],
// 处理小程序page标签不认识的问题
'selector-type-no-unknown': [
true,
{
ignoreTypes: ['page'],
},
],
'comment-empty-line-before': 'never', // never|always|always-multi-line|never-multi-line
'custom-property-empty-line-before': 'never',
'no-empty-source': null,
'comment-no-empty': null,
'no-duplicate-selectors': null,
'scss/comment-no-empty': null,
'selector-class-pattern': null,
'font-family-no-missing-generic-family-keyword': null,
},
}

18
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,18 @@
{
"recommendations": [
"vue.volar",
"stylelint.vscode-stylelint",
"esbenp.prettier-vscode",
"dbaeumer.vscode-eslint",
"antfu.unocss",
"antfu.iconify",
"evils.uniapp-vscode",
"uni-helper.uni-helper-vscode",
"uni-helper.uni-app-schemas-vscode",
"uni-helper.uni-highlight-vscode",
"uni-helper.uni-ui-snippets-vscode",
"uni-helper.uni-app-snippets-vscode",
"mrmlnc.vscode-json5",
"streetsidesoftware.code-spell-checker"
]
}

62
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,62 @@
{
// prettier
"editor.defaultFormatter": "esbenp.prettier-vscode",
//
"editor.formatOnSave": true,
//
"editor.codeActionsOnSave": {
"source.fixAll": "explicit",
"source.fixAll.eslint": "explicit",
"source.fixAll.stylelint": "explicit"
},
// stylelint
"stylelint.validate": ["css", "scss", "vue", "html"], // package.jsonscripts
"stylelint.enable": true,
"css.validate": false,
"less.validate": false,
"scss.validate": false,
"[shellscript]": {
"editor.defaultFormatter": "foxundermoon.shell-format"
},
"[dotenv]": {
"editor.defaultFormatter": "foxundermoon.shell-format"
},
"[vue]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[jsonc]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
//
"files.associations": {
"pages.json": "jsonc", // pages.json
"manifest.json": "jsonc" // manifest.json
},
"cSpell.words": [
"Aplipay",
"climblee",
"commitlint",
"dcloudio",
"iconfont",
"qrcode",
"refresherrefresh",
"scrolltolower",
"tabbar",
"Toutiao",
"unibest",
"uvui",
"Wechat",
"WechatMiniprogram",
"Weixin"
],
"typescript.tsdk": "node_modules\\typescript\\lib",
"explorer.fileNesting.enabled": true,
"explorer.fileNesting.expand": false,
"explorer.fileNesting.patterns": {
"package.json": "pnpm-lock.yaml,pnpm-workspace.yaml,LICENSE,.gitattributes,.gitignore,.gitpod.yml,CNAME,.npmrc,.browserslistrc",
".eslintrc.cjs": ".eslintignore,.prettierignore,.stylelintignore,.commitlintrc.*,.prettierrc.*,.stylelintrc.*,.eslintrc-auto-import.json,.editorconfig,.commitlint.cjs"
}
}

56
.vscode/vue3.code-snippets vendored Normal file
View File

@ -0,0 +1,56 @@
{
// Place your unibest 工作区 snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and
// description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope
// is left empty or omitted, the snippet gets applied to all languages. The prefix is what is
// used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders.
// Placeholders with the same ids are connected.
// Example:
// "Print to console": {
// "scope": "javascript,typescript",
// "prefix": "log",
// "body": [
// "console.log('$1');",
// "$2"
// ],
// "description": "Log output to console"
// }
"Print unibest Vue3 SFC": {
"scope": "vue",
"prefix": "v3",
"body": [
"<route lang=\"json5\" type=\"page\">",
"{",
" layout: 'default',",
" style: {",
" navigationBarTitleText: '$1',",
" },",
"}",
"</route>\n",
"<template>",
" <view class=\"\">$2</view>",
"</template>\n",
"<script lang=\"ts\" setup>",
"//$3",
"</script>\n",
"<style lang=\"scss\" scoped>",
"//$4",
"</style>\n",
],
},
"Print unibest style": {
"scope": "vue",
"prefix": "st",
"body": ["<style lang=\"scss\" scoped>", "//", "</style>\n"],
},
"Print unibest script": {
"scope": "vue",
"prefix": "sc",
"body": ["<script lang=\"ts\" setup>", "//$3", "</script>\n"],
},
"Print unibest template": {
"scope": "vue",
"prefix": "te",
"body": ["<template>", " <view class=\"\">$1</view>", "</template>\n"],
},
}

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 菲鸽
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

94
README.md Normal file
View File

@ -0,0 +1,94 @@
<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` 内置了 `约定式路由`、`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 也请使用新地址,否则无法合并。
## 平台兼容性
| H5 | IOS | 安卓 | 微信小程序 | 字节小程序 | 快手小程序 | 支付宝小程序 | 钉钉小程序 | 百度小程序 |
| --- | --- | ---- | ---------- | ---------- | ---------- | ------------ | ---------- | ---------- |
| √ | √ | √ | √ | √ | √ | √ | √ | √ |
注意每种 `UI框架` 支持的平台有所不同,详情请看各 `UI框架` 的官网,也可以看 `unibest` 文档。
## ⚙️ 环境
- node>=18
- pnpm>=7.30
- Vue Official>=2.1.10
- TypeScript>=5.0
## &#x1F4C2; 快速开始
执行 `pnpm create unibest` 创建项目
执行 `pnpm i` 安装依赖
执行 `pnpm dev` 运行 `H5`
## 📦 运行(支持热更新)
- 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) 2025 菲鸽
## 捐赠
<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>

26
env/.env vendored Normal file
View File

@ -0,0 +1,26 @@
VITE_APP_TITLE = '六维志愿'
VITE_APP_PORT = 9000
VITE_UNI_APPID = 'H57F2ACE4'
VITE_WX_APPID = 'wxa2abb91f64032a2b'
# h5部署网站的base配置到 manifest.config.ts 里的 h5.router.base
VITE_APP_PUBLIC_BASE=
VITE_SERVER_BASEURL = 'https://api.v3.ycymedu.com'
VITE_STATIC_SERVER_BASEURL = "https://api.static.ycymedu.com"
VITE_UPLOAD_BASEURL = 'https://api.v3.ycymedu.com/upload'
# 有些同学可能需要在微信小程序里面根据 develop、trial、release 分别设置上传地址,参考代码如下。
# 下面的变量如果没有设置,会默认使用 VITE_SERVER_BASEURL or VITE_UPLOAD_BASEURL
VITE_SERVER_BASEURL__WEIXIN_DEVELOP = 'https://api.v3.ycymedu.com'
VITE_SERVER_BASEURL__WEIXIN_TRIAL = 'https://api.v3.ycymedu.com'
VITE_SERVER_BASEURL__WEIXIN_RELEASE = 'https://api.v3.ycymedu.com'
VITE_UPLOAD_BASEURL__WEIXIN_DEVELOP = 'https://api.v3.ycymedu.com'
VITE_UPLOAD_BASEURL__WEIXIN_TRIAL = 'https://api.v3.ycymedu.com'
VITE_UPLOAD_BASEURL__WEIXIN_RELEASE = 'https://api.v3.ycymedu.com'
# h5是否需要配置代理
VITE_APP_PROXY=false
VITE_APP_PROXY_PREFIX = '/api'

6
env/.env.development vendored Normal file
View File

@ -0,0 +1,6 @@
# 变量必须以 VITE_ 为前缀才能暴露给外部读取
NODE_ENV = 'development'
# 是否去除console 和 debugger
VITE_DELETE_CONSOLE = false
# 是否开启sourcemap
VITE_SHOW_SOURCEMAP = true

6
env/.env.production vendored Normal file
View File

@ -0,0 +1,6 @@
# 变量必须以 VITE_ 为前缀才能暴露给外部读取
NODE_ENV = 'development'
# 是否去除console 和 debugger
VITE_DELETE_CONSOLE = true
# 是否开启sourcemap
VITE_SHOW_SOURCEMAP = false

4
env/.env.test vendored Normal file
View File

@ -0,0 +1,4 @@
# 变量必须以 VITE_ 为前缀才能暴露给外部读取
NODE_ENV = 'development'
# 是否去除console 和 debugger
VITE_DELETE_CONSOLE = false

BIN
favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

26
index.html Normal file
View File

@ -0,0 +1,26 @@
<!doctype html>
<html build-time="%BUILD_TIME%">
<head>
<meta charset="UTF-8" />
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
<script>
var coverSupport =
'CSS' in window &&
typeof CSS.supports === 'function' &&
(CSS.supports('top: env(a)') || CSS.supports('top: constant(a)'))
document.write(
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
(coverSupport ? ', viewport-fit=cover' : '') +
'" />',
)
</script>
<title>unibest</title>
<!--preload-links-->
<!--app-context-->
</head>
<body>
<div id="app"><!--app-html--></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

107
manifest.config.ts Normal file
View File

@ -0,0 +1,107 @@
// manifest.config.ts
import { defineManifestConfig } from '@uni-helper/vite-plugin-uni-manifest'
import path from 'node:path'
import { loadEnv } from 'vite'
// 获取环境变量的范例
const env = loadEnv(process.env.NODE_ENV!, path.resolve(process.cwd(), 'env'))
const {
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,
mode: 'history',
},
},
/* 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: [
'<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>',
'<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>',
'<uses-permission android:name="android.permission.VIBRATE"/>',
'<uses-permission android:name="android.permission.READ_LOGS"/>',
'<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>',
'<uses-feature android:name="android.hardware.camera.autofocus"/>',
'<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>',
'<uses-permission android:name="android.permission.CAMERA"/>',
'<uses-permission android:name="android.permission.GET_ACCOUNTS"/>',
'<uses-permission android:name="android.permission.READ_PHONE_STATE"/>',
'<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>',
'<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"/>',
],
},
/* ios打包配置 */
ios: {},
/* SDK配置 */
sdkConfigs: {},
/* 图标配置 */
icons: {
android: {},
ios: {},
},
},
},
/* 快应用特有相关 */
quickapp: {},
/* 小程序特有相关 */
'mp-weixin': {
appid: VITE_WX_APPID,
setting: {
urlCheck: false,
},
usingComponents: true,
// __usePrivacyCheck__: true,
},
'mp-alipay': {
usingComponents: true,
styleIsolation: 'shared',
},
'mp-baidu': {
usingComponents: true,
},
'mp-toutiao': {
usingComponents: true,
},
uniStatistics: {
enable: false,
},
vueVersion: '3',
})

View File

@ -0,0 +1,13 @@
import type { GenerateServiceProps } from 'openapi-ts-request'
export default [
{
schemaPath: 'http://petstore.swagger.io/v2/swagger.json',
serversPath: './src/service/app',
requestLibPath: `import request from '@/utils/request';\n import { CustomRequestOptions } from '@/interceptors/request';`,
requestOptionsType: 'CustomRequestOptions',
isGenReactQuery: true,
reactQueryMode: 'vue',
isGenJavaScript: false,
},
] as GenerateServiceProps[]

175
package.json Normal file
View File

@ -0,0 +1,175 @@
{
"name": "volunteer-4",
"type": "commonjs",
"version": "2.5.5",
"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/",
"engines": {
"node": ">=18",
"pnpm": ">=7.30"
},
"scripts": {
"preinstall": "npx only-allow pnpm",
"uvm": "npx @dcloudio/uvm@latest",
"uvm-rm": "node ./scripts/postupgrade.js",
"postuvm": "echo upgrade uni-app success!",
"dev:app": "uni -p app",
"dev:app-android": "uni -p app-android",
"dev:app-ios": "uni -p app-ios",
"dev:custom": "uni -p",
"dev": "uni",
"dev:h5": "uni",
"dev:h5:ssr": "uni --ssr",
"dev:mp": "uni -p mp-weixin",
"dev:mp-alipay": "uni -p mp-alipay",
"dev:mp-baidu": "uni -p mp-baidu",
"dev:mp-jd": "uni -p mp-jd",
"dev:mp-kuaishou": "uni -p mp-kuaishou",
"dev:mp-lark": "uni -p mp-lark",
"dev:mp-qq": "uni -p mp-qq",
"dev:mp-toutiao": "uni -p mp-toutiao",
"dev:mp-weixin": "uni -p mp-weixin",
"dev:mp-xhs": "uni -p mp-xhs",
"dev:quickapp-webview": "uni -p quickapp-webview",
"dev:quickapp-webview-huawei": "uni -p quickapp-webview-huawei",
"dev:quickapp-webview-union": "uni -p quickapp-webview-union",
"build:app": "uni build -p app",
"build:app-android": "uni build -p app-android",
"build:app-ios": "uni build -p app-ios",
"build:custom": "uni build -p",
"build:h5": "uni build",
"build": "uni build",
"build:h5:ssr": "uni build --ssr",
"build:mp-alipay": "uni build -p mp-alipay",
"build:mp": "uni build -p mp-weixin",
"build:mp-baidu": "uni build -p mp-baidu",
"build:mp-jd": "uni build -p mp-jd",
"build:mp-kuaishou": "uni build -p mp-kuaishou",
"build:mp-lark": "uni build -p mp-lark",
"build:mp-qq": "uni build -p mp-qq",
"build:mp-toutiao": "uni build -p mp-toutiao",
"build:mp-weixin": "uni build -p mp-weixin",
"build:mp-xhs": "uni build -p mp-xhs",
"build:quickapp-webview": "uni build -p quickapp-webview",
"build:quickapp-webview-huawei": "uni build -p quickapp-webview-huawei",
"build:quickapp-webview-union": "uni build -p quickapp-webview-union",
"prepare": "git init && husky install ",
"type-check": "vue-tsc --noEmit",
"cz": "czg",
"openapi-ts-request": "openapi-ts"
},
"lint-staged": {
"**/*.{html,vue,ts,cjs,json,md}": [
"prettier --write"
],
"**/*.{vue,js,ts,jsx,tsx}": [
"eslint --cache --fix"
],
"**/*.{vue,css,scss,html}": [
"stylelint --fix"
]
},
"resolutions": {
"bin-wrapper": "npm:bin-wrapper-china"
},
"dependencies": {
"@dcloudio/uni-app": "3.0.0-4020920240930001",
"@dcloudio/uni-app-harmony": "3.0.0-4020920240930001",
"@dcloudio/uni-app-plus": "3.0.0-4020920240930001",
"@dcloudio/uni-components": "3.0.0-4020920240930001",
"@dcloudio/uni-h5": "3.0.0-4020920240930001",
"@dcloudio/uni-mp-alipay": "3.0.0-4020920240930001",
"@dcloudio/uni-mp-baidu": "3.0.0-4020920240930001",
"@dcloudio/uni-mp-jd": "3.0.0-4020920240930001",
"@dcloudio/uni-mp-kuaishou": "3.0.0-4020920240930001",
"@dcloudio/uni-mp-lark": "3.0.0-4020920240930001",
"@dcloudio/uni-mp-qq": "3.0.0-4020920240930001",
"@dcloudio/uni-mp-toutiao": "3.0.0-4020920240930001",
"@dcloudio/uni-mp-weixin": "3.0.0-4020920240930001",
"@dcloudio/uni-mp-xhs": "3.0.0-4020920240930001",
"@dcloudio/uni-quickapp-webview": "3.0.0-4020920240930001",
"@tanstack/vue-query": "^5.62.16",
"abortcontroller-polyfill": "^1.7.8",
"dayjs": "1.11.10",
"pinia": "2.0.36",
"pinia-plugin-persistedstate": "3.2.1",
"pinyin-pro": "^3.26.0",
"qs": "6.5.3",
"vue": "3.4.21",
"wot-design-uni": "^1.4.0",
"z-paging": "^2.8.4"
},
"devDependencies": {
"@commitlint/cli": "^18.6.1",
"@commitlint/config-conventional": "^18.6.3",
"@dcloudio/types": "^3.4.14",
"@dcloudio/uni-automator": "3.0.0-4020920240930001",
"@dcloudio/uni-cli-shared": "3.0.0-4020920240930001",
"@dcloudio/uni-stacktracey": "3.0.0-4020920240930001",
"@dcloudio/vite-plugin-uni": "3.0.0-4020920240930001",
"@esbuild/darwin-arm64": "0.20.2",
"@esbuild/darwin-x64": "0.20.2",
"@iconify-json/carbon": "^1.2.4",
"@rollup/rollup-darwin-x64": "^4.28.0",
"@types/node": "^20.17.9",
"@types/wechat-miniprogram": "^3.4.8",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"@uni-helper/uni-types": "1.0.0-alpha.3",
"@uni-helper/vite-plugin-uni-layouts": "^0.1.10",
"@uni-helper/vite-plugin-uni-manifest": "^0.2.7",
"@uni-helper/vite-plugin-uni-pages": "0.2.20",
"@uni-helper/vite-plugin-uni-platform": "^0.0.4",
"@unocss/preset-legacy-compat": "^0.59.4",
"@vue/runtime-core": "^3.5.13",
"@vue/tsconfig": "^0.1.3",
"autoprefixer": "^10.4.20",
"commitlint": "^18.6.1",
"czg": "^1.9.4",
"eslint": "^8.57.1",
"eslint-config-prettier": "^9.1.0",
"eslint-config-standard": "^17.1.0",
"eslint-import-resolver-typescript": "^3.7.0",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-vue": "^9.32.0",
"husky": "^8.0.3",
"lint-staged": "^15.2.10",
"openapi-ts-request": "^1.1.2",
"postcss": "^8.4.49",
"postcss-html": "^1.7.0",
"postcss-scss": "^4.0.9",
"rollup-plugin-visualizer": "^5.12.0",
"sass": "1.77.8",
"stylelint": "^16.11.0",
"stylelint-config-html": "^1.1.0",
"stylelint-config-recess-order": "^4.6.0",
"stylelint-config-recommended": "^14.0.1",
"stylelint-config-recommended-scss": "^14.1.0",
"stylelint-config-recommended-vue": "^1.5.0",
"stylelint-prettier": "^5.0.2",
"svg-sprite-loader": "^6.0.11",
"terser": "^5.36.0",
"typescript": "^5.7.2",
"unocss": "^0.58.9",
"unocss-applet": "^0.7.8",
"unplugin-auto-import": "^0.17.8",
"vite": "5.2.8",
"vite-plugin-restart": "^0.4.2",
"vue-tsc": "^1.8.27"
}
}

189
pages.config.ts Normal file
View File

@ -0,0 +1,189 @@
import { defineUniPages } from '@uni-helper/vite-plugin-uni-pages'
export default defineUniPages({
globalStyle: {
navigationBarTextStyle: 'black',
navigationBarTitleText: '六纬志愿',
navigationBarBackgroundColor: '#fff',
backgroundColor: '#F8F8F8',
},
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',
},
},
tabBar: {
color: '#7A7E83',
selectedColor: '#3370ff',
borderStyle: 'white',
backgroundColor: '#ffffff',
height: '60px',
fontSize: '10px',
iconWidth: '16px',
spacing: '3px',
list: [
{
iconPath: 'static/tabBar/home.png',
selectedIconPath: 'static/tabBar/home-active.png',
pagePath: 'pages/home/index/index',
text: '首页',
},
{
iconPath: 'static/tabBar/news.png',
selectedIconPath: 'static/tabBar/news-active.png',
pagePath: 'pages/news/index/index',
text: '测评',
},
{
iconPath: 'static/tabBar/place.png',
selectedIconPath: 'static/tabBar/place-active.png',
pagePath: 'pages/place/index/index',
text: '专家',
},
{
iconPath: 'static/tabBar/center.png',
selectedIconPath: 'static/tabBar/center-active.png',
pagePath: 'pages/ucenter/index/index',
text: '我的',
},
],
},
pages: [
{
path: 'pages/home/index/index',
type: 'home',
style: {
navigationBarTitleText: '六维志愿',
navigationStyle: 'custom',
},
},
{
path: 'pages/place/index/index',
type: 'page',
style: {
navigationBarTitleText: '专家',
},
},
{
path: 'pages/aiService/index/index',
type: 'page',
style: {
navigationBarTitleText: '六维管家',
},
},
{
path: 'pages/news/index/index',
type: 'page',
style: {
navigationBarTitleText: '测评',
},
},
{
path: 'pages/ucenter/index/index',
type: 'page',
style: {
navigationBarTitleText: '我的',
},
},
{
path: 'pages/home/city/index',
type: 'page',
style: {
navigationStyle: 'custom',
navigationBarTitleText: '城市',
},
},
{
path: 'pages/home/college/index',
type: 'page',
style: {
navigationBarTitleText: '大学',
},
},
{
path: 'pages/home/career/index',
type: 'page',
style: {
navigationBarTitleText: '职业',
},
},
{
path: 'pages/home/distinguish/index',
type: 'page',
style: {
navigationBarTitleText: '大学甄别',
},
},
{
path: 'pages/home/evaluation/index',
type: 'page',
style: {
navigationBarTitleText: '专业测评',
},
},
{
path: 'pages/home/expand/index',
type: 'page',
style: {
navigationBarTitleText: '查扩缩招',
},
},
{
path: 'pages/home/line/index',
type: 'page',
style: {
navigationBarTitleText: '批次线',
},
},
{
path: 'pages/home/major/index',
type: 'page',
style: {
navigationBarTitleText: '专业',
},
},
{
path: 'pages/home/rank/index',
type: 'page',
style: {
navigationBarTitleText: '排名',
},
},
{
path: 'pages/home/inputScore/index',
type: 'page',
style: {
navigationStyle: 'custom',
navigationBarTitleText: '城市',
},
},
{
path: 'pages/customerService/index/index',
type: 'page',
style: {
navigationBarTitleText: '在线客服',
navigationStyle: 'custom',
},
},
],
preloadRule: {
'pages/home/index/index': {
network: 'all',
packages: ['__APP__'],
},
},
condition: {
current: 0,
list: [
{
name: '',
path: '',
query: '',
},
],
},
})

14815
pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load Diff

28
project.config.json Normal file
View File

@ -0,0 +1,28 @@
{
"appid": "wxd9369129a1e69342",
"compileType": "miniprogram",
"libVersion": "3.7.8",
"packOptions": {
"ignore": [],
"include": []
},
"setting": {
"coverView": true,
"es6": true,
"postcss": true,
"minified": true,
"enhance": true,
"showShadowRootInWxmlPanel": true,
"packNpmRelationList": [],
"babelSetting": {
"ignore": [],
"disablePlugins": [],
"outputPath": ""
}
},
"condition": {},
"editorSetting": {
"tabIndent": "insertSpaces",
"tabSize": 2
}
}

View File

@ -0,0 +1,7 @@
{
"description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html",
"projectname": "volunteer-4",
"setting": {
"compileHotReLoad": true
}
}

BIN
screenshots/pay-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

BIN
screenshots/pay-2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

36
scripts/postupgrade.js Normal file
View File

@ -0,0 +1,36 @@
// # 执行 `pnpm upgrade` 后会升级 `uniapp` 相关依赖
// # 在升级完后,会自动添加很多无用依赖,这需要删除以减小依赖包体积
// # 只需要执行下面的命令即可
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { exec } = require('child_process')
// 定义要执行的命令
const dependencies = [
'@dcloudio/uni-app-harmony',
// TODO: 如果需要某个平台的小程序,请手动删除或注释掉
'@dcloudio/uni-mp-alipay',
'@dcloudio/uni-mp-baidu',
'@dcloudio/uni-mp-jd',
'@dcloudio/uni-mp-kuaishou',
'@dcloudio/uni-mp-lark',
'@dcloudio/uni-mp-qq',
'@dcloudio/uni-mp-toutiao',
'@dcloudio/uni-mp-xhs',
'@dcloudio/uni-quickapp-webview',
// i18n模板要注释掉下面的
'vue-i18n',
]
// 使用exec执行命令
exec(`pnpm un ${dependencies.join(' ')}`, (error, stdout, stderr) => {
if (error) {
// 如果有错误,打印错误信息
console.error(`执行出错: ${error}`)
return
}
// 打印正常输出
console.log(`stdout: ${stdout}`)
// 如果有错误输出,也打印出来
console.error(`stderr: ${stderr}`)
})

62
src/App.vue Normal file
View File

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

0
src/components/.gitkeep Normal file
View File

View File

@ -0,0 +1,100 @@
<template>
<!-- <view
class="tabbar-container fixed bottom-0 left-0 w-full h-[120rpx] flex items-center justify-around text-[#999999] z-[200] bg-white py-[10rpx] px-0"
:style="`padding-bottom:${safeAreaInsets.bottom}px;`"
>
<block class="flex items-center w-full">
<view
class="tabbar-item h-[100rpx] flex flex-col justify-center w-full items-center text-center"
v-for="(item, index) in tabbarList"
:key="index"
:class="[item.centerItem ? 'center-item' : '']"
@click.stop="changeItem(item)"
>
<view class="item-top w-[48rpx] h-[48rpx] p-[10rpx]">
<image
class="w-full h-full object-container"
:src="currentPage == item.id ? item.selectIcon : item.icon"
></image>
</view>
<view
class="item-bottom text-[20rpx] mt-[6rpx]"
:class="[currentPage == item.id ? 'item-active text-[#3370ff]' : '']"
>
<text>{{ item.text }}</text>
</view>
</view>
</block>
</view> -->
<wd-tabbar :bordered="false" safeAreaInsetBottom :placeholder="true" fixed>
<view
class="tabbar-item h-[100rpx] flex flex-col justify-center w-full items-center text-center"
v-for="(item, index) in tabbarList"
:key="index"
:class="[item.centerItem ? 'center-item' : '']"
@click.stop="changeItem(item)"
>
<view class="item-top w-[48rpx] h-[48rpx] p-[10rpx]">
<image
class="w-full h-full object-container"
:src="currentPage == item.id ? item.selectIcon : item.icon"
></image>
</view>
<view
class="item-bottom text-[20rpx] mt-[6rpx]"
:class="[currentPage == item.id ? 'item-active text-[#3370ff]' : '']"
>
<text>{{ item.text }}</text>
</view>
</view>
</wd-tabbar>
</template>
<script setup lang="ts">
import { TabesItem } from '@/service/app/types'
import { tabbarList } from '@/hooks/useTabbarList'
import useNavbarWeixin from '@/hooks/useNavbarWeixin'
const { safeAreaInsets } = useNavbarWeixin()
const tabbar = ref(1)
defineProps({
currentPage: {
type: Number,
default: 0,
},
})
const changeItem = (item: TabesItem) => {
uni.switchTab({
url: item.path,
})
}
onBeforeMount(() => {
uni.hideTabBar()
})
</script>
<style scoped>
view {
box-sizing: border-box;
padding: 0;
margin: 0;
}
.center-item {
position: relative;
}
.center-item .item-top {
width: 98rpx;
height: 98rpx;
}
.center-item .item-bottom {
position: absolute;
bottom: 5rpx;
}
</style>

View File

@ -0,0 +1,32 @@
<template>
<wd-fab :draggable="true" :expandable="false" :gap="{ bottom: 200 }">
<template #trigger>
<view class="btn-wrapper" @click.stop="handleClick">
<image
class="w-full h-full rounded-full"
src="/static/images/customerService/customerService.svg"
></image>
</view>
</template>
</wd-fab>
</template>
<script lang="ts" setup>
import useNavbarWeixin from '@/hooks/useNavbarWeixin'
const { safeAreaInsets } = useNavbarWeixin()
const handleClick = () => {
uni.navigateTo({
url: '/pages/customerService/index/index',
})
}
</script>
<style lang="scss" scoped>
.btn-wrapper {
width: 128rpx;
height: 128rpx;
border-radius: 50%;
}
</style>

View File

@ -0,0 +1,37 @@
<template>
<view class="mx-5 rounded-lg bg-white px-[32rpx] py-[56rpx]">
<view
class="flex items-center justify-between mx-[34rpx] py-[30rpx]"
style="border-bottom: 2rpx solid #ededed"
@click="handleChange"
>
<text class="text-[40rpx] text-[#636363]">输入模考/高考成绩</text>
<image class="w-[42rpx] h-[39rpx]" src="/static/images/home/pen.svg"></image>
</view>
<view class="mt-[56rpx] flex items-center justify-between">
<wd-button
custom-class="w-[240rpx] h-[88rpx] border-[#1580FF] text-[#1580FF] text-[28rpx] font-normal mr-[32rpx]"
:round="false"
plain
>
一键填报
</wd-button>
<wd-button
:round="false"
custom-class="w-[350rpx] h-[88rpx] text-[#fff] text-[28rpx] bg-[#1580FF] font-normal"
>
智能填报
</wd-button>
</view>
</view>
</template>
<script lang="ts" setup>
const value = ref('')
const handleChange = () => {
uni.navigateTo({
url: '/pages/home/inputScore/index',
})
}
</script>

View File

@ -0,0 +1,28 @@
<template>
<view class="mx-[36rpx] mt-[44rpx]">
<view
class="flex items-center justify-between mb-[30rpx]"
hover-class="none"
:hover-stop-propagation="false"
>
<text class="text-[32rpx] text-[#333333] font-semibold">高考资讯</text>
<image class="w-[40rpx] h-[40rpx]" src="/static/images/home/right.svg"></image>
</view>
<view class="my-[30rpx]" hover-class="none" :hover-stop-propagation="false">
<view
class="truncate flex flex-col p-[32rpx]"
style="border-bottom: 2rpx solid #eee"
v-for="item in 3"
:key="item"
>
<text class="truncate text-[28rpx] text-[#333333] font-normal mb-[16rpx] max-w-[70%]">
家长请注意六纬志愿VIP卡即将恢复家长请注意六纬志愿VIP卡即将恢复家长请注意六纬志愿VIP卡即将恢复家长请注意六纬志愿VIP卡即将恢复
</text>
<text class="text-[24rpx] color-[#999999] font-normal">2024.12.04</text>
</view>
</view>
</view>
</template>
<script lang="ts" setup></script>

View File

@ -0,0 +1,121 @@
<template>
<view class="mx-[36rpx] mt-[44rpx]" hover-class="none" :hover-stop-propagation="false">
<view
class="flex items-center justify-between mb-[30rpx]"
hover-class="none"
:hover-stop-propagation="false"
>
<text class="text-[32rpx] text-[#333333] font-semibold">热门排行榜</text>
<image class="w-[40rpx] h-[40rpx]" src="/static/images/home/right.svg"></image>
</view>
<view
class="flex items-center w-full overflow-auto gap-[16rpx] hot-rank-outer"
hover-class="none"
:hover-stop-propagation="false"
>
<view
class="hot-rank-item flex-none pt-[32rpx] pb-[38rpx] px-[32rpx]"
hover-class="none"
:hover-stop-propagation="false"
v-for="item in swiperList"
:key="item.id"
>
<text class="font-semibold text-[#303030] text-[32rpx] inline-block">
{{ item.name }}
</text>
<view
class="flex items-center justify-left mt-[30rpx]"
v-for="(item, index) in 3"
:key="index"
>
<text class="font-[28rpx] text-[#999999] font-normal mr-[10rpx]">
{{ index + 1 }}
</text>
<image
class="w-[80rpx] h-[80rpx] rounded-full flex-none mr-[16rpx]"
:src="`/static/images/home/rank.svg`"
></image>
<view class="truncate flex flex-col" hover-class="none">
<text class="font-normal text-[#333333] text-[28rpx] truncate">
北京大学 北京大学北京大学北京大学
</text>
<text class="text-[22rpx] text-[#999999] font-normal mt-[10rpx]">北京.综合类</text>
</view>
</view>
</view>
</view>
</view>
</template>
<script lang="ts" setup>
// QS
const swiperList = [
{ id: 1, name: '武书联', type: '1' },
{ id: 2, name: '校友会', type: '2' },
{ id: 3, name: '软科', type: '3' },
{ id: 4, name: 'QS', type: '4' },
]
</script>
<style lang="scss" scoped>
.hot-rank-item {
width: 292rpx;
border: 2rpx solid;
}
.hot-rank-outer .hot-rank-item:nth-child(1) {
background: linear-gradient(
180deg,
#dee7f8 0%,
rgba(239, 244, 251, 0) 46%,
rgba(239, 244, 251, 0) 100%
);
border-image: linear-gradient(
180deg,
rgba(201.8750050663948, 221.00000202655792, 255, 1),
rgba(233.7500050663948, 241.39999777078629, 255, 1)
)
2 2;
}
.hot-rank-outer .hot-rank-item:nth-child(2) {
background: linear-gradient(
180deg,
#ddf7ea 0%,
rgba(234, 250, 241, 0) 46%,
rgba(234, 250, 241, 0) 100%
);
border-image: linear-gradient(
180deg,
rgba(205.5883178114891, 245.07227271795273, 225.3302800655365, 1),
rgba(221.00000202655792, 247.00000047683716, 234.00000125169754, 1)
)
2 2;
}
.hot-rank-outer .hot-rank-item:nth-child(3) {
background: linear-gradient(
180deg,
#f7e7ff 0%,
rgba(245, 237, 255, 0) 46%,
rgba(245, 237, 255, 0) 100%
);
border-image: linear-gradient(180deg, rgba(245, 237, 255, 1), rgba(245, 237, 255, 1)) 2 2;
}
.hot-rank-outer .hot-rank-item:nth-child(4) {
background: linear-gradient(
180deg,
#ffe4c4 0%,
rgba(255, 228, 196, 0) 46%,
rgba(255, 228, 196, 0) 100%
);
border-image: linear-gradient(180deg, rgba(255, 228, 196, 1), rgba(255, 228, 196, 1)) 2 2;
}
</style>

View File

@ -0,0 +1,63 @@
<template>
<view class="grid grid-cols-4 grid-rows-2 items-center gap-2 mt-[48rpx] px-[36rpx]">
<view
v-for="item in subMenus"
:key="item.id"
class="flex items-center justify-center flex-col"
@click="goPath(item.path)"
>
<image :src="item.icon" class="w-[88rpx] h-[88rpx]" mode="widthFix"></image>
<view class="text-[22rpx] text-[#303030] mt-[8rpx]">{{ item.name }}</view>
</view>
</view>
</template>
<script lang="ts" setup>
const subMenus = [
{
id: 1,
name: '找大学',
path: '/pages/home/college/index',
icon: '/static/images/home/college.svg',
},
{ id: 2, name: '查专业', path: '/pages/home/major/index', icon: '/static/images/home/major.svg' },
//
{
id: 3,
name: '看职业',
path: '/pages/home/career/index',
icon: '/static/images/home/career.svg',
},
// 线
{ id: 4, name: '批次线', path: '/pages/home/line/index', icon: '/static/images/home/line.svg' },
//
{ id: 5, name: '查位次', path: '/pages/home/rank/index', icon: '/static/images/home/rank.svg' },
//
{
id: 6,
name: '查扩缩招',
path: '/pages/home/expand/index',
icon: '/static/images/home/expand.svg',
},
//
{
id: 7,
name: '专业测评',
path: '/pages/home/evaluation/index',
icon: '/static/images/home/evaluation.svg',
},
//
{
id: 8,
name: '大学甄别',
path: '/pages/home/distinguish/index',
icon: '/static/images/home/distinguish.svg',
},
]
const goPath = (path: string) => {
uni.navigateTo({
url: path,
})
}
</script>

31
src/env.d.ts vendored Normal file
View File

@ -0,0 +1,31 @@
/// <reference types="vite/client" />
/// <reference types="vite-svg-loader" />
declare module '*.vue' {
import { DefineComponent } from 'vue'
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
const component: DefineComponent<{}, {}, any>
export default component
}
interface ImportMetaEnv {
/** 网站标题,应用名称 */
readonly VITE_APP_TITLE: string
/** 服务端口号 */
readonly VITE_SERVER_PORT: string
/** 后台接口地址 */
readonly VITE_SERVER_BASEURL: string
/** H5是否需要代理 */
readonly VITE_APP_PROXY: 'true' | 'false'
/** H5是否需要代理需要的话有个前缀 */
readonly VITE_APP_PROXY_PREFIX: string // 一般是/api
/** 上传图片地址 */
readonly VITE_UPLOAD_BASEURL: string
/** 是否清除console */
readonly VITE_DELETE_CONSOLE: string
// 更多环境变量...
}
interface ImportMeta {
readonly env: ImportMetaEnv
}

0
src/hooks/.gitkeep Normal file
View File

View File

@ -0,0 +1,44 @@
import { getVolunteerInitialization } from '@/service/index/api'
import { useCityStore } from '@/store/city'
import { pinyin } from 'pinyin-pro'
interface Province {
provincename: string
}
const cityStore = useCityStore()
export const cities = []
export const useCityInfo = () => {
getVolunteerInitialization().then((res) => {
if (res.result) {
const list = res.result as Province[]
const li = groupByFirstLetter(list)
cityStore.setCities(li)
const defaultCity = list.filter((item) => item.provincename === '山东省')[0] as City
cityStore.setUserCity(defaultCity)
}
})
}
// 按照首字母分组
const groupByFirstLetter = (lis: Province[]): { letter: string; provinces: Province[] }[] => {
const grouped: { [key: string]: Province[] } = {}
for (let i = 0; i < lis.length; i++) {
const firstLetter = pinyin(lis[i].provincename, {
pattern: 'first',
toneType: 'none',
})[0].toUpperCase()
if (!grouped[firstLetter]) {
grouped[firstLetter] = []
}
grouped[firstLetter].push(lis[i])
}
return Object.keys(grouped)
.sort()
.map((key) => ({ letter: key, provinces: grouped[key] }))
}

View File

@ -0,0 +1,15 @@
let cachedIphoneStyle = ''
;(function () {
wx.getSystemInfo({
success(res) {
const system = res.system.indexOf('iOS')
const isIphoneXOrAbove = res.statusBarHeight > 20
if (isIphoneXOrAbove && system !== -1) {
cachedIphoneStyle = 'bottom: 40rpx;'
}
},
})
})()
export const iphoneBottom = () => cachedIphoneStyle

View File

@ -0,0 +1,62 @@
import { onReady } from '@dcloudio/uni-app'
import { getIsTabbar, getLastItem } from '@/utils/index'
export default () => {
// 获取页面栈
const pages = getCurrentPages()
const isTabbar = getIsTabbar()
// 页面滚动到底部时的操作,通常用于加载更多数据
const onScrollToLower = () => {}
// 获取屏幕边界到安全区域距离
const { safeAreaInsets } = uni.getSystemInfoSync()
// #ifdef MP-WEIXIN
// 基于小程序的 Page 类型扩展 uni-app 的 Page
type PageInstance = Page.PageInstance & WechatMiniprogram.Page.InstanceMethods<any>
// 获取当前页面实例,数组最后一项
const pageInstance = getLastItem(getCurrentPages()) as PageInstance
// 页面渲染完毕,绑定动画效果
onReady(() => {
// 动画效果,导航栏背景色
pageInstance.animate(
'.fly-navbar',
[{ backgroundColor: 'transparent' }, { backgroundColor: '#f8f8f8' }],
1000,
{
scrollSource: '#scroller',
timeRange: 1000,
startScrollOffset: 0,
endScrollOffset: 50,
},
)
// 动画效果,导航栏标题
pageInstance.animate(
'.fly-navbar .title',
[{ color: 'transparent' }, { color: '#000' }],
1000,
{
scrollSource: '#scroller',
timeRange: 1000,
startScrollOffset: 0,
endScrollOffset: 50,
},
)
// 动画效果,导航栏返回按钮
pageInstance.animate('.fly-navbar .left-icon', [{ color: '#fff' }, { color: '#000' }], 1000, {
scrollSource: '#scroller',
timeRange: 1000,
startScrollOffset: 0,
endScrollOffset: 50,
})
})
// #endif
return {
pages,
isTabbar,
onScrollToLower,
safeAreaInsets,
}
}

44
src/hooks/useRequest.ts Normal file
View File

@ -0,0 +1,44 @@
import { UnwrapRef } from 'vue'
type IUseRequestOptions<T> = {
/** 是否立即执行 */
immediate?: boolean
/** 初始化数据 */
initialData?: T
}
/**
* useRequest
* @param func Promise
* @param options {immediate, initialData}
* @param options.immediate false
* @param options.initialData undefined
* @returns {loading, error, data, run}
*/
export default function useRequest<T>(
func: () => Promise<IResData<T>>,
options: IUseRequestOptions<T> = { immediate: false },
) {
const loading = ref(false)
const error = ref(false)
const data = ref<T>(options.initialData)
const run = async () => {
loading.value = true
return func()
.then((res) => {
data.value = res.result as UnwrapRef<T>
error.value = false
return data.value
})
.catch((err) => {
error.value = err
throw err
})
.finally(() => {
loading.value = false
})
}
options.immediate && run()
return { loading, error, data, run }
}

View File

@ -0,0 +1,61 @@
import { TabesItem } from '@/service/app'
import { sysDictType } from '@/service/index/api'
const tabbarList = ref<TabesItem[]>([])
const app = getApp()
sysDictType({ id: 619330547859525 }).then((res) => {
const { code, result } = res
const _tabbarList = [
{
id: 0,
path: '../../home/index/index',
icon: '/static/tabBar/home.png',
selectIcon: '/static/tabBar/home-active.png',
text: '首页',
centerItem: false,
},
{
id: 3,
path: '../../news/index/index',
icon: '/static/tabBar/news.png',
selectIcon: '/static/tabBar/news-active.png',
text: '测评',
centerItem: false,
},
{
id: 2,
path: '../../aiService/index/index',
icon: '/static/tabBar/ai.png',
selectIcon: '/static/tabBar/ai-active.png',
text: '',
centerItem: true,
},
{
id: 1,
path: '../../place/index/index',
icon: '/static/tabBar/place.png',
selectIcon: '/static/tabBar/place-active.png',
text: '专家',
centerItem: false,
},
{
id: 4,
path: '../../ucenter/index/index',
icon: '/static/tabBar/center.png',
selectIcon: '/static/tabBar/center-active.png',
text: '我的',
centerItem: false,
},
]
const { status } = result as { status: number }
if (code === 200) {
if (status === 1) {
tabbarList.value = _tabbarList.filter((item) => item.id !== 2)
} else {
tabbarList.value = _tabbarList
}
}
})
export { tabbarList }

69
src/hooks/useUpload.ts Normal file
View File

@ -0,0 +1,69 @@
// TODO: 别忘加更改环境变量的 VITE_UPLOAD_BASEURL 地址。
import { getEnvBaseUploadUrl } from '@/utils'
const VITE_UPLOAD_BASEURL = `${getEnvBaseUploadUrl()}`
/**
* useUpload
* @param formData {name: '菲鸽'}
* @returns {loading, error, data, run}
*/
export default function useUpload<T = string>(formData: Record<string, any> = {}) {
const loading = ref(false)
const error = ref(false)
const data = ref<T>()
const run = () => {
// #ifdef MP-WEIXIN
// 微信小程序从基础库 2.21.0 开始, wx.chooseImage 停止维护,请使用 uni.chooseMedia 代替。
// 微信小程序在2023年10月17日之后使用本API需要配置隐私协议
uni.chooseMedia({
count: 1,
mediaType: ['image'],
success: (res) => {
loading.value = true
const tempFilePath = res.tempFiles[0].tempFilePath
uploadFile<T>({ tempFilePath, formData, data, error, loading })
},
fail: (err) => {
console.error('uni.chooseMedia err->', err)
error.value = true
},
})
// #endif
// #ifndef MP-WEIXIN
uni.chooseImage({
count: 1,
success: (res) => {
loading.value = true
const tempFilePath = res.tempFilePaths[0]
uploadFile<T>({ tempFilePath, formData, data, error, loading })
},
fail: (err) => {
console.error('uni.chooseImage err->', err)
error.value = true
},
})
// #endif
}
return { loading, error, data, run }
}
function uploadFile<T>({ tempFilePath, formData, data, error, loading }) {
uni.uploadFile({
url: VITE_UPLOAD_BASEURL,
filePath: tempFilePath,
name: 'file',
formData,
success: (uploadFileRes) => {
data.value = uploadFileRes.data as T
},
fail: (err) => {
console.error('uni.uploadFile err->', err)
error.value = true
},
complete: () => {
loading.value = false
},
})
}

View File

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

View File

@ -0,0 +1,13 @@
export const prototypeInterceptor = {
install() {
// 解决低版本手机不识别 array.at() 导致运行报错的问题
if (typeof Array.prototype.at !== 'function') {
// eslint-disable-next-line no-extend-native
Array.prototype.at = function (index: number) {
if (index < 0) return this[this.length + index]
if (index >= this.length) return undefined
return this[index]
}
}
},
}

View File

@ -0,0 +1,49 @@
/* eslint-disable no-param-reassign */
import qs from 'qs'
import { useUserStore } from '@/store'
import { platform } from '@/utils/platform'
export type CustomRequestOptions = UniApp.RequestOptions & {
query?: Record<string, any>
/** 出错时是否隐藏错误提示 */
hideErrorToast?: boolean
} & IUniUploadFileOptions // 添加uni.uploadFile参数类型
// 拦截器配置
const httpInterceptor = {
// 拦截前触发
invoke(options: CustomRequestOptions) {
// 接口请求支持通过 query 参数配置 queryString
if (options.query) {
const queryStr = qs.stringify(options.query)
if (options.url.includes('?')) {
options.url += `&${queryStr}`
} else {
options.url += `?${queryStr}`
}
}
// 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)
},
}

54
src/interceptors/route.ts Normal file
View File

@ -0,0 +1,54 @@
/**
* by on 2024-03-06
*
*
* 便使
*/
import { useUserStore } from '@/store'
import { needLoginPages as _needLoginPages, getNeedLoginPages } from '@/utils'
// TODO Check
const loginRoute = '/pages/login/index'
const isLogined = () => {
const userStore = useUserStore()
return userStore.isLogined
}
const isDev = import.meta.env.DEV
// 黑名单登录拦截器 - (适用于大部分页面不需要登录,少部分页面需要登录)
const navigateToInterceptor = {
// 注意这里的url是 '/' 开头的,如 '/pages/index/index',跟 'pages.json' 里面的 path 不同
invoke({ url }: { url: string }) {
// console.log(url) // /pages/route-interceptor/index?name=feige&age=30
const path = url.split('?')[0]
let needLoginPages: string[] = []
// 为了防止开发时出现BUG这里每次都获取一下。生产环境可以移到函数外性能更好
if (isDev) {
needLoginPages = getNeedLoginPages()
} else {
needLoginPages = _needLoginPages
}
const isNeedLogin = needLoginPages.includes(path)
if (!isNeedLogin) {
return true
}
const hasLogin = isLogined()
if (hasLogin) {
return true
}
const redirectRoute = `${loginRoute}?redirect=${encodeURIComponent(url)}`
uni.navigateTo({ url: redirectRoute })
return false
},
}
export const routeInterceptor = {
install() {
uni.addInterceptor('navigateTo', navigateToInterceptor)
uni.addInterceptor('reLaunch', navigateToInterceptor)
uni.addInterceptor('redirectTo', navigateToInterceptor)
uni.addInterceptor('switchTab', navigateToInterceptor)
},
}

17
src/layouts/default.vue Normal file
View File

@ -0,0 +1,17 @@
<template>
<wd-config-provider :themeVars="themeVars">
<slot />
<wd-toast />
<wd-message-box />
</wd-config-provider>
</template>
<script lang="ts" setup>
import type { ConfigProviderThemeVars } from 'wot-design-uni'
const themeVars: ConfigProviderThemeVars = {
// colorTheme: 'red',
// buttonPrimaryBgColor: '#07c160',
// buttonPrimaryColor: '#07c160',
}
</script>

17
src/layouts/demo.vue Normal file
View File

@ -0,0 +1,17 @@
<template>
<wd-config-provider :themeVars="themeVars">
<slot />
<wd-toast />
<wd-message-box />
</wd-config-provider>
</template>
<script lang="ts" setup>
import type { ConfigProviderThemeVars } from 'wot-design-uni'
const themeVars: ConfigProviderThemeVars = {
// colorTheme: 'red',
// buttonPrimaryBgColor: '#07c160',
// buttonPrimaryColor: '#07c160',
}
</script>

21
src/main.ts Normal file
View File

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

84
src/manifest.json Normal file
View File

@ -0,0 +1,84 @@
{
"name": "六维志愿",
"appid": "H57F2ACE4",
"description": "",
"versionName": "1.0.0",
"versionCode": "100",
"transformPx": false,
"app-plus": {
"usingComponents": true,
"nvueStyleCompiler": "uni-app",
"compilerVersion": 3,
"splashscreen": {
"alwaysShowBeforeRender": true,
"waiting": true,
"autoclose": true,
"delay": 0
},
"modules": {},
"distribute": {
"android": {
"permissions": [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<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\"/>"
],
"minSdkVersion": 30,
"targetSdkVersion": 30,
"abiFilters": [
"armeabi-v7a",
"arm64-v8a"
]
},
"ios": {},
"sdkConfigs": {},
"icons": {
"android": {},
"ios": {}
}
},
"compatible": {
"ignoreVersion": true
}
},
"quickapp": {},
"mp-weixin": {
"appid": "wxa2abb91f64032a2b",
"setting": {
"urlCheck": false
},
"usingComponents": true
},
"mp-alipay": {
"usingComponents": true,
"styleIsolation": "shared"
},
"mp-baidu": {
"usingComponents": true
},
"mp-toutiao": {
"usingComponents": true
},
"uniStatistics": {
"enable": false
},
"vueVersion": "3",
"h5": {
"router": {
"base": "",
"mode": "history"
}
}
}

View File

@ -0,0 +1,20 @@
<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>

203
src/pages.json Normal file
View File

@ -0,0 +1,203 @@
{
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "六纬志愿",
"navigationBarBackgroundColor": "#fff",
"backgroundColor": "#F8F8F8"
},
"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"
}
},
"tabBar": {
"color": "#7A7E83",
"selectedColor": "#3370ff",
"borderStyle": "white",
"backgroundColor": "#ffffff",
"height": "60px",
"fontSize": "10px",
"iconWidth": "16px",
"spacing": "3px",
"list": [
{
"iconPath": "static/tabBar/home.png",
"selectedIconPath": "static/tabBar/home-active.png",
"pagePath": "pages/home/index/index",
"text": "首页"
},
{
"iconPath": "static/tabBar/news.png",
"selectedIconPath": "static/tabBar/news-active.png",
"pagePath": "pages/news/index/index",
"text": "测评"
},
{
"iconPath": "static/tabBar/place.png",
"selectedIconPath": "static/tabBar/place-active.png",
"pagePath": "pages/place/index/index",
"text": "专家"
},
{
"iconPath": "static/tabBar/center.png",
"selectedIconPath": "static/tabBar/center-active.png",
"pagePath": "pages/ucenter/index/index",
"text": "我的"
}
]
},
"pages": [
{
"path": "pages/home/index/index",
"type": "home",
"style": {
"navigationBarTitleText": "六维志愿",
"navigationStyle": "custom"
}
},
{
"path": "pages/index/index",
"type": "home",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "首页"
}
},
{
"path": "pages/about/about",
"type": "page",
"style": {
"navigationBarTitleText": "关于"
}
},
{
"path": "pages/aiService/index/index",
"type": "page",
"style": {
"navigationBarTitleText": "六维管家"
}
},
{
"path": "pages/customerService/index/index",
"type": "page",
"style": {
"navigationBarTitleText": "在线客服",
"navigationStyle": "custom"
}
},
{
"path": "pages/home/career/index",
"type": "page",
"style": {
"navigationBarTitleText": "职业"
}
},
{
"path": "pages/home/city/index",
"type": "page",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "城市"
}
},
{
"path": "pages/home/college/index",
"type": "page",
"style": {
"navigationBarTitleText": "大学"
}
},
{
"path": "pages/home/distinguish/index",
"type": "page",
"style": {
"navigationBarTitleText": "大学甄别"
}
},
{
"path": "pages/home/evaluation/index",
"type": "page",
"style": {
"navigationBarTitleText": "专业测评"
}
},
{
"path": "pages/home/expand/index",
"type": "page",
"style": {
"navigationBarTitleText": "查扩缩招"
}
},
{
"path": "pages/home/inputScore/index",
"type": "page",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "城市"
}
},
{
"path": "pages/home/line/index",
"type": "page",
"style": {
"navigationBarTitleText": "批次线"
}
},
{
"path": "pages/home/major/index",
"type": "page",
"style": {
"navigationBarTitleText": "专业"
}
},
{
"path": "pages/home/rank/index",
"type": "page",
"style": {
"navigationBarTitleText": "排名"
}
},
{
"path": "pages/news/index/index",
"type": "page",
"style": {
"navigationBarTitleText": "测评"
}
},
{
"path": "pages/place/index/index",
"type": "page",
"style": {
"navigationBarTitleText": "专家"
}
},
{
"path": "pages/ucenter/index/index",
"type": "page",
"style": {
"navigationBarTitleText": "我的"
}
}
],
"preloadRule": {
"pages/home/index/index": {
"network": "all",
"packages": [
"__APP__"
]
}
},
"condition": {
"current": 0,
"list": [
{
"name": "",
"path": "",
"query": ""
}
]
},
"subPackages": []
}

36
src/pages/about/about.vue Normal file
View File

@ -0,0 +1,36 @@
<route lang="json5">
{
style: {
navigationBarTitleText: '关于',
},
}
</route>
<template>
<view
class="bg-white overflow-hidden pt-2 px-4"
:style="{ marginTop: safeAreaInsets?.top + 'px' }"
>
<view class="text-center text-3xl mt-8">
鸽友们好我是
<text class="text-red-500">菲鸽</text>
</view>
<RequestComp />
<UploadComp />
</view>
</template>
<script lang="ts" setup>
import RequestComp from './components/request.vue'
import UploadComp from './components/upload.vue'
//
const { safeAreaInsets } = uni.getSystemInfoSync()
</script>
<style lang="scss" scoped>
.test-css {
// mt-4=>1rem=>16px;
margin-top: 16px;
}
</style>

View File

@ -0,0 +1,67 @@
<route lang="json5">
{
layout: 'demo',
style: {
navigationBarTitleText: '请求',
},
}
</route>
<template>
<view class="p-6 text-center">
<view class="my-2">使用的是 laf 云后台</view>
<view class="text-green-400">我的推荐码可以获得佣金</view>
<!-- #ifdef H5 -->
<view class="my-2">
<a class="my-2" :href="recommendUrl" target="_blank">{{ recommendUrl }}</a>
</view>
<!-- #endif -->
<!-- #ifndef H5 -->
<view class="my-2 text-left text-sm">{{ recommendUrl }}</view>
<!-- #endif -->
<!-- http://localhost:9000/#/pages/index/request -->
<wd-button @click="run" class="my-6">发送请求</wd-button>
<view class="h-16">
<view v-if="loading">loading...</view>
<block v-else>
<view class="text-xl">请求数据如下</view>
<view class="text-green leading-8">{{ JSON.stringify(data) }}</view>
</block>
</view>
<wd-button type="error" @click="reset" class="my-6" :disabled="!data">重置数据</wd-button>
</view>
</template>
<script lang="ts" setup>
import { getFooAPI, postFooAPI, IFooItem } from '@/service/index/foo'
import { findPetsByStatusQueryOptions } from '@/service/app'
import { useQuery } from '@tanstack/vue-query'
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,
})
// 使 vue-query useQuery 使
const {
data: data2,
error: error2,
isLoading: isLoading2,
refetch,
} = useQuery(findPetsByStatusQueryOptions({ params: { status: ['available'] } }))
const reset = () => {
data.value = initialData
}
</script>

View File

@ -0,0 +1,30 @@
<route lang="json5" type="page">
{
layout: 'default',
style: {
navigationBarTitleText: '上传-状态一体化',
},
}
</route>
<template>
<view class="p-4 text-center">
<wd-button @click="run"></wd-button>
<view v-if="loading" class="text-blue h-10">...</view>
<template v-else>
<view class="m-2">上传后返回的接口数据</view>
<view class="m-2">{{ data }}</view>
<view class="h-80 w-full">
<image v-if="data" :src="data || data" mode="scaleToFill" />
</view>
</template>
</view>
</template>
<script lang="ts" setup>
const { loading, data, run } = useUpload({ user: '菲鸽' })
</script>
<style lang="scss" scoped>
//
</style>

View File

@ -0,0 +1,7 @@
<template>
<view class="">AI管家</view>
</template>
<script setup></script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,94 @@
<template>
<view class="bg-[#fff] h-[100vh] flex flex-col">
<wd-navbar safeAreaInsetTop custom-class="bg-transparent!" :bordered="false">
<template #title>
<text class="text-[#1F2329] text-[36rpx] font-medium">在线客服</text>
</template>
<template #left>
<wd-icon
name="thin-arrow-left"
custom-style="icon-style"
@click.stop="handleBack"
></wd-icon>
</template>
</wd-navbar>
<view
class="flex-1 bg-[#F8F8F8] px-[32rpx]"
:style="`padding-bottom:${safeAreaInsets.bottom}px;`"
>
<view class="mt-[84rpx] h-[754rpx] radius-[16rpx] bg-[#fff]">
<view class="py-[48rpx] mx-[48rpx] avatar-border flex justify-center items-center">
<image
class="w-[144rpx] h-[144rpx] rounded-full"
src="/static/images/customerService/avatar.svg"
></image>
<view class="flex flex-col text-[#000] ml-[32rpx]">
<text class="mb-[12rpx] font-normal text-[28rpx]">专属客服为您服务</text>
<view class="flex items-center">
<text class="text-[44rpx] font-medium">400-621-1003</text>
<view
@click.stop="makePhoneCall"
class="rounded-[8rpx] w-[88rpx] h-[44rpx] btn-border text-[#1580FF] text-[24rpx] font-normal flex items-center justify-center ml-[44rpx]"
>
拨打
</view>
</view>
</view>
</view>
<view class="px-[168rpx] pt-[48rpx]">
<image
class="w-[352rpx] h-[352rpx]"
src="/static/images/customerService/qrCode.svg"
:show-menu-by-longpress="true"
></image>
<view class="flex items-center justify-center mt-[34rpx]">
<image
class="w-[28rpx] h-[28rpx]"
src="/static/images/customerService/vector.svg"
></image>
<text class="text-[24rpx] text-[#000] font-normal ml-[12rpx]">
扫码添加客服企业微信
</text>
</view>
</view>
</view>
</view>
</view>
</template>
<script lang="ts" setup>
import useNavbarWeixin from '@/hooks/useNavbarWeixin'
const { safeAreaInsets } = useNavbarWeixin()
const makePhoneCall = () => {
uni
.makePhoneCall({
phoneNumber: '400-621-1003',
})
.catch((err) => {
console.error(err)
})
}
const handleBack = () => {
uni.navigateBack()
}
</script>
<style lang="scss" scoped>
.icon-style {
font-size: 48rpx;
}
.btn-border {
border: 2rpx solid #1580ff;
}
.avatar-border {
border-bottom: 2rpx solid #ececec;
}
</style>

View File

@ -0,0 +1,5 @@
<template>
<text>查职业</text>
</template>
<script lang="ts" setup></script>

View File

@ -0,0 +1,43 @@
<template>
<view class="wraper overflow-hidden flex flex-col" :bordered="false">
<wd-navbar title="城市列表" left-arrow @click-left="navigatorBack" safeAreaInsetTop></wd-navbar>
<wd-index-bar sticky class="overflow-y h-0 flex-auto">
<view v-for="item in cities" :key="item.letter">
<wd-index-anchor :index="item.letter" />
<wd-cell
border
clickable
v-for="city in item.provinces"
:key="city.id"
:title="city.provincename"
@click.stop="chooseCity(city)"
></wd-cell>
</view>
</wd-index-bar>
</view>
</template>
<script lang="ts" setup>
import { useCityStore } from '@/store/city'
const cityStore = useCityStore()
const cities = cityStore.userCity.cities ?? []
const navigatorBack = () => {
uni.navigateBack()
}
const chooseCity = (city: City) => {
cityStore.setUserCity(city)
navigatorBack()
}
</script>
<style lang="scss">
.wraper {
height: calc(100vh - var(--window-top));
height: calc(100vh - var(--window-top) - constant(safe-area-inset-bottom));
height: calc(100vh - var(--window-top) - env(safe-area-inset-bottom));
}
</style>

View File

@ -0,0 +1,5 @@
<template>
<text>找大学</text>
</template>
<script lang="ts" setup></script>

View File

@ -0,0 +1,7 @@
<!-- 大学甄别 -->
<template>
<text>大学甄别</text>
</template>
<script lang="ts" setup></script>

View File

@ -0,0 +1,7 @@
<!-- 专业测评 -->
<template>
<text>专业测评</text>
</template>
<script lang="ts" setup></script>

View File

@ -0,0 +1,5 @@
<template>
<text>查扩缩招</text>
</template>
<script lang="ts" setup></script>

View File

@ -0,0 +1,91 @@
<route lang="json5" type="home">
{
style: {
navigationStyle: 'custom',
},
}
</route>
<template>
<scroll-view class="" :scroll-y="true">
<view class="gradient-background relative">
<wd-navbar safeAreaInsetTop custom-class="bg-transparent!" :bordered="false">
<template #left>
<navigator open-type="navigate" class="left-icon" url="/pages/home/city/index">
<text class="color-[#303030] font-[28rpx] font-medium">
{{ cityStore.userCity.city.provincename }}
</text>
</navigator>
</template>
<template #title>
<view class="title">
<image class="w-[198rpx] h-[28rpx]" src="/static/svg/app-logo.svg"></image>
</view>
</template>
</wd-navbar>
<image
class="h-[700rpx] w-full absolute top-0 left-0 z-[-1]"
src="/static/images/home/home-background.png"
/>
</view>
<view class="h-full mt-[48rpx]">
<Banner />
<HomeSubMenu />
<HotRank />
<Consultation />
<Fab />
</view>
</scroll-view>
<TabBar :current-page="0"></TabBar>
</template>
<script setup lang="ts">
import TabBar from '@/components/bar/TabBar.vue'
import { useCityInfo } from '@/hooks/useCityInfoHook'
import { useCityStore } from '@/store/city'
import Banner from '@/components/home/Banner.vue'
import HomeSubMenu from '@/components/home/SubMenu.vue'
import HotRank from '@/components/home/HotRank.vue'
import Consultation from '@/components/home/Consultation.vue'
import Fab from '@/components/fab/Fab.vue'
const cityStore = useCityStore()
useCityInfo()
//
const isTriggered = ref(false)
//
const onRefresherRefresh = async () => {
//
isTriggered.value = true
setTimeout(function fn() {
console.log('refresh - onRefresherRefresh')
//
isTriggered.value = false
}, 1000)
}
</script>
<style lang="scss" scoped>
.left-icon {
position: absolute;
left: 32rpx;
display: flex;
align-items: center;
justify-content: center;
width: max-content;
height: 40rpx;
color: #000;
}
.title {
display: flex;
align-items: center;
justify-content: center;
height: 44px;
font-size: 32rpx;
color: #000;
}
</style>

View File

@ -0,0 +1,42 @@
<template>
<view class="wraper overflow-hidden flex flex-col" :bordered="false">
<wd-navbar title="成绩填写" left-arrow @click-left="navigatorBack" safeAreaInsetTop></wd-navbar>
<view class="px-[32rpx] pt-[47rpx] flex flex-col bg-[#F8F8F8]" hover-class="none">
<text class="text-[22rpx] text-[#636363] text-normal" :selectable="false" :decode="false">
为了使推荐更准确请您认真填写
</text>
<text
class="text-[28rpx] text-[#000] text-medium mt-[47rpx]"
:selectable="false"
:decode="false"
>
预估总分
</text>
<wd-input
custom-class="mt-[24rpx] rounded-[16rpx] bg-white flex items-center px-[32rpx] py-[24rpx]"
custom-input-class="h-full flex items-center"
type="number"
v-model="value"
placeholder="请输入分数"
@change="handleChange"
inputmode="numeric"
:focus="true"
:no-border="true"
>
<template #suffix>
<text class="" :selectable="false" :decode="false"></text>
</template>
</wd-input>
</view>
</view>
</template>
<script lang="ts" setup>
const navigatorBack = () => {
uni.navigateBack()
}
const value = ref('')
const handleChange = (e: any) => {}
</script>

View File

@ -0,0 +1,5 @@
<template>
<text>批次线</text>
</template>
<script lang="ts" setup></script>

View File

@ -0,0 +1,5 @@
<template>
<text>查专业</text>
</template>
<script lang="ts" setup></script>

View File

@ -0,0 +1,5 @@
<template>
<text>查位次</text>
</template>
<script lang="ts" setup></script>

58
src/pages/index/index.vue Normal file
View File

@ -0,0 +1,58 @@
<!-- 使用 type="home" 属性设置首页其他页面不需要设置默认为page推荐使用json5更强大且允许注释 -->
<route lang="json5" type="home">
{
style: {
navigationStyle: 'custom',
navigationBarTitleText: '首页',
},
}
</route>
<template>
<view
class="bg-white overflow-hidden pt-2 px-4"
:style="{ marginTop: safeAreaInsets?.top + 'px' }"
>
<view class="mt-12">
<image src="/static/logo.svg" alt="" class="w-28 h-28 block mx-auto" />
</view>
<view class="text-center text-4xl main-title-color mt-4">unibest</view>
<view class="text-center text-2xl mt-2 mb-8">最好用的 uniapp 开发模板</view>
<view class="text-justify max-w-100 m-auto text-4 indent mb-2">{{ description }}</view>
<view class="text-center mt-8">
当前平台是
<text class="text-green-500">{{ PLATFORM.platform }}</text>
</view>
<view class="text-center mt-4">
模板分支是
<text class="text-green-500">base</text>
</view>
</view>
</template>
<script lang="ts" setup>
import { TestEnum } from '@/typings'
import PLATFORM from '@/utils/platform'
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)
console.log(TestEnum.A)
})
</script>
<style>
.main-title-color {
color: #d14328;
}
</style>

View File

@ -0,0 +1,10 @@
<template>
<view class="">
<text>庄家</text>
<TabBar :current-page="3"></TabBar>
</view>
</template>
<script lang="ts" setup>
import TabBar from '@/components/bar/TabBar.vue'
</script>

View File

@ -0,0 +1,8 @@
<template>
<view class="">专家</view>
<TabBar :current-page="1"></TabBar>
</template>
<script lang="ts" setup>
import TabBar from '@/components/bar/TabBar.vue'
</script>

View File

@ -0,0 +1,8 @@
<template>
<view class="">用户信息</view>
<TabBar :current-page="4"></TabBar>
</template>
<script lang="ts" setup>
import TabBar from '@/components/bar/TabBar.vue'
</script>

View File

@ -0,0 +1,13 @@
/* eslint-disable */
// @ts-ignore
import * as API from './types';
export function displayStatusEnum(field: API.IStatusEnum) {
return { available: 'available', pending: 'pending', sold: 'sold' }[field];
}
export function displayStatusEnum2(field: API.IStatusEnum2) {
return { placed: 'placed', approved: 'approved', delivered: 'delivered' }[
field
];
}

11
src/service/app/index.ts Normal file
View File

@ -0,0 +1,11 @@
/* eslint-disable */
// @ts-ignore
export * from './types';
export * from './displayEnumLabel';
export * from './pet';
export * from './pet.vuequery';
export * from './store';
export * from './store.vuequery';
export * from './user';
export * from './user.vuequery';

193
src/service/app/pet.ts Normal file
View File

@ -0,0 +1,193 @@
/* eslint-disable */
// @ts-ignore
import request from '@/utils/request';
import { CustomRequestOptions } from '@/interceptors/request';
import * as API from './types';
/** Update an existing pet PUT /pet */
export async function updatePet({
body,
options,
}: {
body: API.Pet;
options?: CustomRequestOptions;
}) {
return request<unknown>('/pet', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}
/** Add a new pet to the store POST /pet */
export async function addPet({
body,
options,
}: {
body: API.Pet;
options?: CustomRequestOptions;
}) {
return request<unknown>('/pet', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}
/** Find pet by ID Returns a single pet GET /pet/${param0} */
export async function getPetById({
params,
options,
}: {
// 叠加生成的Param类型 (非body参数openapi默认没有生成对象)
params: API.getPetByIdParams;
options?: CustomRequestOptions;
}) {
const { petId: param0, ...queryParams } = params;
return request<API.Pet>(`/pet/${param0}`, {
method: 'GET',
params: { ...queryParams },
...(options || {}),
});
}
/** Updates a pet in the store with form data POST /pet/${param0} */
export async function updatePetWithForm({
params,
body,
options,
}: {
// 叠加生成的Param类型 (非body参数openapi默认没有生成对象)
params: API.updatePetWithFormParams;
body: {
/** Updated name of the pet */
name?: string;
/** Updated status of the pet */
status?: string;
};
options?: CustomRequestOptions;
}) {
const { petId: param0, ...queryParams } = params;
return request<unknown>(`/pet/${param0}`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
params: { ...queryParams },
data: body,
...(options || {}),
});
}
/** Deletes a pet DELETE /pet/${param0} */
export async function deletePet({
params,
options,
}: {
// 叠加生成的Param类型 (非body参数openapi默认没有生成对象)
params: API.deletePetParams;
options?: CustomRequestOptions;
}) {
const { petId: param0, ...queryParams } = params;
return request<unknown>(`/pet/${param0}`, {
method: 'DELETE',
params: { ...queryParams },
...(options || {}),
});
}
/** uploads an image POST /pet/${param0}/uploadImage */
export async function uploadFile({
params,
body,
file,
options,
}: {
// 叠加生成的Param类型 (非body参数openapi默认没有生成对象)
params: API.uploadFileParams;
body: {
/** Additional data to pass to server */
additionalMetadata?: string;
};
file?: File;
options?: CustomRequestOptions;
}) {
const { petId: param0, ...queryParams } = params;
const formData = new FormData();
if (file) {
formData.append('file', file);
}
Object.keys(body).forEach((ele) => {
const item = (body as { [key: string]: any })[ele];
if (item !== undefined && item !== null) {
if (typeof item === 'object' && !(item instanceof File)) {
if (item instanceof Array) {
item.forEach((f) => formData.append(ele, f || ''));
} else {
formData.append(ele, JSON.stringify(item));
}
} else {
formData.append(ele, item);
}
}
});
return request<API.ApiResponse>(`/pet/${param0}/uploadImage`, {
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
},
params: { ...queryParams },
data: formData,
...(options || {}),
});
}
/** Finds Pets by status Multiple status values can be provided with comma separated strings GET /pet/findByStatus */
export async function findPetsByStatus({
params,
options,
}: {
// 叠加生成的Param类型 (非body参数openapi默认没有生成对象)
params: API.findPetsByStatusParams;
options?: CustomRequestOptions;
}) {
return request<API.Pet[]>('/pet/findByStatus', {
method: 'GET',
params: {
...params,
},
...(options || {}),
});
}
/** Finds Pets by tags Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. GET /pet/findByTags */
export async function findPetsByTags({
params,
options,
}: {
// 叠加生成的Param类型 (非body参数openapi默认没有生成对象)
params: API.findPetsByTagsParams;
options?: CustomRequestOptions;
}) {
return request<API.Pet[]>('/pet/findByTags', {
method: 'GET',
params: {
...params,
},
...(options || {}),
});
}

View File

@ -0,0 +1,151 @@
/* eslint-disable */
// @ts-ignore
import { queryOptions, useMutation } from '@tanstack/vue-query';
import type { DefaultError } from '@tanstack/vue-query';
import request from '@/utils/request';
import { CustomRequestOptions } from '@/interceptors/request';
import * as apis from './pet';
import * as API from './types';
/** Update an existing pet PUT /pet */
export function useUpdatePetMutation(options?: {
onSuccess?: (value?: unknown) => void;
onError?: (error?: DefaultError) => void;
}) {
const { onSuccess, onError } = options || {};
const response = useMutation({
mutationFn: apis.updatePet,
onSuccess(data: unknown) {
onSuccess?.(data);
},
onError(error) {
onError?.(error);
},
});
return response;
}
/** Add a new pet to the store POST /pet */
export function useAddPetMutation(options?: {
onSuccess?: (value?: unknown) => void;
onError?: (error?: DefaultError) => void;
}) {
const { onSuccess, onError } = options || {};
const response = useMutation({
mutationFn: apis.addPet,
onSuccess(data: unknown) {
onSuccess?.(data);
},
onError(error) {
onError?.(error);
},
});
return response;
}
/** Find pet by ID Returns a single pet GET /pet/${param0} */
export function getPetByIdQueryOptions(options: {
// 叠加生成的Param类型 (非body参数openapi默认没有生成对象)
params: API.getPetByIdParams;
options?: CustomRequestOptions;
}) {
return queryOptions({
queryFn: async ({ queryKey }) => {
return apis.getPetById(queryKey[1] as typeof options);
},
queryKey: ['getPetById', options],
});
}
/** Updates a pet in the store with form data POST /pet/${param0} */
export function useUpdatePetWithFormMutation(options?: {
onSuccess?: (value?: unknown) => void;
onError?: (error?: DefaultError) => void;
}) {
const { onSuccess, onError } = options || {};
const response = useMutation({
mutationFn: apis.updatePetWithForm,
onSuccess(data: unknown) {
onSuccess?.(data);
},
onError(error) {
onError?.(error);
},
});
return response;
}
/** Deletes a pet DELETE /pet/${param0} */
export function useDeletePetMutation(options?: {
onSuccess?: (value?: unknown) => void;
onError?: (error?: DefaultError) => void;
}) {
const { onSuccess, onError } = options || {};
const response = useMutation({
mutationFn: apis.deletePet,
onSuccess(data: unknown) {
onSuccess?.(data);
},
onError(error) {
onError?.(error);
},
});
return response;
}
/** uploads an image POST /pet/${param0}/uploadImage */
export function useUploadFileMutation(options?: {
onSuccess?: (value?: API.ApiResponse) => void;
onError?: (error?: DefaultError) => void;
}) {
const { onSuccess, onError } = options || {};
const response = useMutation({
mutationFn: apis.uploadFile,
onSuccess(data: API.ApiResponse) {
onSuccess?.(data);
},
onError(error) {
onError?.(error);
},
});
return response;
}
/** Finds Pets by status Multiple status values can be provided with comma separated strings GET /pet/findByStatus */
export function findPetsByStatusQueryOptions(options: {
// 叠加生成的Param类型 (非body参数openapi默认没有生成对象)
params: API.findPetsByStatusParams;
options?: CustomRequestOptions;
}) {
return queryOptions({
queryFn: async ({ queryKey }) => {
return apis.findPetsByStatus(queryKey[1] as typeof options);
},
queryKey: ['findPetsByStatus', options],
});
}
/** Finds Pets by tags Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. GET /pet/findByTags */
export function findPetsByTagsQueryOptions(options: {
// 叠加生成的Param类型 (非body参数openapi默认没有生成对象)
params: API.findPetsByTagsParams;
options?: CustomRequestOptions;
}) {
return queryOptions({
queryFn: async ({ queryKey }) => {
return apis.findPetsByTags(queryKey[1] as typeof options);
},
queryKey: ['findPetsByTags', options],
});
}

72
src/service/app/store.ts Normal file
View File

@ -0,0 +1,72 @@
/* eslint-disable */
// @ts-ignore
import request from '@/utils/request';
import { CustomRequestOptions } from '@/interceptors/request';
import * as API from './types';
/** Returns pet inventories by status Returns a map of status codes to quantities GET /store/inventory */
export async function getInventory({
options,
}: {
options?: CustomRequestOptions;
}) {
return request<Record<string, unknown>>('/store/inventory', {
method: 'GET',
...(options || {}),
});
}
/** Place an order for a pet POST /store/order */
export async function placeOrder({
body,
options,
}: {
body: API.Order;
options?: CustomRequestOptions;
}) {
return request<API.Order>('/store/order', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}
/** Find purchase order by ID For valid response try integer IDs with value >= 1 and <= 10. Other values will generated exceptions GET /store/order/${param0} */
export async function getOrderById({
params,
options,
}: {
// 叠加生成的Param类型 (非body参数openapi默认没有生成对象)
params: API.getOrderByIdParams;
options?: CustomRequestOptions;
}) {
const { orderId: param0, ...queryParams } = params;
return request<API.Order>(`/store/order/${param0}`, {
method: 'GET',
params: { ...queryParams },
...(options || {}),
});
}
/** Delete purchase order by ID For valid response try integer IDs with positive integer value. Negative or non-integer values will generate API errors DELETE /store/order/${param0} */
export async function deleteOrder({
params,
options,
}: {
// 叠加生成的Param类型 (非body参数openapi默认没有生成对象)
params: API.deleteOrderParams;
options?: CustomRequestOptions;
}) {
const { orderId: param0, ...queryParams } = params;
return request<unknown>(`/store/order/${param0}`, {
method: 'DELETE',
params: { ...queryParams },
...(options || {}),
});
}

View File

@ -0,0 +1,75 @@
/* eslint-disable */
// @ts-ignore
import { queryOptions, useMutation } from '@tanstack/vue-query';
import type { DefaultError } from '@tanstack/vue-query';
import request from '@/utils/request';
import { CustomRequestOptions } from '@/interceptors/request';
import * as apis from './store';
import * as API from './types';
/** Returns pet inventories by status Returns a map of status codes to quantities GET /store/inventory */
export function getInventoryQueryOptions(options: {
options?: CustomRequestOptions;
}) {
return queryOptions({
queryFn: async ({ queryKey }) => {
return apis.getInventory(queryKey[1] as typeof options);
},
queryKey: ['getInventory', options],
});
}
/** Place an order for a pet POST /store/order */
export function usePlaceOrderMutation(options?: {
onSuccess?: (value?: API.Order) => void;
onError?: (error?: DefaultError) => void;
}) {
const { onSuccess, onError } = options || {};
const response = useMutation({
mutationFn: apis.placeOrder,
onSuccess(data: API.Order) {
onSuccess?.(data);
},
onError(error) {
onError?.(error);
},
});
return response;
}
/** Find purchase order by ID For valid response try integer IDs with value >= 1 and <= 10. Other values will generated exceptions GET /store/order/${param0} */
export function getOrderByIdQueryOptions(options: {
// 叠加生成的Param类型 (非body参数openapi默认没有生成对象)
params: API.getOrderByIdParams;
options?: CustomRequestOptions;
}) {
return queryOptions({
queryFn: async ({ queryKey }) => {
return apis.getOrderById(queryKey[1] as typeof options);
},
queryKey: ['getOrderById', options],
});
}
/** Delete purchase order by ID For valid response try integer IDs with positive integer value. Negative or non-integer values will generate API errors DELETE /store/order/${param0} */
export function useDeleteOrderMutation(options?: {
onSuccess?: (value?: unknown) => void;
onError?: (error?: DefaultError) => void;
}) {
const { onSuccess, onError } = options || {};
const response = useMutation({
mutationFn: apis.deleteOrder,
onSuccess(data: unknown) {
onSuccess?.(data);
},
onError(error) {
onError?.(error);
},
});
return response;
}

138
src/service/app/types.ts Normal file
View File

@ -0,0 +1,138 @@
/* eslint-disable */
// @ts-ignore
export type ApiResponse = {
code?: number;
type?: string;
message?: string;
};
export type Category = {
id?: number;
name?: string;
};
export type deleteOrderParams = {
/** ID of the order that needs to be deleted */
orderId: number;
};
export type deletePetParams = {
/** Pet id to delete */
petId: number;
};
export type deleteUserParams = {
/** The name that needs to be deleted */
username: string;
};
export type findPetsByStatusParams = {
/** Status values that need to be considered for filter */
status: ('available' | 'pending' | 'sold')[];
};
export type findPetsByTagsParams = {
/** Tags to filter by */
tags: string[];
};
export type getOrderByIdParams = {
/** ID of pet that needs to be fetched */
orderId: number;
};
export type getPetByIdParams = {
/** ID of pet to return */
petId: number;
};
export type getUserByNameParams = {
/** The name that needs to be fetched. Use user1 for testing. */
username: string;
};
export type loginUserParams = {
/** The user name for login */
username: string;
/** The password for login in clear text */
password: string;
};
export type Order = {
id?: number;
petId?: number;
quantity?: number;
shipDate?: string;
/** Order Status */
status?: 'placed' | 'approved' | 'delivered';
complete?: boolean;
};
export type Pet = {
id?: number;
category?: Category;
name: string;
photoUrls: string[];
tags?: Tag[];
/** pet status in the store */
status?: 'available' | 'pending' | 'sold';
};
export enum StatusEnum {
available = 'available',
pending = 'pending',
sold = 'sold',
}
export type IStatusEnum = keyof typeof StatusEnum;
export enum StatusEnum2 {
placed = 'placed',
approved = 'approved',
delivered = 'delivered',
}
export type IStatusEnum2 = keyof typeof StatusEnum2;
export type Tag = {
id?: number;
name?: string;
};
export type updatePetWithFormParams = {
/** ID of pet that needs to be updated */
petId: number;
};
export type updateUserParams = {
/** name that need to be updated */
username: string;
};
export type uploadFileParams = {
/** ID of pet to update */
petId: number;
};
export type User = {
id?: number;
username?: string;
firstName?: string;
lastName?: string;
email?: string;
password?: string;
phone?: string;
/** User Status */
userStatus?: number;
};
export type TabesItem = {
id: number
path: string
icon: string
selectIcon: string
text: string
centerItem: boolean
}

150
src/service/app/user.ts Normal file
View File

@ -0,0 +1,150 @@
/* eslint-disable */
// @ts-ignore
import request from '@/utils/request';
import { CustomRequestOptions } from '@/interceptors/request';
import * as API from './types';
/** Create user This can only be done by the logged in user. 返回值: successful operation POST /user */
export async function createUser({
body,
options,
}: {
body: API.User;
options?: CustomRequestOptions;
}) {
return request<unknown>('/user', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}
/** Get user by user name GET /user/${param0} */
export async function getUserByName({
params,
options,
}: {
// 叠加生成的Param类型 (非body参数openapi默认没有生成对象)
params: API.getUserByNameParams;
options?: CustomRequestOptions;
}) {
const { username: param0, ...queryParams } = params;
return request<API.User>(`/user/${param0}`, {
method: 'GET',
params: { ...queryParams },
...(options || {}),
});
}
/** Updated user This can only be done by the logged in user. PUT /user/${param0} */
export async function updateUser({
params,
body,
options,
}: {
// 叠加生成的Param类型 (非body参数openapi默认没有生成对象)
params: API.updateUserParams;
body: API.User;
options?: CustomRequestOptions;
}) {
const { username: param0, ...queryParams } = params;
return request<unknown>(`/user/${param0}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
params: { ...queryParams },
data: body,
...(options || {}),
});
}
/** Delete user This can only be done by the logged in user. DELETE /user/${param0} */
export async function deleteUser({
params,
options,
}: {
// 叠加生成的Param类型 (非body参数openapi默认没有生成对象)
params: API.deleteUserParams;
options?: CustomRequestOptions;
}) {
const { username: param0, ...queryParams } = params;
return request<unknown>(`/user/${param0}`, {
method: 'DELETE',
params: { ...queryParams },
...(options || {}),
});
}
/** Creates list of users with given input array 返回值: successful operation POST /user/createWithArray */
export async function createUsersWithArrayInput({
body,
options,
}: {
body: API.User[];
options?: CustomRequestOptions;
}) {
return request<unknown>('/user/createWithArray', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}
/** Creates list of users with given input array 返回值: successful operation POST /user/createWithList */
export async function createUsersWithListInput({
body,
options,
}: {
body: API.User[];
options?: CustomRequestOptions;
}) {
return request<unknown>('/user/createWithList', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}
/** Logs user into the system GET /user/login */
export async function loginUser({
params,
options,
}: {
// 叠加生成的Param类型 (非body参数openapi默认没有生成对象)
params: API.loginUserParams;
options?: CustomRequestOptions;
}) {
return request<string>('/user/login', {
method: 'GET',
params: {
...params,
},
...(options || {}),
});
}
/** Logs out current logged in user session 返回值: successful operation GET /user/logout */
export async function logoutUser({
options,
}: {
options?: CustomRequestOptions;
}) {
return request<unknown>('/user/logout', {
method: 'GET',
...(options || {}),
});
}

View File

@ -0,0 +1,149 @@
/* eslint-disable */
// @ts-ignore
import { queryOptions, useMutation } from '@tanstack/vue-query';
import type { DefaultError } from '@tanstack/vue-query';
import request from '@/utils/request';
import { CustomRequestOptions } from '@/interceptors/request';
import * as apis from './user';
import * as API from './types';
/** Create user This can only be done by the logged in user. 返回值: successful operation POST /user */
export function useCreateUserMutation(options?: {
onSuccess?: (value?: unknown) => void;
onError?: (error?: DefaultError) => void;
}) {
const { onSuccess, onError } = options || {};
const response = useMutation({
mutationFn: apis.createUser,
onSuccess(data: unknown) {
onSuccess?.(data);
},
onError(error) {
onError?.(error);
},
});
return response;
}
/** Get user by user name GET /user/${param0} */
export function getUserByNameQueryOptions(options: {
// 叠加生成的Param类型 (非body参数openapi默认没有生成对象)
params: API.getUserByNameParams;
options?: CustomRequestOptions;
}) {
return queryOptions({
queryFn: async ({ queryKey }) => {
return apis.getUserByName(queryKey[1] as typeof options);
},
queryKey: ['getUserByName', options],
});
}
/** Updated user This can only be done by the logged in user. PUT /user/${param0} */
export function useUpdateUserMutation(options?: {
onSuccess?: (value?: unknown) => void;
onError?: (error?: DefaultError) => void;
}) {
const { onSuccess, onError } = options || {};
const response = useMutation({
mutationFn: apis.updateUser,
onSuccess(data: unknown) {
onSuccess?.(data);
},
onError(error) {
onError?.(error);
},
});
return response;
}
/** Delete user This can only be done by the logged in user. DELETE /user/${param0} */
export function useDeleteUserMutation(options?: {
onSuccess?: (value?: unknown) => void;
onError?: (error?: DefaultError) => void;
}) {
const { onSuccess, onError } = options || {};
const response = useMutation({
mutationFn: apis.deleteUser,
onSuccess(data: unknown) {
onSuccess?.(data);
},
onError(error) {
onError?.(error);
},
});
return response;
}
/** Creates list of users with given input array 返回值: successful operation POST /user/createWithArray */
export function useCreateUsersWithArrayInputMutation(options?: {
onSuccess?: (value?: unknown) => void;
onError?: (error?: DefaultError) => void;
}) {
const { onSuccess, onError } = options || {};
const response = useMutation({
mutationFn: apis.createUsersWithArrayInput,
onSuccess(data: unknown) {
onSuccess?.(data);
},
onError(error) {
onError?.(error);
},
});
return response;
}
/** Creates list of users with given input array 返回值: successful operation POST /user/createWithList */
export function useCreateUsersWithListInputMutation(options?: {
onSuccess?: (value?: unknown) => void;
onError?: (error?: DefaultError) => void;
}) {
const { onSuccess, onError } = options || {};
const response = useMutation({
mutationFn: apis.createUsersWithListInput,
onSuccess(data: unknown) {
onSuccess?.(data);
},
onError(error) {
onError?.(error);
},
});
return response;
}
/** Logs user into the system GET /user/login */
export function loginUserQueryOptions(options: {
// 叠加生成的Param类型 (非body参数openapi默认没有生成对象)
params: API.loginUserParams;
options?: CustomRequestOptions;
}) {
return queryOptions({
queryFn: async ({ queryKey }) => {
return apis.loginUser(queryKey[1] as typeof options);
},
queryKey: ['loginUser', options],
});
}
/** Logs out current logged in user session 返回值: successful operation GET /user/logout */
export function logoutUserQueryOptions(options: {
options?: CustomRequestOptions;
}) {
return queryOptions({
queryFn: async ({ queryKey }) => {
return apis.logoutUser(queryKey[1] as typeof options);
},
queryKey: ['logoutUser', options],
});
}

14
src/service/index/api.ts Normal file
View File

@ -0,0 +1,14 @@
import { http } from '@/utils/http'
export interface IFooItem {
id: string
name: string
}
export const sysDictType = (params: any) => {
return http.get('/api/sysDictData/dicStatus', params)
}
export const getVolunteerInitialization = () => {
return http.get('/api/v1/base/volunteerInitialization.json', { staticType: 'static' })
}

15
src/service/index/foo.ts Normal file
View File

@ -0,0 +1,15 @@
import { http } from '@/utils/http'
export interface IFooItem {
id: string
name: string
}
/** GET 请求 */
export const getFooAPI = (name: string) => {
return http.get<IFooItem>('/foo', { name })
}
/** POST 请求 */
export const postFooAPI = (name: string) => {
return http.post<IFooItem>('/foo', { name }, { name })
}

View File

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 1.1 MiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 59 KiB

View File

@ -0,0 +1,3 @@
<svg width="176" height="176" viewBox="0 0 176 176" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.31747 7.79883H79.1685V22.4068H8.31747V7.79883ZM97.1865 7.79883H138.205V22.4068H97.1865V7.79883ZM153.242 7.79883H168.147V22.7038H153.242V7.79883ZM8.31747 64.3498H79.1685V78.9688H8.31747V64.3498ZM7.85547 7.79883H22.4635V78.6498H7.85547V7.79883ZM64.5605 7.79883H79.1685V78.6498H64.5605V7.79883ZM32.5505 34.5178H52.4385V54.4058H32.5505V34.5178ZM97.1865 22.4068H111.409V37.3998H97.1865V22.4068ZM138.194 22.4068H153.792V49.9948H138.194V22.4068ZM153.242 37.3998H168.147V63.5028H153.242V37.3998ZM111.948 48.5868H138.205V67.3748H111.948V48.5868ZM126.644 63.4918H153.352V78.6388H126.644V63.4918ZM97.2745 63.9648H111.948V78.6388H97.2745V63.9648ZM7.85547 93.2908H22.4635V126.39H7.85547V93.2908ZM22.4965 123.277H38.3035V139.095H22.4965V123.277ZM7.85547 138.468H22.4965V168.212H7.85547V138.468ZM37.4125 93.2908H82.3915V111.463H37.4125V93.2908ZM48.3575 109.846H67.1235V127.116H48.3575V109.846ZM63.6255 123.277H82.3915V153.329H63.6255V123.277ZM49.0615 138.468H67.1235V168.212H49.0615V138.468ZM34.0245 149.38H51.5585V168.212H34.0245V149.38ZM108.142 93.2908H141.703V123.277H108.142V93.2908ZM149.733 93.2908H168.147V111.705H149.733V93.2908ZM93.6885 108.284H112.102V141.68H93.6885V108.284ZM123.179 119.075H141.703V138.303H123.179V119.075ZM93.6885 149.38H112.102V168.212H93.6885V149.38ZM137.985 153.329H168.147V168.212H137.985V153.329ZM153.066 138.303H168.147V156.475H153.066V138.303Z" fill="#272636"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,3 @@
<svg width="12" height="14" viewBox="0 0 12 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.60748 11.523C9.60748 11.6659 9.55621 11.8029 9.46494 11.9039C9.37368 12.0049 9.2499 12.0617 9.12083 12.0617C8.99176 12.0617 8.86798 12.0049 8.77672 11.9039C8.68545 11.8029 8.63418 11.6659 8.63418 11.523V9.26151C8.63418 7.59624 7.4139 6.24614 5.90871 6.24614C4.40352 6.24614 3.1834 7.59624 3.1834 9.26151V11.2C3.1834 11.3428 3.13212 11.4799 3.04084 11.5809C2.94956 11.6819 2.82576 11.7387 2.69667 11.7387C2.56758 11.7387 2.44378 11.6819 2.3525 11.5809C2.26122 11.4799 2.20994 11.3428 2.20994 11.2V9.26151C2.20994 7.00142 3.86595 5.16922 5.90887 5.16922C7.95147 5.16922 9.60748 7.00142 9.60748 9.26151V11.523ZM11.8868 3.09435C11.9278 3.14862 11.9587 3.21129 11.9778 3.27878C11.9969 3.34627 12.0038 3.41726 11.9981 3.4877C11.9923 3.55813 11.9742 3.62663 11.9445 3.68929C11.9149 3.75194 11.8744 3.80753 11.8254 3.85286C11.7263 3.94442 11.5985 3.98871 11.47 3.97598C11.3414 3.96326 11.2227 3.89457 11.1399 3.78501C9.85267 2.08025 7.9552 1.07692 5.90871 1.07692C3.95351 1.07692 2.13243 1.9923 0.848098 3.56784C0.805273 3.62038 0.753518 3.66307 0.695788 3.69347C0.638057 3.72387 0.575482 3.74139 0.511634 3.74502C0.447787 3.74865 0.383918 3.73833 0.323675 3.71464C0.263432 3.69096 0.207994 3.65437 0.160528 3.60696C0.0647506 3.51128 0.00723663 3.37741 0.000637399 3.23479C-0.00596183 3.09217 0.0388942 2.95249 0.125338 2.84648C1.59242 1.04713 3.67508 0 5.90871 0C8.24677 0 10.4165 1.14764 11.8868 3.09435ZM11.6514 8.93844C11.6514 9.08132 11.6001 9.21834 11.5088 9.31938C11.4175 9.42041 11.2937 9.47717 11.1646 9.47717C11.0356 9.47717 10.9118 9.42041 10.8205 9.31938C10.7292 9.21834 10.6779 9.08132 10.6779 8.93844C10.6779 6.74726 9.45975 4.80809 7.64645 4.02266C7.58696 3.99687 7.53264 3.95837 7.48659 3.90935C7.44055 3.86032 7.40368 3.80175 7.37809 3.73695C7.3525 3.67216 7.33868 3.60242 7.33744 3.53172C7.3362 3.46102 7.34755 3.39075 7.37085 3.3249C7.39415 3.25906 7.42893 3.19894 7.47322 3.14797C7.51751 3.09701 7.57044 3.0562 7.62898 3.02787C7.68752 2.99955 7.75052 2.98426 7.8144 2.98289C7.87827 2.98151 7.94177 2.99408 8.00126 3.01986C10.1848 3.9654 11.6514 6.30034 11.6514 8.93844ZM5.90871 2.58461C6.03773 2.58461 6.16147 2.64134 6.25271 2.74232C6.34394 2.8433 6.3952 2.98026 6.3952 3.12307C6.3952 3.26588 6.34394 3.40284 6.25271 3.50382C6.16147 3.6048 6.03773 3.66153 5.90871 3.66153C3.2747 3.66153 1.13934 6.02411 1.13934 8.93844C1.13934 9.08129 1.08807 9.2183 0.996805 9.31931C0.905541 9.42033 0.781759 9.47708 0.652691 9.47708C0.523624 9.47708 0.399842 9.42033 0.308578 9.31931C0.217313 9.2183 0.166041 9.08129 0.166041 8.93844C0.166041 5.42947 2.73713 2.58461 5.90871 2.58461ZM5.90871 8.83074C5.80688 8.83072 5.7091 8.87487 5.63634 8.95372C5.56358 9.03258 5.52164 9.13985 5.51952 9.25254L5.52244 9.33923C5.53351 9.68599 5.53962 10.0329 5.54076 10.3799C5.54093 10.7145 5.53395 10.9937 5.51757 11.2055C5.46325 11.9102 5.28828 12.5249 5.02946 13.048C4.92715 13.2568 4.80709 13.4543 4.67092 13.6379C4.59227 13.7428 4.52692 13.8174 4.48184 13.8623C4.38576 13.9577 4.2594 14.0069 4.13053 13.9992C4.00166 13.9915 3.88083 13.9275 3.79459 13.8212C3.70842 13.7149 3.66391 13.5751 3.67084 13.4326C3.67777 13.29 3.73559 13.1563 3.83157 13.0609C3.83043 13.062 3.83546 13.0568 3.84584 13.0447C3.86757 13.0201 3.89287 12.9887 3.92124 12.951C4.01794 12.8202 4.10319 12.6795 4.17584 12.5309C4.37141 12.1356 4.50535 11.6647 4.54784 11.114C4.5613 10.9394 4.56762 10.6868 4.56746 10.3804C4.56699 10.0462 4.56104 9.712 4.54962 9.378L4.54638 9.28413L4.54606 9.26151C4.54606 8.42869 5.15611 7.75382 5.90871 7.75382C6.27004 7.75378 6.61658 7.91259 6.87213 8.19533C7.12767 8.47807 7.27128 8.86158 7.27136 9.26151V12.1398C7.27136 12.2826 7.22009 12.4196 7.12883 12.5206C7.03756 12.6217 6.91378 12.6784 6.78471 12.6784C6.65565 12.6784 6.53186 12.6217 6.4406 12.5206C6.34933 12.4196 6.29806 12.2826 6.29806 12.1398V9.26151C6.29806 9.14727 6.25706 9.0377 6.18407 8.95691C6.11108 8.87613 6.01209 8.83074 5.90887 8.83074H5.90871Z" fill="#E75859"/>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 39 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 30 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 33 KiB

Some files were not shown because too many files have changed in this diff Show More