fillTeamInfo.vue 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. <template>
  2. <view class="default_page" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
  3. <cus-header title='填写所在团队信息'></cus-header>
  4. <cus-team-info-fill ref="teamRef" :submitting="creationState.submitting || creationState.completed" @handleConfirm="handleConfirm" :confirmText="confirmText" :qtype="qtype"></cus-team-info-fill>
  5. </view>
  6. </template>
  7. <script>
  8. import CusTeamInfoFill from '@/components/CusTeamInfoFill/index.vue'
  9. import teamBackgroundRules from '@/utils/teamBackgroundFile.js'
  10. const {
  11. beginTeamSubmission,
  12. createTeamCreationState,
  13. createTeamPayloadSnapshot,
  14. createTeamSubmitPayload,
  15. finishTeamSubmission,
  16. rememberCreatedTeam,
  17. setTeamSubmissionStage
  18. } = teamBackgroundRules
  19. export default {
  20. components:{ CusTeamInfoFill },
  21. data(){
  22. return {
  23. title:'',
  24. type:'',
  25. next:'',
  26. questionnaireId:'',
  27. confirmText:'下一步',
  28. qtype:'',
  29. creationState:createTeamCreationState(),
  30. navigationTimer:null,
  31. navigationReject:null,
  32. pageUnloaded:false
  33. }
  34. },
  35. onLoad(options) {
  36. this.pageUnloaded = false;
  37. this.title = options.title||'';
  38. this.type = options.type;
  39. this.qtype = options.qtype||'';
  40. this.questionnaireId = options.questionnaireId||'';
  41. this.confirmText = options.type?'确定':'下一步';
  42. this.next = options.next;
  43. if(this.next) this.confirmText = '下一步';
  44. },
  45. onUnload() {
  46. this.pageUnloaded = true
  47. this.cancelPendingNavigation(new Error('页面已离开'))
  48. },
  49. methods:{
  50. async handleConfirm(team){
  51. if(!beginTeamSubmission(this.creationState)) return
  52. const payload = createTeamSubmitPayload(Object.assign({}, team, {
  53. questionnaireId:this.questionnaireId
  54. }))
  55. const payloadSnapshot = createTeamPayloadSnapshot(payload)
  56. try {
  57. let teamId = this.creationState.createdTeamId
  58. const resumeNavigation = this.creationState.stage === 'navigate'
  59. if(!teamId){
  60. setTeamSubmissionStage(this.creationState, 'save')
  61. const { data:res } = await this.$api.post('/core/user/team',payload)
  62. if(res.code!==0){
  63. this.$showToast(res.msg || '团队保存失败,请重试')
  64. return
  65. }
  66. teamId = res.data && res.data.teamId
  67. if(!teamId){
  68. this.$showToast('团队保存未返回团队ID,请重试')
  69. return
  70. }
  71. rememberCreatedTeam(this.creationState, teamId)
  72. this.creationState.teamPayloadSnapshot = payloadSnapshot
  73. } else if(this.creationState.teamPayloadSnapshot !== payloadSnapshot) {
  74. setTeamSubmissionStage(this.creationState, 'save')
  75. let res
  76. try {
  77. const response = await this.$api.put('/core/user/team', Object.assign({}, payload, {
  78. id:teamId
  79. }))
  80. res = response.data
  81. if(res.code!==0) throw new Error(res.msg || '团队更新请求失败')
  82. } catch(error) {
  83. if(resumeNavigation) setTeamSubmissionStage(this.creationState, 'navigate')
  84. throw error
  85. }
  86. this.creationState.teamPayloadSnapshot = payloadSnapshot
  87. }
  88. if(resumeNavigation) {
  89. setTeamSubmissionStage(this.creationState, 'navigate')
  90. await this.continueAfterTeamCreated(teamId)
  91. finishTeamSubmission(this.creationState, true)
  92. return
  93. }
  94. setTeamSubmissionStage(this.creationState, 'upload')
  95. const uploadResult = await this.$refs.teamRef.flushBackgroundFiles(teamId)
  96. if(uploadResult.failed > 0 || this.$refs.teamRef.hasUnresolvedBackgroundFiles()){
  97. await this.$showModal('仍有背景资料未上传成功,请重试后继续;团队已保存,无需再次创建')
  98. return
  99. }
  100. if(this.$refs.teamRef.hasDeferredPcUpload()){
  101. setTeamSubmissionStage(this.creationState, 'pcSession')
  102. await this.$refs.teamRef.waitForDeferredPcUpload(teamId)
  103. }
  104. if(this.next && !this.creationState.teamQuestionnaireId) {
  105. setTeamSubmissionStage(this.creationState, 'publish')
  106. const publishResult = await this.publishQuestionnaire(teamId)
  107. this.creationState.publishResult = publishResult
  108. this.creationState.teamQuestionnaireId = publishResult.data
  109. }
  110. setTeamSubmissionStage(this.creationState, 'navigate')
  111. await this.continueAfterTeamCreated(teamId)
  112. finishTeamSubmission(this.creationState, true)
  113. } catch(error) {
  114. this.showStageError(error)
  115. } finally {
  116. finishTeamSubmission(this.creationState)
  117. }
  118. },
  119. showStageError(error) {
  120. if(this.pageUnloaded) return
  121. const prefix = {
  122. save:'团队保存失败',
  123. upload:'背景资料处理失败',
  124. pcSession:'电脑上传流程失败',
  125. publish:'问卷发布失败',
  126. navigate:'页面跳转失败'
  127. }[this.creationState.stage] || '操作失败'
  128. const message = error && (error.message || error.msg)
  129. this.$showToast(message ? `${prefix}:${message}` : `${prefix},请重试`)
  130. },
  131. async publishQuestionnaire(teamId) {
  132. const response = await this.$api.post('/core/team/questionnaire/publish',{
  133. answerSetting:1,
  134. coachId:JSON.parse(uni.getStorageSync('userInfo')).id,
  135. startTime:new Date().Format('yyyy-MM-dd hh:mm:ss'),
  136. endTime:new Date(new Date().setDate(new Date().getDate()+30)).Format('yyyy-MM-dd hh:mm:ss'),
  137. questionnaireId:this.questionnaireId,
  138. teamId,
  139. type:1
  140. })
  141. const result = response.data
  142. if(result.code!==0) throw new Error(result.msg || '发布请求失败')
  143. return result
  144. },
  145. async continueAfterTeamCreated(teamId) {
  146. if(this.next){
  147. this.$showToast('保存成功,即将填写问卷')
  148. await this.runDelayedNavigation(({ success, fail }) => {
  149. uni.navigateTo({
  150. url:`/pagesPublish/questionnaireFill?teamQuestionnaireId=${this.creationState.teamQuestionnaireId}&teamId=${teamId}&type=${this.type}&title=${this.title}`,
  151. success,
  152. fail
  153. })
  154. })
  155. uni.removeStorageSync('newUser')
  156. return
  157. }
  158. this.$showToast('团队新增成功')
  159. await this.runDelayedNavigation(({ success, fail }) => {
  160. uni.navigateBack({ success, fail })
  161. })
  162. const eventChannel = this.getOpenerEventChannel()
  163. if(eventChannel) eventChannel.emit('saveTeamInfo')
  164. },
  165. runDelayedNavigation(invokeNavigation) {
  166. return new Promise((resolve, reject) => {
  167. if(this.pageUnloaded) {
  168. reject(new Error('页面已离开'))
  169. return
  170. }
  171. let settled = false
  172. const settle = (callback, value) => {
  173. if(settled) return
  174. settled = true
  175. this.navigationTimer = null
  176. this.navigationReject = null
  177. callback(value)
  178. }
  179. this.navigationReject = error => settle(reject, error)
  180. this.navigationTimer = setTimeout(() => {
  181. this.navigationTimer = null
  182. if(this.pageUnloaded) {
  183. settle(reject, new Error('页面已离开'))
  184. return
  185. }
  186. try {
  187. invokeNavigation({
  188. success: result => {
  189. if(this.pageUnloaded) settle(reject, new Error('页面已离开'))
  190. else settle(resolve, result)
  191. },
  192. fail: error => settle(reject, new Error(error && (error.errMsg || error.message) || '跳转失败'))
  193. })
  194. } catch(error) {
  195. settle(reject, error)
  196. }
  197. },1500)
  198. })
  199. },
  200. cancelPendingNavigation(error) {
  201. if(this.navigationTimer) clearTimeout(this.navigationTimer)
  202. this.navigationTimer = null
  203. const reject = this.navigationReject
  204. this.navigationReject = null
  205. if(reject) reject(error || new Error('跳转已取消'))
  206. }
  207. }
  208. }
  209. </script>
  210. <style scoped lang="scss">
  211. .default_page{
  212. box-sizing: border-box;
  213. }
  214. </style>