feat: rename ty-form, add search form collapse, use UnoCSS @apply
- ty-schema-form 改名 ty-form - ty-search-form 支持折叠/展开(collapseCount 默认 2,查询/重置置右) - ty-table/ty-crud/ty-search-form 样式改用 @apply 工具类 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
45b22acd6c
commit
104b7678d3
4
components.d.ts
vendored
4
components.d.ts
vendored
@ -49,10 +49,10 @@ declare module 'vue' {
|
|||||||
TyBreadcrumb: typeof import('./src/components/ty-breadcrumb.vue')['default']
|
TyBreadcrumb: typeof import('./src/components/ty-breadcrumb.vue')['default']
|
||||||
TyCrud: typeof import('./src/components/ty-crud.vue')['default']
|
TyCrud: typeof import('./src/components/ty-crud.vue')['default']
|
||||||
TyFooter: typeof import('./src/components/ty-footer.vue')['default']
|
TyFooter: typeof import('./src/components/ty-footer.vue')['default']
|
||||||
|
TyForm: typeof import('./src/components/ty-form.vue')['default']
|
||||||
TyFormDialog: typeof import('./src/components/ty-form-dialog.vue')['default']
|
TyFormDialog: typeof import('./src/components/ty-form-dialog.vue')['default']
|
||||||
TyHeader: typeof import('./src/components/ty-header.vue')['default']
|
TyHeader: typeof import('./src/components/ty-header.vue')['default']
|
||||||
TyMixbar: typeof import('./src/components/ty-mixbar.vue')['default']
|
TyMixbar: typeof import('./src/components/ty-mixbar.vue')['default']
|
||||||
TySchemaForm: typeof import('./src/components/ty-schema-form.vue')['default']
|
|
||||||
TySearchForm: typeof import('./src/components/ty-search-form.vue')['default']
|
TySearchForm: typeof import('./src/components/ty-search-form.vue')['default']
|
||||||
TySetting: typeof import('./src/components/ty-setting.vue')['default']
|
TySetting: typeof import('./src/components/ty-setting.vue')['default']
|
||||||
TySettingPanel: typeof import('./src/components/ty-setting-panel.vue')['default']
|
TySettingPanel: typeof import('./src/components/ty-setting-panel.vue')['default']
|
||||||
@ -104,10 +104,10 @@ declare global {
|
|||||||
const TyBreadcrumb: typeof import('./src/components/ty-breadcrumb.vue')['default']
|
const TyBreadcrumb: typeof import('./src/components/ty-breadcrumb.vue')['default']
|
||||||
const TyCrud: typeof import('./src/components/ty-crud.vue')['default']
|
const TyCrud: typeof import('./src/components/ty-crud.vue')['default']
|
||||||
const TyFooter: typeof import('./src/components/ty-footer.vue')['default']
|
const TyFooter: typeof import('./src/components/ty-footer.vue')['default']
|
||||||
|
const TyForm: typeof import('./src/components/ty-form.vue')['default']
|
||||||
const TyFormDialog: typeof import('./src/components/ty-form-dialog.vue')['default']
|
const TyFormDialog: typeof import('./src/components/ty-form-dialog.vue')['default']
|
||||||
const TyHeader: typeof import('./src/components/ty-header.vue')['default']
|
const TyHeader: typeof import('./src/components/ty-header.vue')['default']
|
||||||
const TyMixbar: typeof import('./src/components/ty-mixbar.vue')['default']
|
const TyMixbar: typeof import('./src/components/ty-mixbar.vue')['default']
|
||||||
const TySchemaForm: typeof import('./src/components/ty-schema-form.vue')['default']
|
|
||||||
const TySearchForm: typeof import('./src/components/ty-search-form.vue')['default']
|
const TySearchForm: typeof import('./src/components/ty-search-form.vue')['default']
|
||||||
const TySetting: typeof import('./src/components/ty-setting.vue')['default']
|
const TySetting: typeof import('./src/components/ty-setting.vue')['default']
|
||||||
const TySettingPanel: typeof import('./src/components/ty-setting-panel.vue')['default']
|
const TySettingPanel: typeof import('./src/components/ty-setting-panel.vue')['default']
|
||||||
|
|||||||
@ -176,13 +176,11 @@ onMounted(fetchList)
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.ty-crud {
|
.ty-crud__search {
|
||||||
&__search {
|
@apply mb-md;
|
||||||
margin-bottom: 12px;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
&__toolbar {
|
.ty-crud__toolbar {
|
||||||
margin-bottom: 12px;
|
@apply mb-md;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog v-model="visible" :title="title" :width="width" destroy-on-close @closed="onClosed">
|
<el-dialog v-model="visible" :title="title" :width="width" destroy-on-close @closed="onClosed">
|
||||||
<ty-schema-form
|
<ty-form
|
||||||
ref="formRef"
|
ref="formRef"
|
||||||
:schema="schema"
|
:schema="schema"
|
||||||
:model-value="modelValue"
|
:model-value="modelValue"
|
||||||
|
|||||||
@ -66,7 +66,7 @@ import { computed, ref } from 'vue'
|
|||||||
import type { FormInstance, FormRules } from 'element-plus'
|
import type { FormInstance, FormRules } from 'element-plus'
|
||||||
import type { JsonSchema, JsonSchemaProperty } from '@/types/crud'
|
import type { JsonSchema, JsonSchemaProperty } from '@/types/crud'
|
||||||
|
|
||||||
defineOptions({ name: 'TySchemaForm' })
|
defineOptions({ name: 'TyForm' })
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
@ -1,29 +1,53 @@
|
|||||||
<template>
|
<template>
|
||||||
<ty-schema-form :schema="schema" :model-value="modelValue" inline>
|
<ty-form :schema="visibleSchema" :model-value="modelValue" inline>
|
||||||
<el-form-item>
|
<el-form-item class="ty-search-form__actions">
|
||||||
|
<el-button v-if="collapsible" link type="primary" @click="expanded = !expanded">
|
||||||
|
{{ expanded ? '收起' : '展开' }}
|
||||||
|
<icon type="iconify" :icon="expanded ? 'mdi:chevron-up' : 'mdi:chevron-down'" />
|
||||||
|
</el-button>
|
||||||
<el-button type="primary" @click="emit('search')">查询</el-button>
|
<el-button type="primary" @click="emit('search')">查询</el-button>
|
||||||
<el-button @click="handleReset">重置</el-button>
|
<el-button @click="handleReset">重置</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</ty-schema-form>
|
</ty-form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { JsonSchema } from '@/types/crud'
|
import { computed, ref } from 'vue'
|
||||||
|
import type { JsonSchema, JsonSchemaProperty } from '@/types/crud'
|
||||||
|
|
||||||
defineOptions({ name: 'TySearchForm' })
|
defineOptions({ name: 'TySearchForm' })
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = withDefaults(
|
||||||
/** 搜索字段 JSON Schema。 */
|
defineProps<{
|
||||||
schema: JsonSchema
|
/** 搜索字段 JSON Schema。 */
|
||||||
/** 搜索条件(就地绑定)。 */
|
schema: JsonSchema
|
||||||
modelValue: Record<string, any>
|
/** 搜索条件(就地绑定)。 */
|
||||||
}>()
|
modelValue: Record<string, any>
|
||||||
|
/** 折叠时展示的字段数量。 */
|
||||||
|
collapseCount?: number
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
collapseCount: 2,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'search'): void
|
(e: 'search'): void
|
||||||
(e: 'reset'): void
|
(e: 'reset'): void
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
const expanded = ref(false)
|
||||||
|
|
||||||
|
const collapsible = computed(() => Object.keys(props.schema.properties).length > props.collapseCount)
|
||||||
|
|
||||||
|
const visibleSchema = computed<JsonSchema>(() => {
|
||||||
|
if (expanded.value || !collapsible.value) return props.schema
|
||||||
|
const keys = Object.keys(props.schema.properties).slice(0, props.collapseCount)
|
||||||
|
const properties: Record<string, JsonSchemaProperty> = {}
|
||||||
|
for (const k of keys) properties[k] = props.schema.properties[k]
|
||||||
|
return { type: 'object', properties, required: props.schema.required?.filter((r) => keys.includes(r)) }
|
||||||
|
})
|
||||||
|
|
||||||
function handleReset(): void {
|
function handleReset(): void {
|
||||||
for (const [key, prop] of Object.entries(props.schema.properties)) {
|
for (const [key, prop] of Object.entries(props.schema.properties)) {
|
||||||
props.modelValue[key] = prop.default ?? ''
|
props.modelValue[key] = prop.default ?? ''
|
||||||
@ -31,3 +55,9 @@ function handleReset(): void {
|
|||||||
emit('reset')
|
emit('reset')
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.ty-search-form__actions {
|
||||||
|
@apply ml-auto mb-0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@ -105,10 +105,7 @@ function formatDateTime(value: unknown): string {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.ty-table {
|
.ty-table__pagination {
|
||||||
&__pagination {
|
@apply mt-md justify-end;
|
||||||
margin-top: 12px;
|
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user