password.vue 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. <template>
  2. <view class="register-container">
  3. <!-- 标题和进度 -->
  4. <navBar title="创建账号密码2/2" color="#000" />
  5. <view class="progress-box">
  6. <view class="progress-item"></view>
  7. <view class="progress-item"></view>
  8. </view>
  9. <!-- 表单区域 -->
  10. <view class="register-form">
  11. <!-- 密码输入 -->
  12. <view class="form-item">
  13. <view class="item-label"> 密码 </view>
  14. <u-input
  15. placeholder="请输入密码"
  16. v-model="password"
  17. clearable
  18. :type="showPassword ? 'text' : 'password'"
  19. maxlength="20"
  20. class="custom-input"
  21. @input="validatePassword"
  22. >
  23. <template v-slot:suffix>
  24. <u-icon
  25. :name="showPassword ? 'eye-fill' : 'eye-off'"
  26. size="32rpx"
  27. color="#999"
  28. @click="showPassword = !showPassword"
  29. ></u-icon>
  30. </template>
  31. </u-input>
  32. <!-- 密码验证进度条 -->
  33. <view class="password-progress">
  34. <view class="progress-bar">
  35. <view
  36. class="progress-fill"
  37. :class="progressClass"
  38. :style="{ width: progressWidth }"
  39. ></view>
  40. </view>
  41. <view class="progress-text">{{ progressText }}</view>
  42. </view>
  43. <!-- 密码要求列表 -->
  44. <view class="password-rules">
  45. <view class="rule-item" :class="{ 'rule-valid': hasMinLength }">
  46. <image
  47. src="@/static/images/jobApplicant/check.svg"
  48. v-if="hasMinLength"
  49. mode="scaleToFill"
  50. />
  51. <image
  52. src="@/static/images/jobApplicant/border.svg"
  53. v-else
  54. mode="scaleToFill"
  55. />
  56. <text class="rule-text">最少8位数</text>
  57. </view>
  58. <view class="rule-item" :class="{ 'rule-valid': hasNumber }">
  59. <image
  60. src="@/static/images/jobApplicant/check.svg"
  61. v-if="hasNumber"
  62. mode="scaleToFill"
  63. />
  64. <image
  65. src="@/static/images/jobApplicant/border.svg"
  66. v-else
  67. mode="scaleToFill"
  68. />
  69. <text class="rule-text">至少包含1个数字</text>
  70. </view>
  71. <view class="rule-item" :class="{ 'rule-valid': hasUpperCase }">
  72. <image
  73. src="@/static/images/jobApplicant/check.svg"
  74. v-if="hasUpperCase"
  75. mode="scaleToFill"
  76. />
  77. <image
  78. src="@/static/images/jobApplicant/border.svg"
  79. v-else
  80. mode="scaleToFill"
  81. />
  82. <text class="rule-text">至少包含1个大写字母</text>
  83. </view>
  84. </view>
  85. </view>
  86. <u-button
  87. type="primary"
  88. :disabled="!canNext"
  89. @click="handleNext"
  90. :customStyle="{
  91. marginTop: '32rpx',
  92. height: '90rpx',
  93. fontSize: '32rpx',
  94. borderRadius: '100rpx',
  95. }"
  96. >
  97. 继续
  98. </u-button>
  99. </view>
  100. </view>
  101. </template>
  102. <script>
  103. import navBar from "@/components/nav-bar/index.vue";
  104. export default {
  105. data() {
  106. return {
  107. password: "",
  108. showPassword: false,
  109. hasMinLength: false,
  110. hasNumber: false,
  111. hasUpperCase: false,
  112. validCount: 0,
  113. };
  114. },
  115. components: {
  116. navBar,
  117. },
  118. computed: {
  119. // 计算满足的条件数量
  120. satisfiedCount() {
  121. let count = 0;
  122. if (this.hasMinLength) count++;
  123. if (this.hasNumber) count++;
  124. if (this.hasUpperCase) count++;
  125. return count;
  126. },
  127. // 进度条宽度
  128. progressWidth() {
  129. return (this.satisfiedCount / 3) * 100 + "%";
  130. },
  131. // 进度条颜色类
  132. progressClass() {
  133. switch (this.satisfiedCount) {
  134. case 1:
  135. return "progress-red";
  136. case 2:
  137. return "progress-orange";
  138. case 3:
  139. return "progress-blue";
  140. default:
  141. return "";
  142. }
  143. },
  144. // 进度文本
  145. progressText() {
  146. switch (this.satisfiedCount) {
  147. case 0:
  148. return "密码强度:弱";
  149. case 1:
  150. return "密码强度:弱";
  151. case 2:
  152. return "密码强度:中";
  153. case 3:
  154. return "密码强度:强";
  155. default:
  156. return "密码强度:弱";
  157. }
  158. },
  159. // 是否可以下一步
  160. canNext() {
  161. return this.satisfiedCount === 3;
  162. },
  163. },
  164. methods: {
  165. // 密码验证
  166. validatePassword() {
  167. // 验证最小长度
  168. this.hasMinLength = this.password.length >= 8;
  169. // 验证是否包含数字
  170. this.hasNumber = /\d/.test(this.password);
  171. // 验证是否包含大写字母
  172. this.hasUpperCase = /[A-Z]/.test(this.password);
  173. },
  174. // 下一步
  175. handleNext() {
  176. if (!this.validateForm()) {
  177. return;
  178. }
  179. uni.showLoading({
  180. title: "设置中...",
  181. mask: true,
  182. });
  183. setTimeout(() => {
  184. uni.hideLoading();
  185. uni.showToast({
  186. title: "密码设置成功",
  187. icon: "success",
  188. });
  189. // 跳转到下一步
  190. setTimeout(() => {
  191. uni.navigateTo({
  192. url: `/pages/my/jobApplicant/registerSuccess?phone=${this.phoneNumber}`,
  193. });
  194. }, 1000);
  195. }, 1500);
  196. },
  197. // 表单验证
  198. validateForm() {
  199. if (!this.password) {
  200. uni.showToast({
  201. title: "请输入密码",
  202. icon: "none",
  203. });
  204. return false;
  205. }
  206. if (!this.canNext) {
  207. uni.showToast({
  208. title: "请满足所有密码要求",
  209. icon: "none",
  210. });
  211. return false;
  212. }
  213. return true;
  214. },
  215. },
  216. };
  217. </script>
  218. <style scoped lang="scss">
  219. .register-container {
  220. background: #fff;
  221. position: absolute;
  222. left: 0;
  223. right: 0;
  224. top: 0;
  225. bottom: 0;
  226. }
  227. .register-form {
  228. padding: 32rpx;
  229. box-sizing: border-box;
  230. }
  231. .form-item {
  232. margin-bottom: 32rpx;
  233. }
  234. .item-label {
  235. color: rgba(18, 26, 44, 1);
  236. font-family: Roboto;
  237. font-size: 32rpx;
  238. font-weight: 400;
  239. line-height: 51.2rpx;
  240. letter-spacing: 0px;
  241. text-align: left;
  242. padding-bottom: 6rpx;
  243. }
  244. .custom-input {
  245. box-sizing: border-box;
  246. border: 2rpx solid rgba(158, 161, 168, 1);
  247. border-radius: 24rpx;
  248. background: rgba(255, 255, 255, 1);
  249. padding: 8rpx 24rpx !important;
  250. }
  251. // 密码验证进度条
  252. .password-progress {
  253. margin-top: 32rpx;
  254. }
  255. .progress-bar {
  256. width: 100%;
  257. height: 16rpx;
  258. background: #f0f0f0;
  259. border-radius: 40rpx;
  260. overflow: hidden;
  261. }
  262. .progress-fill {
  263. height: 100%;
  264. border-radius: 40rpx;
  265. transition: all 0.3s ease;
  266. }
  267. .progress-red {
  268. background: #d62c01;
  269. }
  270. .progress-orange {
  271. background: #faae16;
  272. }
  273. .progress-blue {
  274. background: #016bf6;
  275. }
  276. .progress-text {
  277. font-size: 24rpx;
  278. color: #666;
  279. margin-top: 8rpx;
  280. text-align: right;
  281. }
  282. // 密码要求列表
  283. .password-rules {
  284. margin-top: 20rpx;
  285. }
  286. .rule-item {
  287. display: flex;
  288. align-items: center;
  289. margin-bottom: 12rpx;
  290. image{
  291. width: 32rpx;
  292. height: 32rpx;
  293. margin-right: 16rpx;
  294. }
  295. }
  296. .rule-text {
  297. color: #4c4a53;
  298. font-family: Roboto;
  299. font-size: 32rpx;
  300. font-weight: 400;
  301. line-height: 51.2rpx;
  302. text-align: left;
  303. }
  304. .rule-valid .rule-text {
  305. color: #4c4a53;
  306. }
  307. .input-box {
  308. position: relative;
  309. }
  310. .next-btn-active {
  311. background: #2979ff;
  312. }
  313. ::v-deep .u-input {
  314. text-align: left !important;
  315. }
  316. .progress-box {
  317. display: flex;
  318. justify-content: center;
  319. align-items: center;
  320. gap: 24rpx;
  321. padding-top: 40rpx;
  322. box-sizing: border-box;
  323. .progress-item {
  324. width: 40rpx;
  325. height: 8rpx;
  326. background-color: #016bf6;
  327. border-radius: 40rpx;
  328. }
  329. }
  330. </style>