SecurityCenterTab.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. <template>
  2. <view class="user-form crm-form">
  3. <view class="card">
  4. <view class="bank-menu card-header">
  5. <view v-for="item in types" :key="item.key" class="bank-menu-item"
  6. :class="{ active: selectedType === item.key }" @click="selectedType = item.key">
  7. <!-- <image class="bank-icon" :src="item.icon" mode="widthFix" />-->
  8. <text>{{ item.label }}</text>
  9. </view>
  10. </view>
  11. <uni-row class="demo-uni-row uni-row1" :gutter="20">
  12. <uni-col v-show="selectedType == 1" :xs="{ span: 24, offset: 0 }" :sm="{ span: 24, offset: 0 }" :md="{ span: 24, offset: 0 }"
  13. :lg="{ span: 12, offset: 6 }" :xl="{ span: 12, offset: 6 }">
  14. <view class=" p-3">
  15. <view class="content-title">
  16. <view v-t="'PersonalManagement.Title.CustomerZonePasswordChange'"></view>
  17. </view>
  18. <hr>
  19. <uni-forms :model="passwordInfo" labelWidth="200" label-position="top">
  20. <uni-row class="demo-uni-row">
  21. <uni-col :xs="24">
  22. <uni-forms-item :label="t('PersonalManagement.Label.OldPassword')">
  23. <uni-easyinput :clearable="false" v-model="passwordInfo.oldPassword"
  24. :placeholder="locale == 'es' ? 'Introduzca el nombre de la red' : t('placeholder.input')" />
  25. </uni-forms-item>
  26. </uni-col>
  27. <uni-col :xs="24">
  28. <uni-forms-item :label="t('PersonalManagement.Label.NewPassword')">
  29. <uni-easyinput :clearable="false" v-model="passwordInfo.newPassword"
  30. :placeholder="locale == 'es' ? 'Introduzca nueva contraseña' : t('placeholder.input')" />
  31. </uni-forms-item>
  32. </uni-col>
  33. <uni-col :xs="24">
  34. <uni-forms-item :label="t('PersonalManagement.Label.NewPasswordConfirmation')">
  35. <uni-easyinput :clearable="false" v-model="passwordInfo.checkPass"
  36. :placeholder="locale == 'es' ? 'Introduzca nueva contraseña' : t('placeholder.input')" />
  37. </uni-forms-item>
  38. </uni-col>
  39. <uni-col :xs="24">
  40. <view class="notice-list">
  41. <view v-for="(item, index) in noticeItems" :key="index"
  42. :class="['notice-item', item.valid ? 'isOK' : '']">
  43. {{ item.label }}
  44. </view>
  45. </view>
  46. </uni-col>
  47. <uni-col :xs="24">
  48. <button hover-class="" type="button" class="btn btn-danger btn-shadow waves-effect mt-4"
  49. @click="passwordUpdate">
  50. {{ locale == 'es' ?
  51. 'Actualizarcontraseña' : t('Btn.Application') }}
  52. </button>
  53. </uni-col>
  54. </uni-row>
  55. </uni-forms>
  56. </view>
  57. </uni-col>
  58. <uni-col v-show="selectedType == 2" :xs="{ span: 24, offset: 0 }" :sm="{ span: { span: 24, offset: 0 }, offset: 0 }"
  59. :md="{ span: 24, offset: 0 }" :lg="{ span: 12, offset: 6 }" :xl="{ span: 12, offset: 6 }">
  60. <view class=" p-3">
  61. <view class="content-title">
  62. <view v-t="'PersonalManagement.Title.EmailChange'"></view>
  63. </view>
  64. <hr>
  65. <uni-forms :model="emailInfo" labelWidth="200" label-position="top">
  66. <uni-row class="demo-uni-row">
  67. <uni-col :xs="24">
  68. <uni-forms-item :label="t('PersonalManagement.Label.OldEmail')">
  69. <uni-easyinput :clearable="false" v-model="emailInfo.oldEmail"
  70. :placeholder="t('placeholder.input')" />
  71. </uni-forms-item>
  72. </uni-col>
  73. <uni-col :xs="24">
  74. <uni-forms-item :label="t('PersonalManagement.Label.NewEmail')">
  75. <uni-easyinput :clearable="false" v-model="emailInfo.email" :placeholder="t('placeholder.input')" />
  76. </uni-forms-item>
  77. </uni-col>
  78. <uni-col :xs="24">
  79. <view class="email-code">
  80. <uni-forms-item :label="t('PersonalManagement.Label.MailboxVerificationCode')"
  81. class="email-code-item">
  82. <uni-easyinput :clearable="false" v-model="emailInfo.emailCode"
  83. :placeholder="locale == 'es' ? 'Código de 6 dígitos' : t('placeholder.input')" />
  84. </uni-forms-item>
  85. <view class="btn btn-code" @click="handleGetCode">{{ getCodeString }}</view>
  86. </view>
  87. </uni-col>
  88. <uni-col :xs="24">
  89. <button hover-class="" type="button" class="btn btn-danger btn-shadow waves-effect mt-4"
  90. @click="emailUpdate">
  91. {{ locale == 'es' ?
  92. 'Actualizarcontraseña' : t('Btn.Application') }}
  93. </button>
  94. </uni-col>
  95. </uni-row>
  96. </uni-forms>
  97. </view>
  98. </uni-col>
  99. </uni-row>
  100. </view>
  101. </view>
  102. </template>
  103. <script setup lang="ts">
  104. import { computed, ref, onMounted } from 'vue';
  105. import { useI18n } from 'vue-i18n';
  106. import { showToast } from "@/utils/toast";
  107. import { personalApi } from '@/service/personal';
  108. import { useEmailCountdown } from '@/hooks/useEmailCountdown';
  109. import config from '@/config';
  110. const {
  111. time,
  112. text: getCodeString,
  113. canSend,
  114. start,
  115. restore,
  116. clear,
  117. } = useEmailCountdown()
  118. const { t, locale } = useI18n();
  119. interface BankListType {
  120. key: string;
  121. label: string;
  122. icon: string;
  123. }
  124. const passwordInfo = ref({
  125. oldPassword: '',
  126. newPassword: '',
  127. checkPass: ''
  128. });
  129. const emailInfo = ref({
  130. email: '',
  131. });
  132. const selectedType = ref('1')
  133. const types = computed(() => {
  134. return [
  135. { key: '1', label: t('PersonalManagement.Title.CustomerZonePasswordChange') },
  136. {
  137. key: '2',
  138. label: t('PersonalManagement.Title.EmailChange'),
  139. },
  140. ]
  141. })
  142. const rule1 = computed(() => {
  143. if (!passwordInfo.value.newPassword) {
  144. return false;
  145. }
  146. return /^.{8,16}$/.test(passwordInfo.value.newPassword);
  147. });
  148. const rule2 = computed(() => {
  149. return /^(?=.*?[a-z])(?=.*?[A-Z]).*$/.test(passwordInfo.value.newPassword);
  150. });
  151. const rule3 = computed(() => {
  152. return /^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?!.*([~!@&%$^\\(\\)#_]).*\\1.*\\1)[A-Za-z0-9~!@&%$^\\(\\)#_]{8,16}$/.test(
  153. passwordInfo.value.newPassword
  154. );
  155. });
  156. const rule4 = computed(() => {
  157. console.log(/^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[~!@&%$^*./\\(\\)\\+\\=#_-])[A-Za-z0-9~!@&%$^*./\\(\\)\\+\\=#_-]{8,16}$/.test(passwordInfo.value.newPassword))
  158. return /^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[~!@&%$^*./\\(\\)\\+\\=#_-])[A-Za-z0-9~!@&%$^*./\\(\\)\\+\\=#_-]{8,16}$/.test(
  159. passwordInfo.value.newPassword
  160. );
  161. });
  162. const noticeItems = computed(() => [
  163. { label: t('signup.form.rules.1st'), valid: rule1.value },
  164. { label: t('signup.form.rules.2nd'), valid: rule2.value },
  165. { label: t('signup.form.rules.4rd'), valid: rule4.value }
  166. ])
  167. // 发送邮箱验证码
  168. async function sendEmailCode() {
  169. try {
  170. const res = await personalApi.customUpdateEmailCode({
  171. email: emailInfo.value.email,
  172. oldEmail: emailInfo.value.oldEmail,
  173. });
  174. if (res.code === 200) {
  175. start()
  176. return true;
  177. } else {
  178. showToast(t("Msg.CodeFail"));
  179. return false;
  180. }
  181. } catch (error: any) {
  182. console.log(error, 12);
  183. showToast(t("Msg.CodeFail"));
  184. return false;
  185. }
  186. }
  187. async function handleGetCode() {
  188. if (!emailInfo.value.email) {
  189. showToast(t("vaildate.email.empty"));
  190. return;
  191. }
  192. if (!config.Pattern.Email.test(emailInfo.value.email)) {
  193. showToast(t("vaildate.email.format"));
  194. return;
  195. }
  196. if (!canSend.value) return
  197. await sendEmailCode();
  198. }
  199. // 提交修改邮箱
  200. async function emailUpdate() {
  201. try {
  202. const res = await personalApi.customUpdateEmail({
  203. ...emailInfo.value
  204. });
  205. if (res.code === 200) {
  206. clear()
  207. emailInfo.value = {}
  208. showToast(t("Msg.Success"));
  209. } else {
  210. showToast(res.msg);
  211. }
  212. } catch (error: any) {
  213. showToast(error.msg);
  214. }
  215. }
  216. // 提交修改密码
  217. async function passwordUpdate() {
  218. try {
  219. if (!rule1.value) {
  220. showToast(t("signup.form.rules.1st"));
  221. return;
  222. }
  223. if (!rule2.value) {
  224. showToast(t("signup.form.rules.2nd"));
  225. return;
  226. }
  227. if (!rule4.value) {
  228. showToast(t("signup.form.rules.4rd"));
  229. return;
  230. }
  231. if (passwordInfo.value.newPassword !== passwordInfo.value.checkPass) {
  232. showToast(t("vaildate.password.same"));
  233. return;
  234. }
  235. const res = await personalApi.customUpdatePassword({
  236. ...passwordInfo.value
  237. });
  238. if (res.code === 200) {
  239. // start()
  240. showToast(t("Msg.Success"));
  241. } else {
  242. showToast(res.msg);
  243. }
  244. } catch (error: any) {
  245. showToast(error.msg);
  246. }
  247. }
  248. onMounted(() => {
  249. restore()
  250. })
  251. </script>
  252. <style scoped lang="scss">
  253. @import "@/uni.scss";
  254. :deep(.uni-row1) {
  255. .uni-col {}
  256. .uni-forms-item {
  257. min-height: px2rpx(79);
  258. margin-bottom: px2rpx(10);
  259. }
  260. .uni-easyinput__content {
  261. //border: none !important;
  262. background-color: transparent;
  263. //background-color: var(--color-zinc-100) !important;
  264. }
  265. }
  266. .btn {
  267. width: 100%;
  268. }
  269. .notice-list {
  270. margin: 0;
  271. padding: 0 px2rpx(12) px2rpx(12) 0;
  272. .notice-item {
  273. font-size: px2rpx(14);
  274. color: var(--bs-emphasis-color);
  275. line-height: px2rpx(24);
  276. }
  277. .isOK {
  278. color: var(--bs-success);
  279. }
  280. }
  281. .email-code {
  282. display: flex;
  283. align-items: flex-end;
  284. :deep(.email-code-item) {
  285. flex: 1;
  286. .uni-easyinput__content {
  287. border-radius: px2rpx(6) 0 0 px2rpx(6);
  288. }
  289. }
  290. .btn-code {
  291. width: 30%;
  292. margin-bottom: px2rpx(10);
  293. //padding: px2rpx(10) px2rpx(16);
  294. padding: 0;
  295. background-color: #102047;
  296. color: #fff;
  297. height: 3rem;
  298. box-sizing: border-box;
  299. line-height: 3rem;
  300. text-align: center;
  301. border-radius: 0 px2rpx(6) px2rpx(6) 0;
  302. cursor: pointer;
  303. font-size: px2rpx(16);
  304. flex-shrink: 0;
  305. }
  306. }
  307. .bank-menu {
  308. background: #fff;
  309. overflow: hidden;
  310. .bank-menu-item {
  311. display: flex;
  312. align-items: center;
  313. gap: px2rpx(12);
  314. padding: px2rpx(10) px2rpx(16);
  315. cursor: pointer;
  316. border: 1px solid #f3f4f6;
  317. font-size: px2rpx(16);
  318. font-weight: 500;
  319. color: #1f2937;
  320. transition: all 0.3s;
  321. height: px2rpx(50);
  322. border-radius: px2rpx(8);
  323. margin-bottom: px2rpx(8);
  324. .bank-icon {
  325. width: px2rpx(50);
  326. }
  327. &.active {
  328. background: #ea2027;
  329. color: var(--bs-emphasis-color);
  330. border-radius: px2rpx(0);
  331. }
  332. &:hover {
  333. background: #f9fafb;
  334. }
  335. &.active:hover {
  336. background: #d11920;
  337. }
  338. }
  339. }
  340. .bank-menu {
  341. // background: #fff;
  342. display: flex;
  343. flex-wrap: wrap;
  344. overflow: hidden;
  345. &.card-header {
  346. padding: px2rpx(10) px2rpx(20);
  347. }
  348. .bank-menu-item {
  349. flex: 1;
  350. min-width: px2rpx(260);
  351. display: flex;
  352. align-items: center;
  353. justify-content: center;
  354. //gap: px2rpx(12);
  355. padding: 0 px2rpx(16);
  356. cursor: pointer;
  357. font-size: px2rpx(16);
  358. font-weight: bold;
  359. color: var(--bs-emphasis-color);
  360. transition: all 0.3s;
  361. height: px2rpx(36);
  362. border-radius: px2rpx(8);
  363. .bank-icon {
  364. width: px2rpx(50);
  365. }
  366. &.active {
  367. background: #f5f5f5;
  368. color: #000;
  369. border-radius: px2rpx(8);
  370. &:hover {
  371. background: var(--bs-link-hover-color-rgb);
  372. color: #333;
  373. }
  374. }
  375. &:hover {
  376. background: #f5f5f5;
  377. color: #333;
  378. }
  379. &.active:hover {
  380. background: #f5f5f5;
  381. }
  382. }
  383. }
  384. </style>