index.vue 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. <template>
  2. <view class="container">
  3. <view class="tab">
  4. <view class="tab-item" @click="chanegTab(1)" :class="tabIdx===1?'active':''">
  5. <view class="text">打卡签到</view>
  6. </view>
  7. <view class="tab-item" @click="chanegTab(2)" :class="tabIdx===2?'active':''">
  8. <view class="text">打卡记录</view>
  9. </view>
  10. </view>
  11. <view class="tab-content">
  12. <view class="tab-wrap">
  13. <view class="signIn" v-if="tabIdx===1">
  14. <view class="info">
  15. <view class="date">日期:<text class="text">{{signInDate}}</text></view>
  16. <view class="location">地点:<text class="text">{{formData.dutyLocation}}</text></view>
  17. </view>
  18. <view class="signIn-handle" @click="creatDuty">
  19. <view class="name">打卡</view>
  20. <view class="signInTime">{{signInTime}}</view>
  21. </view>
  22. </view>
  23. <view class="list" v-if="tabIdx===2">
  24. <!-- <view>
  25. <uni-calendar
  26. ref="calendar"
  27. :insert="false"
  28. @confirm="confirm"
  29. />
  30. <button @click="open">打开日历</button>
  31. </view> -->
  32. <view class="item" v-for="(item,index) in items" :key="index">
  33. <view class="item-info">
  34. <view class="location">
  35. <text>位置:</text>
  36. <text>{{item.dutyLocation}}</text>
  37. </view>
  38. <view class="date">{{item.dutyTime}}</view>
  39. </view>
  40. <view class="item-icon-box" @click="previewImage(item.dutyPhoto)">
  41. <img class="item-icon" :src="item.dutyIcon" alt="打卡图片">
  42. </view>
  43. </view>
  44. </view>
  45. </view>
  46. </view>
  47. <view class="alert success" v-if="state===1">
  48. <view class="mask">
  49. <view class="alert-wrap">
  50. <image class="icon" src="/static/face.png" mode="widthFix"></image>
  51. <view class="tip">打卡成功</view>
  52. <view class="button" @click="state=0">确定</view>
  53. </view>
  54. </view>
  55. </view>
  56. </view>
  57. </template>
  58. <script>
  59. import {parseTime} from '@/utils/index.js';
  60. import { creatDuty} from '@/api/system/dutyApi.js';
  61. import { getDutyRecord} from '@/api/system/dutyApi.js';
  62. import {upload} from '@/api/system/upload.js';
  63. export default{
  64. data(){
  65. return{
  66. signInDate:parseTime(new Date(),'{y}-{m}-{d}'),
  67. signInTime:parseTime(new Date(),'{h}:{i}'),
  68. timer:null,
  69. tabIdx:1,
  70. state:0,
  71. dutyDate:new Date(),
  72. formData:{
  73. dutyLocation:"",
  74. dutyPhoto:"",
  75. dutyIcon:"",
  76. dutyLongitude:"",
  77. dutyLatitude:""
  78. },
  79. items:[]
  80. }
  81. },
  82. created() {
  83. let qrcode=uni.getStorageSync('qrcode')
  84. this.formData.dutyLocation=qrcode.targetTitle||"--"
  85. this.getLocation()
  86. this.setTime()
  87. },
  88. methods:{
  89. open(){
  90. this.$refs.calendar.open();
  91. },
  92. confirm(e) {
  93. console.log(e);
  94. },
  95. setTime(){
  96. this.timer=setInterval(()=>{
  97. this.signInTime=parseTime(new Date(),'{h}:{i}')
  98. },1000)
  99. },
  100. getLocation(){
  101. const self=this;
  102. uni.getLocation({
  103. type: 'wgs84',
  104. success: function (res) {
  105. self.formData.dutyLongitude=res.longitude
  106. self.formData.dutyLatitude=res.latitude
  107. }
  108. });
  109. },
  110. creatDuty(){
  111. const self=this;
  112. uni.chooseImage({
  113. sourceType: ['camera'],
  114. success(res) {
  115. self.onsubmit(res)
  116. },
  117. fail() {
  118. uni.showToast({
  119. icon:"none",
  120. title:"打卡失败"
  121. })
  122. }
  123. })
  124. // let filePath=e.tempFiles[0].url
  125. // let fileresq=await upload({filePath})
  126. },
  127. async onsubmit(res){
  128. let filePath=res.tempFiles[0].path
  129. let fileResq=await upload({filePath,formData:{
  130. additions: `经度:${this.formData.dutyLongitude};纬度:${this.formData.dutyLatitude}`
  131. }})
  132. let file=JSON.parse(fileResq).data
  133. creatDuty({
  134. dutyLocation:this.formData.dutyLocation,
  135. dutyPhoto:file.fileUrl,
  136. dutyIcon:file.fileIcon,
  137. dutyLongitude:this.formData.dutyLongitude,
  138. dutyLatitude:this.formData.dutyLatitude
  139. }).then(()=>{
  140. this.state=1
  141. }).catch(()=>{
  142. uni.showToast({
  143. icon:"none",
  144. title:"打卡失败"
  145. })
  146. })
  147. },
  148. chanegTab(idx){
  149. this.tabIdx=idx
  150. if(idx===2){
  151. this.getRecord()
  152. }
  153. },
  154. getRecord(){
  155. let dutyDate=parseTime(this.dutyDate,"{y}-{m}-{d}")
  156. getDutyRecord(dutyDate).then((res)=>{
  157. this.items=res.data
  158. })
  159. },
  160. previewImage(img){
  161. uni.previewImage({
  162. urls:[img]
  163. })
  164. }
  165. },
  166. onUnload() {
  167. clearInterval(this.timer)
  168. }
  169. }
  170. </script>
  171. <style lang="scss" scoped>
  172. .container{
  173. .tab{
  174. .tab-item{
  175. width: 50%;
  176. display: inline-block;
  177. padding: 0 100rpx;
  178. box-sizing: border-box;
  179. .text{
  180. height: 100rpx;
  181. line-height: 100rpx;
  182. text-align: center;
  183. color: rgba(33, 33, 33, 1);
  184. }
  185. &.active{
  186. .text{
  187. color: rgba(77, 115, 255, 1);
  188. }
  189. }
  190. }
  191. }
  192. .tab-content{
  193. background-color: rgba(245, 246, 248, 1);
  194. padding: 32rpx;
  195. .tab-wrap{
  196. background-color: #fff;
  197. min-height: calc(100vh - 170rpx);
  198. }
  199. .signIn{
  200. padding-top: 32rpx;
  201. .info{
  202. background-color: rgba(245, 246, 248, 1);
  203. width: 622rpx;
  204. margin: 0 auto;
  205. padding: 32rpx;
  206. box-sizing: border-box;
  207. .date{
  208. font-size: 30rpx;
  209. color:rgba(153, 153, 153, 1);
  210. .text{
  211. color: rgba(33, 33, 33, 1);
  212. }
  213. }
  214. .location{
  215. font-size: 30rpx;
  216. color:rgba(153, 153, 153, 1);
  217. .text{
  218. color: rgba(33, 33, 33, 1);
  219. }
  220. }
  221. }
  222. .signIn-handle{
  223. width: 300rpx;
  224. height: 300rpx;
  225. border-radius: 50%;
  226. display: flex;
  227. justify-content: center;
  228. align-items: center;
  229. flex-direction: column;
  230. margin: 180rpx auto;
  231. background-color: rgba(90, 125, 251, 1);
  232. box-shadow: 0px 4px 20px 0px rgba(77, 115, 255, 0.3);
  233. .name{
  234. font-size: 40rpx;
  235. color: #fff;
  236. }
  237. .signInTime{
  238. font-size: 30rpx;
  239. color: rgba(255, 255, 255, 0.7);
  240. }
  241. }
  242. }
  243. .list{
  244. background-color: rgba(245, 246, 248, 1);
  245. .item{
  246. margin-bottom: 20rpx;
  247. display: flex;
  248. align-items: center;
  249. background-color: #fff;
  250. padding: 30rpx;
  251. border-radius: 16rpx;
  252. .item-info{
  253. flex: 1;
  254. .location{
  255. font-weight: 400;
  256. font-size: 34rpx;
  257. color: rgba(33, 33, 33, 1);
  258. }
  259. .date{
  260. font-size: 24rpx;
  261. color: rgba(33, 33, 33, 1);
  262. padding-top: 24rpx;
  263. }
  264. }
  265. .item-icon-box{
  266. width: 228rpx;
  267. height: 152rpx;
  268. background-color: rgba(245, 246, 248, 1);
  269. .item-icon{
  270. display: block;
  271. width: 228rpx;
  272. height: 152rpx;
  273. }
  274. }
  275. }
  276. }
  277. }
  278. .alert{
  279. .mask{
  280. display: block;
  281. position: fixed;
  282. content: "";
  283. left: 0;
  284. right: 0;
  285. top: 0;
  286. bottom: 0;
  287. background-color: rgba(0,0,0,0.6);
  288. z-index: 99
  289. }
  290. .alert-wrap{
  291. width: 630rpx;
  292. height: 556rpx;
  293. background-color: #fff;
  294. position: fixed;
  295. left: 50%;
  296. top: 50%;
  297. transform: translate(-50%,-50%);
  298. z-index: 999;
  299. border-radius: 16rpx;
  300. display: flex;
  301. justify-content: center;
  302. align-items: center;
  303. flex-direction: column;
  304. .icon{
  305. width: 160rpx;
  306. }
  307. .tip{
  308. font-size: 48rpx;
  309. color: rgba(77, 115, 255, 1);
  310. font-weight: 600;
  311. padding: 22rpx 0 40rpx 0;
  312. }
  313. .button{
  314. width: 360rpx;
  315. height: 84rpx;
  316. text-align: center;
  317. line-height: 84rpx;
  318. color: rgba(77, 115, 255, 1);
  319. font-size: 30rpx;
  320. border: 1px solid rgba(77, 115, 255, 1);
  321. border-radius: 8rpx;
  322. }
  323. }
  324. }
  325. }
  326. </style>