web-component-gallery 0.1.5 → 0.1.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "web-component-gallery",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "vue-library-ui组件库",
5
5
  "main": "dist/index.umd.js",
6
6
  "files": [
@@ -7,7 +7,7 @@ import { Button, Upload, Popconfirm } from 'ant-design-vue'
7
7
  let UploadUrl = `${global.WEBSWG}${global.BASEURL}`
8
8
 
9
9
  export default {
10
- name: "Button",
10
+ name: "Button",
11
11
  data() {
12
12
  return {
13
13
  PopconfirmProps: {
@@ -0,0 +1,7 @@
1
+ import Button from './Button'
2
+
3
+ Button.install = function (Vue) {
4
+ Vue.component(Button.name, Button)
5
+ }
6
+
7
+ export default Button
@@ -0,0 +1,185 @@
1
+ import { h } from 'vue'
2
+ import { FormModel } from 'ant-design-vue'
3
+
4
+ import RenderComp from './RenderComp.vue'
5
+
6
+ const FormModelItem = FormModel.Item
7
+
8
+ export default {
9
+ name: 'Model',
10
+ data() {
11
+ return {
12
+ formRules: {},
13
+ labelCol: { span: 4 },
14
+ wrapperCol: { span: 20 }
15
+ }
16
+ },
17
+ props: {
18
+ value: {
19
+ type: Object,
20
+ default: () => ({})
21
+ },
22
+ /* Form布局方式 */
23
+ layout: {
24
+ type: String,
25
+ default: 'vertical'
26
+ },
27
+ /* 一行显示几个 PS:最多4个 */
28
+ layoutSize: {
29
+ type: Number,
30
+ default: 4,
31
+ validator: value => {
32
+ return value <= 4
33
+ }
34
+ },
35
+ /* 表单项配置 */
36
+ formSetting: Array
37
+ },
38
+ computed: {
39
+ form: {
40
+ get() {
41
+ for (const k in this.value) {
42
+ Object.hasOwnProperty.call(this.formRules, k) && this.$refs.FormModel.validateField(k)
43
+ }
44
+ return this.value
45
+ },
46
+ set(value) {
47
+ this.$emit('change', value)
48
+ }
49
+ },
50
+ formAttrs() {
51
+ let attr = {}
52
+ this.layout === 'vertical'
53
+ ? (attr = {
54
+ ...this.$attrs
55
+ })
56
+ : (attr = {
57
+ labelCol: this.labelCol,
58
+ wrapperCol: this.wrapperCol,
59
+ ...this.$attrs
60
+ })
61
+ return attr
62
+ }
63
+ },
64
+ watch: {
65
+ formSetting() {
66
+ this.setFormRules()
67
+ }
68
+ },
69
+ mounted() {
70
+ this.setFormRules()
71
+ this.$emit('update:refForm', this.$refs.FormModel)
72
+ },
73
+ methods: {
74
+ getFormWidth(child, layoutSize) {
75
+ if (!layoutSize) return `margin-right:24px;`
76
+ if (this.layout === 'vertical')
77
+ return `flex: 0 1 calc((${(100 / layoutSize) * (child.size ?? 1)}% - 24px));margin-right:24px;`
78
+ return `flex: 0 1 ${(100 / layoutSize) * (child.size ?? 1)}%;`
79
+ },
80
+ setFormModelItem(child) {
81
+ const { getFormWidth, layout, layoutSize } = this
82
+ return (
83
+ <FormModelItem
84
+ prop={child.model}
85
+ label={child.label}
86
+ colon={!(layout == 'inline')}
87
+ style={getFormWidth(child, layoutSize)}
88
+ class={[
89
+ { FormLineVertical: child.size === layoutSize && layout === 'vertical' },
90
+ { FormLine: child.size === layoutSize }
91
+ ]}
92
+ >
93
+ {this.$scopedSlots[child.model] ? (
94
+ this.$scopedSlots[child.model](child)
95
+ ) : (
96
+ <RenderComp
97
+ v-model={this.form[child.model]}
98
+ component={child.is}
99
+ {...{ on: child.event, attrs: child.attrs }}
100
+ />
101
+ )}
102
+
103
+ {this.$scopedSlots[`${child.model}Handle`] && this.$scopedSlots[`${child.model}Handle`](child)}
104
+
105
+ {/* { h(
106
+ defaultComponents[child.is] ?? Input,
107
+ {
108
+ attrs: {
109
+ // placeholder: getPlaceholder(child),
110
+ ...child.attrs
111
+ },
112
+ props: {
113
+ value: this.form[child.model],
114
+ ...child.attrs
115
+ },
116
+ on: {
117
+ ...child.event,
118
+ 'input': (node) => {
119
+ this.$set( this.form, child.model, node.target?.value ?? node )
120
+ }
121
+ }
122
+ }
123
+ ) } */}
124
+ </FormModelItem>
125
+ )
126
+ },
127
+ setFormRules() {
128
+ const rules = {}
129
+ this.formSetting.forEach(node => {
130
+ node.filed
131
+ ? node.filed.forEach(child => this.$set(rules, child.model, this.setAttrs({ ...node, ...child })))
132
+ : this.$set(rules, node.model, this.setAttrs(node))
133
+ })
134
+ this.formRules = rules
135
+ },
136
+ setAttrs(node) {
137
+ const required = node.hasOwnProperty('required')
138
+ ? node.required
139
+ : node.hasOwnProperty('hidden')
140
+ ? !node.hidden
141
+ : true
142
+ const message =
143
+ node.placeholder ||
144
+ (/(select|picker|radio|upload)/.test((node.is ?? 'Input').toLowerCase()) ? '请选择' : '请输入') +
145
+ (node.label || '')
146
+
147
+ const rules = [
148
+ {
149
+ required,
150
+ message,
151
+ trigger: ['change', 'blur']
152
+ }
153
+ ].concat((node.rules || []).filter(i => i.pattern && (i.pattern = new RegExp(i.pattern))))
154
+
155
+ return rules
156
+ },
157
+ formSubmit() {
158
+ return this.$refs.FormModel.validate()
159
+ }
160
+ },
161
+ render() {
162
+ const { setFormModelItem, layout, formSetting, formRules, formAttrs, form } = this
163
+
164
+ return (
165
+ <FormModel
166
+ ref="FormModel"
167
+ props={{
168
+ model: form,
169
+ rules: formRules,
170
+ layout,
171
+ ...formAttrs
172
+ }}
173
+ >
174
+ {formSetting.map((props, i) => {
175
+ return (
176
+ <div>
177
+ {!props.hidden && setFormModelItem(props)}
178
+ {this.$scopedSlots[`operate${i}`] && this.$scopedSlots[`operate${i}`](props)}
179
+ </div>
180
+ )
181
+ })}
182
+ </FormModel>
183
+ )
184
+ }
185
+ }
@@ -0,0 +1,52 @@
1
+ <template>
2
+ <component :is="component" v-model="nodeValue" v-bind="$attrs" v-on="$listeners" :placeholder='getPlaceholder()' />
3
+ </template>
4
+ <script>
5
+
6
+ import { Input,InputNumber,Checkbox,DatePicker,TimePicker } from 'ant-design-vue'
7
+
8
+ export default {
9
+ name: 'RenderComp',
10
+ model: {
11
+ prop: "value",
12
+ event: "Update:FormModel"
13
+ },
14
+ components: {
15
+ Input,
16
+ InputNumber,
17
+ Checkbox,
18
+ DatePicker,
19
+ TimePicker,
20
+ ARadio: () => import('./components/ARadio.vue'),
21
+ AUpload: () => import( './components/AUpload.vue' ),
22
+ ATagsInput: () => import('./components/ATagsInput.vue'),
23
+ ASelectCustom: () => import('./components/ASelectCustom.vue')
24
+ },
25
+ props: {
26
+ value: [Number, String, Object, Array, Boolean],
27
+ component: {
28
+ type: String,
29
+ default: 'Input'
30
+ }
31
+ },
32
+ computed: {
33
+ nodeValue: {
34
+ get () {
35
+ return this.value
36
+ },
37
+ set ( value ) {
38
+ this.$emit('Update:FormModel', value)
39
+ }
40
+ }
41
+ },
42
+ mounted() {
43
+ },
44
+ methods: {
45
+ getPlaceholder() {
46
+ const RegExp = this.component.toLowerCase()
47
+ if( /range/.test( RegExp ) ) return [ '开始时间', '结束时间' ]
48
+ return this.$attrs.placeholder ?? /(select|picker|radio|upload)/.test( RegExp ) ? "请选择" : "请输入"
49
+ }
50
+ }
51
+ }
52
+ </script>
@@ -0,0 +1,169 @@
1
+ <template>
2
+ <FormModel :model="form" ref="searchForm" layout="inline" @submit="handleSearch" class="WebComponentFormSearch">
3
+
4
+ <template v-for="(node, i) in copyFormSetting.slice(0, count)">
5
+ <FormModelItem
6
+ :key="i"
7
+ :prop="node.model"
8
+ :label="node.label"
9
+ :style="getFormWidth(node, matchMediaSize)"
10
+ v-if="!node.hidden"
11
+ >
12
+ <component
13
+ :is="node.is || 'Input'"
14
+ :placeholder="node.is | defaultPlaceholder"
15
+ :getPopupContainer="
16
+ triggerNode => {
17
+ return triggerNode.parentNode || document.body
18
+ }
19
+ "
20
+ v-on="node.event"
21
+ v-bind="node.attrs"
22
+ v-model="form[node.model]"
23
+ />
24
+ </FormModelItem>
25
+ </template>
26
+
27
+ <div class="WebComponentFormSearch__Actions">
28
+ <Button type="primary" html-type="submit">{{ actionsText.primary }}</Button>
29
+ <Button :style="{ marginLeft: '8px' }" @click="handleReset">{{ actionsText.cancel }}</Button>
30
+ <a @click="advanced = !advanced" style="margin-left: 8px" v-if="copyFormSetting.length > this.matchMediaSize - 1">
31
+ {{ advanced ? '收起' : '展开' }}
32
+ <Icon :type="advanced ? 'up' : 'down'" />
33
+ </a>
34
+ </div>
35
+ </FormModel>
36
+ </template>
37
+ <script>
38
+
39
+ import { FormModel, Button, Radio, Input, InputNumber, Checkbox, DatePicker, TimePicker, Icon } from 'ant-design-vue'
40
+
41
+ export default {
42
+ components: {
43
+ FormModel,
44
+ FormModelItem: FormModel.Item,
45
+ Button,
46
+ Radio,
47
+ Input,
48
+ InputNumber,
49
+ Checkbox,
50
+ DatePicker,
51
+ TimePicker,
52
+ ASelectCustom: () => import('./components/ASelectCustom.vue'),
53
+ Icon
54
+ },
55
+ data() {
56
+ return {
57
+ // 是否收起
58
+ advanced: false,
59
+ matchMediaSize: 0
60
+ }
61
+ },
62
+ model: {
63
+ prop: 'value',
64
+ event: 'change'
65
+ },
66
+ props: {
67
+ /* 双向数据绑定Form */
68
+ value: {
69
+ type: Object,
70
+ default: () => ({})
71
+ },
72
+ /* 配置表单项 */
73
+ formSetting: {
74
+ type: Array,
75
+ default: () => []
76
+ },
77
+ /* 一行显示多少项 */
78
+ layoutSize: {
79
+ type: Number,
80
+ default: 4,
81
+ validator: value => {
82
+ return value <= 4
83
+ }
84
+ },
85
+ // 紧凑型和宽松型
86
+ // default 宽松型
87
+ // middle 紧凑型
88
+ searchStyle: {
89
+ type: String,
90
+ default: 'default'
91
+ },
92
+ /* 操作显示文字 */
93
+ actionsText: {
94
+ type: Object,
95
+ default: () => ({
96
+ primary: '搜索',
97
+ cancel: '重置'
98
+ })
99
+ }
100
+ },
101
+ computed: {
102
+ form: {
103
+ get() {
104
+ return this.value
105
+ },
106
+ set(newValue) {
107
+ this.$emit('change', newValue)
108
+ }
109
+ },
110
+ matchMedia() {
111
+ return {
112
+ '(max-width: 576px)': 1,
113
+ '(min-width: 576px) and (max-width: 992px)': this.layoutSize - 2,
114
+ '(min-width: 992px)': this.layoutSize
115
+ }
116
+ },
117
+ copyFormSetting() {
118
+ return this.formSetting.filter(node => !node.hidden)
119
+ },
120
+ count() {
121
+ return this.advanced ? this.copyFormSetting.length : this.matchMediaSize - 1
122
+ }
123
+ },
124
+ filters: {
125
+ defaultPlaceholder(is) {
126
+ if (is && is.includes('range')) return ['开始时间', '结束时间']
127
+ return /(select|picker|radio|upload)/.test(is) ? '请选择' : '请输入'
128
+ }
129
+ },
130
+ mounted() {
131
+ this.handleSearch()
132
+ this.matchMediaSize = this.layoutSize
133
+ Object.keys(this.matchMedia).forEach(media =>
134
+ window.matchMedia(media).addEventListener('change', this.handleResize)
135
+ )
136
+ },
137
+ methods: {
138
+ handleResize(x) {
139
+ x.matches && (this.matchMediaSize = this.matchMedia[x.media])
140
+ },
141
+ getFormWidth(e) {
142
+ const gap = {
143
+ middle: '16px',
144
+ default: '24px'
145
+ }
146
+ return `flex: 0 1 calc((${(100 / this.matchMediaSize) * (e.size ?? 1)}% - ${
147
+ gap[this.searchStyle]
148
+ })); margin-right: ${gap[this.searchStyle]};`
149
+ },
150
+ handleSearch(e) {
151
+ e && e.preventDefault()
152
+ const searchForm = {}
153
+ // 排除掉form当中hidden的隐藏项
154
+ this.copyFormSetting.forEach(node =>
155
+ this.$set( searchForm, node.model, this.form[node.model] ))
156
+ this.form = { ...searchForm }
157
+ this.$emit('handleSearch', searchForm)
158
+ },
159
+ handleReset() {
160
+ // 初步猜测是因这里的清空导致数据双向绑定得不到最新
161
+ this.$refs.searchForm.resetFields()
162
+ this.$emit('handleReset')
163
+ }
164
+ }
165
+ }
166
+ </script>
167
+ <style lang="less" scoped>
168
+ @import url('../../less/Search.less');
169
+ </style>