浏览代码

事件列表支持登记时间

seimin 10 月之前
父节点
当前提交
ef604789bc
共有 3 个文件被更改,包括 514 次插入2 次删除
  1. 46 2
      components/IncidentListFilter.vue
  2. 387 0
      components/PyhRdtpicker/PyhRdtpicker.vue
  3. 81 0
      components/PyhRdtpicker/readme.md

+ 46 - 2
components/IncidentListFilter.vue

@@ -19,6 +19,12 @@
19 19
         <text class="name">故障现象</text>
20 20
         <text class="value ellipsis">{{searchData.category ? searchData.category.category : ''}}</text>
21 21
       </view>
22
+      
23
+      <view class="acceptDate" @click="changeIsShowDate()">
24
+        <text class="name">登记时间</text>
25
+        <text class="value ellipsis" v-if="searchData.acceptDate.length">{{searchData.acceptDate[0] || ''}}至{{searchData.acceptDate[1] || ''}}</text>
26
+        <text class="value ellipsis" v-else>全部</text>
27
+      </view>
22 28
     </view>
23 29
     <view class="container_foot">
24 30
       <view class="clear" @click="clear">清除选项</view>
@@ -27,6 +33,13 @@
27 33
         <view class="confirm" @click="confirm">确认</view>
28 34
       </view>
29 35
     </view>
36
+    <PyhRdtpicker
37
+        :show="isShowDate"
38
+        @showchange="showDatechange"
39
+        :value="searchData.acceptDate"
40
+        @change="bindDateChange"
41
+        :themeColor="primaryColor"
42
+    ></PyhRdtpicker>
30 43
   </view>
31 44
   <view class="container" @touchmove.stop.prevent v-else-if="pageData.pageRouter === 'area'">
32 45
     <view class="container_form">
@@ -62,13 +75,17 @@
62 75
   </view>
63 76
   <view class="mask" @touchmove.stop.prevent></view>
64 77
   <view class="line" @touchmove.stop.prevent></view>
78
+  
65 79
 </template>
66 80
 
67 81
 <script setup>
82
+  import PyhRdtpicker from '@/components/PyhRdtpicker/PyhRdtpicker.vue';
68 83
   import { defineEmits, ref, reactive, defineProps } from 'vue'
84
+  import { startOfDay, endOfDay, format, startOfWeek, endOfWeek, add } from 'date-fns'
69 85
   import { onLoad } from '@dcloudio/uni-app'
70 86
   import { useLoginUserStore } from '@/stores/loginUser'
71 87
   import { api_area, api_incidentcategory } from "@/http/api.js"
88
+  import { defaultColor } from '@/static/js/theme.js'
72 89
   
73 90
   const emit = defineEmits(['cancelEmit', 'confirmEmit']);
74 91
   const { evt } = defineProps({
@@ -79,6 +96,12 @@
79 96
   });
80 97
   const loginUserStore = useLoginUserStore();
81 98
   
99
+  // 主题颜色
100
+  const primaryColor = ref(defaultColor)
101
+  
102
+  // 登记时间
103
+  const isShowDate = ref(false)
104
+  
82 105
   const tabs = reactive([
83 106
     // { name: '全部事件', value: 'all' },
84 107
     { name: '待我处理', value: 'todoingAll' },
@@ -98,8 +121,20 @@
98 121
     selected: 'todoingAll',
99 122
     area: {id: 0, area: '全部'},
100 123
     category: {id: 0, category: '全部'},
124
+    acceptDate: [format(startOfWeek(add(new Date(), { weeks: -1}), { weekStartsOn: 1 }), 'yyyy-MM-dd'), format(endOfWeek(add(new Date(), { weeks: -1}), { weekStartsOn: 1 }), 'yyyy-MM-dd')],
101 125
   })
102 126
   
127
+  // 显示登记时间
128
+  function showDatechange(){
129
+    isShowDate.value = !isShowDate.value;
130
+  }
131
+  
132
+  // 登记时间确定
133
+  function bindDateChange(e){
134
+    console.log(e);
135
+    searchData.acceptDate = e;
136
+  }
137
+  
103 138
   // 点击tab
