byt-ui 0.0.19 → 0.1.0

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.19",
3
+ "version": "0.1.0",
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-13 09:50:53
5
+ * @LastEditTime: 2024-03-04 15:16:54
6
6
  * @LastEditors: hcm
7
7
  -->
8
8
 
@@ -43,6 +43,7 @@
43
43
  :column-config="{resizable: true}"
44
44
  :row-config="{isCurrent: true, isHover: true}"
45
45
  :show-overflow="showOverflow"
46
+ v-bind="vxeTableProp"
46
47
  >
47
48
  <template v-for="(column,index) in columns">
48
49
  <vxe-column
@@ -66,6 +67,7 @@
66
67
  :width="column.width"
67
68
  :title="column.label"
68
69
  :align="column.align||'center'"
70
+ v-bind="column.prop"
69
71
  :key="index"
70
72
  >
71
73
  <template #default="scope">
@@ -93,13 +95,14 @@
93
95
  :width="column.width"
94
96
  :title="column.label"
95
97
  :align="column.align||'center'"
98
+ v-bind="column.prop"
96
99
  :key="index"
97
100
  ></vxe-column>
98
101
  </template>
99
102
 
100
103
  <template #empty>
101
104
  <el-empty description="暂无数据!">
102
- <el-button type="primary" @click="onSearch">重试</el-button>
105
+ <el-button v-if="emptyBtnShow" type="primary" @click="onSearch">重试</el-button>
103
106
  </el-empty>
104
107
  </template>
105
108
  </vxe-table>
@@ -164,8 +167,16 @@ export default {
164
167
  return []
165
168
  }
166
169
  },
170
+ vxeTableProp: { // vxeTableProp(会使用v-bind展开)
171
+ type: Object,
172
+ default: null
173
+ },
174
+ emptyBtnShow: {
175
+ type: Boolean,
176
+ default: true
177
+ },
167
178
  /** 表格列配置*/
168
- columns: {
179
+ columns: { // column.prop(会使用v-bind展开)
169
180
  type: Array,
170
181
  required: true,
171
182
  default() {
@@ -2,12 +2,12 @@
2
2
  * @Description:
3
3
  * @Author: 王国火
4
4
  * @Date: 2022-07-13 08:46:34
5
- * @LastEditTime: 2023-09-13 09:54:09
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 回车触发过滤 -->
@@ -74,10 +74,10 @@
74
74
  >
75
75
  </el-date-picker>
76
76
  </template>
77
- <!-- add by hcm 加插槽 增加灵活性 -->
78
- <slot name="filters"></slot>
79
77
  </el-form-item>
80
78
 
79
+ <!-- add by hcm 加插槽 增加灵活性 -->
80
+ <slot name="filters"></slot>
81
81
  <el-form-item>
82
82
  <el-button icon="el-icon-search" type="primary" @click="onSearch">查询</el-button>
83
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>
@@ -2,15 +2,19 @@
2
2
  * @Description:
3
3
  * @Author: 王国火
4
4
  * @Date: 2022-09-19 14:31:00
5
- * @LastEditTime: 2022-09-19 14:32:39
6
- * @LastEditors: 王国火
5
+ * @LastEditTime: 2024-02-27 16:36:04
6
+ * @LastEditors: hcm
7
7
  */
8
8
  import BaseView from "./components/basic-view/index"
9
9
  import FormView from "./components/form-view/index"
10
+ import BytMessagePushTarget from "./components/message-push-target/index"
11
+ import BytMessageOne from "./components/message-push-target/MessageOne"
10
12
 
11
13
  const components=[
12
14
  BaseView,
13
- FormView
15
+ FormView,
16
+ BytMessagePushTarget,
17
+ BytMessageOne
14
18
  ]
15
19
 
16
20
  export default components