n20-common-lib 2.1.20 → 2.1.22

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": "n20-common-lib",
3
- "version": "2.1.20",
3
+ "version": "2.1.22",
4
4
  "private": false,
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -4,13 +4,12 @@
4
4
  .el-scrollbar__bar.is-vertical {
5
5
  .el-scrollbar__thumb {
6
6
  display: none;
7
-
8
7
  }
9
8
  }
10
-
11
9
  }
12
10
 
13
11
  .n20-anchor {
12
+ padding-inline-start: 0;
14
13
  position: absolute;
15
14
  top: 16px;
16
15
  right: 0;
@@ -25,7 +24,6 @@
25
24
  margin: 2px 0;
26
25
  border-left: 2px solid var(--color-text-placeholder);
27
26
  }
28
-
29
27
  .n20-anchor-activit {
30
28
  color: var(--color-primary);
31
29
  border-left: 2px solid var(--color-primary);
@@ -38,17 +36,12 @@
38
36
  .el-scrollbar__bar.is-vertical {
39
37
  .el-scrollbar__thumb {
40
38
  display: none;
41
-
42
39
  }
43
40
  }
44
-
45
- }
46
-
47
- ul {
48
- padding-inline-start: 0;
49
41
  }
50
42
 
51
43
  .n20-anchor-left {
44
+ padding-inline-start: 0;
52
45
  position: absolute;
53
46
  top: 16px;
54
47
  left: 0;
@@ -68,4 +61,4 @@ ul {
68
61
  color: var(--color-primary);
69
62
  border-left: 2px solid var(--color-primary);
70
63
  }
71
- }
64
+ }
@@ -1,37 +1,47 @@
1
1
  <template>
2
- <ExpandablePane :id="id" :default-expand.sync="show" :title="title"><slot></slot></ExpandablePane>
2
+ <ExpandablePane :anchor-item-id="id" :default-expand.sync="show" :title="title"><slot></slot></ExpandablePane>
3
3
  </template>
4
4
 
5
5
  <script>
