emailForm.vue 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. <template>
  2. <div class="email-form">
  3. <div class="border-box" v-if="type === 'phone'">
  4. <div class="phone-area" @click.stop="showPhoneArea = !showPhoneArea">
  5. <p>{{selectArea[1]}}</p>
  6. <span class="sanjiao"></span>
  7. <phoneAddressSelect v-show="showPhoneArea" @select="changeArea" />
  8. </div>
  9. <input type="text" oninput="value=value.replace(/[^\d]/g,'')" maxlength="11" :placeholder="$t('login.phonePlaceholder')" v-model="form.phone">
  10. </div>
  11. <input class="border-box" v-model="form.phone" :placeholder="$t('login.emailPlaceholder')" type="text" v-else>
  12. <div class="send-code-w border-box">
  13. <input type="text" maxLength="6" oninput="value=value.replace(/[^\d]/g,'')" :placeholder="$t('login.codePlaceholder')" v-model="form.authCode">
  14. <div class="send-btn" :class="{'is-disabled': time}" @click="sendCode">{{ time? $t('login.resendTime', { time }) : $t('login.sendCodeBtnText')}}</div>
  15. </div>
  16. <div class="password-w border-box" :class="{'show-tip': !form.password && passwordTip}" @mouseleave="passwordTip=false" @click="focusInput('emialInput')" >
  17. <input maxLength="16" class="" ref="emialInput" :placeholder="passwordTip ? '' : $t('login.setPassword')" autocomplete="new-password " v-model="form.password" type="password" @mouseover="passwordTip=true" >
  18. <p>{{ $t('login.passwordTip') }}</p>
  19. </div>
  20. <div class="password-w border-box" :class="{'show-tip': !form.confirmPass && confirmPassWordTip}" @click="focusInput('emialConfirmInput')" @mouseleave="confirmPassWordTip=false">
  21. <input maxLength="16" class="" :placeholder="confirmPassWordTip ? '' : $t('login.rePassword')" ref="emialConfirmInput" autocomplete="new-password" v-model="form.confirmPass" type="password" @mouseenter="confirmPassWordTip=true" >
  22. <p>{{ $t('login.passwordTip') }}</p>
  23. </div>
  24. <!-- <input class="border-box" placeholder="设置密码" type="password" v-model="form.password">
  25. <input class="border-box" placeholder="重复密码" type="password" v-model="form.confirmPass"> -->
  26. <p class="login-entry">{{$t('login.hasAccount')}}<span @click="$router.push('/login/login')">{{$t('login.zhijieLogin')}}</span></p>
  27. <div class="submit-btn" @click="submit">{{$t('common.submit')}}</div>
  28. </div>
  29. </template>
  30. <script>
  31. import phoneAddressSelect from '@/components/common/phoneAddressSelect'
  32. import { mapState } from 'vuex'
  33. import { encodeStr } from '@/util'
  34. import { Base64 } from 'js-base64'
  35. export default {
  36. props: {
  37. type: {
  38. type: String,
  39. default: 'email'
  40. }
  41. },
  42. data () {
  43. return {
  44. form: {},
  45. interEmailTime: 0,
  46. interTime: 0,
  47. showPhoneArea: false,
  48. selectArea: ['中国', '+86', 'China'],
  49. confirmPassWordTip: false,
  50. passwordTip: false
  51. }
  52. },
  53. computed: {
  54. ...mapState({
  55. language: state => state.language.current,
  56. langToast: state => state.language.home.toast
  57. }),
  58. time () {
  59. return this.type === 'email' ? this.interEmailTime : this.interTime
  60. }
  61. },
  62. components: {
  63. phoneAddressSelect
  64. },
  65. methods: {
  66. sendCode () {
  67. this.type === 'phone' ? this.getAuthCode() : this.getEmailAuthCode()
  68. },
  69. changeArea (item) {
  70. this.showPhoneArea = false
  71. if (!item) {
  72. return
  73. }
  74. this.selectArea = item
  75. },
  76. focusInput (input = 'emialInput') {
  77. this.$refs[input].focus()
  78. },
  79. async getAuthCode () {
  80. if (this.interl) {
  81. return
  82. }
  83. let res = await this.$store.dispatch('getAuthCode', {
  84. phone: this.form.phone,
  85. code: Number(this.selectArea[0].substr(1))
  86. })
  87. if (res) {
  88. this.interl && clearInterval(this.interl)
  89. this.interl = null
  90. this.jishi = true
  91. this.interTime = 60
  92. this.interl = setInterval(() => {
  93. this.interTime--
  94. if (this.interTime <= 0) {
  95. this.jishi = false
  96. clearInterval(this.interl)
  97. this.interl = null
  98. }
  99. }, 1000)
  100. }
  101. },
  102. async getEmailAuthCode () {
  103. if (this.emailInterl) {
  104. return
  105. }
  106. if (!this.form.phone) {
  107. this.$toast.show('warn', (this.language === 'en' ? 'E-mail' : '邮箱') + this.langToast['7'])
  108. return
  109. }
  110. let res = await this.$store.dispatch('getAuthCode', {
  111. email: this.form.phone,
  112. qudao: 'email'
  113. })
  114. if (res) {
  115. this.emailInterl && clearInterval(this.emailInterl)
  116. this.emailInterl = null
  117. this.interEmailTime = 60
  118. this.emailInterl = setInterval(() => {
  119. this.interEmailTime--
  120. if (this.interEmailTime <= 0) {
  121. clearInterval(this.emailInterl)
  122. this.emailInterl = null
  123. }
  124. }, 1000)
  125. }
  126. },
  127. async submit () {
  128. let check = value => {
  129. for (let i = 0, len = value.length; i < len; i++) {
  130. if (!value[i].val) {
  131. this.$toast.show('warn', (this.language === 'en' ? value[i].En : value[i].name) + this.langToast['7'])
  132. return
  133. }
  134. }
  135. return true
  136. }
  137. let checkStr = [
  138. {
  139. name: this.type === 'email' ? '邮箱' : '手机',
  140. En: this.type === 'email' ? 'E-mail' : 'Phone number',
  141. val: this.form.phone
  142. },
  143. {
  144. name: '验证码',
  145. En: 'Verification code',
  146. val: this.form.authCode
  147. },
  148. {
  149. name: '密码',
  150. En: 'Password',
  151. val: this.form.password
  152. },
  153. {
  154. name: '确认密码',
  155. En: 'Password',
  156. val: this.form.confirmPass
  157. }
  158. ]
  159. if (!check(checkStr)) {
  160. return
  161. }
  162. if (this.form.password.length < 8 || this.form.confirmPass.length < 8) {
  163. return this.$toast.show('warn', this.langToast['31'])
  164. }
  165. let temp = encodeStr(Base64.encode(this.form.password), Base64.encode(this.form.confirmPass))
  166. let params = {
  167. password: temp[0],
  168. phoneNum: this.form.phone,
  169. confirmPwd: temp[1],
  170. msgAuthCode: this.form.authCode
  171. }
  172. let res = await this.$http({
  173. method: 'post',
  174. headers: {
  175. token: this.token
  176. },
  177. data: params,
  178. url: 'sso/user/changePassword'
  179. })
  180. let response = res.data
  181. if (response.code !== 0) {
  182. return this.$toast.show('warn', this.langToast[response.code])
  183. }
  184. this.$toast.show('success', this.langToast['32'], () => {
  185. this.$router.push('/login/login')
  186. })
  187. }
  188. }
  189. }
  190. </script>
  191. <style lang="less" scoped>
  192. .email-form {
  193. padding-top: 35px;
  194. font-size: 16px;
  195. .border-box {
  196. border: 1px solid #909090;
  197. border-radius: 3px;
  198. height: 42px;
  199. line-height: 40px;
  200. width: 100%;
  201. margin-bottom: 20px;
  202. display: flex;
  203. }
  204. input {
  205. border: none;
  206. padding-left: 10px;
  207. flex: 1;
  208. min-width: 100px;
  209. font-size: 16px;
  210. }
  211. .send-btn {
  212. padding: 0 10px;
  213. cursor: pointer;
  214. white-space: nowrap;
  215. text-align: right;
  216. background: #1FE4DC;
  217. &.is-disabled {
  218. color: #909090;
  219. background: #EBEBEB;
  220. }
  221. }
  222. .login-entry {
  223. margin: 80px 0 30px 0;
  224. text-align: center;
  225. font-size: 14px;
  226. span {
  227. font-weight: bold;
  228. display: inline-block;
  229. position: relative;
  230. cursor: pointer;
  231. &::after {
  232. content: '';
  233. display: block;
  234. height: 2px;
  235. width: 100%;
  236. background: #1FE4DC;
  237. }
  238. }
  239. }
  240. .submit-btn {
  241. line-height: 60px;
  242. text-align: center;
  243. font-size: 20px;
  244. font-weight: bold;
  245. background: #1FE4DC;
  246. border-radius: 3px;
  247. cursor: pointer;
  248. }
  249. .password-w {
  250. position: relative;
  251. margin: 0 0 20px;
  252. input {
  253. margin-bottom: 0;
  254. }
  255. p {
  256. font-size: 12px;
  257. color: #909090;
  258. position: absolute;
  259. line-height: 44px;
  260. z-index: 1;
  261. top: 0;
  262. width: 100%;
  263. text-align: center;
  264. display: none;
  265. white-space: nowrap;
  266. overflow: hidden;
  267. }
  268. &.show-tip {
  269. p {
  270. display: block;
  271. }
  272. }
  273. }
  274. .phone-area {
  275. padding: 0 35px 0 10px;
  276. position: relative;
  277. cursor: pointer;
  278. &>p {
  279. overflow: hidden;
  280. text-overflow: ellipsis;
  281. white-space: nowrap;
  282. }
  283. &::after {
  284. content: '';
  285. display: block;
  286. height: 28px;
  287. width: 1px;
  288. background: #707070;
  289. position: absolute;
  290. right: 0;
  291. top: 6px
  292. }
  293. }
  294. .sanjiao {
  295. display: inline-block;
  296. border: 7px solid #909090;
  297. border-bottom: none;
  298. border-left-color: transparent;
  299. border-right-color: transparent;
  300. position: absolute;
  301. right: 10px;
  302. top: 16px;
  303. }
  304. }
  305. </style>