widget.qw 1.0.92 → 1.0.96

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,7 +1,7 @@
1
1
  {
2
2
  "name": "widget.qw",
3
3
  "private": false,
4
- "version": "1.0.92",
4
+ "version": "1.0.96",
5
5
  "description": "marqstree Vue3组件库",
6
6
  "main": "build/widget.qw.es.js",
7
7
  "keywords": [
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <van-field v-if="!isGone" name="image" :label="props.label" :required="isRequired" :rules="rules"
2
+ <van-field v-if="!isGone" name="image" :label="props.label" :required="isRequired" :rules="rules" :modelValue="modelValue"
3
3
  label-class="label" :placeholder="props.placeholder">
4
4
  <template #input>
5
5
  <div class="file-box">
@@ -1,17 +1,32 @@
1
1
  <template>
2
- <van-field
3
- :label="props.label"
4
- v-model.number="modelValue"
5
- v-if="!isGone && props.type === 'number'"
2
+ <!-- 数字类型 -->
3
+ <van-field :label="props.label" v-model.number="modelValue" v-if="!isGone && props.type === 'number'"
6
4
  :disabled="isDisabled" :required="isRequired" :placeholder="props.placeholder" :type="props.type"
7
- :rows="props.rows" :autosize="props.autosize" :rules="rules" />
5
+ :rows="props.rows" :autosize="props.autosize" :rules="rules">
6
+ <!-- 右侧插槽按钮 -->
7
+ <template #button>
8
+ <van-button size="small" @click="onCalc">
9
+ +
10
+ </van-button>
11
+ </template>
12
+ </van-field>
13
+ <van-popup v-model:show="data.isShowPop" position="bottom" round>
14
+ <van-field v-model="data.express" placeholder="请输入+/-数字" type="text">
15
+ <template #button>
16
+ <van-button size="small" @click="onSubmit">
17
+ 确定
18
+ </van-button>
19
+ </template>
20
+ </van-field>
21
+ </van-popup>
22
+ <!-- 文本类型 -->
8
23
  <van-field :label="props.label" v-model="modelValue" v-if="!isGone && props.type != 'number'" :disabled="isDisabled"
9
24
  :required="isRequired" :placeholder="props.placeholder" :type="props.type" :rows="props.rows"
10
25
  :autosize="props.autosize" :rules="rules" />
11
26
  </template>
12
27
 
13
28
  <script setup>
14
- import { ref, computed, onMounted, defineProps, defineEmits, watch } from "vue"
29
+ import { ref, computed, onMounted, defineProps, defineEmits, watch, reactive } from "vue"
15
30
  import { useVModel } from '@vueuse/core'
16
31
  import util from '../util'
17
32
 
@@ -65,6 +80,29 @@ const props = defineProps({
65
80
  const emit = defineEmits(['update:modelValue'])
66
81
  const modelValue = useVModel(props, 'modelValue', emit)
67
82
  const { isRequired, isReadonly, isGone, isDisabled, rules } = util.props2auth(props)
83
+ const data = reactive({
84
+ isShowPop: false,
85
+ express: ''
86
+ })
87
+
88
+ const onCalc = () => {
89
+ data.isShowPop = true
90
+ data.express = '+'
91
+ }
92
+
93
+ const onSubmit = () => {
94
+ // 简单校验只允许数字 +- .
95
+ if (!/^[\d\.+-]+$/.test(data.express)) {
96
+ throw new Error("非法表达式");
97
+ }
98
+
99
+ let fullExpress = modelValue.value+''+data.express
100
+
101
+ modelValue.value = eval(fullExpress)
102
+
103
+ data.isShowPop = false
104
+ data.express = ''
105
+ }
68
106
 
69
107
  onMounted(() => {
70
108
  })
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <van-field v-if="!isGone" :label="props.label" :required="isRequired" :rules="rules" :disabled="isDisabled"
2
+ <van-field v-if="!isGone" :label="props.label" :required="isRequired" :rules="rules" :disabled="isDisabled" :modelValue="modelValue"
3
3
  :placeholder="props.placeholder" :is-link="isReadonly ? false : true" @click="data.isShowPop = !isReadonly"
4
4
  label-class="label">
5
5
  <template #input v-if="selectOptions.length>0">
@@ -1,9 +1,10 @@
1
1
  <template>
2
2
  <van-field :label="props.label" v-if="!isGone" :disabled="isDisabled" :required="isRequired"
3
- :placeholder="props.placeholder" :rules="rules">
3
+ :modelValue="modelValue" :placeholder="props.placeholder" :rules="rules">
4
4
  <template #input>
5
5
  <div class="widget-box">
6
6
  <div class="option" v-for="(item, index) in modelValue" :key="index">
7
+ <!-- 浏览状态的元素,显示元素的值 -->
7
8
  <div v-if="index != data.selectIndex" style=" display: flex;align-items: center;">
8
9
  <van-icon name="arrow-left" @click.stop="onForward(index)" />
9
10
  <div style="padding: 5px 5px;">
@@ -30,21 +31,25 @@
30
31
  </div>
31
32
  </div>
32
33
 
34
+ <!-- 编辑状态的元素,显示编辑输入框 -->
33
35
  <van-form v-if="data.isShowInput && index == data.selectIndex" :model="data.inputValue">
36
+ <!-- 列出schema中定义的字段的输入框 -->
34
37
  <van-field v-for="(key, i) in keys" :key="i" :label="props.schema[key].label"
35
38
  v-show="props.schema[key].auth != 'gone'" :required="props.schema[key].auth === 'required'"
36
39
  :disabled="props.schema[key].auth === 'readonly'">
37
40
 
38
41
  <template #input>
39
- <van-field
40
- v-if="props.schema[key].type == 'String' && !props.schema[key]?.schema?.options"
41
- :disabled="props.schema[key].auth === 'readonly'" v-model="data.inputValue[key]"
42
- :placeholder="`请输入${key2name(key)}`" type="text" />
43
-
44
- <van-field
45
- v-if="props.schema[key].type == 'Number' && !props.schema[key]?.schema?.options"
46
- :disabled="props.schema[key].auth === 'readonly'"
47
- v-model.number="data.inputValue[key]" :placeholder="`请输入${key2name(key)}`"
42
+ <!-- 根据字段的类型,显示对应的输入框 -->
43
+ <Input v-if="props.schema[key].type == 'String' && !props.schema[key]?.schema?.options"
44
+ :auth="props.schema[key].auth"
45
+ v-model="data.inputValue[key]"
46
+ :placeholder="`请输入${key2name(key)}`"
47
+ type="text" />
48
+
49
+ <Input v-if="props.schema[key].type == 'Number' && !props.schema[key]?.schema?.options"
50
+ :auth="props.schema[key].auth"
51
+ v-model.number="data.inputValue[key]"
52
+ :placeholder="`请输入${key2name(key)}`"
48
53
  type="number" />
49
54
 
50
55
  <van-switch v-if="props.schema[key].type == 'Boolean'"
@@ -90,6 +95,7 @@ import util from '@/util'
90
95
  import DatetimePicker from './DatetimePicker.vue'
91
96
  import DateSelector from './data_selector.vue'
92
97
  import ImagesPicker from './images_picker.vue'
98
+ import Input from './Input.vue'
93
99
 
94
100
  const props = defineProps({
95
101
  modelValue: {
@@ -119,16 +125,19 @@ const props = defineProps({
119
125
  schema: {
120
126
  type: Object,
121
127
  default: {
122
- type: "String",
123
- label: '名称',
124
- default: '',
125
- //权限取值范围: required 必填 option 选填 readonly 只读 gone 隐藏
126
- auth: 'option'
128
+ title: {
129
+ type: "String",
130
+ label: '标题',
131
+ default: '',
132
+ //权限取值范围: required 必填 option 选填 readonly 只读 gone 隐藏
133
+ auth: 'option',
134
+ submit: null
135
+ }
127
136
  }
128
137
  }
129
138
  })
130
139
 
131
- const emit = defineEmits(['update:modelValue'])
140
+ const emit = defineEmits(['update:modelValue','submitItem'])
132
141
  const modelValue = useVModel(props, 'modelValue', emit)
133
142
  const { isRequired, isReadonly, isGone, isDisabled, rules } = util.props2auth(props)
134
143
 
@@ -138,7 +147,9 @@ const data = reactive({
138
147
  selectIndex: -1,
139
148
  oldModelValue: []
140
149
  })
141
- const keys = Object.keys(props.schema)
150
+
151
+ //过滤掉提交添加/修改/删除的元素回调函数
152
+ const keys = Object.keys(props.schema).filter(k=> k != 'submitItem' && k!='deleteItem')
142
153
  const visiableKeys = keys.filter(k => props.schema[k].auth != 'gone')
143
154
 
144
155
  watch(() => JSON.stringify(modelValue.value), (n, o) => {
@@ -179,6 +190,11 @@ const onBack = (index) => {
179
190
 
180
191
  const onDelete = (index) => {
181
192
  modelValue.value.splice(index, 1)
193
+
194
+ //执行删除数组元素回调
195
+ if(props.schema.deleteItem){
196
+ props.schema.deleteItem(index)
197
+ }
182
198
  }
183
199
 
184
200
  const key2name = (key) => {
@@ -249,7 +265,7 @@ const onNewOption = () => {
249
265
  })
250
266
  }
251
267
 
252
- const onInputConfirm = () => {
268
+ const onInputConfirm = (selectIndex, key, label) => {
253
269
  let idx = modelValue.value.indexOf(item => JSON.stringify(item) === JSON.stringify(data.inputValue))
254
270
  if (idx > -1 && idx != data.selectIndex) {
255
271
  util.warnToast('重复添加')
@@ -264,8 +280,22 @@ const onInputConfirm = () => {
264
280
  return
265
281
  }
266
282
 
283
+ //更新v-model的值
267
284
  modelValue.value[data.selectIndex] = data.inputValue
268
285
 
286
+ //执行每个输入框值提交回调
287
+ keys.forEach(key => {
288
+ if (props.schema[key].submitValue) {
289
+ props.schema[key].submitValue(data.inputValue[key])
290
+ }
291
+ })
292
+
293
+ //执行每个数组元素提交回调
294
+ if(props.schema.submitItem){
295
+ props.schema.submitItem(data.inputValue)
296
+ }
297
+
298
+ //输入框恢复到默认值
269
299
  data.isShowInput = false
270
300
  data.inputValue = makeDefaultValue()
271
301
  data.selectIndex = -1
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <van-field :label="props.label" v-if="!isGone" :disabled="isDisabled" :required="isRequired" :rules="rules"
2
+ <van-field :label="props.label" v-if="!isGone" :disabled="isDisabled" :required="isRequired" :rules="rules" :modelValue="modelValue"
3
3
  :placeholder="props.placeholder">
4
4
 
5
5
  <template #input>
@@ -1,12 +1,8 @@
1
1
  <template>
2
2
  <div class="widget">
3
- <van-field v-if="!isGone" v-model="formatLabel"
4
- :is-link="!isReadonly && !isDisabled"
5
- :label="props.label"
6
- :placeholder="props.placeholder"
7
- :rules="rules"
8
- readonly
9
- :required="isRequired" :disabled="isDisabled" @click="onShow" />
3
+ <van-field v-if="!isGone" v-model="formatLabel" :is-link="!isReadonly && !isDisabled" :label="props.label"
4
+ :placeholder="props.placeholder" :rules="rules" readonly :required="isRequired" :disabled="isDisabled"
5
+ @click="onShow" />
10
6
  <van-popup v-model:show="data.isShow" destroy-on-close round position="bottom">
11
7
  <van-picker :columns="props.options" @cancel="onCancel" @confirm="onConfirm" />
12
8
  </van-popup>
@@ -19,6 +15,10 @@ import util from '../util'
19
15
  import { useVModel } from '@vueuse/core'
20
16
 
21
17
  const props = defineProps({
18
+ modelValue: {
19
+ type: String,
20
+ default: null
21
+ },
22
22
  label: {
23
23
  type: String,
24
24
  default: ''
@@ -40,7 +40,7 @@ const props = defineProps({
40
40
  default: "",
41
41
  },
42
42
  options: {
43
- type:Array,
43
+ type: Array,
44
44
  default: []
45
45
  }
46
46
  })
@@ -59,8 +59,8 @@ const formatLabel = computed(() => {
59
59
  onMounted(() => {
60
60
  })
61
61
 
62
- const onShow=()=>{
63
- if(isReadonly.value || isDisabled.value || isGone.value)
62
+ const onShow = () => {
63
+ if (isReadonly.value || isDisabled.value || isGone.value)
64
64
  return
65
65
 
66
66
  data.isShow = true
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <van-field v-if="!isGone"
3
- :label="props.label" :required="isRequired" :rules="rules" :disabled="isDisabled"
3
+ :label="props.label" :required="isRequired" :rules="rules" :disabled="isDisabled" :modelValue="modelValue"
4
4
  :placeholder="props.placeholder" :is-link="isReadonly ? false : true" @click="data.isShowPop = !isReadonly"
5
5
  label-class="label">
6
6
  <template #input>
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <van-field v-if="!isGone" :label="props.label" :required="isRequired" :rules="rules" :disabled="isDisabled"
3
3
  :placeholder="props.placeholder" :is-link="isReadonly ? false : true" @click="data.isShowPop = !isReadonly"
4
- label-class="label">
4
+ label-class="label" :modelValue="modelValue">
5
5
  <template #input>
6
6
  <van-tag class="user" v-if="modelValue" :closeable="!isDisabled" type="primary" plain
7
7
  @close.stop="onDelete">
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <van-field v-if="!isGone"
3
- :label="props.label" :required="isRequired" :rules="rules" :disabled="isDisabled"
3
+ :label="props.label" :required="isRequired" :rules="rules" :disabled="isDisabled" :modelValue="modelValue"
4
4
  :placeholder="props.placeholder" :is-link="isReadonly ? false : true" @click="data.isShowPop = !isReadonly"
5
5
  label-class="label">
6
6
  <template #input>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <van-field v-if="!isGone" name="image" :label="props.label" :required="isRequired" :rules="rules"
2
+ <van-field v-if="!isGone" name="image" :label="props.label" :required="isRequired" :rules="rules" :modelValue="modelValue"
3
3
  label-class="label" :placeholder="props.placeholder">
4
4
  <template #input>
5
5
  <div class="image-box">
@@ -4,7 +4,8 @@
4
4
  :required="isRequired"
5
5
  :rules="rules"
6
6
  label-class="label"
7
- :placeholder="props.placeholder">
7
+ :placeholder="props.placeholder"
8
+ :modelValue="modelValue">
8
9
  <template #input>
9
10
  <div class="image-box">
10
11
  <van-uploader v-if="props.capture && (!isReadonly && !isDisabled)" v-model="files" multiple
@@ -9,91 +9,130 @@ import { onMounted, reactive, watch } from "vue";
9
9
 
10
10
  const data = reactive({
11
11
  schema: {
12
+ // name: {
13
+ // label: '房型',
14
+ // type: 'String',
15
+ // default: '',
16
+ // auth: 'required',
17
+ // schema: {
18
+ // options: [
19
+ // {
20
+ // label: "a",
21
+ // value: "a",
22
+ // materials: [
23
+ // {
24
+ // materialId: "jiFdBeVT",
25
+ // quantity: 1,
26
+ // },
27
+ // {
28
+ // materialId: "v6tjBw4R",
29
+ // quantity: 2,
30
+ // }
31
+ // ]
32
+ // },
33
+ // {
34
+ // label: "b",
35
+ // value: "b",
36
+ // materials: [
37
+ // {
38
+ // materialId: "jiFdBeVT",
39
+ // quantity: 1,
40
+ // },
41
+ // {
42
+ // materialId: "v6tjBw4R",
43
+ // quantity: 2,
44
+ // }
45
+ // ]
46
+ // }
47
+ // ]
48
+ // }
49
+ // },
50
+ // quantity: {
51
+ // label: '金额',
52
+ // type: 'Number',
53
+ // default: 0,
54
+ // auth: 'required',
55
+ // },
56
+ // images: {
57
+ // label: '图片',
58
+ // type: 'Images',
59
+ // default: [],
60
+ // auth: 'required',
61
+ // },
12
62
  name: {
13
- label: '房型',
63
+ label: '名称',
14
64
  type: 'String',
15
65
  default: '',
16
66
  auth: 'required',
17
- schema: {
18
- options: [
19
- {
20
- label: "a",
21
- value: "a",
22
- materials: [
23
- {
24
- materialId: "jiFdBeVT",
25
- quantity: 1,
26
- },
27
- {
28
- materialId: "v6tjBw4R",
29
- quantity: 2,
30
- }
31
- ]
32
- },
33
- {
34
- label: "b",
35
- value: "b",
36
- materials: [
37
- {
38
- materialId: "jiFdBeVT",
39
- quantity: 1,
40
- },
41
- {
42
- materialId: "v6tjBw4R",
43
- quantity: 2,
44
- }
45
- ]
46
- }
47
- ]
48
- }
49
- },
50
- quantity: {
51
- label: '数量',
52
- type: 'Number',
53
- default: 1,
54
- auth: 'readonly',
55
- },
56
- images: {
57
- label: '图片',
58
- type: 'Images',
59
- default: [],
60
- auth: 'required',
61
67
  },
62
68
  materials: {
63
- label: '材料表',
64
- type: 'Array',
69
+ type: "Array",
70
+ label: "金额",
65
71
  default: [],
66
72
  auth: 'required',
67
73
  schema: {
68
- materialId: {
69
- label: '材料id',
74
+ title: {
75
+ label: '标题',
70
76
  type: 'String',
71
77
  default: '',
72
78
  auth: 'required',
73
- schema: {
74
- options: [
75
- {
76
- "name": "保温棉",
77
- "materialId": "jiFdBeVT",
78
- "specification": "6mm",
79
- "unit": "m"
80
- },
81
- {
82
- "name": "保温棉",
83
- "materialId": "v6tjBw4R",
84
- "specification": "8mm",
85
- "unit": "m"
86
- }]
87
- }
88
79
  },
89
- quantity: {
90
- label: '数量',
80
+ price: {
81
+ label: '金额(元)',
91
82
  type: 'Number',
92
83
  default: 0,
93
- auth: 'required'
84
+ auth: 'required',
85
+ submitValue: (value) => {
86
+ console.log('++++++submit value price')
87
+ console.log(value)
88
+ },
89
+ },
90
+ submitItem: (value) => {
91
+ console.log('++++++submit item materials')
92
+ console.log(value)
93
+ },
94
+ deleteItem: (index) => {
95
+ console.log('++++++delete item materials')
96
+ console.log(index)
94
97
  }
95
- }
96
- },
98
+ },
99
+ }
100
+
101
+ // materials: {
102
+ // label: '材料表',
103
+ // type: 'Array',
104
+ // default: [],
105
+ // auth: 'required',
106
+ // schema: {
107
+ // materialId: {
108
+ // label: '材料id',
109
+ // type: 'String',
110
+ // default: '',
111
+ // auth: 'required',
112
+ // schema: {
113
+ // options: [
114
+ // {
115
+ // "name": "保温棉",
116
+ // "materialId": "jiFdBeVT",
117
+ // "specification": "6mm",
118
+ // "unit": "m"
119
+ // },
120
+ // {
121
+ // "name": "保温棉",
122
+ // "materialId": "v6tjBw4R",
123
+ // "specification": "8mm",
124
+ // "unit": "m"
125
+ // }]
126
+ // }
127
+ // },
128
+ // quantity: {
129
+ // label: '数量',
130
+ // type: 'Number',
131
+ // default: 0,
132
+ // auth: 'required'
133
+ // }
134
+ // }
135
+ // },
97
136
  },
98
137
  // schema: {
99
138
  // id:{
@@ -256,6 +295,11 @@ const data = reactive({
256
295
  datas: null,
257
296
  })
258
297
 
298
+ const onSubmit = (params) => {
299
+ console.log('+++onSubmit+++++++')
300
+ console.log(params)
301
+ }
302
+
259
303
  watch(() => data.datas, (n, o) => {
260
304
  console.log('>>>>', n)
261
305
  }, {