punchClocks.jsx 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857
  1. import React, { Component } from 'react'
  2. import { connect } from 'react-redux'
  3. import { Map, OpenData, View, Image, Text, Button } from '@tarojs/components'
  4. import Taro from '@tarojs/taro';
  5. import { AtIcon, AtModal, AtModalHeader, AtModalContent, AtModalAction, AtTextarea, AtRadio, AtList } from "taro-ui";
  6. import dayjs from 'dayjs';
  7. import Skeleton from 'taro-skeleton'
  8. import HistoricalClock from '../../components/historicalClock';
  9. import ImagePicker from '../../components/common/imagePicker';
  10. import { add, minus, asyncAdd } from '../../actions/counter'
  11. import { getPublicReleaseList, publicReleaseClockIn, getPunchClockInfo, getReleasetDails } from '../../utils/servers/servers';
  12. import './index.less'
  13. import switchIocn from '../../image/switch.png';
  14. import Location from '../../image/location.png';
  15. import PunchRange from '../../image/punchRange.png';
  16. import 'taro-ui/dist/style/components/noticebar.scss';
  17. import 'taro-ui/dist/style/components/icon.scss';
  18. import 'taro-ui/dist/style/components/list.scss';
  19. import "taro-ui/dist/style/components/radio.scss";
  20. import "taro-ui/dist/style/components/icon.scss";
  21. import { getClockState, getNewOptions } from "../../utils/tools";
  22. const QQMapWX = require('../../components/common/mapSDK/qqmap-wx-jssdk.min.js');
  23. @connect(({ counter }) => ({
  24. counter
  25. }), (dispatch) => ({
  26. add() {
  27. dispatch(add())
  28. },
  29. dec() {
  30. dispatch(minus())
  31. },
  32. asyncAdd() {
  33. dispatch(asyncAdd())
  34. }
  35. }))
  36. class PunchClocks extends Component {
  37. constructor(props) {
  38. super(props);
  39. this.state = {
  40. imgs: [],
  41. nowTime: '00:00:00',
  42. newArrder: {},
  43. addressLatitude: '',
  44. addressLongitude: '',
  45. defaultLat: '28.2424',
  46. defaultLng: '112.957',
  47. distance: '',
  48. dtails: {},
  49. data: {
  50. prdcList: []
  51. },
  52. loading: true,
  53. isAbnormalOpen: false,
  54. clockInRemarks: "",//打卡说明
  55. }
  56. this.onChange = this.onChange.bind(this);
  57. this.getSpacing = this.getSpacing.bind(this);
  58. this.getData = this.getData.bind(this);
  59. this.publicReleaseClockIn = this.publicReleaseClockIn.bind(this);
  60. this.abnormalClockIn = this.abnormalClockIn.bind(this);
  61. this.refresh = this.refresh.bind(this);
  62. this.getDtails = this.getDtails.bind(this);
  63. this.selectArrder = this.selectArrder.bind(this);
  64. this.selectOn = this.selectOn.bind(this);
  65. }
  66. nowTime = null;
  67. wxConfig = null;
  68. mapCtx = Taro.createMapContext('map');
  69. qqmapsdk = new QQMapWX({
  70. key: 'AWBBZ-GRAC2-JFYUO-CLA7I-JAHXK-YFFGT'
  71. });
  72. componentDidMount() {
  73. this.getDtails();
  74. }
  75. selectOn() {
  76. const { dtails, selectUid } = this.state
  77. if (!selectUid) {
  78. Taro.showToast({ title: '请选择您要打卡的企业', icon: 'none' });
  79. return
  80. }
  81. let list = dtails.prdList
  82. for (var i = 0; i < list.length; i++) {
  83. if (list[i].uid == selectUid) {
  84. console.log(list[i])
  85. this.setState({
  86. data: list[i],
  87. addressLatitude: parseFloat(list[i].latitude || this.state.defaultLat),
  88. addressLongitude: parseFloat(list[i].longitude || this.state.defaultLng),
  89. isTips: false,
  90. selectUid: "",
  91. })
  92. }
  93. }
  94. }
  95. selectArrder() {
  96. const { dtails, data } = this.state
  97. this.props.getId(dtails.id, data.uid)
  98. this.props.getHome()
  99. const key = "AWBBZ-GRAC2-JFYUO-CLA7I-JAHXK-YFFGT"; //使用在腾讯位置服务申请的key
  100. const referer = "科德打卡定位"; //调用插件的app的名称
  101. const category = "公司企业,房产小区";
  102. Taro.navigateTo({
  103. url:
  104. "plugin://chooseLocation/index?key=" +
  105. key +
  106. "&referer=" +
  107. referer +
  108. "&category=" +
  109. category,
  110. });
  111. }
  112. getDtails() {
  113. this.getData(() => {
  114. Taro.startLocationUpdate({
  115. success: () => {
  116. Taro.onLocationChange((v) => {
  117. this.getSpacing(v.latitude, v.longitude)
  118. })
  119. },
  120. fail: (err) => {
  121. Taro.getSetting({
  122. success: (res) => {
  123. if (!res.authSetting['scope.userLocation']) {
  124. Taro.authorize({
  125. scope: 'scope.userLocation',
  126. success: () => {
  127. },
  128. fail: () => {
  129. this.setState({
  130. isOpened: true
  131. })
  132. }
  133. })
  134. }
  135. }
  136. })
  137. this.setState({
  138. loading: false
  139. })
  140. }
  141. })
  142. });
  143. }
  144. componentWillMount() {
  145. let obj = Taro.getStorageSync('userInfor');
  146. if (!obj) {
  147. // 判断是否登录
  148. return
  149. }
  150. this.wxConfig = Taro.getStorageSync('wxConfig');
  151. //获得当前位置
  152. Taro.getLocation({
  153. type: 'gcj02',
  154. isHighAccuracy: true,
  155. success: (res) => {
  156. const latitude = res.latitude
  157. const longitude = res.longitude
  158. this.setState({
  159. newArrder: {
  160. latitude,
  161. longitude
  162. },
  163. })
  164. }
  165. })
  166. this.nowTime = setInterval(() => {
  167. this.setState({
  168. nowTime: dayjs().format('HH:mm:ss')
  169. })
  170. }, 1000)
  171. Taro.eventCenter.on('punchClockComponentDidShow', () => {
  172. if (Object.keys(this.state.dtails).length === 0) {
  173. this.getDtails();
  174. }
  175. })
  176. Taro.eventCenter.on('GoPunchIn', (arg) => {
  177. getReleasetDails({
  178. id: arg.id,
  179. }).then((v) => {
  180. if (v.error.length === 0) {
  181. if (v.data) {
  182. if (!v.data.prdList) {
  183. return
  184. }
  185. let data = v.data.prdList[0]
  186. this.setState({
  187. dtails: v.data,
  188. data,
  189. addressLatitude: parseFloat(data.latitude || this.state.defaultLat),
  190. addressLongitude: parseFloat(data.longitude || this.state.defaultLng),
  191. }, () => {
  192. Taro.showToast({ title: '切换成功' });
  193. Taro.startLocationUpdate({
  194. success: () => {
  195. Taro.onLocationChange((v) => {
  196. this.getSpacing(v.latitude, v.longitude)
  197. })
  198. },
  199. fail: () => {
  200. this.setState({
  201. loading: false
  202. })
  203. }
  204. })
  205. })
  206. } else {
  207. }
  208. } else {
  209. Taro.showToast({ title: v.error[0].message, icon: "none" });
  210. }
  211. }).catch((err) => {
  212. Taro.showToast({ title: "系统错误,请稍后再试", icon: "none" });
  213. });
  214. })
  215. }
  216. componentDidHide() {
  217. Taro.offLocationChange();
  218. this.nowTime && this.nowTime.clearTimeout();
  219. }
  220. // 正常打卡
  221. publicReleaseClockIn(uid) {
  222. const { dtails } = this.state
  223. if (dtails.status !== 2) {
  224. Taro.hideLoading()
  225. Taro.showToast({ title: '公出审核中,不可打卡', icon: 'none' });
  226. return;
  227. }
  228. if (dtails.type === 3 && dtails.publicAssistAdvice === 0) {
  229. Taro.hideLoading()
  230. Taro.showToast({ title: '未填写协单意见,不可打卡', icon: 'none' });
  231. return;
  232. }
  233. if (dtails.status === 3) {
  234. Taro.hideLoading()
  235. Taro.showToast({ title: '申请已撤销,无法打卡', icon: 'none' });
  236. return;
  237. }
  238. if (Object.keys(dtails).length === 0) {
  239. Taro.hideLoading()
  240. Taro.showToast({ title: '暂无公出申请,无法打卡', icon: 'none' });
  241. return;
  242. }
  243. if (![5, 6].includes(dtails.type) && isNaN(parseInt(this.state.distance))) {
  244. Taro.hideLoading()
  245. Taro.showToast({ title: '定位错误,请联系管理员', icon: 'none' })
  246. return;
  247. }
  248. if ([5, 6].indexOf(dtails.type) === -1 && (dayjs().isBefore(dtails.releaseStarts) || dayjs().isAfter(dtails.releaseEnds))) {
  249. Taro.hideLoading()
  250. Taro.showToast({ title: '当前时间不在打卡时间范围内,无法打卡', icon: 'none' })
  251. return;
  252. } else if (dayjs().isAfter(dayjs(dtails.releaseEnds).add(1, 'day'))) {
  253. Taro.hideLoading()
  254. Taro.showToast({ title: '当前时间不在打卡时间范围内,无法打卡', icon: 'none' })
  255. return;
  256. }
  257. // 非公出协单不受位置影响
  258. if ([5, 6].indexOf(dtails.type) === -1 && !(this.state.distance <= this.wxConfig.clockInRange && this.state.distance >= 0)) {
  259. Taro.hideLoading()
  260. Taro.showToast({ title: '当前位置未处于可打卡范围,无法打卡', icon: 'none' })
  261. return;
  262. }
  263. // if (dtails.type == 0 && (dtails.publicType == 1 || dtails.publicType == 3)) {
  264. // Taro.hideLoading()
  265. // Taro.showToast({ title: '公出他人企业!需通过审核,才可打卡!', icon: 'none' });
  266. // return
  267. // }
  268. // if (dtails.type == 1 && (dtails.techStartProcess == 1 || dtails.techStartProcess == 3)) {
  269. // Taro.hideLoading()
  270. // Taro.showToast({ title: '已超过合同规定时限,需审核通过,才可打卡!', icon: 'none' });
  271. // return
  272. // }
  273. if (this.state.imgs.length === 0) {
  274. Taro.hideLoading()
  275. Taro.showToast({ title: '请上传打卡照片', icon: 'none' })
  276. return;
  277. }
  278. publicReleaseClockIn({
  279. id: dtails.id,
  280. photoUrl: this.state.imgs.join(','),
  281. clockIn: 1,
  282. uid: this.state.data.uid,
  283. }).then(v => {
  284. Taro.hideLoading()
  285. if (v.error.length === 0) {
  286. Taro.showToast({
  287. title: dtails.type == 1
  288. ? ((dtails.techStartProcess == 1 || dtails.techStartProcess == 3)
  289. ? '打卡成功!此次公出未通过营销审核!'
  290. : '打卡成功!')
  291. : '打卡成功!',
  292. icon: 'none'
  293. });
  294. this.imagePicker.clear();
  295. this.state.data.prdcList[0].status = 1;
  296. this.setState({
  297. data: this.state.data,
  298. imgs: []
  299. })
  300. } else {
  301. Taro.showToast({ title: v.error[0].message, icon: 'none' })
  302. }
  303. }).catch(() => {
  304. Taro.hideLoading()
  305. Taro.showToast({
  306. title: '系统错误,请稍后再试',
  307. icon: 'none'
  308. })
  309. })
  310. }
  311. // 异常打卡
  312. abnormalClockIn() {
  313. if (!this.state.clockInRemarks) {
  314. Taro.showToast({ title: '请填写异常打卡原因!', icon: 'none' })
  315. return;
  316. }
  317. Taro.showLoading({ title: '正在提交...' });
  318. publicReleaseClockIn({
  319. id: this.state.dtails.id,
  320. photoUrl: this.state.imgs.join(','),
  321. clockInRemarks: this.state.clockInRemarks,
  322. clockIn: 2,
  323. }).then(v => {
  324. Taro.hideLoading()
  325. if (v.error.length === 0) {
  326. Taro.showToast({ title: '打卡成功', icon: 'none' });
  327. this.imagePicker.clear();
  328. this.state.data.prdcList[0].status = 2;
  329. this.setState({
  330. data: this.state.data,
  331. imgs: [],
  332. clockInRemarks: "",
  333. isAbnormalOpen: false,
  334. })
  335. } else {
  336. Taro.showToast({ title: v.error[0].message, icon: 'none' })
  337. }
  338. }).catch(() => {
  339. Taro.hideLoading()
  340. Taro.showToast({
  341. title: '系统错误,请稍后再试',
  342. icon: 'none'
  343. })
  344. })
  345. }
  346. getData(fn) {
  347. this.setState({
  348. loading: true
  349. })
  350. getPunchClockInfo().then(v => {
  351. if (v.error.length === 0) {
  352. this.setState({
  353. loading: false
  354. })
  355. if (v.data) {
  356. let data = v.data.prdList[0]
  357. this.setState({
  358. dtails: v.data,
  359. data,
  360. addressLatitude: data.latitude || this.state.defaultLat,
  361. addressLongitude: data.longitude || this.state.defaultLng,
  362. }, () => {
  363. fn();
  364. })
  365. } else {
  366. this.setState({
  367. dtails: {},
  368. data: {},
  369. })
  370. }
  371. } else {
  372. this.setState({
  373. loading: false
  374. })
  375. Taro.showToast({
  376. title: v.error[0].message,
  377. icon: 'none'
  378. })
  379. }
  380. })
  381. }
  382. getSpacing(latitude, longitude) {
  383. let _this = this;
  384. this.qqmapsdk.calculateDistance({
  385. mode: 'straight',
  386. from: {
  387. latitude: this.state.addressLatitude,
  388. longitude: this.state.addressLongitude,
  389. },
  390. to: [
  391. {
  392. latitude,
  393. longitude,
  394. }
  395. ],
  396. success: function (res) {//成功后的回调
  397. _this.setState({
  398. distance: res.result.elements[0].distance,
  399. loading: false
  400. })
  401. },
  402. fail: function (error) {
  403. _this.setState({
  404. loading: false
  405. })
  406. console.error(error);
  407. },
  408. complete: function (res) {
  409. }
  410. });
  411. }
  412. onChange(value, type) {
  413. let arr = this.state.imgs.concat([]);
  414. if (type === 'add') {
  415. arr.push(value)
  416. } else if (type === 'remove') {
  417. arr.splice(value, 1)
  418. }
  419. this.setState({
  420. imgs: arr,
  421. })
  422. }
  423. refresh() {
  424. this.getData(() => {
  425. Taro.startLocationUpdate({
  426. success: () => {
  427. Taro.onLocationChange((v) => {
  428. this.getSpacing(v.latitude, v.longitude)
  429. })
  430. }
  431. })
  432. });
  433. }
  434. getClockBgColor() {
  435. const { dtails, distance, data } = this.state
  436. const newClockIn = !!data.prdcList && data.prdcList.length > 0 ? data.prdcList[0] : {};
  437. if ([5, 6].indexOf(dtails.type) > -1) {
  438. if (!dayjs().isAfter(dayjs(dtails.releaseEnds).add(1, 'day'))) {
  439. return [1, 2].includes(newClockIn.status) ? '#3f82e8' : '#72cb78'
  440. } else {
  441. return '#828e83'
  442. }
  443. } else {
  444. return (!isNaN(parseInt(distance)))
  445. && distance <= this.wxConfig.clockInRange
  446. && distance >= 0
  447. && !(dayjs().isBefore(dtails.releaseStarts) || dayjs().isAfter(dtails.releaseEnds))
  448. && dtails.status === 2
  449. ? dtails.type === 3
  450. ? dtails.publicAssistAdvice > 0
  451. ? ((newClockIn.status === 1 || newClockIn.status === 2) ? '#3f82e8' : '#72cb78')
  452. : '#828e83'
  453. : ((newClockIn.status === 1 || newClockIn.status === 2) ? '#3f82e8' : '#72cb78')
  454. : '#828e83'
  455. }
  456. }
  457. render() {
  458. const { dtails, data } = this.state;
  459. const newClockIn = !!data.prdcList && data.prdcList.length > 0 ? data.prdcList[0] : {};
  460. return (
  461. <View className='punchClock'>
  462. <View className='header'>
  463. <Skeleton
  464. title
  465. avatar
  466. row={2}
  467. animateName='elastic'
  468. avatarShape='square'
  469. loading={this.state.loading}
  470. >
  471. <View className='headerContent'>
  472. <View className='userAvatarUrl'>
  473. <OpenData type='userAvatarUrl' />
  474. </View>
  475. <View className='infor'>
  476. <View className='name'>
  477. {
  478. Object.keys(dtails).length <= 0 ?
  479. Taro.getStorageSync('userInfor').name :
  480. dtails.aname
  481. }
  482. </View>
  483. <View className='types'
  484. style={{ color: ["#1D4FEA", "#1E90FF", "#FF5500", "red", "", "#1D4FEA"][dtails.type] }}
  485. >
  486. {["业务公出", "技术公出", "行政公出", "技术协单", "", "非公出协单", "非公出协单"][dtails.type]}
  487. </View>
  488. </View>
  489. {
  490. Object.keys(this.state.dtails).length <= 0 ?
  491. <View onClick={this.refresh} className='state' style={{
  492. alignSelf: 'center',
  493. textAlign: 'center',
  494. color: '#b6b5b5',
  495. fontSize: '11px'
  496. }}>
  497. <AtIcon value='reload' size='20' />
  498. <View>刷新</View>
  499. </View> :
  500. <View className='state' style={{
  501. color: getClockState(dtails.status).color
  502. }}>
  503. <View style={{ textAlign: 'right' }}>
  504. {
  505. getClockState(dtails.status).title
  506. }
  507. </View>
  508. <View className='switchContent' onClick={() => {
  509. Taro.switchTab({
  510. url: '/pages/mybusiness/index',
  511. })
  512. }}>
  513. <View className='switchTitle'>切换打卡</View>
  514. <Image src={switchIocn} className='switchItem' />
  515. </View>
  516. </View>
  517. }
  518. </View>
  519. </Skeleton>
  520. </View>
  521. {
  522. Object.keys(this.state.dtails).length <= 0 ?
  523. <View className='content'>
  524. <View className='punchClockContent'
  525. onClick={this.publicReleaseClockIn}
  526. style={{
  527. boxShadow: '1px 1px 15px 1px #acb8ad',
  528. background: '#828e83',
  529. marginTop: '85px',
  530. }}>
  531. <View className='punchClockTitle'>公出打卡</View>
  532. <View className='punchClockTime'>{this.state.nowTime}</View>
  533. </View>
  534. <View className='noData'>
  535. <View className='tipsNoData'>
  536. 暂无公出申请
  537. </View>
  538. <View className='goOut' onClick={() => {
  539. Taro.switchTab({
  540. url: '/pages/applyDepart/index',
  541. })
  542. }}>
  543. 点击前往申请公出
  544. </View>
  545. </View>
  546. </View> :
  547. <View>
  548. <View className='content'>
  549. <View className="enterprise">
  550. <View className='entit'>公出企业</View>
  551. <View className='userlist'>
  552. <Text className='username'>
  553. {data.userName}
  554. {(newClockIn.status === 1 || newClockIn.status === 2) && <Text style={{ color: "#72cb78" }}>(已打卡)</Text>}
  555. </Text>
  556. {
  557. this.state.dtails.prdList?.length > 1 &&
  558. <View className='switch' onClick={() => { this.setState({ isTips: true }) }}>
  559. <View className='stxt'>切换企业</View>
  560. <Image src={switchIocn} className='sicon' />
  561. </View>
  562. }
  563. </View>
  564. </View>
  565. <View className='timeContent'>
  566. <View className='timeItem'>
  567. <View className='timeTitle'>公出开始时间</View>
  568. <View className='timeValue'>{dtails.releaseStarts}</View>
  569. </View>
  570. <View className='timeItem'>
  571. <View className='timeTitle'>公出结束时间</View>
  572. <View className='timeValue'>{dtails.releaseEnds}</View>
  573. </View>
  574. </View>
  575. <View className='photographContent'>
  576. <View className='photographTitle'>打卡拍照<Text className='tips'>〔可以上传多张〕</Text></View>
  577. <AtIcon onClick={() => {
  578. Taro.chooseImage({
  579. count: 1,
  580. sizeType: ['compressed'],
  581. sourceType: ['camera'],
  582. success: (res) => {
  583. // tempFilePath可以作为img标签的src属性显示图片
  584. const tempFilePaths = res.tempFilePaths
  585. this.imagePicker.onImgChange([{ url: tempFilePaths[0] }], 'add', 0, 'camera')
  586. }
  587. })
  588. }} value='camera' size='25' color='#4395ff' />
  589. </View>
  590. <View style={{ alignSelf: 'flex-start', width: '100%' }}>
  591. <ImagePicker ref={ref => this.imagePicker = ref} url='/api/admin/release/upload' showAddBtn={false} onChange={this.onChange} />
  592. </View>
  593. {/* 异常打卡 */}
  594. {
  595. // dtails.type == 3 &&
  596. false &&
  597. <View
  598. className="photographUnusual"
  599. style={{ background: newClockIn.status === 1 ? "#f69c9f" : "red" }}
  600. onClick={() => {
  601. if (this.state.imgs.length === 0) {
  602. Taro.hideLoading()
  603. Taro.showToast({ title: '请上传打卡照片', icon: 'none' })
  604. return;
  605. }
  606. this.setState({
  607. isAbnormalOpen: true
  608. })
  609. }}
  610. >{(newClockIn.status === 1 || newClockIn.status === 2) ? "更新打卡" : "异常打卡"}</View>
  611. }
  612. <View className='punchClockContent'
  613. onClick={() => {
  614. let _this = this;
  615. Taro.showLoading({ title: '加载中...' })
  616. Taro.getSetting({
  617. success: (res) => {
  618. if (!res.authSetting['scope.userLocation']) {
  619. Taro.authorize({
  620. scope: 'scope.userLocation',
  621. success: () => {
  622. _this.publicReleaseClockIn();
  623. },
  624. fail: () => {
  625. Taro.hideLoading()
  626. this.setState({
  627. isOpened: true
  628. })
  629. }
  630. })
  631. } else {
  632. _this.publicReleaseClockIn();
  633. }
  634. }
  635. })
  636. }}
  637. style={{
  638. boxShadow: '1px 1px 15px 1px '+this.getClockBgColor(),
  639. background: this.getClockBgColor()
  640. }}>
  641. <View className='punchClockTitle'>
  642. {
  643. (newClockIn.status === 1 || newClockIn.status === 2) ?
  644. '更新打卡' : '公出打卡'
  645. }
  646. </View>
  647. <View className='punchClockTime'>{this.state.nowTime}</View>
  648. <View
  649. onClick={e => {
  650. e.stopPropagation()
  651. this.refresh()
  652. }}
  653. className='refresh'
  654. style={{
  655. alignSelf: 'center',
  656. textAlign: 'center',
  657. color: '#b6b5b5',
  658. fontSize: '11px'
  659. }}>
  660. <AtIcon value='reload' size='20' />
  661. <View>刷新</View>
  662. </View>
  663. </View>
  664. {
  665. !(this.state.distance <= this.wxConfig.clockInRange && this.state.distance >= 0) && ![5, 6].includes(dtails.type) &&
  666. <View className='switchposition'>您不在打卡范围:
  667. <Text className='stxt' onClick={this.selectArrder}>切换位置</Text>
  668. </View>
  669. }
  670. {/* {
  671. !(this.state.distance <= this.wxConfig.clockInRange && this.state.distance >= 0) ?
  672. <View className='switchposition'>您不在打卡范围:
  673. <Text className='stxt' onClick={this.selectArrder}>切换位置</Text>
  674. </View> : (dtails.type == 0 && (dtails.publicType == 1 || dtails.publicType == 3)) ?
  675. <View className='switchposition'>公出他人企业!需通过审核,才可打卡!</View>
  676. : (dtails.type == 1 && (dtails.techStartProcess == 1 || dtails.techStartProcess == 3)) ?
  677. <View className='switchposition'>已超过合同规定时限,需审核通过,才可打卡!</View>
  678. : null
  679. } */}
  680. <View className='map'>
  681. <View className='locationContent'>
  682. <View className='location' onClick={() => {
  683. this.mapCtx.moveToLocation();
  684. }}>
  685. <Image src={Location} className='locationIcon' />
  686. </View>
  687. <View className='punchRange'
  688. onClick={() => {
  689. this.mapCtx.moveToLocation({
  690. latitude: this.state.addressLatitude,
  691. longitude: this.state.addressLongitude,
  692. });
  693. }}>
  694. <Image src={PunchRange} className='punchRangeIcon' />
  695. </View>
  696. </View>
  697. <Map
  698. id='map'
  699. {...this.state.newArrder}
  700. circles={[
  701. {
  702. latitude: this.state.addressLatitude,
  703. longitude: this.state.addressLongitude,
  704. color: '#c92ddc82',
  705. fillColor: '#c92ddc82',
  706. radius: this.wxConfig.clockInRange,
  707. strokeWidth: 1
  708. }
  709. ]}
  710. showLocation
  711. />
  712. </View>
  713. <View className='tips'>紫色区域为可打卡区域</View>
  714. </View>
  715. <View className='content' onClick={() => {
  716. this.setState({
  717. historicalIsOpened: true
  718. })
  719. }}>
  720. <View className='history'>
  721. <View>查看公出申请日志</View>
  722. <AtIcon value='chevron-right' size='20' color='#767272' />
  723. </View>
  724. </View>
  725. </View>
  726. }
  727. <AtModal
  728. isOpened={this.state.isOpened}
  729. title='提醒'
  730. cancelText='取消'
  731. confirmText='确认'
  732. onClose={() => {
  733. this.setState({
  734. isOpened: false,
  735. })
  736. }}
  737. onCancel={() => {
  738. this.setState({
  739. isOpened: false,
  740. })
  741. }}
  742. onConfirm={() => {
  743. this.setState({
  744. isOpened: false,
  745. }, () => {
  746. Taro.openSetting({
  747. success: (value) => {
  748. if (value.authSetting['scope.userLocation']) {
  749. Taro.getLocation({
  750. type: 'gcj02',
  751. isHighAccuracy: true,
  752. success: (res) => {
  753. const latitude = res.latitude
  754. const longitude = res.longitude
  755. this.setState({
  756. newArrder: {
  757. latitude,
  758. longitude
  759. },
  760. })
  761. }
  762. })
  763. this.getDtails();
  764. }
  765. }
  766. })
  767. })
  768. }}
  769. content='您拒绝了定位权限,请先前往设置打开定位权限'
  770. />
  771. {/* 异常打卡原因 */}
  772. {
  773. this.state.isAbnormalOpen &&
  774. <AtModal isOpened={this.state.isAbnormalOpen}>
  775. <AtModalContent>
  776. <AtTextarea
  777. value={this.state.clockInRemarks}
  778. onChange={e => { this.setState({ clockInRemarks: e }) }}
  779. maxLength={200}
  780. placeholder='请填写异常打卡原因~'
  781. />
  782. </AtModalContent>
  783. <AtModalAction>
  784. <Button type='secondary' onClick={() => { this.setState({ isAbnormalOpen: false }) }}>取消</Button>
  785. <Button type='primary' onClick={this.abnormalClockIn}>提交</Button>
  786. </AtModalAction>
  787. </AtModal>
  788. }
  789. {
  790. this.state.historicalIsOpened &&
  791. <HistoricalClock
  792. id={dtails.id}
  793. isOpened={this.state.historicalIsOpened}
  794. onClose={() => {
  795. this.setState({
  796. historicalIsOpened: false
  797. })
  798. }}
  799. />
  800. }
  801. {
  802. this.state.isTips &&
  803. <AtModal isOpened={this.state.isTips}>
  804. <AtModalHeader>请选择</AtModalHeader>
  805. <AtModalContent>
  806. <AtRadio
  807. options={getNewOptions(dtails.prdList)}
  808. value={this.state.selectUid}
  809. onClick={e => { this.setState({ selectUid: e }) }}
  810. />
  811. </AtModalContent>
  812. <AtModalAction>
  813. <Button type='secondary' onClick={() => { this.setState({ isTips: false }) }}>取消</Button>
  814. <Button type='primary' onClick={this.selectOn}>确定</Button>
  815. </AtModalAction>
  816. </AtModal>
  817. }
  818. </View>
  819. )
  820. }
  821. }
  822. export default PunchClocks