Skip to content

Commit a21f1a9

Browse files
authored
Merge pull request #112 from Tobin1990/master
add timecycleselect
2 parents 6a8243a + 6af6eb9 commit a21f1a9

File tree

10 files changed

+518
-1
lines changed

10 files changed

+518
-1
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@
100100
"dependencies": {
101101
"async-validator": "^3.2.4",
102102
"axios": "^0.18.1",
103+
"timedivselect": "^0.1.4",
103104
"v-click-outside": "^2.1.3"
104105
},
105106
"pre-commit": [
Lines changed: 321 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,321 @@
1+
<template>
2+
<div :class="classes">
3+
<div id="timecontainer" class="timecontainer" @mousedown="mousedownfn">
4+
<div class="swrap">
5+
<div class="leftweek">
6+
<div v-for="(item,index) in computedyAxisName" :key="index" class="weekname">{{ item }}</div>
7+
</div>
8+
<div class="mainbox">
9+
<div class="selectall">
10+
<input id="selectAllid" type="checkbox" @click="selectAllornot">
11+
<label for="selectAllid" style="cursor:pointer;padding-left:5px;">全选</label>
12+
</div>
13+
<div class="righttips">
14+
<div v-for="(item,index) in computedTipName" :key="index" class="tiplist">
15+
<span :class="{'current': !index}" />{{ item }}
16+
</div>
17+
</div>
18+
<div class="bottomtime">
19+
<div v-for="(item,index) in computedxAxisName" :key="index" class="timeList">{{ item }}</div>
20+
</div>
21+
<div class="boxlist" :style="itemStyleWidth">
22+
<div
23+
v-for="(item,index) in timeList"
24+
:key="index"
25+
class="list"
26+
:title="`${timeSetp}小时`"
27+
:class="{selected:item==1}"
28+
@click="setcurrent(item,index)"
29+
/>
30+
</div>
31+
</div>
32+
</div>
33+
</div>
34+
</div>
35+
</template>
36+
<script>
37+
import {classPrefix} from '../utils/const';
38+
import {getValue} from '../utils/processValue';
39+
export default {
40+
inject: ['form'],
41+
props: {
42+
field: {
43+
type: Object,
44+
required: true
45+
}
46+
},
47+
data() {
48+
return {
49+
isSelect: true,
50+
timeSetp: 1,
51+
selectBoxDashed: null,
52+
startX: null,
53+
startY: null,
54+
initx: null,
55+
scrollX: null,
56+
scrollY: null,
57+
inity: null
58+
};
59+
},
60+
computed: {
61+
classes() {
62+
return `${classPrefix}-${this.field.type.toLowerCase()}`;
63+
},
64+
itemStyleWidth() {
65+
let width = this.field.width;
66+
// 兼容老版本的字符串数值,如果是数值字符串,则转为int
67+
if (typeof width === 'string' && /^\d+$/.test(width)) {
68+
width = parseInt(width);
69+
}
70+
return {
71+
width: typeof width === 'string' ? width : width + 'px'
72+
};
73+
},
74+
timexAxisNum() {
75+
return this.field.xAxisNum || 24;
76+
},
77+
timeyAxisNum() {
78+
return this.field.yAxisNum || 7;
79+
},
80+
computedTipName() {
81+
return this.field.tipsName || [];
82+
},
83+
computedyAxisName() {
84+
return this.field.yAxisName || [];
85+
},
86+
computedxAxisName() {
87+
return this.field.xAxisName || [];
88+
},
89+
computedTimeArray() {
90+
let timeArray = [];
91+
for (let i = 0; i < this.timexAxisNum * this.timeyAxisNum; i++) {
92+
timeArray.push('0');
93+
}
94+
return timeArray.join('');
95+
},
96+
computedValue () {
97+
return getValue({
98+
originModel: this.form.model,
99+
model: this.field.model
100+
}) || '';
101+
},
102+
timeList() {
103+
return this.computedValue !== '' ? this.computedValue.split('') : this.computedTimeArray.split('');
104+
}
105+
},
106+
mounted() {
107+
// eslint-disable-next-line no-console
108+
// console.log(this.timeList);
109+
},
110+
methods: {
111+
clearBubble(e) {
112+
if (e.stopPropagation) {
113+
e.stopPropagation();
114+
} else {
115+
e.cancelBubble = true;
116+
}
117+
if (e.preventDefault) {
118+
e.preventDefault();
119+
} else {
120+
e.returnValue = false;
121+
}
122+
},
123+
mousedownfn(e) {
124+
// 创建选框节点
125+
this.selectBoxDashed = document.createElement('div');
126+
this.selectBoxDashed.className = 'select-box-dashed';
127+
document.body.appendChild(this.selectBoxDashed);
128+
this.scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
129+
this.scrollY = document.documentElement.scrollTop || document.body.scrollTop;
130+
131+
// 设置选框的初始位置
132+
this.startX = e.x + this.scrollX || e.clientX + this.scrollX;
133+
this.startY = e.y + this.scrollY || e.clientY + this.scrollY;
134+
this.selectBoxDashed.style.cssText = `left:${this.startX}px;top:${this.startY}px`;
135+
// 清除事件冒泡、捕获
136+
this.clearBubble(e);
137+
document.getElementById('timecontainer').addEventListener('mousemove', this.mousemovefn);
138+
document.body.addEventListener('mouseup', this.mouseUpfn);
139+
},
140+
mousemovefn(e) {
141+
// 设置选框可见
142+
this.selectBoxDashed.style.display = 'block';
143+
// 根据鼠标移动,设置选框的位置、宽高
144+
this.initx = e.x + this.scrollX || e.clientX + this.scrollX;
145+
this.inity = e.y + this.scrollY || e.clientY + this.scrollY;
146+
// 暂存选框的位置及宽高,用于将 select-item 选中
147+
this.left = Math.min(this.initx, this.startX);
148+
this.top = Math.min(this.inity, this.startY);
149+
this.width = Math.abs(this.initx - this.startX);
150+
this.height = Math.abs(this.inity - this.startY);
151+
this.selectBoxDashed.style.left = `${this.left}px`;
152+
this.selectBoxDashed.style.top = `${this.top}px`;
153+
this.selectBoxDashed.style.width = `${this.width}px`;
154+
this.selectBoxDashed.style.height = `${this.height}px`;
155+
let fileDivs = document.getElementsByClassName('list');
156+
for (let i = 0; i < fileDivs.length; i++) {
157+
let itemX_pos = fileDivs[i].getBoundingClientRect().left + this.scrollX;
158+
let itemY_pos = fileDivs[i].getBoundingClientRect().top + this.scrollY;
159+
let condition1 = itemX_pos + fileDivs[i].offsetWidth > this.left;
160+
let condition2 = itemY_pos + fileDivs[i].offsetHeight > this.top;
161+
let condition3 = itemX_pos < this.left + this.width;
162+
let condition4 = itemY_pos < this.top + this.height;
163+
if (condition1 && condition2 && condition3 && condition4) {
164+
fileDivs[i].classList.add('temp-selected');
165+
} else {
166+
fileDivs[i].classList.remove('temp-selected');
167+
}
168+
}
169+
this.clearBubble(e);
170+
},
171+
mouseUpfn(e) {
172+
let timecontainer = document.getElementById('timecontainer');
173+
if (timecontainer !== null) {
174+
timecontainer.removeEventListener('mousemove', this.mousemovefn);
175+
} let selectDom = document.getElementsByClassName('temp-selected');
176+
[].slice.call(selectDom).forEach(item => {
177+
if (item.classList.contains('selected')) {
178+
item.classList.remove('selected');
179+
} else {
180+
item.classList.add('selected');
181+
}
182+
item.classList.remove('temp-selected');
183+
});
184+
if (this.selectBoxDashed) {
185+
try {
186+
this.selectBoxDashed.parentNode.removeChild(this.selectBoxDashed);
187+
} catch (err) {
188+
// console.log(err)
189+
}
190+
}
191+
let fileDivs = document.getElementsByClassName('list');
192+
for (let i = 0; i < fileDivs.length; i++) {
193+
if (fileDivs[i].classList.contains('selected')) {
194+
this.timeList[i] = '1';
195+
} else {
196+
this.timeList[i] = '0';
197+
}
198+
}
199+
this.$emit('triggertime', this.timeList.join(''));
200+
this.clearBubble(e);
201+
},
202+
setcurrent(item, index) {
203+
if (item == 0) {
204+
this.timeList.splice(index, 1, '1');
205+
} else {
206+
this.timeList.splice(index, 1, '0');
207+
}
208+
this.$emit('on-change', this.field.model, this.timeList.join(''), null, this.field);
209+
},
210+
selectAllornot(e) {
211+
this.timeList.forEach((item, index) => {
212+
this.timeList.splice(index, 1, Number(e.target.checked));
213+
});
214+
// console.log(this.timeList.join(''));
215+
this.$emit('on-change', this.field.model, this.timeList.join(''), null, this.field);
216+
217+
}
218+
}
219+
};
220+
</script>
221+
<style>
222+
.timecontainer {
223+
min-width: 500px;
224+
overflow: hidden;
225+
padding-top: 30px;
226+
}
227+
.swrap {
228+
min-width: 500px;
229+
overflow: hidden;
230+
}
231+
.leftweek {
232+
display: inline-block;
233+
width: 50px;
234+
vertical-align: top;
235+
margin-top: 72px;
236+
}
237+
.leftweek .weekname {
238+
width: 50px;
239+
height: 17px;
240+
line-height: 25px;
241+
text-align: center;
242+
font-size: 12px;
243+
}
244+
.mainbox {
245+
display: inline-block;
246+
vertical-align: middle;
247+
padding: 10px 15px 2px 15px;
248+
overflow: hidden;
249+
background-color: #f5f5f5;
250+
}
251+
.boxlist {
252+
border-right: 1px solid #999;
253+
border-bottom: 1px solid #999;
254+
overflow: hidden;
255+
}
256+
.boxlist .list {
257+
float: left;
258+
height: 17px;
259+
width: 17px;
260+
border: 1px solid #999;
261+
border-right: none;
262+
border-bottom: none;
263+
cursor: pointer;
264+
background-color: #fff;
265+
}
266+
.boxlist .list.selected {
267+
background-color: #0099ff;
268+
border-color: #0099ff;
269+
}
270+
.selectall {
271+
float: left;
272+
font-size: 12px;
273+
}
274+
.bottomtime {
275+
clear: both;
276+
}
277+
.righttips {
278+
font-size: 12px;
279+
float: right;
280+
}
281+
.righttips .tiplist {
282+
display: inline-block;
283+
margin-right: 10px;
284+
}
285+
.righttips .tiplist span {
286+
display: inline-block;
287+
position: relative;
288+
top: 3px;
289+
width: 17px;
290+
height: 17px;
291+
background: #fff;
292+
border: 1px solid #999;
293+
margin-right: 3px;
294+
}
295+
.righttips .tiplist span.current {
296+
background: #43a9ed;
297+
border-color: #43a9ed;
298+
}
299+
.timeList {
300+
display: inline-block;
301+
vertical-align: middle;
302+
font-size: 12px;
303+
width: 17px;
304+
text-align: center;
305+
}
306+
.select-box-dashed {
307+
position: absolute;
308+
display: none;
309+
width: 0px;
310+
height: 0px;
311+
padding: 0px;
312+
margin: 0px;
313+
border: 1px dashed #0099ff;
314+
background-color: #c3d5ed;
315+
opacity: 0.5;
316+
filter: alpha(opacity=50);
317+
font-size: 0px;
318+
z-index: 99999;
319+
}
320+
</style>
321+

src/utils/getValidType.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
export const getValidType = function(field) {
23
const type = field.type.toLowerCase();
34
const subtype = field.subtype;
@@ -30,7 +31,7 @@ export const getValidType = function(field) {
3031
return 'string';
3132
}
3233
}
33-
if (type === 'timepicker') {
34+
if (type === 'timepicker' || type === 'timecycleselect') {
3435
if (['timerange'].includes(subtype)){
3536
return 'array';
3637
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// 简单示例
2+
let simple = {
3+
data: {
4+
field: {
5+
type: 'TimeCycleSelect',
6+
model: 'time',
7+
tipsName: ['投放', '不投放'],
8+
yAxisName:['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日'],
9+
xAxisName: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23'],
10+
xAxisNum: 24,
11+
yAxisNum: 7,
12+
width: '409'
13+
},
14+
model: {
15+
time: '000000000000000000000000000000000000000000000000000011111111111111111000000011111111111111111000000011111111111111111000000011111111111111111000000000000000000000000000'
16+
}
17+
}
18+
};
19+
20+
simple.code = `
21+
<script>
22+
const field = ${JSON.stringify(simple.data.field, null, 4)};
23+
const model = ${JSON.stringify(simple.data.model, null, 4)};
24+
export default {
25+
data() {
26+
return {
27+
field,
28+
model
29+
};
30+
}
31+
methods: {
32+
handleFieldChange(model, value) {
33+
console.log(model, value);
34+
}
35+
}
36+
};
37+
<script>
38+
<template>
39+
<Form :model="model">
40+
<FieldGenerator
41+
:field="field"
42+
@on-field-change="handleFieldChange"
43+
/>
44+
</Form>
45+
</template>
46+
`;
47+
48+
export default {
49+
simple
50+
};

0 commit comments

Comments
 (0)