3 Commits

Author SHA1 Message Date
DaxPay
34bfe028a3 perf 优化支付宝js文件加载逻辑 2024-09-26 14:57:08 +08:00
DaxPay
d45408250b feat 自动适配暗黑模式, 联调通道认证功能, 增加虚拟控制台调试插件 2024-09-26 14:40:59 +08:00
DaxPay
3b2ac73eb6 feat 微信获取OpenId 2024-09-25 18:59:06 +08:00
14 changed files with 231 additions and 21 deletions

View File

@@ -5,7 +5,7 @@ VITE_PORT=9100
VITE_PUBLIC_PATH=/
# 跨域代理,可以配置多个,请注意不要换行
VITE_PROXY=[["/server","http://localhost:9000"]]
VITE_PROXY=[["/server","http://localhost:10880"]]
# API 接口地址
VITE_GLOB_API_URL=
@@ -13,5 +13,7 @@ VITE_GLOB_API_URL=
# 接口前缀
VITE_GLOB_API_URL_PREFIX=/server
# 虚拟控制台
VITE_V_CONSOLE=true

View File

@@ -1,5 +1,5 @@
# 独立部署模式
VITE_PUBLIC_PATH = /h5
VITE_PUBLIC_PATH = /
# API 接口前缀
VITE_GLOB_API_URL_PREFIX = /api
@@ -11,6 +11,9 @@ VITE_GLOB_API_URL_PREFIX = /api
# 是否删除console
VITE_DROP_CONSOLE=true
# 虚拟控制台
VITE_V_CONSOLE=false
# 是否启用gzip压缩或brotli压缩, 可选: gzip | brotli | none, 如果你需要多种形式,你可以用','来分隔
VITE_BUILD_COMPRESS='none'

View File

