index.vue 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. <template>
  2. <view class="page-workbench">
  3. <view class="workbench-header">
  4. <wd-navbar fixed placeholder :bordered="false" safeAreaInsetTop customClass="navbar">
  5. <template #title>
  6. <view class="navbar-title"> 要易小助手</view>
  7. </template>
  8. </wd-navbar>
  9. <WorkbenchCard
  10. :is-login="isLoggedIn"
  11. :on-the-way="onTheWay"
  12. :wait-approve="waitApprove"
  13. @go-task="goTask"
  14. @open-history="taskHistory"
  15. @open-status="handleOpenStatus"
  16. />
  17. </view>
  18. <view class="workbench-notice">
  19. <wd-notice-bar
  20. text="任务包即将完成时,请不要做积分较高的任务,避免浪费积分哦~"
  21. prefix="warn-bold"
  22. type="info "
  23. color="#f90"
  24. background-color="#fdf6ec "
  25. />
  26. </view>
  27. <WorkbenchTaskSection @select-task="handleSelectTask" />
  28. <!--廉洁协议 -->
  29. <HonestAgreementGate v-model="isHonestAgreementVisible" />
  30. </view>
  31. </template>
  32. <script setup lang="ts">
  33. import { computed, ref } from 'vue'
  34. import { onShow } from '@dcloudio/uni-app'
  35. import {
  36. getQuizPltTestResultApi,
  37. resetPasswordApi,
  38. stopSixtyReminderApi,
  39. } from '@/services/modules/userInfo'
  40. import { useUserStore } from '@/stores/modules/user'
  41. import HonestAgreementGate from './components/HonestAgreementGate.vue'
  42. import WorkbenchCard from './components/WorkbenchCard.vue'
  43. import WorkbenchTaskSection from './components/WorkbenchTaskSection.vue'
  44. const userStore = useUserStore()
  45. const isLoggedIn = computed(() => userStore.isLoggedIn)
  46. const waitApprove = computed(() => userStore.currentUserInfo?.waitApprove ?? 0)
  47. const onTheWay = computed(() => userStore.currentUserInfo?.onTheWay ?? 0)
  48. onShow(async () => {
  49. // 每次进入页面时刷新用户状态
  50. if (!userStore.isLoggedIn) return
  51. const userInfo = await userStore.getUserInfoByCode()
  52. if (!userInfo) return
  53. // 未签署廉洁协议
  54. if (!userInfo.signedAgreement?.includes('HONEST_AGREEMENT_V2')) {
  55. uni.hideTabBar()
  56. openHonestAgreementGate()
  57. return
  58. }
  59. // 超龄退出
  60. if (userInfo.ageLimit) {
  61. isAgeOverLimit()
  62. }
  63. // 超龄提醒
  64. if (userInfo.ageReminder) {
  65. notifyUpcomingAgeLimit()
  66. }
  67. // 平台合规测试
  68. const res = await getPltQuizResult()
  69. if (!res) return
  70. // 密码修改提醒
  71. checkLastChangePassword()
  72. // 兜底处理
  73. uni.showTabBar()
  74. })
  75. const ensureCanOperate = (): boolean => {
  76. if (!userStore.isLoggedIn) {
  77. uni.showToast({
  78. icon: 'none',
  79. title: '请先登录',
  80. })
  81. setTimeout(() => {
  82. uni.navigateTo({ url: '/pages/login/index' })
  83. }, 1500)
  84. return false
  85. }
  86. if (userStore.hasBlacklistRisk) {
  87. uni.showModal({
  88. title: '提示',
  89. content: '该账号存在风险,请联系管理员',
  90. showCancel: false,
  91. })
  92. return false
  93. }
  94. return true
  95. }
  96. const goTask = () => {
  97. if (!ensureCanOperate()) return
  98. console.log('去领包')
  99. }
  100. const taskHistory = () => {
  101. if (!ensureCanOperate()) return
  102. console.log('领包记录')
  103. }
  104. const handleOpenStatus = (type: 'on-the-way' | 'wait-approve') => {
  105. if (!ensureCanOperate()) return
  106. // 领包记录
  107. console.log('type', type)
  108. }
  109. const handleSelectTask = (item: any) => {
  110. if (!ensureCanOperate()) return
  111. // 统一处理跳转 / 权限校验
  112. }
  113. // 业务判断
  114. // 显示签署廉洁协议弹窗
  115. const isHonestAgreementVisible = ref(false)
  116. const openHonestAgreementGate = () => {
  117. isHonestAgreementVisible.value = true
  118. }
  119. // 年龄已超限
  120. const isAgeOverLimit = () => {
  121. uni.showModal({
  122. title: '提示',
  123. showCancel: false,
  124. content: userStore?.currentUserInfo?.ageReminderInfo || '',
  125. success() {
  126. userStore.logout()
  127. uni.reLaunch({
  128. url: '/pages/login/index',
  129. })
  130. },
  131. })
  132. }
  133. // 提前提醒年龄即将超限
  134. const notifyUpcomingAgeLimit = () => {
  135. uni.showModal({
  136. title: '提示',
  137. cancelText: '不再提醒',
  138. confirmText: '确定',
  139. content: userStore?.currentUserInfo?.ageReminderInfo || '',
  140. async success(res) {
  141. if (res.cancel) {
  142. const res = await stopSixtyReminderApi()
  143. if (res.code === 0 && res.data) {
  144. uni.showToast({
  145. title: '不再弹出年龄提醒',
  146. icon: 'none',
  147. })
  148. }
  149. }
  150. },
  151. })
  152. }
  153. const getPltQuizResult = async (): Promise<boolean> => {
  154. const res = await getQuizPltTestResultApi()
  155. if (res.code === 0) {
  156. const { required, testResults } = res.data
  157. const hasInvalidResult = testResults.some((item) => !item.valid)
  158. const flag = required && hasInvalidResult
  159. if (flag) {
  160. uni.showModal({
  161. title: '提示',
  162. cancelText: '暂不处理',
  163. confirmText: '去测试',
  164. content: '因平台合规升级,现需要您完成风险评估测试,请您认真作答。感谢您的配合!',
  165. async success(res) {
  166. if (res.confirm) {
  167. uni.navigateTo({
  168. url: '/pages/quiz-plt-test/index',
  169. })
  170. }
  171. if (res.cancel) {
  172. userStore.logout()
  173. uni.reLaunch({
  174. url: '/pages/login/index',
  175. })
  176. }
  177. },
  178. })
  179. return false
  180. }
  181. }
  182. return true
  183. }
  184. // 是否修改过密码
  185. const checkLastChangePassword = async () => {
  186. const userInfo = userStore.currentUserInfo
  187. if (!userInfo) return
  188. const latestChangePwdTime = userInfo.latestChangePwdTime
  189. const now = Date.now()
  190. const ninetyDaysAgo = now - 90 * 24 * 60 * 60 * 1000
  191. const lastChangeTime = new Date(latestChangePwdTime).getTime()
  192. if (lastChangeTime < ninetyDaysAgo) {
  193. uni.showModal({
  194. title: '提示',
  195. content: '您的登录密码长时间未修改,为保障账号安全,建议您及时修改密码!',
  196. confirmText: '去修改',
  197. cancelText: '暂不修改',
  198. success: async (res) => {
  199. if (res.confirm) {
  200. uni.navigateTo({
  201. url: '/pages/reset-password/index',
  202. })
  203. } else if (res.cancel) {
  204. resetPasswordApi(userInfo.userId)
  205. }
  206. },
  207. })
  208. }
  209. }
  210. </script>
  211. <style lang="scss" scoped>
  212. .page-workbench {
  213. .workbench-header {
  214. position: relative;
  215. background-image: var(--workbench-bg);
  216. background-size: 100% 100%;
  217. height: 400rpx;
  218. width: 750rpx;
  219. :deep(.navbar) {
  220. background-color: transparent;
  221. }
  222. .navbar-title {
  223. color: #fff;
  224. font-weight: bold;
  225. }
  226. }
  227. .workbench-notice {
  228. padding: 0 30rpx;
  229. margin: 150rpx auto 0;
  230. }
  231. }
  232. </style>