Feat(Menu): Add drop mask
Add drop mask to menu. Optimize tool description.
This commit is contained in:
30
src/assets/css/components/dnd/drop-mask.scss
Normal file
30
src/assets/css/components/dnd/drop-mask.scss
Normal file
@@ -0,0 +1,30 @@
|
||||
@use "@/assets/css/constants" as constants;
|
||||
|
||||
[data-component=component-drop-mask] {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: {
|
||||
left: 10px;
|
||||
right: 10px;
|
||||
bottom: 10px;
|
||||
};
|
||||
background-color: constants.$origin-color;
|
||||
|
||||
.drop-mask-border {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: {
|
||||
width: 2px;
|
||||
color: constants.$font-secondary-color;
|
||||
style: dashed;
|
||||
radius: 8px;
|
||||
};
|
||||
font-size: 1.8em;
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
.version {
|
||||
width: 0;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.operation {
|
||||
@@ -30,6 +31,7 @@
|
||||
font-size: 1.6em;
|
||||
gap: 4px;
|
||||
opacity: 0;
|
||||
transition: all 0.2s;
|
||||
|
||||
> *:hover {
|
||||
color: constants.$font-secondary-color;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
.menu-droppable {
|
||||
display: flex;
|
||||
position: relative;
|
||||
min-height: 0;
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
|
||||
1
src/assets/svg/receive.svg
Normal file
1
src/assets/svg/receive.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"><path d="M927.929032 640.065509a31.994541 31.994541 0 0 0-31.994541 31.994541v127.978163c0 52.918971-43.064652 95.983623-95.983623 95.983623h-575.901736c-52.918971 0-95.983623-43.064652-95.983623-95.983623v-127.978163a31.994541 31.994541 0 0 0-63.989082 0v127.978163C64.076427 888.279157 135.872177 960.010918 224.049132 960.010918h575.901736c88.240944 0 159.972705-71.731761 159.972705-159.972705v-127.978163a31.994541 31.994541 0 0 0-31.994541-31.994541z" /><path d="M412.113043 777.386079c18.684812 18.684812 43.256619 28.027218 67.892416 28.027217s49.143615-9.342406 67.892416-28.027217l274.705128-274.705129A31.930552 31.930552 0 0 0 799.950868 448.098263h-159.140846a629.524587 629.524587 0 0 1 44.408423-202.909378L765.652721 44.0712a32.122519 32.122519 0 0 0-7.998636-35.449951 32.122519 32.122519 0 0 0-35.961864-5.055137L566.582687 81.120879A443.124392 443.124392 0 0 0 321.184558 448.098263H160.06005a31.994541 31.994541 0 0 0-22.652135 54.646676l274.705128 274.64114zM352.027295 512.023356a31.994541 31.994541 0 0 0 31.994541-31.994541A379.711212 379.711212 0 0 1 595.185806 138.391107l79.858375-39.929187-49.207604 122.923026A692.7458 692.7458 0 0 0 575.989082 480.092804a31.994541 31.994541 0 0 0 31.994541 31.994541h114.732424l-220.058453 220.058453a31.994541 31.994541 0 0 1-45.240281 0L237.294872 512.087345 352.027295 512.023356z" /></svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
14
src/components/dnd/DropMask.tsx
Normal file
14
src/components/dnd/DropMask.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import '@/assets/css/components/dnd/drop-mask.scss'
|
||||
import Icon from '@ant-design/icons'
|
||||
|
||||
const DropMask = () => {
|
||||
return (
|
||||
<div data-component={'component-drop-mask'}>
|
||||
<div className={'drop-mask-border'}>
|
||||
<Icon component={IconOxygenReceive} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default DropMask
|
||||
@@ -4,14 +4,19 @@ import protocolCheck from 'custom-protocol-check'
|
||||
import Icon from '@ant-design/icons'
|
||||
import '@/assets/css/components/tools/store-card.scss'
|
||||
import { COLOR_BACKGROUND, COLOR_MAIN, COLOR_PRODUCTION } from '@/constants/common.constants'
|
||||
import { checkDesktop } from '@/util/common'
|
||||
import { navigateToSource, navigateToStore, navigateToView } from '@/util/navigation'
|
||||
import { checkDesktop, omitText } from '@/util/common'
|
||||
import { getLoginStatus, getUserId } from '@/util/auth'
|
||||
import {
|
||||
navigateToLogin,
|
||||
navigateToSource,
|
||||
navigateToStore,
|
||||
navigateToView
|
||||
} from '@/util/navigation'
|
||||
import { r_tool_add_favorite, r_tool_remove_favorite } from '@/services/tool'
|
||||
import Card from '@/components/common/Card'
|
||||
import FlexBox from '@/components/common/FlexBox'
|
||||
import { getUserId } from '@/util/auth.tsx'
|
||||
import DragHandle from '@/components/dnd/DragHandle.tsx'
|
||||
import Draggable from '@/components/dnd/Draggable.tsx'
|
||||
import DragHandle from '@/components/dnd/DragHandle'
|
||||
import Draggable from '@/components/dnd/Draggable'
|
||||
|
||||
interface StoreCardProps extends DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement> {
|
||||
icon: string
|
||||
@@ -58,7 +63,9 @@ const StoreCard = ({
|
||||
|
||||
useEffect(() => {
|
||||
cardRef.current && VanillaTilt.init(cardRef.current, options)
|
||||
getUserId().then((value) => setUserId(value))
|
||||
if (getLoginStatus()) {
|
||||
void getUserId().then((value) => setUserId(value))
|
||||
}
|
||||
}, [options])
|
||||
|
||||
const handleCardOnClick = () => {
|
||||
@@ -99,6 +106,10 @@ const StoreCard = ({
|
||||
|
||||
const handleOnStarBtnClick = (e: MouseEvent<HTMLDivElement>) => {
|
||||
e.stopPropagation()
|
||||
if (!getLoginStatus()) {
|
||||
navigateToLogin(navigate, undefined, `${location.pathname}${location.search}`)
|
||||
return
|
||||
}
|
||||
if (favorite_) {
|
||||
void r_tool_remove_favorite({
|
||||
authorId: author.id,
|
||||
@@ -249,7 +260,12 @@ const StoreCard = ({
|
||||
<div className={'info'}>
|
||||
<div className={'tool-name'}>{toolName}</div>
|
||||
<div className={'tool-id'}>{`ID: ${toolId}`}</div>
|
||||
{toolDesc && <div className={'tool-desc'}>{`简介:${toolDesc}`}</div>}
|
||||
{toolDesc && (
|
||||
<div
|
||||
className={'tool-desc'}
|
||||
title={toolDesc}
|
||||
>{`简介:${omitText(toolDesc, 18)}`}</div>
|
||||
)}
|
||||
</div>
|
||||
{showAuthor && (
|
||||
<div className={'author'} onClick={handleOnClickAuthor}>
|
||||
|
||||
@@ -1,25 +1,30 @@
|
||||
import { DndContext, DragOverEvent, DragStartEvent } from '@dnd-kit/core'
|
||||
import Droppable from '@/components/dnd/Droppable'
|
||||
import { arrayMove, SortableContext } from '@dnd-kit/sortable'
|
||||
import type { DragEndEvent } from '@dnd-kit/core/dist/types'
|
||||
import '@/assets/css/pages/tools-framework.scss'
|
||||
import { tools } from '@/router/tools'
|
||||
import { getToolMenuItem, saveToolMenuItem } from '@/util/common'
|
||||
import { getViewPath } from '@/util/navigation'
|
||||
import FitFullscreen from '@/components/common/FitFullscreen'
|
||||
import Sidebar from '@/components/common/Sidebar'
|
||||
import FullscreenLoadingMask from '@/components/common/FullscreenLoadingMask'
|
||||
import { arrayMove, SortableContext } from '@dnd-kit/sortable'
|
||||
import { getViewPath } from '@/util/navigation.tsx'
|
||||
import Sortable from '@/components/dnd/Sortable.tsx'
|
||||
import DragHandle from '@/components/dnd/DragHandle.tsx'
|
||||
import DraggableOverlay from '@/components/dnd/DraggableOverlay.tsx'
|
||||
import { getToolMenuItem, saveToolMenuItem } from '@/util/common.tsx'
|
||||
import Sortable from '@/components/dnd/Sortable'
|
||||
import DragHandle from '@/components/dnd/DragHandle'
|
||||
import DraggableOverlay from '@/components/dnd/DraggableOverlay'
|
||||
import DropMask from '@/components/dnd/DropMask'
|
||||
import Droppable from '@/components/dnd/Droppable'
|
||||
|
||||
const ToolsFramework = () => {
|
||||
const [isDelete, setIsDelete] = useState(false)
|
||||
const [toolMenuItem, setToolMenuItem] = useState<ToolMenuItem[]>(getToolMenuItem)
|
||||
const [activeItem, setActiveItem] = useState<ToolMenuItem | null>(null)
|
||||
const [showDropMask, setShowDropMask] = useState(false)
|
||||
|
||||
const handleOnDragStart = ({ active }: DragStartEvent) => {
|
||||
setActiveItem(active.data.current as ToolMenuItem)
|
||||
if (!active.data.current?.sortable) {
|
||||
setShowDropMask(true)
|
||||
}
|
||||
}
|
||||
|
||||
const handleOnDragOver = ({ over }: DragOverEvent) => {
|
||||
@@ -62,10 +67,8 @@ const ToolsFramework = () => {
|
||||
}
|
||||
}
|
||||
|
||||
console.log('active', active)
|
||||
console.log('over', over)
|
||||
|
||||
setActiveItem(null)
|
||||
setShowDropMask(false)
|
||||
}
|
||||
|
||||
const handleOnDragCancel = () => {
|
||||
@@ -164,6 +167,7 @@ const ToolsFramework = () => {
|
||||
</DraggableOverlay>
|
||||
</Sidebar.ItemList>
|
||||
</Sidebar.Scroll>
|
||||
{showDropMask && <DropMask />}
|
||||
</Droppable>
|
||||
</Sidebar>
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import FullscreenLoadingMask from '@/components/common/FullscreenLoadingMask'
|
||||
import { floor } from 'lodash'
|
||||
import { getLocalStorage, setLocalStorage } from '@/util/browser.tsx'
|
||||
import { STORAGE_TOOL_MENU_ITEM_KEY } from '@/constants/common.constants.ts'
|
||||
import { STORAGE_TOOL_MENU_ITEM_KEY } from '@/constants/common.constants'
|
||||
import { getLocalStorage, setLocalStorage } from '@/util/browser'
|
||||
import FullscreenLoadingMask from '@/components/common/FullscreenLoadingMask'
|
||||
|
||||
export const randomInt = (start: number, end: number) => {
|
||||
if (start > end) {
|
||||
@@ -147,3 +147,10 @@ export const getToolMenuItem = (): ToolMenuItem[] => {
|
||||
}
|
||||
return JSON.parse(s) as ToolMenuItem[]
|
||||
}
|
||||
|
||||
export const omitText = (text: string, length: number) => {
|
||||
if (text.length <= length) {
|
||||
return text
|
||||
}
|
||||
return `${text.substring(0, length)}...`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user