7abf3d1653b228314a23684f18cdb505ccfa18c3.svn-base 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. <template>
  2. <div class="main user-layout-register">
  3. <h3><span>注册</span></h3>
  4. <a-form-model ref="form" :model="model" :rules="validatorRules">
  5. <a-form-model-item prop="username">
  6. <a-input v-model="model.username" size="large" type="text" autocomplete="false" placeholder="请输入用户名"/>
  7. </a-form-model-item>
  8. <a-popover placement="rightTop" trigger="click" :visible="state.passwordLevelChecked">
  9. <template slot="content">
  10. <div :style="{ width: '240px' }">
  11. <div :class="['user-register', passwordLevelClass]">强度:<span>{{ passwordLevelName }}</span></div>
  12. <a-progress :percent="state.percent" :showInfo="false" :strokeColor=" passwordLevelColor "/>
  13. <div style="margin-top: 10px;">
  14. <span>请至少输入 8 个字符。请不要使用容易被猜到的密码。</span>
  15. </div>
  16. </div>
  17. </template>
  18. <a-form-model-item prop="password">
  19. <a-input
  20. v-model="model.password"
  21. size="large"
  22. type="password"
  23. @click="handlePasswordInputClick"
  24. autocomplete="false"
  25. placeholder="至少8位密码,区分大小写">
  26. </a-input>
  27. </a-form-model-item>
  28. </a-popover>
  29. <a-form-model-item prop="password2">
  30. <a-input v-model="model.password2" size="large" type="password" autocomplete="false" placeholder="确认密码"></a-input>
  31. </a-form-model-item>
  32. <a-form-model-item prop="mobile">
  33. <a-input v-model="model.mobile" size="large" placeholder="11 位手机号">
  34. <a-select slot="addonBefore" size="large" defaultValue="+86">
  35. <a-select-option value="+86">+86</a-select-option>
  36. <a-select-option value="+87">+87</a-select-option>
  37. </a-select>
  38. </a-input>
  39. </a-form-model-item>
  40. <!--<a-input-group size="large" compact>
  41. <a-select style="width: 20%" size="large" defaultValue="+86">
  42. <a-select-option value="+86">+86</a-select-option>
  43. <a-select-option value="+87">+87</a-select-option>
  44. </a-select>
  45. <a-input style="width: 80%" size="large" placeholder="11 位手机号"></a-input>
  46. </a-input-group>-->
  47. <a-row :gutter="16">
  48. <a-col class="gutter-row" :span="16">
  49. <a-form-model-item prop="captcha">
  50. <a-input v-model="model.captcha" size="large" type="text" placeholder="验证码">
  51. <a-icon slot="prefix" type="mail" :style="{ color: 'rgba(0,0,0,.25)' }"/>
  52. </a-input>
  53. </a-form-model-item>
  54. </a-col>
  55. <a-col class="gutter-row" :span="8">
  56. <a-button
  57. class="getCaptcha"
  58. size="large"
  59. :disabled="state.smsSendBtn"
  60. @click.stop.prevent="getCaptcha"
  61. v-text="!state.smsSendBtn && '获取验证码'||(state.time+' s')"></a-button>
  62. </a-col>
  63. </a-row>
  64. <a-form-model-item>
  65. <a-button
  66. size="large"
  67. type="primary"
  68. htmlType="submit"
  69. class="register-button"
  70. :loading="registerBtn"
  71. @click.stop.prevent="handleSubmit"
  72. :disabled="registerBtn">注册
  73. </a-button>
  74. <router-link class="login" :to="{ name: 'login' }">使用已有账户登录</router-link>
  75. </a-form-model-item>
  76. </a-form-model>
  77. </div>
  78. </template>
  79. <script>
  80. import {mixinDevice} from '@/utils/mixin.js'
  81. import {getSmsCaptcha} from '@/api/login'
  82. import {getAction, postAction} from '@/api/manage'
  83. import {checkOnlyUser} from '@/api/api'
  84. const levelNames = {
  85. 0: '低',
  86. 1: '低',
  87. 2: '中',
  88. 3: '强'
  89. }
  90. const levelClass = {
  91. 0: 'error',
  92. 1: 'error',
  93. 2: 'warning',
  94. 3: 'success'
  95. }
  96. const levelColor = {
  97. 0: '#ff0000',
  98. 1: '#ff0000',
  99. 2: '#ff7e05',
  100. 3: '#52c41a',
  101. }
  102. export default {
  103. name: "Register",
  104. components: {},
  105. mixins: [mixinDevice],
  106. data() {
  107. return {
  108. model: {},
  109. validatorRules: {
  110. username: [
  111. { required: false },
  112. { validator: this.checkUsername }
  113. ],
  114. password: [
  115. { required: false},
  116. { validator: this.handlePasswordLevel }
  117. ],
  118. password2: [
  119. { required: false },
  120. { validator: this.handlePasswordCheck }
  121. ],
  122. mobile: [
  123. { required: false },
  124. { validator: this.handlePhoneCheck }
  125. ],
  126. captcha: [
  127. { required: false },
  128. { validator: this.handleCaptchaCheck }
  129. ]
  130. },
  131. state: {
  132. time: 60,
  133. smsSendBtn: false,
  134. passwordLevel: 0,
  135. passwordLevelChecked: false,
  136. percent: 10,
  137. progressColor: '#FF0000'
  138. },
  139. registerBtn: false
  140. }
  141. },
  142. computed: {
  143. passwordLevelClass() {
  144. return levelClass[this.state.passwordLevel]
  145. },
  146. passwordLevelName() {
  147. return levelNames[this.state.passwordLevel]
  148. },
  149. passwordLevelColor() {
  150. return levelColor[this.state.passwordLevel]
  151. }
  152. },
  153. methods: {
  154. checkUsername(rule, value, callback) {
  155. if(!value){
  156. callback(new Error("请输入用户名"))
  157. }else{
  158. var params = {
  159. username: value,
  160. };
  161. checkOnlyUser(params).then((res) => {
  162. if (res.success) {
  163. callback()
  164. } else {
  165. callback("用户名已存在!")
  166. }
  167. })
  168. }
  169. },
  170. handleEmailCheck(rule, value, callback) {
  171. let params = {
  172. email: value,
  173. };
  174. checkOnlyUser(params).then((res) => {
  175. if (res.success) {
  176. callback()
  177. } else {
  178. callback("邮箱已存在!")
  179. }
  180. })
  181. },
  182. handlePasswordLevel(rule, value, callback) {
  183. let level = 0
  184. let reg = /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[~!@#$%^&*()_+`\-={}:";'<>?,./]).{8,}$/;
  185. if (!reg.test(value)) {
  186. callback(new Error('密码由8位数字、大小写字母和特殊符号组成!'))
  187. }
  188. // 判断这个字符串中有没有数字
  189. if (/[0-9]/.test(value)) {
  190. level++
  191. }
  192. // 判断字符串中有没有字母
  193. if (/[a-zA-Z]/.test(value)) {
  194. level++
  195. }
  196. // 判断字符串中有没有特殊符号
  197. if (/[^0-9a-zA-Z_]/.test(value)) {
  198. level++
  199. }
  200. this.state.passwordLevel = level
  201. this.state.percent = level * 30
  202. if (level >= 2) {
  203. if (level >= 3) {
  204. this.state.percent = 100
  205. }
  206. callback()
  207. } else {
  208. if (level === 0) {
  209. this.state.percent = 10
  210. }
  211. callback(new Error('密码强度不够'))
  212. }
  213. },
  214. handlePasswordCheck(rule, value, callback) {
  215. let password = this.model['password']
  216. //console.log('value', value)
  217. if (value === undefined) {
  218. callback(new Error('请输入密码'))
  219. }
  220. if (value && password && value.trim() !== password.trim()) {
  221. callback(new Error('两次密码不一致'))
  222. }
  223. callback()
  224. },
  225. handleCaptchaCheck(rule, value, callback){
  226. if(!value){
  227. callback(new Error("请输入验证码"))
  228. }else{
  229. callback();
  230. }
  231. },
  232. handlePhoneCheck(rule, value, callback) {
  233. var reg=/^1[3456789]\d{9}$/
  234. if(!reg.test(value)){
  235. callback(new Error("请输入正确手机号"))
  236. }else{
  237. var params = {
  238. phone: value,
  239. };
  240. checkOnlyUser(params).then((res) => {
  241. if (res.success) {
  242. callback()
  243. } else {
  244. callback("手机号已存在!")
  245. }
  246. })
  247. }
  248. },
  249. handlePasswordInputClick() {
  250. if (!this.isMobile()) {
  251. this.state.passwordLevelChecked = true
  252. return;
  253. }
  254. this.state.passwordLevelChecked = false
  255. },
  256. handleSubmit() {
  257. this.$refs['form'].validate((success) => {
  258. if (success==true) {
  259. let values = this.model
  260. let register = {
  261. username: values.username,
  262. password: values.password,
  263. phone: values.mobile,
  264. smscode: values.captcha
  265. };
  266. postAction("/sys/user/register", register).then((res) => {
  267. if (!res.success) {
  268. this.registerFailed(res.message)
  269. } else {
  270. this.$router.push({name: 'registerResult', params: {...values}})
  271. }
  272. })
  273. }
  274. })
  275. },
  276. getCaptcha(e) {
  277. e.preventDefault()
  278. let that = this
  279. this.$refs['form'].validateField(['mobile'], (err) => {
  280. if (!err) {
  281. this.state.smsSendBtn = true;
  282. let interval = window.setInterval(() => {
  283. if (that.state.time-- <= 0) {
  284. that.state.time = 60;
  285. that.state.smsSendBtn = false;
  286. window.clearInterval(interval);
  287. }
  288. }, 1000);
  289. const hide = this.$message.loading('验证码发送中..', 3);
  290. const params = {
  291. mobile: this.model.mobile,
  292. smsmode: "1"
  293. };
  294. postAction("/sys/sms", params).then((res) => {
  295. if (!res.success) {
  296. this.registerFailed(res.message);
  297. setTimeout(hide, 0);
  298. }
  299. setTimeout(hide, 500);
  300. }).catch(err => {
  301. setTimeout(hide, 1);
  302. clearInterval(interval);
  303. that.state.time = 60;
  304. that.state.smsSendBtn = false;
  305. this.requestFailed(err);
  306. });
  307. }
  308. }
  309. );
  310. },
  311. registerFailed(message) {
  312. this.$notification['error']({
  313. message: "注册失败",
  314. description: message,
  315. duration: 2,
  316. });
  317. },
  318. requestFailed(err) {
  319. this.$notification['error']({
  320. message: '错误',
  321. description: ((err.response || {}).data || {}).message || "请求出现错误,请稍后再试",
  322. duration: 4,
  323. });
  324. this.registerBtn = false;
  325. },
  326. },
  327. watch: {
  328. 'state.passwordLevel'(val) {
  329. console.log(val)
  330. }
  331. }
  332. }
  333. </script>
  334. <style lang="less">
  335. .user-register {
  336. &.error {
  337. color: #ff0000;
  338. }
  339. &.warning {
  340. color: #ff7e05;
  341. }
  342. &.success {
  343. color: #52c41a;
  344. }
  345. }
  346. .user-layout-register {
  347. .ant-input-group-addon:first-child {
  348. background-color: #fff;
  349. }
  350. }
  351. </style>
  352. <style lang="less" scoped>
  353. .user-layout-register {
  354. & > h3 {
  355. font-size: 16px;
  356. margin-bottom: 20px;
  357. }
  358. .getCaptcha {
  359. display: block;
  360. width: 100%;
  361. height: 40px;
  362. }
  363. .register-button {
  364. width: 50%;
  365. }
  366. .login {
  367. float: right;
  368. line-height: 40px;
  369. }
  370. }
  371. </style>