@@ -1,14 +1,15 @@
import * as path from 'node:path'
import type { PluginOption } from 'vite'
import Components from 'unplugin-vue-components/vite'
import { VantResolver } from 'unplugin-vue-components/resolvers'
import vue from '@vitejs/plugin-vue'
import UnoCSS from 'unocss/vite'
import AutoImport from 'unplugin-auto-import/vite'
import { viteVConsole } from 'vite-plugin-vconsole'
import { configHtmlPlugin } from './html'
import { configCompressPlugin } from './compress'
import { configVisualizerConfig } from './visualizer'
import { configSvgIconsPlugin } from './svgSprite'
/**
* 配置 vite 插件
* @param viteEnv vite 环境变量配置文件键值队 object
@@ -26,6 +27,13 @@ export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
const vitePlugins: (PluginOption | PluginOption[])[] = [
// have to
vue(),
viteVConsole({
entry: path.resolve('src/main.ts'), // 或者可以使用这个配置: [path.resolve('src/main.ts')]
enabled: viteEnv.VITE_V_CONSOLE, // 可自行结合 mode 和 command 进行判断
config: {
theme: 'dark',
},
}),
// 按需引入VantUi且自动创建组件声明
Components({
dts: true,

View File

@@ -57,5 +57,13 @@ export default antfu({
'node/prefer-global/process': 'off',
// 对所有控制语句强制执行一致的大括号样式只有一行的时候eslint默认是不需要大括号的这样会降低代码清晰度
'curly': ['error', 'all'],
// 'indent': 'off',
// 'vue/script-indent': [
// 'error',
// 2,
// {
// baseIndent: 1,
// },
// ],
},
})

View File

@@ -10,14 +10,15 @@
<div id="app">
<script>
;(() => {
const { darkMode = 'dark', appTheme = '#5d9dfe' } =
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
const darkMode = mediaQuery.matches ? 'dark' : 'light'
const { appTheme = '#5d9dfe' } =
JSON.parse(window.localStorage.getItem('DESIGN-SETTING')) || {}
let htmlRoot = document.getElementById('htmlRoot')
if (htmlRoot) {
htmlRoot.classList.add(darkMode)
}
// 设置主题色变量
document.documentElement.style.setProperty('--app-theme-color', appTheme)
})()

View File

@@ -76,6 +76,8 @@
"unocss": "^0.58.9",
"unplugin-auto-import": "^0.17.8",
"unplugin-vue-components": "^0.26.0",
"vconsole": "^3.15.1",
"vite-plugin-vconsole": "^2.1.1",
"vite": "5.2.6",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-html": "^3.2.2",

50
pnpm-lock.yaml generated
View File

@@ -159,6 +159,9 @@ importers:
unplugin-vue-components:
specifier: ^0.26.0
version: 0.26.0(@babel/parser@7.25.6)(rollup@4.22.4)(vue@3.5.8(typescript@5.6.2))(webpack-sources@3.2.3)
vconsole:
specifier: ^3.15.1
version: 3.15.1
vite:
specifier: 5.2.6
version: 5.2.6(@types/node@20.16.5)(less@4.2.0)(terser@5.33.0)
@@ -174,6 +177,9 @@ importers:
vite-plugin-svg-icons:
specifier: ^2.0.1
version: 2.0.1(vite@5.2.6(@types/node@20.16.5)(less@4.2.0)(terser@5.33.0))
vite-plugin-vconsole:
specifier: ^2.1.1
version: 2.1.1
vue-tsc:
specifier: ^1.8.27
version: 1.8.27(typescript@5.6.2)
@@ -357,6 +363,10 @@ packages:
peerDependencies:
'@babel/core': ^7.0.0-0
'@babel/runtime@7.25.6':
resolution: {integrity: sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==}
engines: {node: '>=6.9.0'}
'@babel/template@7.25.0':
resolution: {integrity: sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==}
engines: {node: '>=6.9.0'}
@@ -1615,9 +1625,16 @@ packages:
resolution: {integrity: sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==}
engines: {node: '>=0.10.0'}
copy-text-to-clipboard@3.2.0:
resolution: {integrity: sha512-RnJFp1XR/LOBDckxTib5Qjr/PMfkatD0MUCQgdpqS8MdKiNUzBjAQBEN6oUy+jW7LI93BBG3DtMB2KOOKpGs2Q==}
engines: {node: '>=12'}
core-js-compat@3.38.1:
resolution: {integrity: sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==}
core-js@3.38.1:
resolution: {integrity: sha512-OP35aUorbU3Zvlx7pjsFdu1rGNnD4pgw/CWoYzRY3t2EzoVT7shKHY1dlAy3f41cGIO7ZDPQimhGFTlEYkG/Hw==}
cors@2.8.5:
resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==}
engines: {node: '>= 0.10'}
@@ -3137,6 +3154,9 @@ packages:
muggle-string@0.3.1:
resolution: {integrity: sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==}
mutation-observer@1.0.3:
resolution: {integrity: sha512-M/O/4rF2h776hV7qGMZUH3utZLO/jK7p8rnNgGkjKUw8zCGjRQPxB8z6+5l8+VjRUQ3dNYu4vjqXYLr+U8ZVNA==}
nanoid@3.3.7:
resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
@@ -3519,6 +3539,9 @@ packages:
resolution: {integrity: sha512-J8rn6v4DBb2nnFqkqwy6/NnTYMcgLA+sLr0iIO41qpv0n+ngb7ksag2tMRl0inb1bbO/esUwzW1vbJi7K0sI0g==}
engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
regenerator-runtime@0.14.1:
resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
regex-not@1.0.2:
resolution: {integrity: sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==}
engines: {node: '>=0.10.0'}
@@ -4134,6 +4157,9 @@ packages:
resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
engines: {node: '>= 0.8'}
vconsole@3.15.1:
resolution: {integrity: sha512-KH8XLdrq9T5YHJO/ixrjivHfmF2PC2CdVoK6RWZB4yftMykYIaXY1mxZYAic70vADM54kpMQF+dYmvl5NRNy1g==}
vite-plugin-compression@0.5.1:
resolution: {integrity: sha512-5QJKBDc+gNYVqL/skgFAP81Yuzo9R+EAf19d+EtsMF/i8kFUpNi3J/H01QD3Oo8zBQn+NzoCIFkpPLynoOzaJg==}
peerDependencies:
@@ -4156,6 +4182,9 @@ packages:
peerDependencies:
vite: '>=2.0.0'
vite-plugin-vconsole@2.1.1:
resolution: {integrity: sha512-369FlBnQhzR5pF2+nsmbMeF5qNO6MzUIk3l+DHa8In15cscyk4eXT5pWfExoSLn41dgeI1FPP+kgAKViePYPdQ==}
vite@5.2.6:
resolution: {integrity: sha512-FPtnxFlSIKYjZ2eosBQamz4CbyrTizbZ3hnGJlh/wMtCrlp1Hah6AzBLjGI5I2urTfNnpovpHdrL6YRuBOPnCA==}
engines: {node: ^18.0.0 || >=20.0.0}
@@ -4549,6 +4578,10 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@babel/runtime@7.25.6':
dependencies:
regenerator-runtime: 0.14.1
'@babel/template@7.25.0':
dependencies:
'@babel/code-frame': 7.24.7
@@ -5853,10 +5886,14 @@ snapshots:
copy-descriptor@0.1.1: {}
copy-text-to-clipboard@3.2.0: {}
core-js-compat@3.38.1:
dependencies:
browserslist: 4.23.3
core-js@3.38.1: {}
cors@2.8.5:
dependencies:
object-assign: 4.1.1
@@ -7509,6 +7546,8 @@ snapshots:
muggle-string@0.3.1: {}
mutation-observer@1.0.3: {}
nanoid@3.3.7: {}
nanomatch@1.2.13:
@@ -7888,6 +7927,8 @@ snapshots:
dependencies:
'@eslint-community/regexpp': 4.11.1
regenerator-runtime@0.14.1: {}
regex-not@1.0.2:
dependencies:
extend-shallow: 3.0.2
@@ -8586,6 +8627,13 @@ snapshots:
vary@1.1.2: {}
vconsole@3.15.1:
dependencies:
'@babel/runtime': 7.25.6
copy-text-to-clipboard: 3.2.0
core-js: 3.38.1
mutation-observer: 1.0.3
vite-plugin-compression@0.5.1(vite@5.2.6(@types/node@20.16.5)(less@4.2.0)(terser@5.33.0)):
dependencies:
chalk: 4.1.2
@@ -8640,6 +8688,8 @@ snapshots:
transitivePeerDependencies:
- supports-color
vite-plugin-vconsole@2.1.1: {}
vite@5.2.6(@types/node@20.16.5)(less@4.2.0)(terser@5.33.0):
dependencies:
esbuild: 0.20.2

View File

@@ -25,5 +25,4 @@ async function bootstrap() {
// 路由准备就绪后挂载APP实例
app.mount('#app', true)
}
void bootstrap()

View File

@@ -1,6 +1,6 @@
import type { App } from 'vue'
import type { RouteRecordRaw } from 'vue-router'
import { createRouter, createWebHashHistory } from 'vue-router'
import { createRouter, createWebHashHistory, createWebHistory } from "vue-router";
import { createRouterGuards } from './router-guards'
import { ErrorPageRoute, routeModuleList } from '@/router/base'
import { useRouteStoreWidthOut } from '@/store/modules/route'
@@ -24,7 +24,8 @@ routeStore.setMenus(routeModuleList)
routeStore.setRouters(constantRouter.concat(routeModuleList))
const router = createRouter({
history: createWebHashHistory(''),
// 重定向时hash模式可能无法跳转需要使用history模式
history: createWebHistory(''),
routes: constantRouter.concat(...routeModuleList),
strict: true,
scrollBehavior: () => ({ left: 0, top: 0 }),

View File

@@ -0,0 +1,28 @@
import { http } from '@/utils/http/axios'
import type { Result } from '#/axios'
/**
* 通过AuthCode获取并设置认证结果
* @param param
*/
export function authAndSet(param: AuthCodeParam) {
return http.request<Result>({
url: '/unipay/assist/channel/auth/authAndSet',
method: 'POST',
data: param,
})
}
/**
* 通道认证参数
*/
export interface AuthCodeParam {
// 通道
channel?: string
// 标识码
authCode?: string
// 查询Code
queryCode?: string
// 应用号
appId?: string
}

