【PT.SCC实名制管理系统】24.10.01 -30天,考勤打卡小程序
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

341 lines
7.4 KiB

7 months ago
7 months ago
7 months ago
6 months ago
7 months ago
6 months ago
5 months ago
6 months ago
5 months ago
7 months ago
7 months ago
7 months ago
5 months ago
4 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
5 months ago
4 months ago
7 months ago
7 months ago
5 months ago
7 months ago
7 months ago
7 months ago
5 months ago
7 months ago
7 months ago
7 months ago
4 months ago
7 months ago
6 months ago
5 months ago
5 months ago
5 months ago
6 months ago
5 months ago
6 months ago
5 months ago
5 months ago
6 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
  1. <template>
  2. <view class="home">
  3. <!-- 顶部背景 -->
  4. <view class="home-top">
  5. <!-- https://tennis-oss.xzaiyp.top/2024-10-22/81f3569e-c60c-4945-bfc9-b0e976f26d8e.png -->
  6. <image class="home-top-bg" src="/static/image/center/1.png" mode="widthFix"></image>
  7. </view>
  8. <!-- 卡片(地图) -->
  9. <view class="card">
  10. <view @click="openBroadside" class="team">
  11. <view class="change-icon">
  12. <image src="/static/image/broadside/17.png" mode="widthFix" style="height: 40rpx;"></image>
  13. </view>
  14. <view class="project"
  15. v-if="userInfo.team">
  16. {{ userInfo.team.name }}
  17. </view>
  18. </view>
  19. <view class="map">
  20. <map style="width: 100%; height: 100%"
  21. :latitude="position.latitude"
  22. :longitude="position.longitude"
  23. :markers="covers" :scale="13">
  24. </map>
  25. </view>
  26. </view>
  27. <!-- 打卡按钮 -->
  28. <view class="punch-card">
  29. <view @click="toClock" class="circle"
  30. :style="{background : ['#aaa', '', '#f40'][position.status]}">
  31. <view class="title" v-if="position.status == 0">定位中...</view>
  32. <view class="title" v-else-if="position.status == 2">定位失败</view>
  33. <view class="title" v-else>拍照打卡</view>
  34. <view class="time">{{ date.format('YYYY-MM-DD HH:mm:ss') }}</view>
  35. </view>
  36. </view>
  37. <!-- 签到记录 -->
  38. <div @click="toRecord" class="sign">
  39. <div class="sign-title">
  40. <image class="sign-title-img" src="/static/image/broadside/project.png" mode="widthFix" style="height: 40rpx;"></image>
  41. <div class="title">打卡记录</div>
  42. </div>
  43. <div class="project">
  44. <text class="project-name"
  45. v-if="userInfo.team">{{ userInfo.team.name }}</text>
  46. <uv-icon name="arrow-right" color="#000"></uv-icon>
  47. </div>
  48. </div>
  49. <!-- <image
  50. @click="upload"
  51. :src="image" mode=""></image> -->
  52. <!-- tab栏 -->
  53. <tabbar :select="0"></tabbar>
  54. <!-- 侧边栏 -->
  55. <broadside ref="broadside"></broadside>
  56. </view>
  57. </template>
  58. <script>
  59. import tabbar from '../../components/base/tabbar.vue'
  60. import broadside from '../../components/broadside/broadside.vue'
  61. import { mapState } from 'vuex'
  62. export default {
  63. name: "Home",
  64. components: {
  65. tabbar,
  66. broadside
  67. },
  68. data() {
  69. return {
  70. latitude: 39.909,
  71. longitude: 116.39742,
  72. covers: [],
  73. inter : null,
  74. date : this.$dayjs(),
  75. image : '',
  76. }
  77. },
  78. computed : {
  79. ...mapState(['teamList', 'userInfo', 'position']),
  80. },
  81. onLoad() {
  82. this.inter = setInterval(() => {
  83. this.date = this.$dayjs()
  84. }, 1000)
  85. },
  86. onUnload() {
  87. clearInterval(this.inter)
  88. },
  89. onShow() {
  90. this.getLocation()
  91. this.$store.commit('getUserInfo')
  92. this.$store.commit('getLocation')
  93. },
  94. methods: {
  95. // 跳转签到记录
  96. toRecord() {
  97. uni.navigateTo({
  98. url: "/pages/subPack/record/record"
  99. })
  100. },
  101. upload(){
  102. this.$Oss.ossUploadImage({
  103. success : url => {
  104. this.image = url
  105. }
  106. })
  107. },
  108. //打开侧边栏
  109. openBroadside() {
  110. this.$refs.broadside.open()
  111. },
  112. toClock(){
  113. if(this.position.status == 0){
  114. uni.showToast({
  115. title: '正在定位中,请稍后!',
  116. icon : 'none'
  117. })
  118. return
  119. }
  120. if(this.position.status == 0){
  121. uni.showToast({
  122. title: '定位失败,请检查当前定位是否开启!',
  123. icon : 'none'
  124. })
  125. return
  126. }
  127. // uni.navigateTo({
  128. // url: "/pages/subPack/human/human"
  129. // })
  130. // 检查当前是否在打卡时间段内
  131. this.$api('clockTime', {
  132. lon : this.position.longitude,
  133. lat : this.position.latitude,
  134. }, res => {
  135. //打卡(跳转人脸识别)
  136. if(res.code == 200){
  137. uni.navigateTo({
  138. // url: "/pages/subPack/face/face"
  139. url: "/pages/subPack/human/human"
  140. })
  141. }
  142. })
  143. },
  144. //获取用户位置
  145. getLocation() {
  146. let self = this;
  147. // uni.showLoading({
  148. // title: '定位中...'
  149. // })
  150. uni.getLocation({
  151. type: 'gcj02',
  152. success: function(res) {
  153. // uni.hideLoading()
  154. self.longitude = res.longitude;
  155. self.latitude = res.latitude;
  156. // self.covers.push({
  157. // id: 1,
  158. // latitude: res.latitude,
  159. // longitude: res.longitude,
  160. // iconPath: 'https://tennis-oss.xzaiyp.top/2024-10-22/103fa1db-8524-45e6-8d00-c36a69977a5b.png',
  161. // width: 30,
  162. // height: 30
  163. // })
  164. },
  165. fail() {
  166. self.checkAndRequestLocationPermission()
  167. }
  168. });
  169. },
  170. checkAndRequestLocationPermission() {
  171. let self = this;
  172. uni.getSetting({
  173. success: function(res) {
  174. if (!res.authSetting['scope.userLocation']) {
  175. // 用户未授权定位权限
  176. uni.showModal({
  177. title: '提示',
  178. content: '当前定位未开启,请点击确定手动开启定位',
  179. success: function(modalRes) {
  180. if (modalRes.confirm) {
  181. // 用户选择确认开启定位
  182. uni.openSetting({
  183. success: function(settingRes) {
  184. if (settingRes.authSetting[
  185. 'scope.userLocation']) {
  186. // 重新获取位置信息
  187. self.getLocation();
  188. } else {
  189. // 用户未开启定位权限
  190. console.log('用户未开启定位权限');
  191. }
  192. },
  193. fail: function(err) {
  194. console.log('打开设置页面失败:', err);
  195. }
  196. });
  197. } else {
  198. // 用户选择取消
  199. self.getLocation()
  200. }
  201. }
  202. });
  203. } else {
  204. // 用户已授权定位权限但获取位置失败(可能是设备未开启定位服务)
  205. console.log('用户已授权定位权限,但获取位置失败');
  206. // 可以提示用户检查设备定位服务是否开启
  207. }
  208. }
  209. });
  210. },
  211. }
  212. }
  213. </script>
  214. <style lang="scss" scoped>
  215. .home {
  216. background: $bg-color;
  217. min-height: 100vh;
  218. // 顶部背景
  219. .home-top {
  220. height: 490rpx;
  221. overflow: hidden;
  222. .home-top-bg {
  223. width: 750rpx;
  224. height: 200rpx;
  225. }
  226. }
  227. // 卡片(地图)
  228. .card {
  229. width: 95%;
  230. margin: -340rpx auto 0rpx auto;
  231. position: relative;
  232. .team {
  233. display: flex;
  234. margin: 15rpx 0rpx;
  235. color: white;
  236. font-size: 34rpx;
  237. .change-icon {
  238. display: flex;
  239. align-items: center;
  240. width: 40rpx;
  241. margin-right: 10rpx;
  242. image {
  243. width: 100%;
  244. }
  245. }
  246. }
  247. .map {
  248. height: 350rpx;
  249. background: $main-color;
  250. border-radius: 20rpx;
  251. overflow: hidden;
  252. }
  253. }
  254. //打卡按钮
  255. .punch-card {
  256. display: flex;
  257. justify-content: center;
  258. margin: 60rpx 0rpx;
  259. .circle {
  260. display: flex;
  261. flex-direction: column;
  262. justify-content: center;
  263. align-items: center;
  264. width: 370rpx;
  265. height: 370rpx;
  266. border-radius: 50%;
  267. background: $main-color;
  268. color: white;
  269. .title {
  270. font-size: 36rpx;
  271. }
  272. .time {
  273. font-size: 30rpx;
  274. margin-top: 20rpx;
  275. }
  276. }
  277. }
  278. // 签到记录
  279. .sign {
  280. display: flex;
  281. flex-wrap: wrap;
  282. width: 90%;
  283. margin: 0rpx auto;
  284. background: white;
  285. border-radius: 15rpx;
  286. box-sizing: border-box;
  287. padding: 30rpx 30rpx 30rpx 20rpx;
  288. box-shadow: 0rpx 0rpx 10rpx rgba(0, 0, 0, .1);
  289. .sign-title {
  290. display: flex;
  291. width: 30%;
  292. .sign-title-img {
  293. width: 40rpx;
  294. margin-right: 15rpx;
  295. }
  296. .title {}
  297. }
  298. .project {
  299. display: flex;
  300. width: 70%;
  301. justify-content: space-between;
  302. .project-name {
  303. color: $main-color;
  304. }
  305. }
  306. }
  307. }
  308. </style>