TerminalChangePasswordDialog.vue 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. <template>
  2. <cwg-popup :title="pwdTitle" :visible="props.visible" :showFooters="false"
  3. @update:visible="$emit('update:visible', $event)">
  4. <view class="popup-content">
  5. <text class="account-number">{{ accountLabel }} {{ account.login }}</text>
  6. <template v-if="props.pwdType != 3">
  7. <uni-forms :model="passwordInfo" labelWidth="200" label-position="top" class="crm-form">
  8. <uni-forms-item
  9. :label="props.pwdType == 1 ? t('Custom.Settings.LoginPwdOld') : t('Custom.Settings.InvestorPwdOld')">
  10. <uni-easyinput type="password" :clearable="false" v-model="passwordInfo.oldPassword"
  11. :placeholder="props.pwdType == 1 ? t('Custom.Settings.LoginPwdOld') : t('Custom.Settings.InvestorPwdOld')" />
  12. </uni-forms-item>
  13. <uni-forms-item :label="t('Custom.Settings.NewPwd')">
  14. <uni-easyinput type="password" :clearable="false" v-model="passwordInfo.newPassword"
  15. :placeholder="t('Custom.Settings.NewPwd')" />
  16. </uni-forms-item>
  17. </uni-forms>
  18. <view class="notice-list">
  19. <view v-for="(item, index) in noticeItems" :key="index"
  20. :class="['notice-item', item.valid ? 'isOK' : '']">
  21. {{ item.label }}
  22. </view>
  23. </view>
  24. </template>
  25. <view class="save-btn">
  26. <view v-if="props.pwdType != 3" class="btn btn-secondary btn-shadow waves-effect" @click="save"
  27. v-t="'Btn.Save'" />
  28. <view v-else class="btn btn-secondary btn-shadow waves-effect" @click="resetPwd"
  29. v-t="'Btn.ResetPassword'" />
  30. </view>
  31. </view>
  32. <cwg-confirm-popup />
  33. </cwg-popup>
  34. </template>
  35. <script setup>
  36. import { ref, computed, watch } from 'vue'
  37. import { customApi } from '@/service/custom';
  38. import { useI18n } from 'vue-i18n'
  39. import { showToast } from "@/utils/toast";
  40. import { useConfirm } from '@/hooks/useConfirm'
  41. const confirm = useConfirm()
  42. const { t } = useI18n()
  43. const props = defineProps({
  44. visible: { type: Boolean, default: false },
  45. account: { type: Object, default: () => ({}) },
  46. accountLabel: { type: String, default: '账户: #' },
  47. // 1: 交易密码, 2: 投资者密码
  48. pwdType: { type: [Number, String], default: 1 },
  49. })
  50. const emit = defineEmits(['update:visible', 'save'])
  51. const passwordInfo = ref({
  52. oldPassword: '',
  53. newPassword: ''
  54. });
  55. const pwdTitle = computed(() => {
  56. switch (props.pwdType) {
  57. case 1:
  58. return t('vu.item3')
  59. case 2:
  60. return t('vu.item4')
  61. case 3:
  62. return t('Custom.Settings.TitReset')
  63. }
  64. })
  65. const rule1 = computed(() => {
  66. if (!passwordInfo.value.newPassword) return false;
  67. return /^.{8,16}$/.test(passwordInfo.value.newPassword);
  68. });
  69. const rule2 = computed(() => {
  70. return /^(?=.*?[a-z])(?=.*?[A-Z]).*$/.test(passwordInfo.value.newPassword);
  71. });
  72. const rule3 = computed(() => {
  73. return /^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?!.*([~!@&%$^\\(\\)#_]).*\\1.*\\1)[A-Za-z0-9~!@&%$^\\(\\)#_]{8,16}$/.test(
  74. passwordInfo.value.newPassword
  75. );
  76. });
  77. const rule4 = computed(() => {
  78. return /^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[~!@&%$^*./\\(\\)\\+\\=#_-])[A-Za-z0-9~!@&%$^*./\\(\\)\\+\\=#_-]{8,16}$/.test(
  79. passwordInfo.value.newPassword
  80. );
  81. });
  82. const noticeItems = computed(() => [
  83. { label: t('signup.form.rules.1st'), valid: rule1.value },
  84. { label: t('signup.form.rules.2nd'), valid: rule2.value },
  85. { label: t('signup.form.rules.4rd'), valid: rule4.value }
  86. ]);
  87. const flag = ref(false); // 防止重复提交
  88. const save = async () => {
  89. if (!/^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[~!@&%$^*./\\(\\)\\+\\=#_-])[A-Za-z0-9~!@&%$^*./\\(\\)\\+\\=#_-]{8,16}$/.test(passwordInfo.value.oldPassword)) {
  90. showToast(t('vaildate.password.format'));
  91. return;
  92. }
  93. if (!rule1.value || !rule2.value || !rule4.value) {
  94. return;
  95. }
  96. if (flag.value) return;
  97. flag.value = true;
  98. try {
  99. let res;
  100. if (props.pwdType == 1) {
  101. // 修改交易账户密码
  102. res = await customApi.ChangeDealPassword({
  103. login: props.account.login,
  104. ...passwordInfo.value
  105. });
  106. } else {
  107. // 修改投资者密码
  108. res = await customApi.ChangeInvestorOassword({
  109. login: props.account.login,
  110. ...passwordInfo.value
  111. });
  112. }
  113. if (res.code == 200) {
  114. await confirm({
  115. title: t('Msg.SystemPrompt'),
  116. content: t('ApplicationDialog.Des1'),
  117. confirmText: t('Btn.Confirm'),
  118. cancelText: t('Btn.Cancel')
  119. })
  120. emit('update:visible', false);
  121. passwordInfo.value = {
  122. oldPassword: '',
  123. newPassword: ''
  124. }
  125. emit('save');
  126. } else {
  127. await confirm({
  128. title: t('Msg.SystemPrompt'),
  129. content: res.msg,
  130. confirmText: t('Btn.Confirm'),
  131. cancelText: t('Btn.Cancel')
  132. })
  133. emit('update:visible', false);
  134. }
  135. } catch (error) {
  136. showToast(error.msg);
  137. emit('update:visible', false);
  138. } finally {
  139. flag.value = false;
  140. }
  141. }
  142. // 重置交易账号密码
  143. const resetPwd = async () => {
  144. try {
  145. if (flag.value) {
  146. return
  147. } else {
  148. flag.value = true;
  149. }
  150. let res = await customApi.ResetDealPasswordEmail({
  151. login: props.account.login
  152. });
  153. if (res.code == 200) {
  154. flag.value = false;
  155. await confirm({
  156. title: t('Msg.SystemPrompt'),
  157. content: t('ApplicationDialog.Des1'),
  158. confirmText: t('Btn.Confirm'),
  159. cancelText: t('Btn.Cancel')
  160. })
  161. emit('update:visible', false);
  162. } else {
  163. flag.value = false;
  164. await confirm({
  165. title: t('Msg.SystemPrompt'),
  166. content: res.msg,
  167. confirmText: t('Btn.Confirm'),
  168. cancelText: t('Btn.Cancel')
  169. })
  170. // showToast(res.msg);
  171. emit('update:visible', false);
  172. }
  173. } catch (error) {
  174. showToast(error.msg);
  175. emit('update:visible', false);
  176. } finally {
  177. flag.value = false;
  178. }
  179. }
  180. watch(() => props.visible, (newVal) => {
  181. if (newVal) {
  182. passwordInfo.value = {
  183. oldPassword: '',
  184. newPassword: ''
  185. }
  186. flag.value = false;
  187. }
  188. })
  189. </script>
  190. <style scoped lang="scss">
  191. @import "@/uni.scss";
  192. @media (min-width: 768px) {
  193. :deep(.cwg-dialog) {
  194. background-color: rgba(var(--bs-body-bg-rgb), var(--bs-bg-opacity)) !important;
  195. border-radius: px2rpx(8);
  196. width: px2rpx(480) !important;
  197. }
  198. }
  199. .popup-content {
  200. padding: px2rpx(16);
  201. }
  202. .account-number {
  203. text-align: left;
  204. display: block;
  205. font-size: px2rpx(14);
  206. color: var(--bs-emphasis-color);
  207. margin-bottom: px2rpx(24);
  208. }
  209. .crm-form {
  210. :deep(.uni-forms-item) {
  211. margin-bottom: px2rpx(16);
  212. }
  213. :deep(.uni-easyinput__content) {
  214. border: none !important;
  215. background-color: var(--color-zinc-100) !important;
  216. }
  217. }
  218. .notice-list {
  219. margin: px2rpx(10) 0;
  220. padding: 0 px2rpx(12) px2rpx(12) 0;
  221. .notice-item {
  222. text-align: left;
  223. font-size: px2rpx(14);
  224. color: var(--bs-emphasis-color);
  225. line-height: px2rpx(24);
  226. &::before {
  227. content: '●';
  228. display: inline-block;
  229. font-size: px2rpx(10);
  230. margin-right: px2rpx(4);
  231. }
  232. }
  233. .isOK {
  234. color: var(--bs-success);
  235. }
  236. }
  237. .save-btn {
  238. width: 100%;
  239. display: flex;
  240. justify-content: flex-end;
  241. margin-top: px2rpx(20);
  242. // .btn {
  243. // border: 1px solid rgba(108, 133, 149, 0);
  244. // border-radius: px2rpx(8);
  245. // padding: px2rpx(8) px2rpx(20);
  246. // font-size: px2rpx(14);
  247. // color: rgba(var(--bs-dark-rgb), var(--bs-text-opacity)) !important;
  248. // display: inline-flex;
  249. // align-items: center;
  250. // justify-content: center;
  251. // gap: px2rpx(8);
  252. // cursor: pointer;
  253. // transition: all 0.2s;
  254. // height: px2rpx(40);
  255. // box-sizing: border-box;
  256. // background-color: rgba(108, 133, 149, 0.08);
  257. // &.primary {
  258. // background-color: #cf1322;
  259. // ;
  260. // color: var(--bs-emphasis-color);
  261. // &:hover {
  262. // background-color: var(--color-navy-600);
  263. // }
  264. // &[disabled] {
  265. // cursor: not-allowed;
  266. // }
  267. // }
  268. // }
  269. }
  270. </style>