Kaynağa Gözat

节假日显示增加

dev01 1 yıl önce
ebeveyn
işleme
a5af91d833

+ 205 - 0
src/components/common/DateTimePicker/index.jsx

@@ -0,0 +1,205 @@
+import React, { Component } from 'react';
+import Taro from '@tarojs/taro';
+// import PropTypes from 'prop-types';
+import { AtIcon } from 'taro-ui';
+import { View, Text, PickerView, PickerViewColumn, } from '@tarojs/components';
+import { getPickerViewList, getDate, getArrWithTime, formatDate, getDayList } from './utils';
+import './index.scss';
+
+
+export default class DateTimePicker extends Component {
+  static externalClasses = ['wrap-class', 'select-item-class'];
+
+  state = {
+    yearList: [],   //年 -下拉
+    monthLsit: [], //月 -下拉
+    dayList: [], //日 -下拉
+    hourList: [], //时 -下拉
+    minuteList: [], //分 -下拉
+    selectIndexList: [1, 1, 1, 1, 1], //PickerViewColumn选择的索引
+    fmtInitValue: "", //初始值
+    time: '', //当前选择的数据
+    visible: false, //是否可见
+    hasChange: false, //是否更改
+    year: '',  //时间值
+    month: '',
+    day: '',
+    hour: '',
+    minute: '',
+  };
+  // 打开时间选择的模态框 - 根据当前时间初始化picker-view的数据
+  openModal = () => {
+    const { time, fmtInitValue } = this.state;
+    const selectIndexList = [];
+    const arr = getArrWithTime(time || fmtInitValue || getDate()); //优先当前选择的值,其次默认值,其次当前值
+    const { yearList, monthLsit, dayList, hourList, minuteList } = getPickerViewList();
+    const [year, month, day, hour, minute] = arr;
+
+    //根据arr  数据索引
+    selectIndexList[0] = yearList.indexOf(arr[0] + '年');
+    selectIndexList[1] = monthLsit.indexOf(arr[1] + '月');
+    selectIndexList[2] = dayList.indexOf(arr[2] + '日');
+    selectIndexList[3] = hourList.indexOf(arr[3] + '点');
+    selectIndexList[4] = minuteList.indexOf(arr[4] + '分');
+
+    this.setState({
+      selectIndexList,
+      visible: true,
+      yearList,
+      monthLsit,
+      dayList,
+      hourList,
+      minuteList,
+      year,
+      month,
+      day,
+      hour,
+      minute,
+    });
+  };
+  // 取消
+  cancelHandel = () => {
+    this.setState({
+      visible: false,
+      hasChange: false,
+    });
+
+    const { year, month, day, hour, minute } = this.state;
+    const time = formatDate(year, month, day, hour, minute);
+
+    this.props.onCancel && this.props.onCancel({ time });
+  };
+  // 确定
+  okHandel = () => {
+    const { year, month, day, hour, minute } = this.state;
+    const time = formatDate(year, month, day, hour, minute);
+
+    this.setState({
+      time,
+      hasChange: false,
+      visible: false,
+    });
+    this.props.onOk && this.props.onOk({ time });
+  };
+  // 切换
+  changeHandel = (e) => {
+    const selectIndexList = e.detail.value;
+    const [yearIndex, monthIndex, dayIndex, hourIndex, minuteIndex] = selectIndexList;
+    const { yearList, monthLsit, dayList, hourList, minuteList } = this.state;
+    const yearStr = yearList[yearIndex];
+    const monthStr = monthLsit[monthIndex];
+    const dayStr = dayList[dayIndex];
+    const hourStr = hourList[hourIndex];
+    const minuteStr = minuteList[minuteIndex];
+    const year = Number(yearStr.substr(0, yearStr.length - 1));
+    const month = Number(monthStr.substr(0, monthStr.length - 1));
+    const day = Number(dayStr.substr(0, dayStr.length - 1));
+    const hour = Number(hourStr.substr(0, hourStr.length - 1));
+    const minute = Number(minuteStr.substr(0, minuteStr.length - 1));
+
+    // 更新年、天数
+    const newDayList = getDayList(year, month);
+
+    this.setState({
+      selectIndexList,
+      dayList: newDayList,
+      year,
+      month,
+      day,
+      hour,
+      minute,
+      hasChange: true,
+    });
+  };
+  // 清除数据
+  clear = () => {
+    this.setState({
+      time: ''
+    });
+    this.props.onClear && this.props.onClear({ time: '' });
+  };
+
+  componentDidMount() {
+    const { initValue } = this.props;
+    const fmtInitValue = getDate(initValue);
+    this.setState({ fmtInitValue });
+  }
+
+  render() {
+    const { visible, time, yearList, monthLsit, dayList, hourList, minuteList, selectIndexList } = this.state;
+    const { placeholder = '请选择时间' } = this.props;
+    return (
+      <View className="datetime-picker-wrap wrap-class">
+        <View className="selector-wrap">
+          <View className="select-item select-item-class" onClick={this.openModal}>
+            {time || placeholder}
+          </View>
+          {
+            time && <View className="clear-icon">
+              <AtIcon value="close-circle" size="20" onClick={this.clear} />
+            </View>
+          }
+        </View>
+        {visible
+          && <View className="wrapper">
+            {/*日期模态框 */}
+            <View className="model-box-bg"></View>
+            <View className="model-box">
+              <View className="model-picker">
+                <View className="button-model">
+                  <Text class="btn-txt" onClick={this.cancelHandel}>取消</Text>
+                  <Text class="btn-txt" onClick={this.okHandel}>确定</Text>
+                </View>
+                <View className="cont_model">
+                  <PickerView className="pick-view" indicatorStyle="height: 50px;" value={selectIndexList} onChange={this.changeHandel}>
+                    {/*年*/}
+                    <PickerViewColumn className="picker-view-column">
+                      {
+                        yearList.length && yearList.map((item, index) =>
+                          <View key={String(index)} className="pick-view-column-item">{item}</View>)
+                      }
+                    </PickerViewColumn>
+                    {/*月*/}
+                    <PickerViewColumn className="picker-view-column">
+                      {
+                        monthLsit.length && monthLsit.map((item, index) =>
+                          <View key={String(index)} className="pick-view-column-item">{item}</View>)
+                      }
+                    </PickerViewColumn>
+                    {/*日*/}
+                    <PickerViewColumn className="picker-view-column">
+                      {
+                        dayList.length && dayList.map((item, index) =>
+                          <View key={String(index)} className="pick-view-column-item">{item}</View>)
+                      }
+                    </PickerViewColumn>
+                    {/*时*/}
+                    <PickerViewColumn className="picker-view-column">
+                      {
+                        hourList.length && hourList.map((item, index) =>
+                          <View key={String(index)} className="pick-view-column-item">{item}</View>)
+                      }
+                    </PickerViewColumn>
+                    {/*分*/}
+                    <PickerViewColumn className="picker-view-column">
+                      {
+                        minuteList.length && minuteList.map((item, index) =>
+                          <View key={String(index)} className="pick-view-column-item">{item}</View>)
+                      }
+                    </PickerViewColumn>
+                  </PickerView>
+                </View>
+              </View>
+            </View>
+          </View>}
+      </View>
+    );
+  }
+}
+
+// DateTimePicker.prototype = {
+//     initValue: PropTypes.string, //初始化时间
+//     onClear: PropTypes.func, //清除选择的时间触发
+//     onCancel: PropTypes.func, //时间picker 取消时触发
+//     onOk: PropTypes.func, //时间picker 确定时触发
+// };

