SecurityCenterTab.vue 12 KB

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