gunter-kgd 1.0.4 → 1.0.5

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.
@@ -14,6 +14,26 @@
14
14
  :time_mode="time_mode"
15
15
  :toast-render="toastRender"
16
16
  :toast-class="toastClass"></ganteGcItemContent>
17
+ <button
18
+ v-if="shouldShowLocateStart(item)"
19
+ type="button"
20
+ class="gc-locate-btn gc-locate-btn--left"
21
+ title="定位到开始时间"
22
+ @mousedown.stop.prevent
23
+ @click.stop="locateItem(item,'start')"
24
+ :style="getLocateBtnStyle('left')">
25
+ <span class="gc-locate-btn__arrow">&lt;</span>
26
+ </button>
27
+ <button
28
+ v-if="shouldShowLocateEnd(item)"
29
+ type="button"
30
+ class="gc-locate-btn gc-locate-btn--right"
31
+ title="定位到结束时间"
32
+ @mousedown.stop.prevent
33
+ @click.stop="locateItem(item,'end')"
34
+ :style="getLocateBtnStyle('right')">
35
+ <span class="gc-locate-btn__arrow">&gt;</span>
36
+ </button>
17
37
  <!--<ganteDragCircle :current_data="item"></ganteDragCircle>-->
18
38
  </div>
19
39
  <ganteview-item
@@ -36,6 +56,7 @@
36
56
  </template>
37
57
  <script>
38
58
  import ganteGcItemContent from './gante-gc-item-content'
59
+ import commitEmit from './commit'
39
60
  // import ganteDragCircle from './gante-drag-circle'
40
61
  export default {
41
62
  name: 'ganteview-item',
@@ -46,6 +67,10 @@
46
67
  return {
47
68
  canAnimation: false,
48
69
  bol: false,
70
+ scrollInfo:{
71
+ scrollLeft: 0,
72
+ clientWidth: 0,
73
+ }
49
74
  }
50
75
  },
51
76
  props: {
@@ -58,7 +83,127 @@
58
83
  toastRender: Function,
59
84
  toastClass: String,
60
85
  },
