punchClocks.jsx 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  1. import React, { Component } from 'react'
  2. import { connect } from 'react-redux'
  3. import {Map, OpenData, View, Image} from '@tarojs/components'
  4. import Taro from '@tarojs/taro';
  5. import {AtIcon, AtModal, AtNoticebar} from "taro-ui";
  6. import dayjs from 'dayjs';
  7. import Skeleton from 'taro-skeleton'
  8. import ImagePicker from '../../components/common/imagePicker';
  9. import { add, minus, asyncAdd } from '../../actions/counter'
  10. import {getPublicReleaseList,publicReleaseClockIn} from '../../utils/servers/servers';
  11. import './index.less'
  12. import switchIocn from '../../image/switch.png';
  13. import 'taro-ui/dist/style/components/noticebar.scss';
  14. import 'taro-ui/dist/style/components/icon.scss';
  15. import 'taro-ui/dist/style/components/list.scss';
  16. const QQMapWX = require('../../components/common/mapSDK/qqmap-wx-jssdk.min.js');
  17. @connect(({ counter }) => ({
  18. counter
  19. }), (dispatch) => ({
  20. add () {
  21. dispatch(add())
  22. },
  23. dec () {
  24. dispatch(minus())
  25. },
  26. asyncAdd () {
  27. dispatch(asyncAdd())
  28. }
  29. }))
  30. class PunchClocks extends Component {
  31. constructor(props) {
  32. super(props);
  33. this.state={
  34. imgs:[],
  35. nowTime:'00:00:00',
  36. newArrder:{},
  37. addressLatitude:'',
  38. addressLongitude:'',
  39. distance:'',
  40. dtails:{},
  41. loading:true
  42. }
  43. this.onChange = this.onChange.bind(this);
  44. this.getSpacing = this.getSpacing.bind(this);
  45. this.getPublicReleaseList = this.getPublicReleaseList.bind(this);
  46. this.publicReleaseClockIn = this.publicReleaseClockIn.bind(this);
  47. this.refresh = this.refresh.bind(this);
  48. this.getDtails = this.getDtails.bind(this);
  49. }
  50. nowTime = null;
  51. qqmapsdk = new QQMapWX({
  52. key: 'AWBBZ-GRAC2-JFYUO-CLA7I-JAHXK-YFFGT'
  53. });
  54. componentDidMount(){
  55. this.getDtails();
  56. }
  57. getDtails(){
  58. this.getPublicReleaseList(()=>{
  59. Taro.startLocationUpdate({
  60. success:()=>{
  61. Taro.onLocationChange((v)=>{
  62. this.getSpacing(v.latitude,v.longitude)
  63. })
  64. },
  65. fail:(err)=>{
  66. console.log(err,'err')
  67. Taro.getSetting({
  68. success:(res)=>{
  69. if (!res.authSetting['scope.userLocation']) {
  70. Taro.authorize({
  71. scope: 'scope.userLocation',
  72. success:()=>{
  73. },
  74. fail:()=>{
  75. this.setState({
  76. isOpened:true
  77. })
  78. }
  79. })
  80. }
  81. }
  82. })
  83. this.setState({
  84. loading:false
  85. })
  86. }
  87. })
  88. });
  89. }
  90. componentWillMount() {
  91. //获得当前位置
  92. Taro.getLocation({
  93. type: 'gcj02',
  94. isHighAccuracy:true,
  95. success: (res)=> {
  96. const latitude = res.latitude
  97. const longitude = res.longitude
  98. this.setState({
  99. newArrder:{
  100. latitude,
  101. longitude
  102. },
  103. })
  104. }
  105. })
  106. this.nowTime = setInterval(()=>{
  107. this.setState({
  108. nowTime:dayjs().format('HH:mm:ss')
  109. })
  110. },1000)
  111. Taro.eventCenter.on('punchClockComponentDidShow', () => {
  112. if(Object.keys(this.state.dtails).length === 0){
  113. this.getDtails();
  114. }
  115. })
  116. Taro.eventCenter.on('GoPunchIn', (arg) => {
  117. this.setState({
  118. dtails:arg,
  119. addressLatitude:parseFloat(arg.latitude),
  120. addressLongitude:parseFloat(arg.longitude),
  121. },()=>{
  122. Taro.startLocationUpdate({
  123. success:()=>{
  124. Taro.onLocationChange((v)=>{
  125. this.getSpacing(v.latitude,v.longitude)
  126. })
  127. },
  128. fail:()=>{
  129. this.setState({
  130. loading:false
  131. })
  132. }
  133. })
  134. })
  135. })
  136. }
  137. componentDidHide() {
  138. Taro.offLocationChange();
  139. this.nowTime && this.nowTime.clearTimeout();
  140. }
  141. publicReleaseClockIn(){
  142. if(Object.keys(this.state.dtails).length === 0){
  143. Taro.showToast({title:'暂无公出申请,无法打卡',icon:'none'})
  144. return ;
  145. }
  146. if(isNaN(parseInt(this.state.distance))){
  147. Taro.showToast({title:'定位错误,请联系管理员',icon:'none'})
  148. return ;
  149. }
  150. if(!(this.state.distance <=100 && this.state.distance >= 0)){
  151. Taro.showToast({title:'当前位置未处于可打卡范围,无法打卡',icon:'none'})
  152. return ;
  153. }
  154. if(this.state.imgs.length === 0){
  155. Taro.showToast({title:'请上传打卡照片',icon:'none'})
  156. return ;
  157. }
  158. publicReleaseClockIn({
  159. id:this.state.dtails.id,
  160. photoUrl:this.state.imgs.join(',')
  161. }).then(v=>{
  162. if(v.error.length === 0){
  163. Taro.showToast({title:'打卡成功',icon:'none'});
  164. this.imagePicker.clear();
  165. this.state.dtails.clockIn = 1;
  166. this.setState({
  167. dtails:this.state.dtails,
  168. imgs:[]
  169. })
  170. }else{
  171. Taro.showToast({title:v.error[0].message,icon:'none'})
  172. }
  173. }).catch(()=>{
  174. Taro.showToast({
  175. title:'系统错误,请稍后再试',
  176. icon:'none'
  177. })
  178. })
  179. }
  180. getPublicReleaseList(fn){
  181. this.setState({
  182. loading:true
  183. })
  184. getPublicReleaseList({
  185. type:0,
  186. clockTime:dayjs().format('YYYY-MM-DD HH:mm:ss')
  187. }).then(v=>{
  188. if(v.error.length === 0){
  189. if(v.data.list.length === 0){
  190. getPublicReleaseList({
  191. type:0,
  192. }).then(value=>{
  193. if(value.error.length === 0){
  194. if(value.data.list.length === 0){
  195. this.setState({
  196. dtails: {},
  197. loading:false
  198. })
  199. }else{
  200. this.setState({
  201. dtails:value.data.list[0],
  202. addressLatitude:value.data.list[0].latitude,
  203. addressLongitude:value.data.list[0].longitude,
  204. },()=>{
  205. fn();
  206. })
  207. }
  208. }else{
  209. this.setState({
  210. loading:false
  211. })
  212. Taro.showToast({
  213. title:v.error[0].message,
  214. icon:'none'
  215. })
  216. }
  217. }).catch(()=>{
  218. this.setState({
  219. loading:false
  220. })
  221. Taro.showToast({
  222. title:'系统错误,请稍后再试',
  223. icon:'none'
  224. })
  225. })
  226. }else{
  227. this.setState({
  228. dtails:v.data.list[0],
  229. addressLatitude:v.data.list[0].latitude,
  230. addressLongitude:v.data.list[0].longitude,
  231. },()=>{
  232. fn();
  233. })
  234. }
  235. }else{
  236. this.setState({
  237. loading:false
  238. })
  239. Taro.showToast({
  240. title:v.error[0].message,
  241. icon:'none'
  242. })
  243. }
  244. }).catch((err)=>{
  245. console.log(err)
  246. this.setState({
  247. loading:false
  248. })
  249. Taro.showToast({
  250. title:'系统错误,请稍后再试',
  251. icon:'none'
  252. })
  253. })
  254. }
  255. getSpacing(latitude,longitude){
  256. let _this = this;
  257. this.qqmapsdk.calculateDistance({
  258. mode:'straight',
  259. from: {
  260. latitude: this.state.addressLatitude,
  261. longitude: this.state.addressLongitude,
  262. },
  263. to: [
  264. {
  265. latitude,
  266. longitude,
  267. }
  268. ],
  269. success: function(res) {//成功后的回调
  270. _this.setState({
  271. distance:res.result.elements[0].distance,
  272. loading:false
  273. })
  274. },
  275. fail: function(error) {
  276. _this.setState({
  277. loading:false
  278. })
  279. console.error(error);
  280. },
  281. complete: function(res) {
  282. }
  283. });
  284. }
  285. onChange(value,type){
  286. let arr = this.state.imgs.concat([]);
  287. if(type === 'add'){
  288. arr.push(value)
  289. }else if(type === 'remove'){
  290. arr.splice(value,1)
  291. }
  292. this.setState({
  293. imgs: arr,
  294. })
  295. }
  296. refresh(){
  297. this.getPublicReleaseList(()=>{
  298. Taro.startLocationUpdate({
  299. success:()=>{
  300. Taro.onLocationChange((v)=>{
  301. this.getSpacing(v.latitude,v.longitude)
  302. })
  303. }
  304. })
  305. });
  306. }
  307. render () {
  308. const {dtails} = this.state;
  309. return (
  310. <View className='punchClock'>
  311. <View className='header'>
  312. <Skeleton
  313. title
  314. avatar
  315. row={1}
  316. animateName='elastic'
  317. avatarShape='square'
  318. loading={this.state.loading}
  319. >
  320. <View className='headerContent'>
  321. <View className='userAvatarUrl'>
  322. <OpenData type='userAvatarUrl'/>
  323. </View>
  324. <View className='infor'>
  325. <View className='name'>
  326. {
  327. Object.keys(this.state.dtails).length <= 0 ?
  328. Taro.getStorageSync('userInfor').name:
  329. dtails.aname
  330. }
  331. </View>
  332. <View className='address'>
  333. 公出企业:
  334. {
  335. Object.keys(this.state.dtails).length <= 0 ?
  336. '无':
  337. dtails.nickname
  338. }
  339. </View>
  340. </View>
  341. {
  342. Object.keys(this.state.dtails).length <= 0 ?
  343. <View onClick={this.refresh} className='state' style={{
  344. alignSelf: 'center',
  345. textAlign:'center',
  346. color:'#b6b5b5',
  347. fontSize:'11px'
  348. }}>
  349. <AtIcon value='reload' size='20'/>
  350. <View>刷新</View>
  351. </View> :
  352. <View className='state' style={{
  353. color:dtails.status === 0 ? '#f31212' :
  354. dtails.status === 1 ? '#1d4fea' :
  355. dtails.status === 2 ? '#767272' : ''
  356. }}>
  357. <View>
  358. {
  359. dtails.status === 0 ? '驳回' :
  360. dtails.status === 1 ? '审核中' :
  361. dtails.status === 2 ? '通过' : ''
  362. }
  363. </View>
  364. <Image src={switchIocn} className='switchItem' onClick={()=>{
  365. Taro.switchTab({
  366. url: '/pages/examine/index',
  367. })
  368. }}/>
  369. </View>
  370. }
  371. </View>
  372. </Skeleton>
  373. </View>
  374. {
  375. Object.keys(this.state.dtails).length <= 0 ?
  376. <View className='content'>
  377. <View className='punchClockContent' onClick={this.publicReleaseClockIn} style={{
  378. boxShadow: '1px 1px 15px 1px #acb8ad',
  379. background: '#acb8ad',
  380. marginTop: '85px',
  381. }}>
  382. <View className='punchClockTitle'>公出打卡</View>
  383. <View className='punchClockTime'>{this.state.nowTime}</View>
  384. </View>
  385. <View className='noData'>
  386. <View className='tipsNoData'>
  387. 暂无公出申请
  388. </View>
  389. <View className='goOut' onClick={()=>{
  390. Taro.switchTab({
  391. url: '/pages/applyDepart/index',
  392. })
  393. }}>
  394. 点击前往申请公出
  395. </View>
  396. </View>
  397. </View>:
  398. <View className='content'>
  399. <View className='timeContent'>
  400. <View className='timeItem'>
  401. <View className='timeTitle'>公出开始时间</View>
  402. <View className='timeValue'>{dtails.releaseStarts}</View>
  403. </View>
  404. <View className='timeItem'>
  405. <View className='timeTitle'>公出结束时间</View>
  406. <View className='timeValue'>{dtails.releaseEnds}</View>
  407. </View>
  408. </View>
  409. <View className='photographContent'>
  410. <View className='photographTitle'>打卡拍照</View>
  411. <AtIcon onClick={()=>{
  412. Taro.chooseImage({
  413. count: 1,
  414. sizeType: ['compressed'],
  415. sourceType: ['camera'],
  416. success:(res)=> {
  417. // tempFilePath可以作为img标签的src属性显示图片
  418. const tempFilePaths = res.tempFilePaths
  419. this.imagePicker.onImgChange([{url:tempFilePaths[0]}],'add',0,'camera')
  420. }
  421. })
  422. }} value='camera' size='25' color='#4395ff'/>
  423. </View>
  424. <View style={{alignSelf:'flex-start',width:'100%'}}>
  425. <ImagePicker ref={ref => this.imagePicker = ref} url='/api/admin/release/upload' showAddBtn={false} onChange={this.onChange}/>
  426. </View>
  427. <View className='punchClockContent' onClick={()=>{
  428. let _this = this;
  429. Taro.getSetting({
  430. success:(res)=>{
  431. if (!res.authSetting['scope.userLocation']) {
  432. Taro.authorize({
  433. scope: 'scope.userLocation',
  434. success:()=>{
  435. _this.publicReleaseClockIn();
  436. },
  437. fail:()=>{
  438. this.setState({
  439. isOpened:true
  440. })
  441. }
  442. })
  443. }else{
  444. _this.publicReleaseClockIn();
  445. }
  446. }
  447. })
  448. }} style={{
  449. boxShadow: (!isNaN(parseInt(this.state.distance))) && this.state.distance <=100 && this.state.distance >= 0 ? (dtails.clockIn === 1 ? '1px 1px 15px 1px #3f82e8' : '1px 1px 15px 1px #659268') : '1px 1px 15px 1px #acb8ad',
  450. background: (!isNaN(parseInt(this.state.distance))) && this.state.distance <=100 && this.state.distance >= 0 ? (dtails.clockIn === 1 ? '#3f82e8' : '#72cb78') : '#acb8ad'
  451. }}>
  452. <View className='punchClockTitle'>公出打卡</View>
  453. <View className='punchClockTime'>{this.state.nowTime}</View>
  454. {dtails.clockIn === 1 ? <View className='refreshClock'>刷新打卡</View>:null}
  455. </View>
  456. <View className='map'>
  457. <Map
  458. {...this.state.newArrder}
  459. style={{
  460. height:'300px',
  461. width:'100%'
  462. }}
  463. circles={[
  464. {
  465. latitude: this.state.addressLatitude,
  466. longitude: this.state.addressLongitude,
  467. color: '#c92ddc82',
  468. fillColor: '#c92ddc82',
  469. radius: 100,
  470. strokeWidth: 1
  471. }
  472. ]}
  473. showLocation
  474. showCompass
  475. />
  476. </View>
  477. <View className='tips'>紫色区域为可打卡区域</View>
  478. </View>
  479. }
  480. <AtModal
  481. isOpened={this.state.isOpened}
  482. title='提醒'
  483. cancelText='取消'
  484. confirmText='确认'
  485. onClose={()=>{
  486. this.setState({
  487. isOpened:false,
  488. })
  489. }}
  490. onCancel={()=>{
  491. this.setState({
  492. isOpened:false,
  493. })
  494. }}
  495. onConfirm={()=>{
  496. this.setState({
  497. isOpened:false,
  498. },()=>{
  499. Taro.openSetting({
  500. success:(value)=> {
  501. if(value.authSetting['scope.userLocation']){
  502. Taro.getLocation({
  503. type: 'gcj02',
  504. isHighAccuracy:true,
  505. success: (res)=> {
  506. const latitude = res.latitude
  507. const longitude = res.longitude
  508. this.setState({
  509. newArrder:{
  510. latitude,
  511. longitude
  512. },
  513. })
  514. }
  515. })
  516. this.getDtails();
  517. }
  518. }
  519. })
  520. })
  521. }}
  522. content='您拒绝了定位权限,请先前往设置打开定位权限'
  523. />
  524. </View>
  525. )
  526. }
  527. }
  528. export default PunchClocks