+ 78 - 0
src/components/common/DateTimePicker/index.scss

@@ -0,0 +1,78 @@
+.datetime-picker-wrap {
+  .selector-wrap {
+      display: flex;
+      align-items: center;
+      background: #FFFFFF;
+      color: #9BA0AA;
+      padding: 0 20px;
+      .select-item {
+          flex: 1;
+          font-size: 30px;
+          padding: 12px 0;
+          text-align: center;
+      }
+      .clear-icon{
+        margin-left: 30px;
+      }
+  }
+  .wrapper {
+      .model-box-bg {
+          position: absolute;
+          top: 0;
+          left: 0;
+          z-index: 10000;
+          width: 100%;
+          height: 100%;
+          background: #000;
+          opacity: 0.3;
+      }
+      .model-box {
+          position: absolute;
+          bottom: 0;
+          left: 0;
+          z-index: 999999;
+          width: 100%;
+          background: #fff;
+      }
+
+      .model-picker {
+          position: relative;
+          .button-model {
+              height: 80px;
+              width: 100%;
+              background: #fff;
+              position: relative;
+              border-bottom: 1px solid #d9d9d9;
+              .btn-txt {
+                  color: #007aff;
+                  position: absolute;
+                  background: transparent;
+                  border: none;
+                  line-height: 80px;
+                  &:first-child {
+                      left: 32px;
+                  }
+                  &:last-child {
+                      right: 32px;
+                  }
+              }
+          }
+          .pick-view {
+              width: 100%;
+              height: 600px;
+              .picker-view-column {
+                  text-align: center;
+                  .pick-view-column-item {
+                      line-height: 50PX;
+                  }
+              }
+          }
+
+      }
+  }
+}
+
+
+
+
+

+ 85 - 0
src/components/common/DateTimePicker/utils.js

