mirror of
https://github.com/XiaoDaiGua-Ray/ray-template.git
synced 2025-04-05 07:03:00 +08:00
version: v5.0.8
This commit is contained in:
parent
7647508935
commit
3b2bba391e
14
CHANGELOG.md
14
CHANGELOG.md
@ -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
|
||||
|
@ -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
52
pnpm-lock.yaml
generated
@ -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
|
||||
|
@ -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) // 主色调
|
||||
|
@ -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
|
||||
|
||||
/**
|
||||
|
@ -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)',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
264
src/components/base/RDraggableCard/DraggableCard.tsx
Normal file
264
src/components/base/RDraggableCard/DraggableCard.tsx
Normal 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>
|
||||
)
|
||||
},
|
||||
})
|
25
src/components/base/RDraggableCard/index.scss
Normal file
25
src/components/base/RDraggableCard/index.scss
Normal 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;
|
||||
}
|
@ -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,
|
||||
) => {
|
||||
|
@ -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: () => (
|
||||
|
@ -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'
|
||||
|
@ -53,7 +53,7 @@ $menuTagWrapperWidth: 76px;
|
||||
|
||||
.ray-template--light {
|
||||
.menu-tag__btn-icon:hover {
|
||||
filter: brightness(2);
|
||||
filter: brightness(1.2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
})
|
||||
|
||||
|
@ -29,5 +29,6 @@
|
||||
"TemplateHooks": "Template Api",
|
||||
"scrollReveal": "Scroll Reveal",
|
||||
"TablePro": "Table Pro",
|
||||
"Flow": "Flow"
|
||||
"Flow": "Flow",
|
||||
"DraggableCard": "Draggable Card"
|
||||
}
|
||||
|
@ -29,5 +29,6 @@
|
||||
"TemplateHooks": "模板内置 Api",
|
||||
"scrollReveal": "滚动动画",
|
||||
"TablePro": "高级表格",
|
||||
"Flow": "流程图"
|
||||
"Flow": "流程图",
|
||||
"DraggableCard": "拖拽卡片"
|
||||
}
|
||||
|
19
src/router/modules/demo/draggable-card.ts
Normal file
19
src/router/modules/demo/draggable-card.ts
Normal 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
|
@ -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
|
||||
})
|
||||
|
||||
/**
|
||||
|
@ -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: 追加操作(push),false: 覆盖操作。
|
||||
* 设置标签页。
|
||||
* 如果传递的 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'],
|
||||
},
|
||||
},
|
||||
)
|
||||
|
@ -264,3 +264,17 @@ export const getCatchMenuKey = () => {
|
||||
|
||||
return cacheMenuKey
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns 获取缓存的菜单标签页
|
||||
*/
|
||||
export const getCatchMenuTagOptions = () => {
|
||||
return getStorage<AppMenuOption[]>(
|
||||
APP_CATCH_KEY.appMenuTagOptions,
|
||||
'sessionStorage',
|
||||
{
|
||||
defaultValue: [],
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
46
src/views/demo/draggable-card.tsx
Normal file
46
src/views/demo/draggable-card.tsx
Normal 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>
|
||||
)
|
||||
},
|
||||
})
|
Loading…
x
Reference in New Issue
Block a user