Explorar el Código

维保列表 维保详情 报修列表

tongfeng hace 2 años
padre
commit
b90648a0af

+ 6 - 0
lib/common/utils/ConstantString.dart

@@ -10,8 +10,11 @@ class ConstantString {
   static const String deviceManageText = "设备管理";
 
   static const String patrolJobText = "巡检任务";
+  static const String maintJobText = "维保任务";
+  static const String repairJobText = "报修管理";
 
   static const String patrolJobTitle = "巡检任务来自于'巡检计划管理',计划信息请登录pc端查看";
+  static const String maintJobTitle = "维保任务来自于'维保计划管理',计划信息请登录pc端查看";
 
 
   static const String loadingText = "努力加载中···";
@@ -27,4 +30,7 @@ class ConstantString {
   static const String cancel = "取消";
 
   static const String query = "查询";
+  static const String close_job = "关闭任务";
+
+  static const String login_maint = "登记维保";
 }

+ 37 - 0
lib/model/ImgVO.dart

@@ -0,0 +1,37 @@
+import 'package:json2dart_safe/json2dart.dart';
+
+class FileUrls {
+  int? imgId;
+  String? url;
+  int? step;
+
+  @override
+  String toString(){
+    return 'FilrUrls{imgId: $imgId,url: $url,step: $step}';
+  }
+
+  FileUrls({
+    this.imgId,
+    this.url,
+    this.step,
+  });
+
+  Map<String, dynamic> toJson() {
+    return Map<String, dynamic>()
+      ..put('imgId', this.imgId)
+      ..put('url', this.url)
+      ..put('step', this.step);
+  }
+
+  FileUrls.fromJson(Map<String, dynamic> json) {
+    if (null != json['imgId']) {
+      this.imgId = json.asInt('imgId');
+    }
+    if (null != json['url']) {
+      this.url = json.asString('url');
+    }
+    if (null != json['step']) {
+      this.step = json.asInt('step');
+    }
+  }
+}

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 378 - 0
lib/model/maint_job_detail_response.dart


+ 188 - 0
lib/model/maint_pesonse_entity.dart

@@ -0,0 +1,188 @@
+class MaintJobResponse {
+  int? code;
+  MaintJobList? data;
+  String? msg;
+
+  @override
+  String toString() {
+    return 'maintJobResponse{code: $code, data: $data, msg: $msg}';
+  }
+
+  MaintJobResponse({this.code, this.data, this.msg});
+
+  MaintJobResponse.fromJson(Map<String, dynamic> json) {
+    code = json['code'];
+    data = json['data'] != null ? new MaintJobList.fromJson(json['data']) : null;
+    msg = json['msg'];
+  }
+
+  Map<String, dynamic> toJson() {
+    final Map<String, dynamic> data = new Map<String, dynamic>();
+    data['code'] = this.code;
+    if (this.data != null) {
+      data['data'] = this.data!.toJson();
+    }
+    data['msg'] = this.msg;
+    return data;
+  }
+}
+
+class MaintJobList {
+  int? total;
+  int? index;
+  int? size;
+
+  @override
+  String toString() {
+    return 'maintJobList{total: $total, index: $index, size: $size, sortBy: $sortBy, sort: $sort, query: $query, list: $list}';
+  }
+
+  String? sortBy;
+  int? sort;
+  MaintJobVO? query;
+  List<MaintJobVO>? list;
+
+  MaintJobList(
+      {this.total,
+        this.index,
+        this.size,
+        this.sortBy,
+        this.sort,
+        this.query,
+        this.list});
+
+  MaintJobList.fromJson(Map<String, dynamic> json) {
+    total = json['total'];
+    index = json['index'];
+    size = json['size'];
+    sortBy = json['sortBy'];
+    sort = json['sort'];
+    query = json['query'] != null ? new MaintJobVO.fromJson(json['query']) : null;
+    if (json['list'] != null) {
+      list = <MaintJobVO>[];
+      json['list'].forEach((v) {
+        list!.add(new MaintJobVO.fromJson(v));
+      });
+    }
+  }
+
+  Map<String, dynamic> toJson() {
+    final Map<String, dynamic> data = new Map<String, dynamic>();
+    data['total'] = this.total;
+    data['index'] = this.index;
+    data['size'] = this.size;
+    data['sortBy'] = this.sortBy;
+    data['sort'] = this.sort;
+    if (this.query != null) {
+      data['query'] = this.query!.toJson();
+    }
+    if (this.list != null) {
+      data['list'] = this.list!.map((v) => v.toJson()).toList();
+    }
+    return data;
+  }
+}
+
+
+class MaintJobVO {
+  int? id;
+
+  @override
+  String toString() {
+    return 'maintJobVO{id: $id, jobName: $jobName, jobNum: $jobNum, planName: $planName, planNum: $planNum, status: $status, startTime: $startTime, endTime: $endTime, cycleType: $cycleType, planRemarks: $planRemarks, closeReason: $closeReason, closePerson: $closePerson, closeTime: $closeTime, fileUrls: $fileUrls, creator: $creator, itemsList: $itemsList, maintEquipmentVOList: $maintEquipmentVOList, logs: $logs, customer: $customer, channel: $channel, prodCount: $prodCount}';
+  }
+
+  String? jobName;
+  String? jobNum;
+  String? planName;
+  String? planNum;
+  int? status;
+  String? startTime;
+  String? endTime;
+  int? cycleType;
+  Null? planRemarks;
+  Null? closeReason;
+  Null? closePerson;
+  Null? closeTime;
+  Null? fileUrls;
+  String? creator;
+  Null? itemsList;
+  Null? maintEquipmentVOList;
+  Null? logs;
+  String? customer;
+  String? channel;
+  int? prodCount;
+
+  MaintJobVO(
+      {this.id,
+        this.jobName,
+        this.jobNum,
+        this.planName,
+        this.planNum,
+        this.status,
+        this.startTime,
+        this.endTime,
+        this.cycleType,
+        this.planRemarks,
+        this.closeReason,
+        this.closePerson,
+        this.closeTime,
+        this.fileUrls,
+        this.creator,
+        this.itemsList,
+        this.maintEquipmentVOList,
+        this.logs,
+        this.customer,
+        this.channel,
+        this.prodCount});
+
+  MaintJobVO.fromJson(Map<String, dynamic> json) {
+    id = json['id'];
+    jobName = json['jobName'];
+    jobNum = json['jobNum'];
+    planName = json['planName'];
+    planNum = json['planNum'];
+    status = json['status'];
+    startTime = json['startTime'];
+    endTime = json['endTime'];
+    cycleType = json['cycleType'];
+    planRemarks = json['planRemarks'];
+    closeReason = json['closeReason'];
+    closePerson = json['closePerson'];
+    closeTime = json['closeTime'];
+    fileUrls = json['fileUrls'];
+    creator = json['creator'];
+    itemsList = json['itemsList'];
+    maintEquipmentVOList = json['maintEquipmentVOList'];
+    logs = json['logs'];
+    customer = json['customer'];
+    channel = json['channel'];
+    prodCount = json['prodCount'];
+  }
+
+  Map<String, dynamic> toJson() {
+    final Map<String, dynamic> data = new Map<String, dynamic>();
+    data['id'] = this.id;
+    data['jobName'] = this.jobName;
+    data['jobNum'] = this.jobNum;
+    data['planName'] = this.planName;
+    data['planNum'] = this.planNum;
+    data['status'] = this.status;
+    data['startTime'] = this.startTime;
+    data['endTime'] = this.endTime;
+    data['cycleType'] = this.cycleType;
+    data['planRemarks'] = this.planRemarks;
+    data['closeReason'] = this.closeReason;
+    data['closePerson'] = this.closePerson;
+    data['closeTime'] = this.closeTime;
+    data['fileUrls'] = this.fileUrls;
+    data['creator'] = this.creator;
+    data['itemsList'] = this.itemsList;
+    data['maintEquipmentVOList'] = this.maintEquipmentVOList;
+    data['logs'] = this.logs;
+    data['customer'] = this.customer;
+    data['channel'] = this.channel;
+    data['prodCount'] = this.prodCount;
+    return data;
+  }
+}

+ 2 - 35
lib/model/patrol_response_entity.dart

@@ -1,6 +1,8 @@
 import 'package:deus_app/generated/json/base/json_convert_content.dart';
 import 'package:json2dart_safe/json2dart.dart';
 
+import 'ImgVO.dart';
+
 class PatrolJobDataResponseEntity
     with JsonConvert<PatrolJobDataResponseEntity> {
   late int code;
@@ -369,41 +371,6 @@ class PatrolJobData {
 /**
  * 巡检任务实体类
  */
-class FileUrls {
-  int? imgId;
-  String? url;
-  int? step;
-
-  @override
-  String toString(){
-    return 'FilrUrls{imgId: $imgId,url: $url,step: $step}';
-  }
-
-  FileUrls({
-    this.imgId,
-    this.url,
-    this.step,
-  });
-
-  Map<String, dynamic> toJson() {
-    return Map<String, dynamic>()
-      ..put('imgId', this.imgId)
-      ..put('url', this.url)
-      ..put('step', this.step);
-  }
-
-  FileUrls.fromJson(Map<String, dynamic> json) {
-    if (null != json['imgId']) {
-      this.imgId = json.asInt('imgId');
-    }
-    if (null != json['url']) {
-      this.url = json.asString('url');
-    }
-    if (null != json['step']) {
-      this.step = json.asInt('step');
-    }
-  }
-}
 
 class PatrolItemVOS {
   int? id;

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 594 - 0
lib/page/maint/maint_job_detail.dart


+ 31 - 26
lib/page/maint/maint_job_page.dart

@@ -1,5 +1,7 @@
 //巡检任务列表
 import 'package:deus_app/common/style/TitleBar.dart';
+import 'package:deus_app/model/maint_pesonse_entity.dart';
+import 'package:deus_app/page/maint/maint_job_detail.dart';
 import 'package:deus_app/page/patrol/patrol_job_detail.dart';
 import 'package:flutter/material.dart';
 import '../../common/style/gsy_style.dart';
@@ -21,17 +23,20 @@ class MaintJobPage extends StatefulWidget {
   }
 }
 
-List<PatrolJobData> patrol_job_list = [];
+List<MaintJobVO> maint_job_list = [];
 class _MaintJobPage extends State<MaintJobPage> {
   final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
 
   _load() async {
-    var result = await DioUtil().request('patrolJob/appPatrolJobList',
+    var result = await DioUtil().request('maintJob/list',
         method: DioMethod.post, data: {'query': {}, 'index': 1, 'size': 5});
 
 
-    //var patrolJobResponse = PatrolJobResponse.fromJson(result);
-    //print(patrolJobResponse);
+    MaintJobResponse maintJobResponse= MaintJobResponse.fromJson(result);
+
+    MaintJobList maintJobList = maintJobResponse.data!;
+
+    maint_job_list = maintJobList.list!;
   }
 
   @override
@@ -49,7 +54,7 @@ class _MaintJobPage extends State<MaintJobPage> {
   Widget build(BuildContext context) {
     return Scaffold(
         key: _scaffoldKey,
-        appBar: TitleBar().drawAppBar(ConstantString.patrolJobText, () {
+        appBar: TitleBar().drawAppBar(ConstantString.maintJobText, () {
           _scaffoldKey.currentState?.openEndDrawer();
         }),
         endDrawer: MaintJobDrawer(
@@ -70,24 +75,24 @@ class _MaintJobPage extends State<MaintJobPage> {
                 SizedBox(
                   width: 15,
                 ),
-                Text(ConstantString.patrolJobTitle,
+                Text(ConstantString.maintJobTitle,
                     style: GSYConstant.smallActionLightText),
               ],
             ),
             Expanded(
                 child: Container(
                     child: ListView.builder(
-                      itemCount: patrol_job_list.length,
+                      itemCount: maint_job_list.length,
                       itemBuilder: (context, index) {
-                        PatrolJobData patrolJobData = patrol_job_list[index];
-                        return _patrol_job_list(patrolJobData);
+                        MaintJobVO maintJobVO = maint_job_list[index];
+                        return _maint_job_list(maintJobVO);
                       },
                     )))
           ],
         ));
   }
 
-  Widget _patrol_job_list(PatrolJobData patrolJobData) {
+  Widget _maint_job_list(MaintJobVO maintJobVO) {
     return Container(
         margin: EdgeInsets.only(top: 12, left: 10, right: 10),
         padding: EdgeInsets.only(top: 12, bottom: 10),
@@ -98,7 +103,7 @@ class _MaintJobPage extends State<MaintJobPage> {
               Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
                 Container(
                   child: Text(
-                    patrolJobData.name!,
+                    maintJobVO.jobName!,
                     style: TextStyle(
                       color: Colors.black,
                       fontSize: GSYConstant.middleTextWhiteSize,
@@ -110,25 +115,25 @@ class _MaintJobPage extends State<MaintJobPage> {
                   padding:
                   EdgeInsets.only(top: 3, bottom: 3, left: 5, right: 5),
                   child: Text(
-                    patrolJobData.status == 0
+                    maintJobVO.status == 2
                         ? '已关闭'
-                        : patrolJobData.status == 1
+                        : maintJobVO.status == 3
                         ? '执行中'
-                        : patrolJobData.status == 2
+                        : maintJobVO.status == 5
                         ? '已完成'
-                        : patrolJobData.status == 3
+                        : maintJobVO.status == 1
                         ? '待执行'
-                        : patrolJobData.status == 4
+                        : maintJobVO.status == 4
                         ? '已逾期'
                         : '未知',
                     textAlign: TextAlign.right,
                     style: TextStyle(
                       color:
-                      patrolJobData.status == 0 || patrolJobData.status == 4
+                      maintJobVO.status == 0 || maintJobVO.status == 4
                           ? Colors.red
-                          : patrolJobData.status == 1
+                          : maintJobVO.status == 3
                           ? Colors.orange
-                          : patrolJobData.status == 2
+                          : maintJobVO.status == 2
                           ? Colors.green
                           : Colors.black, //边框颜色
                       fontSize: GSYConstant.minTextSize,
@@ -137,11 +142,11 @@ class _MaintJobPage extends State<MaintJobPage> {
                   decoration: BoxDecoration(
                     border: new Border.all(
                       color:
-                      patrolJobData.status == 0 || patrolJobData.status == 4
+                      maintJobVO.status == 0 || maintJobVO.status == 4
                           ? Colors.red
-                          : patrolJobData.status == 1
+                          : maintJobVO.status == 3
                           ? Colors.orange
-                          : patrolJobData.status == 2
+                          : maintJobVO.status == 2
                           ? Colors.green
                           : Colors.black, //边框颜色
                       width: 1.0, //边框粗细
@@ -166,7 +171,7 @@ class _MaintJobPage extends State<MaintJobPage> {
                 ),
                 Container(
                   child: Text(
-                    patrolJobData.number!,
+                    maintJobVO.jobNum!,
                     textAlign: TextAlign.right,
                     style: TextStyle(
                       color: GSYColors.primaryLightValue,
@@ -190,7 +195,7 @@ class _MaintJobPage extends State<MaintJobPage> {
                 ),
                 Container(
                   child: Text(
-                    patrolJobData.startDate!,
+                    maintJobVO.startTime!,
                     textAlign: TextAlign.right,
                     style: TextStyle(
                       color: GSYColors.primaryLightValue,
@@ -214,7 +219,7 @@ class _MaintJobPage extends State<MaintJobPage> {
                 ),
                 Container(
                   child: Text(
-                    patrolJobData.endDate!,
+                    maintJobVO.endTime!,
                     textAlign: TextAlign.right,
                     style: TextStyle(
                       color: GSYColors.primaryLightValue,
@@ -232,7 +237,7 @@ class _MaintJobPage extends State<MaintJobPage> {
             Navigator.push(
                 context,
                 MaterialPageRoute(
-                    builder: (context) => new PatrolJobDetail(id:patrolJobData.id)));
+                    builder: (context) => new MaintJobDetail(id:maintJobVO.id)));
           },
         ));
   }

+ 252 - 0
lib/page/repair/repair_page.dart

@@ -0,0 +1,252 @@
+//巡检任务列表
+import 'package:deus_app/common/style/TitleBar.dart';
+import 'package:deus_app/page/patrol/patrol_job_detail.dart';
+import 'package:flutter/material.dart';
+import '../../common/style/gsy_style.dart';
+import '../../common/utils/ConstantString.dart';
+import '../../common/utils/DioUtil.dart';
+import '../../common/utils/ToastUtils.dart';
+import '../../model/patrol_response_entity.dart';
+import '../../widget/PatrolJobDrawer.dart';
+
+class RepairPage extends StatefulWidget {
+  const RepairPage({super.key});
+
+  static var routeName = '/RepairPage';
+
+  @override
+  State createState() {
+    return _RepairPage();
+  }
+}
+
+List<PatrolJobData> patrol_job_list = [];
+
+
+class _RepairPage extends State<RepairPage> {
+  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
+
+  _load() async {
+    var result = await DioUtil().request('patrolJob/appPatrolJobList',
+        method: DioMethod.post, data: {'query': {}, 'index': 1, 'size': 5});
+
+    PatrolJobResponse patrolJobResponse = PatrolJobResponse.fromJson(result);
+    print(patrolJobResponse);
+    patrol_job_list = patrolJobResponse.data!.patrolJobVOS!;
+    //var patrolJobResponse = PatrolJobResponse.fromJson(result);
+    //print(patrolJobResponse);
+  }
+
+  @override
+  void initState() {
+    // TODO: implement initState
+    super.initState();
+    Future.delayed(
+        Duration.zero,
+            () => setState(() {
+          _load();
+        }));
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+        key: _scaffoldKey,
+        appBar: TitleBar().drawAppBar(ConstantString.patrolJobText, () {
+          _scaffoldKey.currentState?.openEndDrawer();
+        }),
+        endDrawer: PatrolJobDrawer(
+          callback: (index, str) {
+            showToast(str);
+          },
+        ),
+        //抽屉
+        backgroundColor: const Color(0xfff2f2f2),
+        body: Column(
+          children: [
+            Expanded(
+                child: Container(
+                    child: ListView.builder(
+                      itemCount: patrol_job_list.length,
+                      itemBuilder: (context, index) {
+                        PatrolJobData patrolJobData = patrol_job_list[index];
+                        return _patrol_job_list(patrolJobData);
+                      },
+                    )))
+          ],
+        ));
+  }
+
+  Widget _patrol_job_list(PatrolJobData patrolJobData) {
+    return Container(
+        margin: EdgeInsets.only(top: 12, left: 10, right: 10),
+        padding: EdgeInsets.only(top: 12, bottom: 10),
+        color: Colors.white,
+        child: ListTile(
+          title: Column(
+            children: [
+              Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
+                Container(
+                  child: Text(
+                    patrolJobData.name!,
+                    style: TextStyle(
+                      color: Colors.black,
+                      fontSize: GSYConstant.middleTextWhiteSize,
+                      fontWeight: FontWeight.bold,
+                    ),
+                  ),
+                ),
+                Container(
+                  padding:
+                  EdgeInsets.only(top: 3, bottom: 3, left: 5, right: 5),
+                  child: Text(
+                    patrolJobData.status == 0
+                        ? '已关闭'
+                        : patrolJobData.status == 1
+                        ? '执行中'
+                        : patrolJobData.status == 2
+                        ? '已完成'
+                        : patrolJobData.status == 3
+                        ? '待执行'
+                        : patrolJobData.status == 4
+                        ? '已逾期'
+                        : '未知',
+                    textAlign: TextAlign.right,
+                    style: TextStyle(
+                      color:
+                      patrolJobData.status == 0 || patrolJobData.status == 4
+                          ? Colors.red
+                          : patrolJobData.status == 1
+                          ? Colors.orange
+                          : patrolJobData.status == 2
+                          ? Colors.green
+                          : Colors.black, //边框颜色
+                      fontSize: GSYConstant.minTextSize,
+                    ),
+                  ),
+                  decoration: BoxDecoration(
+                    border: new Border.all(
+                      color:
+                      patrolJobData.status == 0 || patrolJobData.status == 4
+                          ? Colors.red
+                          : patrolJobData.status == 1
+                          ? Colors.orange
+                          : patrolJobData.status == 2
+                          ? Colors.green
+                          : Colors.black, //边框颜色
+                      width: 1.0, //边框粗细
+                    ),
+                    borderRadius: const BorderRadius.all(
+                        const Radius.circular(3.0)), //边框的弧度
+                  ),
+                )
+              ]),
+              SizedBox(
+                height: 12,
+              ),
+              Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
+                Container(
+                  child: Text(
+                    '报修单号:',
+                    style: TextStyle(
+                      color: GSYColors.primaryLightValue,
+                      fontSize: GSYConstant.middleTextWhiteSize,
+                    ),
+                  ),
+                ),
+                Container(
+                  child: Text(
+                    patrolJobData.number!,
+                    textAlign: TextAlign.right,
+                    style: TextStyle(
+                      color: GSYColors.primaryLightValue,
+                      fontSize: GSYConstant.middleTextWhiteSize,
+                    ),
+                  ),
+                ),
+              ]),
+              SizedBox(
+                height: 10,
+              ),
+              Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
+                Container(
+                  child: Text(
+                    '报修设备:',
+                    style: TextStyle(
+                      color: GSYColors.primaryLightValue,
+                      fontSize: GSYConstant.middleTextWhiteSize,
+                    ),
+                  ),
+                ),
+                Container(
+                  child: Text(
+                    patrolJobData.startDate!,
+                    textAlign: TextAlign.right,
+                    style: TextStyle(
+                      color: GSYColors.primaryLightValue,
+                      fontSize: GSYConstant.middleTextWhiteSize,
+                    ),
+                  ),
+                ),
+              ]),
+              SizedBox(
+                height: 10,
+              ),
+              Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
+                Container(
+                  child: Text(
+                    '申请时间:',
+                    style: TextStyle(
+                      color: GSYColors.primaryLightValue,
+                      fontSize: GSYConstant.middleTextWhiteSize,
+                    ),
+                  ),
+                ),
+                Container(
+                  child: Text(
+                    patrolJobData.endDate!,
+                    textAlign: TextAlign.right,
+                    style: TextStyle(
+                      color: GSYColors.primaryLightValue,
+                      fontSize: GSYConstant.middleTextWhiteSize,
+                    ),
+                  ),
+                ),
+              ]),SizedBox(
+                height: 10,
+              ),
+              Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
+                Container(
+                  child: Text(
+                    '申请人:',
+                    style: TextStyle(
+                      color: GSYColors.primaryLightValue,
+                      fontSize: GSYConstant.middleTextWhiteSize,
+                    ),
+                  ),
+                ),
+                Container(
+                  child: Text(
+                    patrolJobData.endDate!,
+                    textAlign: TextAlign.right,
+                    style: TextStyle(
+                      color: GSYColors.primaryLightValue,
+                      fontSize: GSYConstant.middleTextWhiteSize,
+                    ),
+                  ),
+                ),
+              ]),
+              SizedBox(
+                height: 5,
+              ),
+            ],
+          ),
+          onTap: () {
+            Navigator.push(
+                context,
+                MaterialPageRoute(
+                    builder: (context) => new PatrolJobDetail(id:patrolJobData.id)));
+          },
+        ));
+  }
+}

+ 2 - 3
lib/widget/MyDrawer.dart

@@ -4,7 +4,7 @@ import 'package:deus_app/model/drop_menu_item.dart';
 import 'package:flutter/material.dart';
 
 class MyDrawer extends StatefulWidget {
-   final _CallBack callback;
+  final _CallBack callback;
 
   const MyDrawer({super.key,required this.callback});
 
@@ -281,8 +281,7 @@ class _myDrawer extends State<MyDrawer> {
   static const SEX = ['男', '女', '保密'];
   String _device = '', _username = '', _deviceKey = '', _product = '';
 
-  Widget dropDownButtonsColumn(
-      List<DropMenuItem> list, String hint, DropMenuItem select) {
+  Widget dropDownButtonsColumn(List<DropMenuItem> list, String hint, DropMenuItem select) {
     return Container(
       height: 40,
       //gives the height of the dropdown button