mirror of
https://github.com/XiaoDaiGua-Ray/ray-template.git
synced 2025-04-06 03:57:49 +08:00
v4.1.3
This commit is contained in:
parent
dd757d24a4
commit
01d44d46f3
40
CHANGELOG.md
40
CHANGELOG.md
@ -1,5 +1,45 @@
|
|||||||
# CHANGE LOG
|
# CHANGE LOG
|
||||||
|
|
||||||
|
## 4.1.3
|
||||||
|
|
||||||
|
### Feats
|
||||||
|
|
||||||
|
- 新增切换路由自动取消上一路由所有请求。但是可以通过配置 `useRequest` 与 `request` 方法的 `cancelConfig.needCancel` 属性控制是否需要自动取消该请求。该配置默认为 `true`,当配置为 `false` 时,则不会被取消器取消
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { useRequest, useHookPlusRequest } from '@/axios/index'
|
||||||
|
|
||||||
|
// useRequest
|
||||||
|
const { data, loading, run } = useRequest<{
|
||||||
|
title: string
|
||||||
|
}>(
|
||||||
|
{
|
||||||
|
url: 'https://jsonplaceholder.typicode.com/todos/1',
|
||||||
|
method: 'get',
|
||||||
|
cancelConfig: {
|
||||||
|
needCancel: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
manual: true,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
// request
|
||||||
|
request({
|
||||||
|
url: 'https://jsonplaceholder.typicode.com/todos/1',
|
||||||
|
method: 'get',
|
||||||
|
cancelConfig: {
|
||||||
|
needCancel: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
- `localConfig` 新增配置类型保护
|
||||||
|
- 将原 `AppComponent` 组件包移动至 `app-components` 包中,并且按照其功能拆分为 `sys` `provider`
|
||||||
|
- 现在将异步注册 `vue-router`
|
||||||
|
- `RayChart` 组件新增 `macarons` 主题。现在支持便捷的自定义主题,在[主题编辑器](https://echarts.apache.org/zh/theme-builder.html)编辑主题后,下载主题(json)放置于对应主题包中即可被自动注册
|
||||||
|
|
||||||
## 4.1.2
|
## 4.1.2
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { RouterView } from 'vue-router'
|
import { RouterView } from 'vue-router'
|
||||||
import AppNaiveGlobalProvider from '@/components/AppComponents/AppNaiveGlobalProvider/index'
|
import AppNaiveGlobalProvider from '@/app-components/provider/AppNaiveGlobalProvider/index'
|
||||||
import AppStyleProvider from '@/components/AppComponents/AppStyleProvider/index'
|
import AppStyleProvider from '@/app-components/provider/AppStyleProvider/index'
|
||||||
import GlobalSpin from '@/spin/index'
|
import GlobalSpin from '@/spin/index'
|
||||||
import LockScreen from '@/components/AppComponents/AppLockScreen/index'
|
import LockScreen from '@/app-components/app/AppLockScreen/index'
|
||||||
|
|
||||||
const App = defineComponent({
|
const App = defineComponent({
|
||||||
name: 'App',
|
name: 'App',
|
||||||
|
6
src/app-components/README.md
Normal file
6
src/app-components/README.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
## 描述
|
||||||
|
|
||||||
|
该包存放与模板深度绑定的组件:
|
||||||
|
|
||||||
|
- app:存放与模板数据绑定的组件
|
||||||
|
- sys:存放模板注入类组件
|
@ -12,14 +12,11 @@
|
|||||||
/** 锁屏界面 */
|
/** 锁屏界面 */
|
||||||
|
|
||||||
import { NInput, NForm, NFormItem, NButton, NSpace } from 'naive-ui'
|
import { NInput, NForm, NFormItem, NButton, NSpace } from 'naive-ui'
|
||||||
import AppAvatar from '@/components/AppComponents/AppAvatar/index'
|
import AppAvatar from '@/app-components/app/AppAvatar/index'
|
||||||
|
|
||||||
import { useSetting } from '@/store'
|
import { useSetting } from '@/store'
|
||||||
import useAppLockScreen from '@/components/AppComponents/AppLockScreen/appLockVar'
|
import useAppLockScreen from '@/app-components/app/AppLockScreen/appLockVar'
|
||||||
import {
|
import { rules, useCondition } from '@/app-components/app/AppLockScreen/hook'
|
||||||
rules,
|
|
||||||
useCondition,
|
|
||||||
} from '@/components/AppComponents/AppLockScreen/hook'
|
|
||||||
|
|
||||||
import type { FormInst, InputInst } from 'naive-ui'
|
import type { FormInst, InputInst } from 'naive-ui'
|
||||||
|
|
@ -12,15 +12,12 @@
|
|||||||
/** 解锁界面 */
|
/** 解锁界面 */
|
||||||
|
|
||||||
import { NInput, NForm, NFormItem, NButton, NSpace } from 'naive-ui'
|
import { NInput, NForm, NFormItem, NButton, NSpace } from 'naive-ui'
|
||||||
import AppAvatar from '@/components/AppComponents/AppAvatar/index'
|
import AppAvatar from '@/app-components/app/AppAvatar/index'
|
||||||
|
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import { useSetting, useSignin } from '@/store'
|
import { useSetting, useSignin } from '@/store'
|
||||||
import {
|
import { rules, useCondition } from '@/app-components/app/AppLockScreen/hook'
|
||||||
rules,
|
import useAppLockScreen from '@/app-components/app/AppLockScreen/appLockVar'
|
||||||
useCondition,
|
|
||||||
} from '@/components/AppComponents/AppLockScreen/hook'
|
|
||||||
import useAppLockScreen from '@/components/AppComponents/AppLockScreen/appLockVar'
|
|
||||||
|
|
||||||
import type { FormInst, InputInst } from 'naive-ui'
|
import type { FormInst, InputInst } from 'naive-ui'
|
||||||
|
|
@ -22,7 +22,7 @@ import LockScreen from './components/LockScreen'
|
|||||||
import UnlockScreen from './components/UnlockScreen'
|
import UnlockScreen from './components/UnlockScreen'
|
||||||
|
|
||||||
import { useSetting } from '@/store'
|
import { useSetting } from '@/store'
|
||||||
import useAppLockScreen from '@/components/AppComponents/AppLockScreen/appLockVar'
|
import useAppLockScreen from '@/app-components/app/AppLockScreen/appLockVar'
|
||||||
|
|
||||||
const AppLockScreen = defineComponent({
|
const AppLockScreen = defineComponent({
|
||||||
name: 'AppLockScreen',
|
name: 'AppLockScreen',
|
40
src/app-components/provider/AppRequestCanceler/index.tsx
Normal file
40
src/app-components/provider/AppRequestCanceler/index.tsx
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Ray <https://github.com/XiaoDaiGua-Ray>
|
||||||
|
*
|
||||||
|
* @date 2023-07-21
|
||||||
|
*
|
||||||
|
* @workspace ray-template
|
||||||
|
*
|
||||||
|
* @remark 今天也是元气满满撸代码的一天
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 路由更新前,取消上一路由所有请求
|
||||||
|
*
|
||||||
|
* 生命周期示意图:
|
||||||
|
* beforeRouteUpdate -> cancelAllRequest -> routerUpdate
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { axiosCanceler } from '@/axios/helper/interceptor'
|
||||||
|
|
||||||
|
const AppRequestCanceler = defineComponent({
|
||||||
|
name: 'AppRequestCanceler',
|
||||||
|
setup() {
|
||||||
|
onBeforeRouteUpdate(() => {
|
||||||
|
axiosCanceler.cancelAllRequest()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'none',
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
export default AppRequestCanceler
|
@ -19,7 +19,7 @@ import type { AppLocalesDropdownMixedOption } from '@/locales/type'
|
|||||||
* 语言包语种添加后, 需要在此文件配置语言包
|
* 语言包语种添加后, 需要在此文件配置语言包
|
||||||
* 该配置中的 key 也会影响 naiveLocales 方法, 配置后请仔细核对一下
|
* 该配置中的 key 也会影响 naiveLocales 方法, 配置后请仔细核对一下
|
||||||
*
|
*
|
||||||
* 添加新的语言包后, 如果需要其类型提示, 需要在 CurrentAppMessages 中添加新的类型
|
* 添加新的语言包后, 如果需要其类型提示, 需要在 AppCurrentAppMessages 中添加新的类型
|
||||||
*/
|
*/
|
||||||
export const LOCAL_OPTIONS: AppLocalesDropdownMixedOption[] = [
|
export const LOCAL_OPTIONS: AppLocalesDropdownMixedOption[] = [
|
||||||
{
|
{
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
* 可以根据自己项目进行定制化配置
|
* 可以根据自己项目进行定制化配置
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { AxiosRequestConfig } from 'axios'
|
import type { AppRawRequestConfig } from '@/axios/type'
|
||||||
|
|
||||||
export default class RequestCanceler {
|
export default class RequestCanceler {
|
||||||
pendingRequest: Map<string, AbortController>
|
pendingRequest: Map<string, AbortController>
|
||||||
@ -25,6 +25,11 @@ export default class RequestCanceler {
|
|||||||
this.pendingRequest = new Map<string, AbortController>()
|
this.pendingRequest = new Map<string, AbortController>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 是否需要加入取消请求表中 */
|
||||||
|
isApending(config: AppRawRequestConfig) {
|
||||||
|
return config.cancelConfig?.needCancel ?? true
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param config 请求体 config
|
* @param config 请求体 config
|
||||||
@ -32,7 +37,7 @@ export default class RequestCanceler {
|
|||||||
*
|
*
|
||||||
* @remark 将当前请求 config 生成 request key
|
* @remark 将当前请求 config 生成 request key
|
||||||
*/
|
*/
|
||||||
generateRequestKey(config: AxiosRequestConfig): string {
|
generateRequestKey(config: AppRawRequestConfig): string {
|
||||||
const { method, url } = config
|
const { method, url } = config
|
||||||
|
|
||||||
return [
|
return [
|
||||||
@ -49,18 +54,20 @@ export default class RequestCanceler {
|
|||||||
*
|
*
|
||||||
* @remark 给请求体添加 signal 属性, 用于取消请求
|
* @remark 给请求体添加 signal 属性, 用于取消请求
|
||||||
*/
|
*/
|
||||||
addPendingRequest(config: AxiosRequestConfig) {
|
addPendingRequest(config: AppRawRequestConfig) {
|
||||||
const requestKey = this.generateRequestKey(config)
|
if (this.isApending(config)) {
|
||||||
|
const requestKey = this.generateRequestKey(config)
|
||||||
|
|
||||||
if (!this.pendingRequest.has(requestKey)) {
|
if (!this.pendingRequest.has(requestKey)) {
|
||||||
const controller = new AbortController()
|
const controller = new AbortController()
|
||||||
|
|
||||||
config.signal = controller.signal
|
config.signal = controller.signal
|
||||||
|
|
||||||
this.pendingRequest.set(requestKey, controller)
|
this.pendingRequest.set(requestKey, controller)
|
||||||
} else {
|
} else {
|
||||||
// 如果已经有该 key 则重新挂载 signal
|
// 如果已经有该 key 则重新挂载 signal
|
||||||
config.signal = this.pendingRequest.get(requestKey)?.signal
|
config.signal = this.pendingRequest.get(requestKey)?.signal
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +77,7 @@ export default class RequestCanceler {
|
|||||||
*
|
*
|
||||||
* @remark 取消该请求, 并且清除 map 中对应 generateRequestKey value
|
* @remark 取消该请求, 并且清除 map 中对应 generateRequestKey value
|
||||||
*/
|
*/
|
||||||
removePendingRequest(config: AxiosRequestConfig) {
|
removePendingRequest(config: AppRawRequestConfig) {
|
||||||
const requestKey = this.generateRequestKey(config)
|
const requestKey = this.generateRequestKey(config)
|
||||||
|
|
||||||
if (this.pendingRequest.has(requestKey)) {
|
if (this.pendingRequest.has(requestKey)) {
|
||||||
@ -79,4 +86,11 @@ export default class RequestCanceler {
|
|||||||
this.pendingRequest.delete(requestKey)
|
this.pendingRequest.delete(requestKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 取消所有请求 */
|
||||||
|
cancelAllRequest() {
|
||||||
|
this.pendingRequest.forEach((curr) => {
|
||||||
|
curr.abort()
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ import type {
|
|||||||
AxiosFetchInstance,
|
AxiosFetchInstance,
|
||||||
AxiosFetchError,
|
AxiosFetchError,
|
||||||
} from '@/axios/type'
|
} from '@/axios/type'
|
||||||
import type { AnyFunc } from '@/types/modules/utils'
|
import type { AnyFC } from '@/types/modules/utils'
|
||||||
|
|
||||||
/** 当前请求的实例 */
|
/** 当前请求的实例 */
|
||||||
const axiosFetchInstance: AxiosFetchInstance = {
|
const axiosFetchInstance: AxiosFetchInstance = {
|
||||||
@ -77,7 +77,7 @@ export const useAxiosInterceptor = () => {
|
|||||||
/** 设置注入方法队列 */
|
/** 设置注入方法队列 */
|
||||||
const setImplement = (
|
const setImplement = (
|
||||||
key: keyof ImplementQueue | keyof ErrorImplementQueue,
|
key: keyof ImplementQueue | keyof ErrorImplementQueue,
|
||||||
func: AnyFunc[],
|
func: AnyFC[],
|
||||||
fetchType: FetchType,
|
fetchType: FetchType,
|
||||||
) => {
|
) => {
|
||||||
fetchType === 'ok' ? (implement[key] = func) : (errorImplement[key] = func)
|
fetchType === 'ok' ? (implement[key] = func) : (errorImplement[key] = func)
|
||||||
@ -87,12 +87,12 @@ export const useAxiosInterceptor = () => {
|
|||||||
const getImplement = (
|
const getImplement = (
|
||||||
key: keyof ImplementQueue | keyof ErrorImplementQueue,
|
key: keyof ImplementQueue | keyof ErrorImplementQueue,
|
||||||
fetchType: FetchType,
|
fetchType: FetchType,
|
||||||
): AnyFunc[] => {
|
): AnyFC[] => {
|
||||||
return fetchType === 'ok' ? implement[key] : errorImplement[key]
|
return fetchType === 'ok' ? implement[key] : errorImplement[key]
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 队列执行器 */
|
/** 队列执行器 */
|
||||||
const implementer = (funcs: AnyFunc[], ...args: any[]) => {
|
const implementer = (funcs: AnyFC[], ...args: any[]) => {
|
||||||
if (Array.isArray(funcs)) {
|
if (Array.isArray(funcs)) {
|
||||||
funcs?.forEach((curr) => {
|
funcs?.forEach((curr) => {
|
||||||
if (typeof curr === 'function') {
|
if (typeof curr === 'function') {
|
||||||
|
@ -25,7 +25,7 @@ import useHookPlusRequest from 'vue-hooks-plus/es/useRequest'
|
|||||||
import request from '@/axios/instance'
|
import request from '@/axios/instance'
|
||||||
|
|
||||||
import type { UseRequestOptions } from 'vue-hooks-plus/es/useRequest/types'
|
import type { UseRequestOptions } from 'vue-hooks-plus/es/useRequest/types'
|
||||||
import type { AxiosRequestConfig } from 'axios'
|
import type { AppRawRequestConfig } from '@/axios/type'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -43,7 +43,7 @@ function useRequest<
|
|||||||
HookPlusParams extends unknown[] = unknown[],
|
HookPlusParams extends unknown[] = unknown[],
|
||||||
HookPlusPlugin = unknown,
|
HookPlusPlugin = unknown,
|
||||||
>(
|
>(
|
||||||
fetchOption: AxiosRequestConfig<Response>,
|
fetchOption: AppRawRequestConfig<Response>,
|
||||||
option?: UseRequestOptions<Response, HookPlusParams, HookPlusPlugin>,
|
option?: UseRequestOptions<Response, HookPlusParams, HookPlusPlugin>,
|
||||||
) {
|
) {
|
||||||
const fc = () => {
|
const fc = () => {
|
||||||
@ -52,7 +52,10 @@ function useRequest<
|
|||||||
return cb
|
return cb
|
||||||
}
|
}
|
||||||
|
|
||||||
const hooks = useHookPlusRequest(fc, Object.assign({}, option))
|
const hooks = useHookPlusRequest<Response, HookPlusParams>(
|
||||||
|
fc,
|
||||||
|
Object.assign({}, option),
|
||||||
|
)
|
||||||
|
|
||||||
return hooks
|
return hooks
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ import type {
|
|||||||
Axios,
|
Axios,
|
||||||
AxiosResponse,
|
AxiosResponse,
|
||||||
} from 'axios'
|
} from 'axios'
|
||||||
import type { AnyFunc } from '@/types/modules/utils'
|
import type { AnyFC } from '@/types/modules/utils'
|
||||||
|
|
||||||
export type AxiosHeaderValue =
|
export type AxiosHeaderValue =
|
||||||
| AxiosHeaders
|
| AxiosHeaders
|
||||||
@ -22,54 +22,65 @@ export interface RequestHeaderOptions {
|
|||||||
value: AxiosHeaderValue
|
value: AxiosHeaderValue
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AxiosInstanceExpand extends Axios {
|
export interface CancelConfig {
|
||||||
<T = any, D = any>(config: AxiosRequestConfig<D>): Promise<T>
|
needCancel?: boolean
|
||||||
<T = any, D = any>(url: string, config?: AxiosRequestConfig<D>): Promise<T>
|
}
|
||||||
|
|
||||||
getUri(config?: AxiosRequestConfig): string
|
export interface AppRawRequestConfig<T = any> extends AxiosRequestConfig<T> {
|
||||||
request<R = any, D = any>(config: AxiosRequestConfig<D>): Promise<R>
|
cancelConfig?: CancelConfig
|
||||||
get<R = any, D = any>(url: string, config?: AxiosRequestConfig<D>): Promise<R>
|
}
|
||||||
|
|
||||||
|
export interface AxiosInstanceExpand extends Axios {
|
||||||
|
<T = any, D = any>(config: AppRawRequestConfig<D>): Promise<T>
|
||||||
|
<T = any, D = any>(url: string, config?: AppRawRequestConfig<D>): Promise<T>
|
||||||
|
|
||||||
|
getUri(config?: AppRawRequestConfig): string
|
||||||
|
request<R = any, D = any>(config: AppRawRequestConfig<D>): Promise<R>
|
||||||
|
get<R = any, D = any>(
|
||||||
|
url: string,
|
||||||
|
config?: AppRawRequestConfig<D>,
|
||||||
|
): Promise<R>
|
||||||
delete<R = any, D = any>(
|
delete<R = any, D = any>(
|
||||||
url: string,
|
url: string,
|
||||||
config?: AxiosRequestConfig<D>,
|
config?: AppRawRequestConfig<D>,
|
||||||
): Promise<R>
|
): Promise<R>
|
||||||
head<R = any, D = any>(
|
head<R = any, D = any>(
|
||||||
url: string,
|
url: string,
|
||||||
config?: AxiosRequestConfig<D>,
|
config?: AppRawRequestConfig<D>,
|
||||||
): Promise<R>
|
): Promise<R>
|
||||||
options<R = any, D = any>(
|
options<R = any, D = any>(
|
||||||
url: string,
|
url: string,
|
||||||
config?: AxiosRequestConfig<D>,
|
config?: AppRawRequestConfig<D>,
|
||||||
): Promise<R>
|
): Promise<R>
|
||||||
post<R = any, D = any>(
|
post<R = any, D = any>(
|
||||||
url: string,
|
url: string,
|
||||||
data?: D,
|
data?: D,
|
||||||
config?: AxiosRequestConfig<D>,
|
config?: AppRawRequestConfig<D>,
|
||||||
): Promise<R>
|
): Promise<R>
|
||||||
put<R = any, D = any>(
|
put<R = any, D = any>(
|
||||||
url: string,
|
url: string,
|
||||||
data?: D,
|
data?: D,
|
||||||
config?: AxiosRequestConfig<D>,
|
config?: AppRawRequestConfig<D>,
|
||||||
): Promise<R>
|
): Promise<R>
|
||||||
patch<R = any, D = any>(
|
patch<R = any, D = any>(
|
||||||
url: string,
|
url: string,
|
||||||
data?: D,
|
data?: D,
|
||||||
config?: AxiosRequestConfig<D>,
|
config?: AppRawRequestConfig<D>,
|
||||||
): Promise<R>
|
): Promise<R>
|
||||||
postForm<R = any, D = any>(
|
postForm<R = any, D = any>(
|
||||||
url: string,
|
url: string,
|
||||||
data?: D,
|
data?: D,
|
||||||
config?: AxiosRequestConfig<D>,
|
config?: AppRawRequestConfig<D>,
|
||||||
): Promise<R>
|
): Promise<R>
|
||||||
putForm<R = any, D = any>(
|
putForm<R = any, D = any>(
|
||||||
url: string,
|
url: string,
|
||||||
data?: D,
|
data?: D,
|
||||||
config?: AxiosRequestConfig<D>,
|
config?: AppRawRequestConfig<D>,
|
||||||
): Promise<R>
|
): Promise<R>
|
||||||
patchForm<R = any, D = any>(
|
patchForm<R = any, D = any>(
|
||||||
url: string,
|
url: string,
|
||||||
data?: D,
|
data?: D,
|
||||||
config?: AxiosRequestConfig<D>,
|
config?: AppRawRequestConfig<D>,
|
||||||
): Promise<R>
|
): Promise<R>
|
||||||
|
|
||||||
defaults: Omit<AxiosDefaults, 'headers' | 'cancelToken'> & {
|
defaults: Omit<AxiosDefaults, 'headers' | 'cancelToken'> & {
|
||||||
@ -79,18 +90,18 @@ export interface AxiosInstanceExpand extends Axios {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type RequestInterceptorConfig<T = any> = AxiosRequestConfig<T>
|
export type RequestInterceptorConfig<T = any> = AppRawRequestConfig<T>
|
||||||
|
|
||||||
export type ResponseInterceptorConfig<T = any, K = any> = AxiosResponse<T, K>
|
export type ResponseInterceptorConfig<T = any, K = any> = AxiosResponse<T, K>
|
||||||
|
|
||||||
export interface ImplementQueue {
|
export interface ImplementQueue {
|
||||||
implementRequestInterceptorArray: AnyFunc[]
|
implementRequestInterceptorArray: AnyFC[]
|
||||||
implementResponseInterceptorArray: AnyFunc[]
|
implementResponseInterceptorArray: AnyFC[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ErrorImplementQueue {
|
export interface ErrorImplementQueue {
|
||||||
implementRequestInterceptorErrorArray: AnyFunc[]
|
implementRequestInterceptorErrorArray: AnyFC[]
|
||||||
implementResponseInterceptorErrorArray: AnyFunc[]
|
implementResponseInterceptorErrorArray: AnyFC[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export type BeforeFetchFunction<
|
export type BeforeFetchFunction<
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
## 描述
|
|
||||||
|
|
||||||
> 该组件包存放依赖系统数据的公共组件和与项目绑定的一些组件。
|
|
||||||
|
|
||||||
## 约束
|
|
||||||
|
|
||||||
- 该组件包仅存放与系统数据有绑定、关联的组件,纯组件或纯 UI 组件应放置于外层包中
|
|
||||||
- 以 `App` 开头标记组件是系统组件
|
|
||||||
- 组件应该尽量避免与其他系统组件有关联性
|
|
81
src/components/RayChart/helper.ts
Normal file
81
src/components/RayChart/helper.ts
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Ray <https://github.com/XiaoDaiGua-Ray>
|
||||||
|
*
|
||||||
|
* @date 2023-07-22
|
||||||
|
*
|
||||||
|
* @workspace ray-template
|
||||||
|
*
|
||||||
|
* @remark 今天也是元气满满撸代码的一天
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type {
|
||||||
|
ChartThemeRawArray,
|
||||||
|
ChartThemeRawModules,
|
||||||
|
LoadingOptions,
|
||||||
|
} from '@/components/RayChart/type'
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 自动注册所有主题
|
||||||
|
*
|
||||||
|
* 默认以文件名当作主题名称
|
||||||
|
*
|
||||||
|
* 主题配置器:https://echarts.apache.org/zh/theme-builder.html
|
||||||
|
* 流程:
|
||||||
|
* 1. 配置、选择主题
|
||||||
|
* 2. 点击下载主题
|
||||||
|
* 3. 选择 json 类型,然后复制
|
||||||
|
* 4. 在 @/components/RayChart/theme 包中创建对应的 json 文件,文件名为主题名称
|
||||||
|
*/
|
||||||
|
export const setupChartTheme = () => {
|
||||||
|
// 获取所有主题
|
||||||
|
const themeRawModules: Record<string, ChartThemeRawModules> =
|
||||||
|
import.meta.glob('@/components/RayChart/theme/**/*.json', {
|
||||||
|
eager: true,
|
||||||
|
})
|
||||||
|
const regx = /\/([^/]+)\.json$/
|
||||||
|
|
||||||
|
const rawThemes = Object.keys(themeRawModules).reduce((pre, curr) => {
|
||||||
|
const name = curr.match(regx)?.[1]
|
||||||
|
|
||||||
|
if (name) {
|
||||||
|
pre.push({
|
||||||
|
name,
|
||||||
|
theme: themeRawModules[curr].default,
|
||||||
|
})
|
||||||
|
|
||||||
|
return pre
|
||||||
|
} else {
|
||||||
|
throw new Error('theme name is not found')
|
||||||
|
}
|
||||||
|
}, [] as ChartThemeRawArray[])
|
||||||
|
|
||||||
|
return rawThemes
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @returns LoadingOptions
|
||||||
|
*
|
||||||
|
* 为了方便使用加载动画, 写了此方法, 虽然没啥用
|
||||||
|
*/
|
||||||
|
export const loadingOptions = (options?: LoadingOptions) =>
|
||||||
|
Object.assign(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
text: 'loading',
|
||||||
|
color: '#c23531',
|
||||||
|
textColor: '#000',
|
||||||
|
maskColor: 'rgba(255, 255, 255, 0.9)',
|
||||||
|
zlevel: 0,
|
||||||
|
fontSize: 12,
|
||||||
|
showSpinner: true,
|
||||||
|
spinnerRadius: 10,
|
||||||
|
lineWidth: 5,
|
||||||
|
fontWeight: 'normal',
|
||||||
|
fontStyle: 'normal',
|
||||||
|
fontFamily: 'sans-serif',
|
||||||
|
},
|
||||||
|
options,
|
||||||
|
)
|
@ -40,66 +40,22 @@ import { CanvasRenderer } from 'echarts/renderers' // `echarts` 渲染器
|
|||||||
|
|
||||||
import { useSetting } from '@/store'
|
import { useSetting } from '@/store'
|
||||||
import { cloneDeep, throttle } from 'lodash-es'
|
import { cloneDeep, throttle } from 'lodash-es'
|
||||||
import { on, off, addStyle, completeSize } from '@/utils/element'
|
import { on, off, completeSize } from '@/utils/element'
|
||||||
import { call } from '@/utils/vue/index'
|
import { call } from '@/utils/vue/index'
|
||||||
|
import { setupChartTheme, loadingOptions } from './helper'
|
||||||
|
|
||||||
import type { PropType } from 'vue'
|
import type { PropType } from 'vue'
|
||||||
import type { EChartsInstance } from '@/types/modules/component'
|
import type { EChartsInstance } from '@/types/modules/component'
|
||||||
import type { AnyFunc, MaybeArray } from '@/types/modules/utils'
|
import type { AnyFC, MaybeArray } from '@/types/modules/utils'
|
||||||
import type { DebouncedFunc } from 'lodash-es'
|
import type { DebouncedFunc } from 'lodash-es'
|
||||||
|
import type {
|
||||||
export type AutoResize =
|
LoadingOptions,
|
||||||
| boolean
|
AutoResize,
|
||||||
| {
|
ChartTheme,
|
||||||
width: number
|
} from '@/components/RayChart/type'
|
||||||
height: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface LoadingOptions {
|
|
||||||
text: string // 文本内容
|
|
||||||
color: string // 颜色
|
|
||||||
textColor: string // 字体颜色
|
|
||||||
maskColor: string // 遮罩颜色
|
|
||||||
zlevel: number // 水平
|
|
||||||
fontSize: number // 字体大小
|
|
||||||
showSpinner: boolean // 是否显示旋转动画(`spinner`)
|
|
||||||
spinnerRadius: number // 旋转动画(`spinner`)的半径
|
|
||||||
lineWidth: number // 旋转动画(`spinner`)的线宽
|
|
||||||
fontWeight: string // 字体粗细
|
|
||||||
fontStyle: string // 字体风格
|
|
||||||
fontFamily: string // 字体系列
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ChartTheme = 'dark' | '' | object
|
|
||||||
|
|
||||||
export type EChartsExtensionInstallRegisters = typeof CanvasRenderer
|
export type EChartsExtensionInstallRegisters = typeof CanvasRenderer
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @returns LoadingOptions
|
|
||||||
*
|
|
||||||
* 为了方便使用加载动画, 写了此方法, 虽然没啥用
|
|
||||||
*/
|
|
||||||
export const loadingOptions = (options?: LoadingOptions) =>
|
|
||||||
Object.assign(
|
|
||||||
{},
|
|
||||||
{
|
|
||||||
text: 'loading',
|
|
||||||
color: '#c23531',
|
|
||||||
textColor: '#000',
|
|
||||||
maskColor: 'rgba(255, 255, 255, 0.9)',
|
|
||||||
zlevel: 0,
|
|
||||||
fontSize: 12,
|
|
||||||
showSpinner: true,
|
|
||||||
spinnerRadius: 10,
|
|
||||||
lineWidth: 5,
|
|
||||||
fontWeight: 'normal',
|
|
||||||
fontStyle: 'normal',
|
|
||||||
fontFamily: 'sans-serif',
|
|
||||||
},
|
|
||||||
options,
|
|
||||||
)
|
|
||||||
|
|
||||||
const RayChart = defineComponent({
|
const RayChart = defineComponent({
|
||||||
name: 'RayChart',
|
name: 'RayChart',
|
||||||
props: {
|
props: {
|
||||||
@ -229,7 +185,7 @@ const RayChart = defineComponent({
|
|||||||
const rayChartRef = ref<HTMLElement>() // `echart` 容器实例
|
const rayChartRef = ref<HTMLElement>() // `echart` 容器实例
|
||||||
const echartInstanceRef = ref<EChartsInstance>() // `echart` 拷贝实例, 解决直接使用响应式实例带来的问题
|
const echartInstanceRef = ref<EChartsInstance>() // `echart` 拷贝实例, 解决直接使用响应式实例带来的问题
|
||||||
let echartInstance: EChartsInstance // `echart` 实例
|
let echartInstance: EChartsInstance // `echart` 实例
|
||||||
let resizeThrottle: DebouncedFunc<AnyFunc> // resize 防抖方法实例
|
let resizeThrottle: DebouncedFunc<AnyFC> // resize 防抖方法实例
|
||||||
|
|
||||||
const cssVarsRef = computed(() => {
|
const cssVarsRef = computed(() => {
|
||||||
const cssVars = {
|
const cssVars = {
|
||||||
@ -294,13 +250,13 @@ const RayChart = defineComponent({
|
|||||||
*
|
*
|
||||||
* 如果有需要特殊全局配置的可以在此继续写...
|
* 如果有需要特殊全局配置的可以在此继续写...
|
||||||
*/
|
*/
|
||||||
const useMergeOptions = () => {
|
const combineChartOptions = () => {
|
||||||
let options = cloneDeep(props.options)
|
let options = cloneDeep(props.options)
|
||||||
|
|
||||||
const merge = (opts: object) => Object.assign({}, options, opts)
|
const assign = (opts: object) => Object.assign({}, options, opts)
|
||||||
|
|
||||||
if (props.showAria) {
|
if (props.showAria) {
|
||||||
options = merge({
|
options = assign({
|
||||||
aria: {
|
aria: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
decal: {
|
decal: {
|
||||||
@ -321,32 +277,28 @@ const RayChart = defineComponent({
|
|||||||
*
|
*
|
||||||
* 直接使用响应式代理实例会出现诡异的问题, 例如 `legend` 点击时报错
|
* 直接使用响应式代理实例会出现诡异的问题, 例如 `legend` 点击时报错
|
||||||
*/
|
*/
|
||||||
const renderChart = (theme: ChartTheme) => {
|
const renderChart = (theme: ChartTheme = 'macarons') => {
|
||||||
/** 获取 dom 容器 */
|
/** 获取 dom 容器 */
|
||||||
const element = rayChartRef.value as HTMLElement
|
const element = rayChartRef.value as HTMLElement
|
||||||
/** 获取配置项 */
|
/** 获取配置项 */
|
||||||
const options = useMergeOptions()
|
const options = combineChartOptions()
|
||||||
/** 获取 dom 容器实际宽高 */
|
/** 获取 dom 容器实际宽高 */
|
||||||
const { height, width } = element.getBoundingClientRect()
|
const { height, width } = element.getBoundingClientRect()
|
||||||
const { success, error } = props
|
const { success, error } = props
|
||||||
|
|
||||||
/** 如果高度为 0, 则以 200px 填充 */
|
|
||||||
if (height === 0) {
|
|
||||||
addStyle(element, {
|
|
||||||
height: '200px',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 如果款度为 0, 则以 200px 填充 */
|
|
||||||
if (width === 0) {
|
|
||||||
addStyle(element, {
|
|
||||||
width: '200px',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
/** 注册主题 */
|
||||||
|
setupChartTheme().forEach((curr) => {
|
||||||
|
echarts.registerTheme(curr.name, curr.theme)
|
||||||
|
})
|
||||||
|
|
||||||
/** 注册 chart */
|
/** 注册 chart */
|
||||||
echartInstance = echarts.init(element, theme)
|
echartInstance = echarts.init(element, theme, {
|
||||||
|
/** 如果款度为 0, 则以 200px 填充 */
|
||||||
|
width: width === 0 ? 200 : undefined,
|
||||||
|
/** 如果高度为 0, 则以 200px 填充 */
|
||||||
|
height: height === 0 ? 200 : undefined,
|
||||||
|
})
|
||||||
echartInstanceRef.value = echartInstance
|
echartInstanceRef.value = echartInstance
|
||||||
|
|
||||||
/** 设置 options 配置项 */
|
/** 设置 options 配置项 */
|
||||||
@ -373,13 +325,13 @@ const RayChart = defineComponent({
|
|||||||
*/
|
*/
|
||||||
const renderThemeChart = (bool?: boolean) => {
|
const renderThemeChart = (bool?: boolean) => {
|
||||||
if (props.autoChangeTheme) {
|
if (props.autoChangeTheme) {
|
||||||
bool ? renderChart('dark') : renderChart('')
|
bool ? renderChart('dark') : renderChart()
|
||||||
|
|
||||||
return void 0
|
return void 0
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!props.theme) {
|
if (!props.theme) {
|
||||||
renderChart('')
|
renderChart()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -431,9 +383,9 @@ const RayChart = defineComponent({
|
|||||||
* 自动跟随模板主题或者指定主题皆可
|
* 自动跟随模板主题或者指定主题皆可
|
||||||
*/
|
*/
|
||||||
if (props.autoChangeTheme || props.theme) {
|
if (props.autoChangeTheme || props.theme) {
|
||||||
themeValue.value ? renderChart('dark') : renderChart('')
|
themeValue.value ? renderChart('dark') : renderChart()
|
||||||
} else {
|
} else {
|
||||||
renderChart('')
|
renderChart()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -454,7 +406,7 @@ const RayChart = defineComponent({
|
|||||||
() => props.watchOptions,
|
() => props.watchOptions,
|
||||||
() => {
|
() => {
|
||||||
/** 重新组合 options */
|
/** 重新组合 options */
|
||||||
const options = useMergeOptions()
|
const options = combineChartOptions()
|
||||||
|
|
||||||
/** 如果 options 发生变动更新 echarts */
|
/** 如果 options 发生变动更新 echarts */
|
||||||
echartInstance?.setOption(options)
|
echartInstance?.setOption(options)
|
||||||
@ -473,7 +425,7 @@ const RayChart = defineComponent({
|
|||||||
if (props.autoChangeTheme) {
|
if (props.autoChangeTheme) {
|
||||||
renderThemeChart(themeValue.value)
|
renderThemeChart(themeValue.value)
|
||||||
} else {
|
} else {
|
||||||
props.theme ? renderChart('dark') : renderChart('')
|
props.theme ? renderChart('dark') : renderChart()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 注册事件 */
|
/** 注册事件 */
|
||||||
|
396
src/components/RayChart/theme/macarons.json
Normal file
396
src/components/RayChart/theme/macarons.json
Normal file
@ -0,0 +1,396 @@
|
|||||||
|
{
|
||||||
|
"color": [
|
||||||
|
"#2ec7c9",
|
||||||
|
"#b6a2de",
|
||||||
|
"#5ab1ef",
|
||||||
|
"#ffb980",
|
||||||
|
"#d87a80",
|
||||||
|
"#8d98b3",
|
||||||
|
"#e5cf0d",
|
||||||
|
"#97b552",
|
||||||
|
"#95706d",
|
||||||
|
"#dc69aa",
|
||||||
|
"#07a2a4",
|
||||||
|
"#9a7fd1",
|
||||||
|
"#588dd5",
|
||||||
|
"#f5994e",
|
||||||
|
"#c05050",
|
||||||
|
"#59678c",
|
||||||
|
"#c9ab00",
|
||||||
|
"#7eb00a",
|
||||||
|
"#6f5553",
|
||||||
|
"#c14089"
|
||||||
|
],
|
||||||
|
"backgroundColor": "rgba(0,0,0,0)",
|
||||||
|
"textStyle": {},
|
||||||
|
"title": {
|
||||||
|
"textStyle": {
|
||||||
|
"color": "#008acd"
|
||||||
|
},
|
||||||
|
"subtextStyle": {
|
||||||
|
"color": "#aaaaaa"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"line": {
|
||||||
|
"itemStyle": {
|
||||||
|
"borderWidth": 1
|
||||||
|
},
|
||||||
|
"lineStyle": {
|
||||||
|
"width": 2
|
||||||
|
},
|
||||||
|
"symbolSize": 3,
|
||||||
|
"symbol": "emptyCircle",
|
||||||
|
"smooth": true
|
||||||
|
},
|
||||||
|
"radar": {
|
||||||
|
"itemStyle": {
|
||||||
|
"borderWidth": 1
|
||||||
|
},
|
||||||
|
"lineStyle": {
|
||||||
|
"width": 2
|
||||||
|
},
|
||||||
|
"symbolSize": 3,
|
||||||
|
"symbol": "emptyCircle",
|
||||||
|
"smooth": true
|
||||||
|
},
|
||||||
|
"bar": {
|
||||||
|
"itemStyle": {
|
||||||
|
"barBorderWidth": 0,
|
||||||
|
"barBorderColor": "#ccc"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pie": {
|
||||||
|
"itemStyle": {
|
||||||
|
"borderWidth": 0,
|
||||||
|
"borderColor": "#ccc"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"scatter": {
|
||||||
|
"itemStyle": {
|
||||||
|
"borderWidth": 0,
|
||||||
|
"borderColor": "#ccc"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"boxplot": {
|
||||||
|
"itemStyle": {
|
||||||
|
"borderWidth": 0,
|
||||||
|
"borderColor": "#ccc"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parallel": {
|
||||||
|
"itemStyle": {
|
||||||
|
"borderWidth": 0,
|
||||||
|
"borderColor": "#ccc"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sankey": {
|
||||||
|
"itemStyle": {
|
||||||
|
"borderWidth": 0,
|
||||||
|
"borderColor": "#ccc"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"funnel": {
|
||||||
|
"itemStyle": {
|
||||||
|
"borderWidth": 0,
|
||||||
|
"borderColor": "#ccc"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"gauge": {
|
||||||
|
"itemStyle": {
|
||||||
|
"borderWidth": 0,
|
||||||
|
"borderColor": "#ccc"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"candlestick": {
|
||||||
|
"itemStyle": {
|
||||||
|
"color": "#d87a80",
|
||||||
|
"color0": "#2ec7c9",
|
||||||
|
"borderColor": "#d87a80",
|
||||||
|
"borderColor0": "#2ec7c9",
|
||||||
|
"borderWidth": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"graph": {
|
||||||
|
"itemStyle": {
|
||||||
|
"borderWidth": 0,
|
||||||
|
"borderColor": "#ccc"
|
||||||
|
},
|
||||||
|
"lineStyle": {
|
||||||
|
"width": 1,
|
||||||
|
"color": "#aaa"
|
||||||
|
},
|
||||||
|
"symbolSize": 3,
|
||||||
|
"symbol": "emptyCircle",
|
||||||
|
"smooth": true,
|
||||||
|
"color": [
|
||||||
|
"#2ec7c9",
|
||||||
|
"#b6a2de",
|
||||||
|
"#5ab1ef",
|
||||||
|
"#ffb980",
|
||||||
|
"#d87a80",
|
||||||
|
"#8d98b3",
|
||||||
|
"#e5cf0d",
|
||||||
|
"#97b552",
|
||||||
|
"#95706d",
|
||||||
|
"#dc69aa",
|
||||||
|
"#07a2a4",
|
||||||
|
"#9a7fd1",
|
||||||
|
"#588dd5",
|
||||||
|
"#f5994e",
|
||||||
|
"#c05050",
|
||||||
|
"#59678c",
|
||||||
|
"#c9ab00",
|
||||||
|
"#7eb00a",
|
||||||
|
"#6f5553",
|
||||||
|
"#c14089"
|
||||||
|
],
|
||||||
|
"label": {
|
||||||
|
"color": "#eee"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"map": {
|
||||||
|
"itemStyle": {
|
||||||
|
"areaColor": "#dddddd",
|
||||||
|
"borderColor": "#eeeeee",
|
||||||
|
"borderWidth": 0.5
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"color": "#d87a80"
|
||||||
|
},
|
||||||
|
"emphasis": {
|
||||||
|
"itemStyle": {
|
||||||
|
"areaColor": "rgba(254,153,78,1)",
|
||||||
|
"borderColor": "#444",
|
||||||
|
"borderWidth": 1
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"color": "rgb(100,0,0)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"geo": {
|
||||||
|
"itemStyle": {
|
||||||
|
"areaColor": "#dddddd",
|
||||||
|
"borderColor": "#eeeeee",
|
||||||
|
"borderWidth": 0.5
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"color": "#d87a80"
|
||||||
|
},
|
||||||
|
"emphasis": {
|
||||||
|
"itemStyle": {
|
||||||
|
"areaColor": "rgba(254,153,78,1)",
|
||||||
|
"borderColor": "#444",
|
||||||
|
"borderWidth": 1
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"color": "rgb(100,0,0)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"categoryAxis": {
|
||||||
|
"axisLine": {
|
||||||
|
"show": true,
|
||||||
|
"lineStyle": {
|
||||||
|
"color": "#008acd"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"axisTick": {
|
||||||
|
"show": true,
|
||||||
|
"lineStyle": {
|
||||||
|
"color": "#333"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"axisLabel": {
|
||||||
|
"show": true,
|
||||||
|
"color": "#333"
|
||||||
|
},
|
||||||
|
"splitLine": {
|
||||||
|
"show": false,
|
||||||
|
"lineStyle": {
|
||||||
|
"color": ["#eee"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"splitArea": {
|
||||||
|
"show": false,
|
||||||
|
"areaStyle": {
|
||||||
|
"color": ["rgba(250,250,250,0.3)", "rgba(200,200,200,0.3)"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"valueAxis": {
|
||||||
|
"axisLine": {
|
||||||
|
"show": true,
|
||||||
|
"lineStyle": {
|
||||||
|
"color": "#008acd"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"axisTick": {
|
||||||
|
"show": true,
|
||||||
|
"lineStyle": {
|
||||||
|
"color": "#333"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"axisLabel": {
|
||||||
|
"show": true,
|
||||||
|
"color": "#333"
|
||||||
|
},
|
||||||
|
"splitLine": {
|
||||||
|
"show": true,
|
||||||
|
"lineStyle": {
|
||||||
|
"color": ["#eee"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"splitArea": {
|
||||||
|
"show": true,
|
||||||
|
"areaStyle": {
|
||||||
|
"color": ["rgba(250,250,250,0.3)", "rgba(200,200,200,0.3)"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"logAxis": {
|
||||||
|
"axisLine": {
|
||||||
|
"show": true,
|
||||||
|
"lineStyle": {
|
||||||
|
"color": "#008acd"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"axisTick": {
|
||||||
|
"show": true,
|
||||||
|
"lineStyle": {
|
||||||
|
"color": "#333"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"axisLabel": {
|
||||||
|
"show": true,
|
||||||
|
"color": "#333"
|
||||||
|
},
|
||||||
|
"splitLine": {
|
||||||
|
"show": true,
|
||||||
|
"lineStyle": {
|
||||||
|
"color": ["#eee"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"splitArea": {
|
||||||
|
"show": true,
|
||||||
|
"areaStyle": {
|
||||||
|
"color": ["rgba(250,250,250,0.3)", "rgba(200,200,200,0.3)"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"timeAxis": {
|
||||||
|
"axisLine": {
|
||||||
|
"show": true,
|
||||||
|
"lineStyle": {
|
||||||
|
"color": "#008acd"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"axisTick": {
|
||||||
|
"show": true,
|
||||||
|
"lineStyle": {
|
||||||
|
"color": "#333"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"axisLabel": {
|
||||||
|
"show": true,
|
||||||
|
"color": "#333"
|
||||||
|
},
|
||||||
|
"splitLine": {
|
||||||
|
"show": true,
|
||||||
|
"lineStyle": {
|
||||||
|
"color": ["#eee"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"splitArea": {
|
||||||
|
"show": false,
|
||||||
|
"areaStyle": {
|
||||||
|
"color": ["rgba(250,250,250,0.3)", "rgba(200,200,200,0.3)"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"toolbox": {
|
||||||
|
"iconStyle": {
|
||||||
|
"borderColor": "#2ec7c9"
|
||||||
|
},
|
||||||
|
"emphasis": {
|
||||||
|
"iconStyle": {
|
||||||
|
"borderColor": "#18a4a6"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"legend": {
|
||||||
|
"textStyle": {
|
||||||
|
"color": "#333333"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"axisPointer": {
|
||||||
|
"lineStyle": {
|
||||||
|
"color": "#008acd",
|
||||||
|
"width": "1"
|
||||||
|
},
|
||||||
|
"crossStyle": {
|
||||||
|
"color": "#008acd",
|
||||||
|
"width": "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"timeline": {
|
||||||
|
"lineStyle": {
|
||||||
|
"color": "#008acd",
|
||||||
|
"width": 1
|
||||||
|
},
|
||||||
|
"itemStyle": {
|
||||||
|
"color": "#008acd",
|
||||||
|
"borderWidth": 1
|
||||||
|
},
|
||||||
|
"controlStyle": {
|
||||||
|
"color": "#008acd",
|
||||||
|
"borderColor": "#008acd",
|
||||||
|
"borderWidth": 0.5
|
||||||
|
},
|
||||||
|
"checkpointStyle": {
|
||||||
|
"color": "#2ec7c9",
|
||||||
|
"borderColor": "#2ec7c9"
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"color": "#008acd"
|
||||||
|
},
|
||||||
|
"emphasis": {
|
||||||
|
"itemStyle": {
|
||||||
|
"color": "#a9334c"
|
||||||
|
},
|
||||||
|
"controlStyle": {
|
||||||
|
"color": "#008acd",
|
||||||
|
"borderColor": "#008acd",
|
||||||
|
"borderWidth": 0.5
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"color": "#008acd"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"visualMap": {
|
||||||
|
"color": ["#5ab1ef", "#e0ffff"]
|
||||||
|
},
|
||||||
|
"dataZoom": {
|
||||||
|
"backgroundColor": "rgba(47,69,84,0)",
|
||||||
|
"dataBackgroundColor": "#efefff",
|
||||||
|
"fillerColor": "rgba(182,162,222,0.2)",
|
||||||
|
"handleColor": "#008acd",
|
||||||
|
"handleSize": "100%",
|
||||||
|
"textStyle": {
|
||||||
|
"color": "#333333"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"markPoint": {
|
||||||
|
"label": {
|
||||||
|
"color": "#eee"
|
||||||
|
},
|
||||||
|
"emphasis": {
|
||||||
|
"label": {
|
||||||
|
"color": "#eee"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
43
src/components/RayChart/type.ts
Normal file
43
src/components/RayChart/type.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Ray <https://github.com/XiaoDaiGua-Ray>
|
||||||
|
*
|
||||||
|
* @date 2023-07-22
|
||||||
|
*
|
||||||
|
* @workspace ray-template
|
||||||
|
*
|
||||||
|
* @remark 今天也是元气满满撸代码的一天
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface ChartThemeRawModules {
|
||||||
|
default: Record<string, UnknownObjectKey>
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ChartThemeRawArray {
|
||||||
|
name: string
|
||||||
|
theme: UnknownObjectKey
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LoadingOptions {
|
||||||
|
text: string // 文本内容
|
||||||
|
color: string // 颜色
|
||||||
|
textColor: string // 字体颜色
|
||||||
|
maskColor: string // 遮罩颜色
|
||||||
|
zlevel: number // 水平
|
||||||
|
fontSize: number // 字体大小
|
||||||
|
showSpinner: boolean // 是否显示旋转动画(`spinner`)
|
||||||
|
spinnerRadius: number // 旋转动画(`spinner`)的半径
|
||||||
|
lineWidth: number // 旋转动画(`spinner`)的线宽
|
||||||
|
fontWeight: string // 字体粗细
|
||||||
|
fontStyle: string // 字体风格
|
||||||
|
fontFamily: string // 字体系列
|
||||||
|
}
|
||||||
|
|
||||||
|
export type AutoResize =
|
||||||
|
| boolean
|
||||||
|
| {
|
||||||
|
width: number
|
||||||
|
height: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ChartTheme = 'dark' | string | object | 'macarons'
|
@ -72,7 +72,6 @@ const RayCollapseGrid = defineComponent({
|
|||||||
collapsed={this.modelCollapsed}
|
collapsed={this.modelCollapsed}
|
||||||
xGap={this.xGap || 12}
|
xGap={this.xGap || 12}
|
||||||
yGap={this.yGap || 18}
|
yGap={this.yGap || 18}
|
||||||
cols={this.cols}
|
|
||||||
collapsedRows={this.collapsedRows}
|
collapsedRows={this.collapsedRows}
|
||||||
>
|
>
|
||||||
{this.$slots.default?.()}
|
{this.$slots.default?.()}
|
||||||
|
@ -2,7 +2,7 @@ import { gridProps } from 'naive-ui'
|
|||||||
|
|
||||||
import type { PropType } from 'vue'
|
import type { PropType } from 'vue'
|
||||||
import type { CollapseToggleText } from './type'
|
import type { CollapseToggleText } from './type'
|
||||||
import type { AnyFunc, MaybeArray } from '@/types/modules/utils'
|
import type { AnyFC, MaybeArray } from '@/types/modules/utils'
|
||||||
|
|
||||||
export const collapseGridProps = {
|
export const collapseGridProps = {
|
||||||
value: {
|
value: {
|
||||||
|
@ -88,6 +88,7 @@ const RayIcon = defineComponent({
|
|||||||
call(onClick, e)
|
call(onClick, e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
modelColor,
|
modelColor,
|
||||||
symbolId,
|
symbolId,
|
||||||
|
@ -1,6 +1,15 @@
|
|||||||
export type DayjsLocal = 'zh-cn' | 'en'
|
import type { AppCurrentAppMessages } from '@/locales/type'
|
||||||
|
|
||||||
export interface DayjsLocalMap {
|
type A<T> = {
|
||||||
'zh-CN': 'zh-cn'
|
[K in keyof T & string]: T[K] extends object ? string : never
|
||||||
'en-US': 'en'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PickDayjsLocalValue<T> = {
|
||||||
|
[K in keyof T]: T[K]
|
||||||
|
}[keyof T]
|
||||||
|
|
||||||
|
type DayjsLocalMaps = A<AppCurrentAppMessages>
|
||||||
|
|
||||||
|
export type DayjsLocal = PickDayjsLocalValue<DayjsLocalMaps>
|
||||||
|
|
||||||
|
export type DayjsLocalMap = Record<keyof AppCurrentAppMessages, DayjsLocal>
|
||||||
|
@ -27,7 +27,7 @@ import type { DirectiveModules } from '@/directives/type'
|
|||||||
export const setupDirectives = (app: App<Element>) => {
|
export const setupDirectives = (app: App<Element>) => {
|
||||||
// 获取 modules 包下所有的 index.ts 文件
|
// 获取 modules 包下所有的 index.ts 文件
|
||||||
const directiveRawModules: Record<string, DirectiveModules> =
|
const directiveRawModules: Record<string, DirectiveModules> =
|
||||||
import.meta.glob('./modules/**/index.ts', {
|
import.meta.glob('@/directives/modules/**/index.ts', {
|
||||||
eager: true,
|
eager: true,
|
||||||
})
|
})
|
||||||
// 将所有的包提取出来(./modules/[file-name]/index.ts)
|
// 将所有的包提取出来(./modules/[file-name]/index.ts)
|
||||||
|
@ -52,4 +52,5 @@ const copyDirective: CustomDirectiveFC<CopyElement, string> = () => {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default copyDirective
|
export default copyDirective
|
||||||
|
@ -19,7 +19,7 @@ import { on, off } from '@use-utils/element'
|
|||||||
|
|
||||||
import type { Directive } from 'vue'
|
import type { Directive } from 'vue'
|
||||||
import type { DebounceBindingOptions } from './type'
|
import type { DebounceBindingOptions } from './type'
|
||||||
import type { AnyFunc } from '@/types/modules/utils'
|
import type { AnyFC } from '@/types/modules/utils'
|
||||||
import type { DebouncedFunc } from 'lodash-es'
|
import type { DebouncedFunc } from 'lodash-es'
|
||||||
import type { CustomDirectiveFC } from '@/directives/type'
|
import type { CustomDirectiveFC } from '@/directives/type'
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ const debounceDirective: CustomDirectiveFC<
|
|||||||
HTMLElement,
|
HTMLElement,
|
||||||
DebounceBindingOptions
|
DebounceBindingOptions
|
||||||
> = () => {
|
> = () => {
|
||||||
let debounceFunction: DebouncedFunc<AnyFunc> | null
|
let debounceFunction: DebouncedFunc<AnyFC> | null
|
||||||
|
|
||||||
return {
|
return {
|
||||||
beforeMount: (el, binding) => {
|
beforeMount: (el, binding) => {
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import type { DebounceSettings } from 'lodash-es'
|
import type { DebounceSettings } from 'lodash-es'
|
||||||
import type { AnyFunc } from '@/types/modules/utils'
|
import type { AnyFC } from '@/types/modules/utils'
|
||||||
|
|
||||||
export interface DebounceBindingOptions {
|
export interface DebounceBindingOptions {
|
||||||
func: AnyFunc
|
func: AnyFC
|
||||||
trigger: string
|
trigger: string
|
||||||
wait: number
|
wait: number
|
||||||
options: DebounceSettings
|
options: DebounceSettings
|
||||||
|
@ -42,4 +42,5 @@ const disabledDirective: CustomDirectiveFC<HTMLElement, boolean> = () => {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default disabledDirective
|
export default disabledDirective
|
||||||
|
@ -19,7 +19,7 @@ import { on, off } from '@use-utils/element'
|
|||||||
|
|
||||||
import type { Directive } from 'vue'
|
import type { Directive } from 'vue'
|
||||||
import type { ThrottleBindingOptions } from './type'
|
import type { ThrottleBindingOptions } from './type'
|
||||||
import type { AnyFunc } from '@/types/modules/utils'
|
import type { AnyFC } from '@/types/modules/utils'
|
||||||
import type { DebouncedFunc } from 'lodash-es'
|
import type { DebouncedFunc } from 'lodash-es'
|
||||||
import type { CustomDirectiveFC } from '@/directives/type'
|
import type { CustomDirectiveFC } from '@/directives/type'
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ const throttleDirective: CustomDirectiveFC<
|
|||||||
HTMLElement,
|
HTMLElement,
|
||||||
ThrottleBindingOptions
|
ThrottleBindingOptions
|
||||||
> = () => {
|
> = () => {
|
||||||
let throttleFunction: DebouncedFunc<AnyFunc> | null
|
let throttleFunction: DebouncedFunc<AnyFC> | null
|
||||||
|
|
||||||
return {
|
return {
|
||||||
beforeMount: (el, binding) => {
|
beforeMount: (el, binding) => {
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import type { ThrottleSettings } from 'lodash-es'
|
import type { ThrottleSettings } from 'lodash-es'
|
||||||
import type { AnyFunc } from '@/types/modules/utils'
|
import type { AnyFC } from '@/types/modules/utils'
|
||||||
|
|
||||||
export interface ThrottleBindingOptions {
|
export interface ThrottleBindingOptions {
|
||||||
func: AnyFunc
|
func: AnyFC
|
||||||
trigger: string
|
trigger: string
|
||||||
wait: number
|
wait: number
|
||||||
options: ThrottleSettings
|
options: ThrottleSettings
|
||||||
|
@ -36,7 +36,7 @@ const PageResult = defineComponent({
|
|||||||
{{
|
{{
|
||||||
...this.$slots,
|
...this.$slots,
|
||||||
footer: () => (
|
footer: () => (
|
||||||
<NButton onClick={redirectRouterToDashboard.bind(this, false)}>
|
<NButton onClick={redirectRouterToDashboard.bind(this, true)}>
|
||||||
返回首页
|
返回首页
|
||||||
</NButton>
|
</NButton>
|
||||||
),
|
),
|
||||||
|
@ -24,7 +24,7 @@ import TootipIcon from '@/layout/components/SiderBar/components/TooltipIcon/inde
|
|||||||
import SettingDrawer from './components/SettingDrawer/index'
|
import SettingDrawer from './components/SettingDrawer/index'
|
||||||
import Breadcrumb from './components/Breadcrumb/index'
|
import Breadcrumb from './components/Breadcrumb/index'
|
||||||
import GlobalSeach from './components/GlobalSeach/index'
|
import GlobalSeach from './components/GlobalSeach/index'
|
||||||
import AppAvatar from '@/components/AppComponents/AppAvatar/index'
|
import AppAvatar from '@/app-components/app/AppAvatar/index'
|
||||||
|
|
||||||
import { useSetting } from '@/store'
|
import { useSetting } from '@/store'
|
||||||
import { LOCAL_OPTIONS } from '@/appConfig/localConfig'
|
import { LOCAL_OPTIONS } from '@/appConfig/localConfig'
|
||||||
|
@ -19,6 +19,7 @@ import './index.scss'
|
|||||||
|
|
||||||
import RayTransitionComponent from '@/components/RayTransitionComponent/index.vue'
|
import RayTransitionComponent from '@/components/RayTransitionComponent/index.vue'
|
||||||
import { NSpin } from 'naive-ui'
|
import { NSpin } from 'naive-ui'
|
||||||
|
import AppRequestCanceler from '@/app-components/provider/AppRequestCanceler/index'
|
||||||
|
|
||||||
import { useSetting } from '@/store'
|
import { useSetting } from '@/store'
|
||||||
|
|
||||||
@ -64,6 +65,7 @@ const ContentWrapper = defineComponent({
|
|||||||
size="large"
|
size="large"
|
||||||
themeOverrides={this.thmeOverridesSpin}
|
themeOverrides={this.thmeOverridesSpin}
|
||||||
>
|
>
|
||||||
|
<AppRequestCanceler />
|
||||||
{this.reloadRouteSwitch ? (
|
{this.reloadRouteSwitch ? (
|
||||||
<RayTransitionComponent
|
<RayTransitionComponent
|
||||||
class="content-wrapper"
|
class="content-wrapper"
|
||||||
|
@ -21,7 +21,7 @@ import FooterWrapper from '@/layout/default/FooterWrapper'
|
|||||||
import { useSetting } from '@/store'
|
import { useSetting } from '@/store'
|
||||||
import { LAYOUT_CONTENT_REF } from '@/appConfig/routerConfig'
|
import { LAYOUT_CONTENT_REF } from '@/appConfig/routerConfig'
|
||||||
import { layoutHeaderCssVars } from '@/layout/layoutResize'
|
import { layoutHeaderCssVars } from '@/layout/layoutResize'
|
||||||
import useAppLockScreen from '@/components/AppComponents/AppLockScreen/appLockVar'
|
import useAppLockScreen from '@/app-components/app/AppLockScreen/appLockVar'
|
||||||
|
|
||||||
const Layout = defineComponent({
|
const Layout = defineComponent({
|
||||||
name: 'RLayout',
|
name: 'RLayout',
|
||||||
|
@ -26,7 +26,7 @@ import type { Recordable } from '@/types/modules/helper'
|
|||||||
import type {
|
import type {
|
||||||
AppLocalesModules,
|
AppLocalesModules,
|
||||||
AppLocalesDropdownMixedOption,
|
AppLocalesDropdownMixedOption,
|
||||||
CurrentAppMessages,
|
AppCurrentAppMessages,
|
||||||
I18nModules,
|
I18nModules,
|
||||||
} from '@/locales/type'
|
} from '@/locales/type'
|
||||||
|
|
||||||
@ -73,7 +73,7 @@ export const combineI18nMessages = (langs: I18nModules, prefix: string) => {
|
|||||||
export const getAppLocalMessages = async (
|
export const getAppLocalMessages = async (
|
||||||
LOCAL_OPTIONS: AppLocalesDropdownMixedOption[],
|
LOCAL_OPTIONS: AppLocalesDropdownMixedOption[],
|
||||||
) => {
|
) => {
|
||||||
const message = {} as CurrentAppMessages
|
const message = {} as AppCurrentAppMessages
|
||||||
|
|
||||||
for (const curr of LOCAL_OPTIONS) {
|
for (const curr of LOCAL_OPTIONS) {
|
||||||
const msg: AppLocalesModules = await import(`./lang/${curr.key}.ts`)
|
const msg: AppLocalesModules = await import(`./lang/${curr.key}.ts`)
|
||||||
@ -132,5 +132,5 @@ export const getAppDefaultLanguage = () => {
|
|||||||
SYSTEM_DEFAULT_LOCAL,
|
SYSTEM_DEFAULT_LOCAL,
|
||||||
)
|
)
|
||||||
|
|
||||||
return language
|
return language as keyof AppCurrentAppMessages
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ import type {
|
|||||||
} from 'naive-ui'
|
} from 'naive-ui'
|
||||||
import type { Recordable } from '@/types/modules/helper'
|
import type { Recordable } from '@/types/modules/helper'
|
||||||
|
|
||||||
export interface CurrentAppMessages {
|
export interface AppCurrentAppMessages {
|
||||||
'zh-CN': object
|
'zh-CN': object
|
||||||
'en-US': object
|
'en-US': object
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ import type { App as AppType } from 'vue'
|
|||||||
const setupPlugins = async (inst: AppType<Element>) => {
|
const setupPlugins = async (inst: AppType<Element>) => {
|
||||||
await setupI18n(inst)
|
await setupI18n(inst)
|
||||||
await setupStore(inst)
|
await setupStore(inst)
|
||||||
setupRouter(inst)
|
await setupRouter(inst)
|
||||||
setupDayjs()
|
setupDayjs()
|
||||||
setupDirectives(inst)
|
setupDirectives(inst)
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,7 @@ interface RouteMeta {
|
|||||||
keepAlive?: boolean
|
keepAlive?: boolean
|
||||||
sameLevel?: boolean
|
sameLevel?: boolean
|
||||||
dev?: string | string[]
|
dev?: string | string[]
|
||||||
|
needCancel?: boolean
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -135,5 +135,5 @@ export const redirectRouterToDashboard = (isReplace = true) => {
|
|||||||
|
|
||||||
setStorage('menuKey', path)
|
setStorage('menuKey', path)
|
||||||
|
|
||||||
isReplace ? push(path) : replace(path)
|
isReplace ? replace(path) : push(path)
|
||||||
}
|
}
|
||||||
|
@ -10,10 +10,10 @@ import type { RouteRecordRaw, Router } from 'vue-router'
|
|||||||
|
|
||||||
export let router: Router
|
export let router: Router
|
||||||
|
|
||||||
const createVueRouter = () => {
|
const createVueRouter = async () => {
|
||||||
return createRouter({
|
return createRouter({
|
||||||
history: createWebHashHistory(),
|
history: createWebHashHistory(),
|
||||||
routes: constantRoutes() as unknown as RouteRecordRaw[],
|
routes: (await constantRoutes()) as unknown as RouteRecordRaw[],
|
||||||
scrollBehavior: (to) => {
|
scrollBehavior: (to) => {
|
||||||
scrollViewToTop(to)
|
scrollViewToTop(to)
|
||||||
|
|
||||||
@ -26,8 +26,8 @@ const createVueRouter = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// setup router
|
// setup router
|
||||||
export const setupRouter = (app: App<Element>) => {
|
export const setupRouter = async (app: App<Element>) => {
|
||||||
router = createVueRouter()
|
router = await createVueRouter()
|
||||||
|
|
||||||
vueRouterRegister(router)
|
vueRouterRegister(router)
|
||||||
useVueRouter()
|
useVueRouter()
|
||||||
|
@ -5,7 +5,7 @@ import { expandRoutes } from '@/router/helper/expandRoutes'
|
|||||||
|
|
||||||
const { path } = ROOT_ROUTE
|
const { path } = ROOT_ROUTE
|
||||||
|
|
||||||
export default () => [
|
export default async () => [
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
name: 'login',
|
name: 'login',
|
||||||
|
@ -65,9 +65,13 @@ export const useKeepAlive = defineStore(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 获取当前缓存队列 */
|
||||||
|
const getKeepAliveInclude = () => state.keepAliveInclude
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...toRefs(state),
|
...toRefs(state),
|
||||||
setKeepAliveInclude,
|
setKeepAliveInclude,
|
||||||
|
getKeepAliveInclude,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,13 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
import type CryptoJS from 'crypto-js'
|
import type CryptoJS from 'crypto-js'
|
||||||
|
|
||||||
export type CacheType = 'sessionStorage' | 'localStorage'
|
export type StorageLike = 'sessionStorage' | 'localStorage'
|
||||||
|
|
||||||
|
export type RemoveStorageKey =
|
||||||
|
| string
|
||||||
|
| 'all'
|
||||||
|
| 'all-sessionStorage'
|
||||||
|
| 'all-localStorage'
|
||||||
|
|
||||||
export type EventListenerOrEventListenerObject =
|
export type EventListenerOrEventListenerObject =
|
||||||
| EventListener
|
| EventListener
|
||||||
@ -39,7 +45,7 @@ export type WordArray = CryptoJS.lib.WordArray
|
|||||||
|
|
||||||
export type CipherParams = CryptoJS.lib.CipherParams
|
export type CipherParams = CryptoJS.lib.CipherParams
|
||||||
|
|
||||||
export type AnyFunc = (...args: any[]) => any
|
export type AnyFC = (...args: any[]) => any
|
||||||
|
|
||||||
export type AnyVoidFunc = (...args: any[]) => void
|
export type AnyVoidFunc = (...args: any[]) => void
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
/** vue3 项目里建议直接用 vueuse useStorage 方法 */
|
/** vue3 项目里建议直接用 vueuse useStorage 方法 */
|
||||||
|
|
||||||
import type { CacheType } from '@/types/modules/utils'
|
import type { StorageLike, RemoveStorageKey } from '@/types/modules/utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -21,7 +21,7 @@ import type { CacheType } from '@/types/modules/utils'
|
|||||||
function setStorage<T = unknown>(
|
function setStorage<T = unknown>(
|
||||||
key: string,
|
key: string,
|
||||||
value: T,
|
value: T,
|
||||||
type: CacheType = 'sessionStorage',
|
type: StorageLike = 'sessionStorage',
|
||||||
) {
|
) {
|
||||||
if (!key) {
|
if (!key) {
|
||||||
console.error('Failed to set stored data: key is empty or undefined')
|
console.error('Failed to set stored data: key is empty or undefined')
|
||||||
@ -41,12 +41,16 @@ function setStorage<T = unknown>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** 重载函数 getStorage */
|
/** 重载函数 getStorage */
|
||||||
function getStorage<T>(key: string, storageType: CacheType, defaultValue: T): T
|
function getStorage<T>(
|
||||||
|
key: string,
|
||||||
|
storageType: StorageLike,
|
||||||
|
defaultValue: T,
|
||||||
|
): T
|
||||||
|
|
||||||
/** 重载函数 getStorage */
|
/** 重载函数 getStorage */
|
||||||
function getStorage<T>(
|
function getStorage<T>(
|
||||||
key: string,
|
key: string,
|
||||||
storageType?: CacheType,
|
storageType?: StorageLike,
|
||||||
defaultValue?: T,
|
defaultValue?: T,
|
||||||
): T | null
|
): T | null
|
||||||
|
|
||||||
@ -57,7 +61,7 @@ function getStorage<T>(
|
|||||||
*/
|
*/
|
||||||
function getStorage<T>(
|
function getStorage<T>(
|
||||||
key: string,
|
key: string,
|
||||||
storageType: CacheType = 'sessionStorage',
|
storageType: StorageLike = 'sessionStorage',
|
||||||
defaultValue?: T,
|
defaultValue?: T,
|
||||||
): T | null {
|
): T | null {
|
||||||
try {
|
try {
|
||||||
@ -88,8 +92,8 @@ function getStorage<T>(
|
|||||||
* - all-localStorage: 删除所有 localStorage 缓存值
|
* - all-localStorage: 删除所有 localStorage 缓存值
|
||||||
*/
|
*/
|
||||||
function removeStorage(
|
function removeStorage(
|
||||||
key: string | 'all' | 'all-sessionStorage' | 'all-localStorage',
|
key: RemoveStorageKey,
|
||||||
type: CacheType = 'sessionStorage',
|
type: StorageLike = 'sessionStorage',
|
||||||
) {
|
) {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'all':
|
case 'all':
|
||||||
|
@ -32,7 +32,7 @@ import currency from 'currency.js'
|
|||||||
import { cloneDeep } from 'lodash-es'
|
import { cloneDeep } from 'lodash-es'
|
||||||
|
|
||||||
import type { Options } from 'currency.js'
|
import type { Options } from 'currency.js'
|
||||||
import type { AnyFunc } from '@/types/modules/utils'
|
import type { AnyFC } from '@/types/modules/utils'
|
||||||
|
|
||||||
export type CurrencyArguments = string | number | currency
|
export type CurrencyArguments = string | number | currency
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ export type OriginalValueType = 'string' | 'number'
|
|||||||
const basic = (
|
const basic = (
|
||||||
valueOptions: CurrencyArguments[],
|
valueOptions: CurrencyArguments[],
|
||||||
dividend: CurrencyArguments,
|
dividend: CurrencyArguments,
|
||||||
cb: AnyFunc,
|
cb: AnyFC,
|
||||||
) => {
|
) => {
|
||||||
if (!valueOptions?.length) {
|
if (!valueOptions?.length) {
|
||||||
return 0
|
return 0
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
import type { AnyFunc, MaybeArray } from '@/types/modules/utils'
|
import type { AnyFC, MaybeArray } from '@/types/modules/utils'
|
||||||
|
|
||||||
function call(funcs: MaybeArray<() => void>): void
|
function call(funcs: MaybeArray<() => void>): void
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ function call<A1, A2, A3, A4>(
|
|||||||
a4: A4,
|
a4: A4,
|
||||||
): void
|
): void
|
||||||
|
|
||||||
function call<A extends any[]>(funcs: AnyFunc[] | AnyFunc, ...args: A) {
|
function call<A extends any[]>(funcs: AnyFC[] | AnyFC, ...args: A) {
|
||||||
if (Array.isArray(funcs)) {
|
if (Array.isArray(funcs)) {
|
||||||
funcs.forEach((func) => (call as any)(func, ...args))
|
funcs.forEach((func) => (call as any)(func, ...args))
|
||||||
} else {
|
} else {
|
||||||
|
@ -21,6 +21,7 @@ const Axios = defineComponent({
|
|||||||
run: throttleDemoRun,
|
run: throttleDemoRun,
|
||||||
} = useHookPlusRequest(getTypicode, {
|
} = useHookPlusRequest(getTypicode, {
|
||||||
throttleWait: 1000,
|
throttleWait: 1000,
|
||||||
|
manual: true,
|
||||||
})
|
})
|
||||||
const {
|
const {
|
||||||
data: debounceDemoValue,
|
data: debounceDemoValue,
|
||||||
@ -28,6 +29,7 @@ const Axios = defineComponent({
|
|||||||
run: debounceDemoRun,
|
run: debounceDemoRun,
|
||||||
} = useHookPlusRequest(getTypicode, {
|
} = useHookPlusRequest(getTypicode, {
|
||||||
debounceWait: 1000,
|
debounceWait: 1000,
|
||||||
|
manual: true,
|
||||||
})
|
})
|
||||||
const {
|
const {
|
||||||
data: weatherDemoValue,
|
data: weatherDemoValue,
|
||||||
@ -35,6 +37,7 @@ const Axios = defineComponent({
|
|||||||
run: weatherDemoRun,
|
run: weatherDemoRun,
|
||||||
} = useHookPlusRequest(getWeather, {
|
} = useHookPlusRequest(getWeather, {
|
||||||
throttleWait: 1000,
|
throttleWait: 1000,
|
||||||
|
manual: true,
|
||||||
})
|
})
|
||||||
const {
|
const {
|
||||||
data: demoData,
|
data: demoData,
|
||||||
@ -46,6 +49,9 @@ const Axios = defineComponent({
|
|||||||
{
|
{
|
||||||
url: 'https://jsonplaceholder.typicode.com/todos/1',
|
url: 'https://jsonplaceholder.typicode.com/todos/1',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
|
cancelConfig: {
|
||||||
|
needCancel: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
manual: true,
|
manual: true,
|
||||||
|
@ -10,7 +10,7 @@ import {
|
|||||||
NH6,
|
NH6,
|
||||||
} from 'naive-ui'
|
} from 'naive-ui'
|
||||||
import RayIcon from '@/components/RayIcon/index'
|
import RayIcon from '@/components/RayIcon/index'
|
||||||
import RayLink from '@/components/RayLink/index'
|
import RayLink from '@/app-components/app/RayLink/index'
|
||||||
|
|
||||||
const Dashboard = defineComponent({
|
const Dashboard = defineComponent({
|
||||||
name: 'RDashboard',
|
name: 'RDashboard',
|
||||||
|
@ -35,6 +35,15 @@ const Echart = defineComponent({
|
|||||||
color: 'rgba(180, 180, 180, 0.2)',
|
color: 'rgba(180, 180, 180, 0.2)',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: '数量',
|
||||||
|
data: [12, 220, 250, 180, 20, 10, 190],
|
||||||
|
type: 'bar',
|
||||||
|
showBackground: true,
|
||||||
|
backgroundStyle: {
|
||||||
|
color: 'rgba(180, 180, 180, 0.2)',
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
const basePieOptions = {
|
const basePieOptions = {
|
||||||
|
@ -16,7 +16,7 @@ import Register from './components/Register/index'
|
|||||||
import QRCodeSignin from './components/QRCodeSignin/index'
|
import QRCodeSignin from './components/QRCodeSignin/index'
|
||||||
import SSOSignin from './components/SSOSignin/index'
|
import SSOSignin from './components/SSOSignin/index'
|
||||||
import RayIcon from '@/components/RayIcon'
|
import RayIcon from '@/components/RayIcon'
|
||||||
import RayLink from '@/components/RayLink/index'
|
import RayLink from '@/app-components/app/RayLink/index'
|
||||||
import ThemeSwitch from '@/layout/components/SiderBar/components/SettingDrawer/components/ThemeSwitch/index'
|
import ThemeSwitch from '@/layout/components/SiderBar/components/SettingDrawer/components/ThemeSwitch/index'
|
||||||
|
|
||||||
import { useSetting } from '@/store'
|
import { useSetting } from '@/store'
|
||||||
|
@ -27,16 +27,10 @@
|
|||||||
},
|
},
|
||||||
"suppressImplicitAnyIndexErrors": true,
|
"suppressImplicitAnyIndexErrors": true,
|
||||||
"typeRoots": ["./src/types/app.d.ts", "./src/types/global.d.ts"],
|
"typeRoots": ["./src/types/app.d.ts", "./src/types/global.d.ts"],
|
||||||
"types": [
|
"types": ["vite/client"],
|
||||||
"@intlify/unplugin-vue-i18n/messages",
|
|
||||||
"naive-ui/volar",
|
|
||||||
"vite/client",
|
|
||||||
"./src/types/global.d.ts"
|
|
||||||
],
|
|
||||||
"ignoreDeprecations": "5.0"
|
"ignoreDeprecations": "5.0"
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"./src/types/global.d.ts",
|
|
||||||
"vite.config.ts",
|
"vite.config.ts",
|
||||||
"vite-plugin/index.ts",
|
"vite-plugin/index.ts",
|
||||||
"vite-plugin/type.ts",
|
"vite-plugin/type.ts",
|
||||||
@ -45,7 +39,6 @@
|
|||||||
"vite-env.d.ts",
|
"vite-env.d.ts",
|
||||||
"components.d.ts",
|
"components.d.ts",
|
||||||
"auto-imports.d.ts",
|
"auto-imports.d.ts",
|
||||||
"src/**/*",
|
"src/**/*"
|
||||||
"./src/types/app.d.ts"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user