teamEdit.vue 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. <template>
  2. <view class="default_page" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
  3. <cus-header title='编辑团队' :interceptBack="true" @back="requestBack"></cus-header>
  4. <cus-team-info-fill ref="teamRef" :teamId="id" :submitting="saving" @handleConfirm="handleConfirm" :confirmText="confirmText"></cus-team-info-fill>
  5. <view class="dialog adffcacjc" v-if="show">
  6. <view class="dbox">
  7. <view class="dbox-title">温馨提示</view>
  8. <view class="dbox-content">本次团队配置修改将在本团队<span>所有激活状态下的PERILL团队发展动态评估问卷中</span>生效,确定提交吗?</view>
  9. <view class="dbox-btns adfacjb">
  10. <view class="zt_btn" @click="editConfirm">确定</view>
  11. <view class="qx_btn" @click="show=false">取消</view>
  12. </view>
  13. </view>
  14. </view>
  15. </view>
  16. </template>
  17. <script>
  18. import CusTeamInfoFill from '@/components/CusTeamInfoFill/index.vue'
  19. import teamBackgroundRules from '@/utils/teamBackgroundFile.js'
  20. const { createTeamPayloadSnapshot, createTeamSubmitPayload } = teamBackgroundRules
  21. export default {
  22. components:{ CusTeamInfoFill },
  23. data(){
  24. return {
  25. id:'',
  26. teamInfo:null,
  27. confirmText:'确定',
  28. scaleName:'',
  29. hierarchyName:'',
  30. submitDto:null,
  31. show:false,
  32. saving:false,
  33. saveSucceeded:false,
  34. savedPayloadSnapshot:'',
  35. saveStage:'idle',
  36. navigationTimer:null,
  37. navigationReject:null,
  38. pageUnloaded:false
  39. }
  40. },
  41. onLoad(options) {
  42. this.pageUnloaded = false
  43. this.id = options.id;
  44. this.scaleName = options.scaleName;
  45. this.hierarchyName = options.hierarchyName;
  46. this.getDetail()
  47. },
  48. onShow() {
  49. if (!this.id) return
  50. this.$nextTick(() => {
  51. const background = this.$refs.teamRef && this.$refs.teamRef.$refs.backgroundRef
  52. if (background) background.refreshFiles(this.id).catch(error => {
  53. this.$showToast(error && (error.message || error.msg) || '资料列表刷新失败')
  54. })
  55. })
  56. },
  57. onUnload() {
  58. this.pageUnloaded = true
  59. this.cancelPendingRedirect(new Error('页面已离开'))
  60. },
  61. methods:{
  62. hasPendingBackgroundFiles(){
  63. const team = this.$refs.teamRef
  64. return Boolean(team && (team.hasUnresolvedBackgroundFiles()
  65. || team.isBackgroundUploadActive()))
  66. },
  67. requestBack(){
  68. if(this.saving) return this.$showToast('团队正在保存,请稍候')
  69. if(!this.hasPendingBackgroundFiles()) return uni.navigateBack()
  70. uni.showModal({
  71. title:'背景资料尚未完成',
  72. content:'仍有背景资料正在上传或等待重试,返回将丢弃待处理队列;已发出的上传可能仍会完成。确定返回吗?',
  73. confirmText:'仍然返回',
  74. confirmColor:'#FD4F66',
  75. success: result => {
  76. if(result.confirm) uni.navigateBack()
  77. }
  78. })
  79. },
  80. getDetail(){
  81. this.$api.get(`/core/user/team/${this.id}`).then(({data:res})=>{
  82. if(res.code!==0) return this.$showToast(res.msg)
  83. this.teamInfo = res.data;
  84. this.$refs.teamRef.setTeamInfo(res.data)
  85. this.$refs.teamRef.teamInfo.functionIds = res.data.functions.map(f=>f.id);
  86. this.$refs.teamRef.teamInfo.orgIds = res.data.organizations.map(o=>o.id);
  87. this.$refs.teamRef.areaText = res.data.provinceName+res.data.cityName;
  88. this.$refs.teamRef.industryText = res.data.industryName;
  89. this.$refs.teamRef.functionTypeText = res.data.functions.map(f=>f.functionName).join('、');
  90. this.$refs.teamRef.architectureTypeText = res.data.organizations.map(f=>f.orgName).join('、');
  91. this.$refs.teamRef.teamScaleText = this.scaleName;
  92. this.$refs.teamRef.teamLevelText = this.hierarchyName;
  93. })
  94. },
  95. handleConfirm(data){
  96. this.submitDto = createTeamSubmitPayload(data);
  97. this.show = true;
  98. },
  99. async editConfirm(){
  100. if(this.saving) return
  101. this.saving = true
  102. const payload = createTeamSubmitPayload(this.submitDto)
  103. const payloadSnapshot = createTeamPayloadSnapshot(payload)
  104. try {
  105. if(!this.saveSucceeded || this.savedPayloadSnapshot !== payloadSnapshot) {
  106. this.saveStage = 'save'
  107. const { data:res } = await this.$api.put('/core/user/team',payload)
  108. if(res.code!==0){
  109. this.$showToast(res.msg)
  110. return
  111. }
  112. this.saveSucceeded = true
  113. this.savedPayloadSnapshot = payloadSnapshot
  114. this.show = false
  115. this.$showToast('编辑成功')
  116. }
  117. this.saveStage = 'navigate'
  118. await this.runDelayedRedirect(({ success, fail }) => {
  119. uni.redirectTo({
  120. url:'/pagesMy/team',
  121. success,
  122. fail
  123. })
  124. })
  125. } catch(error) {
  126. if(!this.pageUnloaded) {
  127. const fallback = this.saveStage === 'navigate' ? '页面跳转失败,请重试' : '团队编辑失败,请重试'
  128. const message = error && (error.message || error.msg)
  129. this.$showToast(message && this.saveStage === 'navigate' ? `页面跳转失败:${message}` : message || fallback)
  130. }
  131. } finally {
  132. this.saving = false
  133. }
  134. },
  135. runDelayedRedirect(invokeRedirect) {
  136. return new Promise((resolve, reject) => {
  137. if(this.pageUnloaded) {
  138. reject(new Error('页面已离开'))
  139. return
  140. }
  141. let settled = false
  142. const settle = (callback, value) => {
  143. if(settled) return
  144. settled = true
  145. this.navigationTimer = null
  146. this.navigationReject = null
  147. callback(value)
  148. }
  149. this.navigationReject = error => settle(reject, error)
  150. this.navigationTimer = setTimeout(() => {
  151. this.navigationTimer = null
  152. if(this.pageUnloaded) {
  153. settle(reject, new Error('页面已离开'))
  154. return
  155. }
  156. try {
  157. invokeRedirect({
  158. success: result => {
  159. if(this.pageUnloaded) settle(reject, new Error('页面已离开'))
  160. else settle(resolve, result)
  161. },
  162. fail: error => settle(reject, new Error(error && (error.errMsg || error.message) || '跳转失败'))
  163. })
  164. } catch(error) {
  165. settle(reject, error)
  166. }
  167. },1500)
  168. })
  169. },
  170. cancelPendingRedirect(error) {
  171. if(this.navigationTimer) clearTimeout(this.navigationTimer)
  172. this.navigationTimer = null
  173. const reject = this.navigationReject
  174. this.navigationReject = null
  175. if(reject) reject(error || new Error('跳转已取消'))
  176. }
  177. }
  178. }
  179. </script>
  180. <style scoped lang="scss">
  181. .default_page{
  182. box-sizing: border-box;
  183. }
  184. .dialog{
  185. position: fixed;
  186. left: 0;
  187. right: 0;
  188. top: 0;
  189. bottom: 0;
  190. background: rgba(0, 0, 0, .4);
  191. z-index: 1000;
  192. .dbox{
  193. width: calc(100% - 150rpx);
  194. background: #FFFFFF;
  195. border-radius: 32rpx;
  196. padding: 48rpx 30rpx;
  197. box-sizing: border-box;
  198. &-title{
  199. font-family: PingFang-SC, PingFang-SC;
  200. font-weight: bold;
  201. font-size: 34rpx;
  202. color: #002846;
  203. line-height: 48rpx;
  204. text-align: center;
  205. }
  206. &-content{
  207. padding: 0 14rpx;
  208. font-family: PingFangSC, PingFang SC;
  209. font-weight: 400;
  210. font-size: 32rpx;
  211. color: #002846;
  212. line-height: 54rpx;
  213. text-align: center;
  214. margin-top: 30rpx;
  215. span{
  216. font-weight: bold;
  217. }
  218. }
  219. &-btns{
  220. margin-top: 56rpx;
  221. &>view{
  222. width: calc(50% - 20rpx);
  223. }
  224. }
  225. }
  226. }
  227. </style>