punchClocks.jsx 28 KB

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