refactor: 同步 GiDemo 更新

This commit is contained in:
2025-04-04 19:00:18 +08:00
parent 269266d261
commit d97cf15938
14 changed files with 362 additions and 145 deletions

View File

@@ -145,4 +145,12 @@ const isDisabled: Props['cellDisabled'] = (p) => {
defineExpose({ formRef })
</script>
<style lang='scss' scoped></style>
<style lang='scss' scoped>
:deep(.arco-form-item) {
margin-bottom: 0;
.arco-form-item-message {
display: none;
}
}
</style>

View File

@@ -1,36 +0,0 @@
<template>
<div ref="BoxRef" class="gi-flexible-box" :style="style">
<slot></slot>
</div>
</template>
<script setup lang="ts">
import type { CSSProperties } from 'vue'
defineOptions({ name: 'GiFlexibleBox' })
const props = withDefaults(defineProps<Props>(), {
modelValue: false,
direction: 'right',
})
interface Props {
modelValue: boolean
direction: 'left' | 'right'
}
const BoxRef = ref<HTMLElement | null>()
const style = computed(() => {
const obj: CSSProperties = {}
obj[`margin-${props.direction}`]
= !props.modelValue && BoxRef.value && BoxRef.value.clientWidth ? `-${BoxRef.value.clientWidth}px` : 0
return obj
})
</script>
<style scoped lang="scss">
.gi-flexible-box {
transition: all 0.36s;
}
</style>

View File

@@ -0,0 +1,120 @@
<!--
@file GiIconBox 组件 - 图标容器
@description 提供可自定义的图标容器支持不同颜色尺寸和形状
-->
<template>
<div class="gi-icon-box" :class="getClass" :style="getStyle">
<slot />
</div>
</template>
<script setup lang="ts">
import { type CSSProperties, computed } from 'vue'
const props = withDefaults(defineProps<Props>(), {
color: '#165DFF',
size: 20,
shape: 'square',
})
/** 预设状态颜色 */
const STATUS_COLORS = ['primary', 'success', 'warning', 'danger'] as const
/** 形状类型 */
type ShapeType = 'square' | 'round'
/** 颜色类型 */
type ColorType = typeof STATUS_COLORS[number] | string
/** 组件属性定义 */
interface Props {
/**
* 背景颜色
* @description 支持预设状态颜色或自定义颜色值
* @default '#165DFF'
*/
color?: ColorType
/**
* 容器尺寸
* @description 单位为像素
* @default 20
*/
size?: number
/**
* 容器形状
* @description square-方形round-圆形
* @default 'square'
*/
shape?: ShapeType
}
/** 计算容器的 class */
const getClass = computed(() => {
const classes = [
STATUS_COLORS.includes(props.color as typeof STATUS_COLORS[number])
&& `gi-icon-box--${props.color}`,
props.shape && `gi-icon-box__shape--${props.shape}`,
].filter(Boolean)
return classes.join(' ')
})
/** 计算容器的样式 */
const getStyle = computed((): CSSProperties => {
const style: CSSProperties = {}
// 处理自定义颜色
if (!STATUS_COLORS.includes(props.color as typeof STATUS_COLORS[number])) {
style.backgroundColor = props.color
}
// 处理自定义尺寸
if (props.size !== 20) {
style.width = `${props.size}px`
style.height = `${props.size}px`
}
return style
})
</script>
<style lang="scss" scoped>
.gi-icon-box {
display: flex;
justify-content: center;
align-items: center;
flex-shrink: 0;
width: 20px;
height: 20px;
color: #fff;
transition: all 0.2s ease;
// 状态颜色
&--primary {
background-color: rgba(var(--primary-6));
}
&--success {
background-color: rgba(var(--success-6));
}
&--warning {
background-color: rgba(var(--warning-6));
}
&--danger {
background-color: rgba(var(--danger-6));
}
// 形状样式
&__shape {
&--square {
border-radius: 4px;
}
&--round {
border-radius: 50%;
}
}
}
</style>

View File

@@ -1,60 +0,0 @@
<template>
<a-row align="stretch" :gutter="14" class="gi-left-right-pane">
<a-col
:xs="0" :sm="8" :md="7" :lg="6" :xl="5" :xxl="4" flex="260px" v-bind="props.leftColProps"
class="h-full overflow-hidden"
>
<div class="gi-left-right-pane__left">
<slot name="left"></slot>
</div>
</a-col>
<a-col
:xs="24" :sm="16" :md="17" :lg="18" :xl="19" :xxl="20" flex="1" v-bind="props.rightColProps"
class="h-full overflow-hidden"
>
<div class="gi-left-right-pane__right">
<slot></slot>
</div>
</a-col>
</a-row>
</template>
<script lang='ts' setup>
import type { ColProps } from '@arco-design/web-vue'
interface Props {
leftColProps?: ColProps
rightColProps?: ColProps
}
defineOptions({ name: 'GiLeftRightPane' })
const props = withDefaults(defineProps<Props>(), {
leftColProps: () => ({}),
rightColProps: () => ({}),
})
// 一般用于左树右表结构页面
defineSlots<{
left: () => void
}>()
</script>
<style lang='scss' scoped>
.gi-left-right-pane {
flex: 1;
overflow: hidden;
padding: $margin;
box-sizing: border-box;
&__left,
&__right {
height: 100%;
display: flex;
flex-direction: column;
overflow: hidden;
}
}
</style>

View File

@@ -1,32 +0,0 @@
<template>
<a-overflow-list v-if="data.length">
<a-tag v-for="(item, index) in data" :key="index" size="small">
{{ item }}
</a-tag>
<template #overflow="{ number }">
<a-popover :content-style="{ maxWidth: '300px', padding: '8px 12px' }">
<a-tag color="arcoblue" size="small">+{{ number }}</a-tag>
<template #content>
<a-space wrap>
<a-tag v-for="tag in data.filter((i, n) => n >= data.length - number)" :key="tag" size="small">
{{ tag }}
</a-tag>
</a-space>
</template>
</a-popover>
</template>
</a-overflow-list>
</template>
<script setup lang="ts">
defineOptions({ name: 'GiOverFlowTags' })
withDefaults(defineProps<Props>(), {
data: () => [],
})
interface Props {
data: string[]
}
</script>
<style scoped lang="scss"></style>

View File

@@ -0,0 +1,134 @@
<template>
<a-row align="stretch" :gutter="rowGutter" class="gi-page-layout" :class="getClass">
<a-col v-if="slots.left" v-bind="props.leftColProps" :xs="0" :sm="8" :md="7" :lg="6" :xl="5" :xxl="4" flex="260px">
<div class="gi-page-layout__left" :style="props.leftStyle">
<slot name="left"></slot>
</div>
</a-col>
<a-col :xs="24" :sm="16" :md="17" :lg="18" :xl="19" :xxl="20" flex="1" v-bind="props.rightColProps">
<div v-if="slots.header" class="gi-page-layout__header" :style="props.headerStyle">
<slot name="header"></slot>
</div>
<div class="gi-page-layout__body" :style="props.bodyStyle">
<slot></slot>
</div>
</a-col>
</a-row>
</template>
<script setup lang='ts'>
import type { ColProps } from '@arco-design/web-vue'
import type { CSSProperties } from 'vue'
defineOptions({ name: 'GiPageLayout' })
const props = withDefaults(defineProps<Props>(), {
margin: true,
padding: true,
gutter: false,
leftColProps: () => ({}),
rightColProps: () => ({}),
leftStyle: () => ({}),
headerStyle: () => ({}),
bodyStyle: () => ({}),
})
/** 组件插槽定义 */
defineSlots<{
header: () => void
left: () => void
default: () => void
}>()
const getClass = computed(() => {
return {
'gi-page-layout--margin': props.margin,
'gi-page-layout--padding': props.padding,
'gi-page-layout--gutter': !!props.gutter,
}
})
const rowGutter = computed(() => {
if (typeof props.gutter === 'boolean') {
return props.gutter ? 14 : undefined
}
return props.gutter
})
/** 组件属性定义 */
interface Props {
margin?: boolean
padding?: boolean
gutter?: boolean | number
leftColProps?: ColProps
rightColProps?: ColProps
leftStyle?: CSSProperties
headerStyle?: CSSProperties
bodyStyle?: CSSProperties
}
const slots = useSlots()
</script>
<style lang='scss' scoped>
.gi-page-layout {
flex: 1;
height: 100%;
display: flex;
overflow: hidden;
box-sizing: border-box;
background-color: var(--color-bg-1);
&--margin {
margin: $margin;
}
&--padding {
.gi-page-layout__left,
.gi-page-layout__header,
.gi-page-layout__body {
padding: $padding;
}
.gi-page-layout__header {
padding-bottom: 0;
}
}
&--gutter {
.gi-page-layout__body-left {
border-right: none;
}
}
:deep(.arco-col) {
height: 100%;
display: flex;
flex-direction: column;
overflow: hidden;
}
}
.gi-page-layout__left {
height: 100%;
border-right: 1px solid var(--color-border);
display: flex;
flex-direction: column;
overflow: hidden;
box-sizing: border-box;
}
.gi-page-layout__header {
border-bottom: 1px solid var(--color-border);
box-sizing: border-box;
}
.gi-page-layout__body {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
box-sizing: border-box;
}
</style>