byt-ui 0.0.20 → 0.1.1

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": "byt-ui",
3
- "version": "0.0.20",
3
+ "version": "0.1.1",
4
4
  "private": false,
5
5
  "description": "byt组件库",
6
6
  "author": {
@@ -35,7 +35,7 @@
35
35
  "babel-preset-env": "^1.7.0",
36
36
  "eslint": "^7.32.0",
37
37
  "eslint-plugin-vue": "^8.0.3",
38
- "node-sass": "4.14.1",
38
+ "sass": "^1.69.5",
39
39
  "sass-loader": "10.0.4",
40
40
  "vue-cli-plugin-styleguidist": "~4.45.1",
41
41
  "vue-template-compiler": "^2.6.14"
@@ -68,6 +68,6 @@
68
68
  "license": "MIT",
69
69
  "publishConfig": {
70
70
  "access": "public",
71
- "registry": "https://registry.npmjs.org/"
71
+ "registry": "https://registry.npmjs.com/"
72
72
  }
73
73
  }
@@ -2,7 +2,7 @@
2
2
  * @Description:
3
3
  * @Author: 王国火
4
4
  * @Date: 2022-07-12 17:47:20
5
- * @LastEditTime: 2023-09-14 12:24:33
5
+ * @LastEditTime: 2024-03-04 15:16:54
6
6
  * @LastEditors: hcm
7
7
  -->
8
8
 
@@ -67,6 +67,7 @@
67
67
  :width="column.width"
68
68
  :title="column.label"
69
69
  :align="column.align||'center'"
70
+ v-bind="column.prop"
70
71
  :key="index"
71
72
  >
72
73
  <template #default="scope">
@@ -94,13 +95,14 @@
94
95
  :width="column.width"
95
96
  :title="column.label"
96
97
  :align="column.align||'center'"
98
+ v-bind="column.prop"
97
99
  :key="index"
98
100
  ></vxe-column>
99
101
  </template>
100
102
 
101
103
  <template #empty>
102
104
  <el-empty description="暂无数据!">
103
- <el-button type="primary" @click="onSearch">重试</el-button>
105
+ <el-button v-if="emptyBtnShow" type="primary" @click="onSearch">重试</el-button>
104
106
  </el-empty>
105
107
  </template>
106
108
  </vxe-table>
@@ -157,11 +159,6 @@ export default {
157
159
  type: Boolean,
158
160
  default: true
159
161
  },
160
- // add by hcm 更灵活的修改vxe table组件属性
161
- vxeTableProp: {
162
- type: Object,
163
- default: null
164
- },
165
162
  /** 表格数据*/
166
163
  tableData: {
167
164
  type: Array,
@@ -170,8 +167,16 @@ export default {
170
167
  return []
171
168
  }
172
169
  },
170
+ vxeTableProp: { // vxeTableProp(会使用v-bind展开)
171
+ type: Object,
172
+ default: null
173
+ },
174
+ emptyBtnShow: {
175
+ type: Boolean,
176
+ default: true
177
+ },
173
178
  /** 表格列配置*/
