version: v5.0.8

This commit is contained in:
XiaoDaiGua-Ray 2024-12-20 18:23:55 +08:00
parent 7647508935
commit 3b2bba391e
22 changed files with 490 additions and 83 deletions

View File

@ -1,5 +1,19 @@
# CHANGE LOG
## 5.0.8
## Feats
- 修改 `menuTagOptions` 的缓存方式,现在会缓存至 `sessionStorage` 中,兼容可能多系统版本部署与多开系统页面标签页冲突的问题
- 新增 `RDraggableCard` 组件
- 更新 `vite` 版本至 `6.0.4`
## Fixes
- 修复 `updateObjectValue` 方法对于对象值判断不准确的问题
- 修复 `SettingDrawer` 组件初始化时,没有正确初始化 `settingStore` 的问题
- 修复 `RTable` 组件在未设置 `title``tool``false` 时,导致 `headerStyle` 样式会高一些的问题
## 5.0.7
## Feats

View File

@ -1,7 +1,7 @@
{
"name": "ray-template",
"private": false,
"version": "5.0.7",
"version": "5.0.8",
"type": "module",
"engines": {
"node": "^18.0.0 || ^20.0.0 || >=22.0.0",
@ -95,7 +95,7 @@
"typescript": "^5.6.3",
"unplugin-auto-import": "^0.18.2",
"unplugin-vue-components": "^0.27.4",
"vite": "^6.0.3",
"vite": "^6.0.4",
"vite-bundle-analyzer": "0.9.4",
"vite-plugin-cdn2": "1.1.0",
"vite-plugin-ejs": "^1.7.0",

52
pnpm-lock.yaml generated
View File

@ -116,10 +116,10 @@ importers:
version: 8.16.0(eslint@9.11.0(jiti@1.21.6))(typescript@5.6.3)
'@vitejs/plugin-vue':
specifier: ^5.1.0
version: 5.1.0(vite@6.0.3(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1))(vue@3.5.13(typescript@5.6.3))
version: 5.1.0(vite@6.0.4(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1))(vue@3.5.13(typescript@5.6.3))
'@vitejs/plugin-vue-jsx':
specifier: ^4.1.1
version: 4.1.1(vite@6.0.3(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1))(vue@3.5.13(typescript@5.6.3))
version: 4.1.1(vite@6.0.4(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1))(vue@3.5.13(typescript@5.6.3))
'@vitest/ui':
specifier: 1.5.2
version: 1.5.2(vitest@2.0.5)
@ -190,8 +190,8 @@ importers:
specifier: ^0.27.4
version: 0.27.4(@babel/parser@7.26.2)(@nuxt/kit@3.13.2(rollup@4.27.4)(webpack-sources@3.2.3))(rollup@4.27.4)(vue@3.5.13(typescript@5.6.3))(webpack-sources@3.2.3)
vite:
specifier: ^6.0.3
version: 6.0.3(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1)
specifier: ^6.0.4
version: 6.0.4(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1)
vite-bundle-analyzer:
specifier: 0.9.4
version: 0.9.4
@ -200,19 +200,19 @@ importers:
version: 1.1.0(rollup@4.27.4)
vite-plugin-ejs:
specifier: ^1.7.0
version: 1.7.0(vite@6.0.3(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1))
version: 1.7.0(vite@6.0.4(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1))
vite-plugin-eslint:
specifier: 1.8.1
version: 1.8.1(eslint@9.11.0(jiti@1.21.6))(vite@6.0.3(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1))
version: 1.8.1(eslint@9.11.0(jiti@1.21.6))(vite@6.0.4(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1))
vite-plugin-inspect:
specifier: ^0.8.4
version: 0.8.4(@nuxt/kit@3.13.2(rollup@4.27.4)(webpack-sources@3.2.3))(rollup@4.27.4)(vite@6.0.3(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1))
version: 0.8.4(@nuxt/kit@3.13.2(rollup@4.27.4)(webpack-sources@3.2.3))(rollup@4.27.4)(vite@6.0.4(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1))
vite-plugin-mock-dev-server:
specifier: 1.8.0
version: 1.8.0(esbuild@0.24.0)(rollup@4.27.4)(vite@6.0.3(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1))
version: 1.8.0(esbuild@0.24.0)(rollup@4.27.4)(vite@6.0.4(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1))
vite-plugin-svg-icons:
specifier: ^2.0.1
version: 2.0.1(vite@6.0.3(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1))
version: 2.0.1(vite@6.0.4(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1))
vite-svg-loader:
specifier: ^5.1.0
version: 5.1.0(vue@3.5.13(typescript@5.6.3))
@ -4183,8 +4183,8 @@ packages:
terser:
optional: true
vite@6.0.3:
resolution: {integrity: sha512-Cmuo5P0ENTN6HxLSo6IHsjCLn/81Vgrp81oaiFFMRa8gGDj5xEjIcEpf2ZymZtZR8oU0P2JX5WuUp/rlXcHkAw==}
vite@6.0.4:
resolution: {integrity: sha512-zwlH6ar+6o6b4Wp+ydhtIKLrGM/LoqZzcdVmkGAFun0KHTzIzjh+h0kungEx7KJg/PYnC80I4TII9WkjciSR6Q==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
hasBin: true
peerDependencies:
@ -5461,19 +5461,19 @@ snapshots:
'@typescript-eslint/types': 8.16.0
eslint-visitor-keys: 4.2.0
'@vitejs/plugin-vue-jsx@4.1.1(vite@6.0.3(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1))(vue@3.5.13(typescript@5.6.3))':
'@vitejs/plugin-vue-jsx@4.1.1(vite@6.0.4(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1))(vue@3.5.13(typescript@5.6.3))':
dependencies:
'@babel/core': 7.26.0
'@babel/plugin-transform-typescript': 7.25.9(@babel/core@7.26.0)
'@vue/babel-plugin-jsx': 1.2.5(@babel/core@7.26.0)
vite: 6.0.3(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1)
vite: 6.0.4(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1)
vue: 3.5.13(typescript@5.6.3)
transitivePeerDependencies:
- supports-color
'@vitejs/plugin-vue@5.1.0(vite@6.0.3(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1))(vue@3.5.13(typescript@5.6.3))':
'@vitejs/plugin-vue@5.1.0(vite@6.0.4(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1))(vue@3.5.13(typescript@5.6.3))':
dependencies:
vite: 6.0.3(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1)
vite: 6.0.4(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1)
vue: 3.5.13(typescript@5.6.3)
'@vitest/expect@2.0.5':
@ -8582,20 +8582,20 @@ snapshots:
- rollup
- supports-color
vite-plugin-ejs@1.7.0(vite@6.0.3(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1)):
vite-plugin-ejs@1.7.0(vite@6.0.4(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1)):
dependencies:
ejs: 3.1.9
vite: 6.0.3(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1)
vite: 6.0.4(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1)
vite-plugin-eslint@1.8.1(eslint@9.11.0(jiti@1.21.6))(vite@6.0.3(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1)):
vite-plugin-eslint@1.8.1(eslint@9.11.0(jiti@1.21.6))(vite@6.0.4(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1)):
dependencies:
'@rollup/pluginutils': 4.2.1
'@types/eslint': 8.56.6
eslint: 9.11.0(jiti@1.21.6)
rollup: 2.79.1
vite: 6.0.3(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1)
vite: 6.0.4(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1)
vite-plugin-inspect@0.8.4(@nuxt/kit@3.13.2(rollup@4.27.4)(webpack-sources@3.2.3))(rollup@4.27.4)(vite@6.0.3(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1)):
vite-plugin-inspect@0.8.4(@nuxt/kit@3.13.2(rollup@4.27.4)(webpack-sources@3.2.3))(rollup@4.27.4)(vite@6.0.4(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1)):
dependencies:
'@antfu/utils': 0.7.10
'@rollup/pluginutils': 5.1.2(rollup@4.27.4)
@ -8606,14 +8606,14 @@ snapshots:
perfect-debounce: 1.0.0
picocolors: 1.1.1
sirv: 2.0.4
vite: 6.0.3(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1)
vite: 6.0.4(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1)
optionalDependencies:
'@nuxt/kit': 3.13.2(rollup@4.27.4)(webpack-sources@3.2.3)
transitivePeerDependencies:
- rollup
- supports-color
vite-plugin-mock-dev-server@1.8.0(esbuild@0.24.0)(rollup@4.27.4)(vite@6.0.3(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1)):
vite-plugin-mock-dev-server@1.8.0(esbuild@0.24.0)(rollup@4.27.4)(vite@6.0.4(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1)):
dependencies:
'@pengzhanbo/utils': 1.1.2
'@rollup/pluginutils': 5.1.2(rollup@4.27.4)
@ -8630,7 +8630,7 @@ snapshots:
mime-types: 2.1.35
path-to-regexp: 6.2.2
picocolors: 1.1.1
vite: 6.0.3(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1)
vite: 6.0.4(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1)
ws: 8.18.0
optionalDependencies:
esbuild: 0.24.0
@ -8640,7 +8640,7 @@ snapshots:
- supports-color
- utf-8-validate
vite-plugin-svg-icons@2.0.1(vite@6.0.3(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1)):
vite-plugin-svg-icons@2.0.1(vite@6.0.4(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1)):
dependencies:
'@types/svgo': 2.6.4
cors: 2.8.5
@ -8650,7 +8650,7 @@ snapshots:
pathe: 0.2.0
svg-baker: 1.7.0
svgo: 2.8.0
vite: 6.0.3(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1)
vite: 6.0.4(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1)
transitivePeerDependencies:
- supports-color
@ -8669,7 +8669,7 @@ snapshots:
fsevents: 2.3.3
sass: 1.77.1
vite@6.0.3(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1):
vite@6.0.4(@types/node@22.5.5)(jiti@1.21.6)(sass@1.77.1):
dependencies:
esbuild: 0.24.0
postcss: 8.4.49

View File

@ -44,7 +44,7 @@ export default defineComponent({
primaryColor,
)
// 将主色调任意颜色转换为 rgba 格式
const fp = colorToRgba(p, 0.8)
const fp = colorToRgba(p, 0.85)
// 设置全局主题色 css 变量
html.style.setProperty(rayTemplateThemePrimaryColor, p) // 主色调

View File

@ -93,6 +93,7 @@ export const APP_CATCH_KEY_PREFIX = ''
* - appPiniaMenuStore: pinia menu store key
* - appPiniaSigningStore: pinia signing store key
* - appVersionProvider: 版本信息缓存 key
* - appMenuTagOptions: 标签页菜单列表
*/
export const APP_CATCH_KEY = {
signing: 'signing',
@ -106,6 +107,7 @@ export const APP_CATCH_KEY = {
appVersionProvider: 'appVersionProvider',
isAppLockScreen: 'isAppLockScreen',
appGlobalSearchOptions: 'appGlobalSearchOptions',
appMenuTagOptions: 'appMenuTagOptions',
} as const
/**

View File

@ -20,7 +20,7 @@ export const APP_THEME: AppTheme = {
// 主题色
primaryColor: '#2d8cf0',
// 主题辅助色(用于整体 hover、active 等之类颜色)
primaryFadeColor: 'rgba(45, 140, 240, 0.8)',
primaryFadeColor: 'rgba(45, 140, 240, 0.85)',
},
/**
*
@ -52,14 +52,12 @@ export const APP_THEME: AppTheme = {
common: {
borderRadius: '4px',
baseColor: 'rgb(18, 18, 18)',
textColorBase: 'rgb(255, 255, 255)',
},
},
light: {
common: {
borderRadius: '4px',
baseColor: 'rgb(255, 255, 255)',
textColorBase: 'rgb(31, 31, 31)',
},
},
},

View File

@ -0,0 +1,264 @@
import './index.scss'
import { NCard } from 'naive-ui'
import { Teleport, Transition } from 'vue'
import interact from 'interactjs'
import { cardProps } from 'naive-ui'
import { unrefElement, completeSize, queryElements } from '@/utils'
import { useTemplateRef } from 'vue'
import type { VNode } from 'vue'
type RestrictRectOptions = Parameters<typeof interact.modifiers.restrictRect>[0]
type Position = {
x: number
y: number
}
const props = {
...cardProps,
/**
*
* @description
*
*
* @default body
*/
restrictionElement: {
type: [String, HTMLElement, Function] as PropType<
string | HTMLElement | (() => VNode)
>,
default: 'body',
},
/**
*
* @description
*
*
* @default true
*/
dad: {
type: Boolean,
default: true,
},
/**
*
* @description
*
*
* @default undefined
*/
restrictRectOptions: {
type: Object as PropType<RestrictRectOptions>,
default: void 0,
},
/**
*
* @description
*
*
* @default { x: 0, y: 0 }
*/
defaultPosition: {
type: Object as PropType<Position>,
default: () => ({
x: 0,
y: 0,
}),
},
/**
*
* @description
*
*
* @default 600
*/
width: {
type: [String, Number] as PropType<string | number>,
default: 600,
},
/**
*
* @description
* z-index
*
* @default undefined
*/
zIndex: {
type: Number,
default: void 0,
},
/**
*
* @description
*
*
* @default false
*/
animation: {
type: Boolean,
default: false,
},
}
export default defineComponent({
name: 'RDraggableCard',
props,
setup(props, { expose }) {
const cardRef = useTemplateRef<HTMLElement>('cardRef')
let interactInst: ReturnType<typeof interact> | null = null
const position = {
...props.defaultPosition,
}
const CONTAINER_ID = 'draggable-card-container'
const cssVars = computed(() => {
return {
'--r-draggable-card-width': completeSize(props.width),
'--r-draggable-card-z-index': props.zIndex,
}
})
let isSetup = false
const createDraggableCardContainer = () => {
if (!document.getElementById(CONTAINER_ID)) {
const container = document.createElement('div')
container.id = CONTAINER_ID
document.documentElement.appendChild(container)
}
}
createDraggableCardContainer()
const getDom = () => {
const card = unrefElement(cardRef)
const re =
typeof props.restrictionElement === 'string'
? queryElements<HTMLElement>(props.restrictionElement)
: props.restrictionElement
let restrictionElement: HTMLElement | null = null
if (Array.isArray(re)) {
restrictionElement = re[0]
} else if (typeof re === 'function') {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
restrictionElement = unrefElement<HTMLElement>(re as any) as HTMLElement
} else {
restrictionElement = re
}
return {
card,
restrictionElement,
}
}
const setupDraggable = () => {
const { card, restrictionElement } = getDom()
if (!card || !props.dad) {
return
}
const restrictionRect = restrictionElement?.getBoundingClientRect()
const cardHeader = card.querySelector('.n-card-header')
const restrictRectOptions = Object.assign(
{},
{
restriction: restrictionElement,
endOnly: true,
},
props.restrictRectOptions,
)
if (restrictionRect && !isSetup) {
// 计算偏移位置
const offsetX = restrictionRect.x + position.x
const offsetY = restrictionRect.y + position.y
// 设置初始位置
card.style.transform = `translate(${offsetX}px, ${offsetY}px)`
position.x = offsetX
position.y = offsetY
}
interactInst = interact(card)
.draggable({
inertia: true,
autoScroll: true,
allowFrom: cardHeader ? '.n-card-header' : '.n-card__content',
modifiers: [interact.modifiers.restrictRect(restrictRectOptions)],
listeners: {
move: (event) => {
card.setAttribute('can-drag', 'true')
position.x += event.dx
position.y += event.dy
card.style.transform = `translate(${position.x}px, ${position.y}px)`
},
},
})
.resizable(false)
isSetup = true
}
expose()
watchEffect(() => {
if (props.dad) {
setupDraggable()
} else {
interactInst?.unset()
interactInst = null
}
})
onMounted(() => {
nextTick(() => {
setupDraggable()
})
})
return {
cardRef,
CONTAINER_ID,
cssVars,
}
},
render() {
const { $attrs, $slots, $props, CONTAINER_ID, cssVars, animation } = this
return (
<Teleport to={`#${CONTAINER_ID}`}>
{animation ? (
<Transition name="draggable-card" appear mode="out-in">
<NCard
{...$attrs}
{...$props}
class="r-draggable-card"
style={[cssVars]}
ref="cardRef"
>
{{ ...$slots }}
</NCard>
</Transition>
) : (
<NCard
{...$attrs}
{...$props}
class="r-draggable-card"
style={[cssVars]}
ref="cardRef"
>
{{ ...$slots }}
</NCard>
)}
</Teleport>
)
},
})

View File

@ -0,0 +1,25 @@
.n-card.r-draggable-card {
transform-origin: 0 0;
position: absolute;
width: var(--r-draggable-card-width);
z-index: var(--r-draggable-card-z-index);
}
#draggable-card-container {
position: fixed;
top: 0;
left: 0;
width: 0;
height: 0;
}
// draggable-card Transition 样式
.draggable-card-enter-active,
.draggable-card-leave-active {
transition: opacity 0.3s var(--r-bezier);
}
.draggable-card-enter-from,
.draggable-card-leave-to {
opacity: 0;
}

View File

@ -36,7 +36,10 @@ import type { Recordable } from '@/types'
* },
* })
*/
const useForm = <T extends Recordable, R extends RFormRules>(
const useForm = <
T extends Recordable = Recordable,
R extends RFormRules = RFormRules,
>(
model?: T,
rules?: R,
) => {

View File

@ -61,6 +61,23 @@ export default defineComponent({
pick(props, 'striped', 'bordered'),
),
)
// 默认设置 card header style
const cardHeaderStyle = computed(() => {
const { title, tool, cardProps } = props
const { headerStyle = {} } = cardProps ?? {}
if (!title && !tool) {
return Object.assign(
{},
{
paddingTop: '0px',
},
headerStyle,
)
}
return headerStyle
})
/**
*
@ -231,6 +248,7 @@ export default defineComponent({
tool,
wrapperRef,
propsPopselectValue,
cardHeaderStyle,
}
},
render() {
@ -243,6 +261,7 @@ export default defineComponent({
uuidWrapper,
privateReactive,
propsPopselectValue,
cardHeaderStyle,
} = this
const { class: className, ...restAttrs } = $attrs
const { tool, combineRowProps, contextMenuSelect } = this
@ -255,11 +274,12 @@ export default defineComponent({
tableFlexHeight,
cardProps,
...restProps
} = $props as ExtractPublicPropTypes<typeof props>
} = $props
const { headerStyle, ...restCardProps } = cardProps ?? {}
return (
<NCard
{...cardProps}
{...restCardProps}
{...{
id: uuidWrapper,
}}
@ -267,6 +287,7 @@ export default defineComponent({
ref="wrapperRef"
bordered={wrapperBordered}
class={className}
style={cardHeaderStyle}
>
{{
default: () => (

View File

@ -1,4 +1,5 @@
import RCollapse from '../components/pro/RCollapse/Collapse'
import RDraggableCard from '../components/base/RDraggableCard/DraggableCard'
// 导出所有自定义组件
export * from './base/RChart'
@ -14,7 +15,7 @@ export * from './base/RSegment'
export * from './base/RBarcode'
export * from '../components/pro/RTablePro'
export * from './base/RFlow'
export { RCollapse }
export { RCollapse, RDraggableCard }
// 导出自定义组件类型
export type * from './base/RChart/src/types'

View File

@ -53,7 +53,7 @@ $menuTagWrapperWidth: 76px;
.ray-template--light {
.menu-tag__btn-icon:hover {
filter: brightness(2);
filter: brightness(1.2);
}
}

View File

@ -16,7 +16,7 @@ import SegmentViewsCustomMenu from './segment-views/CustomMenu'
import { useSettingGetters, useSettingActions, useMenuActions } from '@/store'
import { SETTING_DRAWER_INJECT_KEY } from './constant'
import { forIn, throttle } from 'lodash-es'
import { cloneDeep, forIn, throttle } from 'lodash-es'
import { drawerProps } from 'naive-ui'
import { useModal } from '@/components'
import { getDefaultSettingConfig } from '@/store/modules/setting/constant'
@ -71,11 +71,13 @@ export default defineComponent({
positiveText: '确认初始化',
negativeText: '取消',
onPositiveClick: () => {
forIn(getDefaultSettingConfig(), (value, key) => {
forIn(cloneDeep(getDefaultSettingConfig()), (value, key) => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
modelReactive[key] = value
console.log(value, key)
updateSettingState(key as keyof SettingState, value)
})

View File

@ -29,5 +29,6 @@
"TemplateHooks": "Template Api",
"scrollReveal": "Scroll Reveal",
"TablePro": "Table Pro",
"Flow": "Flow"
"Flow": "Flow",
"DraggableCard": "Draggable Card"
}

View File

@ -29,5 +29,6 @@
"TemplateHooks": "模板内置 Api",
"scrollReveal": "滚动动画",
"TablePro": "高级表格",
"Flow": "流程图"
"Flow": "流程图",
"DraggableCard": "拖拽卡片"
}

View File

@ -0,0 +1,19 @@
import { t } from '@/hooks/web/useI18n'
import { LAYOUT } from '@/router/constant'
import type { AppRouteRecordRaw } from '@/router/types'
const r: AppRouteRecordRaw = {
path: '/draggable-card',
component: () => import('@/views/demo/draggable-card'),
meta: {
i18nKey: t('menu.DraggableCard'),
icon: 'other',
order: 2,
extra: {
label: 'drag',
},
},
}
export default r

View File

@ -1,5 +1,4 @@
import { piniaMenuStore } from '../modules/menu'
import { useAppRoot } from '@/hooks'
export const useMenuGetters = () => {
const variable = piniaMenuStore()
@ -31,25 +30,7 @@ export const useMenuGetters = () => {
*
*/
const getMenuTagOptions = computed(() => {
const { getRootPath } = useAppRoot()
return variable.menuTagOptions.map((curr, _idx, currentArray) => {
if (curr.key === getMenuKey.value && curr.key !== getRootPath.value) {
curr.closeable = true
} else {
curr.closeable = false
}
if (curr.key === getRootPath.value) {
curr.closeable = false
}
if (currentArray.length <= 1) {
curr.closeable = false
}
return curr
})
return variable.menuTagOptions
})
/**

View File

@ -8,6 +8,7 @@ import {
createMenuIcon,
getCatchMenuKey,
createMenuExtra,
getCatchMenuTagOptions,
} from './utils'
import { useI18n } from '@/hooks'
import { getAppRawRoutes } from '@/router/app-route-modules'
@ -73,7 +74,7 @@ export const piniaMenuStore = defineStore(
menuKey: getCatchMenuKey(), // 当前菜单 `key`
options: [], // 菜单列表
collapsed: false, // 是否折叠菜单
menuTagOptions: [], // tag 标签菜单
menuTagOptions: getCatchMenuTagOptions(), // tag 标签菜单
breadcrumbOptions: [], // 面包屑菜单
currentMenuOption: null, // 当前激活菜单项
})
@ -117,11 +118,7 @@ export const piniaMenuStore = defineStore(
// 设置 label, i18nKey 优先级最高
const label = computed(() => (i18nKey ? t(`${i18nKey}`) : noLocalTitle))
/**
*
*
* key path
*/
// 拼装菜单项,容错处理,兼容以前版本 key 选取为 path 的情况
const route = {
...option,
key: option.fullPath,
@ -137,10 +134,12 @@ export const piniaMenuStore = defineStore(
extra: createMenuExtra(option),
})
// 如果当前菜单项与缓存菜单项相同,则更新当前菜单项
if (option.fullPath === getCatchMenuKey()) {
menuState.currentMenuOption = attr
}
// 验证菜单项是否显示
attr.show = validMenuItemShow(attr)
return attr
@ -163,12 +162,13 @@ export const piniaMenuStore = defineStore(
/**
*
* @param options menu tag options
* @param isAppend is append
* @param options menu tag option(s)
* @param isAppend true: (push), false:
*
* @description
*
* true: pushfalse:
*
* options
* options
*/
const setMenuTagOptions = (
options: MenuTagOptions | MenuTagOptions[],
@ -180,6 +180,8 @@ export const piniaMenuStore = defineStore(
isAppend
? menuState.menuTagOptions.push(...arr)
: (menuState.menuTagOptions = arr)
setStorage(APP_CATCH_KEY.appMenuTagOptions, menuState.menuTagOptions)
}
/**
@ -199,6 +201,13 @@ export const piniaMenuStore = defineStore(
if (!tag) {
menuState.menuTagOptions.push(option as MenuTagOptions)
}
// 清理所有非根路径的标签页
menuState.menuTagOptions = menuState.menuTagOptions.filter((curr) =>
curr.fullPath?.startsWith('/'),
)
setStorage(APP_CATCH_KEY.appMenuTagOptions, menuState.menuTagOptions)
}
/**
@ -402,8 +411,13 @@ export const piniaMenuStore = defineStore(
* @description
* menu tag
*/
const spliceMenTagOptions = (idx: number, length = 1) =>
menuState.menuTagOptions.splice(idx, length)
const spliceMenTagOptions = (idx: number, length = 1) => {
const r = menuState.menuTagOptions.splice(idx, length)
setStorage(APP_CATCH_KEY.appMenuTagOptions, menuState.menuTagOptions)
return r
}
/**
*
@ -451,7 +465,7 @@ export const piniaMenuStore = defineStore(
persist: {
key: APP_CATCH_KEY.appPiniaMenuStore,
storage: window.localStorage,
pick: ['breadcrumbOptions', 'menuKey', 'menuTagOptions', 'collapsed'],
pick: ['breadcrumbOptions', 'menuKey', 'collapsed'],
},
},
)

View File

@ -264,3 +264,17 @@ export const getCatchMenuKey = () => {
return cacheMenuKey
}
/**
*
* @returns
*/
export const getCatchMenuTagOptions = () => {
return getStorage<AppMenuOption[]>(
APP_CATCH_KEY.appMenuTagOptions,
'sessionStorage',
{
defaultValue: [],
},
)
}

View File

@ -3,7 +3,7 @@ import { colorToRgba, setStorage, updateObjectValue, setStyle } from '@/utils'
import { useI18n, useDayjs } from '@/hooks'
import { APP_CATCH_KEY, APP_THEME, GLOBAL_CLASS_NAMES } from '@/app-config'
import { getDefaultSettingConfig } from './constant'
import { merge } from 'lodash-es'
import { cloneDeep, merge } from 'lodash-es'
import type { SettingState } from '@/store/modules/setting/types'
import type { LocalKey } from '@/hooks'
@ -24,8 +24,8 @@ export const piniaSettingStore = defineStore(
common: {
primaryColor: primaryColor,
primaryColorHover: primaryFadeColor,
primaryColorPressed: primaryFadeColor,
primaryColorSuppl: colorToRgba(primaryColor, 0.9),
primaryColorPressed: primaryColor,
primaryColorSuppl: primaryFadeColor,
},
},
// 内部使用用于判断是否为黑夜主题为了兼容历史遗留版本true 为黑夜主题false 为明亮主题
@ -48,7 +48,7 @@ export const piniaSettingStore = defineStore(
url: '/dashboard',
jumpType: 'station',
},
...getDefaultSettingConfig(),
...cloneDeep(getDefaultSettingConfig()),
})
// 修改当前语言
@ -65,14 +65,13 @@ export const piniaSettingStore = defineStore(
* @description
* naive-ui
*/
const changePrimaryColor = (value: string, alpha = 0.8) => {
const changePrimaryColor = (value: string, alpha = 0.85) => {
const alphaColor1 = colorToRgba(value, alpha)
const alphaColor2 = colorToRgba(value, 0.9)
const themeOverrides = {
primaryColor: value,
primaryColorHover: alphaColor1,
primaryColorPressed: alphaColor1,
primaryColorSuppl: alphaColor2,
primaryColorPressed: value,
primaryColorSuppl: alphaColor1,
}
const { rayTemplateThemePrimaryColor, rayTemplateThemePrimaryFadeColor } =
GLOBAL_CLASS_NAMES

View File

@ -1,3 +1,5 @@
import { isValueType } from '@/utils'
import type { Recordable, AnyFC } from '@/types'
/**
@ -42,7 +44,7 @@ export const updateObjectValue = <
return
}
if (typeof value === 'object' && value !== null) {
if (isValueType<object>(value, 'Object')) {
targetObject[key] = {
...targetObject[key],
...value,

View File

@ -0,0 +1,46 @@
import { RDraggableCard } from '@/components'
import { NButton, NCard, NFlex } from 'naive-ui'
export default defineComponent({
name: 'DraggableCardDemo',
setup() {
const card3 = ref(false)
return {
card3,
}
},
render() {
const { card3 } = this
return (
<div>
<RDraggableCard animation title="Body">
body
</RDraggableCard>
{card3 ? (
<RDraggableCard
animation
title="Layout Container"
restrictionElement=".r-layout-full__viewer-content"
closable
onClose={() => (this.card3 = false)}
>
{{
default: () =>
'我被限制在 Layout Container 中。并且我支持 NCard 的所有配置与插槽。',
'header-extra': () => '其实我就是 NCard 封装的',
footer: () => '我支持 footer 插槽',
action: () => '我支持 action 插槽',
}}
</RDraggableCard>
) : null}
<NCard title="显示与隐藏卡片">
<NButton type="primary" onClick={() => (this.card3 = !this.card3)}>
</NButton>
</NCard>
</div>
)
},
})