feat 多商户适配中

This commit is contained in:
DaxPay
2024-09-23 19:27:15 +08:00
parent 91945d4399
commit 2ba1318212
31 changed files with 6459 additions and 5406 deletions

View File

@@ -21,7 +21,7 @@ VITE_GLOB_UPLOAD_URL =
VITE_GLOB_IMG_URL =
# 接口前缀
VITE_GLOB_API_URL_PREFIX = /server
VITE_GLOB_API_URL_PREFIX = /

View File

@@ -4,7 +4,7 @@
# 网站根目录(与PC部署在一起, 所以根目录不可以为 /) 和 接口 (server) 前缀 这个是独立部署模式
VITE_PUBLIC_PATH=/h5
VITE_GLOB_API_URL_PREFIX=/server
VITE_GLOB_API_URL_PREFIX=
# 是否删除console
VITE_DROP_CONSOLE=true

View File

@@ -11,13 +11,15 @@
## 🍒 项目地址
| 项目 | GITEE | GITHUB |
|---------|---------------------------------------------|-------------------------------------------------|
| ----------- | ------------------------------------------- | ----------------------------------------------- |
| 后端地址 | [GITEE](https://gitee.com/dromara/dax-pay) | [GITHUB](https://github.com/dromara/dax-pay) |
| Web前端地址 | [GITEE](https://gitee.com/bootx/dax-pay-ui) | [GITHUB](https://github.com/xxm1995/dax-pay-ui) |
| H5前端地址 | [GITEE](https://gitee.com/bootx/dax-pay-h5) | [GITHUB](https://github.com/xxm1995/dax-pay-h5) |
## 🏬 系统演示
### 管理平台:
> 注:演示账号部分功能修改删除权限未开放。
地址https://daxpay.demo.bootx.cn
@@ -27,6 +29,7 @@
密码123456
### 网关接口
> 注:接口平台只开放支付网关相关的接口,不开放系统其他接口。
地址: https://daxpay.server.bootx.cn/doc.html
@@ -36,6 +39,7 @@
密码: 123456
### 收银台演示
> 请勿大额支付,可以通过后台管理端进行退款
电脑收银台地址: https://daxpay.demo.bootx.cn/#/cashier

View File

@@ -6,7 +6,7 @@ import { viteMockServe } from 'vite-plugin-mock'
export function configMockPlugin(isBuild: boolean, prodMock: boolean) {
return viteMockServe({
ignore: /^\_/,
ignore: /^_/,
mockPath: 'mock',
localEnabled: !isBuild,
prodEnabled: isBuild && prodMock,

View File

@@ -19,10 +19,7 @@
}
// 设置主题色变量
document.documentElement.style.setProperty(
'--app-theme-color',
appTheme,
)
document.documentElement.style.setProperty('--app-theme-color', appTheme)
})()
</script>
<style>

View File

@@ -1,25 +1,10 @@
{
"name": "vue3-vant4-mobile",
"name": "daxpay-h5",
"type": "module",
"version": "2.1.0",
"private": true,
"packageManager": "pnpm@8.6.10",
"author": {
"name": "xiangshu233",
"email": "xiangshu233@outlook.com",
"url": "https://github.com/xiangshu233"
},
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/xiangshu233/vue3-vant4-mobile.git"
},
"bugs": {
"url": "https://github.com/xiangshu233/vue3-vant4-mobile/issues"
},
"version": "3.0.0",
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0",
"pnpm": ">=8.6.10"
"node": ">=18.12.0",
"pnpm": ">=9.0.2"
},
"scripts": {
"preinstall": "npx only-allow pnpm",
@@ -40,60 +25,58 @@
},
"dependencies": {
"@types/lodash-es": "^4.17.12",
"@unocss/reset": "^0.58.5",
"@vueuse/core": "^10.7.0",
"axios": "^1.4.0",
"date-fns": "^3.0.6",
"echarts": "^5.4.3",
"@unocss/reset": "^0.58.9",
"@vueuse/core": "^10.11.1",
"axios": "^1.7.7",
"date-fns": "^3.6.0",
"lodash-es": "^4.17.21",
"mockjs": "^1.1.0",
"nprogress": "^0.2.0",
"pinia": "^2.1.7",
"pinia": "^2.2.2",
"pinia-plugin-persist": "^1.0.0",
"qs": "^6.11.2",
"vant": "^4.8.1",
"vue": "^3.3.13",
"qs": "^6.13.0",
"vant": "^4.9.7",
"vue": "^3.5.8",
"vue-router": "4.2.5"
},
"devDependencies": {
"@antfu/eslint-config": "^2.6.3",
"@commitlint/cli": "^18.4.3",
"@commitlint/config-conventional": "^18.4.3",
"@iconify/json": "^2.2.188",
"@antfu/eslint-config": "^2.27.3",
"@commitlint/cli": "^18.6.1",
"@commitlint/config-conventional": "^18.6.3",
"@iconify/json": "^2.2.252",
"@types/fs-extra": "^11.0.4",
"@types/mockjs": "^1.0.10",
"@types/node": "^20.10.5",
"@types/node": "^20.16.5",
"@types/nprogress": "^0.2.3",
"@types/qs": "^6.9.11",
"@unocss/eslint-plugin": "^0.58.4",
"@unocss/preset-icons": "^0.58.5",
"@unocss/preset-rem-to-px": "^0.58.5",
"@unocss/transformer-directives": "^0.58.4",
"@unocss/transformer-variant-group": "^0.58.4",
"@vitejs/plugin-vue": "^5.0.0",
"autoprefixer": "^10.4.16",
"@types/qs": "^6.9.16",
"@unocss/eslint-plugin": "^0.58.9",
"@unocss/preset-icons": "^0.58.9",
"@unocss/preset-rem-to-px": "^0.58.9",
"@unocss/transformer-directives": "^0.58.9",
"@unocss/transformer-variant-group": "^0.58.9",
"@vitejs/plugin-vue": "^5.1.4",
"autoprefixer": "^10.4.20",
"cross-env": "^7.0.3",
"cz-git": "^1.8.0",
"dotenv": "^16.3.1",
"eslint": "^8.56.0",
"eslint-plugin-format": "^0.1.0",
"cz-git": "^1.9.4",
"dotenv": "^16.4.5",
"eslint": "^8.57.1",
"eslint-plugin-format": "^0.1.2",
"esno": "^0.16.3",
"fs-extra": "^11.2.0",
"less": "^4.2.0",
"lint-staged": "^15.2.0",
"lint-staged": "^15.2.10",
"only-allow": "^1.2.1",
"picocolors": "^1.0.0",
"postcss": "^8.4.32",
"postcss-mobile-forever": "^4.0.0",
"picocolors": "^1.1.0",
"postcss": "^8.4.47",
"postcss-mobile-forever": "^4.1.6",
"rimraf": "^3.0.2",
"rollup": "^4.9.1",
"rollup-plugin-visualizer": "^5.11.0",
"simple-git-hooks": "^2.9.0",
"typescript": "^5.3.3",
"unocss": "^0.58.5",
"unplugin-auto-import": "^0.17.5",
"rollup": "^4.22.4",
"rollup-plugin-visualizer": "^5.12.0",
"simple-git-hooks": "^2.11.1",
"typescript": "^5.6.2",
"unocss": "^0.58.9",
"unplugin-auto-import": "^0.17.8",
"unplugin-vue-components": "^0.26.0",
"vite": "^5.0.10",
"vite": "5.2.6",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-html": "^3.2.2",
"vite-plugin-mock": "^2.9.8",

11002
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,86 +0,0 @@
import { Result } from '#/axios'
import { http } from '@/utils/http/axios'
/**
* 获取文件预览地址
*/
export const getFilePreviewUrl = (id) => {
return http.request<Result<string>>({
url: `/file/getFilePreviewUrl`,
method: 'get',
params: { id },
})
}
/**
* 获取文件预览地址前缀
*/
export const getFilePreviewUrlPrefix = () => {
return http.request<Result<string>>({
method: 'get',
url: `/file/getFilePreviewUrlPrefix`,
})
}
/**
* 获取文件下载地址
*/
export const getFileDownloadUrl = (id) => {
return http.request<Result<string>>({
method: 'get',
url: `/file/getFileDownloadUrl`,
params: { id },
})
}
/**
* 上传文件信息
*/
export interface UpdateFileInfo {
// id
id?: number
// 文件访问地址
url?: string
// 文件大小,单位字节
size?: string
// 文件名称
filename?: string
// 原始文件名
originalFilename?: string
// 基础存储路径
basePath?: string
// 存储路径
path?: string
// 文件扩展名
ext?: string
// MIME类型
contentType?: string
// 存储平台
platform?: string
// 缩略图访问路径
thUrl?: string
// 缩略图名称
thFilename?: string
// 缩略图大小,单位字节
thSize?: string
// 缩略图MIME类型
thContentType?: string
// 文件所属对象id
objectId?: string
// 文件所属对象类型,例如用户头像,评价图片
objectType?: string
// 文件元数据
metadata?: string
// 文件用户元数据
userMetadata?: string
// 缩略图元数据
thMetadata?: string
// 缩略图用户元数据
thUserMetadata?: string
// 附加属性
attr?: string
// 文件ACL
fileAcl?: string
// 缩略图文件ACL
thFileAcl?: string
}

View File

@@ -1,5 +1,5 @@
import { http } from '@/utils/http/axios'
import { Result } from '#/axios'
import type { Result } from '#/axios'
export interface BasicResponseModel<T = any> {
code: number

View File

@@ -1,14 +0,0 @@
// token key
export const TOKEN_KEY = 'TOKEN'
// user info key
export const USER_INFO_KEY = 'USER__INFO__'
// role info key
export const ROLES_KEY = 'ROLES__KEY__'
// base global local key
export const BASE_LOCAL_CACHE_KEY = 'LOCAL__CACHE__KEY__'
// base global session key
export const BASE_SESSION_CACHE_KEY = 'SESSION__CACHE__KEY__'

View File

@@ -1,11 +1,9 @@
/* eslint-disable ts/no-duplicate-enum-values */
export enum PageEnum {
// 登录
BASE_LOGIN = '/login',
BASE_LOGIN_NAME = 'Login',
// 首页
BASE_HOME = '/dashboard',
BASE_HOME_REDIRECT = '/dashboard',
// 错误
ERROR_PAGE_NAME = 'ErrorPage',
}

View File

@@ -10,11 +10,10 @@ export function useGlobSetting(): Readonly<GlobConfig> {
VITE_GLOB_APP_SHORT_NAME,
VITE_GLOB_API_URL_PREFIX,
VITE_GLOB_UPLOAD_URL,
VITE_GLOB_PROD_MOCK,
VITE_GLOB_IMG_URL,
} = getAppEnvConfig()
if (!/[a-zA-Z\_]*/.test(VITE_GLOB_APP_SHORT_NAME)) {
if (!/[a-z_]*/i.test(VITE_GLOB_APP_SHORT_NAME)) {
warn(
`VITE_GLOB_APP_SHORT_NAME Variables can only be characters/underscores, please modify in the environment variables and re-running.`,
)
@@ -28,7 +27,6 @@ export function useGlobSetting(): Readonly<GlobConfig> {
shortName: VITE_GLOB_APP_SHORT_NAME,
urlPrefix: VITE_GLOB_API_URL_PREFIX,
uploadUrl: VITE_GLOB_UPLOAD_URL,
prodMock: VITE_GLOB_PROD_MOCK,
imgUrl: VITE_GLOB_IMG_URL,
}
return glob as Readonly<GlobConfig>

View File

@@ -1,122 +0,0 @@
import type { EChartsOption } from 'echarts'
import type { Ref } from 'vue'
import type { Fn } from '@vueuse/core'
import { tryOnUnmounted, useDebounceFn } from '@vueuse/core'
import { computed, nextTick, ref, unref, watch } from 'vue'
import { useTimeoutFn } from '@/hooks/core/useTimeout'
import { useEventListener } from '@/hooks/event/useEventListener'
import { useBreakpoint } from '@/hooks/event/useBreakpoint'
import { useDesignSettingStore } from '@/store/modules/designSetting'
import echarts from '@/utils/lib/echarts'
export function useECharts(
elRef: Ref<HTMLDivElement>,
theme: 'light' | 'dark' | 'default' = 'default',
) {
const designStore = useDesignSettingStore()
const getDarkMode = computed(() => {
return theme === 'default' ? designStore.getDarkMode : theme
})
let chartInstance: echarts.ECharts | null = null
let resizeFn: Fn = resize
const cacheOptions = ref({})
let removeResizeFn: Fn = () => {}
resizeFn = useDebounceFn(resize, 200)
const getOptions = computed((): EChartsOption => {
if (getDarkMode.value !== 'dark') {
return cacheOptions.value
}
return {
backgroundColor: 'transparent',
...cacheOptions.value,
}
})
function initCharts(t = theme) {
const el = unref(elRef)
if (!el || !unref(el)) {
return
}
chartInstance = echarts.init(el, t)
const { removeEvent } = useEventListener({
el: window,
name: 'resize',
listener: resizeFn,
})
removeResizeFn = removeEvent
const { widthRef, screenEnum } = useBreakpoint()
if (unref(widthRef) <= screenEnum.MD || el.offsetHeight === 0) {
useTimeoutFn(() => {
resizeFn()
}, 30)
}
}
function setOptions(options: EChartsOption, clear = true) {
cacheOptions.value = options
if (unref(elRef)?.offsetHeight === 0) {
useTimeoutFn(() => {
setOptions(unref(getOptions))
}, 30)
return
}
nextTick(() => {
useTimeoutFn(() => {
if (!chartInstance) {
initCharts(getDarkMode.value as 'default')
if (!chartInstance) {
return
}
}
clear && chartInstance?.clear()
chartInstance?.setOption(unref(getOptions))
}, 30)
})
}
function resize() {
chartInstance?.resize()
}
watch(
() => getDarkMode.value,
(theme) => {
if (chartInstance) {
chartInstance.dispose()
initCharts(theme as 'default')
setOptions(cacheOptions.value)
}
},
)
tryOnUnmounted(() => {
if (!chartInstance) {
return
}
removeResizeFn()
chartInstance.dispose()
chartInstance = null
})
function getInstance(): echarts.ECharts | null {
if (!chartInstance) {
initCharts(getDarkMode.value as 'default')
}
return chartInstance
}
return {
setOptions,
resize,
echarts,
getInstance,
}
}

View File

@@ -24,12 +24,3 @@ export const ErrorPageRoute: RouteRecordRaw = {
},
],
}
export const RootRoute: RouteRecordRaw = {
path: '/',
name: 'Root',
redirect: PageEnum.BASE_HOME,
meta: {
title: 'Root',
},
}

View File

@@ -1,4 +1,5 @@
import { RouteRecordRaw } from 'vue-router'
import type { RouteRecordRaw } from 'vue-router'
import { PageEnum } from '@/enums/pageEnum'
const Layout = () => import('@/layout/index.vue')
@@ -8,6 +9,7 @@ const Layout = () => import('@/layout/index.vue')
export const BusinessRoute: RouteRecordRaw = {
path: '/',
name: '',
redirect: PageEnum.BASE_HOME,
component: Layout,
children: [
{

View File

@@ -1,4 +1,4 @@
import { RouteRecordRaw } from 'vue-router'
import type { RouteRecordRaw } from 'vue-router'
const Layout = () => import('@/layout/index.vue')
@@ -6,8 +6,8 @@ const Layout = () => import('@/layout/index.vue')
* 演示模块路由
*/
export const DemoRoute: RouteRecordRaw = {
path: '/',
name: '',
path: '/demo',
name: 'demo',
component: Layout,
children: [
{

View File

@@ -3,7 +3,7 @@ import type { RouteRecordRaw } from 'vue-router'
import { createRouter, createWebHashHistory } from 'vue-router'
import { createRouterGuards } from './router-guards'
import routeModuleList from './modules'
import { ErrorPageRoute, RootRoute } from '@/router/base'
import { ErrorPageRoute } from '@/router/base'
import { useRouteStoreWidthOut } from '@/store/modules/route'
// 菜单
@@ -13,7 +13,6 @@ import { DemoRoute } from '@/router/demo'
// 普通路由
export const constantRouter: RouteRecordRaw[] = [
DemoRoute,
RootRoute,
ErrorPageRoute,
BusinessRoute,
]

View File

@@ -19,7 +19,7 @@ export function getBoundingClientRect(element: Element): DOMRect | number {
}
function trim(string: string) {
return (string || '').replace(/^[\s\uFEFF]+|[\s\uFEFF]+$/g, '')
return (string || '').replace(/^\s+|\s+$/g, '')
}
/* istanbul ignore next */

View File

@@ -33,7 +33,7 @@ export function getAppEnvConfig() {
VITE_GLOB_IMG_URL,
} = ENV
if (!/^[a-zA-Z\_]*$/.test(VITE_GLOB_APP_SHORT_NAME)) {
if (!/^[a-z_]*$/i.test(VITE_GLOB_APP_SHORT_NAME)) {
warn(
`VITE_GLOB_APP_SHORT_NAME Variables can only be characters/underscores, please modify in the environment variables and re-running.`,
)

View File

@@ -55,7 +55,6 @@ export class VAxios {
request<T = any>(config: AxiosRequestConfig, options?: RequestOptions): Promise<T> {
let conf: any = cloneDeep(config)
const transform = this.getTransform()
const { requestOptions } = this.options
const opt: RequestOptions = { ...requestOptions, ...options }
@@ -69,7 +68,6 @@ export class VAxios {
conf.requestOptions = opt
// 支持 FormData
conf = this.supportFormData(conf)
return new Promise((resolve, reject) => {
this.axiosInstance
.request<any, AxiosResponse<Result>>(conf)

View File

@@ -1,10 +1,13 @@
// axios配置 可自行根据项目进行更改,只需更改该文件即可,其他文件可以不动
import type { AxiosResponse } from 'axios'
import axios from 'axios'
import { showDialog, showFailToast } from 'vant'
import { VAxios } from './Axios'
import { AxiosTransform } from './axiosTransform'
import axios, { AxiosResponse } from 'axios'
import type { AxiosTransform } from './axiosTransform'
import { checkStatus } from './checkStatus'
import { joinTimestamp, formatRequestDate } from './helper'
import { RequestEnum, ResultEnum, ContentTypeEnum } from '@/enums/httpEnum'
import { formatRequestDate, joinTimestamp } from './helper'
import type { CreateAxiosOptions, RequestOptions } from './types'
import { ContentTypeEnum, RequestEnum, ResultEnum } from '@/enums/httpEnum'
import { PageEnum } from '@/enums/pageEnum'
import { useGlobSetting } from '@/hooks/setting'
@@ -12,17 +15,14 @@ import { isString } from '@/utils/is/'
import { deepMerge, isUrl } from '@/utils'
import { setObjToUrlParams } from '@/utils/urlUtils'
import { RequestOptions, CreateAxiosOptions } from './types'
import { useUserStoreWidthOut } from '@/store/modules/user'
const globSetting = useGlobSetting()
const urlPrefix = globSetting.urlPrefix || ''
import router from '@/router'
import { storage } from '@/utils/Storage'
import { showFailToast, showDialog } from 'vant'
import { Result } from '#/axios'
import type { Result } from '#/axios'
const globSetting = useGlobSetting()
const urlPrefix = globSetting.urlPrefix
/**
* @description: 数据处理,方便区分多种处理方式
@@ -70,10 +70,12 @@ const transform: AxiosTransform = {
}).then(() => {
// on close
})
} else if (!hasSuccess && (errorMessageText || isShowErrorMessage)) {
}
else if (!hasSuccess && (errorMessageText || isShowErrorMessage)) {
// 是否显示自定义信息提示
showFailToast(msg || errorMessageText || '操作失败!')
} else if (!hasSuccess && options.errorMessageMode === 'modal') {
}
else if (!hasSuccess && options.errorMessageMode === 'modal') {
// errorMessageMode=custom-modal的时候会显示modal错误弹窗而不是消息提示用于一些比较重要的错误
showDialog({
title: '提示',
@@ -100,7 +102,9 @@ const transform: AxiosTransform = {
case ResultEnum.TOKEN_EXPIRED:
const LoginName = PageEnum.BASE_LOGIN_NAME
const LoginPath = PageEnum.BASE_LOGIN
if (router.currentRoute.value?.name === LoginName) return
if (router.currentRoute.value?.name === LoginName) {
return
}
// 到登录页
errorMsg = '登录超时,请重新登录!'
showDialog({
@@ -122,7 +126,6 @@ const transform: AxiosTransform = {
// 请求之前处理config
beforeRequestHook: (config, options) => {
const { apiUrl, joinPrefix, joinParamsToUrl, formatDate, joinTime = true, urlPrefix } = options
const isUrlStr = isUrl(config.url as string)
if (!isUrlStr && joinPrefix) {
@@ -138,22 +141,25 @@ const transform: AxiosTransform = {
if (!isString(params)) {
// 给 get 请求加上时间戳参数,避免从缓存中拿数据。
config.params = Object.assign(params || {}, joinTimestamp(joinTime, false))
} else {
}
else {
// 兼容restful风格
config.url = config.url + params + `${joinTimestamp(joinTime, true)}`
config.url = `${config.url + params}${joinTimestamp(joinTime, true)}`
config.params = undefined
}
} else {
}
else {
if (!isString(params)) {
formatDate && formatRequestDate(params)
if (
Reflect.has(config, 'data') &&
config.data &&
(Object.keys(config.data).length > 0 || config.data instanceof FormData)
Reflect.has(config, 'data')
&& config.data
&& (Object.keys(config.data).length > 0 || config.data instanceof FormData)
) {
config.data = data
config.params = params
} else {
}
else {
config.data = data
// params 是添加到 url 的请求字符串中的,用于 get 请求
config.params = params
@@ -161,10 +167,11 @@ const transform: AxiosTransform = {
if (joinParamsToUrl) {
config.url = setObjToUrlParams(
config.url as string,
Object.assign({}, config.params, config.data),
{ ...config.params, ...config.data },
)
}
} else {
}
else {
// 兼容restful风格
config.url = config.url + params
config.params = undefined
@@ -192,11 +199,11 @@ const transform: AxiosTransform = {
responseInterceptorsCatch: (error: any) => {
const { response, code, message } = error || {}
// TODO 此处要根据后端接口返回格式修改
const msg: string =
response && response.data && response.data.message ? response.data.message : ''
const msg: string
= response && response.data && response.data.message ? response.data.message : ''
const err: string = error.toString()
try {
if (code === 'ECONNABORTED' && message.indexOf('timeout') !== -1) {
if (code === 'ECONNABORTED' && message.includes('timeout')) {
showFailToast('接口请求超时,请刷新页面重试!')
return
}
@@ -209,7 +216,8 @@ const transform: AxiosTransform = {
.catch(() => {})
return Promise.reject(error)
}
} catch (error) {
}
catch (error) {
console.log(error)
throw new Error(error as any)
}
@@ -217,10 +225,11 @@ const transform: AxiosTransform = {
const isCancel = axios.isCancel(error)
if (!isCancel) {
checkStatus(error.response && error.response.status, msg)
} else {
}
else {
console.warn(error, '请求被取消!')
}
//return Promise.reject(error);
// return Promise.reject(error);
return Promise.reject(response?.data)
},
}
@@ -257,7 +266,7 @@ function createAxios(opt?: Partial<CreateAxiosOptions>) {
// 接口地址
apiUrl: globSetting.apiUrl,
// 接口拼接地址
urlPrefix: urlPrefix,
urlPrefix,
// 是否加入时间戳
joinTime: true,
// 忽略重复请求

View File

@@ -1,57 +0,0 @@
import * as echarts from 'echarts/core'
import {
BarChart,
GaugeChart,
LineChart,
MapChart,
PictorialBarChart,
PieChart,
RadarChart,
} from 'echarts/charts'
import {
AriaComponent,
CalendarComponent,
DataZoomComponent,
GridComponent,
LegendComponent,
MarkLineComponent,
ParallelComponent,
PolarComponent,
RadarComponent,
TimelineComponent,
TitleComponent,
ToolboxComponent,
TooltipComponent,
VisualMapComponent,
} from 'echarts/components'
import { SVGRenderer } from 'echarts/renderers'
echarts.use([
LegendComponent,
TitleComponent,
TooltipComponent,
GridComponent,
PolarComponent,
AriaComponent,
ParallelComponent,
BarChart,
LineChart,
PieChart,
MapChart,
RadarChart,
GaugeChart,
SVGRenderer,
PictorialBarChart,
RadarComponent,
ToolboxComponent,
DataZoomComponent,
VisualMapComponent,
TimelineComponent,
CalendarComponent,
MarkLineComponent,
])
export default echarts

View File

@@ -74,6 +74,7 @@ declare global {
const onStartTyping: typeof import('@vueuse/core')['onStartTyping']
const onUnmounted: typeof import('vue')['onUnmounted']
const onUpdated: typeof import('vue')['onUpdated']
const onWatcherCleanup: typeof import('vue')['onWatcherCleanup']
const pausableWatch: typeof import('@vueuse/core')['pausableWatch']
const provide: typeof import('vue')['provide']
const provideLocal: typeof import('@vueuse/core')['provideLocal']
@@ -185,6 +186,7 @@ declare global {
const useFullscreen: typeof import('@vueuse/core')['useFullscreen']
const useGamepad: typeof import('@vueuse/core')['useGamepad']
const useGeolocation: typeof import('@vueuse/core')['useGeolocation']
const useId: typeof import('vue')['useId']
const useIdle: typeof import('@vueuse/core')['useIdle']
const useImage: typeof import('@vueuse/core')['useImage']
const useInfiniteScroll: typeof import('@vueuse/core')['useInfiniteScroll']
@@ -201,6 +203,7 @@ declare global {
const useMediaQuery: typeof import('@vueuse/core')['useMediaQuery']
const useMemoize: typeof import('@vueuse/core')['useMemoize']
const useMemory: typeof import('@vueuse/core')['useMemory']
const useModel: typeof import('vue')['useModel']
const useMounted: typeof import('@vueuse/core')['useMounted']
const useMouse: typeof import('@vueuse/core')['useMouse']
const useMouseInElement: typeof import('@vueuse/core')['useMouseInElement']
@@ -248,6 +251,7 @@ declare global {
const useStyleTag: typeof import('@vueuse/core')['useStyleTag']
const useSupported: typeof import('@vueuse/core')['useSupported']
const useSwipe: typeof import('@vueuse/core')['useSwipe']
const useTemplateRef: typeof import('vue')['useTemplateRef']
const useTemplateRefsList: typeof import('@vueuse/core')['useTemplateRefsList']
const useTextDirection: typeof import('@vueuse/core')['useTextDirection']
const useTextSelection: typeof import('@vueuse/core')['useTextSelection']

18
types/axios.d.ts vendored
View File

@@ -2,19 +2,19 @@
* 通用响应类
*/
export interface Result<T = any> {
code: number;
type: 'success' | 'error' | 'warning';
msg: string;
traceId: string | null | undefined;
data: T;
code: number
type: 'success' | 'error' | 'warning'
msg: string
traceId: string | null | undefined
data: T
}
/**
* 分页响应类
*/
export interface PageResult<T = any> {
current: number;
records: Array<T>;
size: number;
total: number;
current: number
records: Array<T>
size: number
total: number
}

28
types/config.d.ts vendored
View File

@@ -1,26 +1,26 @@
export interface GlobConfig {
title: string;
titleCN: string;
apiUrl: string;
shortName: string;
urlPrefix?: string;
uploadUrl?: string;
imgUrl?: string;
title: string
titleCN: string
apiUrl: string
shortName: string
urlPrefix?: string
uploadUrl?: string
imgUrl?: string
}
export interface GlobEnvConfig {
// 标题
VITE_GLOB_APP_TITLE: string;
VITE_GLOB_APP_TITLE: string
// 中文标题
VITE_GLOB_APP_TITLE_CN: string;
VITE_GLOB_APP_TITLE_CN: string
// 接口地址
VITE_GLOB_API_URL: string;
VITE_GLOB_API_URL: string
// 接口前缀
VITE_GLOB_API_URL_PREFIX?: string;
VITE_GLOB_API_URL_PREFIX?: string
// Project abbreviation
VITE_GLOB_APP_SHORT_NAME: string;
VITE_GLOB_APP_SHORT_NAME: string
// 图片上传地址
VITE_GLOB_UPLOAD_URL?: string;
VITE_GLOB_UPLOAD_URL?: string
// 图片前缀地址
VITE_GLOB_IMG_URL?: string;
VITE_GLOB_IMG_URL?: string
}

74
types/global.d.ts vendored
View File

@@ -1,9 +1,9 @@
import type {
VNodeChild,
ComponentPublicInstance,
FunctionalComponent,
VNodeChild,
PropType as VuePropType,
} from 'vue';
} from 'vue'
// declare global 在具有 import 或 export 声明全局范围内的事物的文件中使用。
// 这在包含 import 或 export 因为此类文件被视为模块的文件中是必需的,并且在模块中声明的任何内容都在模块范围内。
@@ -12,64 +12,64 @@ import type {
declare global {
const __APP_INFO__: {
pkg: {
name: string;
version: string;
dependencies: Recordable<string>;
devDependencies: Recordable<string>;
};
lastBuildTime: string;
};
name: string
version: string
dependencies: Recordable<string>
devDependencies: Recordable<string>
}
lastBuildTime: string
}
// vue
type PropType<T> = VuePropType<T>;
type VueNode = VNodeChild | JSX.Element;
type PropType<T> = VuePropType<T>
type VueNode = VNodeChild | JSX.Element
export type Writable<T> = {
-readonly [P in keyof T]: T[P];
};
}
type Nullable<T> = T | null;
type NonNullable<T> = T extends null | undefined ? never : T;
type Recordable<T = any> = Record<string, T>;
type ReadonlyRecordable<T = any> = {
readonly [key: string]: T;
};
type Indexable<T = any> = {
[key: string]: T;
};
type Nullable<T> = T | null
type NonNullable<T> = T extends null | undefined ? never : T
type Recordable<T = any> = Record<string, T>
interface ReadonlyRecordable<T = any> {
readonly [key: string]: T
}
interface Indexable<T = any> {
[key: string]: T
}
type DeepPartial<T> = {
[P in keyof T]?: DeepPartial<T[P]>;
};
type TimeoutHandle = ReturnType<typeof setTimeout>;
type IntervalHandle = ReturnType<typeof setInterval>;
}
type TimeoutHandle = ReturnType<typeof setTimeout>
type IntervalHandle = ReturnType<typeof setInterval>
interface ChangeEvent extends Event {
target: HTMLInputElement;
target: HTMLInputElement
}
interface WheelEvent {
path?: EventTarget[];
path?: EventTarget[]
}
interface ImportMetaEnv extends ViteEnv {
__: unknown;
__: unknown
}
interface ViteEnv {
VITE_PORT: number;
VITE_PUBLIC_PATH: string;
VITE_GLOB_APP_TITLE: string;
VITE_GLOB_APP_SHORT_NAME: string;
VITE_DROP_CONSOLE: boolean;
VITE_GLOB_IMG_URL: string;
VITE_PROXY: [string, string][];
VITE_BUILD_COMPRESS: 'gzip' | 'brotli' | 'none';
VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE: boolean;
VITE_PORT: number
VITE_PUBLIC_PATH: string
VITE_GLOB_APP_TITLE: string
VITE_GLOB_APP_SHORT_NAME: string
VITE_DROP_CONSOLE: boolean
VITE_GLOB_IMG_URL: string
VITE_PROXY: [string, string][]
VITE_BUILD_COMPRESS: 'gzip' | 'brotli' | 'none'
VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE: boolean
}
}
declare module 'vue' {
export type JSXComponent<Props = any> =
| { new (): ComponentPublicInstance<Props> }
| FunctionalComponent<Props>;
| FunctionalComponent<Props>
}

26
types/index.d.ts vendored
View File

@@ -1,29 +1,29 @@
declare interface Fn<T = any, R = T> {
(...arg: T[]): R;
(...arg: T[]): R
}
declare interface PromiseFn<T = any, R = T> {
(...arg: T[]): Promise<R>;
(...arg: T[]): Promise<R>
}
declare type RefType<T> = T | null;
declare type RefType<T> = T | null
// 就是数组里的 value 是这个对象类型
declare type LabelValueOptions = {
label: string;
value: any;
disabled: boolean;
[key: string]: string | number | boolean;
}[];
label: string
value: any
disabled: boolean
[key: string]: string | number | boolean
}[]
declare type EmitType = (event: string, ...args: any[]) => void;
declare type EmitType = (event: string, ...args: any[]) => void
declare type TargetContext = '_self' | '_blank';
declare type TargetContext = '_self' | '_blank'
declare interface ComponentElRef<T extends HTMLElement = HTMLDivElement> {
$el: T;
$el: T
}
declare type ComponentRef<T extends HTMLElement = HTMLDivElement> = ComponentElRef<T> | null;
declare type ComponentRef<T extends HTMLElement = HTMLDivElement> = ComponentElRef<T> | null
declare type ElRef<T extends HTMLElement = HTMLDivElement> = Nullable<T>;
declare type ElRef<T extends HTMLElement = HTMLDivElement> = Nullable<T>

7
types/modules.d.ts vendored
View File

@@ -1,7 +1,8 @@
/// <reference types="vite/client" />
declare module '*.vue' {
import { DefineComponent } from 'vue';
const Component: DefineComponent<{}, {}, any>;
export default Component;
import type { DefineComponent } from 'vue'
const Component: DefineComponent<{}, {}, any>
export default Component
}

18
types/web.d.ts vendored
View File

@@ -1,13 +1,13 @@
import { PageResult } from "@/types/axios";
import type { PageResult } from '@/types/axios'
/**
* 分页参数
*/
export interface PageParam {
// 每页数量
size: number;
size: number
// 当前页数
current: number;
current: number
}
/**
@@ -15,24 +15,24 @@ export interface PageParam {
*/
export interface TablePageModel<T = any> {
// 分页参数
pages: PageParam;
pages: PageParam
// 查询参数
queryParam: object;
queryParam: object
// 结果
pagination: PageResult<T>;
pagination: PageResult<T>
}
/**
* 基础实体对象
*/
export interface BaseEntity {
id?: number | string | null;
id?: number | string | null
}
/**
* 键值对对象
*/
export interface KeyValue {
key: string;
value: string;
key: string
value: string
}

View File

@@ -48,12 +48,12 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
alias: [
// @/xxxx => src/xxxx
{
find: /\@\//,
find: /@\//,
replacement: `${pathResolve('src')}/`,
},
// #/xxxx => types/xxxx
{
find: /\#\//,
find: /#\//,
replacement: `${pathResolve('types')}/`,
},
],