104 139
   function clickTab(tab){
105 140
     searchData.selected = tab.value;
@@ -123,6 +158,8 @@
123 158
     searchData.selected = 'todoingAll';
124 159
     searchData.area = {id: 0, area: '全部'};
125 160
     searchData.category = {id: 0, category: '全部'};
161
+    searchData.acceptDate = [format(startOfWeek(add(new Date(), { weeks: -1}), { weekStartsOn: 1 }), 'yyyy-MM-dd'), format(endOfWeek(add(new Date(), { weeks: -1}), { weekStartsOn: 1 }), 'yyyy-MM-dd')];
162
+    console.log(searchData.acceptDate)
126 163
   }
127 164
   
128 165
   // 取消
@@ -225,6 +262,11 @@
225 262
     }
226 263
   }
227 264
   
265
+  // 显示登记时间
266
+  function changeIsShowDate(type){
267
+    isShowDate.value = true;
268
+  }
269
+  
228 270
   onLoad((option) => {
229 271
     // searchData.hospital = evt.hospital;
230 272
     for (let i = 0; i < loginUserStore.loginUser.menu.length; i++) {
@@ -236,6 +278,7 @@
236 278
     searchData.selected = evt.selected;
237 279
     searchData.area = evt.area;
238 280
     searchData.category = evt.category;
281
+    searchData.acceptDate = evt.acceptDate;
239 282
   })
240 283
 </script>
241 284
 
@@ -261,7 +304,7 @@
261 304
 }
262 305
 .container{
263 306
   position: fixed;
264
-  left: 150rpx;
307
+  left: 125rpx;
265 308
   top: 0;
266 309
   right: 0;
267 310
   bottom: 0;
@@ -353,7 +396,8 @@
353 396
   }
354 397
   
355 398
   .area,