6
- import ExpandablePane from '../Expandable/main.vue'
6
+ import ExpandablePane from '../../components/Expandable/main.vue'
7
7
  export default {
8
8
  name: 'AnchorItem',
9
9
  components: {
10
10
  ExpandablePane
11
11
  },
12
12
  props: {
13
- title: {
14
- type: String,
13
+ id: {
14
+ type: [String, Number],
15
15
  default: undefined
16
16
  },
17
- id: {
17
+ title: {
18
18
  type: String,
19
- default: ''
20
- },
21
- // eslint-disable-next-line vue/require-default-prop
22
- sort: [String, Number]
19
+ default: undefined
20
+ }
21
+ },
22
+ inject: {
23
+ init: {
24
+ type: Function,
25
+ default: () => () => {}
26
+ }
23
27
  },
24
- inject: ['init'],
25
28
  data() {
26
29
  return {
27
30
  show: true
28
31
  }
29
32
  },
33
+ watch: {
34
+ title(val) {
35
+ if (val) {
36
+ this.init('title', this.id, this.title)
37
+ }
38
+ }
39
+ },
30
40
  mounted() {
31
- this.init()
41
+ this.init('mount', this.id, this.title)
32
42
  },
33
- destroyed() {
34
- this.init()
43
+ beforeDestroy() {
44
+ this.init('destroy', this.id, this.title)
35
45
  }
36
46
  }
37
47
  </script>
@@ -1,40 +1,31 @@
1
1
  <template>
2
- <el-scrollbar :id="position === 'right' ? 'page-scrollbar' : 'page-scrollbar-left'" style="height: 100%">
3
- <div v-if="position === 'right'" ref="Anchor">
2
+ <div class="flex-box" style="height: 100%">
3
+ <AnchorSidebar
4
+ v-if="position !== 'right'"
5
+ :nav-list="navList"
6
+ :activit="value"
7
+ :style="{ width: navWidth }"
8
+ @click="activitFn"
9
+ />
10
+ <div ref="anchor-content" class="flex-item" style="height: 100%; overflow: auto">
4
11
  <slot></slot>
5
- <ul class="n20-anchor">
6
- <li
7
- v-for="(item, index) in AnchorNavList"
8
- :key="index"
9
- :class="['n20-anchor-item', value === item.id ? 'n20-anchor-activit' : '']"
10
- @click="getAnchorItem(item.id, index)"
11
- >
12
- {{ item.title }}
13
- </li>
14
- </ul>
15
12
  </div>
16
- <div v-else ref="Anchor">
17
- <ul class="n20-anchor-left">
18
- <li
19
- v-for="(item, index) in AnchorNavList"
20
- :key="index"
21
- :class="['n20-anchor-item', value === item.id ? 'n20-anchor-activit' : '']"
22
- @click="getAnchorItem(item.id, index)"
23
- >
24
- {{ item.title }}
25
- </li>
26
- </ul>
27
- <slot></slot>
28
- </div>
29
- </el-scrollbar>
13
+ <AnchorSidebar v-if="position === 'right'" :nav-list="navList" :activit="value" @click="activitFn" />
14
+ </div>
30
15
  </template>
31
16
 
32
17
  <script>
33
- import { getScrollContainer, vueDebounce } from '../../utils/getScrollContainer.js'
18
+ import { debounce } from 'throttle-debounce'
19
+ import { addListener, removeListener } from 'resize-detector'
20
+
21
+ import AnchorSidebar from './sidebar.vue'
34
22
  export default {
35
23
  name: 'Anchor',
24
+ components: {
25
+ AnchorSidebar
26
+ },
36
27
  props: {
37
- scrollDom: {
28
+ value: {
38
29
  type: String,
39
30
  default: ''
40
31
  },
@@ -42,161 +33,171 @@ export default {
42
33
  type: String,
43
34
  default: 'right'
44
35
  },
45
- // 默认选中tab按钮
46
- value: {
36
+ navWidth: {
47
37
  type: String,
48
- default: ''
49
- }
50
- },
51
- provide() {
52
- return {
53
- init: this.init
38
+ default: '110px'
54
39
  }
55
40
  },
56
41
  data() {
57
42
  return {
58
- AnchorNavList: [], // 按钮数据
59
- AnchorNavMap: {}, // 楼层高度的映射
60
- scrollDisabled: false, //禁止滚动函数执行
61
- valueType: 1, //当前楼层改变的类型,1是组件传递、按钮直达改变,2是通过滚动监听自动改变
62
- scrollFunDebounceFun: vueDebounce('scrollFun', 100)
63
- }
64
- },
65
- computed: {
66
- scrollWrap() {
67
- if (this.scrollDom) {
68
- return document.querySelector(this.scrollDom)
69
- } else {
70
- return getScrollContainer(this.$refs.Anchor, true)
71
- }
43
+ navList: [],
44
+ wrapTop: 0,
45
+ wrapHeight: 48
72
46
  }
73
47
  },
74
48
  watch: {
75
- // 监听楼层变化,当为父组件传递,或者按钮直达时,手动滚动到当前楼层
76
- value: function (val) {
77
- this.valueType === 1 && this.scrollDomFun(this.AnchorNavMap[val])
49
+ navList() {
50
+ this.navsWatch()
51
+ },
52
+ value() {
53
+ this.valueWatch()
78
54
  }
79
55
  },
80
- async mounted() {
81
- await this.init()
82
- // 如果传了当前楼层,直接到达对应的高度
83
- if (this.value) {
84
- this.scrollWrap.scrollTop = this.AnchorNavMap[this.value]
85
- } else {
86
- //没有传楼层,则根据当前高度自动获取
87
- this.getAnchorValue(this.scrollWrap.scrollTop)
56
+ provide() {
57
+ return {
58
+ init: this.itemWatch
88
59
  }
89
- this.scrollWrap.addEventListener('scroll', this.scrollFunDebounce)
90
60
  },
91
- beforeDestroy() {
92
- this.scrollWrap.removeEventListener('scroll', this.scrollFunDebounce)
61
+ mounted() {
62
+ this.mdIng = true
63
+ let wrap = this.$refs['anchor-content']
64
+
65
+ wrap.addEventListener('scroll', this.scrollFn)
66
+ this.sizeFn()
67
+ addListener(wrap, debounce(30, this.sizeFn))
68
+
69
+ setTimeout(() => {
70
+ this.valueWatch()
71
+ this.mdIng = false
72
+ }, 100)
93
73
  },
94
74
  methods: {
95
- init: vueDebounce('initAs', 500),
96
- // 初始化,获取电梯按钮数据,获取楼层高度映射
97
- initAs() {
98
- let parentTop = this.$refs.Anchor.getBoundingClientRect().top - this.scrollWrap.getBoundingClientRect().top
99
- let list = this.$children[0].$children.map((item) => {
100
- let rect = item.$el.getBoundingClientRect()
101
- let itemScrollTop = item.$el.offsetTop
102
- this.AnchorNavMap[item.id] = itemScrollTop
103
- // console.log(item, 123)
104
- return {
105
- scrollTop: itemScrollTop,
106
- top: rect.top - parentTop,
107
- bottom: rect.bottom - parentTop,
108
- height: rect.height,
109
- title: item.title,
110
- id: item.id,
111
- sort: item.sort
112
- }
113
- })
114
- // 去掉多余的节点
115
- this.AnchorNavList = list
116
- .filter((val) => val.id !== undefined && val.title !== undefined)
117
- .sort((a, b) => {
118
- return a.sort - b.sort
119
- })
120
- },
121
- //滚动的函数
122
- scrollFun(e) {
123
- this.getAnchorValue(e.target.scrollTop)
124
- },
125
- scrollFunDebounce(e) {
126
- !this.scrollDisabled && this.scrollFunDebounceFun(e)
127
- },
128
- // 根据当前高度获取楼层位置
129
- getAnchorValue(scrollTop) {
130
- let arr = []
131
- for (let i = 0; i < this.AnchorNavList.length; i++) {
132
- let item = this.AnchorNavList[i]
133
- let height = this.scrollWrap.getBoundingClientRect().height + scrollTop
134
- let value = 0
135
- if (scrollTop <= item.top) {
136
- value = height - item.top
137
- if (value > item.height) {
138
- value = item.height
139
- } else if (value < 0) {
140
- value = 0
75
+ valueWatch() {
76
+ if (!this.scIng && !this.acIng) {
77
+ if (this.navList.length && (this.value || this.value === 0)) {
78
+ let item = this.navList.find((c) => c.id === this.value)
79
+ if (item) {
80
+ this.activitFn(item)
81
+ } else {
82
+ this.$emit('input', undefined)
141
83
  }
142
- } else if (scrollTop > item.top && scrollTop <= item.bottom) {
143
- value = item.bottom - scrollTop
144
84
  }
145
- value = value / item.height
146
- arr.push(value)
147
85
  }
148
- let max = Math.max(...arr)
149
- for (let i = 0; i < arr.length; i++) {
150
- if (arr[i] === max) {
151
- this.valueType = 2
152
- this.$emit('input', this.AnchorNavList[i].id)
153
- break
86
+ },
87
+ navsWatch() {
88
+ if (!this.mdIng) {
89
+ if (this.navList.length && (this.value || this.value === 0)) {
90
+ this.scrollFn()
154
91
  }
155
92
  }
156
93
  },
157
- getAnchorItem(id, i) {
158
- //直达楼层
159
- if (id === this.value || this.scrollDisabled) {
160
- return
94
+ itemWatch(type, id, title) {
95
+ if (type === 'mount') {
96
+ let item = this.navList.find((c) => c.id === id)
97
+ if (!item) {
98
+ item = { id: id, title: title, height: 48 }
99
+ this.navList.push(item)
100
+ } else {
101
+ item.title = title
102
+ }
103
+
104
+ let dom = this.$refs['anchor-content'].querySelector(`[anchor-item-id="${id}"]`)
105
+ if (dom) {
106
+ this.getHeight(item, dom)
107
+ addListener(dom, debounce(30, this.getHeight.bind(this, item)))
108
+ }
109
+
110
+ this.sortList()
111
+ } else if (type === 'destroy') {
112
+ let dom = this.$refs['anchor-content']?.querySelector(`[anchor-item-id="${id}"]`)
113
+ dom && removeListener(dom)
114
+
115
+ this.sortList()
116
+ } else if (type === 'title') {
117
+ let item = this.navList.find((c) => c.id === id)
118
+ if (item) {
119
+ item.title = title
120
+ }
161
121
  }
162
- this.$children[0].$children[i].show = true
163
- this.valueType = 1
164
- this.$emit('input', id)
165
122
  },
166
- // 模拟滚动
167
- scrollDomFun(itemScrollTop) {
168
- this.scrollDisabled = true //模拟滚动过程中,禁用直达楼层和监听的滚动事件
169
- let speed = 50
170
- let scrollTop = this.scrollWrap.scrollTop
171
- if (itemScrollTop > scrollTop) {
172
- // 向下滚动
173
- let timer = setInterval(() => {
174
- scrollTop += speed
175
- if (scrollTop < itemScrollTop) {
176
- this.scrollWrap.scrollTop = scrollTop
177
- } else {
178
- this.scrollWrap.scrollTop = itemScrollTop
179
- clearInterval(timer)
180
- setTimeout(() => {
181
- this.scrollDisabled = false
182
- }, 100)
183
- }
184
- }, 20)
185
- } else {
186
- // 向上滚动
187
- let timer = setInterval(() => {
188
- scrollTop -= speed
189
- if (scrollTop >= itemScrollTop) {
190
- this.scrollWrap.scrollTop = scrollTop
191
- } else {
192
- this.scrollWrap.scrollTop = itemScrollTop
193
- clearInterval(timer)
194
- setTimeout(() => {
195
- this.scrollDisabled = false
196
- }, 100)
123
+ getHeight(item, dom) {
124
+ item.height = dom.offsetHeight
125
+ },
126
+ sortList: debounce(30, function () {
127
+ if (this.$refs['anchor-content']) {
128
+ let list = []
129
+ let DomList = this.$refs['anchor-content'].querySelectorAll('[anchor-item-id]')
130
+ DomList.forEach((dom) => {
131
+ let id = dom.getAttribute('anchor-item-id')
132
+ let item = this.navList.find((c) => c.id === id)
133
+ if (item) {
134
+ list.push(item)
197
135
  }
198
- }, 20)
136
+ })
137
+ this.navList = list
199
138
  }
139
+ }),
140
+ sizeFn: debounce(30, function () {
141
+ this.wrapHeight = this.$refs['anchor-content']?.offsetHeight
142
+ }),
143
+ scrollFn: debounce(30, function () {
144
+ if (this.acIng) return
145
+
146
+ this.scIng = true
147
+
148
+ let wrapTop = this.$refs['anchor-content'].scrollTop
149
+
150
+ let mB = 8 // 边距
151
+ let pHs = 0
152
+ this.navList.some((item) => {
153
+ if (!(pHs <= wrapTop && pHs + item.height - mB > wrapTop)) {
154
+ pHs += item.height
155
+ } else {
156
+ this.$emit('input', item.id)
157
+
158
+ return true
159
+ }
160
+ })
161
+
162
+ this.wrapTop = wrapTop
163
+
164
+ this.$nextTick(() => {
165
+ this.scIng = false
166
+ })
167
+ }),
168
+ activitFn(item) {
169
+ this.acIng = true
170
+ this.$emit('input', item.id)
171
+
172
+ let pHs = 0
173
+ this.navList.some((c) => {
174
+ if (c.id !== item.id) {
175
+ pHs += c.height
176
+ } else {
177
+ let wrap = this.$refs['anchor-content']
178
+ // wrap.scrollTop = pHs
179
+ // this.acIng = false
180
+ this.animation(wrap, wrap.scrollTop, pHs)
181
+ return true
182
+ }
183
+ })
184
+ },
185
+ animation(dom, F, T) {
186
+ let sT = 16 //每步时间
187
+ let N = 16 //步数
188
+ let S = T - F //距离
189
+ let V = S / N //每步长
190
+ let nI = 0
191
+ let stO = setInterval(() => {
192
+ nI++
193
+ if (nI <= N) {
194
+ dom.scrollTop = dom.scrollTop + V
195
+ } else {
196
+ dom.scrollTop = T
197
+ setTimeout(() => (this.acIng = false), 60)
198
+ clearInterval(stO)
199
+ }
200
+ }, sT)
200
201
  }
201
202
  }
202
203
  }
@@ -0,0 +1,41 @@
1
+ <template>
2
+ <div class="p-t-m">
3
+ <div
4
+ v-for="item in navList"
5
+ :key="item.id"
6
+ class="n20-anchor2-nav"
7
+ :class="{ 'n20-anchor2-nav-activit': item.id === activit }"
8
+ @click="$emit('click', item)"
9
+ >
10
+ {{ item.title }}
11
+ </div>
12
+ </div>
13
+ </template>
14
+
15
+ <script>
16
+ export default {
17
+ props: {
18
+ navList: {
19
+ type: Array,
20
+ default: () => []
21
+ },
22
+ activit: {
23
+ type: [String, Number],
24
+ default: undefined
25
+ }
26
+ }
27
+ }
28
+ </script>
29
+
30
+ <style>
31
+ .n20-anchor2-nav {
32
+ padding: 5px 10px;
33
+ margin: 2px 0;
34
+ border-left: 2px solid var(--color-text-placeholder);
35
+ cursor: pointer;
36
+ }
37
+ .n20-anchor2-nav-activit {
38
+ color: var(--color-primary);
39
+ border-left: 2px solid var(--color-primary);
40
+ }
41
+ </style>
@@ -6,12 +6,7 @@
6
6
  :options="areaTree"
7
7
  :filterable="filterable"
8
8
  :clearable="clearable"
9
- :props="{
10
- value: 'regionNo',
11
- label: 'regionName',
12
- children: 'children',
13
- expandTrigger: 'hover'
14
- }"
9
+ :props="propsAs"
15
10
  v-on="$listeners"
16
11
  />
17
12
  </template>
@@ -44,6 +39,10 @@ export default {
44
39
  countryId: {
45
40
  type: String,
46
41
  default: 'CHN'
42
+ },
43
+ props: {
44
+ type: Object,
45
+ default: undefined
47
46
  }
48
47
  },
49
48
  data() {
@@ -52,6 +51,15 @@ export default {
52
51
  }
53
52
  },
54
53
  computed: {
54
+ propsAs() {
55
+ let _prop = {
56
+ value: 'regionNo',
57
+ label: 'regionName',
58
+ children: 'children',
59
+ expandTrigger: 'hover'
60
+ }
61
+ return Object.assign(_prop, this.props)
62
+ },
55
63
  areaKey() {
56
64
  return this.countryId === 'CHN' ? '_china_area_tree_' : `_${this.countryId}_area_tree_`
57
65
  },
@@ -27,10 +27,10 @@
27
27
  </div>
28
28
  <div class="text-c m-t m-b">
29
29
  <slot name="actions">
30
- <el-button size="mini" type="primary" style="width: 76px" @click="filter">
30
+ <el-button type="primary" @click="filter">
31
31
  {{ filterText }}
32
32
  </el-button>
33
- <el-button size="mini" plain style="width: 76px" @click="clear">
33
+ <el-button plain @click="clear">
34
34
  {{ clearText }}
35
35
  </el-button>
36
36
  </slot>
@@ -155,7 +155,7 @@
155
155
  </dialogWrap>
156
156
  <!-- 消息/通知 -->
157
157
  <el-popover ref="noticePop" trigger="click" width="400" @after-enter="$refs.noticeContent.show()">
158
- <noticePop ref="noticeContent" :num.sync="noticeNum" />
158
+ <noticePop ref="noticeContent" />
159
159
  </el-popover>
160
160
  <el-dialog :visible.sync="scV" :title="'切换用户' | $lc" append-to-body width="600px">
161
161
  <switchUser :visible.sync="scV" :user-no="userNo" />
@@ -270,6 +270,10 @@ export default {
270
270
  this.show = true
271
271
  }
272
272
  })
273
+
274
+ this.getNNum()
275
+ document.addEventListener('visibilitychange', this.getNNum)
276
+ window.addEventListener('message', this.updateNotice)
273
277
  },
274
278
  mounted() {
275
279
  let userInfo = JSON.parse(sessionStorage.getItem('userInfo') || '{}')
@@ -281,6 +285,10 @@ export default {
281
285
  }
282
286
  this.rolesList = userInfo.roles || []
283
287
  },
288
+ beforeDestroy() {
289
+ document.removeEventListener('visibilitychange', this.getNNum)
290
+ window.removeEventListener('message', this.updateNotice)
291
+ },
284
292
  methods: {
285
293
  // 跳转打主数据人员页面
286
294
  goMdmUser() {
@@ -422,6 +430,29 @@ export default {
422
430
  })
423
431
 
424
432
  this.underway = !!res.data
433
+ },
434
+ // 更新消息条数
435
+ updateNotice(ev) {
436
+ if (ev.data === 'NstcUpdateNotice') {
437
+ this.getNNum()
438
+ }
439
+ },
440
+ // 获取消息条数
441
+ getNNum() {
442
+ clearTimeout(this.getNNumTimeOut)
443
+ if (!document.hidden) {
444
+ Promise.all([
445
+ axios.get('/bems/wkb/messageCenter/getUnReadTotal/' + this.username, null, { loading: false, noMsg: true }),
446
+ axios.get('/bems/1.0/notice/notReadCount', null, {
447
+ loading: false,
448
+ noMsg: true
449
+ })
450
+ ]).then(([res_1, res_2]) => {
451
+ this.noticeNum = (res_1.data.data || 0) + (res_2.data || 0)
452
+ })
453
+
454
+ this.getNNumTimeOut = setTimeout(this.loopGetNNum, 1000 * 60 * 3)
455
+ }
425
456
  }
426
457
  }
427
458
  }