174
- columns: {
179
+ columns: { // column.prop(会使用v-bind展开)
175
180
  type: Array,
176
181
  required: true,
177
182
  default() {
@@ -272,7 +277,6 @@ export default {
272
277
  onReset() {
273
278
  this.pageOpt.page = 1;
274
279
  this.searchForm = {};
275
- this.$emit('reset') // add by hcm filters插槽时用到
276
280
  this.fetchData();
277
281
  },
278
282
  clear(){
@@ -2,12 +2,12 @@
2
2
  * @Description:
3
3
  * @Author: 王国火
4
4
  * @Date: 2022-07-13 08:46:34
5
- * @LastEditTime: 2023-09-14 11:59:28
5
+ * @LastEditTime: 2023-10-16 10:21:19
6
6
  * @LastEditors: hcm
7
7
  -->
8
8
  <!-- -->
9
9
  <template>
10
- <el-form ref="form" :model="form" :inline="inline" :label-width="`${labelWidth}px`">
10
+ <el-form ref="form" :model="form" :inline="inline" :label-width="`${labelWidth}px`" @submit.native.prevent>
11
11
  <el-form-item :label="item.label" :key="index" v-for="(item,index) in searchList">
12
12
  <template v-if="item.type=='input' || !item.type">
13
13
  <!-- update by hcm 回车触发过滤 -->
@@ -75,10 +75,9 @@
75
75
  </el-date-picker>
76
76
  </template>
77
77
  </el-form-item>
78
- <el-form-item>
79
- <!-- add by hcm 加插槽 增加灵活性 -->
80
- <slot name="filters"></slot>
81
- </el-form-item>
78
+
79
+ <!-- add by hcm 加插槽 增加灵活性 -->
80
+ <slot name="filters"></slot>
82
81
  <el-form-item>
83
82
  <el-button icon="el-icon-search" type="primary" @click="onSearch">查询</el-button>
84
83
  <el-button icon="el-icon-refresh-right" @click="onReset">重置</el-button>
@@ -0,0 +1,348 @@
1
+ <!--
2
+ * @Author: hcm
3
+ * @Date: 2023-05-29 13:18:19
4
+ * @LastEditors: hcm
5
+ * @LastEditTime: 2024-04-10 17:09:38
6
+ * @Description: 消息推送选择目标组件
7
+ -->
8
+ <template>
9
+ <div :class="`mpt-box ${boxClass}`">
10
+ <div :class="`mpt-target ${targetClass}`">
11
+ <div v-if="currentValue && currentValue.length > 0" class="mpt-target-show" @click="handleClick">
12
+ <div v-for="(labelList, itemKey) in labelMap" :key="itemKey" class="mpt-tag-box">
13
+ <div class="mpt-tag-tip">{{ itemKey || '' }}</div>
14
+ <div class="mpt-tag-body">
15
+ <el-tag v-for="label in labelList" :key="label" class="mpt-tag" size="mini"> {{ label }}</el-tag>
16
+ </div>
17
+ </div>
18
+ </div>
19
+ <el-cascader
20
+ v-model="currentValue"
21
+ ref="mptCascader"
22
+ :class="`mpt-cascader ${!currentValue || currentValue.length === 0 ? 'mpt-block' : ''}`"
23
+ :options="optionList"
24
+ :props="props"
25
+ :clearable="clearable"
26
+ :filterable="filterable"
27
+ :multiple="multiple"
28
+ :disabled="disabled"
29
+ @change="change"
30
+ >
31
+ </el-cascader>
32
+ </div>
33
+ </div>
34
+ </template>
35
+
36
+ <script>
37
+ export default {
38
+ name: 'MessageOne',
39
+ props: {
40
+ // '10': '企业微信','20': '企业微信群','30': '企业微信群机器人','40': '短信','50': '邮件','60': '小程序','70': '公众号','80': 'app'
41
+ channelType: {
42
+ type: [String, Number],
43
+ default: null
44
+ },
45
+ channelTypeDisabled: { // channelType对应不能选择key数组
46
+ type: Object,
47
+ default: () => ({
48
+ '10': ['robot'],
49
+ '20': ['robot', 'user', 'dept', 'role'],
50
+ '30': ['user', 'dept', 'role'],
51
+ '40': ['robot'],
52
+ '50': ['robot'],
53
+ '60': ['robot'],
54
+ '70': ['robot'],
55
+ '80': ['robot']
56
+ })
57
+ },
58
+ optionKeyMap: { // 下拉数据源 keyMap
59
+ type: Object,
60
+ default: () => ({
61
+ 'user': '员工',
62
+ 'dept': '部门',
63
+ 'role': '角色',
64
+ 'robot': '机器人'
65
+ })
66
+ },
67
+ optionMap: { // 下拉数据源
68
+ type: Object,
69
+ default: null
70
+ },
71
+ value: { // 单选时,传入值,如'user$$111'
72
+ type: [String, Number],
73
+ default: null
74
+ },
75
+ valueList: { // 多选时,传入数组,如['user$$111', 'dept$$221']
76
+ type: Array,
77
+ default: null
78
+ },
79
+ multiple: { // 推送目标允许多选
80
+ type: Boolean,
81
+ default: true
82
+ },
83
+ boxClass: { // 自定义 大盒子class
84
+ type: String,
85
+ default: ''
86
+ },
87
+ targetClass: { // 自定义 目标选择class
88
+ type: String,
89
+ default: ''
90
+ },
91
+ typeClass: { // 自定义 推送类型选择class
92
+ type: String,
93
+ default: ''
94
+ },
95
+ clearable: { // 推送目标允许清空
96
+ type: Boolean,
97
+ default: true
98
+ },
99
+ filterable: { // 推送目标允许过滤
100
+ type: Boolean,
101
+ default: true
102
+ },
103
+ disabled: { // 禁止编辑
104
+ type: Boolean,
105
+ default: false
106
+ }
107
+ },
108
+ data() {
109
+ return {
110
+ currentValue: null,
111
+ // dataList: null
112
+ props: { multiple: true }
113
+ // mock
114
+ // multiple: true,
115
+ // optionMap: {
116
+ // 'user': [
117
+ // { value: '111', label: '张三' },
118
+ // { value: '112', label: '李四' },
119
+ // { value: '113', label: '王五' }
120
+ // ],
121
+ // 'dept': [
122
+ // { value: '221', label: '杭州一部' },
123
+ // { value: '222', label: '杭州二部' },
124
+ // { value: '223', label: '杭州三部' }
125
+ // ]
126
+ // }
127
+ }
128
+ },
129
+ watch: {
130
+ value() {
131
+ if (this.value) {
132
+ const list = this.value.split('$$')
133
+ this.currentValue = [list[0], list[1]]
134
+ this.$emit('labelMapInit', this.labelMap, this.channelType)
135
+ console.log('value转化:', this.currentValue)
136
+ }
137
+ },
138
+ valueList: {
139
+ handler() {
140
+ if (this.valueList) {
141
+ this.currentValue = this.valueList.map(value => {
142
+ const list = value.split('$$')
143
+ return [list[0], list[1]]
144
+ })
145
+ console.log('valueList转化:', this.currentValue)
146
+ this.$emit('labelMapInit', this.labelMap, this.channelType)
147
+ } else {
148
+ this.currentValue = []
149
+ }
150
+ },
151
+ immediate: true,
152
+ deep: true
153
+ }
154
+ },
155
+ computed: {
156
+ optionList() {
157
+ const optionList = []
158
+ for (const key in this.optionMap) {
159
+ optionList.push({
160
+ label: this.optionKeyMap[key],
161
+ value: key,
162
+ disabled: (this.channelTypeDisabled[this.channelType] || []).indexOf(key) > -1,
163
+ children: this.optionMap[key] || []
164
+ })
165
+ }
166
+ // console.log('map转optionList:', optionList)
167
+ return optionList
168
+ },
169
+ labelMap() {
170
+ const map = {}
171
+ if (this.multiple && this.currentValue) { // 值格式 currentValue:[['','',''], ['','','']]
172
+ this.currentValue.forEach(valList => {
173
+ const obj0 = this.optionList.filter(n => n.value === valList[0])[0] || {}
174
+ const obj1 = (obj0.children || []).filter(n => n.value === valList[1])[0] || {}
175
+ // console.log(111111111111, valList, obj0, obj1)
176
+ if (!map[obj0.label]) {
177
+ map[obj0.label] = []
178
+ }
179
+ map[obj0.label].push(obj1.label)
180
+ })
181
+ } else if (!this.multiple && this.currentValue && this.currentValue[0]) { // 值格式 currentValue:['','','']
182
+ const obj0 = this.optionList.filter(n => n.value === this.currentValue[0])[0] || {}
183
+ const obj1 = (obj0.children || []).filter(n => n.value === this.currentValue[1])[0] || {}
184
+ map[obj0.label] = [obj1.label]
185
+ }
186
+ // console.log('labelMap转换:', map)
187
+ return map
188
+ }
189
+ },
190
+ /** ***************************初始化 end *************************** **/
191
+ /** *************************生命周期钩子 start************************* **/
192
+ created() {
193
+ this.props.multiple = this.multiple
194
+ },
195
+ mounted() {},
196
+ /** **************************生命周期钩子 end************************** **/
197
+ /** ***************************methods start*************************** **/
198
+ methods: {
199
+ // -----其他方法 start-----
200
+ // 按钮点击事件
201
+ handleClick() {
202
+ console.log(this.$refs.mptCascader)
203
+ // 主动触发点击事件
204
+ this.$refs.mptCascader.$el.click()
205
+ // dispatchEvent(new MouseEvent('click'));
206
+ },
207
+ change() {
208
+ let val = null
209
+ if (this.multiple) {
210
+ if (this.currentValue) {
211
+ val = this.currentValue.map(value => {
212
+ return `${value[0]}$$${value[1]}`
213
+ })
214
+ }
215
+ } else {
216
+ val = `${this.currentValue[0]}$$${this.currentValue[1]}`
217
+ }
218
+ // console.log('MessageOne返回值:', val, this.channelType, this.labelMap, this.currentValue)
219
+ this.$emit('change', val, this.channelType, this.labelMap, this.currentValue)
220
+ }
221
+ // -----其他方法 end -----
222
+ // -----增删改查 start-----
223
+ }
224
+ }
225
+ </script>
226
+
227
+ <style lang="scss" scoped>
228
+ .mpt-box {
229
+ position: relative;
230
+ width: 100%;
231
+ display: flex;
232
+ justify-content: space-between;
233
+ align-items: center;
234
+ margin-bottom: 15px;
235
+ // border: 1px solid #dadada;
236
+ // border-radius: 4px;
237
+ // padding: 4px;
238
+ }
239
+ .mpt-target {
240
+ position: relative;
241
+ display: flex;
242
+ flex: 1;
243
+ }
244
+ .mpt-target-show {
245
+ z-index: 1;
246
+ padding: 0;
247
+ width: 100%;
248
+ height: 100%;
249
+ box-sizing: border-box;
250
+ overflow-y: auto;
251
+ cursor: pointer;
252
+ }
253
+ .mpt-tag-box {
254
+ display: inline-block;
255
+ // width: 95%;
256
+ margin-top: 4px;
257
+ border: 1px solid #dadada;
258
+ border-radius: 4px;
259
+ font-size: 12px;
260
+ line-height: 16px;
261
+ height: auto;
262
+ display: flex;
263
+ flex-direction: row;
264
+ justify-content: flex-start;
265
+ align-items: stretch;
266
+ position: relative;
267
+ }
268
+ .mpt-tag-box:first-child {
269
+ margin-top: 2px;
270
+ }
271
+ .mpt-tag-tip {
272
+ width: 100px;
273
+ border-top-left-radius: 4px;
274
+ border-bottom-left-radius: 4px;
275
+ background: #409EFE;
276
+ color: #ffffff;
277
+ font-size: 14px;
278
+ padding: 0 8px;
279
+ box-sizing: border-box;
280
+ display: flex;
281
+ align-items: center;
282
+ }
283
+ .mpt-tag-body {
284
+ display: flex;
285
+ flex: 1;
286
+ padding-top: 4px;
287
+ padding-left: 4px;
288
+ flex-shrink: 0;
289
+ flex-wrap: wrap;
290
+ }
291
+ .mpt-tag {
292
+ margin-right: 4px;
293
+ margin-bottom: 4px;
294
+ }
295
+ .mpt-cascader {
296
+ display: none;
297
+ width: 100%;
298
+ }
299
+ .mpt-block {
300
+ display: block;
301
+ }
302
+ .mpt-target:has(.is-focus) {
303
+ .mpt-cascader {
304
+ display: block;
305
+ }
306
+ .mpt-target-show {
307
+ display: none;
308
+ }
309
+ }
310
+ .mpt-type {
311
+ width: 125px;
312
+ }
313
+ // 美化滚动条
314
+ .mpt-target-show::-webkit-scrollbar {
315
+ width: 6px;
316
+ height: 10px;
317
+ }
318
+ .mpt-target-show::-webkit-scrollbar-track {
319
+ width: 6px;
320
+ background: rgba(#101F1C, 0.1);
321
+ }
322
+ .mpt-target-show::-webkit-scrollbar-thumb {
323
+ background-color: rgba(144,147,153,.45);
324
+ background-clip: padding-box;
325
+ min-height: 28px;
326
+ transition: background-color .2s;
327
+ cursor: pointer;
328
+ }
329
+ .mpt-target-show::-webkit-scrollbar-thumb:hover {
330
+ background-color: rgba(144,147,153,.2);
331
+ }
332
+ // 美化滚动条
333
+ .mpt-target-show::-webkit-scrollbar {
334
+ -webkit-appearance: none;
335
+ }
336
+ .mpt-target-show::-webkit-scrollbar-track {
337
+ display: none;
338
+ }
339
+ .mpt-target-show::-webkit-scrollbar-thumb {
340
+ display: none;
341
+ }
342
+ .mpt-target-show:hover::-webkit-scrollbar-track {
343
+ display: block;
344
+ }
345
+ .mpt-target-show:hover::-webkit-scrollbar-thumb {
346
+ display: block;
347
+ }
348
+ </style>
@@ -0,0 +1,212 @@
1
+ <!--
2
+ * @Author: hcm
3
+ * @Date: 2023-05-29 13:18:19
4
+ * @LastEditors: hcm
5
+ * @LastEditTime: 2024-04-11 09:37:02
6
+ * @Description: 消息推送选择目标
7
+ -->
8
+ <template>
9
+ <div :class="`mpt-box-multi ${multiBoxClass}`">
10
+ <div v-for="multiKey in multiKeys" :key="multiKey">
11
+ <div v-if="!titleHide" class="mpt-title">{{ channelTypeMap[multiKey] }}</div>
12
+ <MessageOne
13
+ :channel-type="multiKey"
14
+ :value-list="formMap[multiKey]"
15
+ :box-class="boxClass"
16
+ :target-class="targetClass"
17
+ :type-class="typeClass"
18
+ :clearable="clearable"
19
+ :filterable="filterable"
20
+ :multiple="multiple"
21
+ :disabled="disabled"
22
+ :option-map="optionMap"
23
+ :channel-type-disabled="channelTypeDisabled"
24
+ :option-key-map="optionKeyMap"
25
+ @change="messageOneChange"
26
+ @labelMapInit="labelMapInit"
27
+ ></MessageOne>
28
+ </div>
29
+ <!-- multiKeys null 为单框模式 -->
30
+ <MessageOne
31
+ v-if="!multiKeys"
32
+ :value-list="formMap.value"
33
+ :box-class="boxClass"
34
+ :target-class="targetClass"
35
+ :type-class="typeClass"
36
+ :clearable="clearable"
37
+ :filterable="filterable"
38
+ :multiple="multiple"
39
+ :disabled="disabled"
40
+ :option-map="optionMap"
41
+ @change="messageOneChange"
42
+ @labelMapInit="labelMapInit"
43
+ ></MessageOne>
44
+ </div>
45
+ </template>
46
+
47
+ <script>
48
+ import MessageOne from './MessageOne.vue'
49
+
50
+ export default {
51
+ name: 'BytMessagePushTarget',
52
+ components: {
53
+ MessageOne
54
+ }, // 组件
55
+ props: {
56
+ titleHide: {
57
+ type: Boolean,
58
+ default: false
59
+ },
60
+ multiKeys: { // null 表示单框模式
61
+ type: Array,
62
+ default: () => ['10', '20', '30', '40', '50', '60', '70', '80'] // channelType数组
63
+ },
64
+ channelTypeMap: { // 字典可传入,避免字典更新,要发包
65
+ type: Object,
66
+ default: () => ({
67
+ '10': '企业微信',
68
+ '20': '企业微信群',
69
+ '30': '企业微信群机器人',
70
+ '40': '短信',
71
+ '50': '邮件',
72
+ '60': '小程序',
73
+ '70': '公众号',
74
+ '80': 'app'
75
+ })
76
+ },
77
+ channelTypeDisabled: { // 默认值在子组件内,默认值必须undefined
78
+ type: Object,
79
+ default: undefined
80
+ },
81
+ optionKeyMap: { // 默认值在子组件内,默认值必须undefined
82
+ type: Object,
83
+ default: undefined
84
+ },
85
+ targetMap: { // { '40': ['dept$$221'] }
86
+ type: Object,
87
+ default: null
88
+ },
89
+ // option数据源,模式1
90
+ optionUrl: {
91
+ type: String,
92
+ default: '/news/chain/getSourceMap'
93
+ },
94
+ requestFun: {
95
+ type: Function,
96
+ default: null
97
+ },
98
+ // option数据源,模式2
99
+ optionMapProp: {
100
+ type: Object,
101
+ default: null
102
+ },
103
+ multiBoxClass: { // 自定义 大盒子class
104
+ type: String,
105
+ default: ''
106
+ },
107
+ boxClass: { // 自定义 大盒子class
108
+ type: String,
109
+ default: ''
110
+ },
111
+ targetClass: { // 自定义 目标选择class
112
+ type: String,
113
+ default: ''
114
+ },
115
+ typeClass: { // 自定义 推送类型选择class
116
+ type: String,
117
+ default: ''
118
+ },
119
+ clearable: { // 推送目标允许清空
120
+ type: Boolean,
121
+ default: true
122
+ },
123
+ filterable: { // 推送目标允许过滤
124
+ type: Boolean,
125
+ default: true
126
+ },
127
+ multiple: { // 推送目标允许多选
128
+ type: Boolean,
129
+ default: true
130
+ },
131
+ disabled: { // 禁止编辑
132
+ type: Boolean,
133
+ default: false
134
+ }
135
+ },
136
+ data() {
137
+ return {
138
+ optionMap: null, // {'user': [{ value: '111', label: '张三' }], 'dept': [{ value: '221', label: '杭州一部' }]}
139
+ formMap: {}, // { '40': ['dept$$221'] }
140
+ formNameMap: {} // {'短信': {'部门': '杭州一部'}}
141
+ }
142
+ },
143
+ watch: {
144
+ targetMap: {
145
+ handler() {
146
+ if (this.targetMap) {
147
+ this.formMap = this.targetMap
148
+ }
149
+ },
150
+ immediate: true,
151
+ deep: true
152
+ }
153
+ },
154
+ computed: {
155
+ },
156
+ /** ***************************初始化 end *************************** **/
157
+ /** *************************生命周期钩子 start************************* **/
158
+ created() {
159
+ this.getOptionMap()
160
+ },
161
+ mounted() {},
162
+ /** **************************生命周期钩子 end************************** **/
163
+ /** ***************************methods start*************************** **/
164
+ methods: {
165
+ // -----其他方法 start-----
166
+ messageOneChange(value, channelType, labelMap) {
167
+ // console.log(111, value, channelType, labelMap)
168
+ if (this.multiKeys) {
169
+ this.formMap[channelType] = value
170
+ this.formNameMap[this.channelTypeMap[channelType]] = labelMap
171
+ this.$emit('change', this.formMap, this.formNameMap)
172
+ } else {
173
+ this.$emit('change', value, labelMap)
174
+ }
175
+ },
176
+ labelMapInit(labelMap, channelType) {
177
+ if (this.multiKeys) {
178
+ this.formNameMap[this.channelTypeMap[channelType]] = labelMap
179
+ }
180
+ },
181
+ // -----其他方法 end -----
182
+ // -----增删改查 start-----
183
+ getOptionMap() {
184
+ if (this.optionMapProp) {
185
+ this.optionMap = this.optionMapProp
186
+ } else if (this.requestFun) {
187
+ this.loading = true
188
+ this.requestFun({
189
+ url: this.optionUrl,
190
+ method: 'get',
191
+ data: {}
192
+ }).then(res => {
193
+ this.optionMap = res.data || {}
194
+ }).finally(() => {
195
+ this.loading = false
196
+ })
197
+ }
198
+ }
199
+ }
200
+ }
201
+ </script>
202
+
203
+ <style lang="scss" scoped>
204
+ .mpt-box-multi {
205
+ position: relative;
206
+ }
207
+ .mpt-title {
208
+ border-left: 4px solid #409EFE;
209
+ padding-left: 6px;
210
+ margin-bottom: 4px;
211
+ }
212
+ </style>