View File

@@ -1,17 +1,75 @@
<template>
<div>
</div>
<van-overlay v-show="show" :show="true">
<div class="wrapper" @click.stop>
<van-loading size="24px">
获取中...
</van-loading>
</div>
</van-overlay>
</template>
<script setup lang="ts">
import { useRoute } from 'vue-router'
import { ref } from 'vue'
import { showDialog } from 'vant'
import type { AuthCodeParam } from '@/views/daxpay/channel/ChannelAuth.api'
import { authAndSet } from '@/views/daxpay/channel/ChannelAuth.api'
const script = document.createElement('script')
script.setAttribute(
'src',
'https://gw.alipayobjects.com/as/g/h5-lib/alipayjsapi/3.1.1/alipayjsapi.min.js',
)
document.head.appendChild(script)
// 脚本加载完毕后进行初始化
script.onload = () => {
init()
}
const route = useRoute()
const {appId, channel, queryCode, aliAppId} = route.params
const { appId, channel, queryCode, aliAppId } = route.params
console.log(appId, channel)
const show = ref(true)
/**
* 页面初始化
*/
async function init() {
ap.getAuthCode ({
appId: aliAppId,
scopes: ['auth_base'],
}, (res) => {
const authCode = res.authCode
const param = ref<AuthCodeParam>({
appId: appId as string,
queryCode: queryCode as string,
authCode: authCode as string,
channel: channel as string,
})
authAndSet(param.value).then(() => {
show.value = false
showDialog({
message: '已成功获取用户信息!',
confirmButtonText: '关闭',
}).then(() => {
AlipayJSBridge.call('closeWebview')
})
})
})
}
</script>
<style scoped lang="less">
.wrapper {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
.block {
width: 120px;
height: 120px;
background-color: #fff;
}
</style>

View File

@@ -1,13 +1,62 @@
<script setup lang="ts">
</script>
<template>
const {appId, channel,queryCode} = route.params
console.log(appId, channel)
<van-overlay :show="true" v-show="show">
<div class="wrapper" @click.stop>
<van-loading size="24px">
获取中...
</van-loading>
</div>
</van-overlay>
</template>
<style scoped lang="less">
<script setup lang="ts">
import { useRoute } from 'vue-router'
import { ref, onMounted } from 'vue'
import type { AuthCodeParam } from '@/views/daxpay/channel/ChannelAuth.api'
import { authAndSet } from '@/views/daxpay/channel/ChannelAuth.api'
import { showDialog } from "vant";
const route = useRoute()
const { appId, channel, queryCode } = route.params
const { code } = route.query
const param = ref<AuthCodeParam>({
appId: appId as string,
queryCode: queryCode as string,
authCode: code as string,
channel: channel as string,
})
const show = ref(true)
onMounted(() => {
init()
})
/**
* 页面初始化
*/
async function init() {
authAndSet(param.value).then(() => {
show.value = false
showDialog({
message: '已成功获取用户信息!',
confirmButtonText: '关闭',
}).then(() => {
WeixinJSBridge.call('closeWindow')
})
})
}
</script>
<style scoped lang="less">
.wrapper {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
.block {
width: 120px;
height: 120px;
background-color: #fff;
}
</style>

1
types/global.d.ts vendored
View File

@@ -61,6 +61,7 @@ declare global {
VITE_GLOB_APP_TITLE: string
VITE_GLOB_APP_SHORT_NAME: string
VITE_DROP_CONSOLE: boolean
VITE_V_CONSOLE: boolean
VITE_PROXY: [string, string][]
VITE_BUILD_COMPRESS: 'gzip' | 'brotli' | 'none'
VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE: boolean

View File

@@ -132,7 +132,7 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
server: {
host: true,
// 服务启动时是否自动打开浏览器
open: true,
open: false,
// 服务端口号
port: Number(VITE_PORT),
proxy: createProxy(VITE_PROXY),