This commit is contained in:
ray_wuhao 2023-07-22 23:31:06 +08:00
parent dd757d24a4
commit 01d44d46f3
58 changed files with 805 additions and 198 deletions

View File

@ -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

View File

@ -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',

View File

@ -0,0 +1,6 @@
## 描述
该包存放与模板深度绑定的组件:
- app存放与模板数据绑定的组件
- sys存放模板注入类组件

View File

@ -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'

View File

@ -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'

View File

@ -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',

View 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

View File

@ -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[] = [
{ {

View File

@ -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()
})
}
} }

View File

@ -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') {

View File

@ -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
} }

View File

@ -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<

View File

@ -1,9 +0,0 @@
## 描述
> 该组件包存放依赖系统数据的公共组件和与项目绑定的一些组件。
## 约束
- 该组件包仅存放与系统数据有绑定、关联的组件,纯组件或纯 UI 组件应放置于外层包中
- 以 `App` 开头标记组件是系统组件
- 组件应该尽量避免与其他系统组件有关联性

View 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,
)

View File

@ -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()
} }
/** 注册事件 */ /** 注册事件 */

View 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"
}
}
}
}

View 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'

View File

@ -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?.()}

View File

@ -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: {

View File

@ -88,6 +88,7 @@ const RayIcon = defineComponent({
call(onClick, e) call(onClick, e)
} }
} }
return { return {
modelColor, modelColor,
symbolId, symbolId,

View File

@ -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>

View File

@ -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)

View File

@ -52,4 +52,5 @@ const copyDirective: CustomDirectiveFC<CopyElement, string> = () => {
}, },
} }
} }
export default copyDirective export default copyDirective

View File

@ -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) => {

View File

@ -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

View File

@ -42,4 +42,5 @@ const disabledDirective: CustomDirectiveFC<HTMLElement, boolean> = () => {
}, },
} }
} }
export default disabledDirective export default disabledDirective

View File

@ -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) => {

View File

@ -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

View File

@ -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>
), ),

View File

@ -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'

View File

@ -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"

View File

@ -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',

View File

@ -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
} }

View File

@ -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
} }

View File

@ -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)
} }

View File

@ -55,6 +55,7 @@ interface RouteMeta {
keepAlive?: boolean keepAlive?: boolean
sameLevel?: boolean sameLevel?: boolean
dev?: string | string[] dev?: string | string[]
needCancel?: boolean
} }
``` ```

View File

@ -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)
} }

View File

@ -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()

View File

@ -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',

View File

@ -65,9 +65,13 @@ export const useKeepAlive = defineStore(
} }
} }
/** 获取当前缓存队列 */
const getKeepAliveInclude = () => state.keepAliveInclude
return { return {
...toRefs(state), ...toRefs(state),
setKeepAliveInclude, setKeepAliveInclude,
getKeepAliveInclude,
} }
}, },
{ {

View File

@ -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

View File

@ -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':

View File

@ -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

View File

@ -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 {

View File

@ -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,

View File

@ -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',

View File

@ -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 = {

View File

@ -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'

View File

@ -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"
] ]
} }