86
+ created() {
87
+ this._onGcScroll = (info = {}) => {
88
+ if(info && typeof info === 'object'){
89
+ this.scrollInfo.scrollLeft = Number(info.scrollLeft) || 0
90
+ this.scrollInfo.clientWidth = Number(info.clientWidth) || 0
91
+ }
92
+ }
93
+ commitEmit.$on('gc-scroll', this._onGcScroll)
94
+ },
95
+ destroyed() {
96
+ if(this._onGcScroll){
97
+ commitEmit.$off('gc-scroll', this._onGcScroll)
98
+ this._onGcScroll = null
99
+ }
100
+ },
61
101
  methods: {
102
+ getScroller(){
103
+ if(this.$el && this.$el.closest){
104
+ const found = this.$el.closest('.ganteview')
105
+ if(found){
106
+ return found
107
+ }
108
+ }
109
+ return document.getElementsByClassName('ganteview')[0] || null
110
+ },
111
+ getItemRange(item){
112
+ const start = Number(item && item.left) || 0
113
+ const width = Number(item && item.width) || 0
114
+ const end = start + width
115
+ return { start, end }
116
+ },
117
+ getLocateBtnStyle(side){
118
+ const padding = 6
119
+ const btnWidth = 18
120
+ const viewLeft = Number(this.scrollInfo.scrollLeft) || 0
121
+ const viewWidth = Number(this.scrollInfo.clientWidth) || 0
122
+ if(!viewWidth){
123
+ return {}
124
+ }
125
+ let left = viewLeft + padding
126
+ if(side === 'right'){
127
+ left = viewLeft + viewWidth - btnWidth - padding
128
+ if(left < viewLeft + padding){
129
+ left = viewLeft + padding
130
+ }
131
+ }
132
+ return { left: left + 'px' }
133
+ },
134
+ shouldShowLocateStart(item){
135
+ if(!item || item.left == null || !this.scrollInfo.clientWidth){
136
+ return false
137
+ }
138
+ const { start, end } = this.getItemRange(item)
139
+ const barEnd = end || start
140
+ const padding = 20
141
+ const viewStart = this.scrollInfo.scrollLeft
142
+ const viewEnd = viewStart + this.scrollInfo.clientWidth
143
+ const fullyLeft = barEnd < viewStart
144
+ const fullyRight = start > viewEnd
145
+ if(fullyLeft){
146
+ return true
147
+ }
148
+ if(fullyRight){
149
+ return false
150
+ }
151
+ return start < viewStart + padding
152
+ },
153
+ shouldShowLocateEnd(item){
154
+ if(!item || item.left == null || !this.scrollInfo.clientWidth){
155
+ return false
156
+ }
157
+ const { start, end } = this.getItemRange(item)
158
+ const barEnd = end || start
159
+ const padding = 20
160
+ const viewStart = this.scrollInfo.scrollLeft
161
+ const viewEnd = viewStart + this.scrollInfo.clientWidth
162
+ const fullyLeft = barEnd < viewStart
163
+ const fullyRight = start > viewEnd
164
+ if(fullyRight){
165
+ return true
166
+ }
167
+ if(fullyLeft){
168
+ return false
169
+ }
170
+ return barEnd > viewEnd - padding
171
+ },
172
+ locateItem(item,edge){
173
+ const scroller = this.getScroller()
174
+ if(!scroller){
175
+ return
176
+ }
177
+ const { start, end } = this.getItemRange(item)
178
+ const viewStart = scroller.scrollLeft
179
+ const viewEnd = viewStart + scroller.clientWidth
180
+ const padding = 20
181
+ let nextScroll = null
182
+
183
+ if(edge === 'start'){
184
+ if(start < viewStart + padding || start > viewEnd - padding){
185
+ nextScroll = Math.max(start - padding,0)
186
+ }
187
+ }else{
188
+ const targetEdge = end || start
189
+ if(targetEdge > viewEnd - padding || targetEdge < viewStart + padding){
190
+ nextScroll = Math.max(targetEdge - scroller.clientWidth + padding,0)
191
+ }
192
+ }
193
+ if(nextScroll === null){
194
+ return
195
+ }
196
+ const maxScroll = Math.max(0,(scroller.scrollWidth || 0) - scroller.clientWidth)
197
+ const resolved = Math.min(nextScroll,maxScroll)
198
+ if(Math.abs(resolved - viewStart) < 1){
199
+ return
200
+ }
201
+ if(scroller.scrollTo){
202
+ scroller.scrollTo({left: resolved,behavior:'smooth'})
203
+ }else{
204
+ scroller.scrollLeft = resolved
205
+ }
206
+ },
62
207
  // 进入到了tr上
63
208
  enterTr(ev, tr) {
64
209
  this.$set(tr, 'is_hover', true)
@@ -91,5 +236,38 @@
91
236
  .ganteview-content-one.gj_hover_class{
92
237
  background: rgba(246, 246, 246, 0.7);
93
238
  }
239
+ .gc-locate-btn{
240
+ position: absolute;
241
+ top: 9px;
242
+ width: 18px;
243
+ height: 22px;
244
+ border-radius: 4px;
245
+ border: 1px solid rgba(0,0,0,0.12);
246
+ background: rgba(255,255,255,0.92);
247
+ cursor: pointer;
248
+ padding: 0;
249
+ display: inline-flex;
250
+ align-items: center;
251
+ justify-content: center;
252
+ color: #00a578;
253
+ box-shadow: 0 2px 8px rgba(0,0,0,0.08);
254
+ z-index: 4;
255
+ &:hover{
256
+ background: #fff;
257
+ border-color: rgba(0,165,120,0.4);
258
+ }
259
+ .gc-locate-btn__arrow{
260
+ font-weight: 700;
261
+ font-size: 12px;
262
+ line-height: 1;
263
+ }
264
+ }
265
+ .gc-locate-btn--left{
266
+ margin-right: 6px;
267
+ }
268
+ .gc-locate-btn--right{
269
+ margin-left: 6px;
270
+ margin-right: 6px;
271
+ }
94
272
 
95
273
  </style>
@@ -84,6 +84,7 @@
84
84
  document.getElementsByClassName('ganteview-header')[0].style.left = -(e.target.scrollLeft) + 'px'
85
85
  this.$parent.show_calendar = false
86
86
  let scrollEl = e.target
87
+ commitEmit.$emit('gc-scroll', { scrollLeft: scrollEl.scrollLeft, clientWidth: scrollEl.clientWidth })
87
88
  if(scrollEl.scrollHeight <= scrollEl.scrollTop + scrollEl.clientHeight && this.requestBol){
88
89
  this.requestBol = false
89
90
  commitEmit.$emit('on-load')
@@ -186,6 +187,12 @@
186
187
  this.get_top_time(mode, this.first_day, time, all_time, time_mode)
187
188
  this.time_1px = time;
188
189
  this.time_mode = time_mode;
190
+ this.$nextTick(() => {
191
+ const el = this.$el && this.$el.querySelector ? this.$el.querySelector('.ganteview') : null
192
+ if(el){
193
+ commitEmit.$emit('gc-scroll', { scrollLeft: el.scrollLeft, clientWidth: el.clientWidth })
194
+ }
195
+ })
189
196
  return {time: time, start_time: start_time}
190
197
  },
191
198
  /**
@@ -1,11 +1,6 @@
1
1
  <!--中间分割线,分割左侧表格和右侧图表-->
2
2
  <template>
3
3
  <div @mousedown="down" ref="split_liu" :style="{left:Number(left)?left+'px':left}" class="gante-split-liu">
4
- <!--<div class="gante-split-column">-->
5
- <!--<div></div>-->
6
- <!--<div></div>-->
7
- <!--<div></div>-->
8
- <!--</div>-->
9
4
  <div v-show="show_split" :style="{left:split_resize_left+'px'}" class="gante-split-liu-resize"></div>
10
5
  </div>
11
6
  </template>
@@ -17,10 +12,16 @@
17
12
  return{
18
13
  show_split:false,
19
14
  split_resize_left:0,
20
- mouseDown:false
15
+ mouseDown:false,
16
+ rafId: 0,
17
+ lastResizePayload: null,
21
18
  }
22
19
  },
23
- props:['left','th_data'],
20
+ props:{
21
+ left: [Number,String],
22
+ th_data: Object,
23
+ onSplitResize: Function,
24
+ },
24
25
  mounted(){
25
26
 
26
27
  },
@@ -51,7 +52,6 @@
51
52
  let _left = e.pageX - this.$refs.split_liu.getBoundingClientRect().left +3, // 移动的距离
52
53
  _width = document.getElementsByClassName('gante-table-box')[0].offsetWidth, // 表格的宽度
53
54
  _width_gc = document.getElementsByClassName('ganteview-box')[0].offsetWidth; // 图表的宽度
54
- console.log(_left)
55
55
  if(_left + _width <= 480){
56
56
  _left = 480 - _width
57
57
  }
@@ -65,7 +65,10 @@
65
65
  doc_up(){
66
66
  if(this.mouseDown){
67
67
  var _body = document.getElementsByTagName('body')[0]
68
- this.$parent.tabe_width = this.split_resize_left + document.getElementsByClassName('gante-table-box')[0].offsetWidth;
68
+ const baseTableWidth = document.getElementsByClassName('gante-table-box')[0].offsetWidth;
69
+ const baseGanttWidth = document.getElementsByClassName('ganteview-box')[0].offsetWidth;
70
+ const delta = this.split_resize_left;
71
+ this.$parent.tabe_width = delta + baseTableWidth;
69
72
  this.find_attr(this.$parent.tabe_width,this.th_data)
70
73
  this.show_split = false
71
74
  this.split_resize_left = 0
@@ -74,8 +77,34 @@
74
77
  _body.style.cursor = null
75
78
  document.removeEventListener('mousemove',this.doc_move,false)
76
79
  document.removeEventListener('mouseup',this.doc_up,false)
80
+
81
+ this.emitResize(this.$parent.tabe_width, baseGanttWidth - delta, true)
77
82
  }
78
83
  },
84
+ emitResize(tableWidth,ganttWidth,isFinal){
85
+ if(!isFinal){
86
+ return
87
+ }
88
+ if(typeof this.onSplitResize !== 'function'){
89
+ return
90
+ }
91
+ this.lastResizePayload = {
92
+ tableWidth,
93
+ ganttWidth,
94
+ isFinal,
95
+ }
96
+ if(this.rafId){
97
+ return
98
+ }
99
+ this.rafId = requestAnimationFrame(() => {
100
+ this.rafId = 0
101
+ if(!this.lastResizePayload){
102
+ return
103
+ }
104
+ this.onSplitResize(this.lastResizePayload)
105
+ this.lastResizePayload = null
106
+ })
107
+ },
79
108
  down(){
80
109
  this.mouseDown = true
81
110
  this.show_split = true
@@ -33,6 +33,8 @@
33
33
  },
34
34
  proxy_left:0,
35
35
  show_proxy:false,
36
+ rafId: 0,
37
+ lastResizePayload: null,
36
38
  }
37
39
  },
38
40
  props:{
@@ -40,8 +42,46 @@
40
42
  data:Array,
41
43
  showLoading:Boolean,
42
44
  cellSlots: Object,
45
+ onColumnResize: Function,
43
46
  },
44
47
  methods:{
48
+ collectColumnWidths(changedKey,changedWidth){
49
+ const columnWidths = {}
50
+ let tableWidth = 0
51
+ for(let key in this.th_data){
52
+ const th = this.th_data[key] || {}
53
+ if(th.show === false){
54
+ continue
55
+ }
56
+ let width = th.width ? Number(th.width) : 80
57
+ if(changedKey && key === changedKey && typeof changedWidth === 'number' && !Number.isNaN(changedWidth)){
58
+ width = changedWidth
59
+ }
60
+ columnWidths[key] = width
61
+ tableWidth += width
62
+ }
63
+ return { columnWidths, tableWidth }
64
+ },
65
+ emitColumnResize(payload){
66
+ if(!payload || payload.isFinal !== true){
67
+ return
68
+ }
69
+ if(typeof this.onColumnResize !== 'function'){
70
+ return
71
+ }
72
+ this.lastResizePayload = payload
73
+ if(this.rafId){
74
+ return
75
+ }
76
+ this.rafId = requestAnimationFrame(() => {
77
+ this.rafId = 0
78
+ if(!this.lastResizePayload){
79
+ return
80
+ }
81
+ this.onColumnResize(this.lastResizePayload)
82
+ this.lastResizePayload = null
83
+ })
84
+ },
45
85
  //排序
46
86
  sortCaret(mode,key){
47
87
  let cla = 'asc',assign_key = key
@@ -193,6 +233,12 @@
193
233
  if(str < _width){
194
234
  this.$parent.tabe_width = (str + 2) <= 480 ? 480 : (str + 2) + 'px';
195
235
  }
236
+ const widths = this.collectColumnWidths()
237
+ this.emitColumnResize({
238
+ changedKey: this.tTD.current_index,
239
+ isFinal: true,
240
+ ...widths
241
+ })
196
242
 
197
243
  // 初始化所有的值
198
244
  this.tTD.mouseDown = false
@@ -18,7 +18,8 @@
18
18
  @sort="sortGunter"
19
19
  :th_data="th_data"
20
20
  :showLoading="showLoading"
21
- :data="ganteData">
21
+ :data="ganteData"
22
+ :onColumnResize="onColumnResize">
22
23
 
23
24
  </gante-table>
24
25
  </div>
@@ -34,7 +35,7 @@
34
35
  :toast-render="toastRender"
35
36
  :toast-class="toastClass"></gante-gc>
36
37
  </div>
37
- <gante-split :left="tabe_width" :th_data="th_data"></gante-split>
38
+ <gante-split :left="tabe_width" :th_data="th_data" :onSplitResize="onSplitResize"></gante-split>
38
39
  </div>
39
40
  <!--日历-->
40
41
  <calendar :left="calendar_left" :choose_date="checkDate" v-model="show_calendar" @change="chooseDate"
@@ -81,6 +82,8 @@
81
82
  onClick: () => {},
82
83
  onLoad: () => {},//懒加载
83
84
  onDragChangeTime: () => {}, // 拖动改变时间
85
+ onSplitResize: () => {}, // 拖动分割线改变宽度回调
86
+ onColumnResize: () => {}, // 拖动列宽回调
84
87
  dropdownOptions: [
85
88
  { value: 1, label: '日' },
86
89
  { value: 2, label: '周' },
package/gante.vue CHANGED
@@ -19,6 +19,7 @@
19
19
  :th_data="th_data"
20
20
  :showLoading="showLoading"
21
21
  :data="ganteData"
22
+ :onColumnResize="onColumnResize"
22
23
  :cell-slots="$scopedSlots">
23
24
 
24
25
  </gante-table>
@@ -35,7 +36,7 @@
35
36
  :toast-render="toastRender"
36
37
  :toast-class="toastClass"></gante-gc>
37
38
  </div>
38
- <gante-split :left="tabe_width" :th_data="th_data"></gante-split>
39
+ <gante-split :left="tabe_width" :th_data="th_data" :onSplitResize="onSplitResize"></gante-split>
39
40
  </div>
40
41
  <!--日历-->
41
42
  <calendar :left="calendar_left" :choose_date="checkDate" v-model="show_calendar" @change="chooseDate"
@@ -84,6 +85,8 @@
84
85
  onClick: () => {},
85
86
  onLoad: () => {},//懒加载
86
87
  onDragChangeTime: () => {}, // 拖动改变时间
88
+ onSplitResize: () => {}, // 拖动分割线改变宽度回调
89
+ onColumnResize: () => {}, // 拖动列宽回调
87
90
  dropdownOptions: [
88
91
  { value: 1, label: '日' },
89
92
  { value: 2, label: '周' },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gunter-kgd",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "main": "gante-vue.common.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"