356
-  .category{
399
+  .category,
400
+  .acceptDate{
357 401
     display: flex;
358 402
     justify-content: space-between;
359 403
     align-items: center;

+ 387 - 0
components/PyhRdtpicker/PyhRdtpicker.vue

@@ -0,0 +1,387 @@
1
+<template>
2
+	<view class="rpickerBox">
3
+		<view :class="{'pickerMask':showPicker}" @click="maskClick"  @touchmove.stop.prevent="returnHandle">
4
+			<view class="r-dtpicker" :class="{'r-dtpicker-show':showPicker}">
5
+				<view class="rdtBtn" @touchmove.stop.prevent="returnHandle" @tap.stop="returnHandle">
6
+					<view @click="pickerCancel">取消</view>
7
+					<view :style="{color:themeColor}" @click="pickerConfirm">确定</view>
8
+				</view>
9
+				<view class="rangeBox" @touchmove.stop.prevent="returnHandle" @tap.stop="returnHandle">
10
+					<view :class="['inputView',{'inputEmpty':!startDate}]" :style="{color:themeColor,'border-color':themeColor,opacity:dateType=='startDate'?1:.5}" @tap="changeDateType('startDate')">{{startDate||'开始时间'}}</view>
11
+					至
12
+					<view :class="['inputView',{'inputEmpty':!endDate}]" :style="{color:themeColor,'border-color':themeColor,opacity:dateType=='endDate'?1:.5}" @tap="changeDateType('endDate')">{{endDate||'结束时间'}}</view>
13
+				</view>
14
+				<picker-view indicator-style="height: 40px;" class="mpvue-picker-view" :value="pickerValue" @change="pickerChangeMul">
15
+					<picker-view-column>
16
+						<view class="picker-item" v-for="(item,index) in yearArr" :key="index">{{item}}</view>
17
+					</picker-view-column>
18
+					<picker-view-column v-if="fields!='year'">
19
+						<view class="picker-item" v-for="(item,index) in monthArr" :key="index">{{item}}</view>
20
+					</picker-view-column>
21
+					<picker-view-column v-if="fields=='day'">
22
+						<view class="picker-item" v-for="(item,index) in dayArr" :key="index">{{item}}</view>
23
+					</picker-view-column>
24
+				</picker-view>
25
+			</view>
26
+		</view>
27
+	</view>
28
+</template>
29
+
30
+<script>
31
+	export default {
32
+		name: 'range-dtpicker',
33
+		props: {
34
+			//粒度
35
+			fields:{
36
+			  type: String,
37
+			  default: 'day'
38
+			},
39
+			/**
40
+			 * picker允许选中的最小值
41
+			 */
42
+			start: {
43
+			  type: String,
44
+			  default: '1900-01-01'
45
+			},
46
+			/**
47
+			 * picker允许选中的最大值
48
+			 */
49
+			end: {
50
+			  type: String,
51
+			  default: '2200-12-01'
52
+			},
53
+			/**
54
+			 * picker默认展示的值
55
+			 */
56
+			value: {
57
+                type: Array,
58
+                default(){
59
+					return [0,0]
60
+				}
61
+            },
62
+			//是否显示
63
+			show: {
64
+				type: Boolean,
65
+				default: false
66
+			},
67
+			/**
68
+			主题色
69
+			*/
70
+			themeColor:{
71
+			  type: String,
72
+			  default: '#4C83D6'
73
+			}
74
+		},
75
+		created() {
76
+			this.init()
77
+		},
78
+		data() {
79
+			return {
80
+				showPicker: this.show,
81
+				dayArr:[],
82
+				pickerValue:this.fields=='year'?[0]:this.fields=='month'?[0,0]:[0,0,0],
83
+				dateType:"startDate",
84
+				startDate:'',
85
+				endDate:""
86
+			};
87
+		},
88
+		watch: {
89
+			value(value){
90
+				this.value=value;
91
+				this.init()
92
+			},
93
+			show(isShow) {
94
+				this.showPicker = isShow;
95
+			},
96
+			start(){
97
+				this.init()
98
+			},
99
+			end(){
100
+				this.init()
101
+			}
102
+		},
103
+		computed: {
104
+			yearArr(){
105
+				var arr = [],start = parseInt(this.start.slice(0,4)),end=parseInt(this.end.slice(0,4));
106
+				for(var i=0;i<=end-start;i++){
107
+					arr.push(start+i)
108
+				}
109
+				return arr;
110
+			},
111
+			monthArr(){
112
+				var arr = [];
113
+				for(var i=1;i<=12;i++){
114
+					var v = i;
115
+					if(v<10)v="0"+v;
116
+					if(this.start.length>4&&this.end.length>4&&(this.start.slice(0,4)==this.end.slice(0,4))){
117
+						if(parseInt(v)>=this.start.slice(5,7)&&parseInt(v)<=this.end.slice(5,7)){
118
+							arr.push(v.toString())
119
+						}
120
+					}else{
121
+						arr.push(v.toString())
122
+					}
123
+				}
124
+				return arr;
125
+			}
126
+		},
127
+		methods:{
128
+			returnHandle(){},
129
+			init(){
130
+				var that = this,pickerValue="";
131
+				if((this.fields=='year'&&this.start.length!=4)||(this.fields=='month'&&this.start.length!=7)||(this.fields=='day'&&this.start.length!=10)){
132
+					console.error("最小值格式与粒度格式不符");return;
133
+				}else if((this.fields=='year'&&this.end.length!=4)||(this.fields=='month'&&this.end.length!=7)||(this.fields=='day'&&this.end.length!=10)){
134
+					console.error("最大值格式与粒度格式不符");return;
135
+				}
136
+				var start=this.fields=='year'?this.start.slice(0,4):this.fields=='month'?this.start.slice(0,7):this.start,
137
+					end=this.fields=='year'?this.end.slice(0,4):this.fields=='month'?this.end.slice(0,7):this.end;
138
+				if(!start||!end){
139
+					console.error("时间不能为空");return;
140
+				}else if(start>end){
141
+					console.error("结束时间必须大等于开始时间");return;
142
+				}
143
+				if(this.value[0]){
144
+					if((this.fields=='year'&&this.value[0].length!=4)||(this.fields=='month'&&this.value[0].length!=7)||(this.fields=='day'&&this.value[0].length!=10)){
145
+						console.error("默认值格式与粒度格式不符");return;
146
+					}
147
+					this.startDate=this.value[0];
148
+					if(this.value[1]){
149
+						if((this.fields=='year'&&this.value[1].length!=4)||(this.fields=='month'&&this.value[1].length!=7)||(this.fields=='day'&&this.value[1].length!=10)){
150
+							console.error("默认值格式与粒度格式不符");return;
151
+						}
152
+						this.endDate=this.value[1];
153
+						this.dateType="endDate";
154
+						if(this.fields=='day')this.dayArr=this.getMonthDay(this.value[1].slice(0,4),this.value[1].slice(5,7));
155
+						pickerValue=this.getIndex(this.value[1]);
156
+					}else{
157
+						this.dateType="startDate";
158
+						if(this.fields=='day')this.dayArr=this.getMonthDay(this.value[0].slice(0,4),this.value[0].slice(5,7));
159
+						pickerValue=this.getIndex(this.value[0]);
160
+					}
161
+				}else{
162
+					this.startDate=start;
163
+					pickerValue=this.getIndex(start);
164
+					if(this.fields=='day')this.dayArr=this.getMonthDay(start.slice(0,4),start.slice(5,7));
165
+				}
166
+				if(pickerValue)setTimeout(function(){that.pickerValue=pickerValue},20)
167
+			},
168
+			maskClick(){
169
+				this.$emit("showchange",false);
170
+			},
171
+			pickerConfirm(){
172
+				if(this.endDate<this.startDate){
173
+					uni.showToast({
174
+						title:"结束时间不得小于开始时间",
175
+						icon:"none",
176
+						mask:true
177
+					})
178
+					return;
179
+				}
180
+				this.$emit("change",[this.startDate,this.endDate]);
181
+				this.$emit("showchange",false);
182
+			},
183
+			pickerCancel(){
184
+				this.$emit("cancel");
185
+				this.$emit("showchange",false);
186
+			},
187
+			changeDateType(dateType){
188
+				var that = this;
189
+				this.dateType=dateType;
190
+				if(this[dateType]){
191
+					this.pickerValue=this.getIndex(this[dateType])
192
+				}else{
193
+					var dateTxt=this.fields=='year'?this.yearArr[this.pickerValue[0]]:this.fields=='month'?this.yearArr[this.pickerValue[0]]+'-'+this.monthArr[this.pickerValue[1]]:this.yearArr[this.pickerValue[0]]+'-'+this.monthArr[this.pickerValue[1]]+'-'+this.dayArr[this.pickerValue[2]];
194
+					this[dateType]=dateTxt;
195
+					this.pickerValue=this.fields=='year'?[this.pickerValue[0]]:this.fields=='month'?[this.pickerValue[0],this.pickerValue[1]]:[this.pickerValue[0],this.pickerValue[1],this.pickerValue[2]];
196
+				}
197
+			},
198
+			pickerChangeMul(e){
199
+				var that=this,val = e.detail.value,dateTxt="";
200
+				if(this.fields=='day'&&(val[0]!=this.pickerValue[0]||val[1]!=this.pickerValue[1])){
201
+					this.dayArr=this.getMonthDay(this.yearArr[val[0]],this.monthArr[val[1]])
202
+					function returnMax(){
203
+						if(!that.dayArr[val[2]]){
204
+							val[2]=(val[2]-1)
205
+							returnMax()
206
+						}
207
+					}
208
+					returnMax()
209
+				}
210
+				dateTxt=this.yearArr[val[0]]+'-'+this.monthArr[val[1]]+'-'+this.dayArr[val[2]];
211
+				this[this.dateType]=this.fields=='year'?dateTxt.slice(0,4):this.fields=='month'?dateTxt.slice(0,7):dateTxt;
212
+				this.pickerValue=this.getIndex(this[this.dateType]);
213
+			},
214
+			getIndex(value){
215
+				var year = value.slice(0,4),month=value.slice(5,7),day=value.slice(8,10),y=0,m=0,d=0;
216
+				for(var i in this.yearArr){
217
+					if(year==this.yearArr[i]){
218
+						y=i;break;
219
+					}
220
+				}
221
+				for(var i in this.monthArr){
222
+					if(month==this.monthArr[i]){
223
+						m=i;break;
224
+					}
225
+				}
226
+				for(var i in this.dayArr){
227
+					if(day==this.dayArr[i]){
228
+						d=i;break;
229
+					}
230
+				}
231
+				var value = [];
232
+				switch (this.fields){
233
+					case 'year':value = [Number(y)]
234
+						break;
235
+					case 'month':value = [Number(y),Number(m)]
236
+						break;
237
+					default:value = [Number(y),Number(m),Number(d)]
238
+						break;
239
+				}
240
+				return value;
241
+			},
242
+			withData: (num) => {
243
+				let param = parseInt(num);
244
+			  return param < 10 ? '0' + param : '' + param;
245
+			},
246
+			getLoopArray(start, end,specialDay){
247
+			  var start = start || 0;
248
+			  var end = end || 1;
249
+			  var array = [];
250
+				if(specialDay){
251
+					array=specialDay;
252
+					return array;
253
+				}
254
+			  for (var i = start; i <= end; i++) {
255
+			    array.push(this.withData(i));
256
+			  }
257
+			  return array;
258
+			},
259
+			getMonthDay(year, month,specialDay){
260
+			  var flag = year % 400 == 0 || (year % 4 == 0 && year % 100 != 0), array = null;
261
+			
262
+			  switch (month) {
263
+			    case '01':
264
+			    case '03':
265
+			    case '05':
266
+			    case '07':
267
+			    case '08':
268
+			    case '10':
269
+			    case '12':
270
+			      array = this.getLoopArray(1, 31,specialDay)
271
+			      break;
272
+			    case '04':
273
+			    case '06':
274
+			    case '09':
275
+			    case '11':
276
+			      array = this.getLoopArray(1, 30,specialDay)
277
+			      break;
278
+			    case '02':
279
+			      array = flag ? this.getLoopArray(1, 29,specialDay) : this.getLoopArray(1, 28,specialDay)
280
+			      break;
281
+			    default:
282
+			      array = '月份格式不正确,请重新输入!'
283
+			  }
284
+			  return array;
285
+			}
286
+		}
287
+	}
288
+</script>
289
+
290
+<style>
291
+    .pickerMask {
292
+        position: fixed;
293
+        z-index: 998;
294
+        top: 0;
295
+        right: 0;
296
+        left: 0;
297
+        bottom: 0;
298
+        background: rgba(0, 0, 0, 0.6);
299
+    }
300
+
301
+    .r-dtpicker {
302
+        position: fixed;
303
+        bottom: 0;
304
+        left: 0;
305
+        width: 100%;
306
+        transition: all 0.3s ease;
307
+        transform: translateY(100%);
308
+        z-index: 998;
309
+    }
310
+	
311
+    .r-dtpicker-show {
312
+        transform: translateY(0);
313
+    }
314
+    
315
+    .rdtBtn {
316
+        display: flex;
317
+        padding: 9px 15px;
318
+        background-color: #fff;
319
+        position: relative;
320
+        text-align: center;
321
+        font-size: 17px;
322
+    }
323
+    
324
+    .rdtBtn:after {
325
+        content: ' ';
326
+        position: absolute;
327
+        left: 0;
328
+        bottom: 0;
329
+        right: 0;
330
+        height: 1px;
331
+        border-bottom: 1px solid #e5e5e5;
332
+        color: #e5e5e5;
333
+        transform-origin: 0 100%;
334
+        transform: scaleY(0.5);
335
+    }
336
+    
337
+    .rdtBtn view{
338
+        display: block;
339
+        flex: 1;
340
+        color: #1aad19;
341
+    }
342
+    
343
+    .rdtBtn view:first-child {
344
+        text-align: left;
345
+        color: #888;
346
+    }
347
+    
348
+    .rdtBtn view:last-child {
349
+        text-align: right;
350
+    }
351
+    
352
+    .picker-item {
353
+        text-align: center;
354
+        line-height: 40px;
355
+        font-size: 16px;
356
+    }
357
+    
358
+    .mpvue-picker-view {
359
+        position: relative;
360
+        bottom: 0;
361
+        left: 0;
362
+        width: 100%;
363
+        height: 238px;
364
+        background-color: rgba(255, 255, 255, 1);
365
+    }
366
+	.rangeBox{
367
+		background: #fff;
368
+		display: flex;
369
+		justify-content: center;
370
+		padding: 15px 0;
371
+		font-size: 16px;
372
+		align-items: center;
373
+	}
374
+	.rangeBox .inputView{
375
+		white-space: nowrap;
376
+		min-width: 196upx;
377
+		padding: 8rpx;
378
+		margin: 0 10px;
379
+		text-align: center;
380
+		align-items: center;
381
+		min-height: auto;
382
+		border-bottom: 1px solid #000;
383
+	}
384
+	.rangeBox .inputView.inputEmpty{
385
+		color: #999!important;
386
+	}
387
+</style>

+ 81 - 0
components/PyhRdtpicker/readme.md

@@ -0,0 +1,81 @@
1
+### pyh-rdtPicker 日期区间选择器
2
+
3
+可进行多粒度的时间选择器,组件名:``pyh-rdtpicker``,代码块: rangeDatePick。
4
+
5
+**使用方式:**
6
+
7
+在 ``script`` 中引用组件 
8
+
9
+```javascript
10
+import rangeDatePick from '@/components/pyh-rdtpicker/pyh-rdtpicker.vue';
11
+export default {
12
+    components: {rangeDatePick}
13
+}
14
+```
15
+
16
+在 ``template`` 中使用组件
17
+
18
+```html
19
+<rangeDatePick 
20
+	:show="isShow"
21
+	@showchange="showchange"
22
+	:start="start"
23
+	:end="end"
24
+	:value="value"
25
+	@change="bindChange"
26
+	@cancel="bindCancel"
27
+	themeColor="#4C83D6"
28
+	fields="month"
29
+></rangeDatePick>
30
+```
31
+
32
+**pdtPicker 属性说明:**
33
+
34
+|属性名		|类型	|默认值	                    |说明					|
35
+|---		|----	|---	                    |---					|
36
+|themeColor	|String	|'#4C83D6'	            	|主题色					|
37
+|start		|String	|'1900-01-01'				|限制选择器选择的最小时间	(只支持年限制),粒度格式和value格式要相符,否则会有错误提示|
38
+|end		|String	|'2200-12-01'				|限制选择器选择的最大时间(只支持年限制),粒度格式和value格式要相符,否则会有错误提示|
39
+|value		|Array	|''	                        |当前日期选择器显示的时间	,粒度格式和value格式要相符,否则会又错误提示|
40
+|fields		|String	|'day'	               		|当前日期选择器粒度:year/month/day|
41
+
42
+
43
+**value 值说明:**
44
+
45
+|值 		|类型	|说明					|
46
+|---		|----	|---					|
47
+|[]			|Array	|当前日期选择器为开始时间的默认值			|
48
+|['1900-01-01']	|Array	|当前日期选择器开始时间为1900-01-01			|
49
+|['1900-01-01','2010-12-01'] |Array	|当前日期选择器开始时间为1900-01-01,结束时间为2010-12-01|
50
+
51
+**事件说明:**
52
+
53
+|事件名称	|说明		|
54
+|---|---|
55
+|showchange	|必传,用于控制显示隐藏|
56
+|change	|时间选择器点击【确定】按钮时时触发的事件,参数为选择器的当前的 value|
57
+|cancel	|时间选择器点击【取消】按钮时时触发的事件|
58
+
59
+**showchange事件说明:**
60
+
61
+showchange(){
62
+	this.isShow=!this.isShow;
63
+}
64
+
65
+**更新记录:**
66
+
67
+1.0.6:添加动态修改start和end,示例项目由新增注释</br>
68
+
69
+1.0.5:修复月份切换时,day存在显示undefined的问题;修复小程序value设置后滚动位置不对的问题</br>
70
+
71
+1.0.4:修复滚动穿透;修改默认fields为day,添加了同年限制月份(start和end同年,有月份限制),改正作者名与组件名字</br>
72
+
73
+1.0.3:修复动态的value不能赋值问题;修复end值的可选值与实际填入的end值小一年问题</br>
74
+
75
+1.0.2:优化了开始日期和结束日期的切换,当前版本切换时会显示更合适的日期;添加了粒度选择,现支持year/month/day;修复了demo的getDate -60年的获取问题</br>
76
+		
77
+1.0.1:新增组件——日期区间选择器
78
+
79
+**感谢:**
80
+
81
+> 有更多优化建议和需求,请联系作者panyh。谢谢!