api.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. import config from '@/config.js'
  2. const BASE_URL = config.API_BASE_URL
  3. var _redirectingToLogin = false
  4. function _clearAuthAndRedirect() {
  5. if (_redirectingToLogin) return
  6. _redirectingToLogin = true
  7. uni.removeStorageSync('token')
  8. uni.removeStorageSync('userId')
  9. uni.removeStorageSync('role')
  10. uni.removeStorageSync('alumniVerify')
  11. uni.removeStorageSync('classId')
  12. uni.removeStorageSync('userInfo')
  13. try {
  14. var app = typeof getApp === 'function' ? getApp() : null
  15. if (app && app.$store) {
  16. app.$store.commit('logout')
  17. }
  18. } catch (e) {}
  19. uni.showToast({ title: '登录已过期,请重新登录', icon: 'none' })
  20. setTimeout(function() {
  21. uni.$emit('showLoginSheet', {})
  22. _redirectingToLogin = false
  23. }, 1500)
  24. }
  25. export const request = (url, method = 'POST', data = {}) => {
  26. var fullUrl = BASE_URL + url
  27. const token = uni.getStorageSync('token')
  28. // 过滤空字符串 ID 字段,防止后端 Long.valueOf("") 抛 NumberFormatException
  29. var body = data
  30. if (data && typeof data === 'object' && !Array.isArray(data)) {
  31. body = {}
  32. var hasFiltered = false
  33. for (var bk in data) {
  34. if (Object.prototype.hasOwnProperty.call(data, bk)) {
  35. var bv = data[bk]
  36. if (bv === '' && /(?:Id|ID|_id)$/.test(bk)) {
  37. hasFiltered = true
  38. continue
  39. }
  40. body[bk] = bv
  41. }
  42. }
  43. if (!hasFiltered) body = data
  44. }
  45. return new Promise((resolve, reject) => {
  46. uni.request({
  47. url: fullUrl,
  48. method: method,
  49. data: body,
  50. header: {
  51. 'Content-Type': 'application/json',
  52. 'Authorization': token ? 'Bearer ' + token : ''
  53. },
  54. success: (res) => {
  55. if (res.statusCode === 401 || (res.data && res.data.code === 401)) {
  56. _clearAuthAndRedirect()
  57. reject(res.data || { code: 401, message: '未授权' })
  58. return
  59. }
  60. if (res.data && res.data.code === 200) {
  61. resolve(res.data)
  62. } else {
  63. uni.showToast({
  64. title: (res.data && res.data.message) || '请求失败',
  65. icon: 'none'
  66. })
  67. reject(res.data)
  68. }
  69. },
  70. fail: (err) => {
  71. console.error('[API] 网络错误 ' + method + ' ' + fullUrl, err)
  72. uni.showToast({ title: '网络请求失败', icon: 'none' })
  73. reject(err)
  74. }
  75. })
  76. })
  77. }
  78. // === API 函数 ===
  79. // 登录
  80. export const wechatLogin = (code) => {
  81. return request('/api/auth/wechat-login', 'POST', { code })
  82. }
  83. // 校友验证
  84. export const alumniVerify = (data) => {
  85. return request('/api/auth/alumni-verify', 'POST', data)
  86. }
  87. // 班次
  88. export const joinClass = (code) => {
  89. return request('/api/class/join', 'POST', { code })
  90. }
  91. export const getClassInfo = () => {
  92. return request('/api/class/info', 'POST')
  93. }
  94. // 课程(L0/L1/L2/L3/L4)
  95. export const getCourseList = () => {
  96. return request('/api/course/list', 'POST')
  97. }
  98. export const getMyCourse = () => {
  99. return request('/api/course/current', 'POST')
  100. }
  101. // 分组
  102. export const joinGroup = (groupId) => {
  103. return request('/api/group/join', 'POST', { groupId })
  104. }
  105. export const getMyGroup = () => {
  106. return request('/api/group/mine', 'POST')
  107. }
  108. export const getClassGroups = () => {
  109. return request('/api/group/list', 'POST')
  110. }
  111. export const setSpokesperson = (speakerUid) => {
  112. return request('/api/group/spokesperson', 'POST', { speakerUid })
  113. }
  114. export const assignRole = (bookType) => {
  115. return request('/api/group/assign', 'POST', { bookType })
  116. }
  117. // 三本账
  118. export const claimAssignment = (data) => {
  119. return request('/api/assignment/claim', 'POST', data)
  120. }
  121. export const getMyAssignments = () => {
  122. return request('/api/assignment/mine', 'POST')
  123. }
  124. export const getGroupAssignments = () => {
  125. return request('/api/assignment/group', 'POST')
  126. }
  127. // 提交/打卡
  128. export const checkin = (image) => {
  129. return request('/api/submission/checkin', 'POST', { image })
  130. }
  131. export const getCheckinStatus = () => {
  132. return request('/api/submission/checkin/status', 'POST')
  133. }
  134. export const prepCheck = (data) => {
  135. return request('/api/submission/prep-check', 'POST', data)
  136. }
  137. export const getPrepCheckStatus = () => {
  138. return request('/api/submission/prep-check/status', 'POST')
  139. }
  140. export const uploadSubmission = (data) => {
  141. return request('/api/submission/upload', 'POST', data)
  142. }
  143. export const getMySubmissions = () => {
  144. return request('/api/submission/mylist', 'POST')
  145. }
  146. export const submitTeachingCard = (data) => {
  147. return request('/api/submission/teaching-card', 'POST', data)
  148. }
  149. // 路演
  150. export const uploadRoadmap = (data) => {
  151. return request('/api/vote/roadmap/upload', 'POST', data)
  152. }
  153. // 投票
  154. export const castVote = (data) => {
  155. return request('/api/vote/cast', 'POST', data)
  156. }
  157. export const getVoteResult = (data) => {
  158. return request('/api/vote/result', 'POST', data)
  159. }
  160. export const getVotedStatus = (data) => {
  161. return request('/api/vote/voted', 'POST', data)
  162. }
  163. export const getScoreboard = (classId) => {
  164. return request('/api/vote/scoreboard', 'POST', { classId })
  165. }
  166. // 行动计划
  167. export const submitPlan = (data) => {
  168. return request('/api/plan/submit', 'POST', data)
  169. }
  170. export const getMyPlan = () => {
  171. return request('/api/plan/mine', 'POST')
  172. }
  173. export const submitSurvey = (data) => {
  174. return request('/api/plan/survey', 'POST', data)
  175. }
  176. export const getMyCoupons = () => {
  177. return request('/api/plan/coupons', 'POST')
  178. }
  179. // 文件上传
  180. export const uploadFile = (filePath) => {
  181. return new Promise((resolve, reject) => {
  182. const token = uni.getStorageSync('token')
  183. uni.uploadFile({
  184. url: BASE_URL + '/api/upload/file',
  185. filePath: filePath,
  186. name: 'file',
  187. header: {
  188. 'Authorization': token ? 'Bearer ' + token : ''
  189. },
  190. success: (res) => {
  191. try {
  192. const data = JSON.parse(res.data)
  193. if (data.code === 200) {
  194. resolve(data)
  195. } else {
  196. uni.showToast({ title: data.message || '上传失败', icon: 'none' })
  197. reject(data)
  198. }
  199. } catch (e) {
  200. reject(e)
  201. }
  202. },
  203. fail: (err) => {
  204. console.error('[API] 上传失败', err)
  205. uni.showToast({ title: '上传失败', icon: 'none' })
  206. reject(err)
  207. }
  208. })
  209. })
  210. }