@@ -0,0 +1,85 @@
+function addZero(num) {
+  return Number(num) < 10 ? `0${num}` : num;
+}
+
+export const formatDate = (year, month, day, hour, minute) => {
+  const newmonth = addZero(month);
+  const newday = addZero(day);
+  const newhour = addZero(hour);
+  const newminute = addZero(minute);
+
+  return year + '-' + newmonth + '-' + newday + ' ' + newhour + ":" + newminute;
+};
+
+// 获取当前时间
+export const getDate = (value) => {
+  let date = '';
+  if (value) {
+      date = new Date(value);
+  } else {
+      date = new Date();
+  }
+  const y = date.getFullYear(),
+      m = date.getMonth() + 1,
+      d = date.getDate(),
+      h = date.getHours(), //获取当前小时数(0-23)
+      f = date.getMinutes();
+  return formatDate(y, m, d, h, f);
+};
+
+// 获取对应年份月份的天数
+export const getMonthDay = (year, month) => {
+  var d = new Date(year, month, 0);
+  return d.getDate();
+};
+
+//根据时间2019-01-02 09:12  得到 ['2019','1','2','9','12']
+export const getArrWithTime = (str) => {
+  let arr1 = str.split(' ');
+  let arr2 = (arr1[0]).split('-');
+  let arr3 = arr1[1].split(':');
+  let arr = arr2.concat(arr3);
+  arr[1] = arr[1].startsWith('0') ? arr[1].substr(1, arr[1].length) : arr[1];
+  arr[2] = arr[2].startsWith('0') ? arr[2].substr(1, arr[2].length) : arr[2];
+  arr[3] = arr[3].startsWith('0') ? arr[3].substr(1, arr[3].length) : arr[3];
+  arr[4] = arr[4].startsWith('0') ? arr[4].substr(1, arr[4].length) : arr[4];
+  return arr;
+};
+
+// 获取月份天数
+export const getDayList = (year, month) => {
+  const dayList = [];
+  var d = new Date(year, month, 0);
+  for (let i = 1; i <= d.getDate(); i++) {
+      dayList.push(i + "日");
+  }
+
+  return dayList;
+};
+
+// 获取最近的年、月、日、时、分的集合
+export const getPickerViewList = () => {
+  const now = new Date();
+  const year = now.getFullYear();
+  const month = now.getMonth() + 1;
+  const yearList = [];
+  const monthLsit = [];
+  const dayList = getDayList(year, month);
+  const hourList = [];
+  const minuteList = [];
+
+  for (let i = 1970; i <= 2070; i++) {
+      yearList.push(i + "年");
+  }
+  for (let i = 1; i <= 12; i++) {
+      monthLsit.push(i + "月");
+  }
+
+  for (let i = 0; i <= 23; i++) {
+      hourList.push(i + "点");
+  }
+  for (let i = 0; i <= 59; i++) {
+      minuteList.push(i + "分");
+  }
+  return { yearList, monthLsit, dayList, hourList, minuteList };
+};

+ 18 - 3
src/components/common/xx-calendar/xx-calendar.js

@@ -17,10 +17,23 @@ Component({
             nowMonthDays.forEach(item => {
               if (ele == item.time) {
                 item.color = el.status
+                item.dayStatus = el.dayStatus
               }
             })
           })
         }
