feat: 实现发行申请提交
This commit is contained in:
2
src/components/ui/collapse/exports.ts
Normal file
2
src/components/ui/collapse/exports.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export { default as Collapse } from './index.vue';
|
||||
export type * from './types';
|
||||
138
src/components/ui/collapse/index.vue
Normal file
138
src/components/ui/collapse/index.vue
Normal file
@@ -0,0 +1,138 @@
|
||||
<script lang='ts' setup>
|
||||
import type { CollapseEmits, CollapseProps } from "./types";
|
||||
import { IonIcon } from "@ionic/vue";
|
||||
import { chevronDownOutline } from "ionicons/icons";
|
||||
import { nextTick, ref } from "vue";
|
||||
|
||||
const props = withDefaults(defineProps<CollapseProps>(), {
|
||||
disabled: false,
|
||||
bordered: true,
|
||||
size: "medium",
|
||||
});
|
||||
|
||||
defineEmits<CollapseEmits>();
|
||||
|
||||
const active = defineModel<boolean>("active", { type: Boolean, default: true });
|
||||
|
||||
const contentRef = ref<HTMLElement>();
|
||||
|
||||
async function toggle() {
|
||||
if (props.disabled)
|
||||
return;
|
||||
|
||||
if (!active.value) {
|
||||
// 展开
|
||||
active.value = true;
|
||||
await nextTick();
|
||||
|
||||
if (contentRef.value) {
|
||||
const height = contentRef.value.scrollHeight;
|
||||
contentRef.value.style.height = "0px";
|
||||
requestAnimationFrame(() => {
|
||||
contentRef.value!.style.height = `${height}px`;
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
// 收起
|
||||
if (contentRef.value) {
|
||||
const height = contentRef.value.scrollHeight;
|
||||
contentRef.value.style.height = `${height}px`;
|
||||
requestAnimationFrame(() => {
|
||||
contentRef.value!.style.height = "0px";
|
||||
});
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
active.value = false;
|
||||
}, 300);
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
if (contentRef.value && active.value) {
|
||||
contentRef.value.style.height = "auto";
|
||||
}
|
||||
}, 300);
|
||||
}
|
||||
|
||||
function onTransitionEnd() {
|
||||
if (contentRef.value && !active.value) {
|
||||
contentRef.value.style.height = "0px";
|
||||
}
|
||||
}
|
||||
|
||||
// 暴露给父组件的方法和属性
|
||||
defineExpose({
|
||||
toggle,
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="w-full overflow-hidden"
|
||||
:class="{
|
||||
'border border-gray-200 dark:border-gray-600 rounded-lg': bordered,
|
||||
'opacity-60': disabled,
|
||||
}"
|
||||
>
|
||||
<!-- 头部触发区域 -->
|
||||
<div
|
||||
class="flex items-center justify-between cursor-pointer transition-colors duration-200 select-none"
|
||||
:class="[
|
||||
{
|
||||
'border-b border-gray-200 dark:border-gray-600': bordered,
|
||||
},
|
||||
{
|
||||
'p-3 text-sm': size === 'small',
|
||||
'p-4 text-base': size === 'medium',
|
||||
'p-5 text-lg': size === 'large',
|
||||
},
|
||||
{
|
||||
'cursor-not-allowed': disabled,
|
||||
},
|
||||
]"
|
||||
@click="toggle"
|
||||
>
|
||||
<div class="font-medium text-gray-900 dark:text-white flex-1">
|
||||
<slot name="title">
|
||||
{{ title }}
|
||||
</slot>
|
||||
</div>
|
||||
|
||||
<IonIcon
|
||||
:icon="chevronDownOutline"
|
||||
class="text-gray-500 dark:text-gray-400 transition-transform duration-300"
|
||||
:class="[
|
||||
{
|
||||
'w-4 h-4': size === 'small',
|
||||
'w-5 h-5': size === 'medium',
|
||||
'w-6 h-6': size === 'large',
|
||||
},
|
||||
{
|
||||
'rotate-180': active,
|
||||
},
|
||||
]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 内容区域 -->
|
||||
<div
|
||||
ref="contentRef"
|
||||
class="overflow-hidden transition-all duration-300 ease-in-out"
|
||||
:style="{ height: active ? 'auto' : '0' }"
|
||||
@transitionend="onTransitionEnd"
|
||||
>
|
||||
<div
|
||||
class="p-4 text-gray-600 dark:text-gray-300 space-y-5"
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang='css' scoped>
|
||||
.select-none {
|
||||
user-select: none;
|
||||
}
|
||||
</style>
|
||||
29
src/components/ui/collapse/types.ts
Normal file
29
src/components/ui/collapse/types.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
export interface CollapseProps {
|
||||
/** 面板标题 */
|
||||
title?: string;
|
||||
/** 是否禁用 */
|
||||
disabled?: boolean;
|
||||
/** 是否显示边框 */
|
||||
bordered?: boolean;
|
||||
/** 尺寸大小 */
|
||||
size?: "small" | "medium" | "large";
|
||||
/** 是否展开 (v-model:active) */
|
||||
active?: boolean;
|
||||
}
|
||||
|
||||
export interface CollapseEmits {
|
||||
/** 展开状态变化时触发 */
|
||||
"update:active": [value: boolean];
|
||||
}
|
||||
|
||||
export interface CollapseSlots {
|
||||
/** 默认插槽 - 面板内容 */
|
||||
default: () => any;
|
||||
/** 标题插槽 - 自定义标题内容 */
|
||||
title: () => any;
|
||||
}
|
||||
|
||||
export interface CollapseInstance {
|
||||
/** 切换展开/收起状态 */
|
||||
toggle: () => void;
|
||||
}
|
||||
Reference in New Issue
Block a user