@a2simcode/ui 0.0.132 → 0.0.134
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/index.d.ts +4 -1
- package/dist/components/input-map/index.d.ts +101 -0
- package/dist/components/input-map/src/input-map.vue.d.ts +86 -0
- package/dist/components/vpanel/index.d.ts +22 -0
- package/dist/components/vpanel/src/vpanel.vue.d.ts +19 -0
- package/dist/simcode-ui.es.js +3504 -3332
- package/dist/simcode-ui.umd.js +2 -2
- package/dist/stats.html +1 -1
- package/docs/components/form.md +15 -0
- package/docs/components/input-map.md +24 -0
- package/docs/components/meta/input-map.ts +32 -0
- package/docs/components/meta/vpanel.ts +20 -0
- package/docs/components/vpanel.md +25 -0
- package/docs/examples/form/master-detail.vue +203 -0
- package/docs/examples/input-map/basic.vue +18 -0
- package/docs/examples/vpanel/basic.vue +88 -0
- package/package.json +1 -1
package/docs/components/form.md
CHANGED
|
@@ -28,6 +28,19 @@
|
|
|
28
28
|
</template>
|
|
29
29
|
</Demo>
|
|
30
30
|
|
|
31
|
+
## 主从表(主表 + 子表)
|
|
32
|
+
|
|
33
|
+
通过 `j-layout` 划分区域,并在 `children` 中利用 `j-table` 搭配其子级输入组件,可以实现复杂的主从表(表单 + 子表格)布局。
|
|
34
|
+
|
|
35
|
+
<Demo :source-code="masterDetailCode">
|
|
36
|
+
<template #source>
|
|
37
|
+
<master-detail />
|
|
38
|
+
</template>
|
|
39
|
+
<template #description>
|
|
40
|
+
结合 `j-layout` 布局组件实现主从表单。在子表中配置 `editConfig: { isAddBtn: true, isRemoveBtn: true }` 并提供 `addRow` 函数来管理行数据;通过 `slot: 'top'` 指定字段归属为主表区域。
|
|
41
|
+
</template>
|
|
42
|
+
</Demo>
|
|
43
|
+
|
|
31
44
|
## API
|
|
32
45
|
|
|
33
46
|
<ApiTable :data="formApi" componentName="form" />
|
|
@@ -35,8 +48,10 @@
|
|
|
35
48
|
<script setup>
|
|
36
49
|
import Basic from '../examples/form/basic.vue'
|
|
37
50
|
import Init from '../examples/form/init.vue'
|
|
51
|
+
import MasterDetail from '../examples/form/master-detail.vue'
|
|
38
52
|
import formApi from './meta/form'
|
|
39
53
|
|
|
40
54
|
import basicCode from '../examples/form/basic.vue?raw'
|
|
41
55
|
import initCode from '../examples/form/init.vue?raw'
|
|
56
|
+
import masterDetailCode from '../examples/form/master-detail.vue?raw'
|
|
42
57
|
</script>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# InputMap 地图选择器
|
|
2
|
+
|
|
3
|
+
一个基于输入框的地图选择组件,允许用户通过地图选择位置信息。
|
|
4
|
+
|
|
5
|
+
## 基础用法
|
|
6
|
+
|
|
7
|
+
<Demo :source-code="inputMapBasicCode">
|
|
8
|
+
<template #source>
|
|
9
|
+
<input-map-basic />
|
|
10
|
+
</template>
|
|
11
|
+
<template #description>
|
|
12
|
+
通过 `v-model` 绑定当前选中的位置信息,支持 `placeholder` 等属性来自定义。
|
|
13
|
+
</template>
|
|
14
|
+
</Demo>
|
|
15
|
+
|
|
16
|
+
## API
|
|
17
|
+
|
|
18
|
+
<ApiTable :data="inputMapApi" componentName="input-map" />
|
|
19
|
+
|
|
20
|
+
<script setup>
|
|
21
|
+
import InputMapBasic from '../examples/input-map/basic.vue'
|
|
22
|
+
import inputMapApi from './meta/input-map'
|
|
23
|
+
import inputMapBasicCode from '../examples/input-map/basic.vue?raw'
|
|
24
|
+
</script>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export default [
|
|
2
|
+
{
|
|
3
|
+
"name": "modelValue",
|
|
4
|
+
"description": "输入值",
|
|
5
|
+
"type": "string",
|
|
6
|
+
"default": "-"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"name": "placeholder",
|
|
10
|
+
"description": "占位符",
|
|
11
|
+
"type": "string",
|
|
12
|
+
"default": "请选择"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"name": "readonly",
|
|
16
|
+
"description": "是否只读",
|
|
17
|
+
"type": "boolean",
|
|
18
|
+
"default": "false"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"name": "size",
|
|
22
|
+
"description": "选框尺寸",
|
|
23
|
+
"type": "'small' | 'large' | 'middle'",
|
|
24
|
+
"default": "-"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"name": "clearable",
|
|
28
|
+
"description": "是否可以清除",
|
|
29
|
+
"type": "boolean",
|
|
30
|
+
"default": "true"
|
|
31
|
+
}
|
|
32
|
+
]
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
"props": [],
|
|
3
|
+
"events": [],
|
|
4
|
+
"slots": [
|
|
5
|
+
{
|
|
6
|
+
"name": "top",
|
|
7
|
+
"description": "顶部内容区域"
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"name": "default",
|
|
11
|
+
"description": "主要内容区域"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"name": "bottom",
|
|
15
|
+
"description": "底部内容区域"
|
|
16
|
+
}
|
|
17
|
+
],
|
|
18
|
+
"methods": [],
|
|
19
|
+
"types": []
|
|
20
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# VPanel 垂直布局
|
|
2
|
+
|
|
3
|
+
`VPanel` 是一个用于垂直方向内容布局的组件,可以方便地将内容分为顶部、主内容区域和底部。
|
|
4
|
+
|
|
5
|
+
## 基础用法
|
|
6
|
+
|
|
7
|
+
<Demo :source-code="vpanelBasicCode">
|
|
8
|
+
<template #source>
|
|
9
|
+
<vpanel-basic />
|
|
10
|
+
</template>
|
|
11
|
+
<template #description>
|
|
12
|
+
`VPanel` 通过 `top` 具名插槽和 `bottom` 具名插槽来放置顶部和底部内容,未具名插槽则为主内容区域。
|
|
13
|
+
</template>
|
|
14
|
+
</Demo>
|
|
15
|
+
|
|
16
|
+
## API
|
|
17
|
+
|
|
18
|
+
<ApiTable :data="vpanelApi" componentName="vpanel" />
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
<script setup>
|
|
22
|
+
import VpanelBasic from '../examples/vpanel/basic.vue'
|
|
23
|
+
import vpanelApi from './meta/vpanel'
|
|
24
|
+
import vpanelBasicCode from '../examples/vpanel/basic.vue?raw'
|
|
25
|
+
</script>
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="demo-form-layout">
|
|
3
|
+
<j-form ref="formRef" :schema="schema" :config="{ labelWidth: '80px' }" />
|
|
4
|
+
<div class="demo-actions" style="margin-top: 16px; text-align: right">
|
|
5
|
+
<j-button type="primary" label="保存" @click="handleSave"></j-button>
|
|
6
|
+
<j-button style="margin-left: 8px" label="重置" @click="handleReset"></j-button>
|
|
7
|
+
<j-button style="margin-left: 8px" label="加载模拟数据" @click="handleLoadMock"></j-button>
|
|
8
|
+
</div>
|
|
9
|
+
</div>
|
|
10
|
+
</template>
|
|
11
|
+
|
|
12
|
+
<script setup lang="ts">
|
|
13
|
+
import { ref } from 'vue'
|
|
14
|
+
import { type FormSchemaConfig, buildUUID } from '@a2simcode/ui'
|
|
15
|
+
|
|
16
|
+
const formRef = ref()
|
|
17
|
+
|
|
18
|
+
// 模拟字典数据
|
|
19
|
+
const goodsTypeOptions = [
|
|
20
|
+
{ label: '电子产品', value: 'electronics' },
|
|
21
|
+
{ label: '服装', value: 'clothing' },
|
|
22
|
+
{ label: '食品', value: 'food' },
|
|
23
|
+
{ label: '日用品', value: 'daily' },
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
// 将原先 page.ts 中的 config 和 formConfig 融合到 schema 中
|
|
27
|
+
const schema: FormSchemaConfig[] = [
|
|
28
|
+
{
|
|
29
|
+
type: 'j-layout',
|
|
30
|
+
config: {
|
|
31
|
+
label: '上下布局',
|
|
32
|
+
field: 'layout',
|
|
33
|
+
top: 100,
|
|
34
|
+
needRow: { top: true },
|
|
35
|
+
needFormItem: { top: true },
|
|
36
|
+
},
|
|
37
|
+
children: [
|
|
38
|
+
{
|
|
39
|
+
type: 'j-input',
|
|
40
|
+
slot: 'top',
|
|
41
|
+
config: {
|
|
42
|
+
label: '订单号',
|
|
43
|
+
field: 'orderNo',
|
|
44
|
+
|
|
45
|
+
rule: [{ required: true, message: '请输入订单号' }],
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
type: 'j-input',
|
|
50
|
+
slot: 'top',
|
|
51
|
+
config: {
|
|
52
|
+
label: '客户名称',
|
|
53
|
+
field: 'customerName',
|
|
54
|
+
|
|
55
|
+
rule: [{ required: true, message: '请输入客户名称' }],
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
type: 'j-date',
|
|
60
|
+
slot: 'top',
|
|
61
|
+
config: {
|
|
62
|
+
label: '订单日期',
|
|
63
|
+
field: 'orderDate',
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
type: 'j-table',
|
|
68
|
+
config: {
|
|
69
|
+
label: '订单明细',
|
|
70
|
+
field: 'orderDetails',
|
|
71
|
+
editConfig: { isAddBtn: true, isRemoveBtn: true },
|
|
72
|
+
addRow: (tableData: Record<string, any>[]) => {
|
|
73
|
+
tableData.push({
|
|
74
|
+
j_Id: buildUUID(),
|
|
75
|
+
goodsName: '',
|
|
76
|
+
goodsType: 'electronics',
|
|
77
|
+
quantity: 1,
|
|
78
|
+
price: 0,
|
|
79
|
+
isShipped: 0,
|
|
80
|
+
remark: '',
|
|
81
|
+
})
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
children: [
|
|
85
|
+
{
|
|
86
|
+
type: 'j-input',
|
|
87
|
+
config: {
|
|
88
|
+
label: '商品名称',
|
|
89
|
+
field: 'goodsName',
|
|
90
|
+
minWidth: 120,
|
|
91
|
+
rule: [{ required: true, message: '请输入商品名称' }],
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
type: 'j-select',
|
|
96
|
+
config: {
|
|
97
|
+
label: '商品类型',
|
|
98
|
+
field: 'goodsType',
|
|
99
|
+
width: 120,
|
|
100
|
+
options: goodsTypeOptions,
|
|
101
|
+
rule: [{ required: true, message: '请选择商品类型' }],
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
type: 'j-number',
|
|
106
|
+
config: {
|
|
107
|
+
label: '数量',
|
|
108
|
+
field: 'quantity',
|
|
109
|
+
width: 100,
|
|
110
|
+
min: 1,
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
type: 'j-number',
|
|
115
|
+
config: {
|
|
116
|
+
label: '单价',
|
|
117
|
+
field: 'price',
|
|
118
|
+
width: 100,
|
|
119
|
+
min: 0,
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
type: 'j-switch',
|
|
124
|
+
config: {
|
|
125
|
+
label: '是否发货',
|
|
126
|
+
field: 'isShipped',
|
|
127
|
+
width: 80,
|
|
128
|
+
size: 'small',
|
|
129
|
+
activeValue: 1,
|
|
130
|
+
inactiveValue: 0,
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
type: 'j-input',
|
|
135
|
+
config: {
|
|
136
|
+
label: '备注',
|
|
137
|
+
field: 'remark',
|
|
138
|
+
minWidth: 150,
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
},
|
|
145
|
+
]
|
|
146
|
+
|
|
147
|
+
const handleSave = async () => {
|
|
148
|
+
// 调用组件内部校验方法
|
|
149
|
+
const isValid = await formRef.value?.validate()
|
|
150
|
+
if (!isValid) {
|
|
151
|
+
console.warn('表单校验未通过')
|
|
152
|
+
return
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const formData = formRef.value?.getFormData()
|
|
156
|
+
const { orderDetails, ...orderEntity } = formData || {}
|
|
157
|
+
|
|
158
|
+
const postData = {
|
|
159
|
+
OrderEntity: orderEntity,
|
|
160
|
+
OrderDetailsList: orderDetails || [],
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
console.log('保存的数据:', postData)
|
|
164
|
+
alert('数据已在控制台打印!')
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const handleReset = () => {
|
|
168
|
+
formRef.value?.resetFields()
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const handleLoadMock = () => {
|
|
172
|
+
const mockData = {
|
|
173
|
+
orderNo: 'ORD-20231001',
|
|
174
|
+
customerName: '张三',
|
|
175
|
+
orderDate: '2023-10-01',
|
|
176
|
+
orderDetails: [
|
|
177
|
+
{
|
|
178
|
+
j_Id: buildUUID(),
|
|
179
|
+
goodsName: '智能手机',
|
|
180
|
+
goodsType: 'electronics',
|
|
181
|
+
quantity: 2,
|
|
182
|
+
price: 4999,
|
|
183
|
+
isShipped: 1,
|
|
184
|
+
remark: '加急',
|
|
185
|
+
},
|
|
186
|
+
],
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// 设置表单数据
|
|
190
|
+
formRef.value?.setFormData(mockData)
|
|
191
|
+
}
|
|
192
|
+
</script>
|
|
193
|
+
|
|
194
|
+
<style scoped>
|
|
195
|
+
.demo-form-layout {
|
|
196
|
+
border: 1px solid var(--el-border-color-lighter);
|
|
197
|
+
padding: 16px;
|
|
198
|
+
border-radius: 4px;
|
|
199
|
+
position: relative;
|
|
200
|
+
width: 100%;
|
|
201
|
+
height: 400px;
|
|
202
|
+
}
|
|
203
|
+
</style>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<h3>基本用法</h3>
|
|
4
|
+
<j-input-map v-model="mapValue1" placeholder="请选择地图位置" />
|
|
5
|
+
<p>当前选中的位置: {{ mapValue1 }}</p>
|
|
6
|
+
|
|
7
|
+
<h3>只读模式</h3>
|
|
8
|
+
<j-input-map v-model="mapValue2" placeholder="只读位置" readonly />
|
|
9
|
+
<p>当前选中的位置: {{ mapValue2 }}</p>
|
|
10
|
+
</div>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script setup lang="ts">
|
|
14
|
+
import { ref } from 'vue'
|
|
15
|
+
|
|
16
|
+
const mapValue1 = ref('北京市东城区,116.4041750886573,39.909279981306405')
|
|
17
|
+
const mapValue2 = ref('北京市东城区,116.4041750886573,39.909279981306405')
|
|
18
|
+
</script>
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="hpanel-demo">
|
|
3
|
+
<div class="demo-item">
|
|
4
|
+
<p>基础用法</p>
|
|
5
|
+
<j-vpanel class="custom-panel">
|
|
6
|
+
<template #top>
|
|
7
|
+
<div class="top-content">Top Slot</div>
|
|
8
|
+
</template>
|
|
9
|
+
<div class="main-content">Default Slot (Main Content)</div>
|
|
10
|
+
<template #bottom>
|
|
11
|
+
<div class="bottom-content">Bottom Slot</div>
|
|
12
|
+
</template>
|
|
13
|
+
</j-vpanel>
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
<div class="demo-item">
|
|
17
|
+
<p>仅顶部和内容</p>
|
|
18
|
+
<j-vpanel class="custom-panel">
|
|
19
|
+
<template #top>
|
|
20
|
+
<div class="top-content">Top Slot</div>
|
|
21
|
+
</template>
|
|
22
|
+
<div class="main-content">Main Content</div>
|
|
23
|
+
</j-vpanel>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<div class="demo-item">
|
|
27
|
+
<p>仅内容和底部</p>
|
|
28
|
+
<j-vpanel class="custom-panel">
|
|
29
|
+
<div class="main-content">Main Content</div>
|
|
30
|
+
<template #bottom>
|
|
31
|
+
<div class="bottom-content">Bottom Slot</div>
|
|
32
|
+
</template>
|
|
33
|
+
</j-vpanel>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
</template>
|
|
37
|
+
|
|
38
|
+
<script setup lang="ts">
|
|
39
|
+
// 示例代码无需额外逻辑
|
|
40
|
+
</script>
|
|
41
|
+
|
|
42
|
+
<style scoped>
|
|
43
|
+
.hpanel-demo {
|
|
44
|
+
display: flex;
|
|
45
|
+
flex-direction: column;
|
|
46
|
+
gap: 24px;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.demo-item p {
|
|
50
|
+
margin: 0 0 12px;
|
|
51
|
+
font-size: 14px;
|
|
52
|
+
color: var(--j-color-text-2);
|
|
53
|
+
font-weight: 500;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.custom-panel {
|
|
57
|
+
border: 1px solid var(--j-color-border);
|
|
58
|
+
border-radius: 4px;
|
|
59
|
+
overflow: hidden;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.top-content {
|
|
63
|
+
background-color: #e0f7fa; /* Light cyan */
|
|
64
|
+
padding: 12px 20px;
|
|
65
|
+
display: flex;
|
|
66
|
+
align-items: center;
|
|
67
|
+
justify-content: center;
|
|
68
|
+
min-width: 100px;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.main-content {
|
|
72
|
+
background-color: #f0f4c3; /* Light lime */
|
|
73
|
+
padding: 12px 20px;
|
|
74
|
+
height: 200px;
|
|
75
|
+
display: flex;
|
|
76
|
+
align-items: center;
|
|
77
|
+
justify-content: center;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.bottom-content {
|
|
81
|
+
background-color: #ffecb3; /* Light amber */
|
|
82
|
+
padding: 12px 20px;
|
|
83
|
+
display: flex;
|
|
84
|
+
align-items: center;
|
|
85
|
+
justify-content: center;
|
|
86
|
+
min-width: 100px;
|
|
87
|
+
}
|
|
88
|
+
</style>
|