+        let date1 = new Date().getDate()
+        let time1 = ""
+        let obj1 = {}
+        for (var i = 0; i < nowMonthDays.length; i++) {
+          if (nowMonthDays[i].date == date1) {
+            time1 = nowMonthDays[i].time.replace(/\//g, "-")
+            obj1 = nowMonthDays[i]
+          }
+        }
+        if (!!time1) {
+          this.triggerEvent('selectdate', { selectDate: time1, obj: obj1 })
+        }
         this.setData({
           nowMonthDays
         })
@@ -136,6 +149,7 @@ Component({
           week: this.data.weeksArr[new Date(year, month - 1, i).getDay()], //星期几
           time,
           color: -1,
+          dayStatus: -1,
           day: newdate,
           isNowMonthDay: (year == nowYear && month == nowMonth && i == nowDay) ? "isNowMonthDay" : ""
         });
@@ -203,11 +217,12 @@ Component({
     selectDate(e) {
       let type = e.currentTarget.dataset.type //选择的时间类型
       let index = e.currentTarget.dataset.index //选择的下标
-      let date = e.currentTarget.dataset.item.time //选择的下标
+      let date = e.currentTarget.dataset.item.time //选择的日期
+      let obj = e.currentTarget.dataset.item //选择日期的所有信息
       let selectDate = date.replace(/\//g, "-")
-      // console.log("选择的时间", selectDate)
+      // console.log("选择的时间", e)
       // 自定义事件,父组件调用,回调 选择的时间selectDate
-      this.triggerEvent('selectdate', selectDate)
+      this.triggerEvent('selectdate', { selectDate: selectDate, obj: obj })
       //将选择的时间类型的 isNowMonthDay 全改为''
       this.data[type]?.forEach(item => {
         item.isNowMonthDay = ''

+ 3 - 5
src/components/common/xx-calendar/xx-calendar.wxml

@@ -29,12 +29,10 @@
     <view class="mouth-date current-mouth" wx:for="{{nowMonthDays}}" wx:key="*this" bindtap="selectDate"
      data-item="{{item}}" data-type="nowMonthDays" data-index="{{index}}"
     >
-       <view class="day-box {{item.isNowMonthDay?'active':''}}">
-        <!-- <text class="day-text {{item.color?'color':''}}">{{item.date}}</text> -->
-        <text class="day-text">{{item.date}}</text>
+        <view class="day-box {{item.isNowMonthDay?'active':''}}">
+        <text class="{{(item.dayStatus==3||item.dayStatus==4)?'day-text-v':'day-text'}}">{{item.date}}</text>
         <!-- day 后面会换成农历展示 -->
-        <!-- <text class="day-nongli">{{item.day}}</text> -->
-        <text class=" {{item.color==0?'day-dot3':item.color==1?'day-dot0':item.color==2?'day-dot1':item.color==3?'day-dot2':'not-dot'}}"></text>
+        <text class=" {{(item.dayStatus==0||item.dayStatus==2)?(item.color==0?'day-dot1':item.color==1?'day-dot2':item.color==2?'day-dot0':item.color==3?'day-dot3':'not-dot'):(item.dayStatus==3||item.dayStatus==4)?(item.color==1?'day-dot2':item.color==2?'day-dot0':'not-dot'):'not-dot'}} "></text>
        </view>
     </view>
     <!-- 下个月日期 -->

+ 12 - 1
src/components/common/xx-calendar/xx-calendar.wxss

@@ -98,7 +98,7 @@
     /* margin-bottom: 10rpx; */
     padding-bottom: 8rpx;
 }
-.mouth-date .day-text{
+.mouth-date .day-text,.day-text-v{
     width: 60rpx;
     height: 60rpx;
     display: flex;
@@ -119,6 +119,17 @@
     font-weight: 600;
 
 }
+.mouth-date .day-text-v{
+    color: #6190E8;
+    font-weight: 600;
+
+}
+.mouth-date .active .day-text-v{
+    color: #fff;
+    background-color: #6190E8;
+    font-weight: 600;
+
+}
 .not-dot{
     width: 10rpx;
     height: 10rpx;

BIN
src/image/sel.png


BIN
src/image/sels.png


+ 147 - 4
src/pages/mybusiness/index.jsx

@@ -1,15 +1,23 @@
 import React, { Component } from 'react';
 import Taro from '@tarojs/taro';
-import { View, Picker, ScrollView, Button } from '@tarojs/components'
-import { getProjectList, listRecord } from '../../utils/servers/servers';
+import { View, Picker, ScrollView, Button, Image } from '@tarojs/components'
+import { getProjectList, listRecord, batchExamineRecord } from '../../utils/servers/servers';
 import dayjs from 'dayjs';
 import {
   AtTabs,
   AtTabsPane,
   AtIcon,
   AtSearchBar,
+  AtButton,
+  AtModal,
+  AtModalContent,
+  AtModalAction,
+  AtTextarea,
 } from 'taro-ui';
 
+import sels from "../../image/sels.png";
+import sel from "../../image/sel.png";
+
 import './index.less';
 import "taro-ui/dist/style/components/search-bar.scss";
 import 'taro-ui/dist/style/components/tabs.scss';
@@ -21,6 +29,7 @@ import "taro-ui/dist/style/components/icon.scss";
 import "taro-ui/dist/style/components/modal.scss";
 
 import MyList from './myList';
+import DateTimePicker from '../../components/common/DateTimePicker';
 
 class Examine extends Component {
 
@@ -37,11 +46,16 @@ class Examine extends Component {
       tlist: [{ title: '我的打卡', type: 0 }],
       tabs: 0,
       list: [],
+      sublist: [],
       pageNum: 1,
       listState: 'LOADING',
       isPickerRender: false,
       rangeEndMinuteVal: '',
       rangeStartMinuteVal: '',
+      isVopen: false,
+      content: "",
+      examineTime: "",
+      time: "",
 
     }
     this.getPublicReleaseList = this.getPublicReleaseList.bind(this);
@@ -77,6 +91,14 @@ class Examine extends Component {
   //   }
   // }
 
+  onOK = ({ time }) => {
+    this.setState({
+      time,
+      examineTime: dayjs(time).format("YYYY-MM-DD HH:mm:ss"),
+    });
+  }
+
+
   async onTabTap() {
     await this.getMyList(1);
   }
@@ -87,7 +109,6 @@ class Examine extends Component {
   }
 
   async getMyList(pageNum) {
-    const { current } = this.state
     this.setState({
       listState: 'LOADING'
     })
@@ -151,8 +172,72 @@ class Examine extends Component {
     await this.getMyList(1);
   }
 
+  onChecked(item) {
+    let list = this.state.sublist
+    list.includes(item.id)
+      ? list = list.filter(function (value) {
+        return value !== item.id;
+      }, this)
+      : list.push(item.id)
+    this.setState({
+      sublist: list
+    })
+  }
+
+  onAllCheck() {
+    const { list, } = this.state
+    let nlist = this.state.sublist
+    if (list.length == nlist.length) {
+      nlist = []
+    } else {
+      nlist = list.map(i => i.id)
+    }
+    this.setState({
+      sublist: nlist
+    })
+  }
+
+  // 同意/驳回
+  agree(sta) {
+    if (!this.state.opinion) {
+      Taro.showToast({ title: "请填写审批意见", icon: "none" });
+      return;
+    }
+    let data = {
+      id: this.state.sublist.toString(),
+      processStatus: sta,
+      content: this.state.opinion,
+      examineTime: "",
+    }
+    for (let i in data) {
+      if (!data[i] && data[i] != 0) {
+        delete data[i]
+      }
+    }
+    batchExamineRecord(data)
+      .then((v) => {
+        this.setState({
+          isVopen: false
+        })
+        if (v.code === 200) {
+          Taro.showToast({
+            title: "操作成功",
+            icon: "none",
+          });
+          this.getMyList(1);
+        } else {
+          Taro.showToast({ title: v.msg, icon: "none" });
+        }
+      })
+      .catch((err) => {
+        Taro.showToast({ title: "系统错误,请稍后再试", icon: "none" });
+        // console.log(err);
+      });
+  }
+
 
   render() {
+    const { isVopen } = this.state
     return (
       <View className='indexPage' >
         <View className='searchContent'>
@@ -298,6 +383,8 @@ class Examine extends Component {
                     onRefresh={() => {
                       this.getProjectList(true);
                     }}
+                    sublist={this.state.sublist}
+                    onChecked={e => { this.onChecked(e) }}
                   />
                 </AtTabsPane>
               )
@@ -305,7 +392,34 @@ class Examine extends Component {
 
           </AtTabs>
         </View>
-
+        {
+          this.state.list.length > 0 && this.state.tabs == 1 &&
+          <View className='bottom'>
+            <View className='lbt'>
+              {
+                this.state.seltype.type == 1 &&
+                <View className='lbtxt'
+                  onClick={() => {
+                    this.onAllCheck()
+                  }}
+                >
+                  <Image className='lbtck' src={this.state.list.length == this.state.sublist.length ? sels : sel} />
+                  全选
+                </View>
+              }
+            </View>
+            <DateTimePicker
+              onOk={this.onOK}
+              initValue={dayjs().format("YYYY/MM/DD HH:mm:ss")}
+            />
+            <Button
+              disabled={this.state.sublist.length == 0}
+              className='rbt'
+              type='primary'
+              onClick={() => { this.setState({ isVopen: true }) }}
+            >批量审核</Button>
+          </View>
+        }
         <timePicker
           config={{
             endDate: true,
@@ -327,6 +441,35 @@ class Examine extends Component {
           }}>
         </timePicker>
 
+        <AtModal
+          width="90%"
+          isOpened={isVopen}
+          onClose={() => { this.setState({ isVopen: false }) }}
+        >
+          <AtModalContent>
+            <View className='tips'>
+              <View className="tit">审批意见</View>
+              <AtTextarea
+                count={false}
+                value={this.state.opinion}
+                onChange={(value) => {
+                  this.setState({
+                    opinion: value,
+                  });
+                }}
+                maxLength={100}
+                placeholder="请填写审批意见"
+              />
+            </View>
+          </AtModalContent>
+          <AtModalAction>
+            <Button
+              onClick={() => { this.agree(3) }}>驳回</Button>
+            <Button
+              onClick={() => { this.agree(2) }}>同意</Button>
+          </AtModalAction>
+        </AtModal>
+
       </View>
     )
   }

+ 103 - 5
src/pages/mybusiness/index.less

@@ -1,8 +1,8 @@
 .indexPage {
-  position: relative;
+  // position: relative;
   z-index: 1;
   background: #F5F5F5;
-  min-height: calc(100vh - 52px);
+  min-height: calc(100vh);
 
   .item-content__info-title {
     font-size: 28px;
@@ -29,6 +29,7 @@
   .searchContent {
     position: relative;
     background: white;
+    padding-bottom: 100px;
 
     .searchTop {
       z-index: 1000;
@@ -183,6 +184,9 @@
 
   .list {
     padding: 20px 23px 52px 23px;
+    display: flex;
+    flex-direction: column;
+    flex: 1;
 
     .item {
       border-radius: 6px;
@@ -213,6 +217,16 @@
         }
       }
 
+      .left {
+        padding: 0 15px 0 0;
+
+        .check {
+          width: 32px;
+          height: 32px;
+
+        }
+      }
+
       .infor {
         width: 100%;
         position: relative;
@@ -313,6 +327,56 @@
     }
   }
 
+  .bottom {
+    width: 94%;
+    height: 100px;
+    background: #fff;
+    position: fixed;
+    bottom: 0;
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    justify-content: space-between;
+    padding: 0 3%;
+
+    .lbt {
+      display: flex;
+      flex-direction: row;
+      align-items: center;
+      font-size: 24px;
+
+      .lbtxt {
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+        margin-right: 20px;
+
+        .lbtck {
+          width: 32px;
+          height: 32px;
+          margin-right: 10px;
+
+        }
+
+      }
+
+    }
+
+    .del {
+      background: red;
+      font-size: 24px;
+
+    }
+
+    .rbt {
+      background: #6190E8;
+      font-size: 24px;
+      margin: 0;
+
+    }
+
+  }
+
   .skeleton {
     border-radius: 11px;
     margin-bottom: 20px;
@@ -320,12 +384,46 @@
 }
 
 .at-modal__container {
-  width: 718px;
+
+  // width: 718px;
+  textarea {
+    width: 420px;
+    height: 150px;
+    background-color: #F5F5F5;
+    padding: 20px;
+    border-radius: 20px;
+    margin-top: 30px;
+
+  }
 }
 
-.operation{
+.operation {
   display: flex;
   flex-flow: row nowrap;
   margin: 30px 0;
 
-}
+}
+
+.tips {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  padding: 30px 0;
+
+  .tit {
+    font-size: 34px;
+    font-weight: bold;
+    margin-bottom: 10px;
+  }
+
+}
+
+// .my-class {
+//   width: 80%;
+//   background: #CCCCCC;
+//   border: 1px solid red;
+// }
+
+// .mySelector {
+//   color: red;
+// }

+ 15 - 1
src/pages/mybusiness/myList.jsx

@@ -5,6 +5,8 @@ import Skeleton from "taro-skeleton";
 import { getClockState } from "../../utils/tools";
 import ListBottomStart from "../../components/common/listBottomStart";
 import "./index.less";
+import sels from "../../image/sels.png";
+import sel from "../../image/sel.png";
 
 class MyList extends Component {
   constructor(props) {
@@ -12,7 +14,7 @@ class MyList extends Component {
   }
 
   render() {
-    const { type } = this.props
+    const { type, sublist = [] } = this.props
     return (
       <View className="indexPage">
         <View className="list">
@@ -33,6 +35,18 @@ class MyList extends Component {
                 });
               }}
             >
+              {
+                type == 1 &&
+                <View className='left'
+                  onClick={e => {
+                    e.stopPropagation();
+                    v.processStatus == 1
+                      ? this.props.onChecked(v)
+                      : Taro.showToast({ title: '该打卡信息已审核!', icon: 'none' })
+                  }}>
+                  <Image className='check' src={sublist.includes(v.id) ? sels : sel} />
+                </View>
+              }
               <View className="infor">
                 <View className="title">
                   <View className="aname">

+ 146 - 42
src/pages/project/index.jsx

@@ -7,8 +7,9 @@ import {
   AtSearchBar,
   AtTabs,
   AtTabsPane,
+  AtIcon,
 } from 'taro-ui';
-import { clockState } from '../../utils/tools/config';
+import { dateList } from '../../utils/tools/config';
 
 import './index.less';
 
@@ -33,14 +34,22 @@ class Project extends Component {
         // { title: '我参与', type: 3 }
       ],
       current: 0,
-
+      isPickerRender: false,
       list: [],
       pageNum: 1,
       listState: 'LOADING',
+      searchType: { title: "按项目名称", desc: "请输入项目名称", id: 0 },
+      search: [
+        { title: "按项目名称", desc: "请输入项目名称", id: 0 },
+        { title: "按负责人", desc: "请输入项目负责人", id: 1 },
+        { title: "研发人员", desc: "请输入研发人员名称", id: 2 },
+      ]
 
     }
     this.getProjectList = this.getProjectList.bind(this);
     this.getMyList = this.getMyList.bind(this);
+    this.onSetPickerTime = this.onSetPickerTime.bind(this);
+    this.onPickerHide = this.onPickerHide.bind(this)
   }
 
   componentDidShow() {
@@ -84,8 +93,12 @@ class Project extends Component {
       pageNum: pageNum,
       pageSize: 10,
       roleType: 0,
-      name: this.state.searchValue || undefined,
-
+      projectYear: this.state.starts,
+      startTime: this.state.rangeStartMinuteVal || undefined,
+      endTime: this.state.rangeEndMinuteVal || undefined,
+      name: this.state.searchType.id == 0 ? this.state.searchValue : undefined,
+      headName: this.state.searchType.id == 1 ? this.state.searchValue : undefined,
+      staffName: this.state.searchType.id == 2 ? this.state.searchValue : undefined,
     }
     for (let i in data) {
       if (!data[i] && data[i] != 0) {
@@ -136,44 +149,43 @@ class Project extends Component {
     }
   }
 
-  // submit() {
-  //   if (!this.state.rmk) {
-  //     Taro.showToast({ title: '请填写备注!', icon: 'none' });
-  //     return
-  //   }
-  //   Taro.showLoading({ title: '正在提交...' });
-  //   techReject({
-  //     id: this.state.id,
-  //     remarks: this.state.rmk,
-  //   }).then(v => {
-  //     Taro.hideLoading()
-  //     if (v.error.length === 0) {
-  //       Taro.showToast({ title: '提交成功', icon: 'none' });
-  //       this.getProjectList();
-  //       this.setState({
-  //         isOpen: false,
-  //         rmk: "",
-  //       })
-  //     } else {
-  //       Taro.showToast({ title: v.error[0].message, icon: 'none' })
-  //     }
-  //   }).catch(() => {
-  //     Taro.hideLoading()
-  //     Taro.showToast({
-  //       title: '系统错误,请稍后再试',
-  //       icon: 'none'
-  //     })
-  //   })
-  // }
+  async onSetPickerTime(val) {
+    let data = val.detail;
+    await this.setState({
+      rangeStartMinuteVal: dayjs(data.selectStartTime).format("YYYY-MM-DD"),
+      rangeEndMinuteVal: dayjs(data.selectEndTime).format("YYYY-MM-DD")
+    })
+    await this.getMyList(1);
+  }
+
+  onPickerHide() {
+    this.setState({
+      isPickerRender: false,
+    });
+  }
 
   render() {
+    const { searchType, search } = this.state
     return (
       <View className='indexPage' >
         <View className='searchContent'>
           <View className='searchTop'>
+            <Picker
+              value={searchType.id}
+              range={search} rangeKey='title' mode='selector'
+              onChange={(e) => {
+                this.setState({
+                  searchType: search[e.detail.value],
+                })
+              }}>
+              <View className='shortValuecontent'>
+                <View className='selectTitle'>{searchType.title}</View>
+                <View className='iconContent'><AtIcon value='chevron-down' size='10' color='#FFFFFF' /></View>
+              </View>
+            </Picker>
             <AtSearchBar
               showActionButton
-              placeholder='请输项目名称'
+              placeholder={searchType.desc}
               value={this.state.searchValue}
               onActionClick={() => {
                 this.getProjectList();
@@ -190,17 +202,90 @@ class Project extends Component {
               }}
             />
           </View>
-          {/* <View className='searchBottom'>
-            <View className='searchAdd' style={{ paddingLeft: '5px' }}
-              onClick={() => {
+          <ScrollView className={this.state.openSearch ? 'searchBottomLOL' : ''} scrollX style={{ width: '100%' }}>
+            <View className='searchBottom'>
+              <View className='searchItem' style={{ paddingLeft: '5px' }}>
+                <Picker
+                  value={this.state.starts}
+                  range={dateList} mode='selector'
+                  onChange={(e) => {
+                    this.setState({
+                      starts: dateList[e.detail.value],
+                    }, () => {
+                      this.getProjectList();
+                    })
+                  }}>
+                  {
+                    !this.state.starts ?
+                      <View className='shortValuecontent'>
+                        <View className='selectTitle'>年份</View>
+                        <View className='iconContent'><AtIcon value='chevron-down' size='10' color='#FFFFFF' /></View>
+                      </View> :
+                      <View className='shortValuecontent'>
+                        <View className='selectValue'>
+                          {this.state.starts}年
+                        </View>
+                        <View className='iconContent' />
+                      </View>
+                  }
+                </Picker>
+                {
+                  this.state.starts &&
+                  <View className='searchSelectContent'>
+                    <View className='selectIcon'
+                      onClick={(e) => {
+                        e.stopPropagation();
+                        this.setState({
+                          starts: ""
+                        }, () => {
+                          this.getProjectList();
+                        })
+                      }}>
+                      <AtIcon value='close-circle' size='10' color='#FFFFFF' />
+                    </View>
+                  </View>
+                }
+              </View>
+              <View className='searchItem' onClick={() => {
                 this.setState({
-                  isOpen: true
+                  isPickerRender: true
                 })
-              }}
-            >
-              + 创建新项目
+              }}>
+                <View>
+                  {
+                    !this.state.rangeStartMinuteVal ?
+                      <View className='valuecontent'>
+                        <View className='selectTitle'>开始及结束时间</View>
+                        <View className='iconContent' ><AtIcon value='chevron-down' size='10' color='#FFFFFF' /></View>
+                      </View> :
+                      <View className='valuecontent'>
+                        <View className='selectValue' >
+                          {this.state.rangeStartMinuteVal + "~" + this.state.rangeEndMinuteVal}
+                        </View>
+                        <View className='iconContent' />
+                      </View>
+                  }
+                </View>
+                {
+                  this.state.rangeStartMinuteVal &&
+                  <View className='searchSelectContent'>
+                    <View className='selectIcon'
+                      onClick={(e) => {
+                        e.stopPropagation();
+                        this.setState({
+                          rangeStartMinuteVal: '',
+                          rangeEndMinuteVal: '',
+                        }, () => {
+                          this.getProjectList();
+                        })
+                      }}>
+                      <AtIcon value='close-circle' size='10' color='#FFFFFF' />
+                    </View>
+                  </View>
+                }
+              </View>
             </View>
-          </View> */}
+          </ScrollView>
         </View>
         <AtTabs
           swipeable={false}
@@ -235,6 +320,25 @@ class Project extends Component {
             )
           }
         </AtTabs>
+        <timePicker
+          config={{
+            endDate: true,
+            column: "minute",
+            dateLimit: false,
+            limitStartTime: dayjs().subtract(3, 'year').format('YYYY-MM-DD '),
+            limitEndTime: dayjs().add(3, 'year').format('YYYY-MM-DD ')
+          }}
+          isPartition
+          pickerShow={this.state.isPickerRender}
+          onconditionaljudgment={(v) => {
+          }}
+          onhidepicker={() => {
+            this.onPickerHide()
+          }}
+          onsetpickertime={(v) => {
+            this.onSetPickerTime(v)
+          }}>
+        </timePicker>
       </View>
     )
   }

+ 62 - 23
src/pages/project/index.less

@@ -29,9 +29,51 @@
   .searchContent {
     position: relative;
     background: white;
+    padding: 20px;
 
     .searchTop {
       z-index: 1000;
+      display: flex;
+      flex-direction: row;
+      align-items: center;
+      justify-content: space-between;
+
+      .at-search-bar{
+        width: 70%;
+      }
+
+      .shortValuecontent {
+        position: relative;
+        display: flex;
+        align-items: center;
+        text-align: center;
+        width: 200px;
+        background: #6190E8;
+        border-radius: 100px;
+        padding: 10px 0;
+        margin-left: 10px;
+        font-size: 25px;
+        color: #FFFFFF;
+
+        .selectValue {
+          width: 100%;
+          text-align: center;
+          white-space: nowrap;
+        }
+
+        .selectTitle {
+          width: 100%;
+          text-align: center;
+        }
+
+        .iconContent {
+          position: absolute;
+          right: 0;
+          width: 60px;
+          text-align: center;
+        }
+      }
+
     }
 
     .searchBottom {
@@ -42,11 +84,6 @@
       border-bottom-left-radius: 10px;
       border-bottom-right-radius: 10px;
       padding: 10px 0 10px 0;
-      border: 1px solid red;
-
-      .searchAdd{
-        
-      }
 
       .searchBottomBack {
         position: fixed;
@@ -67,28 +104,29 @@
           position: relative;
           display: flex;
           align-items: center;
-          width: 155px;
+          text-align: center;
+          width: 200px;
           background: #6190E8;
           border-radius: 100px;
           padding: 10px 0;
           margin-right: 5px;
 
           .selectValue {
-            width: 110px;
-            padding-left: 15px;
+            width: 100%;
+            text-align: center;
             white-space: nowrap;
           }
 
           .selectTitle {
-            padding-left: 15px;
-            white-space: nowrap;
-            width: 110px;
+            width: 100%;
+            text-align: center;
           }
 
           .iconContent {
-            width: 45px;
-            padding-right: 20px;
-            text-align: right;
+            position: absolute;
+            right: 0;
+            width: 60px;
+            text-align: center;
           }
         }
 
@@ -96,28 +134,29 @@
           position: relative;
           display: flex;
           align-items: center;
-          width: 190px;
+          width: 460px;
           background: #6190E8;
           border-radius: 100px;
           padding: 10px 0;
-          margin-right: 5px;
+          margin-right: 20px;
 
           .selectValue {
-            padding-left: 15px;
-            width: 145px;
+            width: 100%;
+            text-align: center;
             white-space: nowrap;
           }
 
           .selectTitle {
-            padding-left: 15px;
+            width: 100%;
+            text-align: center;
             white-space: nowrap;
-            width: 145px;
           }
 
           .iconContent {
-            width: 45px;
-            padding-right: 20px;
-            text-align: right;
+            position: absolute;
+            right: 0;
+            width: 60px;
+            text-align: center;
           }
         }
 

+ 14 - 0
src/pages/punchClock/index.less

@@ -440,6 +440,20 @@
     font-size: 24px;
   }
 
+  .tits{
+    font-size: 34px;
+    font-weight: bold;
+    margin-bottom: 10px;
+    color: red;
+  }
+
+  .txts{
+    padding: 20px;
+    font-size: 28px;
+    font-weight: bold;
+    color: red;
+  }
+
 }
 
 textarea {

+ 44 - 5
src/pages/punchClock/punchClocks.jsx

@@ -51,6 +51,8 @@ class PunchClocks extends Component {
       clockId: "",
       dateList: [],
       isCalendar: true,
+      //isVacation: false, // 是否节假日
+      isVopen: false, // 节假日提示
 
       year: new Date().getFullYear(),
       month: new Date().getMonth() + 1,
@@ -221,27 +223,29 @@ class PunchClocks extends Component {
       })
     }
   }
-
+  // 选择日期
   onSelectDate(val) {
-    let data = val.detail;
+    let data = val.detail.selectDate;
+    let obj = val.detail.obj
     let date = dayjs(data)
     this.setState({
       dateSel: data,
       year: date.year(),
       month: date.month() + 1,
       day: date.date(),
+      isVacation: (obj.dayStatus == 3 || obj.dayStatus == 4) ? true : false,
     }, () => {
       this.onmyDuration()
     })
   }
-
+  // 切换月份
   onChangeDate(val) {
     let data = val.detail;
     this.onMyDurationMonth(this.state.data, data)
   }
 
   render() {
-    const { data, dateList, year, month, day } = this.state;
+    const { data, dateList, year, month, day, isVacation, isVopen } = this.state;
     return (
       <View className='punchClock'>
         <View className='header'>
@@ -387,7 +391,11 @@ class PunchClocks extends Component {
 
                   <View className='content'>
                     <View className='punchClockContent'
-                      onClick={this.publicReleaseClockIn}
+                      onClick={() => {
+                        isVacation
+                          ? this.setState({ isVopen: true })
+                          : this.publicReleaseClockIn()
+                      }}
                       style={{
                         boxShadow: '1px 1px 15px 1px #acb8ad',
                         background: '#009DD9',
@@ -416,6 +424,37 @@ class PunchClocks extends Component {
           </AtModalAction>
         </AtModal>
 
+        <AtModal
+          width="90%"
+          isOpened={isVopen}
+        >
+          <AtModalContent>
+            <View className='tips'>
+              <View className="tits">提示</View>
+              <View className="txts">
+                节假日为法定休息日,不安排上班!
+                如特殊原因且已与用人单位商议,需
+                研发打卡,请点击“继续打卡”。
+              </View>
+            </View>
+          </AtModalContent>
+          <AtModalAction>
+            <Button
+              onClick={() => {
+                this.setState({
+                  isVopen: false
+                }, () => {
+                  this.publicReleaseClockIn()
+                })
+              }}>继续打卡</Button>
+            <Button
+              onClick={() => {
+                this.setState({
+                  isVopen: false
+                })
+              }}>取消打卡</Button>
+          </AtModalAction>
+        </AtModal>
       </View >
     )
   }

+ 2 - 2
src/utils/servers/baseUrl.js

@@ -7,9 +7,9 @@ const getBaseUrl = (url) => {
     BASE_URL = 'https://yanfa.jishutao.com/prod-api'
   } else {
     // 生产环境
-    // BASE_URL = 'http://172.16.0.255:8888'
+    BASE_URL = 'http://172.16.0.255:8888'
     // BASE_URL = 'https://uat.jishutao.com'
-    BASE_URL = 'https://yanfa.jishutao.com/prod-api'
+    // BASE_URL = 'https://yanfa.jishutao.com/prod-api'
   }
   return BASE_URL
 }

+ 5 - 0
src/utils/servers/servers.js

@@ -67,6 +67,11 @@ export const listRecord = (postData = {}) => {
   return HTTPREQUEST.get('/api/project/listRecord', postData)
 }
 
+// 研发日志批量审核
+export const batchExamineRecord = (postData = {}) => {
+  return HTTPREQUEST.post('/api/project/batchExamineRecord', postData)
+}
+
 // 研发日志详情
 export const recordDetails = (postData = {}) => {
   return HTTPREQUEST.get('/api/project/recordDetails', postData)

+ 7 - 0
src/utils/tools/config.js

@@ -65,3 +65,10 @@ export const stageList = [
     value: 3,
   },
 ];
+
+export const dateList = [
+  "2016","2017","2018","2019","2020",
+  "2021","2022","2023","2024","2025",
+  "2026","2027","2028","2029","2030",
+  "2031","2032","2033","2034","2035",
+]