| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797 |
- <template>
- <cwg-page-wrapper isLoginPage>
- <view class="regist-content">
- <uni-row class="content">
- <uni-col :span="20" :offset="2" :sm="{ span: 14, offset: 5 }">
- <view class="regist-header">
- <text class="title">{{ t('signup.title') }}</text>
- <view class="login-link">
- <text class="text">{{ t('Label.Or') }}</text>
- <navigator url="/pages/login/index" class="link" hover-class="none">{{ t('signin.login') }}
- </navigator>
- </view>
- </view>
- <uni-forms ref="form" :modelValue="formData" :rules="rules" validate-trigger="blur" label-position="top"
- label-width="120">
- <uni-row :gutter="20" class="formContent">
- <uni-col :xs="24" :md="24">
- <uni-forms-item name="country" :label="t('newSignup.item3')">
- <cwg-combox v-model:value="formData.country" :options="countryOptions" filterable>
- </cwg-combox>
- </uni-forms-item>
- </uni-col>
- <uni-col :xs="24" :md="24">
- <uni-forms-item name="phone" :label="t('newSignup.item5')">
- <uni-easyinput v-model="formData.phone"></uni-easyinput>
- </uni-forms-item>
- </uni-col>
- <uni-col :xs="24" :md="24">
- <uni-forms-item name="birthDate" :label="t('newSignup.item18')">
- <uni-datetime-picker type="date" v-model="formData.birthDate"
- :placeholder="t('newSignup.item19')" @change="checkAge" />
- </uni-forms-item>
- </uni-col>
- <uni-col :xs="24" :md="24">
- <uni-forms-item name="email" :label="t('newSignup.item7')">
- <uni-easyinput v-model="formData.email"
- :placeholder="t('newSignup.item8')"
- :disabled="!isAgeValid || !formData.birthDate"></uni-easyinput>
- </uni-forms-item>
- </uni-col>
- <uni-col :xs="24" :md="24">
- <uni-forms-item name="emailCode" :label="t('newSignup.item9')">
- <uni-easyinput :disabled="!isAgeValid || !formData.birthDate"
- v-model="formData.emailCode" :placeholder="t('newSignup.item10')">
- <template #right>
- <view class="btn-code" @click="(!isAgeValid || !formData.birthDate) ? '' : handleGetCode()">
- {{ getCodeString }}
- </view>
- </template>
- </uni-easyinput>
- </uni-forms-item>
- </uni-col>
- <uni-col :xs="24" :md="24">
- <view class="agreemnet9">*{{ t('signup.agreemnet9') }}</view>
- </uni-col>
- <uni-col :xs="24" :md="24">
- <uni-forms-item name="password" :label="t('newSignup.item12')">
- <uni-easyinput v-model.trim="formData.password"
- :disabled="!isAgeValid || !formData.birthDate"
- :placeholder="t('newSignup.item13')" type="password"></uni-easyinput>
- </uni-forms-item>
- </uni-col>
- <uni-col :xs="24" :md="24">
- <uni-forms-item>
- <ul class="pwd">
- <li :class="{ fit: rule1 }" v-t="'signup.form.rules.1st'"></li>
- <li :class="{ fit: rule2 }" v-t="'signup.form.rules.2nd'"></li>
- <li :class="{ fit: rule3 }" v-t="'signup.form.rules.3rd'"></li>
- </ul>
- </uni-forms-item>
- </uni-col>
- <uni-col :xs="24" :md="24">
- <uni-forms-item v-if="!isRouteHasId" name="linkValue" :label="t('newSignup.item14')">
- <uni-easyinput v-model.trim="formData.linkValue"
- :disabled="!isAgeValid || !formData.birthDate"
- :placeholder="t('newSignup.item15')"
- @input="limitAgentIdLength"></uni-easyinput>
- </uni-forms-item>
- </uni-col>
- </uni-row>
- <uni-forms-item name="agree">
- <view class="check-box" @click="toggleAgree">
- <up-checkbox-group v-model="agreeGroup" @change="onAgreeChange">
- <up-checkbox size="14" labelSize="14" labelColor="#666666" activeColor="#ea002a"
- name="agree"
- class="wcg-checkbox"></up-checkbox>
- </up-checkbox-group>
- <text class="checkbox-label">{{ t('signup.agree') }}</text>
- </view>
- </uni-forms-item>
- <uni-forms-item name="isSubscribeEmail">
- <view class="check-box" @click="toggleSubscribeEmail">
- <up-checkbox-group v-model="subscribeEmailGroup" @change="onSubscribeEmailChange">
- <up-checkbox size="14" labelSize="14" labelColor="#666666" activeColor="#ea002a"
- name="subscribeEmail"
- class="wcg-checkbox"></up-checkbox>
- </up-checkbox-group>
- <text class="checkbox-label">{{ t('signup.agree1') }}</text>
- </view>
- </uni-forms-item>
- </uni-forms>
- <view>
- <u-button class="regiset-btn" @click="register">
- {{ t('signup.button') }}
- </u-button>
- </view>
- <view class="des-bottom">
- <text v-t="'signup.agreemnet1'"></text>
- <a @click="openUrl('pdf/Client_Agreement.pdf')" target="_blank" v-t="'signup.agreemnet2'"></a>
- <text v-t="'signup.agreemnet3'"></text>
- <a @click="openUrl('pdf/Terms&Conditions.pdf')" target="_blank" v-t="'signup.agreemnet4'"></a>
- <text v-t="'signup.agreemnet5'"></text>
- <a @click="openUrl('pdf/Privacy_Policy.pdf')" target="_blank" v-t="'signup.agreemnet6'"></a>
- <text v-t="'signup.agreemnet7'"></text>
- </view>
- <!-- <view class="or-title">-->
- <!-- <view class="line"></view>-->
- <!-- <view class="qr-tit2">OR</view>-->
- <!-- <view class="line"></view>-->
- <!-- </view>-->
- <!-- <uni-row :gutter="20">-->
- <!-- <uni-col :xs="24" :md="12">-->
- <!-- <u-button class="login-btn">-->
- <!-- {{ t('signup.button') }}-->
- <!-- </u-button>-->
- <!-- </uni-col>-->
- <!-- <uni-col :xs="24" :md="12">-->
- <!-- <u-button class="login-btn">-->
- <!-- {{ t('signup.button') }}-->
- <!-- </u-button>-->
- <!-- </uni-col>-->
- <!-- </uni-row>-->
- </uni-col>
- </uni-row>
- </view>
- <!-- <cwg-custom-footer />-->
- </cwg-page-wrapper>
- </template>
- <script setup>
- import { ref, watch, onMounted, computed } from 'vue'
- import { useI18n } from 'vue-i18n'
- import { useEmailCountdown } from '@/hooks/useEmailCountdown'
- import { loginApi } from '@/api/login'
- import { systemApi } from '@/api/system'
- import Config from '@/config/index'
- import { showToast } from '@/utils/toast'
- import { onLoad } from '@dcloudio/uni-app'
- import useUserStore from '@/stores/use-user-store'
- import { userToken } from '@/composables/config'
- import { userApi } from '@/api/user'
- import { openLocalPdf } from '@/utils/pdf.js'
- const { t } = useI18n()
- const userStore = useUserStore()
- const {
- time,
- text: getCodeString,
- canSend,
- start,
- restore,
- } = useEmailCountdown()
- const isRouteHasId = ref(false)
- const formData = ref({
- country: '',
- phone: '',
- birthDate: '',
- email: '',
- code: '',
- password: '',
- linkValue: '',
- agree: 0,
- isSubscribeEmail: 0,
- sourceCode: null,
- w: '',
- subId: '',
- oc: '',
- agentId: null,
- ibInvalid: null,
- })
- const rules = {
- country: { rules: [{ required: true, errorMessage: t('vaildate.country.empty'), trigger: 'blur' }] },
- email: {
- rules: [
- { required: true, errorMessage: t('vaildate.email.empty'), trigger: 'blur' },
- { pattern: Config.Pattern.Email, errorMessage: t('vaildate.email.format'), trigger: 'blur' },
- ],
- },
- emailCode: { rules: [{ required: true, errorMessage: t('vaildate.code.empty'), trigger: 'blur' }] },
- password: {
- rules: [
- { required: true, errorMessage: t('vaildate.password.format'), trigger: 'blur' },
- { pattern: Config.Pattern.Password, errorMessage: t('vaildate.password.format'), trigger: 'blur' },
- ],
- },
- agree: {
- rules: [
- {
- validateFunction: (rule, value) => {
- if (value) return true
- return t('vaildate.agree.empty')
- },
- trigger: 'change',
- },
- ],
- },
- phone: {
- rules: [
- { required: true, errorMessage: t('vaildate.phone.format'), trigger: 'blur' },
- { pattern: Config.Pattern.NonNegInt, errorMessage: t('vaildate.phone.format'), trigger: 'blur' },
- ],
- },
- birthDate: { rules: [{ required: true, errorMessage: t('vaildate.birthDate.empty'), trigger: 'change' }] },
- }
- const agreeGroup = ref([])
- const subscribeEmailGroup = ref([])
- watch(() => formData.value.agree, (val) => {
- agreeGroup.value = val === 1 ? ['agree'] : []
- }, { immediate: true })
- watch(() => formData.value.isSubscribeEmail, (val) => {
- subscribeEmailGroup.value = val === 1 ? ['subscribeEmail'] : []
- }, { immediate: true })
- const onAgreeChange = (e) => {
- formData.value.agree = e && e.length ? 1 : 0
- }
- const onSubscribeEmailChange = (e) => {
- formData.value.isSubscribeEmail = e && e.length ? 1 : 0
- }
- const toggleAgree = () => {
- const next = agreeGroup.value.length ? [] : ['agree']
- agreeGroup.value = next
- onAgreeChange(next)
- }
- const toggleSubscribeEmail = () => {
- const next = subscribeEmailGroup.value.length ? [] : ['subscribeEmail']
- subscribeEmailGroup.value = next
- onSubscribeEmailChange(next)
- }
- const rule1 = computed(() => {
- if (!formData.value.password) return false
- return /^.{8,16}$/.test(formData.value.password)
- })
- const rule2 = computed(() => {
- return /^(?=.*?[a-z])(?=.*?[A-Z]).*$/.test(formData.value.password)
- })
- const rule3 = computed(() => {
- return /^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?!.*([~!@&%$^\(\)#_]).*\1.*\1)[A-Za-z0-9~!@&%$^\(\)#_]{8,16}$/.test(
- formData.value.password,
- )
- })
- const openUrl = (url) => {
- openLocalPdf(url)
- }
- // 检查是否满18周岁
- const isAgeValid = computed(() => {
- if (!formData.value.birthDate) {
- return false // 如果还没选择日期,不允许继续
- }
- const today = new Date()
- const birthDate = new Date(formData.value.birthDate)
- let age = today.getFullYear() - birthDate.getFullYear()
- const monthDiff = today.getMonth() - birthDate.getMonth()
- if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {
- age--
- }
- return age >= 18
- })
- // 检查年龄并提示
- const checkAge = () => {
- if (formData.value.birthDate && !isAgeValid.value) {
- uni.showModal({
- title: t('Msg.SystemPrompt'),
- content: t('signup.ageRestriction'),
- showCancel: false,
- confirmText: t('Btn.Confirm'),
- success: function(res) {
- if (res.confirm) {
- // 用户点击确认后的操作
- }
- },
- })
- }
- }
- const limitAgentIdLength = (val) => {
- if (val == null || val === '') return
- // 推荐码只能输入数字和英文
- const filtered = val.toString().replace(/[^0-9a-zA-Z]/g, '').slice(0, 10)
- if (formData.value.linkValue !== filtered) {
- formData.value.linkValue = filtered
- }
- }
- onLoad((options) => {
- if (options) {
- formData.value.sourceCode = options.ex || null
- formData.value.w = options.w || ''
- formData.value.subId = options.SUBID || ''
- formData.value.oc = options.oc || ''
- formData.value.email = options.emailAdvertisement || ''
- console.log(options, '-----')
- if (options.id) {
- isRouteHasId.value = true
- formData.value.agentId = Number(options.id)
- formData.value.linkValue = options.commission || ''
- switch (options.ibInvalid) {
- case 'B0':
- formData.value.ibInvalid = 0
- break
- case 'B1':
- formData.value.ibInvalid = 1
- break
- }
- }
- }
- })
- const ho = ref('')
- // 账号类型
- const accountType = ref(1)
- const form = ref(null)
- const value = ref('')
- const mock_options = ref([])
- const countryCode = ref('')
- const countryOptions = computed(() => {
- return mock_options.value.map(item => ({
- text: item.name,
- value: item.code,
- disabled: item.isOpenAccount == 0 || item.isOpenAccount === null ? true : false,
- }))
- })
- watch(value, (newValue, oldValue) => {
- // console.log('v-model', newValue);
- })
- async function getCountry() {
- try {
- let res = await systemApi.countryGet({})
- if (res.code == 200) { // Code.StatusOK
- mock_options.value = res.data
- countryCode.value = res.msg
- } else {
- showToast(res.msg)
- }
- } catch (error) {
- console.error(error)
- }
- }
- // 获取验证码按钮点击
- async function handleGetCode() {
- if (!formData.value.birthDate) {
- showToast(t('vaildate.birthDate.empty'))
- return
- }
- if (!isAgeValid.value) {
- showToast(t('signup.ageRestriction'))
- return
- }
- if (!formData.value.country) {
- showToast(t('vaildate.country.empty'))
- return
- }
- if (!formData.value.email) {
- showToast(t('vaildate.email.empty'))
- return
- }
- if (!Config.Pattern.Email.test(formData.value.email)) {
- showToast(t('vaildate.email.format'))
- return
- }
- if (!canSend.value) return
- await sendEmailCode()
- }
- // 发送邮箱验证码
- async function sendEmailCode() {
- const res = await loginApi.Code({
- ...formData.value,
- })
- if (res.code === 200) {
- showToast(t('Msg.CodeSuccess'))
- start()
- return true
- } else {
- showToast(t('Msg.CodeFail'))
- return false
- }
- }
- const register = async () => {
- if (countryCode.value == 'MY' || countryCode.value == 'ID') {
- status.value = true
- return
- }
- console.log(123333)
- form.value.validate().then(async (res) => {
- // 中国(含港澳台)使用 X-System: B,非中国使用 X-System: A
- const chinaCountryCodes = ['CN']
- const isChina = chinaCountryCodes.includes(formData.value.country)
- const xSystemValue = isChina ? 'B' : 'A'
- let resData = await loginApi.Register(
- { ...formData.value },
- { headers: { 'X-System': xSystemValue } },
- )
- console.log(resData)
- if (resData.code == 200) { // Code.StatusOK
- showToast(t('Msg.registerSuc'))
- login()
- } else {
- console.log(123)
- showToast(resData.msg)
- }
- }).catch(err => {
- console.log('表单错误信息:', err)
- showToast(err.msg)
- return false
- })
- }
- const login = async () => {
- try {
- let res = await userApi.login({
- loginName: formData.value.email,
- password: formData.value.password,
- })
- if (res.code == 200) { // Code.StatusOK
- userToken.value = res.data
- getLoginInfo()
- } else {
- showToast(res.msg)
- }
- } catch (error) {
- console.error(error)
- }
- }
- const getLoginInfo = async () => {
- try {
- let res = await userApi.getUserInfo()
- if (res.code == 200) { // Code.StatusOK
- userStore.saveUserInfo(res.data)
- showToast(t('Msg.LoginSuccess'))
- setTimeout(() => {
- uni.reLaunch({
- url: '/pages/customer/index',
- })
- // this.$store.commit("isActiveTab", "0"); (可能需要适配相应的逻辑)
- }, 1000)
- } else {
- showToast(t('Msg.SystemError'))
- }
- } catch (error) {
- console.error(error)
- }
- }
- onMounted(() => {
- getCountry()
- const hostParts = window.location.host.split('.')
- ho.value = hostParts.length > 1 ? hostParts[1] : ''
- })
- </script>
- <style lang="scss"> .pwd {
- list-style: none;
- padding-left: 0;
- margin: 0;
- li {
- font-size: px2rpx(12);
- color: #999;
- line-height: px2rpx(20);
- position: relative;
- padding-left: px2rpx(16);
- &::before {
- content: '';
- position: absolute;
- left: 0;
- top: 50%;
- transform: translateY(-50%);
- width: px2rpx(6);
- height: px2rpx(6);
- border-radius: 50%;
- background-color: #999;
- }
- &.fit {
- color: #67c23a;
- &::before {
- background-color: #67c23a;
- }
- }
- }
- }
- </style>
- <style lang="scss" scoped>
- @import "@/uni.scss";
- :deep(uni-content) {
- padding-left: 0 !important;
- }
- .regist-page {
- height: 100vh;
- border: none;
- padding: 0;
- }
- .regist-content {
- display: flex;
- align-items: center;
- justify-content: center;
- }
- .content {
- width: px2rpx(650);
- margin: 0 auto;
- }
- .regist-header {
- display: flex;
- justify-content: space-between;
- align-items: flex-end;
- margin: px2rpx(40) 0 px2rpx(20);
- padding-bottom: px2rpx(10);
- .title {
- font-size: px2rpx(28);
- font-weight: bold;
- color: #141d22;
- line-height: 1;
- }
- .login-link {
- font-size: px2rpx(14);
- color: #141d22;
- display: flex;
- align-items: center;
- line-height: 1;
- .text {
- margin-right: px2rpx(4);
- }
- .link {
- color: #005bbb;
- text-decoration: none;
- border-bottom: 1px dashed #005bbb;
- padding-bottom: 2px;
- cursor: pointer;
- }
- }
- }
- //display: flex;
- .logo {
- width: 100%;
- margin-top: px2rpx(40);
- display: flex;
- align-items: center;
- justify-content: center;
- }
- .agreemnet9 {
- text-align: initial;
- color: #e61f1e;
- }
- .company-icon {
- width: px2rpx(234);
- }
- .account-type {
- width: 100%;
- margin-top: px2rpx(20);
- padding: px2rpx(10);
- background-color: $uni-bg-color-hover;
- height: px2rpx(60);
- box-sizing: border-box;
- border-radius: px2rpx(20);
- display: flex;
- align-items: center;
- .type-btn {
- width: 50%;
- text-align: center;
- height: px2rpx(40);
- border-radius: px2rpx(20);
- line-height: px2rpx(40);
- font-size: px2rpx(18);
- cursor: pointer;
- &.active {
- background-color: var(--primary-color);
- }
- }
- }
- .formStyle {
- height: px2rpx(40);
- }
- .account-tip {
- width: 100%;
- text-align: center;
- margin: px2rpx(30) 0;
- .title {
- font-size: px2rpx(26);
- font-weight: bold;
- }
- .tip {
- margin-top: px2rpx(5);
- color: var(--gray);
- }
- }
- .formContent {
- padding: 0 10px;
- }
- // 修改表单组件高度。
- :deep(.uni-stat-box) {
- height: 100%;
- }
- :deep(.uni-select) {
- height: 100%;
- }
- :deep(.uni-easyinput__content) {
- height: 100%;
- }
- :deep(.uni-date-editor) {
- height: 100%;
- }
- :deep(.uni-date-editor--x) {
- height: 100%;
- }
- .btn-code {
- width: 30%;
- height: 100%;
- box-sizing: border-box;
- background-color: #102047;
- border: 1px solid rgb(229, 229, 229);
- color: #fff;
- text-align: center;
- line-height: px2rpx(38);
- border-radius: 0 4px 4px 0;
- }
- .check-box {
- padding: 0 px2rpx(10);
- margin-bottom: px2rpx(10);
- display: flex;
- align-items: center;
- cursor: pointer;
- .checkbox-label {
- font-size: px2rpx(14);
- color: #666666;
- margin-left: px2rpx(8);
- user-select: none;
- }
- :deep(.u-checkbox) {
- display: flex;
- align-items: flex-start;
- }
- }
- .regiset-btn {
- width: 100%;
- height: px2rpx(40);
- border-radius: px2rpx(4);
- background-color: #ffde02;
- color: #333;
- font-weight: bold;
- }
- .or-title {
- font-size: px2rpx(16);
- line-height: 1.5;
- color: #333;
- font-weight: 500;
- text-align: center;
- margin: px2rpx(20) 0 px2rpx(18) 0;
- display: flex;
- align-items: center;
- justify-content: center;
- .line {
- flex: 1;
- height: 1px;
- background-color: #e4e4e4;
- }
- .qr-tit2 {
- margin: 0 px2rpx(12);
- }
- }
- .login-btn {
- width: 100%;
- height: px2rpx(40);
- border-radius: px2rpx(20);
- background-color: #1EBF42;
- color: #fff;
- font-weight: bold;
- margin-bottom: px2rpx(20);
- }
- .code-text {
- padding-right: px2rpx(20);
- }
- .des-bottom {
- margin-top: px2rpx(20);
- line-height: 20px;
- color: #000;
- font-size: 12px;
- a {
- color: #e61f1e;
- }
- }
- .des {
- width: 100%;
- box-sizing: border-box;
- text-align: start;
- line-height: 20px;
- color: #000;
- font-size: 12px;
- padding: px2rpx(20) px2rpx(30);
- //display: none;
- :nth-child(n) {
- display: inline;
- word-break: break-all;
- word-wrap: break-word;
- }
- a {
- color: #e61f1e;
- }
- }
- :deep(.u-text__value) {
- color: #ea002a !important;
- font-size: px2rpx(14) !important;
- }
- </style>
|